Commit 8bb07859 authored by Filip Wiesner's avatar Filip Wiesner

Course name in Evemnt detail (-> Course Dao, init load on login)

parent 8407751e
......@@ -5,6 +5,7 @@ import dagger.Provides
import javax.inject.Singleton
import androidx.room.Room
import com.cvut.blackbird.model.database.BlackBirdDB
import com.cvut.blackbird.model.database.CourseDao
import com.cvut.blackbird.model.database.EventDao
import dagger.Module
......@@ -19,13 +20,13 @@ class RoomModule(context: Context) {
@Singleton
@Provides
internal fun providesRoomDatabase(): BlackBirdDB {
return db
}
internal fun providesRoomDatabase() = db
@Singleton
@Provides
internal fun providesEventDao(db: BlackBirdDB): EventDao {
return db.eventDao()
}
internal fun providesEventDao(db: BlackBirdDB) = db.eventDao()
@Singleton
@Provides
internal fun providesCourseDao(db: BlackBirdDB) = db.courseDao()
}
\ No newline at end of file
......@@ -12,6 +12,7 @@ import android.view.View
import android.view.ViewGroup
import android.view.animation.AccelerateDecelerateInterpolator
import android.view.animation.AlphaAnimation
import android.widget.Toast
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.navigation.findNavController
......@@ -21,6 +22,7 @@ import bg.devlabs.transitioner.Transitioner
import com.cvut.blackbird.R
import com.cvut.blackbird.extensions.*
import com.cvut.blackbird.model.Failure
import com.cvut.blackbird.model.Success
import com.cvut.blackbird.model.entities.Student
import com.cvut.blackbird.model.services.AuthService
......@@ -85,6 +87,20 @@ class AuthFragment : Fragment() {
}
observe(viewModel.userInitResult) {result ->
infoMessage.text = when (result) {
is Success -> {
onAuthFinished()
"Succesfully fetched"
}
is Failure -> {
UserInfo.username = ""
result.message
}
else -> infoMessage.text
}
}
observe(viewModel.authLoadingStatus) { if (it) snack?.dismiss() }
bind(authProgress) visibilityTo viewModel.authLoadingStatus
......@@ -116,12 +132,13 @@ class AuthFragment : Fragment() {
private fun onLogged() {
// UserInfo.setStudent(lastValidUser)
UserInfo.setStudent(lastValidUser)
viewModel.initUser()
please {
animate(usernameInputLayout) toBe { invisible() }
animate(acceptBtn) toBe { invisible() }
animate(infoMessage) toBe { textSize(24f) }
animate(infoMessage) toBe { textSize(18f) }
}.withEndAction {
infoMessage.gravity = Gravity.CENTER or Gravity.BOTTOM
infoMessage.setTextColor(getColor(R.color.colorTextLight))
......
......@@ -23,11 +23,13 @@ class AuthViewModel : ViewModel() {
private val _studentResult = MutableLiveData<Result<Student>>() withDefault NotYet()
private val _authLoadingStatus = MutableLiveData<Boolean>() withDefault false
private val _userLoadingStatus = MutableLiveData<Boolean>() withDefault false
private val _userInitResult = MutableLiveData<Result<Unit>>() withDefault NotYet()
val authStatus: LiveData<AuthResult> get() = _authStatus
val studentResult: LiveData<Result<Student>> get() = _studentResult
val authLoadingStatus: LiveData<Boolean> get() = _authLoadingStatus
val userLoadingStatus: LiveData<Boolean> get() = _userLoadingStatus
val userInitResult: LiveData<Result<Unit>> get() = _userInitResult
fun initToken(code: String) {
launch { _authLoadingStatus.asBoolProgressStatus {
......@@ -36,14 +38,14 @@ class AuthViewModel : ViewModel() {
} }
}
var refreshJob: Job? = null
private var refreshJob: Job? = null
fun refreshToken() {
refreshJob?.cancel()
refreshJob = launch { _authStatus.postValue(model.refreshTokenGuarded()) }
.indicateProgressBy(_authLoadingStatus)
}
var studentJob: Job? = null
private var studentJob: Job? = null
fun fetchStudent(username: String) {
studentJob?.cancel()
studentJob = _studentResult
......@@ -51,4 +53,10 @@ class AuthViewModel : ViewModel() {
.indicateProgressBy(_userLoadingStatus)
}
private var initJob: Job? = null
fun initUser() {
initJob?.cancel()
initJob = _userInitResult
.fetchUsing { model.initLoad() }
}
}
\ No newline at end of file
......@@ -11,6 +11,7 @@ import androidx.lifecycle.ViewModelProviders
import com.cvut.blackbird.R
import com.cvut.blackbird.extensions.CircularRevealSettings
import com.cvut.blackbird.extensions.lastIndexOfNumber
import com.cvut.blackbird.model.Success
import com.cvut.blackbird.model.entities.Event
import com.cvut.blackbird.model.entities.EventType
import com.cvut.blackbird.support.glue.bind
......@@ -29,6 +30,9 @@ class TimetableDetailFragment : Fragment() {
viewModel = ViewModelProviders.of(activity!!).get(TimetableViewModel::class.java)
this bind viewModel.eventDetail toPassValueTo ::setupEvent
bind(viewModel.course) toPassValueTo {
if (it is Success) detail_fullName.text = it.value.name
}
// detailExitBtn.setOnClickListener { _ ->
// view?.startCircularExit(revealSettings) {
......@@ -46,6 +50,9 @@ class TimetableDetailFragment : Fragment() {
}
private fun setupEvent(event: Event) {
viewModel.requestCourse(event.linked?.course ?: "")
detail_abbr.background = when {
event.eventType == EventType.LECTURE -> context?.resources?.getDrawable(R.drawable.ic_timetable_lecture, context?.theme)
event.eventType == EventType.TUTORIAL -> context?.resources?.getDrawable(R.drawable.ic_timetable_tutorial, context?.theme)
......
......@@ -7,6 +7,8 @@ import com.cvut.blackbird.extensions.atStartOfTheDay
import com.cvut.blackbird.extensions.withDefault
import com.cvut.blackbird.model.NotYet
import com.cvut.blackbird.model.Result
import com.cvut.blackbird.model.Success
import com.cvut.blackbird.model.entities.Course
import com.cvut.blackbird.model.entities.Event
import com.cvut.blackbird.model.flows.DateSpan
import com.cvut.blackbird.model.flows.TimetableModel
......@@ -23,11 +25,13 @@ class TimetableViewModel : ViewModel() {
private val _timetableUpdateRequestResult = MutableLiveData<Result<List<Event>>>() withDefault NotYet()
private val _timetable = MutableLiveData<Map<Int,List<Event>>>() withDefault mapOf()
private val _displayedWeek = MutableLiveData<DateTime>() withDefault DateTime.now()
private val _course = MutableLiveData<Result<Course>>() withDefault NotYet()
val loadingStatus: LiveData<Boolean> get() = _loadingStatus
val timetableUpdateResult: LiveData<Result<List<Event>>> get() = _timetableUpdateRequestResult
val timetable: LiveData<Map<Int,List<Event>>> get() = _timetable
val displayedWeek: LiveData<DateTime> get() = _displayedWeek
val course: LiveData<Result<Course>> get() = _course
val eventDetail = MutableLiveData<Event>() withDefault Event.empty
......@@ -65,6 +69,10 @@ class TimetableViewModel : ViewModel() {
}
}
fun requestCourse(code: String) {
launch { _course.postValue(Success(model.getCourse(code))) }
}
private var refreshJob: Job? = null
fun refresh() {
refreshJob?.cancel()
......
......@@ -4,6 +4,7 @@ import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.TypeConverter
import androidx.room.TypeConverters
import com.cvut.blackbird.model.entities.Course
import com.cvut.blackbird.model.entities.Event
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
......@@ -11,10 +12,11 @@ import org.joda.time.DateTime
import org.joda.time.format.ISODateTimeFormat
@Database(entities = [Event::class], version = 3)
@Database(entities = [Event::class, Course::class], version = 4)
@TypeConverters(DBTypeConverters::class)
abstract class BlackBirdDB: RoomDatabase() {
abstract fun eventDao(): EventDao
abstract fun courseDao(): CourseDao
}
class DBTypeConverters {
......
......@@ -3,10 +3,15 @@ package com.cvut.blackbird.model.database
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.cvut.blackbird.model.entities.Course
@Dao
interface CourseDao {
@Query("SELECT * FROM Course WHERE code = :code")
fun getCourse(code: String): Course
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertAll(events: List<Course>)
fun insertAll(courses: List<Course>)
}
\ No newline at end of file
package com.cvut.blackbird.model.entities
import androidx.room.Embedded
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.tickaroo.tikxml.annotation.*
@Xml(name = "atom:feed")
class CourseRoot (
@PropertyElement(name = "osearch:startIndex")
val startIndex: Int,
@PropertyElement(name = "atom:entry")
val courses: List<Course>
@Xml
class EnrolledCourseRoot (
@Element(name = "atom:entry")
val courses: List<EnrolledCourse>
)
@Xml
class EnrolledCourse (
@Path("atom:content/course")
@Attribute(name = "xlink:href")
val link: String
) {
val name get() = link.split('/')[1]
}
@Xml
@Entity
data class Course (
@PrimaryKey
@Path("atom:content")
@PropertyElement(name = "course")
val name: String,
@PropertyElement val code: String,
@Path("atom:content")
@Attribute(name = "xlink:href")
val link: String,
@PropertyElement val completion: String,
@Path("atom:content")
@PropertyElement(name = "semester")
val semester: String
)
@PropertyElement val credits: Int,
@Path("atom:content")
@PropertyElement val department: String,
@Path("atom:content")
@PropertyElement val homepage: String?,
@Path("atom:content")
@PropertyElement val name: String,
@Path("atom:content")
@PropertyElement val range: String,
@Path("atom:content")
@PropertyElement val season: String,
@Path("atom:content")
@PropertyElement val state: String,
@Path("atom:content")
@PropertyElement val studyForm: String?
)
\ No newline at end of file
......@@ -2,20 +2,23 @@ package com.cvut.blackbird.model.flows
import com.cvut.blackbird.BlackBirdAC
import com.cvut.blackbird.model.*
import com.cvut.blackbird.model.database.CourseDao
import com.cvut.blackbird.model.database.EventDao
import com.cvut.blackbird.model.entities.Course
import com.cvut.blackbird.model.entities.Student
import com.cvut.blackbird.model.services.AuthInfo
import com.cvut.blackbird.model.services.KosService
import com.cvut.blackbird.model.services.SiriusService
import com.cvut.blackbird.model.support.AuthResult
import kotlinx.coroutines.experimental.Deferred
import kotlinx.coroutines.experimental.async
import javax.inject.Inject
class AuthModel: BlackBirdModel() {
@Inject
lateinit var kosService: KosService
lateinit var siriusService: SiriusService
lateinit var eventDao: EventDao
@Inject lateinit var kosService: KosService
@Inject lateinit var siriusService: SiriusService
@Inject lateinit var eventDao: EventDao
@Inject lateinit var courseDao: CourseDao
init {
......@@ -80,20 +83,30 @@ class AuthModel: BlackBirdModel() {
}
suspend fun initLoad(): Result<Unit> {
val courses = async { fetch(kosService.getStudentsCourses()) }
val events = async { refreshEvents(siriusService, eventDao) }
val courses = async {
val deferredCourseList = ArrayList<Deferred<Result<Course>>>()
val completedCoarses = ArrayList<Result<Course>>()
val courses = fetch(kosService.getStudentsCourses())
if (courses is Success) {
for (link in courses.value.courses)
deferredCourseList.add(async { fetch(kosService.getCourse(link.name)) })
deferredCourseList.forEach { completedCoarses.add(it.await()) }
}
completedCoarses
}
val resultCourses = courses.await()
val resultEvents = events.await()
return if (resultCourses is Success && resultEvents is Success) {
return if (resultCourses.all { it is Success } && resultEvents is Success) {
courseDao.insertAll(resultCourses.map { (it as Success).value })
Success(Unit)
} else Failure("Failed initializing account.\n" +
"Error message: " +
when {
resultCourses is Failure -> resultCourses.message
resultEvents is Failure -> resultEvents.message
else -> "Unknown Error"
when (resultEvents) {
is Failure -> resultEvents.message
else -> (resultCourses.firstOrNull { it is Failure } as? Failure)
?.message ?: "Unknow error"
}
)
}
......
......@@ -2,6 +2,7 @@ package com.cvut.blackbird.model.flows
import com.cvut.blackbird.BlackBirdAC
import com.cvut.blackbird.model.*
import com.cvut.blackbird.model.database.CourseDao
import com.cvut.blackbird.model.database.EventDao
import com.cvut.blackbird.model.services.SiriusService
import javax.inject.Inject
......@@ -9,14 +10,15 @@ import javax.inject.Inject
typealias DateSpan = Pair<Long, Long>
class TimetableModel: BlackBirdModel() {
@Inject
lateinit var siriusService: SiriusService
@Inject
lateinit var eventDao: EventDao
@Inject lateinit var siriusService: SiriusService
@Inject lateinit var eventDao: EventDao
@Inject lateinit var courseDao: CourseDao
init { BlackBirdAC.graph.inject(this) }
suspend fun getTimetable(span: DateSpan) = eventDao.timeSpan(span.first, span.second)
suspend fun refreshEvents() = refreshEvents(siriusService, eventDao)
suspend fun getCourse(code: String) = courseDao.getCourse(code)
}
\ No newline at end of file
package com.cvut.blackbird.model.services
import com.cvut.blackbird.model.entities.CourseRoot
import com.cvut.blackbird.model.entities.Course
import com.cvut.blackbird.model.entities.EnrolledCourseRoot
import com.cvut.blackbird.model.entities.Student
import retrofit2.Call
import retrofit2.Response
import retrofit2.http.*
interface KosService {
......@@ -21,9 +21,18 @@ interface KosService {
@GET("students/{user}/enrolledCourses")
fun getStudentsCourses(
@Path("user") user: String = UserInfo.username,
@Query("sem") semester: String = "none",
@Header("Authorization") token: String = accessToken,
@Query("limit") resultsLimit: Int = 1000,
@Query("lang") lang: String = "en",
@Query("multilang") multilang: Boolean = false
): Call<EnrolledCourseRoot>
@GET("courses/{course}")
fun getCourse(
@Path("course") course: String,
@Header("Authorization") token: String = accessToken,
@Query("lang") lang: String = "en"
): Call<CourseRoot>
): Call<Course>
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment