mirror of
https://github.com/wulkanowy/wulkanowy.git
synced 2025-01-31 12:58:21 +01:00
Refactor attendance module (#161)
This commit is contained in:
parent
a1f64baca4
commit
357b2350cb
@ -68,12 +68,13 @@ play {
|
|||||||
uploadImages = true
|
uploadImages = true
|
||||||
}
|
}
|
||||||
|
|
||||||
ext.supportVersion = "28.0.0-rc02"
|
ext.supportVersion = "28.0.0"
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
implementation 'com.github.wulkanowy:api:ad57669'
|
implementation('com.github.wulkanowy:api:07201a4') {
|
||||||
|
exclude module: "threetenbp"
|
||||||
|
}
|
||||||
implementation "com.android.support:support-v4:$supportVersion"
|
implementation "com.android.support:support-v4:$supportVersion"
|
||||||
implementation "com.android.support:design:$supportVersion"
|
implementation "com.android.support:design:$supportVersion"
|
||||||
implementation "com.android.support:cardview-v7:$supportVersion"
|
implementation "com.android.support:cardview-v7:$supportVersion"
|
||||||
@ -116,6 +117,7 @@ dependencies {
|
|||||||
debugImplementation "com.amitshekhar.android:debug-db:1.0.4"
|
debugImplementation "com.amitshekhar.android:debug-db:1.0.4"
|
||||||
|
|
||||||
testImplementation "junit:junit:4.12"
|
testImplementation "junit:junit:4.12"
|
||||||
|
testImplementation "io.mockk:mockk:1.8.8"
|
||||||
testImplementation "org.mockito:mockito-inline:2.21.0"
|
testImplementation "org.mockito:mockito-inline:2.21.0"
|
||||||
|
|
||||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
package io.github.wulkanowy.data.repositories.local
|
||||||
|
|
||||||
|
import android.arch.persistence.room.Room
|
||||||
|
import android.support.test.InstrumentationRegistry
|
||||||
|
import android.support.test.runner.AndroidJUnit4
|
||||||
|
import io.github.wulkanowy.data.db.AppDatabase
|
||||||
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.threeten.bp.LocalDate
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class AttendanceLocalTest {
|
||||||
|
|
||||||
|
private lateinit var attendanceLocal: AttendanceLocal
|
||||||
|
|
||||||
|
private lateinit var testDb: AppDatabase
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun createDb() {
|
||||||
|
testDb = Room.inMemoryDatabaseBuilder(InstrumentationRegistry.getContext(), AppDatabase::class.java).build()
|
||||||
|
attendanceLocal = AttendanceLocal(testDb.attendanceDao())
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun closeDb() {
|
||||||
|
testDb.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun saveAndReadTest() {
|
||||||
|
attendanceLocal.saveAttendance(listOf(
|
||||||
|
Attendance(studentId = "1", diaryId = "2", date = LocalDate.of(2018, 9, 10)),
|
||||||
|
Attendance(studentId = "1", diaryId = "2", date = LocalDate.of(2018, 9, 14)),
|
||||||
|
Attendance(studentId = "1", diaryId = "2", date = LocalDate.of(2018, 9, 17)) // in next week
|
||||||
|
))
|
||||||
|
|
||||||
|
val attendance = attendanceLocal
|
||||||
|
.getAttendance(Semester(studentId = "1", diaryId = "2", semesterId = "3"),
|
||||||
|
LocalDate.of(2018, 9, 10),
|
||||||
|
LocalDate.of(2018, 9, 14)
|
||||||
|
)
|
||||||
|
.blockingGet()
|
||||||
|
assertEquals(2, attendance.size)
|
||||||
|
assertEquals(attendance[0].date, LocalDate.of(2018, 9, 10))
|
||||||
|
assertEquals(attendance[1].date, LocalDate.of(2018, 9, 14))
|
||||||
|
}
|
||||||
|
}
|
@ -11,7 +11,6 @@ import org.junit.Before
|
|||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
import java.sql.Date
|
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@ -35,16 +34,19 @@ class ExamLocalTest {
|
|||||||
@Test
|
@Test
|
||||||
fun saveAndReadTest() {
|
fun saveAndReadTest() {
|
||||||
examLocal.saveExams(listOf(
|
examLocal.saveExams(listOf(
|
||||||
Exam(studentId = "1", diaryId = "2", date = Date.valueOf("2018-09-10")),
|
Exam(studentId = "1", diaryId = "2", date = LocalDate.of(2018, 9, 10)),
|
||||||
Exam(studentId = "1", diaryId = "2", date = Date.valueOf("2018-09-14")),
|
Exam(studentId = "1", diaryId = "2", date = LocalDate.of(2018, 9, 14)),
|
||||||
Exam(studentId = "1", diaryId = "2", date = Date.valueOf("2018-09-17")) // in next week
|
Exam(studentId = "1", diaryId = "2", date = LocalDate.of(2018, 9, 17)) // in next week
|
||||||
))
|
))
|
||||||
|
|
||||||
val exams = examLocal
|
val exams = examLocal
|
||||||
.getExams(Semester(studentId = "1", diaryId = "2", semesterId = "3"), LocalDate.of(2018, 9, 10))
|
.getExams(Semester(studentId = "1", diaryId = "2", semesterId = "3"),
|
||||||
|
LocalDate.of(2018, 9, 10),
|
||||||
|
LocalDate.of(2018, 9, 14)
|
||||||
|
)
|
||||||
.blockingGet()
|
.blockingGet()
|
||||||
assertEquals(2, exams.size)
|
assertEquals(2, exams.size)
|
||||||
assertEquals(exams[0].date, Date.valueOf("2018-09-10"))
|
assertEquals(exams[0].date, LocalDate.of(2018, 9, 10))
|
||||||
assertEquals(exams[1].date, Date.valueOf("2018-09-14"))
|
assertEquals(exams[1].date, LocalDate.of(2018, 9, 14))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,4 +52,8 @@ internal class RepositoryModule {
|
|||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
fun provideExamDao(database: AppDatabase) = database.examsDao()
|
fun provideExamDao(database: AppDatabase) = database.examsDao()
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
fun provideAttendanceDao(database: AppDatabase) = database.attendanceDao()
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,11 @@ package io.github.wulkanowy.data.db
|
|||||||
import android.arch.persistence.room.Database
|
import android.arch.persistence.room.Database
|
||||||
import android.arch.persistence.room.RoomDatabase
|
import android.arch.persistence.room.RoomDatabase
|
||||||
import android.arch.persistence.room.TypeConverters
|
import android.arch.persistence.room.TypeConverters
|
||||||
|
import io.github.wulkanowy.data.db.dao.AttendanceDao
|
||||||
import io.github.wulkanowy.data.db.dao.ExamDao
|
import io.github.wulkanowy.data.db.dao.ExamDao
|
||||||
import io.github.wulkanowy.data.db.dao.SemesterDao
|
import io.github.wulkanowy.data.db.dao.SemesterDao
|
||||||
import io.github.wulkanowy.data.db.dao.StudentDao
|
import io.github.wulkanowy.data.db.dao.StudentDao
|
||||||
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
import io.github.wulkanowy.data.db.entities.Exam
|
import io.github.wulkanowy.data.db.entities.Exam
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
@ -16,7 +18,8 @@ import javax.inject.Singleton
|
|||||||
entities = [
|
entities = [
|
||||||
Student::class,
|
Student::class,
|
||||||
Semester::class,
|
Semester::class,
|
||||||
Exam::class
|
Exam::class,
|
||||||
|
Attendance::class
|
||||||
],
|
],
|
||||||
version = 1,
|
version = 1,
|
||||||
exportSchema = false
|
exportSchema = false
|
||||||
@ -29,4 +32,6 @@ abstract class AppDatabase : RoomDatabase() {
|
|||||||
abstract fun semesterDao(): SemesterDao
|
abstract fun semesterDao(): SemesterDao
|
||||||
|
|
||||||
abstract fun examsDao(): ExamDao
|
abstract fun examsDao(): ExamDao
|
||||||
|
|
||||||
|
abstract fun attendanceDao(): AttendanceDao
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
package io.github.wulkanowy.data.db
|
package io.github.wulkanowy.data.db
|
||||||
|
|
||||||
import android.arch.persistence.room.TypeConverter
|
import android.arch.persistence.room.TypeConverter
|
||||||
|
import org.threeten.bp.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class Converters {
|
class Converters {
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun fromTimestamp(value: Long?): Date? = value?.run { Date(value) }
|
fun fromTimestamp(value: Long?): LocalDate? = value?.run {
|
||||||
|
DateTimeUtils.toInstant(Date(value)).atZone(ZoneOffset.UTC).toLocalDate()
|
||||||
|
}
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun dateToTimestamp(date: Date?): Long? = date?.time
|
fun dateToTimestamp(date: LocalDate?): Long? {
|
||||||
|
return date?.atStartOfDay()?.toInstant(ZoneOffset.UTC)?.toEpochMilli()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
|
import android.arch.persistence.room.Dao
|
||||||
|
import android.arch.persistence.room.Delete
|
||||||
|
import android.arch.persistence.room.Insert
|
||||||
|
import android.arch.persistence.room.Query
|
||||||
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
|
import io.reactivex.Maybe
|
||||||
|
import org.threeten.bp.LocalDate
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface AttendanceDao {
|
||||||
|
|
||||||
|
@Insert
|
||||||
|
fun insertAll(exams: List<Attendance>): List<Long>
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
fun deleteAll(exams: List<Attendance>)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM Attendance WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
||||||
|
fun getExams(diaryId: String, studentId: String, from: LocalDate, end: LocalDate): Maybe<List<Attendance>>
|
||||||
|
}
|
@ -6,7 +6,7 @@ import android.arch.persistence.room.Insert
|
|||||||
import android.arch.persistence.room.Query
|
import android.arch.persistence.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.Exam
|
import io.github.wulkanowy.data.db.entities.Exam
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
import java.util.*
|
import org.threeten.bp.LocalDate
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface ExamDao {
|
interface ExamDao {
|
||||||
@ -18,5 +18,5 @@ interface ExamDao {
|
|||||||
fun deleteAll(exams: List<Exam>)
|
fun deleteAll(exams: List<Exam>)
|
||||||
|
|
||||||
@Query("SELECT * FROM Exams WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
@Query("SELECT * FROM Exams WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
||||||
fun getExams(diaryId: String, studentId: String, from: Date, end: Date): Maybe<List<Exam>>
|
fun getExams(diaryId: String, studentId: String, from: LocalDate, end: LocalDate): Maybe<List<Exam>>
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
package io.github.wulkanowy.data.db.entities
|
||||||
|
|
||||||
|
import android.arch.persistence.room.ColumnInfo
|
||||||
|
import android.arch.persistence.room.Entity
|
||||||
|
import android.arch.persistence.room.PrimaryKey
|
||||||
|
import org.threeten.bp.LocalDate
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
@Entity(tableName = "Attendance")
|
||||||
|
data class Attendance(
|
||||||
|
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
var id: Long = 0,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "student_id")
|
||||||
|
var studentId: String = "",
|
||||||
|
|
||||||
|
@ColumnInfo(name = "diary_id")
|
||||||
|
var diaryId: String = "",
|
||||||
|
|
||||||
|
var date: LocalDate,
|
||||||
|
|
||||||
|
var number: Int = 0,
|
||||||
|
|
||||||
|
var subject: String = "",
|
||||||
|
|
||||||
|
var name: String = "",
|
||||||
|
|
||||||
|
var presence: Boolean = false,
|
||||||
|
|
||||||
|
var absence: Boolean = false,
|
||||||
|
|
||||||
|
var exemption: Boolean = false,
|
||||||
|
|
||||||
|
var lateness: Boolean = false,
|
||||||
|
|
||||||
|
var excused: Boolean = false,
|
||||||
|
|
||||||
|
var deleted: Boolean = false
|
||||||
|
) : Serializable
|
@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.entities
|
|||||||
import android.arch.persistence.room.ColumnInfo
|
import android.arch.persistence.room.ColumnInfo
|
||||||
import android.arch.persistence.room.Entity
|
import android.arch.persistence.room.Entity
|
||||||
import android.arch.persistence.room.PrimaryKey
|
import android.arch.persistence.room.PrimaryKey
|
||||||
|
import org.threeten.bp.LocalDate
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
@Entity(tableName = "Exams")
|
@Entity(tableName = "Exams")
|
||||||
data class Exam(
|
data class Exam(
|
||||||
@ -18,10 +18,10 @@ data class Exam(
|
|||||||
@ColumnInfo(name = "diary_id")
|
@ColumnInfo(name = "diary_id")
|
||||||
var diaryId: String = "",
|
var diaryId: String = "",
|
||||||
|
|
||||||
var date: Date,
|
var date: LocalDate,
|
||||||
|
|
||||||
@ColumnInfo(name = "entry_date")
|
@ColumnInfo(name = "entry_date")
|
||||||
var entryDate: Date = Date(),
|
var entryDate: LocalDate = LocalDate.now(),
|
||||||
|
|
||||||
var subject: String = "",
|
var subject: String = "",
|
||||||
|
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
package io.github.wulkanowy.data.repositories
|
||||||
|
|
||||||
|
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
|
||||||
|
import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
|
||||||
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import io.github.wulkanowy.data.repositories.local.AttendanceLocal
|
||||||
|
import io.github.wulkanowy.data.repositories.remote.AttendanceRemote
|
||||||
|
import io.github.wulkanowy.utils.extension.getWeekFirstDayAlwaysCurrent
|
||||||
|
import io.reactivex.Single
|
||||||
|
import org.threeten.bp.DayOfWeek
|
||||||
|
import org.threeten.bp.LocalDate
|
||||||
|
import org.threeten.bp.temporal.TemporalAdjusters
|
||||||
|
import java.net.UnknownHostException
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class AttendanceRepository @Inject constructor(
|
||||||
|
private val settings: InternetObservingSettings,
|
||||||
|
private val local: AttendanceLocal,
|
||||||
|
private val remote: AttendanceRemote
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun getAttendance(semester: Semester, startDate: LocalDate, endDate: LocalDate, forceRefresh: Boolean = false): Single<List<Attendance>> {
|
||||||
|
val start = startDate.getWeekFirstDayAlwaysCurrent()
|
||||||
|
val end = endDate.with(TemporalAdjusters.nextOrSame(DayOfWeek.FRIDAY))
|
||||||
|
|
||||||
|
return local.getAttendance(semester, start, end).filter { !forceRefresh }
|
||||||
|
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings).flatMap {
|
||||||
|
if (it) remote.getAttendance(semester, start, end)
|
||||||
|
else Single.error(UnknownHostException())
|
||||||
|
}.flatMap { newLessons ->
|
||||||
|
local.getAttendance(semester, start, end).toSingle(emptyList()).map { grades ->
|
||||||
|
local.deleteAttendance(grades - newLessons)
|
||||||
|
local.saveAttendance(newLessons - grades)
|
||||||
|
newLessons
|
||||||
|
}
|
||||||
|
}).map { list ->
|
||||||
|
list.asSequence().filter {
|
||||||
|
it.date in startDate..endDate
|
||||||
|
}.toList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,8 +6,12 @@ import io.github.wulkanowy.data.db.entities.Exam
|
|||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.repositories.local.ExamLocal
|
import io.github.wulkanowy.data.repositories.local.ExamLocal
|
||||||
import io.github.wulkanowy.data.repositories.remote.ExamRemote
|
import io.github.wulkanowy.data.repositories.remote.ExamRemote
|
||||||
|
import io.github.wulkanowy.utils.extension.getWeekFirstDayAlwaysCurrent
|
||||||
|
import io.github.wulkanowy.utils.extension.toDate
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
|
import org.threeten.bp.DayOfWeek
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
|
import org.threeten.bp.temporal.TemporalAdjusters
|
||||||
import java.net.UnknownHostException
|
import java.net.UnknownHostException
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@ -19,21 +23,24 @@ class ExamRepository @Inject constructor(
|
|||||||
private val remote: ExamRemote
|
private val remote: ExamRemote
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun getExams(semester: Semester, date: LocalDate, forceRefresh: Boolean = false): Single<List<Exam>> {
|
fun getExams(semester: Semester, startDate: LocalDate, endDate: LocalDate, forceRefresh: Boolean = false): Single<List<Exam>> {
|
||||||
return local.getExams(semester, date).filter { !forceRefresh }
|
val start = startDate.getWeekFirstDayAlwaysCurrent()
|
||||||
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
|
val end = endDate.with(TemporalAdjusters.nextOrSame(DayOfWeek.FRIDAY))
|
||||||
.flatMap {
|
|
||||||
if (it) remote.getExams(semester, date)
|
return local.getExams(semester, start, end).filter { !forceRefresh }
|
||||||
|
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings).flatMap {
|
||||||
|
if (it) remote.getExams(semester, start, end)
|
||||||
else Single.error(UnknownHostException())
|
else Single.error(UnknownHostException())
|
||||||
}.flatMap { newExams ->
|
}.flatMap { newExams ->
|
||||||
local.getExams(semester, date).toSingle(emptyList())
|
local.getExams(semester, start, end).toSingle(emptyList()).map { grades ->
|
||||||
.map {
|
local.deleteExams(grades - newExams)
|
||||||
local.deleteExams(it - newExams)
|
local.saveExams(newExams - grades)
|
||||||
local.saveExams(newExams - it)
|
|
||||||
|
|
||||||
newExams
|
newExams
|
||||||
}
|
}
|
||||||
|
}).map { list ->
|
||||||
|
list.asSequence().filter {
|
||||||
|
it.date in startDate..endDate
|
||||||
|
}.toList()
|
||||||
}
|
}
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
package io.github.wulkanowy.data.repositories.local
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.db.dao.AttendanceDao
|
||||||
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import io.reactivex.Maybe
|
||||||
|
import org.threeten.bp.LocalDate
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class AttendanceLocal @Inject constructor(private val attendanceDb: AttendanceDao) {
|
||||||
|
|
||||||
|
fun getAttendance(semester: Semester, startDate: LocalDate, endDate: LocalDate): Maybe<List<Attendance>> {
|
||||||
|
return attendanceDb.getExams(semester.diaryId, semester.studentId, startDate, endDate)
|
||||||
|
.filter { !it.isEmpty() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveAttendance(attendance: List<Attendance>) {
|
||||||
|
attendanceDb.insertAll(attendance)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteAttendance(attendance: List<Attendance>) {
|
||||||
|
attendanceDb.deleteAll(attendance)
|
||||||
|
}
|
||||||
|
}
|
@ -12,10 +12,9 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
class ExamLocal @Inject constructor(private val examDb: ExamDao) {
|
class ExamLocal @Inject constructor(private val examDb: ExamDao) {
|
||||||
|
|
||||||
fun getExams(semester: Semester, startDate: LocalDate): Maybe<List<Exam>> {
|
fun getExams(semester: Semester, startDate: LocalDate, endDate: LocalDate): Maybe<List<Exam>> {
|
||||||
return examDb.getExams(semester.diaryId, semester.studentId, startDate.toDate(),
|
return examDb.getExams(semester.diaryId, semester.studentId, startDate, endDate)
|
||||||
startDate.with(TemporalAdjusters.next(DayOfWeek.FRIDAY)).toDate()
|
.filter { !it.isEmpty() }
|
||||||
).filter { !it.isEmpty() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveExams(exams: List<Exam>) {
|
fun saveExams(exams: List<Exam>) {
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
package io.github.wulkanowy.data.repositories.remote
|
||||||
|
|
||||||
|
import io.github.wulkanowy.api.Api
|
||||||
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import io.github.wulkanowy.utils.extension.toLocalDate
|
||||||
|
import io.reactivex.Single
|
||||||
|
import org.threeten.bp.LocalDate
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class AttendanceRemote @Inject constructor(private val api: Api) {
|
||||||
|
|
||||||
|
fun getAttendance(semester: Semester, startDate: LocalDate, endDate: LocalDate): Single<List<Attendance>> {
|
||||||
|
return Single.just(api.run {
|
||||||
|
if (diaryId != semester.diaryId) {
|
||||||
|
diaryId = semester.diaryId
|
||||||
|
notifyDataChanged()
|
||||||
|
}
|
||||||
|
}).flatMap { api.getAttendance(startDate, endDate) }.map { attendance ->
|
||||||
|
attendance.map {
|
||||||
|
Attendance(
|
||||||
|
studentId = semester.studentId,
|
||||||
|
diaryId = semester.diaryId,
|
||||||
|
date = it.date.toLocalDate(),
|
||||||
|
number = it.number,
|
||||||
|
subject = it.subject,
|
||||||
|
name = it.name,
|
||||||
|
presence = it.presence,
|
||||||
|
absence = it.absence,
|
||||||
|
exemption = it.exemption,
|
||||||
|
lateness = it.lateness,
|
||||||
|
excused = it.excused,
|
||||||
|
deleted = it.deleted
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,27 +3,26 @@ package io.github.wulkanowy.data.repositories.remote
|
|||||||
import io.github.wulkanowy.api.Api
|
import io.github.wulkanowy.api.Api
|
||||||
import io.github.wulkanowy.data.db.entities.Exam
|
import io.github.wulkanowy.data.db.entities.Exam
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.utils.extension.toDate
|
import io.github.wulkanowy.utils.extension.toLocalDate
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class ExamRemote @Inject constructor(private val api: Api) {
|
class ExamRemote @Inject constructor(private val api: Api) {
|
||||||
|
|
||||||
fun getExams(semester: Semester, startDate: LocalDate): Single<List<Exam>> {
|
fun getExams(semester: Semester, startDate: LocalDate, endDate: LocalDate): Single<List<Exam>> {
|
||||||
return Single.just(api.run {
|
return Single.just(api.run {
|
||||||
if (diaryId != semester.diaryId) {
|
if (diaryId != semester.diaryId) {
|
||||||
diaryId = semester.diaryId
|
diaryId = semester.diaryId
|
||||||
notifyDataChanged()
|
notifyDataChanged()
|
||||||
}
|
}
|
||||||
}).flatMap { api.getExams(startDate.toDate()) }
|
}).flatMap { api.getExams(startDate, endDate) }.map { exams ->
|
||||||
.map { exams ->
|
|
||||||
exams.map {
|
exams.map {
|
||||||
Exam(
|
Exam(
|
||||||
studentId = semester.studentId,
|
studentId = semester.studentId,
|
||||||
diaryId = semester.diaryId,
|
diaryId = semester.diaryId,
|
||||||
date = it.date,
|
date = it.date.toLocalDate(),
|
||||||
entryDate = it.entryDate,
|
entryDate = it.entryDate.toLocalDate(),
|
||||||
subject = it.subject,
|
subject = it.subject,
|
||||||
group = it.group,
|
group = it.group,
|
||||||
type = it.type,
|
type = it.type,
|
||||||
|
@ -0,0 +1,49 @@
|
|||||||
|
package io.github.wulkanowy.ui.main.attendance
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.support.v4.app.DialogFragment
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import io.github.wulkanowy.R
|
||||||
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
|
import io.github.wulkanowy.utils.extension.toFormat
|
||||||
|
import kotlinx.android.synthetic.main.dialog_attendance.*
|
||||||
|
|
||||||
|
class AttendanceDialog : DialogFragment() {
|
||||||
|
|
||||||
|
private lateinit var attendance: Attendance
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val ARGUMENT_KEY = "Item"
|
||||||
|
|
||||||
|
fun newInstance(exam: Attendance): AttendanceDialog {
|
||||||
|
return AttendanceDialog().apply {
|
||||||
|
arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, exam) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setStyle(DialogFragment.STYLE_NORMAL, R.style.DialogFragmentTheme)
|
||||||
|
arguments?.run {
|
||||||
|
attendance = getSerializable(ARGUMENT_KEY) as Attendance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
|
dialog.setTitle(getString(R.string.all_details))
|
||||||
|
return inflater.inflate(R.layout.dialog_attendance, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
|
super.onActivityCreated(savedInstanceState)
|
||||||
|
|
||||||
|
attendanceDialogSubject.text = attendance.subject
|
||||||
|
attendanceDialogDescription.text = attendance.name
|
||||||
|
attendanceDialogDate.text = attendance.date.toFormat()
|
||||||
|
attendanceDialogNumber.text = attendance.number.toString()
|
||||||
|
attendanceDialogClose.setOnClickListener { dismiss() }
|
||||||
|
}
|
||||||
|
}
|
@ -4,17 +4,111 @@ import android.os.Bundle
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
|
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
||||||
|
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
import io.github.wulkanowy.ui.base.BaseFragment
|
import io.github.wulkanowy.ui.base.BaseFragment
|
||||||
|
import io.github.wulkanowy.utils.extension.setOnItemClickListener
|
||||||
|
import kotlinx.android.synthetic.main.fragment_attendance.*
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
class AttendanceFragment : BaseFragment() {
|
class AttendanceFragment : BaseFragment(), AttendanceView {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var presenter: AttendancePresenter
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var attendanceAdapter: FlexibleAdapter<AbstractFlexibleItem<*>>
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
private const val SAVED_DATE_KEY = "CURRENT_DATE"
|
||||||
fun newInstance() = AttendanceFragment()
|
fun newInstance() = AttendanceFragment()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
return inflater.inflate(R.layout.fragment_attendance, container, false)
|
return inflater.inflate(R.layout.fragment_attendance, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
|
super.onActivityCreated(savedInstanceState)
|
||||||
|
presenter.run {
|
||||||
|
attachView(this@AttendanceFragment)
|
||||||
|
loadData(date = savedInstanceState?.getLong(SAVED_DATE_KEY))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun initView() {
|
||||||
|
attendanceAdapter.run {
|
||||||
|
isAutoCollapseOnExpand = true
|
||||||
|
isAutoScrollOnExpand = true
|
||||||
|
setOnItemClickListener { presenter.onAttendanceItemSelected(getItem(it))}
|
||||||
|
}
|
||||||
|
attendanceRecycler.run {
|
||||||
|
layoutManager = SmoothScrollLinearLayoutManager(context)
|
||||||
|
adapter = attendanceAdapter
|
||||||
|
}
|
||||||
|
attendanceSwipe.setOnRefreshListener { presenter.loadData(date = null, forceRefresh = true) }
|
||||||
|
attendancePreviousButton.setOnClickListener { presenter.loadAttendanceForPreviousDay() }
|
||||||
|
attendanceNextButton.setOnClickListener { presenter.loadAttendanceForNextDay() }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateData(data: List<AttendanceItem>) {
|
||||||
|
attendanceAdapter.updateDataSet(data, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun clearData() {
|
||||||
|
attendanceAdapter.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateNavigationDay(date: String) {
|
||||||
|
attendanceNavDate.text = date
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isViewEmpty() = attendanceAdapter.isEmpty
|
||||||
|
|
||||||
|
override fun showEmpty(show: Boolean) {
|
||||||
|
attendanceEmpty.visibility = if (show) View.VISIBLE else View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showProgress(show: Boolean) {
|
||||||
|
attendanceProgress.visibility = if (show) View.VISIBLE else View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showContent(show: Boolean) {
|
||||||
|
attendanceRecycler.visibility = if (show) View.VISIBLE else View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showRefresh(show: Boolean) {
|
||||||
|
attendanceSwipe.isRefreshing = show
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showPreButton(show: Boolean) {
|
||||||
|
attendancePreviousButton.visibility = if (show) View.VISIBLE else View.INVISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showNextButton(show: Boolean) {
|
||||||
|
attendanceNextButton.visibility = if (show) View.VISIBLE else View.INVISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun showAttendanceDialog(lesson: Attendance) {
|
||||||
|
AttendanceDialog.newInstance(lesson).show(fragmentManager, lesson.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
|
super.onSaveInstanceState(outState)
|
||||||
|
outState.putLong(SAVED_DATE_KEY, presenter.currentDate.toEpochDay())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewStateRestored(savedInstanceState: Bundle?) {
|
||||||
|
super.onViewStateRestored(savedInstanceState)
|
||||||
|
presenter.loadData(date = savedInstanceState?.getLong(SAVED_DATE_KEY))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
presenter.detachView()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,55 @@
|
|||||||
|
package io.github.wulkanowy.ui.main.attendance
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
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 kotlinx.android.extensions.LayoutContainer
|
||||||
|
import kotlinx.android.synthetic.main.item_attendance.*
|
||||||
|
|
||||||
|
class AttendanceItem : AbstractFlexibleItem<AttendanceItem.ViewHolder>() {
|
||||||
|
|
||||||
|
lateinit var attendance: Attendance
|
||||||
|
|
||||||
|
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<*>>): ViewHolder {
|
||||||
|
return ViewHolder(view, adapter)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getLayoutRes(): Int = R.layout.item_attendance
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as AttendanceItem
|
||||||
|
|
||||||
|
if (attendance != other.attendance) return false
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return attendance.hashCode()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<*>>, holder: ViewHolder,
|
||||||
|
position: Int, payloads: MutableList<Any>?) {
|
||||||
|
holder.bind(attendance)
|
||||||
|
}
|
||||||
|
|
||||||
|
class ViewHolder(val view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter),
|
||||||
|
LayoutContainer {
|
||||||
|
|
||||||
|
override val containerView: View
|
||||||
|
get() = contentView
|
||||||
|
|
||||||
|
fun bind(lesson: Attendance) {
|
||||||
|
attendanceItemNumber.text = lesson.number.toString()
|
||||||
|
attendanceItemSubject.text = lesson.subject
|
||||||
|
attendanceItemDescription.text = lesson.name
|
||||||
|
attendanceItemAlert.visibility = if (lesson.absence && !lesson.excused) View.VISIBLE else View.INVISIBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,96 @@
|
|||||||
|
package io.github.wulkanowy.ui.main.attendance
|
||||||
|
|
||||||
|
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||||
|
import io.github.wulkanowy.data.ErrorHandler
|
||||||
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import io.github.wulkanowy.data.repositories.AttendanceRepository
|
||||||
|
import io.github.wulkanowy.data.repositories.SessionRepository
|
||||||
|
import io.github.wulkanowy.ui.base.BasePresenter
|
||||||
|
import io.github.wulkanowy.utils.extension.*
|
||||||
|
import io.github.wulkanowy.utils.schedulers.SchedulersManager
|
||||||
|
import org.threeten.bp.LocalDate
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class AttendancePresenter @Inject constructor(
|
||||||
|
private val errorHandler: ErrorHandler,
|
||||||
|
private val schedulers: SchedulersManager,
|
||||||
|
private val attendanceRepository: AttendanceRepository,
|
||||||
|
private val sessionRepository: SessionRepository
|
||||||
|
) : BasePresenter<AttendanceView>(errorHandler) {
|
||||||
|
|
||||||
|
var currentDate: LocalDate = LocalDate.now().getNearSchoolDayPrevOnWeekEnd()
|
||||||
|
private set
|
||||||
|
|
||||||
|
override fun attachView(view: AttendanceView) {
|
||||||
|
super.attachView(view)
|
||||||
|
view.initView()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadAttendanceForPreviousDay() = loadData(currentDate.getPreviousWorkDay().toEpochDay())
|
||||||
|
|
||||||
|
fun loadAttendanceForNextDay() = loadData(currentDate.getNextWorkDay().toEpochDay())
|
||||||
|
|
||||||
|
fun loadData(date: Long?, forceRefresh: Boolean = false) {
|
||||||
|
this.currentDate = LocalDate.ofEpochDay(date ?: currentDate.getNearSchoolDayPrevOnWeekEnd().toEpochDay())
|
||||||
|
if (currentDate.isHolidays()) return
|
||||||
|
|
||||||
|
disposable.clear()
|
||||||
|
disposable.add(sessionRepository.getSemesters()
|
||||||
|
.map { selectSemester(it, -1) }
|
||||||
|
.flatMap { attendanceRepository.getAttendance(it, currentDate, currentDate, forceRefresh) }
|
||||||
|
.map { createTimetableItems(it) }
|
||||||
|
.subscribeOn(schedulers.backgroundThread())
|
||||||
|
.observeOn(schedulers.mainThread())
|
||||||
|
.doOnSubscribe {
|
||||||
|
view?.run {
|
||||||
|
showRefresh(forceRefresh)
|
||||||
|
showProgress(!forceRefresh)
|
||||||
|
if (!forceRefresh) {
|
||||||
|
showEmpty(false)
|
||||||
|
clearData()
|
||||||
|
}
|
||||||
|
showPreButton(!currentDate.minusDays(1).isHolidays())
|
||||||
|
showNextButton(!currentDate.plusDays(1).isHolidays())
|
||||||
|
updateNavigationDay(currentDate.toFormat("EEEE \n dd.MM.YYYY").capitalize())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.doFinally {
|
||||||
|
view?.run {
|
||||||
|
showRefresh(false)
|
||||||
|
showProgress(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.subscribe({
|
||||||
|
view?.run {
|
||||||
|
showEmpty(it.isEmpty())
|
||||||
|
showContent(it.isNotEmpty())
|
||||||
|
updateData(it)
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
view?.run { showEmpty(isViewEmpty()) }
|
||||||
|
errorHandler.proceed(it)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createTimetableItems(items: List<Attendance>): List<AttendanceItem> {
|
||||||
|
return items.map {
|
||||||
|
AttendanceItem().apply { attendance = it }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onAttendanceItemSelected(item: AbstractFlexibleItem<*>?) {
|
||||||
|
if (item is AttendanceItem) view?.showAttendanceDialog(item.attendance)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun selectSemester(semesters: List<Semester>, index: Int): Semester {
|
||||||
|
return semesters.single { it.current }.let { currentSemester ->
|
||||||
|
if (index == -1) currentSemester
|
||||||
|
else semesters.single { semester ->
|
||||||
|
semester.run {
|
||||||
|
semesterName - 1 == index && diaryId == currentSemester.diaryId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package io.github.wulkanowy.ui.main.attendance
|
||||||
|
|
||||||
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
|
import io.github.wulkanowy.ui.base.BaseView
|
||||||
|
|
||||||
|
interface AttendanceView : BaseView {
|
||||||
|
|
||||||
|
fun initView()
|
||||||
|
|
||||||
|
fun updateData(data: List<AttendanceItem>)
|
||||||
|
|
||||||
|
fun clearData()
|
||||||
|
|
||||||
|
fun updateNavigationDay(date: String)
|
||||||
|
|
||||||
|
fun isViewEmpty(): Boolean
|
||||||
|
|
||||||
|
fun showEmpty(show: Boolean)
|
||||||
|
|
||||||
|
fun showProgress(show: Boolean)
|
||||||
|
|
||||||
|
fun showContent(show: Boolean)
|
||||||
|
|
||||||
|
fun showRefresh(show: Boolean)
|
||||||
|
|
||||||
|
fun showPreButton(show: Boolean)
|
||||||
|
|
||||||
|
fun showNextButton(show: Boolean)
|
||||||
|
|
||||||
|
fun showAttendanceDialog(lesson: Attendance)
|
||||||
|
}
|
@ -10,12 +10,11 @@ import io.github.wulkanowy.utils.extension.getWeekDayName
|
|||||||
import io.github.wulkanowy.utils.extension.toFormat
|
import io.github.wulkanowy.utils.extension.toFormat
|
||||||
import kotlinx.android.extensions.LayoutContainer
|
import kotlinx.android.extensions.LayoutContainer
|
||||||
import kotlinx.android.synthetic.main.header_exam.*
|
import kotlinx.android.synthetic.main.header_exam.*
|
||||||
import org.apache.commons.lang3.StringUtils
|
import org.threeten.bp.LocalDate
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class ExamHeader : AbstractHeaderItem<ExamHeader.ViewHolder>() {
|
class ExamHeader : AbstractHeaderItem<ExamHeader.ViewHolder>() {
|
||||||
|
|
||||||
lateinit var date: Date
|
lateinit var date: LocalDate
|
||||||
|
|
||||||
override fun createViewHolder(view: View?, adapter: FlexibleAdapter<IFlexible<*>>?): ViewHolder {
|
override fun createViewHolder(view: View?, adapter: FlexibleAdapter<IFlexible<*>>?): ViewHolder {
|
||||||
return ViewHolder(view, adapter)
|
return ViewHolder(view, adapter)
|
||||||
@ -41,7 +40,7 @@ class ExamHeader : AbstractHeaderItem<ExamHeader.ViewHolder>() {
|
|||||||
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<*>>?, holder: ViewHolder,
|
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<*>>?, holder: ViewHolder,
|
||||||
position: Int, payloads: MutableList<Any>?) {
|
position: Int, payloads: MutableList<Any>?) {
|
||||||
holder.run {
|
holder.run {
|
||||||
examHeaderDay.text = StringUtils.capitalize(date.getWeekDayName())
|
examHeaderDay.text = date.getWeekDayName().capitalize()
|
||||||
examHeaderDate.text = date.toFormat()
|
examHeaderDate.text = date.toFormat()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,12 +7,11 @@ import io.github.wulkanowy.data.db.entities.Semester
|
|||||||
import io.github.wulkanowy.data.repositories.ExamRepository
|
import io.github.wulkanowy.data.repositories.ExamRepository
|
||||||
import io.github.wulkanowy.data.repositories.SessionRepository
|
import io.github.wulkanowy.data.repositories.SessionRepository
|
||||||
import io.github.wulkanowy.ui.base.BasePresenter
|
import io.github.wulkanowy.ui.base.BasePresenter
|
||||||
|
import io.github.wulkanowy.utils.extension.getWeekFirstDayNextOnWeekEnd
|
||||||
import io.github.wulkanowy.utils.extension.isHolidays
|
import io.github.wulkanowy.utils.extension.isHolidays
|
||||||
import io.github.wulkanowy.utils.extension.toFormat
|
import io.github.wulkanowy.utils.extension.toFormat
|
||||||
import io.github.wulkanowy.utils.getNearMonday
|
|
||||||
import io.github.wulkanowy.utils.schedulers.SchedulersManager
|
import io.github.wulkanowy.utils.schedulers.SchedulersManager
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
import java.util.*
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class ExamPresenter @Inject constructor(
|
class ExamPresenter @Inject constructor(
|
||||||
@ -22,7 +21,7 @@ class ExamPresenter @Inject constructor(
|
|||||||
private val sessionRepository: SessionRepository
|
private val sessionRepository: SessionRepository
|
||||||
) : BasePresenter<ExamView>(errorHandler) {
|
) : BasePresenter<ExamView>(errorHandler) {
|
||||||
|
|
||||||
var currentDate: LocalDate = getNearMonday(LocalDate.now())
|
var currentDate: LocalDate = LocalDate.now().getWeekFirstDayNextOnWeekEnd()
|
||||||
private set
|
private set
|
||||||
|
|
||||||
override fun attachView(view: ExamView) {
|
override fun attachView(view: ExamView) {
|
||||||
@ -35,13 +34,13 @@ class ExamPresenter @Inject constructor(
|
|||||||
fun loadExamsForNextWeek() = loadData(currentDate.plusDays(7).toEpochDay())
|
fun loadExamsForNextWeek() = loadData(currentDate.plusDays(7).toEpochDay())
|
||||||
|
|
||||||
fun loadData(date: Long?, forceRefresh: Boolean = false) {
|
fun loadData(date: Long?, forceRefresh: Boolean = false) {
|
||||||
this.currentDate = LocalDate.ofEpochDay(date ?: getNearMonday(currentDate).toEpochDay())
|
this.currentDate = LocalDate.ofEpochDay(date ?: currentDate.getWeekFirstDayNextOnWeekEnd().toEpochDay())
|
||||||
if (currentDate.isHolidays()) return
|
if (currentDate.isHolidays()) return
|
||||||
|
|
||||||
disposable.clear()
|
disposable.clear()
|
||||||
disposable.add(sessionRepository.getSemesters()
|
disposable.add(sessionRepository.getSemesters()
|
||||||
.map { selectSemester(it, -1) }
|
.map { selectSemester(it, -1) }
|
||||||
.flatMap { examRepository.getExams(it, currentDate, forceRefresh) }
|
.flatMap { examRepository.getExams(it, currentDate, currentDate.plusDays(4), forceRefresh) }
|
||||||
.map { it.groupBy { exam -> exam.date }.toSortedMap() }
|
.map { it.groupBy { exam -> exam.date }.toSortedMap() }
|
||||||
.map { createExamItems(it) }
|
.map { createExamItems(it) }
|
||||||
.subscribeOn(schedulers.backgroundThread())
|
.subscribeOn(schedulers.backgroundThread())
|
||||||
@ -72,7 +71,7 @@ class ExamPresenter @Inject constructor(
|
|||||||
.subscribe({ view?.updateData(it) }) { errorHandler.proceed(it) })
|
.subscribe({ view?.updateData(it) }) { errorHandler.proceed(it) })
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createExamItems(items: Map<Date, List<Exam>>): List<ExamItem> {
|
private fun createExamItems(items: Map<LocalDate, List<Exam>>): List<ExamItem> {
|
||||||
return items.flatMap {
|
return items.flatMap {
|
||||||
val header = ExamHeader().apply { date = it.key }
|
val header = ExamHeader().apply { date = it.key }
|
||||||
it.value.reversed().map { item ->
|
it.value.reversed().map { item ->
|
||||||
|
@ -1,104 +0,0 @@
|
|||||||
package io.github.wulkanowy.utils
|
|
||||||
|
|
||||||
import org.threeten.bp.DayOfWeek.*
|
|
||||||
import org.threeten.bp.LocalDate
|
|
||||||
import org.threeten.bp.Year
|
|
||||||
import org.threeten.bp.format.DateTimeFormatter
|
|
||||||
import org.threeten.bp.temporal.TemporalAdjuster
|
|
||||||
import org.threeten.bp.temporal.TemporalAdjusters
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
private val formatter = DateTimeFormatter.ofPattern(DATE_PATTERN)
|
|
||||||
|
|
||||||
fun getParsedDate(dateString: String, dateFormat: String): LocalDate {
|
|
||||||
return LocalDate.parse(dateString, DateTimeFormatter.ofPattern(dateFormat))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getMondaysFromCurrentSchoolYear() = getMondaysFromCurrentSchoolYear(LocalDate.now())
|
|
||||||
|
|
||||||
fun getMondaysFromCurrentSchoolYear(date: LocalDate): List<String> {
|
|
||||||
val startDate = getFirstSchoolDay(getSchoolYearForDate(date))
|
|
||||||
?.with(TemporalAdjusters.previousOrSame(MONDAY))
|
|
||||||
val endDate = getFirstSchoolDay(getSchoolYearForDate(date) + 1)
|
|
||||||
?.with(TemporalAdjusters.previousOrSame(MONDAY))
|
|
||||||
|
|
||||||
val dateList = ArrayList<String>()
|
|
||||||
var monday = startDate as LocalDate
|
|
||||||
while (monday.isBefore(endDate)) {
|
|
||||||
dateList.add(monday.format(formatter))
|
|
||||||
monday = monday.plusWeeks(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return dateList
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getSchoolYearForDate(date: LocalDate): Int {
|
|
||||||
return if (date.monthValue <= 8) date.year - 1 else date.year
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getFirstDayOfCurrentWeek(): String = getFirstDayOfCurrentWeek(LocalDate.now())
|
|
||||||
|
|
||||||
fun getFirstDayOfCurrentWeek(date: LocalDate): String {
|
|
||||||
return when (date.dayOfWeek) {
|
|
||||||
SATURDAY -> date.plusDays(2)
|
|
||||||
SUNDAY -> date.plusDays(1)
|
|
||||||
else -> date.with(MONDAY)
|
|
||||||
}.format(formatter)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getTodayOrNextDayOrder(next: Boolean): Int = getTodayOrNextDayOrder(next, LocalDate.now())
|
|
||||||
|
|
||||||
fun getTodayOrNextDayOrder(next: Boolean, date: LocalDate): Int {
|
|
||||||
val day = date.dayOfWeek
|
|
||||||
return if (next) {
|
|
||||||
if (day == SUNDAY) {
|
|
||||||
0
|
|
||||||
} else day.value
|
|
||||||
} else day.value - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getTodayOrNextDay(next: Boolean): String? = getTodayOrNextDay(next, LocalDate.now())
|
|
||||||
|
|
||||||
fun getTodayOrNextDay(next: Boolean, date: LocalDate): String? {
|
|
||||||
return (if (next) {
|
|
||||||
date.plusDays(1)
|
|
||||||
} else date).format(formatter)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isDateInWeek(firstWeekDay: LocalDate, date: LocalDate): Boolean {
|
|
||||||
return date.isAfter(firstWeekDay.minusDays(1)) && date.isBefore(firstWeekDay.plusDays(5))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getNearMonday(date: LocalDate): LocalDate {
|
|
||||||
return when(date.dayOfWeek) {
|
|
||||||
MONDAY -> date
|
|
||||||
SATURDAY, SUNDAY -> date.with(TemporalAdjusters.next(MONDAY))
|
|
||||||
else -> date.with(TemporalAdjusters.previous(MONDAY))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [Dz.U. 2016 poz. 1335](http://prawo.sejm.gov.pl/isap.nsf/DocDetails.xsp?id=WDU20160001335)
|
|
||||||
*/
|
|
||||||
fun isHolidays(): Boolean = isHolidays(LocalDate.now())
|
|
||||||
|
|
||||||
fun isHolidays(day: LocalDate): Boolean {
|
|
||||||
return day.isAfter(getLastSchoolDay(day.year)) && day.isBefore(getFirstSchoolDay(day.year))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getFirstSchoolDay(year: Int): LocalDate {
|
|
||||||
val firstSeptember = LocalDate.of(year, 9, 1)
|
|
||||||
|
|
||||||
return when (firstSeptember.dayOfWeek) {
|
|
||||||
FRIDAY,
|
|
||||||
SATURDAY,
|
|
||||||
SUNDAY -> firstSeptember.with(TemporalAdjusters.firstInMonth(MONDAY))
|
|
||||||
else -> firstSeptember
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getLastSchoolDay(year: Int): LocalDate {
|
|
||||||
return LocalDate
|
|
||||||
.of(year, 6, 20)
|
|
||||||
.with(TemporalAdjusters.next(FRIDAY))
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package io.github.wulkanowy.utils.extension
|
|
||||||
|
|
||||||
import io.github.wulkanowy.utils.DATE_PATTERN
|
|
||||||
import io.github.wulkanowy.utils.isHolidays
|
|
||||||
import org.threeten.bp.Instant
|
|
||||||
import org.threeten.bp.LocalDate
|
|
||||||
import org.threeten.bp.ZoneId
|
|
||||||
import org.threeten.bp.format.DateTimeFormatter
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
private val formatter = DateTimeFormatter.ofPattern(DATE_PATTERN)
|
|
||||||
|
|
||||||
fun LocalDate.toDate(): Date = java.sql.Date.valueOf(this.format(formatter))
|
|
||||||
|
|
||||||
fun LocalDate.toFormat(format: String): String = this.format(DateTimeFormatter.ofPattern(format))
|
|
||||||
|
|
||||||
fun LocalDate.toFormat(): String = this.toFormat(DATE_PATTERN)
|
|
||||||
|
|
||||||
fun LocalDate.isHolidays(): Boolean = isHolidays(this)
|
|
||||||
|
|
||||||
fun Date.toLocalDate(): LocalDate = Instant.ofEpochMilli(this.time).atZone(ZoneId.systemDefault()).toLocalDate()
|
|
||||||
|
|
||||||
fun Date.getWeekDayName(): String = this.toLocalDate().format(DateTimeFormatter.ofPattern("EEEE", Locale.getDefault()))
|
|
||||||
|
|
||||||
fun Date.toFormat(): String = this.toLocalDate().toFormat()
|
|
@ -0,0 +1,79 @@
|
|||||||
|
package io.github.wulkanowy.utils.extension
|
||||||
|
|
||||||
|
import io.github.wulkanowy.utils.DATE_PATTERN
|
||||||
|
import org.threeten.bp.*
|
||||||
|
import org.threeten.bp.format.DateTimeFormatter
|
||||||
|
import org.threeten.bp.temporal.TemporalAdjusters
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
fun Date.toLocalDate(): LocalDate = LocalDate.parse(SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(this))
|
||||||
|
|
||||||
|
fun String.toDate(format: String = "yyyy-MM-dd"): LocalDate = LocalDate.parse(this, DateTimeFormatter.ofPattern(format))
|
||||||
|
|
||||||
|
fun LocalDate.toFormat(format: String): String = this.format(DateTimeFormatter.ofPattern(format))
|
||||||
|
|
||||||
|
fun LocalDate.toFormat(): String = this.toFormat(DATE_PATTERN)
|
||||||
|
|
||||||
|
fun LocalDate.getNextWorkDay(): LocalDate {
|
||||||
|
return when(this.dayOfWeek) {
|
||||||
|
DayOfWeek.FRIDAY, DayOfWeek.SATURDAY, DayOfWeek.SUNDAY -> this.with(TemporalAdjusters.next(DayOfWeek.MONDAY))
|
||||||
|
else -> this.plusDays(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun LocalDate.getPreviousWorkDay(): LocalDate {
|
||||||
|
return when(this.dayOfWeek) {
|
||||||
|
DayOfWeek.SATURDAY, DayOfWeek.SUNDAY, DayOfWeek.MONDAY -> this.with(TemporalAdjusters.previous(DayOfWeek.FRIDAY))
|
||||||
|
else -> this.minusDays(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun LocalDate.getNearSchoolDayPrevOnWeekEnd(): LocalDate {
|
||||||
|
return when(this.dayOfWeek) {
|
||||||
|
DayOfWeek.SATURDAY, DayOfWeek.SUNDAY -> this.with(TemporalAdjusters.previous(DayOfWeek.FRIDAY))
|
||||||
|
else -> this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun LocalDate.getNearSchoolDayNextOnWeekEnd(): LocalDate {
|
||||||
|
return when(this.dayOfWeek) {
|
||||||
|
DayOfWeek.SATURDAY, DayOfWeek.SUNDAY -> this.with(TemporalAdjusters.next(DayOfWeek.MONDAY))
|
||||||
|
else -> this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun LocalDate.getWeekDayName(): String = this.format(DateTimeFormatter.ofPattern("EEEE", Locale.getDefault()))
|
||||||
|
|
||||||
|
fun LocalDate.getWeekFirstDayAlwaysCurrent(): LocalDate {
|
||||||
|
return this.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun LocalDate.getWeekFirstDayNextOnWeekEnd(): LocalDate {
|
||||||
|
return when(this.dayOfWeek) {
|
||||||
|
DayOfWeek.SATURDAY, DayOfWeek.SUNDAY -> this.with(TemporalAdjusters.next(DayOfWeek.MONDAY))
|
||||||
|
else -> this.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [Dz.U. 2016 poz. 1335](http://prawo.sejm.gov.pl/isap.nsf/DocDetails.xsp?id=WDU20160001335)
|
||||||
|
*/
|
||||||
|
fun LocalDate.isHolidays(): Boolean = this.isAfter(this.getLastSchoolDay()) && this.isBefore(this.getFirstSchoolDay())
|
||||||
|
|
||||||
|
fun LocalDate.getSchoolYear(): Int = if (this.monthValue <= 8) this.year - 1 else this.year
|
||||||
|
|
||||||
|
fun LocalDate.getFirstSchoolDay(): LocalDate {
|
||||||
|
return LocalDate.of(this.year, 9, 1).run {
|
||||||
|
when (dayOfWeek) {
|
||||||
|
DayOfWeek.FRIDAY, DayOfWeek.SATURDAY, DayOfWeek.SUNDAY -> with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY))
|
||||||
|
else -> this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun LocalDate.getLastSchoolDay(): LocalDate {
|
||||||
|
return LocalDate
|
||||||
|
.of(this.year, 6, 20)
|
||||||
|
.with(TemporalAdjusters.next(DayOfWeek.FRIDAY))
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
@ -8,146 +7,84 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:minWidth="300dp"
|
android:minWidth="300dp"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical"
|
||||||
|
android:padding="20dp">
|
||||||
<RelativeLayout
|
|
||||||
android:id="@+id/attendance_dialog_relative_layout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:paddingBottom="20dp"
|
|
||||||
android:paddingEnd="20dp"
|
|
||||||
android:paddingLeft="20dp"
|
|
||||||
android:paddingRight="20dp"
|
|
||||||
android:paddingStart="20dp"
|
|
||||||
android:paddingTop="10dp"
|
|
||||||
tools:ignore="UselessParent">
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/attendance_dialog_details"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:layout_alignParentTop="true"
|
|
||||||
android:layout_gravity="start"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:maxLines="5"
|
|
||||||
android:minHeight="60dp"
|
|
||||||
android:minLines="2"
|
|
||||||
android:paddingTop="10dp"
|
|
||||||
android:text="@string/all_details"
|
|
||||||
android:textIsSelectable="true"
|
|
||||||
android:textSize="20sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/attendance_dialog_subject"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:layout_below="@+id/attendance_dialog_details"
|
|
||||||
android:layout_marginTop="10dp"
|
|
||||||
android:text="@string/all_subject"
|
android:text="@string/all_subject"
|
||||||
android:textIsSelectable="true"
|
android:textIsSelectable="true"
|
||||||
android:textSize="17sp" />
|
android:textSize="17sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/attendance_dialog_subject_value"
|
android:id="@+id/attendanceDialogSubject"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:layout_below="@+id/attendance_dialog_subject"
|
|
||||||
android:layout_marginTop="3dp"
|
android:layout_marginTop="3dp"
|
||||||
android:text="@string/all_no_data"
|
android:text="@string/all_no_data"
|
||||||
android:textIsSelectable="true"
|
android:textIsSelectable="true"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/attendance_dialog_description"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:layout_below="@+id/attendance_dialog_subject_value"
|
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:text="@string/all_description"
|
android:text="@string/all_description"
|
||||||
android:textSize="17sp" />
|
android:textSize="17sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/attendance_dialog_description_value"
|
android:id="@+id/attendanceDialogDescription"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:layout_below="@+id/attendance_dialog_description"
|
|
||||||
android:layout_marginTop="3dp"
|
android:layout_marginTop="3dp"
|
||||||
android:text="@string/all_no_data"
|
android:text="@string/all_no_data"
|
||||||
android:textIsSelectable="true"
|
android:textIsSelectable="true"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/attendance_dialog_date"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:layout_below="@+id/attendance_dialog_description_value"
|
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:text="@string/all_date"
|
android:text="@string/all_date"
|
||||||
android:textSize="17sp" />
|
android:textSize="17sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/attendance_dialog_date_value"
|
android:id="@+id/attendanceDialogDate"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:layout_below="@+id/attendance_dialog_date"
|
|
||||||
android:layout_marginTop="3dp"
|
android:layout_marginTop="3dp"
|
||||||
android:text="@string/all_no_data"
|
android:text="@string/all_no_data"
|
||||||
android:textIsSelectable="true"
|
android:textIsSelectable="true"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/attendance_dialog_number"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:layout_below="@+id/attendance_dialog_date_value"
|
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
android:text="@string/attendance_number"
|
android:text="@string/attendance_number"
|
||||||
android:textSize="17sp" />
|
android:textSize="17sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/attendance_dialog_number_value"
|
android:id="@+id/attendanceDialogNumber"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:layout_below="@+id/attendance_dialog_number"
|
|
||||||
android:layout_marginTop="3dp"
|
android:layout_marginTop="3dp"
|
||||||
android:text="@string/all_no_data"
|
android:text="@string/all_no_data"
|
||||||
android:textIsSelectable="true"
|
android:textIsSelectable="true"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/attendance_dialog_close"
|
android:id="@+id/attendanceDialogClose"
|
||||||
|
style="@style/Widget.AppCompat.Button.Borderless"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_gravity="end"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_marginTop="15dp"
|
||||||
android:layout_alignParentRight="true"
|
android:padding="0dp"
|
||||||
android:layout_alignTop="@+id/attendance_dialog_number_value"
|
|
||||||
android:layout_marginTop="25dp"
|
|
||||||
android:background="?attr/selectableItemBackground"
|
|
||||||
android:focusable="true"
|
|
||||||
android:text="@string/all_close"
|
android:text="@string/all_close"
|
||||||
android:textAllCaps="true"
|
android:textAllCaps="true"
|
||||||
android:textColor="?android:attr/android:textColorSecondary"
|
|
||||||
android:textSize="15sp" />
|
android:textSize="15sp" />
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
@ -1,30 +1,99 @@
|
|||||||
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:id="@+id/attendanceContainer"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_alignParentBottom="true">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<TextView
|
<FrameLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="0dp"
|
||||||
android:gravity="center"
|
android:layout_weight="1"
|
||||||
android:text="Attendance" />
|
android:orientation="vertical">
|
||||||
|
|
||||||
<!--<RelativeLayout
|
<ProgressBar
|
||||||
|
android:id="@+id/attendanceProgress"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:indeterminate="true" />
|
||||||
|
|
||||||
|
<android.support.v4.widget.SwipeRefreshLayout
|
||||||
|
android:id="@+id/attendanceSwipe"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<android.support.design.widget.TabLayout
|
<android.support.v7.widget.RecyclerView
|
||||||
android:id="@+id/attendance_fragment_tab_layout"
|
android:id="@+id/attendanceRecycler"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent" />
|
||||||
app:tabMinWidth="125dp"
|
|
||||||
app:tabMode="scrollable"/>
|
|
||||||
|
|
||||||
<android.support.v4.view.ViewPager
|
</android.support.v4.widget.SwipeRefreshLayout>
|
||||||
android:id="@+id/attendance_fragment_viewpager"
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/attendanceEmpty"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_below="@id/attendance_fragment_tab_layout" />
|
android:gravity="center"
|
||||||
</RelativeLayout>-->
|
android:orientation="vertical"
|
||||||
</android.support.design.widget.CoordinatorLayout>
|
android:padding="10dp"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<android.support.v7.widget.AppCompatImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:minHeight="100dp"
|
||||||
|
android:minWidth="100dp"
|
||||||
|
app:srcCompat="@drawable/ic_menu_main_attendance_24dp"
|
||||||
|
app:tint="?android:attr/textColorPrimary"
|
||||||
|
tools:ignore="contentDescription" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/attendance_no_items"
|
||||||
|
android:textSize="20sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/attendancePreviousButton"
|
||||||
|
style="@style/Widget.AppCompat.Button.Borderless"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:drawablePadding="4dp"
|
||||||
|
android:gravity="start|center"
|
||||||
|
android:text="@string/prev"
|
||||||
|
android:textAlignment="gravity" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/attendanceNavDate"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/app_name" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/attendanceNextButton"
|
||||||
|
style="@style/Widget.AppCompat.Button.Borderless"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="end"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:drawablePadding="4dp"
|
||||||
|
android:gravity="end|center"
|
||||||
|
android:text="@string/next"
|
||||||
|
android:textAlignment="gravity" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
@ -1,30 +1,19 @@
|
|||||||
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tool="http://schemas.android.com/tools"
|
xmlns:tool="http://schemas.android.com/tools"
|
||||||
android:id="@+id/attendance_subItem_cardView"
|
android:id="@+id/attendanceItemContainer"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="7dp"
|
|
||||||
android:layout_marginEnd="5dp"
|
|
||||||
android:layout_marginLeft="5dp"
|
|
||||||
android:layout_marginRight="5dp"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:foreground="?attr/selectableItemBackgroundBorderless"
|
android:foreground="?attr/selectableItemBackgroundBorderless"
|
||||||
card_view:cardElevation="0dp">
|
android:paddingStart="12dp"
|
||||||
|
android:paddingLeft="12dp"
|
||||||
<RelativeLayout
|
android:paddingTop="7dp"
|
||||||
android:layout_width="match_parent"
|
android:paddingEnd="12dp"
|
||||||
android:layout_height="wrap_content"
|
android:paddingRight="12dp"
|
||||||
android:layout_marginBottom="7dp"
|
android:paddingBottom="7dp">
|
||||||
android:layout_marginEnd="7dp"
|
|
||||||
android:layout_marginLeft="7dp"
|
|
||||||
android:layout_marginRight="7dp"
|
|
||||||
android:layout_marginStart="7dp"
|
|
||||||
android:layout_marginTop="7dp">
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/attendance_subItem_number"
|
android:id="@+id/attendanceItemNumber"
|
||||||
android:layout_width="40dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
@ -35,16 +24,16 @@
|
|||||||
tool:ignore="all" />
|
tool:ignore="all" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/attendance_subItem_lesson"
|
android:id="@+id/attendanceItemSubject"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_marginEnd="40dp"
|
|
||||||
android:layout_marginLeft="10dp"
|
|
||||||
android:layout_marginRight="40dp"
|
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
android:layout_toEndOf="@+id/attendance_subItem_number"
|
android:layout_marginLeft="10dp"
|
||||||
android:layout_toRightOf="@+id/attendance_subItem_number"
|
android:layout_marginEnd="40dp"
|
||||||
|
android:layout_marginRight="40dp"
|
||||||
|
android:layout_toEndOf="@+id/attendanceItemNumber"
|
||||||
|
android:layout_toRightOf="@+id/attendanceItemNumber"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:text="@string/app_name"
|
android:text="@string/app_name"
|
||||||
@ -52,19 +41,19 @@
|
|||||||
tool:ignore="all" />
|
tool:ignore="all" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/attendance_subItem_description"
|
android:id="@+id/attendanceItemDescription"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignBottom="@+id/attendance_subItem_number"
|
android:layout_alignStart="@id/attendanceItemSubject"
|
||||||
android:layout_alignLeft="@id/attendance_subItem_lesson"
|
android:layout_alignLeft="@id/attendanceItemSubject"
|
||||||
android:layout_alignStart="@id/attendance_subItem_lesson"
|
android:layout_alignBottom="@+id/attendanceItemNumber"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:text="@string/app_name"
|
android:text="@string/app_name"
|
||||||
android:textColor="?android:attr/android:textColorSecondary"
|
android:textColor="?android:attr/android:textColorSecondary"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/attendance_subItem_alert_image"
|
android:id="@+id/attendanceItemAlert"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
@ -73,5 +62,4 @@
|
|||||||
app:srcCompat="@drawable/ic_all_note_24dp"
|
app:srcCompat="@drawable/ic_all_note_24dp"
|
||||||
tool:ignore="contentDescription" />
|
tool:ignore="contentDescription" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
</android.support.v7.widget.CardView>
|
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
package io.github.wulkanowy.data.repositories.remote
|
||||||
|
|
||||||
|
import io.github.wulkanowy.api.Api
|
||||||
|
import io.github.wulkanowy.api.attendance.Attendance
|
||||||
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import io.mockk.MockKAnnotations
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.impl.annotations.MockK
|
||||||
|
import io.reactivex.Single
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.threeten.bp.LocalDate
|
||||||
|
import java.sql.Date
|
||||||
|
|
||||||
|
class AttendanceRemoteTest {
|
||||||
|
|
||||||
|
@MockK
|
||||||
|
private lateinit var mockApi: Api
|
||||||
|
|
||||||
|
@MockK
|
||||||
|
private lateinit var semesterMock: Semester
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun initApi() {
|
||||||
|
MockKAnnotations.init(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getExamsTest() {
|
||||||
|
every { mockApi.getAttendance(
|
||||||
|
LocalDate.of(2018, 9, 10),
|
||||||
|
LocalDate.of(2018, 9, 15)
|
||||||
|
) } returns Single.just(listOf(
|
||||||
|
getAttendance("2018-09-10"),
|
||||||
|
getAttendance("2018-09-17")
|
||||||
|
))
|
||||||
|
|
||||||
|
every { mockApi.diaryId } returns "1"
|
||||||
|
every { semesterMock.studentId } returns "1"
|
||||||
|
every { semesterMock.diaryId } returns "1"
|
||||||
|
|
||||||
|
val attendance = AttendanceRemote(mockApi).getAttendance(semesterMock,
|
||||||
|
LocalDate.of(2018, 9, 10),
|
||||||
|
LocalDate.of(2018, 9, 15)).blockingGet()
|
||||||
|
assertEquals(2, attendance.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getAttendance(dateString: String): Attendance {
|
||||||
|
return Attendance().apply {
|
||||||
|
subject = "Fizyka"
|
||||||
|
name = "Obecność"
|
||||||
|
date = Date.valueOf(dateString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,41 +3,47 @@ package io.github.wulkanowy.data.repositories.remote
|
|||||||
import io.github.wulkanowy.api.Api
|
import io.github.wulkanowy.api.Api
|
||||||
import io.github.wulkanowy.api.exams.Exam
|
import io.github.wulkanowy.api.exams.Exam
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
|
import io.mockk.MockKAnnotations
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.impl.annotations.MockK
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.mockito.ArgumentMatchers.any
|
|
||||||
import org.mockito.Mock
|
|
||||||
import org.mockito.Mockito.doReturn
|
|
||||||
import org.mockito.MockitoAnnotations
|
|
||||||
import org.threeten.bp.LocalDate
|
import org.threeten.bp.LocalDate
|
||||||
import java.sql.Date
|
import java.sql.Date
|
||||||
|
|
||||||
class ExamRemoteTest {
|
class ExamRemoteTest {
|
||||||
|
|
||||||
@Mock
|
@MockK
|
||||||
private lateinit var mockApi: Api
|
private lateinit var mockApi: Api
|
||||||
|
|
||||||
@Mock
|
@MockK
|
||||||
private lateinit var semesterMock: Semester
|
private lateinit var semesterMock: Semester
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun initApi() {
|
fun initApi() {
|
||||||
MockitoAnnotations.initMocks(this)
|
MockKAnnotations.init(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun getExamsTest() {
|
fun getExamsTest() {
|
||||||
doReturn(Single.just(listOf(
|
every { mockApi.getExams(
|
||||||
|
LocalDate.of(2018, 9, 10),
|
||||||
|
LocalDate.of(2018, 9, 15)
|
||||||
|
) } returns Single.just(listOf(
|
||||||
getExam("2018-09-10"),
|
getExam("2018-09-10"),
|
||||||
getExam("2018-09-17")
|
getExam("2018-09-17")
|
||||||
))).`when`(mockApi).getExams(any())
|
))
|
||||||
|
|
||||||
doReturn("1").`when`(semesterMock).studentId
|
every { mockApi.diaryId } returns "1"
|
||||||
doReturn("1").`when`(semesterMock).diaryId
|
every { semesterMock.studentId } returns "1"
|
||||||
|
every { semesterMock.diaryId } returns "1"
|
||||||
|
|
||||||
val exams = ExamRemote(mockApi).getExams(semesterMock, LocalDate.of(2018, 9, 10)).blockingGet()
|
val exams = ExamRemote(mockApi).getExams(semesterMock,
|
||||||
|
LocalDate.of(2018, 9, 10),
|
||||||
|
LocalDate.of(2018, 9, 15)
|
||||||
|
).blockingGet()
|
||||||
assertEquals(2, exams.size)
|
assertEquals(2, exams.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,140 +0,0 @@
|
|||||||
package io.github.wulkanowy.utils
|
|
||||||
|
|
||||||
import org.junit.Test
|
|
||||||
import org.threeten.bp.LocalDate
|
|
||||||
|
|
||||||
import org.junit.Assert.assertEquals
|
|
||||||
import org.junit.Assert.assertFalse
|
|
||||||
import org.junit.Assert.assertTrue
|
|
||||||
|
|
||||||
class TimeUtilsTest {
|
|
||||||
|
|
||||||
@Test fun getParsedDateTest() {
|
|
||||||
assertEquals(LocalDate.of(1970, 1, 1),
|
|
||||||
getParsedDate("1970-01-01", "yyyy-MM-dd"))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test fun getMondaysFromCurrentSchoolYearTest() {
|
|
||||||
val y201718 = getMondaysFromCurrentSchoolYear(LocalDate.of(2018, 1, 1))
|
|
||||||
assertEquals("2017-09-04", y201718.first())
|
|
||||||
assertEquals("2018-08-27", y201718.last())
|
|
||||||
|
|
||||||
val y202122 = getMondaysFromCurrentSchoolYear(LocalDate.of(2022, 1, 1))
|
|
||||||
assertEquals("2021-08-30", y202122.first())
|
|
||||||
assertEquals("2022-08-22", y202122.last())
|
|
||||||
|
|
||||||
val y202223 = getMondaysFromCurrentSchoolYear(LocalDate.of(2023, 1, 1))
|
|
||||||
assertEquals("2022-08-29", y202223.first())
|
|
||||||
assertEquals("2023-08-28", y202223.last())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test fun getCurrentSchoolYearTest() {
|
|
||||||
assertEquals(2017, getSchoolYearForDate(LocalDate.of(2018, 8, 31)))
|
|
||||||
assertEquals(2018, getSchoolYearForDate(LocalDate.of(2018, 9, 1)))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test fun getFirstWeekDayTest() {
|
|
||||||
assertEquals("2018-06-18", getFirstDayOfCurrentWeek(LocalDate.of(2018, 6, 21)))
|
|
||||||
assertEquals("2018-06-18", getFirstDayOfCurrentWeek(LocalDate.of(2018, 6, 22)))
|
|
||||||
assertEquals("2018-06-25", getFirstDayOfCurrentWeek(LocalDate.of(2018, 6, 23)))
|
|
||||||
assertEquals("2018-06-25", getFirstDayOfCurrentWeek(LocalDate.of(2018, 6, 24)))
|
|
||||||
assertEquals("2018-06-25", getFirstDayOfCurrentWeek(LocalDate.of(2018, 6, 25)))
|
|
||||||
assertEquals("2018-06-25", getFirstDayOfCurrentWeek(LocalDate.of(2018, 6, 26)))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test fun getTodayOrNextDayOrderTest() {
|
|
||||||
assertEquals(0, getTodayOrNextDayOrder(true, LocalDate.of(2018, 6, 24))) // sunday
|
|
||||||
assertEquals(6, getTodayOrNextDayOrder(false, LocalDate.of(2018, 6, 24)))
|
|
||||||
assertEquals(1, getTodayOrNextDayOrder(true, LocalDate.of(2018, 6, 25)))
|
|
||||||
assertEquals(0, getTodayOrNextDayOrder(false, LocalDate.of(2018, 6, 25)))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test fun getTodayOrNextDayTest() {
|
|
||||||
assertEquals("2018-06-26", getTodayOrNextDay(false, LocalDate.of(2018, 6, 26)))
|
|
||||||
assertEquals("2018-06-27", getTodayOrNextDay(true, LocalDate.of(2018, 6, 26)))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test fun isDateInWeekInsideTest() {
|
|
||||||
assertTrue(isDateInWeek(
|
|
||||||
LocalDate.of(2018, 5, 28),
|
|
||||||
LocalDate.of(2018, 5, 31)
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test fun isDateInWeekExtremesTest() {
|
|
||||||
assertTrue(isDateInWeek(
|
|
||||||
LocalDate.of(2018, 5, 28),
|
|
||||||
LocalDate.of(2018, 5, 28)
|
|
||||||
))
|
|
||||||
|
|
||||||
assertTrue(isDateInWeek(
|
|
||||||
LocalDate.of(2018, 5, 28),
|
|
||||||
LocalDate.of(2018, 6, 1)
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test fun isDateInWeekOutOfTest() {
|
|
||||||
assertFalse(isDateInWeek(
|
|
||||||
LocalDate.of(2018, 5, 28),
|
|
||||||
LocalDate.of(2018, 6, 2)
|
|
||||||
))
|
|
||||||
|
|
||||||
assertFalse(isDateInWeek(
|
|
||||||
LocalDate.of(2018, 5, 28),
|
|
||||||
LocalDate.of(2018, 5, 27)
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test fun isHolidaysInSchoolEndTest() {
|
|
||||||
assertFalse(isHolidays(LocalDate.of(2017, 6, 23)))
|
|
||||||
assertFalse(isHolidays(LocalDate.of(2018, 6, 22)))
|
|
||||||
assertFalse(isHolidays(LocalDate.of(2019, 6, 21)))
|
|
||||||
assertFalse(isHolidays(LocalDate.of(2020, 6, 26)))
|
|
||||||
assertFalse(isHolidays(LocalDate.of(2021, 6, 25)))
|
|
||||||
assertFalse(isHolidays(LocalDate.of(2022, 6, 24)))
|
|
||||||
assertFalse(isHolidays(LocalDate.of(2023, 6, 23)))
|
|
||||||
assertFalse(isHolidays(LocalDate.of(2024, 6, 21)))
|
|
||||||
assertFalse(isHolidays(LocalDate.of(2025, 6, 27)))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test fun isHolidaysInHolidaysStartTest() {
|
|
||||||
assertTrue(isHolidays(LocalDate.of(2017, 6, 24)))
|
|
||||||
assertTrue(isHolidays(LocalDate.of(2018, 6, 23)))
|
|
||||||
assertTrue(isHolidays(LocalDate.of(2019, 6, 22)))
|
|
||||||
assertTrue(isHolidays(LocalDate.of(2020, 6, 27)))
|
|
||||||
assertTrue(isHolidays(LocalDate.of(2021, 6, 26)))
|
|
||||||
assertTrue(isHolidays(LocalDate.of(2022, 6, 25)))
|
|
||||||
assertTrue(isHolidays(LocalDate.of(2023, 6, 24)))
|
|
||||||
assertTrue(isHolidays(LocalDate.of(2024, 6, 22)))
|
|
||||||
assertTrue(isHolidays(LocalDate.of(2025, 6, 28)))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test fun isHolidaysInHolidaysEndTest() {
|
|
||||||
assertTrue(isHolidays(LocalDate.of(2017, 9, 1))) // friday
|
|
||||||
assertTrue(isHolidays(LocalDate.of(2017, 9, 2))) // saturday
|
|
||||||
assertTrue(isHolidays(LocalDate.of(2017, 9, 3))) // sunday
|
|
||||||
assertTrue(isHolidays(LocalDate.of(2018, 9, 1))) // saturday
|
|
||||||
assertTrue(isHolidays(LocalDate.of(2018, 9, 2))) // sunday
|
|
||||||
assertTrue(isHolidays(LocalDate.of(2019, 9, 1))) // sunday
|
|
||||||
assertTrue(isHolidays(LocalDate.of(2020, 8, 31))) // monday
|
|
||||||
assertTrue(isHolidays(LocalDate.of(2021, 8, 31))) // tuesday
|
|
||||||
assertTrue(isHolidays(LocalDate.of(2022, 8, 31))) // wednesday
|
|
||||||
assertTrue(isHolidays(LocalDate.of(2023, 9, 1))) // friday
|
|
||||||
assertTrue(isHolidays(LocalDate.of(2023, 9, 2))) // saturday
|
|
||||||
assertTrue(isHolidays(LocalDate.of(2023, 9, 3))) // sunday
|
|
||||||
assertTrue(isHolidays(LocalDate.of(2024, 9, 1))) // sunday
|
|
||||||
assertTrue(isHolidays(LocalDate.of(2025, 8, 31))) // sunday
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test fun isHolidaysInSchoolStartTest() {
|
|
||||||
assertFalse(isHolidays(LocalDate.of(2017, 9, 4))) // monday
|
|
||||||
assertFalse(isHolidays(LocalDate.of(2018, 9, 3))) // monday
|
|
||||||
assertFalse(isHolidays(LocalDate.of(2019, 9, 2))) // monday
|
|
||||||
assertFalse(isHolidays(LocalDate.of(2020, 9, 1))) // tuesday
|
|
||||||
assertFalse(isHolidays(LocalDate.of(2021, 9, 1))) // wednesday
|
|
||||||
assertFalse(isHolidays(LocalDate.of(2022, 9, 1))) // thursday
|
|
||||||
assertFalse(isHolidays(LocalDate.of(2023, 9, 4))) // monday
|
|
||||||
assertFalse(isHolidays(LocalDate.of(2024, 9, 2))) // monday
|
|
||||||
assertFalse(isHolidays(LocalDate.of(2025, 9, 1))) // monday
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,150 @@
|
|||||||
|
package io.github.wulkanowy.utils.extension
|
||||||
|
|
||||||
|
import org.junit.Assert.*
|
||||||
|
import org.junit.Test
|
||||||
|
import org.threeten.bp.LocalDate
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class TimeExtensionTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun toDate() {
|
||||||
|
assertEquals(LocalDate.of(1970, 1, 1), "1970-01-01".toDate("yyyy-MM-dd"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun toFormat() {
|
||||||
|
assertEquals("2018-10-01", LocalDate.of(2018, 10, 1).toFormat())
|
||||||
|
assertEquals("2018-10.01", LocalDate.of(2018, 10, 1).toFormat("yyyy-MM.dd"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getWeekFirstDayAlwaysCurrent() {
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 1), LocalDate.of(2018, 10, 2).getWeekFirstDayAlwaysCurrent())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 1), LocalDate.of(2018, 10, 5).getWeekFirstDayAlwaysCurrent())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 1), LocalDate.of(2018, 10, 6).getWeekFirstDayAlwaysCurrent())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 1), LocalDate.of(2018, 10, 7).getWeekFirstDayAlwaysCurrent())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 8), LocalDate.of(2018, 10, 8).getWeekFirstDayAlwaysCurrent())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getWeekFirstDayNextOnWeekEnd() {
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 1), LocalDate.of(2018, 10, 2).getWeekFirstDayNextOnWeekEnd())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 1), LocalDate.of(2018, 10, 5).getWeekFirstDayNextOnWeekEnd())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 8), LocalDate.of(2018, 10, 6).getWeekFirstDayNextOnWeekEnd())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 8), LocalDate.of(2018, 10, 7).getWeekFirstDayNextOnWeekEnd())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 8), LocalDate.of(2018, 10, 8).getWeekFirstDayNextOnWeekEnd())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getWeekDayName() {
|
||||||
|
Locale.setDefault(Locale.forLanguageTag("PL"))
|
||||||
|
assertEquals("poniedziałek", LocalDate.of(2018, 10, 1).getWeekDayName())
|
||||||
|
Locale.setDefault(Locale.forLanguageTag("US"))
|
||||||
|
assertEquals("Monday", LocalDate.of(2018, 10, 1).getWeekDayName())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getSchoolYear() {
|
||||||
|
assertEquals(2017, LocalDate.of(2018, 8, 31).getSchoolYear())
|
||||||
|
assertEquals(2018, LocalDate.of(2018, 9, 1).getSchoolYear())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getNextSchoolDay() {
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 2), LocalDate.of(2018, 10, 1).getNextWorkDay())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 3), LocalDate.of(2018, 10, 2).getNextWorkDay())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 4), LocalDate.of(2018, 10, 3).getNextWorkDay())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 5), LocalDate.of(2018, 10, 4).getNextWorkDay())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 8), LocalDate.of(2018, 10, 5).getNextWorkDay())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 8), LocalDate.of(2018, 10, 6).getNextWorkDay())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 8), LocalDate.of(2018, 10, 7).getNextWorkDay())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 9), LocalDate.of(2018, 10, 8).getNextWorkDay())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getPreviousSchoolDay() {
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 9), LocalDate.of(2018, 10, 10).getPreviousWorkDay())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 8), LocalDate.of(2018, 10, 9).getPreviousWorkDay())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 5), LocalDate.of(2018, 10, 8).getPreviousWorkDay())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 5), LocalDate.of(2018, 10, 7).getPreviousWorkDay())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 5), LocalDate.of(2018, 10, 6).getPreviousWorkDay())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 4), LocalDate.of(2018, 10, 5).getPreviousWorkDay())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 3), LocalDate.of(2018, 10, 4).getPreviousWorkDay())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getNearSchoolDayPrevOnWeekEnd() {
|
||||||
|
assertEquals(LocalDate.of(2018, 9, 28), LocalDate.of(2018, 9, 28).getNearSchoolDayPrevOnWeekEnd())
|
||||||
|
assertEquals(LocalDate.of(2018, 9, 28), LocalDate.of(2018, 9, 29).getNearSchoolDayPrevOnWeekEnd())
|
||||||
|
assertEquals(LocalDate.of(2018, 9, 28), LocalDate.of(2018, 9, 30).getNearSchoolDayPrevOnWeekEnd())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 1), LocalDate.of(2018, 10, 1).getNearSchoolDayPrevOnWeekEnd())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 2), LocalDate.of(2018, 10, 2).getNearSchoolDayPrevOnWeekEnd())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getNearSchoolDayNextOnWeekEnd() {
|
||||||
|
assertEquals(LocalDate.of(2018, 9, 28), LocalDate.of(2018, 9, 28).getNearSchoolDayNextOnWeekEnd())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 1), LocalDate.of(2018, 9, 29).getNearSchoolDayNextOnWeekEnd())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 1), LocalDate.of(2018, 9, 30).getNearSchoolDayNextOnWeekEnd())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 1), LocalDate.of(2018, 10, 1).getNearSchoolDayNextOnWeekEnd())
|
||||||
|
assertEquals(LocalDate.of(2018, 10, 2), LocalDate.of(2018, 10, 2).getNearSchoolDayNextOnWeekEnd())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isHolidays_schoolEnd() {
|
||||||
|
assertFalse(LocalDate.of(2017, 6, 23).isHolidays())
|
||||||
|
assertFalse(LocalDate.of(2018, 6, 22).isHolidays())
|
||||||
|
assertFalse(LocalDate.of(2019, 6, 21).isHolidays())
|
||||||
|
assertFalse(LocalDate.of(2020, 6, 26).isHolidays())
|
||||||
|
assertFalse(LocalDate.of(2021, 6, 25).isHolidays())
|
||||||
|
assertFalse(LocalDate.of(2022, 6, 24).isHolidays())
|
||||||
|
assertFalse(LocalDate.of(2023, 6, 23).isHolidays())
|
||||||
|
assertFalse(LocalDate.of(2024, 6, 21).isHolidays())
|
||||||
|
assertFalse(LocalDate.of(2025, 6, 27).isHolidays())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isHolidays_holidaysStart() {
|
||||||
|
assertTrue(LocalDate.of(2017, 6, 24).isHolidays())
|
||||||
|
assertTrue(LocalDate.of(2018, 6, 23).isHolidays())
|
||||||
|
assertTrue(LocalDate.of(2019, 6, 22).isHolidays())
|
||||||
|
assertTrue(LocalDate.of(2020, 6, 27).isHolidays())
|
||||||
|
assertTrue(LocalDate.of(2021, 6, 26).isHolidays())
|
||||||
|
assertTrue(LocalDate.of(2022, 6, 25).isHolidays())
|
||||||
|
assertTrue(LocalDate.of(2023, 6, 24).isHolidays())
|
||||||
|
assertTrue(LocalDate.of(2024, 6, 22).isHolidays())
|
||||||
|
assertTrue(LocalDate.of(2025, 6, 28).isHolidays())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isHolidays_holidaysEnd() {
|
||||||
|
assertTrue(LocalDate.of(2017, 9, 1).isHolidays()) // friday
|
||||||
|
assertTrue(LocalDate.of(2017, 9, 2).isHolidays()) // saturday
|
||||||
|
assertTrue(LocalDate.of(2017, 9, 3).isHolidays()) // sunday
|
||||||
|
assertTrue(LocalDate.of(2018, 9, 1).isHolidays()) // saturday
|
||||||
|
assertTrue(LocalDate.of(2018, 9, 2).isHolidays()) // sunday
|
||||||
|
assertTrue(LocalDate.of(2019, 9, 1).isHolidays()) // sunday
|
||||||
|
assertTrue(LocalDate.of(2020, 8, 31).isHolidays()) // monday
|
||||||
|
assertTrue(LocalDate.of(2021, 8, 31).isHolidays()) // tuesday
|
||||||
|
assertTrue(LocalDate.of(2022, 8, 31).isHolidays()) // wednesday
|
||||||
|
assertTrue(LocalDate.of(2023, 9, 1).isHolidays()) // friday
|
||||||
|
assertTrue(LocalDate.of(2023, 9, 2).isHolidays()) // saturday
|
||||||
|
assertTrue(LocalDate.of(2023, 9, 3).isHolidays()) // sunday
|
||||||
|
assertTrue(LocalDate.of(2024, 9, 1).isHolidays()) // sunday
|
||||||
|
assertTrue(LocalDate.of(2025, 8, 31).isHolidays()) // sunday
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isHolidays_schoolStart() {
|
||||||
|
assertFalse(LocalDate.of(2017, 9, 4).isHolidays()) // monday
|
||||||
|
assertFalse(LocalDate.of(2018, 9, 3).isHolidays()) // monday
|
||||||
|
assertFalse(LocalDate.of(2019, 9, 2).isHolidays()) // monday
|
||||||
|
assertFalse(LocalDate.of(2020, 9, 1).isHolidays()) // tuesday
|
||||||
|
assertFalse(LocalDate.of(2021, 9, 1).isHolidays()) // wednesday
|
||||||
|
assertFalse(LocalDate.of(2022, 9, 1).isHolidays()) // thursday
|
||||||
|
assertFalse(LocalDate.of(2023, 9, 4).isHolidays()) // monday
|
||||||
|
assertFalse(LocalDate.of(2024, 9, 2).isHolidays()) // monday
|
||||||
|
assertFalse(LocalDate.of(2025, 9, 1).isHolidays()) // monday
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,7 @@ buildscript {
|
|||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
classpath 'com.android.tools.build:gradle:3.1.4'
|
classpath 'com.android.tools.build:gradle:3.2.0'
|
||||||
classpath "io.fabric.tools:gradle:1.25.4"
|
classpath "io.fabric.tools:gradle:1.25.4"
|
||||||
classpath "com.google.gms:oss-licenses:0.9.2"
|
classpath "com.google.gms:oss-licenses:0.9.2"
|
||||||
classpath "com.github.triplet.gradle:play-publisher:1.2.2"
|
classpath "com.github.triplet.gradle:play-publisher:1.2.2"
|
||||||
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
|||||||
#Tue Mar 27 02:10:44 CEST 2018
|
#Sat Sep 29 23:00:14 CEST 2018
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
|
||||||
|
Loading…
x
Reference in New Issue
Block a user