Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
vavali08 committed Apr 21, 2024
2 parents 92ef6ef + 9b7cac6 commit 529c9a0
Show file tree
Hide file tree
Showing 10 changed files with 379 additions and 21 deletions.
38 changes: 21 additions & 17 deletions PennMobile/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ plugins {
}

apply plugin: 'kotlin-android-extensions'
apply plugin: "kotlin-android"

android {
namespace 'com.pennapps.labs.pennmobile'
Expand Down Expand Up @@ -35,6 +36,7 @@ android {
packagingOptions {
pickFirst 'META-INF/LICENSE.txt'
pickFirst 'META-INF/NOTICE.txt'
exclude 'META-INF/rxjava.properties'
}
}

Expand Down Expand Up @@ -68,6 +70,7 @@ dependencies {
implementation 'com.squareup.picasso:picasso:2.71828'
implementation 'com.squareup.okhttp:okhttp:2.7.5'
implementation 'io.reactivex:rxandroid:1.2.1'
implementation "io.reactivex.rxjava2:rxandroid:2.0.2"
implementation 'androidx.browser:browser:1.5.0'
implementation 'androidx.recyclerview:recyclerview:1.3.2'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
Expand All @@ -91,6 +94,7 @@ dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation 'com.kaspersky.android-components:kaspresso:1.5.3'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
implementation 'com.squareup.retrofit2:converter-moshi:2.9.0'
implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
Expand All @@ -116,7 +120,7 @@ String getPlatformRedirectUri() {
// Code Coverage: https://www.raywenderlich.com/10562143-continuous-integration-for-android#toc-anchor-014

jacoco {
toolVersion = "0.8.11"
toolVersion = "0.8.11"
}

// https://stackoverflow.com/questions/68065743/cannot-run-gradle-test-tasks-because-of-java-lang-noclassdeffounderror-jdk-inte
Expand All @@ -131,28 +135,28 @@ def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*',

// Location of generated output classes
def debugTree = fileTree(dir: "$project.buildDir/tmp/kotlin-classes/debug",
excludes: fileFilter)
excludes: fileFilter)

// Source code directory
def mainSrc = "$project.projectDir/src/main/java"

// Task declaration

task jacocoTestReport(type: JacocoReport) {
// Runs only after the dependencies are executed
dependsOn = ['testDebugUnitTest', 'createDebugCoverageReport']
// Export formats
/*reports {
xml.enabled = true
html.enabled = true
}*/

sourceDirectories.setFrom(files([mainSrc]))
classDirectories.setFrom(files([debugTree]))

// Inform Gradle where the files generated by test cases - are located
executionData.from = fileTree(dir: project.buildDir, includes: [
'jacoco/testDebugUnitTest.exec'
// Runs only after the dependencies are executed
dependsOn = ['testDebugUnitTest', 'createDebugCoverageReport']
// Export formats
/*reports {
xml.enabled = true
html.enabled = true
}*/

sourceDirectories.setFrom(files([mainSrc]))
classDirectories.setFrom(files([debugTree]))

// Inform Gradle where the files generated by test cases - are located
executionData.from = fileTree(dir: project.buildDir, includes: [
'jacoco/testDebugUnitTest.exec'
// 'outputs/code_coverage/debugAndroidTest/connected/*.ec'
])
])
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,18 @@ import com.pennapps.labs.pennmobile.classes.LaundryCell
import com.pennapps.labs.pennmobile.classes.NewsCell
import com.pennapps.labs.pennmobile.classes.PollCell
import com.pennapps.labs.pennmobile.classes.PostCell
import com.pennapps.labs.pennmobile.classes.GSRCell
import com.pennapps.labs.pennmobile.components.sneaker.Utils.convertToDp
import com.pennapps.labs.pennmobile.utils.Utils
import eightbitlab.com.blurview.RenderScriptBlur
import kotlinx.android.synthetic.main.home_base_card.view.*
import kotlinx.android.synthetic.main.home_base_card.view.home_card_rv
import kotlinx.android.synthetic.main.home_base_card.view.home_card_subtitle
import kotlinx.android.synthetic.main.home_base_card.view.home_card_title
import kotlinx.android.synthetic.main.home_gsr_card.view.home_gsr_button
import kotlinx.android.synthetic.main.home_gsr_card.view.home_gsr_rv
import kotlinx.android.synthetic.main.home_gsr_card.view.home_gsr_subtitle
import kotlinx.android.synthetic.main.home_gsr_card.view.home_gsr_title
import kotlinx.android.synthetic.main.poll_card.view.*
import kotlinx.android.synthetic.main.home_news_card.view.*
import kotlinx.android.synthetic.main.home_post_card.view.*
Expand Down Expand Up @@ -106,6 +111,9 @@ class HomeAdapter(private val dataModel: HomepageDataModel) :
POLL -> {
ViewHolder(LayoutInflater.from(mContext).inflate(R.layout.poll_card, parent, false))
}
GSR_BOOKING -> {
ViewHolder(LayoutInflater.from(mContext).inflate(R.layout.home_gsr_card, parent, false))
}
NOT_SUPPORTED -> {
ViewHolder(LayoutInflater.from(mContext).inflate(R.layout.empty_view, parent, false))
}
Expand All @@ -114,7 +122,6 @@ class HomeAdapter(private val dataModel: HomepageDataModel) :
}
}
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val cell = dataModel.getCell(position)
when (cell.type) {
Expand All @@ -124,6 +131,7 @@ class HomeAdapter(private val dataModel: HomepageDataModel) :
"laundry" -> bindLaundryCell(holder, cell as LaundryCell)
"post" -> bindPostCell(holder, cell as PostCell)
"poll" -> bindPollCell(holder, cell as PollCell, position)
"gsr_booking" -> bindGSRCell(holder, cell as GSRCell)
"none" -> Log.i("HomeAdapter", "Empty cell at position $position")
else -> Log.i("HomeAdapter", "Unsupported type of data at position $position")
}
Expand Down Expand Up @@ -470,6 +478,26 @@ class HomeAdapter(private val dataModel: HomepageDataModel) :
}
}

