forked from github/wulkanowy-mirror
Add excusing for absence (#533)
This commit is contained in:

committed by
Rafał Borcz

parent
0c5d45717c
commit
19f495cba6
@ -61,6 +61,7 @@ import io.github.wulkanowy.data.db.migrations.Migration18
|
||||
import io.github.wulkanowy.data.db.migrations.Migration19
|
||||
import io.github.wulkanowy.data.db.migrations.Migration2
|
||||
import io.github.wulkanowy.data.db.migrations.Migration20
|
||||
import io.github.wulkanowy.data.db.migrations.Migration21
|
||||
import io.github.wulkanowy.data.db.migrations.Migration3
|
||||
import io.github.wulkanowy.data.db.migrations.Migration4
|
||||
import io.github.wulkanowy.data.db.migrations.Migration5
|
||||
@ -102,7 +103,7 @@ import javax.inject.Singleton
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
|
||||
companion object {
|
||||
const val VERSION_SCHEMA = 20
|
||||
const val VERSION_SCHEMA = 21
|
||||
|
||||
fun getMigrations(sharedPrefProvider: SharedPrefProvider): Array<Migration> {
|
||||
return arrayOf(
|
||||
@ -124,7 +125,8 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
Migration17(),
|
||||
Migration18(),
|
||||
Migration19(sharedPrefProvider),
|
||||
Migration20()
|
||||
Migration20(),
|
||||
Migration21()
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,9 @@ data class Attendance(
|
||||
@ColumnInfo(name = "diary_id")
|
||||
val diaryId: Int,
|
||||
|
||||
@ColumnInfo(name = "time_id")
|
||||
val timeId: Int,
|
||||
|
||||
val date: LocalDate,
|
||||
|
||||
val number: Int,
|
||||
@ -33,7 +36,13 @@ data class Attendance(
|
||||
|
||||
val excused: Boolean,
|
||||
|
||||
val deleted: Boolean
|
||||
val deleted: Boolean,
|
||||
|
||||
val excusable: Boolean,
|
||||
|
||||
@ColumnInfo(name = "excuse_status")
|
||||
val excuseStatus: String?
|
||||
|
||||
) : Serializable {
|
||||
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
|
@ -0,0 +1,13 @@
|
||||
package io.github.wulkanowy.data.db.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration21 : Migration(20, 21) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE Attendance ADD COLUMN excusable INTEGER NOT NULL DEFAULT 0")
|
||||
database.execSQL("ALTER TABLE Attendance ADD COLUMN time_id INTEGER NOT NULL DEFAULT 0")
|
||||
database.execSQL("ALTER TABLE Attendance ADD COLUMN excuse_status TEXT DEFAULT NULL")
|
||||
}
|
||||
}
|
@ -3,8 +3,11 @@ package io.github.wulkanowy.data.repositories.attendance
|
||||
import io.github.wulkanowy.data.db.entities.Attendance
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.sdk.Sdk
|
||||
import io.github.wulkanowy.sdk.pojo.Absent
|
||||
import io.reactivex.Single
|
||||
import org.threeten.bp.LocalDate
|
||||
import org.threeten.bp.LocalDateTime
|
||||
import org.threeten.bp.LocalTime
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@ -19,6 +22,7 @@ class AttendanceRemote @Inject constructor(private val sdk: Sdk) {
|
||||
studentId = semester.studentId,
|
||||
diaryId = semester.diaryId,
|
||||
date = it.date,
|
||||
timeId = it.timeId,
|
||||
number = it.number,
|
||||
subject = it.subject,
|
||||
name = it.name,
|
||||
@ -27,9 +31,20 @@ class AttendanceRemote @Inject constructor(private val sdk: Sdk) {
|
||||
exemption = it.exemption,
|
||||
lateness = it.lateness,
|
||||
excused = it.excused,
|
||||
deleted = it.deleted
|
||||
deleted = it.deleted,
|
||||
excusable = it.excusable,
|
||||
excuseStatus = it.excuseStatus?.name
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun excuseAbsence(semester: Semester, absenceList: List<Attendance>, reason: String?): Single<Boolean> {
|
||||
return sdk.switchDiary(semester.diaryId, semester.schoolYear).excuseForAbsence(absenceList.map { attendance ->
|
||||
Absent(
|
||||
date = LocalDateTime.of(attendance.date, LocalTime.of(0, 0)),
|
||||
timeId = attendance.timeId
|
||||
)
|
||||
}, reason)
|
||||
}
|
||||
}
|
||||
|
@ -41,4 +41,8 @@ class AttendanceRepository @Inject constructor(
|
||||
}).map { list -> list.filter { it.date in startDate..endDate } }
|
||||
}
|
||||
}
|
||||
|
||||
fun excuseForAbsence(semester: Semester, attendanceList: List<Attendance>, reason: String? = null): Single<Boolean> {
|
||||
return remote.excuseAbsence(semester, attendanceList, reason)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,7 @@
|
||||
package io.github.wulkanowy.data.repositories.attendance
|
||||
|
||||
enum class SentExcuseStatus(val id: Int = 0) {
|
||||
WAITING,
|
||||
ACCEPTED,
|
||||
DENIED
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package io.github.wulkanowy.ui.modules.attendance
|
||||
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import io.github.wulkanowy.data.db.entities.Attendance
|
||||
|
||||
class AttendanceAdapter<T : IFlexible<*>> : FlexibleAdapter<T>(null, null, true) {
|
||||
|
||||
var excuseActionMode: Boolean = false
|
||||
|
||||
var onExcuseCheckboxSelect: (attendanceItem: Attendance, checked: Boolean) -> Unit = { _, _ -> }
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package io.github.wulkanowy.ui.modules.attendance
|
||||
|
||||
import android.content.DialogInterface.BUTTON_POSITIVE
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
@ -10,8 +11,9 @@ import android.view.View.GONE
|
||||
import android.view.View.INVISIBLE
|
||||
import android.view.View.VISIBLE
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.view.ActionMode
|
||||
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.common.FlexibleItemDecoration
|
||||
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
@ -24,6 +26,7 @@ import io.github.wulkanowy.ui.modules.main.MainView
|
||||
import io.github.wulkanowy.utils.SchooldaysRangeLimiter
|
||||
import io.github.wulkanowy.utils.dpToPx
|
||||
import io.github.wulkanowy.utils.setOnItemClickListener
|
||||
import kotlinx.android.synthetic.main.dialog_excuse.*
|
||||
import kotlinx.android.synthetic.main.fragment_attendance.*
|
||||
import org.threeten.bp.LocalDate
|
||||
import javax.inject.Inject
|
||||
@ -35,7 +38,13 @@ class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildVie
|
||||
lateinit var presenter: AttendancePresenter
|
||||
|
||||
@Inject
|
||||
lateinit var attendanceAdapter: FlexibleAdapter<AbstractFlexibleItem<*>>
|
||||
lateinit var attendanceAdapter: AttendanceAdapter<AbstractFlexibleItem<*>>
|
||||
|
||||
override val excuseSuccessString: String
|
||||
get() = getString(R.string.attendance_excuse_success)
|
||||
|
||||
override val excuseNoSelectionString: String
|
||||
get() = getString(R.string.attendance_excuse_no_selection)
|
||||
|
||||
companion object {
|
||||
private const val SAVED_DATE_KEY = "CURRENT_DATE"
|
||||
@ -49,6 +58,34 @@ class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildVie
|
||||
|
||||
override val currentStackSize get() = (activity as? MainActivity)?.currentStackSize
|
||||
|
||||
override val excuseActionMode: Boolean get() = attendanceAdapter.excuseActionMode
|
||||
|
||||
private var actionMode: ActionMode? = null
|
||||
private val actionModeCallback = object : ActionMode.Callback {
|
||||
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
|
||||
val inflater = mode.menuInflater
|
||||
inflater.inflate(R.menu.context_menu_excuse, menu)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
|
||||
mode.title = getString(R.string.attendance_excuse_title)
|
||||
return presenter.onPrepareActionMode()
|
||||
}
|
||||
|
||||
override fun onDestroyActionMode(mode: ActionMode) {
|
||||
presenter.onDestroyActionMode()
|
||||
actionMode = null
|
||||
}
|
||||
|
||||
override fun onActionItemClicked(mode: ActionMode, menu: MenuItem): Boolean {
|
||||
return when (menu.itemId) {
|
||||
R.id.excuseMenuSubmit -> presenter.onExcuseSubmitButtonClick()
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
@ -66,6 +103,7 @@ class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildVie
|
||||
|
||||
override fun initView() {
|
||||
attendanceAdapter.setOnItemClickListener(presenter::onAttendanceItemSelected)
|
||||
attendanceAdapter.onExcuseCheckboxSelect = presenter::onExcuseCheckboxSelect
|
||||
|
||||
with(attendanceRecycler) {
|
||||
layoutManager = SmoothScrollLinearLayoutManager(context)
|
||||
@ -83,6 +121,8 @@ class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildVie
|
||||
attendanceNavDate.setOnClickListener { presenter.onPickDate() }
|
||||
attendanceNextButton.setOnClickListener { presenter.onNextDay() }
|
||||
|
||||
attendanceExcuseButton.setOnClickListener { presenter.onExcuseButtonClick() }
|
||||
|
||||
attendanceNavContainer.setElevationCompat(requireContext().dpToPx(8f))
|
||||
}
|
||||
|
||||
@ -115,6 +155,10 @@ class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildVie
|
||||
if (::presenter.isInitialized) presenter.onViewReselected()
|
||||
}
|
||||
|
||||
override fun onFragmentChanged() {
|
||||
if (::presenter.isInitialized) presenter.onMainViewChanged()
|
||||
}
|
||||
|
||||
override fun popView() {
|
||||
(activity as? MainActivity)?.popView()
|
||||
}
|
||||
@ -155,6 +199,10 @@ class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildVie
|
||||
attendanceNextButton.visibility = if (show) VISIBLE else INVISIBLE
|
||||
}
|
||||
|
||||
override fun showExcuseButton(show: Boolean) {
|
||||
attendanceExcuseButton.visibility = if (show) VISIBLE else GONE
|
||||
}
|
||||
|
||||
override fun showAttendanceDialog(lesson: Attendance) {
|
||||
(activity as? MainActivity)?.showDialogFragment(AttendanceDialog.newInstance(lesson))
|
||||
}
|
||||
@ -174,10 +222,38 @@ class AttendanceFragment : BaseFragment(), AttendanceView, MainView.MainChildVie
|
||||
}
|
||||
}
|
||||
|
||||
override fun showExcuseDialog() {
|
||||
AlertDialog.Builder(requireContext())
|
||||
.setTitle(R.string.attendance_excuse_title)
|
||||
.setView(R.layout.dialog_excuse)
|
||||
.setNegativeButton(android.R.string.cancel) { _, _ -> }
|
||||
.create()
|
||||
.apply {
|
||||
setButton(BUTTON_POSITIVE, getString(R.string.attendance_excuse_dialog_submit)) { _, _ ->
|
||||
presenter.onExcuseDialogSubmit(excuseReason.text?.toString().orEmpty())
|
||||
}
|
||||
}.show()
|
||||
}
|
||||
|
||||
override fun openSummaryView() {
|
||||
(activity as? MainActivity)?.pushView(AttendanceSummaryFragment.newInstance())
|
||||
}
|
||||
|
||||
override fun startActionMode() {
|
||||
actionMode = (activity as MainActivity?)?.startSupportActionMode(actionModeCallback)
|
||||
}
|
||||
|
||||
override fun showExcuseCheckboxes(show: Boolean) {
|
||||
attendanceAdapter.apply {
|
||||
excuseActionMode = show
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
override fun finishActionMode() {
|
||||
actionMode?.finish()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putLong(SAVED_DATE_KEY, presenter.currentDate.toEpochDay())
|
||||
|
@ -1,18 +1,22 @@
|
||||
package io.github.wulkanowy.ui.modules.attendance
|
||||
|
||||
import android.view.View
|
||||
import android.view.View.GONE
|
||||
import android.view.View.INVISIBLE
|
||||
import android.view.View.VISIBLE
|
||||
import androidx.core.view.isVisible
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.davidea.viewholders.FlexibleViewHolder
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Attendance
|
||||
import io.github.wulkanowy.data.repositories.attendance.SentExcuseStatus
|
||||
import kotlinx.android.extensions.LayoutContainer
|
||||
import kotlinx.android.synthetic.main.item_attendance.*
|
||||
|
||||
class AttendanceItem(val attendance: Attendance) : AbstractFlexibleItem<AttendanceItem.ViewHolder>() {
|
||||
class AttendanceItem(val attendance: Attendance) :
|
||||
AbstractFlexibleItem<AttendanceItem.ViewHolder>() {
|
||||
|
||||
override fun getLayoutRes() = R.layout.item_attendance
|
||||
|
||||
@ -26,6 +30,34 @@ class AttendanceItem(val attendance: Attendance) : AbstractFlexibleItem<Attendan
|
||||
attendanceItemSubject.text = attendance.subject
|
||||
attendanceItemDescription.text = attendance.name
|
||||
attendanceItemAlert.visibility = attendance.run { if (absence && !excused) VISIBLE else INVISIBLE }
|
||||
attendanceItemNumber.visibility = GONE
|
||||
attendanceItemExcuseInfo.visibility = GONE
|
||||
attendanceItemExcuseCheckbox.visibility = GONE
|
||||
attendanceItemExcuseCheckbox.isChecked = false
|
||||
attendanceItemExcuseCheckbox.setOnCheckedChangeListener { _, checked ->
|
||||
(adapter as AttendanceAdapter).onExcuseCheckboxSelect(attendance, checked)
|
||||
}
|
||||
|
||||
when (if (attendance.excuseStatus != null) SentExcuseStatus.valueOf(attendance.excuseStatus) else null) {
|
||||
SentExcuseStatus.WAITING -> {
|
||||
attendanceItemExcuseInfo.setImageResource(R.drawable.ic_excuse_waiting)
|
||||
attendanceItemExcuseInfo.visibility = VISIBLE
|
||||
attendanceItemAlert.visibility = INVISIBLE
|
||||
}
|
||||
SentExcuseStatus.DENIED -> {
|
||||
attendanceItemExcuseInfo.setImageResource(R.drawable.ic_excuse_denied)
|
||||
attendanceItemExcuseInfo.visibility = VISIBLE
|
||||
}
|
||||
else -> {
|
||||
if (attendance.excusable && (adapter as AttendanceAdapter).excuseActionMode) {
|
||||
attendanceItemNumber.visibility = GONE
|
||||
attendanceItemExcuseCheckbox.visibility = VISIBLE
|
||||
} else {
|
||||
attendanceItemNumber.visibility = VISIBLE
|
||||
attendanceItemExcuseCheckbox.visibility = GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,8 +78,20 @@ class AttendanceItem(val attendance: Attendance) : AbstractFlexibleItem<Attendan
|
||||
return result
|
||||
}
|
||||
|
||||
class ViewHolder(view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter), LayoutContainer {
|
||||
class ViewHolder(view: View, val adapter: FlexibleAdapter<*>) :
|
||||
FlexibleViewHolder(view, adapter),
|
||||
LayoutContainer {
|
||||
|
||||
override val containerView: View
|
||||
get() = contentView
|
||||
|
||||
override fun onClick(view: View?) {
|
||||
super.onClick(view)
|
||||
attendanceItemExcuseCheckbox.apply {
|
||||
if ((adapter as AttendanceAdapter).excuseActionMode && isVisible) {
|
||||
isChecked = !isChecked
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,12 @@
|
||||
package io.github.wulkanowy.ui.modules.attendance
|
||||
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
|
||||
@Module
|
||||
class AttendanceModule {
|
||||
|
||||
@Provides
|
||||
fun provideAttendanceFlexibleAdapter() = AttendanceAdapter<AbstractFlexibleItem<*>>()
|
||||
}
|
@ -2,6 +2,7 @@ package io.github.wulkanowy.ui.modules.attendance
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import io.github.wulkanowy.data.db.entities.Attendance
|
||||
import io.github.wulkanowy.data.repositories.attendance.AttendanceRepository
|
||||
import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
|
||||
import io.github.wulkanowy.data.repositories.semester.SemesterRepository
|
||||
@ -40,6 +41,8 @@ class AttendancePresenter @Inject constructor(
|
||||
|
||||
private lateinit var lastError: Throwable
|
||||
|
||||
private val attendanceToExcuseList = mutableListOf<Attendance>()
|
||||
|
||||
fun onAttachView(view: AttendanceView, date: Long?) {
|
||||
super.onAttachView(view)
|
||||
view.initView()
|
||||
@ -51,11 +54,15 @@ class AttendancePresenter @Inject constructor(
|
||||
}
|
||||
|
||||
fun onPreviousDay() {
|
||||
view?.finishActionMode()
|
||||
attendanceToExcuseList.clear()
|
||||
loadData(currentDate.previousSchoolDay)
|
||||
reloadView()
|
||||
}
|
||||
|
||||
fun onNextDay() {
|
||||
view?.finishActionMode()
|
||||
attendanceToExcuseList.clear()
|
||||
loadData(currentDate.nextSchoolDay)
|
||||
reloadView()
|
||||
}
|
||||
@ -100,10 +107,59 @@ class AttendancePresenter @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun onMainViewChanged() {
|
||||
view?.finishActionMode()
|
||||
}
|
||||
|
||||
fun onAttendanceItemSelected(item: AbstractFlexibleItem<*>?) {
|
||||
if (item is AttendanceItem) {
|
||||
Timber.i("Select attendance item ${item.attendance.id}")
|
||||
view?.showAttendanceDialog(item.attendance)
|
||||
view?.apply {
|
||||
if (item is AttendanceItem && !excuseActionMode) {
|
||||
Timber.i("Select attendance item ${item.attendance.id}")
|
||||
showAttendanceDialog(item.attendance)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onExcuseButtonClick() {
|
||||
view?.startActionMode()
|
||||
}
|
||||
|
||||
fun onExcuseCheckboxSelect(attendanceItem: Attendance, checked: Boolean) {
|
||||
if (checked) attendanceToExcuseList.add(attendanceItem)
|
||||
else attendanceToExcuseList.remove(attendanceItem)
|
||||
}
|
||||
|
||||
fun onExcuseSubmitButtonClick(): Boolean {
|
||||
view?.apply {
|
||||
return if (attendanceToExcuseList.isNotEmpty()) {
|
||||
showExcuseDialog()
|
||||
true
|
||||
} else {
|
||||
showMessage(excuseNoSelectionString)
|
||||
false
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun onExcuseDialogSubmit(reason: String) {
|
||||
view?.finishActionMode()
|
||||
excuseAbsence(if (reason != "") reason else null, attendanceToExcuseList.toList())
|
||||
}
|
||||
|
||||
fun onPrepareActionMode(): Boolean {
|
||||
view?.apply {
|
||||
showExcuseCheckboxes(true)
|
||||
showExcuseButton(false)
|
||||
}
|
||||
attendanceToExcuseList.clear()
|
||||
return true
|
||||
}
|
||||
|
||||
fun onDestroyActionMode() {
|
||||
view?.apply {
|
||||
showExcuseCheckboxes(false)
|
||||
showExcuseButton(true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,6 +213,7 @@ class AttendancePresenter @Inject constructor(
|
||||
showEmpty(it.isEmpty())
|
||||
showErrorView(false)
|
||||
showContent(it.isNotEmpty())
|
||||
showExcuseButton(it.any { item -> item.attendance.excusable })
|
||||
}
|
||||
analytics.logEvent("load_attendance", "items" to it.size, "force_refresh" to forceRefresh)
|
||||
}) {
|
||||
@ -167,6 +224,39 @@ class AttendancePresenter @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun excuseAbsence(reason: String?, toExcuseList: List<Attendance>) {
|
||||
Timber.i("Excusing absence started")
|
||||
disposable.apply {
|
||||
add(studentRepository.getCurrentStudent()
|
||||
.delay(200, MILLISECONDS)
|
||||
.flatMap { semesterRepository.getCurrentSemester(it) }
|
||||
.flatMap { attendanceRepository.excuseForAbsence(it, toExcuseList, reason) }
|
||||
.subscribeOn(schedulers.backgroundThread)
|
||||
.observeOn(schedulers.mainThread)
|
||||
.doOnSubscribe {
|
||||
view?.apply {
|
||||
showProgress(true)
|
||||
showContent(false)
|
||||
showExcuseButton(false)
|
||||
}
|
||||
}
|
||||
.subscribe({
|
||||
Timber.i("Excusing for absence result: Success")
|
||||
analytics.logEvent("excuse_absence", "items" to attendanceToExcuseList.size)
|
||||
attendanceToExcuseList.clear()
|
||||
view?.apply {
|
||||
showExcuseButton(false)
|
||||
showMessage(excuseSuccessString)
|
||||
}
|
||||
loadData(currentDate, true)
|
||||
}) {
|
||||
Timber.i("Excusing for absence result: An exception occurred")
|
||||
view?.showProgress(false)
|
||||
errorHandler.dispatch(it)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun showErrorViewOnError(message: String, error: Throwable) {
|
||||
view?.run {
|
||||
if (isViewEmpty) {
|
||||
|
@ -10,6 +10,12 @@ interface AttendanceView : BaseView {
|
||||
|
||||
val currentStackSize: Int?
|
||||
|
||||
val excuseSuccessString: String
|
||||
|
||||
val excuseNoSelectionString: String
|
||||
|
||||
val excuseActionMode: Boolean
|
||||
|
||||
fun initView()
|
||||
|
||||
fun updateData(data: List<AttendanceItem>)
|
||||
@ -38,11 +44,21 @@ interface AttendanceView : BaseView {
|
||||
|
||||
fun showNextButton(show: Boolean)
|
||||
|
||||
fun showExcuseButton(show: Boolean)
|
||||
|
||||
fun showAttendanceDialog(lesson: Attendance)
|
||||
|
||||
fun showDatePickerDialog(currentDate: LocalDate)
|
||||
|
||||
fun showExcuseDialog()
|
||||
|
||||
fun openSummaryView()
|
||||
|
||||
fun startActionMode()
|
||||
|
||||
fun showExcuseCheckboxes(show: Boolean)
|
||||
|
||||
fun finishActionMode()
|
||||
|
||||
fun popView()
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ import io.github.wulkanowy.utils.getThemeAttrColor
|
||||
import io.github.wulkanowy.utils.safelyPopFragments
|
||||
import io.github.wulkanowy.utils.setOnViewChangeListener
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
class MainActivity : BaseActivity<MainPresenter>(), MainView {
|
||||
@ -167,6 +168,11 @@ class MainActivity : BaseActivity<MainPresenter>(), MainView {
|
||||
(navController.currentStack?.getOrNull(0) as? MainView.MainChildView)?.onFragmentReselected()
|
||||
}
|
||||
|
||||
override fun notifyMenuViewChanged() {
|
||||
Timber.d("Menu view changed")
|
||||
(navController.currentStack?.getOrNull(0) as? MainView.MainChildView)?.onFragmentChanged()
|
||||
}
|
||||
|
||||
fun showDialogFragment(dialog: DialogFragment) {
|
||||
navController.showDialogFragment(dialog)
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import io.github.wulkanowy.ui.modules.about.license.LicenseFragment
|
||||
import io.github.wulkanowy.ui.modules.about.license.LicenseModule
|
||||
import io.github.wulkanowy.ui.modules.account.AccountDialog
|
||||
import io.github.wulkanowy.ui.modules.attendance.AttendanceFragment
|
||||
import io.github.wulkanowy.ui.modules.attendance.AttendanceModule
|
||||
import io.github.wulkanowy.ui.modules.attendance.summary.AttendanceSummaryFragment
|
||||
import io.github.wulkanowy.ui.modules.exam.ExamFragment
|
||||
import io.github.wulkanowy.ui.modules.grade.GradeFragment
|
||||
@ -51,7 +52,7 @@ abstract class MainModule {
|
||||
}
|
||||
|
||||
@PerFragment
|
||||
@ContributesAndroidInjector
|
||||
@ContributesAndroidInjector(modules = [AttendanceModule::class])
|
||||
abstract fun bindAttendanceFragment(): AttendanceFragment
|
||||
|
||||
@PerFragment
|
||||
|
@ -75,6 +75,7 @@ class MainPresenter @Inject constructor(
|
||||
notifyMenuViewReselected()
|
||||
false
|
||||
} else {
|
||||
notifyMenuViewChanged()
|
||||
switchMenuView(index)
|
||||
true
|
||||
}
|
||||
|
@ -26,6 +26,8 @@ interface MainView : BaseView {
|
||||
|
||||
fun notifyMenuViewReselected()
|
||||
|
||||
fun notifyMenuViewChanged()
|
||||
|
||||
fun setViewTitle(title: String)
|
||||
|
||||
fun popView(depth: Int = 1)
|
||||
@ -33,6 +35,8 @@ interface MainView : BaseView {
|
||||
interface MainChildView {
|
||||
|
||||
fun onFragmentReselected()
|
||||
|
||||
fun onFragmentChanged() {}
|
||||
}
|
||||
|
||||
interface TitledView {
|
||||
|
Reference in New Issue
Block a user