private fun bindGSRCell(holder: ViewHolder, cell: GSRCell) {
holder.itemView.home_gsr_title?.text = "Reservations"
holder.itemView.home_gsr_subtitle?.text = "Group Study Rooms"
val reservations = cell.reservations
holder.itemView.home_gsr_rv?.layoutManager = LinearLayoutManager(mContext,
LinearLayoutManager.VERTICAL, false)
holder.itemView.home_gsr_button?.text = "Book a Room"
holder.itemView.home_gsr_button?.setOnClickListener {
mActivity.setTab(MainActivity.GSR_ID)
for (fragment in mActivity.supportFragmentManager.fragments) {
if(fragment is GsrTabbedFragment) {
fragment.viewPager.currentItem = 0
}
}
}
holder.itemView.home_gsr_rv?.adapter = HomeGsrReservationAdapter(reservations)
}



// Chrome custom tabs to launch news site
internal inner class NewsCustomTabsServiceConnection : CustomTabsServiceConnection() {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package com.pennapps.labs.pennmobile.adapters

import android.content.Context
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.FragmentTransaction
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.View.GONE
import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.fragment.app.Fragment
import com.bumptech.glide.Glide
import com.pennapps.labs.pennmobile.GsrReservationsFragment
import com.pennapps.labs.pennmobile.GsrTabbedFragment
import com.pennapps.labs.pennmobile.MainActivity
import com.pennapps.labs.pennmobile.MenuFragment
import com.pennapps.labs.pennmobile.R
import com.pennapps.labs.pennmobile.api.StudentLife
import com.pennapps.labs.pennmobile.classes.GSRReservation
import com.squareup.picasso.Picasso
import kotlinx.android.synthetic.main.dining_list_item.view.*
import kotlinx.android.synthetic.main.gsr_list_item.view.item_gsr_date
import kotlinx.android.synthetic.main.gsr_list_item.view.item_gsr_image
import kotlinx.android.synthetic.main.gsr_list_item.view.item_gsr_location
import kotlinx.android.synthetic.main.gsr_reservation.view.gsr_reservation_cancel_btn
import kotlinx.android.synthetic.main.gsr_reservation.view.gsr_reservation_date_tv
import kotlinx.android.synthetic.main.gsr_reservation.view.gsr_reservation_iv
import kotlinx.android.synthetic.main.gsr_reservation.view.gsr_reservation_location_tv
import org.joda.time.format.DateTimeFormat
import org.joda.time.format.DateTimeFormatter
import rx.android.schedulers.AndroidSchedulers

class HomeGsrReservationAdapter (reservations: List<GSRReservation>) : RecyclerView.Adapter<HomeGsrReservationAdapter.ViewHolder>() {
private var activeReservations: List<GSRReservation> = reservations

private lateinit var itemImage: ImageView
private lateinit var itemLocation: TextView
private lateinit var itemDate: TextView


private lateinit var mContext: Context
private lateinit var mActivity: MainActivity
private lateinit var mStudentLife: StudentLife
override fun onBindViewHolder(holder: HomeGsrReservationAdapter.ViewHolder, position: Int) {
val currentReservation = activeReservations[position]
val location = currentReservation.name
val formatter: DateTimeFormatter = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssZ")
val from = formatter.parseDateTime(currentReservation.fromDate)
val to = formatter.parseDateTime(currentReservation.toDate)
val day = from.toString("EEEE, MMMM d")
val fromHour = from.toString("h:mm a")
val toHour = to.toString("h:mm a")

val imageUrl = currentReservation.info?.get("thumbnail") ?: "https://s3.us-east-2.amazonaws.com/labs.api/dining/MBA+Cafe.jpg"
Picasso.get().load(imageUrl).fit().centerCrop().into(holder.itemView.item_gsr_image)

holder.itemView.item_gsr_location.text = location
holder.itemView.item_gsr_date.text = day + "\n" + fromHour + "-" + toHour

holder.itemView.setOnClickListener {
// Moves to GSR Booking Tab
mActivity.setTab(MainActivity.GSR_ID)

// Changes tab to "My Reservations" tab (from "Book a Room" tab)
for (fragment in mActivity.supportFragmentManager.fragments) {
if(fragment is GsrTabbedFragment) {
fragment.viewPager.currentItem = 1
}
}
}

}

override fun getItemCount(): Int {
return activeReservations.size
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HomeGsrReservationAdapter.ViewHolder {
mContext = parent.context
mActivity = mContext as MainActivity
mStudentLife = MainActivity.studentLifeInstance

val view = LayoutInflater.from(parent.context).inflate(R.layout.gsr_list_item, parent, false)
return ViewHolder(view)
}
inner class ViewHolder (itemView: View) : RecyclerView.ViewHolder(itemView) {

init {
itemImage = itemView.item_gsr_image
itemLocation = itemView.item_gsr_location
itemDate = itemView.item_gsr_date

}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.pennapps.labs.pennmobile.classes

data class GSRCell(val reservations: List<GSRReservation>) : HomeCell() {
init {
type = "gsr_booking"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,21 @@ class GSRReservation {
@Expose
@JvmField
var info: Map<String, String>? = null

override fun equals(other: Any?): Boolean {
return other is GSRReservation && this.booking_id == other.booking_id && this.name == other.name
&& this.fromDate == other.fromDate && this.toDate == other.toDate && this.gid == other.gid
&& this.lid == other.lid
}

override fun hashCode(): Int {
var result = (booking_id?.hashCode() ?: 0)
result = 31 * result + (name?.hashCode() ?: 0)
result = 31 * result + (fromDate?.hashCode() ?: 0)
result = 31 * result + (toDate?.hashCode() ?: 0)
result = 31 * result + (gid?.hashCode() ?: 0)
result = 31 * result + (lid?.hashCode() ?: 0)
result = 31 * result + (info?.hashCode() ?: 0)
return result
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import java.util.concurrent.CountDownLatch

class HomepageViewModel : HomepageDataModel, ViewModel() {
companion object {
private const val NUM_CELLS = 6
private const val NUM_CELLS = 7
private const val NUM_CELLS_LOGGED_IN = NUM_CELLS
private const val NUM_CELLS_GUEST = 2

Expand All @@ -37,6 +37,7 @@ class HomepageViewModel : HomepageDataModel, ViewModel() {
private const val POST_POS = 3
private const val DINING_POS = 4
private const val LAUNDRY_POS = 5
private const val GSR_POS = 6

private const val TAG = "HomepageVM"
private const val UPDATE_TAG = "CellUpdate"
Expand Down Expand Up @@ -138,6 +139,7 @@ class HomepageViewModel : HomepageDataModel, ViewModel() {
getLaundry(studentLife, bearerToken, latch)
getPosts(studentLife, bearerToken, latch)
getDiningPrefs(studentLife, bearerToken, latch)
getGSRReservations(studentLife, bearerToken, latch)
// waits until all of the network calls are processed
latch.await()
} else {
Expand Down Expand Up @@ -285,6 +287,25 @@ class HomepageViewModel : HomepageDataModel, ViewModel() {
})
}

private fun getGSRReservations(studentLife: StudentLife, bearerToken: String, latch: CountDownLatch) {
studentLife.getGsrReservations(bearerToken).subscribe({ reservationsList ->
if (reservationsList.isEmpty()) {
addCell(HomeCell(), GSR_POS)

} else {
val gsrCell = GSRCell(reservationsList)
Log.i(TAG, "Loaded GSR Reservations")
addCell(gsrCell, GSR_POS)
}
latch.countDown()
},{
throwable ->
Log.i(TAG, "Could not load GSR reservations")
throwable.printStackTrace()
latch.countDown()
})
}

private fun setPostBlurView(status: Boolean) = runBlocking {
postBlurMutex.withLock {
postBlurViewLoaded = status
Expand Down
Binary file modified PennMobile/src/main/res/drawable/baron.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 529c9a0

Please sign in to comment.