forked from github/wulkanowy-mirror
Refactor exam module (#157)
This commit is contained in:
parent
b617957891
commit
a1f64baca4
@ -8,8 +8,8 @@ apply from: 'sonarqube.gradle'
|
||||
apply plugin: 'com.github.triplet.play'
|
||||
|
||||
android {
|
||||
compileSdkVersion 27
|
||||
buildToolsVersion '27.0.3'
|
||||
compileSdkVersion 28
|
||||
buildToolsVersion '28.0.2'
|
||||
|
||||
playAccountConfigs {
|
||||
defaultAccountConfig {
|
||||
@ -22,7 +22,7 @@ android {
|
||||
applicationId "io.github.wulkanowy"
|
||||
testApplicationId "io.github.tests.wulkanowy"
|
||||
minSdkVersion 15
|
||||
targetSdkVersion 27
|
||||
targetSdkVersion 28
|
||||
versionCode 16
|
||||
versionName "0.5.2"
|
||||
multiDexEnabled true
|
||||
@ -68,11 +68,11 @@ play {
|
||||
uploadImages = true
|
||||
}
|
||||
|
||||
ext.supportVersion = "27.1.1"
|
||||
ext.supportVersion = "28.0.0-rc02"
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||
implementation 'com.github.wulkanowy:api:88ede83149'
|
||||
implementation 'com.github.wulkanowy:api:ad57669'
|
||||
|
||||
implementation "com.android.support:support-v4:$supportVersion"
|
||||
implementation "com.android.support:design:$supportVersion"
|
||||
@ -98,7 +98,7 @@ dependencies {
|
||||
|
||||
implementation 'com.github.pwittchen:reactivenetwork-rx2:2.1.0'
|
||||
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
|
||||
implementation "io.reactivex.rxjava2:rxjava:2.2.0"
|
||||
implementation "io.reactivex.rxjava2:rxjava:2.2.1"
|
||||
|
||||
implementation "org.apache.commons:commons-lang3:3.8"
|
||||
implementation "org.apache.commons:commons-collections4:4.2"
|
||||
|
@ -0,0 +1,50 @@
|
||||
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.Exam
|
||||
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 java.sql.Date
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExamLocalTest {
|
||||
|
||||
private lateinit var examLocal: ExamLocal
|
||||
|
||||
private lateinit var testDb: AppDatabase
|
||||
|
||||
@Before
|
||||
fun createDb() {
|
||||
testDb = Room.inMemoryDatabaseBuilder(InstrumentationRegistry.getContext(), AppDatabase::class.java).build()
|
||||
examLocal = ExamLocal(testDb.examsDao())
|
||||
}
|
||||
|
||||
@After
|
||||
fun closeDb() {
|
||||
testDb.close()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun saveAndReadTest() {
|
||||
examLocal.saveExams(listOf(
|
||||
Exam(studentId = "1", diaryId = "2", date = Date.valueOf("2018-09-10")),
|
||||
Exam(studentId = "1", diaryId = "2", date = Date.valueOf("2018-09-14")),
|
||||
Exam(studentId = "1", diaryId = "2", date = Date.valueOf("2018-09-17")) // in next week
|
||||
))
|
||||
|
||||
val exams = examLocal
|
||||
.getExams(Semester(studentId = "1", diaryId = "2", semesterId = "3"), LocalDate.of(2018, 9, 10))
|
||||
.blockingGet()
|
||||
assertEquals(2, exams.size)
|
||||
assertEquals(exams[0].date, Date.valueOf("2018-09-10"))
|
||||
assertEquals(exams[1].date, Date.valueOf("2018-09-14"))
|
||||
}
|
||||
}
|
@ -14,9 +14,9 @@ import org.junit.runner.RunWith
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class StudentLocalTest {
|
||||
class SessionLocalTest {
|
||||
|
||||
private lateinit var studentLocal: StudentLocal
|
||||
private lateinit var studentLocal: SessionLocal
|
||||
|
||||
private lateinit var testDb: AppDatabase
|
||||
|
||||
@ -28,7 +28,7 @@ class StudentLocalTest {
|
||||
testDb = Room.inMemoryDatabaseBuilder(context, AppDatabase::class.java)
|
||||
.build()
|
||||
sharedHelper = SharedPrefHelper(context.getSharedPreferences("TEST", Context.MODE_PRIVATE))
|
||||
studentLocal = StudentLocal(testDb.studentDao(), sharedHelper, context)
|
||||
studentLocal = SessionLocal(testDb.studentDao(), testDb.semesterDao(), sharedHelper, context)
|
||||
}
|
||||
|
||||
@After
|
||||
@ -38,12 +38,12 @@ class StudentLocalTest {
|
||||
|
||||
@Test
|
||||
fun saveAndReadTest() {
|
||||
studentLocal.save(Student(email = "test", password = "test123", schoolId = "23")).blockingAwait()
|
||||
assert(sharedHelper.getLong(StudentLocal.CURRENT_USER_KEY, 0) == 1L)
|
||||
studentLocal.saveStudent(Student(email = "test", password = "test123", schoolId = "23")).blockingAwait()
|
||||
assert(sharedHelper.getLong(SessionLocal.LAST_USER_KEY, 0) == 1L)
|
||||
|
||||
assert(studentLocal.isStudentLoggedIn)
|
||||
assert(studentLocal.isSessionSaved)
|
||||
|
||||
val student = studentLocal.getCurrentStudent().blockingGet()
|
||||
val student = studentLocal.getLastStudent().blockingGet()
|
||||
assertEquals("23", student.schoolId)
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="io.github.wulkanowy"
|
||||
android:installLocation="internalOnly">
|
||||
|
||||
@ -13,7 +14,9 @@
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:theme="@style/WulkanowyTheme">
|
||||
android:theme="@style/WulkanowyTheme"
|
||||
android:usesCleartextTraffic="true"
|
||||
tools:targetApi="m">
|
||||
<activity
|
||||
android:name=".ui.splash.SplashActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
|
@ -32,6 +32,9 @@ internal class RepositoryModule {
|
||||
.build()
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun provideErrorHandler(context: Context) = ErrorHandler(context.resources)
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideSharedPref(context: Context): SharedPreferences {
|
||||
@ -41,4 +44,12 @@ internal class RepositoryModule {
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideStudentDao(database: AppDatabase) = database.studentDao()
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideSemesterDao(database: AppDatabase) = database.semesterDao()
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun provideExamDao(database: AppDatabase) = database.examsDao()
|
||||
}
|
||||
|
@ -2,21 +2,31 @@ package io.github.wulkanowy.data.db
|
||||
|
||||
import android.arch.persistence.room.Database
|
||||
import android.arch.persistence.room.RoomDatabase
|
||||
import android.arch.persistence.room.TypeConverters
|
||||
import io.github.wulkanowy.data.db.dao.ExamDao
|
||||
import io.github.wulkanowy.data.db.dao.SemesterDao
|
||||
import io.github.wulkanowy.data.db.dao.StudentDao
|
||||
import io.github.wulkanowy.data.db.entities.Exam
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
@Database(
|
||||
entities = [Student::class, Semester::class],
|
||||
entities = [
|
||||
Student::class,
|
||||
Semester::class,
|
||||
Exam::class
|
||||
],
|
||||
version = 1,
|
||||
exportSchema = false
|
||||
)
|
||||
@TypeConverters(Converters::class)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
|
||||
abstract fun studentDao(): StudentDao
|
||||
|
||||
abstract fun semesterDao(): SemesterDao
|
||||
|
||||
abstract fun examsDao(): ExamDao
|
||||
}
|
||||
|
14
app/src/main/java/io/github/wulkanowy/data/db/Converters.kt
Normal file
14
app/src/main/java/io/github/wulkanowy/data/db/Converters.kt
Normal file
@ -0,0 +1,14 @@
|
||||
package io.github.wulkanowy.data.db
|
||||
|
||||
import android.arch.persistence.room.TypeConverter
|
||||
import java.util.*
|
||||
|
||||
class Converters {
|
||||
|
||||
@TypeConverter
|
||||
fun fromTimestamp(value: Long?): Date? = value?.run { Date(value) }
|
||||
|
||||
|
||||
@TypeConverter
|
||||
fun dateToTimestamp(date: Date?): Long? = date?.time
|
||||
}
|
22
app/src/main/java/io/github/wulkanowy/data/db/dao/ExamDao.kt
Normal file
22
app/src/main/java/io/github/wulkanowy/data/db/dao/ExamDao.kt
Normal file
@ -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.Exam
|
||||
import io.reactivex.Maybe
|
||||
import java.util.*
|
||||
|
||||
@Dao
|
||||
interface ExamDao {
|
||||
|
||||
@Insert
|
||||
fun insertAll(exams: List<Exam>): List<Long>
|
||||
|
||||
@Delete
|
||||
fun deleteAll(exams: List<Exam>)
|
||||
|
||||
@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>>
|
||||
}
|
@ -3,11 +3,16 @@ package io.github.wulkanowy.data.db.dao
|
||||
import android.arch.persistence.room.Dao
|
||||
import android.arch.persistence.room.Insert
|
||||
import android.arch.persistence.room.OnConflictStrategy.REPLACE
|
||||
import android.arch.persistence.room.Query
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.reactivex.Single
|
||||
|
||||
@Dao
|
||||
interface SemesterDao {
|
||||
|
||||
@Insert(onConflict = REPLACE)
|
||||
fun insert(semester: Semester): Long
|
||||
fun insertAll(semester: List<Semester>)
|
||||
|
||||
@Query("SELECT * FROM Semesters WHERE student_id = :studentId")
|
||||
fun getSemester(studentId: String): Single<List<Semester>>
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import android.arch.persistence.room.Insert
|
||||
import android.arch.persistence.room.OnConflictStrategy.REPLACE
|
||||
import android.arch.persistence.room.Query
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.reactivex.Single
|
||||
import io.reactivex.Maybe
|
||||
|
||||
@Dao
|
||||
interface StudentDao {
|
||||
@ -14,5 +14,5 @@ interface StudentDao {
|
||||
fun insert(student: Student): Long
|
||||
|
||||
@Query("SELECT * FROM Students WHERE id = :id")
|
||||
fun load(id: Long): Single<Student>
|
||||
fun load(id: Long): Maybe<Student>
|
||||
}
|
||||
|
@ -0,0 +1,38 @@
|
||||
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 java.io.Serializable
|
||||
import java.util.*
|
||||
|
||||
@Entity(tableName = "Exams")
|
||||
data class Exam(
|
||||
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
var id: Long = 0,
|
||||
|
||||
@ColumnInfo(name = "student_id")
|
||||
var studentId: String = "",
|
||||
|
||||
@ColumnInfo(name = "diary_id")
|
||||
var diaryId: String = "",
|
||||
|
||||
var date: Date,
|
||||
|
||||
@ColumnInfo(name = "entry_date")
|
||||
var entryDate: Date = Date(),
|
||||
|
||||
var subject: String = "",
|
||||
|
||||
var group: String = "",
|
||||
|
||||
var type: String = "",
|
||||
|
||||
var description: String = "",
|
||||
|
||||
var teacher: String = "",
|
||||
|
||||
@ColumnInfo(name = "teacher_symbol")
|
||||
var teacherSymbol: String = ""
|
||||
) : Serializable
|
@ -6,12 +6,15 @@ import android.arch.persistence.room.Index
|
||||
import android.arch.persistence.room.PrimaryKey
|
||||
|
||||
@Entity(tableName = "Semesters",
|
||||
indices = [Index(value = ["diary_id", "semester_id"], unique = true)])
|
||||
indices = [Index(value = ["semester_id", "diary_id", "student_id"], unique = true)])
|
||||
data class Semester(
|
||||
|
||||
@PrimaryKey
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
var id: Long = 0,
|
||||
|
||||
@ColumnInfo(name = "student_id")
|
||||
var studentId: String,
|
||||
|
||||
@ColumnInfo(name = "diary_id")
|
||||
var diaryId: String,
|
||||
|
||||
@ -22,5 +25,8 @@ data class Semester(
|
||||
var semesterId: String,
|
||||
|
||||
@ColumnInfo(name = "semester_name")
|
||||
var semesterName: String = ""
|
||||
var semesterName: Int = 0,
|
||||
|
||||
@ColumnInfo(name = "is_current")
|
||||
var current: Boolean = false
|
||||
)
|
||||
|
@ -0,0 +1,39 @@
|
||||
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.Exam
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.repositories.local.ExamLocal
|
||||
import io.github.wulkanowy.data.repositories.remote.ExamRemote
|
||||
import io.reactivex.Single
|
||||
import org.threeten.bp.LocalDate
|
||||
import java.net.UnknownHostException
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class ExamRepository @Inject constructor(
|
||||
private val settings: InternetObservingSettings,
|
||||
private val local: ExamLocal,
|
||||
private val remote: ExamRemote
|
||||
) {
|
||||
|
||||
fun getExams(semester: Semester, date: LocalDate, forceRefresh: Boolean = false): Single<List<Exam>> {
|
||||
return local.getExams(semester, date).filter { !forceRefresh }
|
||||
.switchIfEmpty(ReactiveNetwork.checkInternetConnectivity(settings)
|
||||
.flatMap {
|
||||
if (it) remote.getExams(semester, date)
|
||||
else Single.error(UnknownHostException())
|
||||
}.flatMap { newExams ->
|
||||
local.getExams(semester, date).toSingle(emptyList())
|
||||
.map {
|
||||
local.deleteExams(it - newExams)
|
||||
local.saveExams(newExams - it)
|
||||
|
||||
newExams
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
@ -2,9 +2,10 @@ 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.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.repositories.local.StudentLocal
|
||||
import io.github.wulkanowy.data.repositories.remote.StudentRemote
|
||||
import io.github.wulkanowy.data.repositories.local.SessionLocal
|
||||
import io.github.wulkanowy.data.repositories.remote.SessionRemote
|
||||
import io.reactivex.Completable
|
||||
import io.reactivex.Single
|
||||
import java.net.UnknownHostException
|
||||
@ -12,17 +13,17 @@ import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class StudentRepository @Inject constructor(
|
||||
private val local: StudentLocal,
|
||||
private val remote: StudentRemote,
|
||||
class SessionRepository @Inject constructor(
|
||||
private val local: SessionLocal,
|
||||
private val remote: SessionRemote,
|
||||
private val settings: InternetObservingSettings) {
|
||||
|
||||
val isSessionSaved
|
||||
get() = local.isSessionSaved
|
||||
|
||||
lateinit var cachedStudents: Single<List<Student>>
|
||||
private set
|
||||
|
||||
val isStudentLoggedIn: Boolean
|
||||
get() = local.isStudentLoggedIn
|
||||
|
||||
fun getConnectedStudents(email: String, password: String, symbol: String): Single<List<Student>> {
|
||||
cachedStudents = ReactiveNetwork.checkInternetConnectivity(settings)
|
||||
.flatMap { isConnected ->
|
||||
@ -32,9 +33,19 @@ class StudentRepository @Inject constructor(
|
||||
return cachedStudents
|
||||
}
|
||||
|
||||
fun save(student: Student): Completable = local.save(student)
|
||||
fun getSemesters(): Single<List<Semester>> {
|
||||
return local.getLastStudent()
|
||||
.flatMapSingle {
|
||||
remote.initApi(it, true)
|
||||
local.getSemesters(it)
|
||||
}
|
||||
}
|
||||
|
||||
fun getCurrentStudent(): Single<Student> = local.getCurrentStudent()
|
||||
fun saveStudent(student: Student): Completable {
|
||||
return remote.getSemesters(student).flatMapCompletable {
|
||||
local.saveSemesters(it)
|
||||
}.concatWith(local.saveStudent(student))
|
||||
}
|
||||
|
||||
fun clearCache() {
|
||||
cachedStudents = Single.just(emptyList())
|
@ -0,0 +1,28 @@
|
||||
package io.github.wulkanowy.data.repositories.local
|
||||
|
||||
import io.github.wulkanowy.data.db.dao.ExamDao
|
||||
import io.github.wulkanowy.data.db.entities.Exam
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.utils.extension.toDate
|
||||
import io.reactivex.Maybe
|
||||
import org.threeten.bp.DayOfWeek
|
||||
import org.threeten.bp.LocalDate
|
||||
import org.threeten.bp.temporal.TemporalAdjusters
|
||||
import javax.inject.Inject
|
||||
|
||||
class ExamLocal @Inject constructor(private val examDb: ExamDao) {
|
||||
|
||||
fun getExams(semester: Semester, startDate: LocalDate): Maybe<List<Exam>> {
|
||||
return examDb.getExams(semester.diaryId, semester.studentId, startDate.toDate(),
|
||||
startDate.with(TemporalAdjusters.next(DayOfWeek.FRIDAY)).toDate()
|
||||
).filter { !it.isEmpty() }
|
||||
}
|
||||
|
||||
fun saveExams(exams: List<Exam>) {
|
||||
examDb.insertAll(exams)
|
||||
}
|
||||
|
||||
fun deleteExams(exams: List<Exam>) {
|
||||
examDb.deleteAll(exams)
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package io.github.wulkanowy.data.repositories.local
|
||||
|
||||
import android.content.Context
|
||||
import io.github.wulkanowy.data.db.SharedPrefHelper
|
||||
import io.github.wulkanowy.data.db.dao.SemesterDao
|
||||
import io.github.wulkanowy.data.db.dao.StudentDao
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.utils.security.Scrambler.decrypt
|
||||
import io.github.wulkanowy.utils.security.Scrambler.encrypt
|
||||
import io.reactivex.Completable
|
||||
import io.reactivex.Maybe
|
||||
import io.reactivex.Single
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class SessionLocal @Inject constructor(
|
||||
private val studentDb: StudentDao,
|
||||
private val semesterDb: SemesterDao,
|
||||
private val sharedPref: SharedPrefHelper,
|
||||
private val context: Context) {
|
||||
|
||||
companion object {
|
||||
const val LAST_USER_KEY: String = "last_user_id"
|
||||
}
|
||||
|
||||
val isSessionSaved
|
||||
get() = sharedPref.getLong(LAST_USER_KEY, defaultValue = 0L) != 0L
|
||||
|
||||
fun saveStudent(student: Student): Completable {
|
||||
return Single.fromCallable { studentDb.insert(student.copy(password = encrypt(student.password, context))) }
|
||||
.map { sharedPref.putLong(LAST_USER_KEY, it) }
|
||||
.ignoreElement()
|
||||
}
|
||||
|
||||
fun getLastStudent(): Maybe<Student> {
|
||||
return studentDb.load(sharedPref.getLong(LAST_USER_KEY, defaultValue = 0))
|
||||
.map { it.apply { password = decrypt(password) } }
|
||||
}
|
||||
|
||||
fun saveSemesters(semesters: List<Semester>): Completable {
|
||||
return Single.fromCallable { semesterDb.insertAll(semesters) }.ignoreElement()
|
||||
}
|
||||
|
||||
fun getSemesters(student: Student): Single<List<Semester>> {
|
||||
return semesterDb.getSemester(student.studentId)
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package io.github.wulkanowy.data.repositories.local
|
||||
|
||||
import android.content.Context
|
||||
import io.github.wulkanowy.data.db.SharedPrefHelper
|
||||
import io.github.wulkanowy.data.db.dao.StudentDao
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.utils.security.Scrambler.decrypt
|
||||
import io.github.wulkanowy.utils.security.Scrambler.encrypt
|
||||
import io.reactivex.Completable
|
||||
import io.reactivex.Single
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class StudentLocal @Inject constructor(
|
||||
private val studentDb: StudentDao,
|
||||
private val sharedPref: SharedPrefHelper,
|
||||
private val context: Context) {
|
||||
|
||||
companion object {
|
||||
const val CURRENT_USER_KEY: String = "current_user_id"
|
||||
}
|
||||
|
||||
val isStudentLoggedIn: Boolean
|
||||
get() = sharedPref.getLong(CURRENT_USER_KEY, 0) != 0L
|
||||
|
||||
fun save(student: Student): Completable {
|
||||
return Single.fromCallable { studentDb.insert(student.copy(password = encrypt(student.password, context))) }
|
||||
.map { sharedPref.putLong(CURRENT_USER_KEY, it) }
|
||||
.ignoreElement()
|
||||
}
|
||||
|
||||
fun getCurrentStudent(): Single<Student> {
|
||||
return studentDb.load(sharedPref.getLong(CURRENT_USER_KEY, defaultValue = 0))
|
||||
.map { it.apply { password = decrypt(password) } }
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package io.github.wulkanowy.data.repositories.remote
|
||||
|
||||
import io.github.wulkanowy.api.Api
|
||||
import io.github.wulkanowy.data.db.entities.Exam
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.utils.extension.toDate
|
||||
import io.reactivex.Single
|
||||
import org.threeten.bp.LocalDate
|
||||
import javax.inject.Inject
|
||||
|
||||
class ExamRemote @Inject constructor(private val api: Api) {
|
||||
|
||||
fun getExams(semester: Semester, startDate: LocalDate): Single<List<Exam>> {
|
||||
return Single.just(api.run {
|
||||
if (diaryId != semester.diaryId) {
|
||||
diaryId = semester.diaryId
|
||||
notifyDataChanged()
|
||||
}
|
||||
}).flatMap { api.getExams(startDate.toDate()) }
|
||||
.map { exams ->
|
||||
exams.map {
|
||||
Exam(
|
||||
studentId = semester.studentId,
|
||||
diaryId = semester.diaryId,
|
||||
date = it.date,
|
||||
entryDate = it.entryDate,
|
||||
subject = it.subject,
|
||||
group = it.group,
|
||||
type = it.type,
|
||||
description = it.description,
|
||||
teacher = it.teacher,
|
||||
teacherSymbol = it.teacherSymbol
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package io.github.wulkanowy.data.repositories.remote
|
||||
|
||||
import io.github.wulkanowy.api.Api
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.reactivex.Single
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class SessionRemote @Inject constructor(private val api: Api) {
|
||||
|
||||
fun getConnectedStudents(email: String, password: String, symbol: String): Single<List<Student>> {
|
||||
return Single.just(initApi(Student(email = email, password = password, symbol = symbol)))
|
||||
.flatMap { _ ->
|
||||
api.getPupils().map { students ->
|
||||
students.map {
|
||||
Student(email = email,
|
||||
password = password,
|
||||
symbol = it.symbol,
|
||||
studentId = it.studentId,
|
||||
studentName = it.studentName,
|
||||
schoolId = it.schoolId,
|
||||
schoolName = it.schoolName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getSemesters(student: Student): Single<List<Semester>> {
|
||||
return Single.just(initApi(student)).flatMap { _ ->
|
||||
api.getSemesters().map { semesters ->
|
||||
semesters.map {
|
||||
Semester(studentId = student.studentId,
|
||||
diaryId = it.diaryId,
|
||||
diaryName = it.diaryName,
|
||||
semesterId = it.semesterId.toString(),
|
||||
semesterName = it.semesterNumber,
|
||||
current = it.current)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun initApi(student: Student, checkInit: Boolean = false) {
|
||||
if (if (checkInit) api.studentId.isEmpty() else true) {
|
||||
api.run {
|
||||
email = student.email
|
||||
password = student.password
|
||||
symbol = student.symbol
|
||||
host = "vulcan.net.pl"
|
||||
schoolId = student.schoolId
|
||||
studentId = student.studentId
|
||||
notifyDataChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
package io.github.wulkanowy.data.repositories.remote
|
||||
|
||||
import io.github.wulkanowy.api.Api
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.reactivex.Single
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class StudentRemote @Inject constructor(private val api: Api) {
|
||||
|
||||
fun getConnectedStudents(email: String, password: String, symbol: String): Single<List<Student>> {
|
||||
api.let {
|
||||
it.email = email
|
||||
it.password = password
|
||||
it.symbol = symbol
|
||||
it.host = "vulcan.net.pl"
|
||||
it.onConfigChange()
|
||||
}
|
||||
return api.getPupils().map { students ->
|
||||
students.map {
|
||||
Student(email = email,
|
||||
password = password,
|
||||
symbol = it.symbol,
|
||||
studentId = it.studentId,
|
||||
studentName = it.studentName,
|
||||
schoolId = it.schoolId,
|
||||
schoolName = it.schoolName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -3,8 +3,9 @@ package io.github.wulkanowy.di
|
||||
import android.content.Context
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import io.github.wulkanowy.WulkanowyApp
|
||||
import io.github.wulkanowy.data.ErrorHandler
|
||||
import io.github.wulkanowy.utils.schedulers.SchedulersManager
|
||||
import io.github.wulkanowy.utils.schedulers.SchedulersProvider
|
||||
|
||||
@ -18,5 +19,5 @@ internal class AppModule {
|
||||
fun provideSchedulers(): SchedulersManager = SchedulersProvider()
|
||||
|
||||
@Provides
|
||||
fun provideErrorHandler(context: Context): ErrorHandler = ErrorHandler(context.resources)
|
||||
fun provideFlexibleAdapter() = FlexibleAdapter<AbstractFlexibleItem<*>>(null, null, true)
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package io.github.wulkanowy.ui.login.form
|
||||
|
||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||
import io.github.wulkanowy.data.repositories.SessionRepository
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.login.LoginErrorHandler
|
||||
import io.github.wulkanowy.utils.DEFAULT_SYMBOL
|
||||
@ -10,7 +10,7 @@ import javax.inject.Inject
|
||||
class LoginFormPresenter @Inject constructor(
|
||||
private val schedulers: SchedulersManager,
|
||||
private val errorHandler: LoginErrorHandler,
|
||||
private val studentRepository: StudentRepository)
|
||||
private val sessionRepository: SessionRepository)
|
||||
: BasePresenter<LoginFormView>(errorHandler) {
|
||||
|
||||
private var wasEmpty = false
|
||||
@ -22,7 +22,7 @@ class LoginFormPresenter @Inject constructor(
|
||||
|
||||
fun attemptLogin(email: String, password: String, symbol: String) {
|
||||
if (!validateCredentials(email, password, symbol)) return
|
||||
disposable.add(studentRepository.getConnectedStudents(email, password, normalizeSymbol(symbol))
|
||||
disposable.add(sessionRepository.getConnectedStudents(email, password, normalizeSymbol(symbol))
|
||||
.observeOn(schedulers.mainThread())
|
||||
.subscribeOn(schedulers.backgroundThread())
|
||||
.doOnSubscribe {
|
||||
@ -34,7 +34,7 @@ class LoginFormPresenter @Inject constructor(
|
||||
showSoftKeyboard()
|
||||
}
|
||||
}
|
||||
studentRepository.clearCache()
|
||||
sessionRepository.clearCache()
|
||||
}
|
||||
.doFinally { view?.showLoginProgress(false) }
|
||||
.subscribe({
|
||||
|
@ -9,6 +9,7 @@ import android.view.View.VISIBLE
|
||||
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.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.ui.main.MainActivity
|
||||
@ -22,7 +23,11 @@ class LoginOptionsFragment : BaseFragment(), LoginOptionsView {
|
||||
lateinit var presenter: LoginOptionsPresenter
|
||||
|
||||
@Inject
|
||||
lateinit var loginAdapter: FlexibleAdapter<LoginOptionsItem>
|
||||
lateinit var loginAdapter: FlexibleAdapter<AbstractFlexibleItem<*>>
|
||||
|
||||
companion object {
|
||||
fun newInstance() = LoginOptionsFragment()
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_login_options, container, false)
|
||||
@ -34,7 +39,13 @@ class LoginOptionsFragment : BaseFragment(), LoginOptionsView {
|
||||
}
|
||||
|
||||
override fun initRecycler() {
|
||||
loginAdapter.setOnItemClickListener { item -> item?.let { presenter.onSelectStudent(it.student) } }
|
||||
loginAdapter.run {
|
||||
setOnItemClickListener { position ->
|
||||
(getItem(position) as? LoginOptionsItem)?.let {
|
||||
presenter.onSelectStudent(it.student)
|
||||
}
|
||||
}
|
||||
}
|
||||
loginOptionsRecycler.run {
|
||||
adapter = loginAdapter
|
||||
layoutManager = SmoothScrollLinearLayoutManager(context)
|
||||
@ -47,7 +58,7 @@ class LoginOptionsFragment : BaseFragment(), LoginOptionsView {
|
||||
|
||||
override fun updateData(data: List<LoginOptionsItem>) {
|
||||
loginAdapter.run {
|
||||
updateDataSet(data)
|
||||
updateDataSet(data, true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,4 +77,9 @@ class LoginOptionsFragment : BaseFragment(), LoginOptionsView {
|
||||
override fun showActionBar(show: Boolean) {
|
||||
(activity as AppCompatActivity?)?.supportActionBar?.run { if (show) show() else hide() }
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
presenter.detachView()
|
||||
}
|
||||
}
|
||||
|
@ -2,14 +2,14 @@ package io.github.wulkanowy.ui.login.options
|
||||
|
||||
import io.github.wulkanowy.data.ErrorHandler
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||
import io.github.wulkanowy.data.repositories.SessionRepository
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.utils.schedulers.SchedulersManager
|
||||
import javax.inject.Inject
|
||||
|
||||
class LoginOptionsPresenter @Inject constructor(
|
||||
private val errorHandler: ErrorHandler,
|
||||
private val repository: StudentRepository,
|
||||
private val repository: SessionRepository,
|
||||
private val schedulers: SchedulersManager)
|
||||
: BasePresenter<LoginOptionsView>(errorHandler) {
|
||||
|
||||
@ -32,7 +32,7 @@ class LoginOptionsPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
fun onSelectStudent(student: Student) {
|
||||
disposable.add(repository.save(student)
|
||||
disposable.add(repository.saveStudent(student)
|
||||
.subscribeOn(schedulers.backgroundThread())
|
||||
.observeOn(schedulers.mainThread())
|
||||
.doOnSubscribe { _ ->
|
||||
|
@ -0,0 +1,51 @@
|
||||
package io.github.wulkanowy.ui.main.exam
|
||||
|
||||
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.Exam
|
||||
import io.github.wulkanowy.utils.extension.toFormat
|
||||
import kotlinx.android.synthetic.main.dialog_exam.*
|
||||
|
||||
class ExamDialog : DialogFragment() {
|
||||
|
||||
private lateinit var exam: Exam
|
||||
|
||||
companion object {
|
||||
private const val ARGUMENT_KEY = "Item"
|
||||
|
||||
fun newInstance(exam: Exam): ExamDialog {
|
||||
return ExamDialog().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 {
|
||||
exam = getSerializable(ARGUMENT_KEY) as Exam
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
dialog.setTitle(getString(R.string.all_details))
|
||||
return inflater.inflate(R.layout.dialog_exam, container, false)
|
||||
}
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
|
||||
examDialogSubjectValue.text = exam.subject
|
||||
examDialogTypeValue.text = exam.type
|
||||
examDialogTeacherValue.text = exam.teacher
|
||||
examDialogDateValue.text = exam.entryDate.toFormat()
|
||||
examDialogDescriptionValue.text = exam.description
|
||||
|
||||
examDialogClose.setOnClickListener { dismiss() }
|
||||
}
|
||||
}
|
@ -3,17 +3,104 @@ package io.github.wulkanowy.ui.main.exam
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.View.*
|
||||
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.data.db.entities.Exam
|
||||
import io.github.wulkanowy.ui.base.BaseFragment
|
||||
import io.github.wulkanowy.utils.extension.setOnItemClickListener
|
||||
import kotlinx.android.synthetic.main.fragment_exam.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class ExamFragment : BaseFragment() {
|
||||
class ExamFragment : BaseFragment(), ExamView {
|
||||
|
||||
@Inject
|
||||
lateinit var presenter: ExamPresenter
|
||||
|
||||
@Inject
|
||||
lateinit var examAdapter: FlexibleAdapter<AbstractFlexibleItem<*>>
|
||||
|
||||
companion object {
|
||||
private const val SAVED_DATE_KEY = "CURRENT_DATE"
|
||||
fun newInstance() = ExamFragment()
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_exam, container, false)
|
||||
}
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
presenter.run {
|
||||
attachView(this@ExamFragment)
|
||||
loadData(date = savedInstanceState?.getLong(SAVED_DATE_KEY))
|
||||
}
|
||||
}
|
||||
|
||||
override fun initView() {
|
||||
examAdapter.run {
|
||||
setOnItemClickListener { presenter.onExamItemSelected(getItem(it)) }
|
||||
}
|
||||
examRecycler.run {
|
||||
layoutManager = SmoothScrollLinearLayoutManager(context)
|
||||
adapter = examAdapter
|
||||
}
|
||||
examSwipe.setOnRefreshListener { presenter.loadData(date = null, forceRefresh = true) }
|
||||
examPreviousButton.setOnClickListener { presenter.loadExamsForPreviousWeek() }
|
||||
examNextButton.setOnClickListener { presenter.loadExamsForNextWeek()}
|
||||
}
|
||||
|
||||
override fun updateData(data: List<ExamItem>) {
|
||||
examAdapter.updateDataSet(data, true)
|
||||
}
|
||||
|
||||
override fun updateNavigationWeek(date: String) {
|
||||
examNavDate.text = date
|
||||
}
|
||||
|
||||
override fun showEmpty(show: Boolean) {
|
||||
examEmpty.visibility = if (show) VISIBLE else GONE
|
||||
}
|
||||
|
||||
override fun showProgress(show: Boolean) {
|
||||
examProgress.visibility = if (show) VISIBLE else GONE
|
||||
}
|
||||
|
||||
override fun showContent(show: Boolean) {
|
||||
examRecycler.visibility = if (show) VISIBLE else GONE
|
||||
}
|
||||
|
||||
override fun showRefresh(show: Boolean) {
|
||||
examSwipe.isRefreshing = show
|
||||
}
|
||||
|
||||
override fun showPreButton(show: Boolean) {
|
||||
examPreviousButton.visibility = if (show) VISIBLE else INVISIBLE
|
||||
}
|
||||
|
||||
override fun showNextButton(show: Boolean) {
|
||||
examNextButton.visibility = if (show) VISIBLE else INVISIBLE
|
||||
}
|
||||
|
||||
override fun showExamDialog(exam: Exam) {
|
||||
ExamDialog.newInstance(exam).show(fragmentManager, exam.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,59 @@
|
||||
package io.github.wulkanowy.ui.main.exam
|
||||
|
||||
import android.view.View
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.AbstractHeaderItem
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.davidea.viewholders.ExpandableViewHolder
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.utils.extension.getWeekDayName
|
||||
import io.github.wulkanowy.utils.extension.toFormat
|
||||
import kotlinx.android.extensions.LayoutContainer
|
||||
import kotlinx.android.synthetic.main.header_exam.*
|
||||
import org.apache.commons.lang3.StringUtils
|
||||
import java.util.*
|
||||
|
||||
class ExamHeader : AbstractHeaderItem<ExamHeader.ViewHolder>() {
|
||||
|
||||
lateinit var date: Date
|
||||
|
||||
override fun createViewHolder(view: View?, adapter: FlexibleAdapter<IFlexible<*>>?): ViewHolder {
|
||||
return ViewHolder(view, adapter)
|
||||
}
|
||||
|
||||
override fun getLayoutRes() = R.layout.header_exam
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as ExamHeader
|
||||
|
||||
if (date != other.date) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return date.hashCode()
|
||||
}
|
||||
|
||||
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<*>>?, holder: ViewHolder,
|
||||
position: Int, payloads: MutableList<Any>?) {
|
||||
holder.run {
|
||||
examHeaderDay.text = StringUtils.capitalize(date.getWeekDayName())
|
||||
examHeaderDate.text = date.toFormat()
|
||||
}
|
||||
}
|
||||
|
||||
class ViewHolder(view: View?, adapter: FlexibleAdapter<IFlexible<*>>?) : ExpandableViewHolder(view, adapter),
|
||||
LayoutContainer {
|
||||
|
||||
init {
|
||||
contentView.setOnClickListener(this)
|
||||
}
|
||||
|
||||
override val containerView: View
|
||||
get() = contentView
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package io.github.wulkanowy.ui.main.exam
|
||||
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.View
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.AbstractSectionableItem
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.davidea.viewholders.FlexibleViewHolder
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Exam
|
||||
import kotlinx.android.extensions.LayoutContainer
|
||||
import kotlinx.android.synthetic.main.item_exam.*
|
||||
|
||||
class ExamItem(header: ExamHeader, val exam: Exam) : AbstractSectionableItem<ExamItem.ViewHolder, ExamHeader>(header) {
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as ExamItem
|
||||
|
||||
if (exam != other.exam) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return exam.hashCode()
|
||||
}
|
||||
|
||||
override fun getLayoutRes() = R.layout.item_exam
|
||||
|
||||
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): ViewHolder {
|
||||
return ViewHolder(view, adapter)
|
||||
}
|
||||
|
||||
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<*>>, holder: ViewHolder,
|
||||
position: Int, payloads: MutableList<Any>?) {
|
||||
holder.run {
|
||||
examItemSubject.text = exam.subject
|
||||
examItemTeacher.text = exam.teacher
|
||||
examItemType.text = exam.type
|
||||
}
|
||||
}
|
||||
|
||||
class ViewHolder(view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter),
|
||||
LayoutContainer {
|
||||
|
||||
override val containerView: View
|
||||
get() = contentView
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
package io.github.wulkanowy.ui.main.exam
|
||||
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
import io.github.wulkanowy.data.ErrorHandler
|
||||
import io.github.wulkanowy.data.db.entities.Exam
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.repositories.ExamRepository
|
||||
import io.github.wulkanowy.data.repositories.SessionRepository
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.utils.extension.isHolidays
|
||||
import io.github.wulkanowy.utils.extension.toFormat
|
||||
import io.github.wulkanowy.utils.getNearMonday
|
||||
import io.github.wulkanowy.utils.schedulers.SchedulersManager
|
||||
import org.threeten.bp.LocalDate
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class ExamPresenter @Inject constructor(
|
||||
private val errorHandler: ErrorHandler,
|
||||
private val schedulers: SchedulersManager,
|
||||
private val examRepository: ExamRepository,
|
||||
private val sessionRepository: SessionRepository
|
||||
) : BasePresenter<ExamView>(errorHandler) {
|
||||
|
||||
var currentDate: LocalDate = getNearMonday(LocalDate.now())
|
||||
private set
|
||||
|
||||
override fun attachView(view: ExamView) {
|
||||
super.attachView(view)
|
||||
view.initView()
|
||||
}
|
||||
|
||||
fun loadExamsForPreviousWeek() = loadData(currentDate.minusDays(7).toEpochDay())
|
||||
|
||||
fun loadExamsForNextWeek() = loadData(currentDate.plusDays(7).toEpochDay())
|
||||
|
||||
fun loadData(date: Long?, forceRefresh: Boolean = false) {
|
||||
this.currentDate = LocalDate.ofEpochDay(date ?: getNearMonday(currentDate).toEpochDay())
|
||||
if (currentDate.isHolidays()) return
|
||||
|
||||
disposable.clear()
|
||||
disposable.add(sessionRepository.getSemesters()
|
||||
.map { selectSemester(it, -1) }
|
||||
.flatMap { examRepository.getExams(it, currentDate, forceRefresh) }
|
||||
.map { it.groupBy { exam -> exam.date }.toSortedMap() }
|
||||
.map { createExamItems(it) }
|
||||
.subscribeOn(schedulers.backgroundThread())
|
||||
.observeOn(schedulers.mainThread())
|
||||
.doOnSubscribe {
|
||||
view?.run {
|
||||
showRefresh(forceRefresh)
|
||||
showProgress(!forceRefresh)
|
||||
if (!forceRefresh) showEmpty(false)
|
||||
showContent(null == date && forceRefresh)
|
||||
showPreButton(!currentDate.minusDays(7).isHolidays())
|
||||
showNextButton(!currentDate.plusDays(7).isHolidays())
|
||||
updateNavigationWeek("${currentDate.toFormat("dd.MM")}-${currentDate.plusDays(4).toFormat("dd.MM")}")
|
||||
}
|
||||
}
|
||||
.doAfterSuccess {
|
||||
view?.run {
|
||||
showEmpty(it.isEmpty())
|
||||
showContent(it.isNotEmpty())
|
||||
}
|
||||
}
|
||||
.doFinally {
|
||||
view?.run {
|
||||
showRefresh(false)
|
||||
showProgress(false)
|
||||
}
|
||||
}
|
||||
.subscribe({ view?.updateData(it) }) { errorHandler.proceed(it) })
|
||||
}
|
||||
|
||||
private fun createExamItems(items: Map<Date, List<Exam>>): List<ExamItem> {
|
||||
return items.flatMap {
|
||||
val header = ExamHeader().apply { date = it.key }
|
||||
it.value.reversed().map { item ->
|
||||
ExamItem(header, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onExamItemSelected(item: AbstractFlexibleItem<*>?) {
|
||||
if (item is ExamItem) view?.showExamDialog(item.exam)
|
||||
}
|
||||
|
||||
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,28 @@
|
||||
package io.github.wulkanowy.ui.main.exam
|
||||
|
||||
import io.github.wulkanowy.data.db.entities.Exam
|
||||
import io.github.wulkanowy.ui.base.BaseView
|
||||
import org.threeten.bp.LocalDate
|
||||
|
||||
interface ExamView : BaseView {
|
||||
|
||||
fun initView()
|
||||
|
||||
fun updateData(data: List<ExamItem>)
|
||||
|
||||
fun showEmpty(show: Boolean)
|
||||
|
||||
fun showProgress(show: Boolean)
|
||||
|
||||
fun showContent(show: Boolean)
|
||||
|
||||
fun showRefresh(show: Boolean)
|
||||
|
||||
fun showNextButton(show: Boolean)
|
||||
|
||||
fun showPreButton(show: Boolean)
|
||||
|
||||
fun showExamDialog(exam: Exam)
|
||||
|
||||
fun updateNavigationWeek(date: String)
|
||||
}
|
@ -21,12 +21,12 @@ class SplashActivity : BaseActivity(), SplashView {
|
||||
presenter.detachView()
|
||||
}
|
||||
|
||||
override fun openLoginActivity() {
|
||||
override fun openLoginView() {
|
||||
startActivity(LoginActivity.getStartIntent(this))
|
||||
finish()
|
||||
}
|
||||
|
||||
override fun openMainActivity() {
|
||||
override fun openMainView() {
|
||||
startActivity(MainActivity.getStartIntent(this))
|
||||
finish()
|
||||
}
|
||||
|
@ -1,16 +1,16 @@
|
||||
package io.github.wulkanowy.ui.splash
|
||||
|
||||
import io.github.wulkanowy.data.ErrorHandler
|
||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||
import io.github.wulkanowy.data.repositories.SessionRepository
|
||||
import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import javax.inject.Inject
|
||||
|
||||
class SplashPresenter @Inject constructor(private val studentRepository: StudentRepository,
|
||||
class SplashPresenter @Inject constructor(private val sessionRepository: SessionRepository,
|
||||
errorHandler: ErrorHandler)
|
||||
: BasePresenter<SplashView>(errorHandler) {
|
||||
|
||||
override fun attachView(view: SplashView) {
|
||||
super.attachView(view)
|
||||
view.run { if (studentRepository.isStudentLoggedIn) openMainActivity() else openLoginActivity() }
|
||||
view.run { if (sessionRepository.isSessionSaved) openMainView() else openLoginView() }
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import io.github.wulkanowy.ui.base.BaseView
|
||||
|
||||
interface SplashView : BaseView {
|
||||
|
||||
fun openLoginActivity()
|
||||
fun openLoginView()
|
||||
|
||||
fun openMainActivity()
|
||||
fun openMainView()
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ 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.*
|
||||
|
||||
@ -68,29 +69,35 @@ 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(), Year.now().value)
|
||||
fun isHolidays(): Boolean = isHolidays(LocalDate.now())
|
||||
|
||||
fun isHolidays(day: LocalDate, year: Int): Boolean {
|
||||
return day.isAfter(getLastSchoolDay(year)) && day.isBefore(getFirstSchoolDay(year))
|
||||
fun isHolidays(day: LocalDate): Boolean {
|
||||
return day.isAfter(getLastSchoolDay(day.year)) && day.isBefore(getFirstSchoolDay(day.year))
|
||||
}
|
||||
|
||||
fun getFirstSchoolDay(year: Int): LocalDate? {
|
||||
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
|
||||
}
|
||||
else -> firstSeptember
|
||||
}
|
||||
}
|
||||
|
||||
fun getLastSchoolDay(year: Int): LocalDate? {
|
||||
fun getLastSchoolDay(year: Int): LocalDate {
|
||||
return LocalDate
|
||||
.of(year, 6, 20)
|
||||
.with(TemporalAdjusters.next(FRIDAY))
|
||||
|
@ -0,0 +1,25 @@
|
||||
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()
|
@ -3,9 +3,13 @@ package io.github.wulkanowy.utils.extension
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||
|
||||
fun <K : AbstractFlexibleItem<*>, T : FlexibleAdapter<K>> T.setOnItemClickListener(listener: (K?) -> Unit) {
|
||||
fun FlexibleAdapter<*>.setOnItemClickListener(listener: (position: Int) -> Unit) {
|
||||
addListener(FlexibleAdapter.OnItemClickListener { _, position ->
|
||||
listener(getItem(position))
|
||||
listener(position)
|
||||
true
|
||||
})
|
||||
}
|
||||
|
||||
fun FlexibleAdapter<*>.setOnUpdateListener(listener: (size: Int) -> Unit) {
|
||||
addListener(FlexibleAdapter.OnUpdateListener { listener(it) })
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
@ -8,171 +7,106 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="300dp"
|
||||
android:orientation="vertical">
|
||||
android:orientation="vertical"
|
||||
android:padding="20dp">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/timetable_dialog_relative_layout"
|
||||
android:layout_width="match_parent"
|
||||
<TextView
|
||||
android:id="@+id/examDialogSubject"
|
||||
android:layout_width="wrap_content"
|
||||
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">
|
||||
android:text="@string/all_subject"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="17sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/exams_dialog_details"
|
||||
android:layout_width="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/examDialogSubjectValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="3dp"
|
||||
android:text="@string/all_no_data"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/exams_dialog_subject"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/exams_dialog_details"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/all_subject"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="17sp" />
|
||||
<TextView
|
||||
android:id="@+id/examDialogType"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/exam_type"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="17sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/exams_dialog_subject_value"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/exams_dialog_subject"
|
||||
android:layout_marginTop="3dp"
|
||||
android:text="@string/all_no_data"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="12sp" />
|
||||
<TextView
|
||||
android:id="@+id/examDialogTypeValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="3dp"
|
||||
android:text="@string/all_no_data"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/exams_dialog_type"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/exams_dialog_subject_value"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/exam_type"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="17sp" />
|
||||
<TextView
|
||||
android:id="@+id/examDialogTeacher"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/all_teacher"
|
||||
android:textSize="17sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/exams_dialog_type_value"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/exams_dialog_type"
|
||||
android:layout_marginTop="3dp"
|
||||
android:text="@string/all_no_data"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="12sp" />
|
||||
<TextView
|
||||
android:id="@+id/examDialogTeacherValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="3dp"
|
||||
android:text="@string/all_no_data"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/exams_dialog_teacher"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/exams_dialog_type_value"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/all_teacher"
|
||||
android:textSize="17sp" />
|
||||
<TextView
|
||||
android:id="@+id/examDialogDate"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/exam_entry_date"
|
||||
android:textSize="17sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/exams_dialog_teacher_value"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/exams_dialog_teacher"
|
||||
android:layout_marginTop="3dp"
|
||||
android:text="@string/all_no_data"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="12sp" />
|
||||
<TextView
|
||||
android:id="@+id/examDialogDateValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="3dp"
|
||||
android:text="@string/all_no_data"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/exams_dialog_date"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/exams_dialog_teacher_value"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/exam_entry_date"
|
||||
android:textSize="17sp" />
|
||||
<TextView
|
||||
android:id="@+id/examDialogDescription"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/all_description"
|
||||
android:textSize="17sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/exams_dialog_date_value"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/exams_dialog_date"
|
||||
android:layout_marginTop="3dp"
|
||||
android:text="@string/all_no_data"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="12sp" />
|
||||
<TextView
|
||||
android:id="@+id/examDialogDescriptionValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="3dp"
|
||||
android:text="@string/all_no_data"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/exams_dialog_description"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/exams_dialog_date_value"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/all_description"
|
||||
android:textSize="17sp" />
|
||||
<Button
|
||||
android:id="@+id/examDialogClose"
|
||||
style="@style/Widget.AppCompat.Button.Borderless"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginTop="15dp"
|
||||
android:padding="0dp"
|
||||
android:text="@string/all_close"
|
||||
android:textAllCaps="true"
|
||||
android:textSize="15sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/exams_dialog_description_value"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/exams_dialog_description"
|
||||
android:layout_marginTop="3dp"
|
||||
android:text="@string/all_no_data"
|
||||
android:textIsSelectable="true"
|
||||
android:textSize="12sp" />
|
||||
|
||||
|
||||
<Button
|
||||
android:id="@+id/exams_dialog_close"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignTop="@+id/exams_dialog_description_value"
|
||||
android:layout_marginTop="25dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:focusable="true"
|
||||
android:text="@string/all_close"
|
||||
android:textColor="?android:attr/android:textColorSecondary"
|
||||
android:textAllCaps="true"
|
||||
android:textSize="15sp" />
|
||||
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
@ -1,30 +1,99 @@
|
||||
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/examContainer"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentBottom="true">
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:text="Exam" />
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!--<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.design.widget.TabLayout
|
||||
android:id="@+id/exams_fragment_tab_layout"
|
||||
android:layout_width="match_parent"
|
||||
<ProgressBar
|
||||
android:id="@+id/examProgress"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:tabMinWidth="125dp"
|
||||
app:tabMode="scrollable" />
|
||||
android:layout_gravity="center"
|
||||
android:indeterminate="true" />
|
||||
|
||||
<android.support.v4.view.ViewPager
|
||||
android:id="@+id/exams_fragment_viewpager"
|
||||
<android.support.v4.widget.SwipeRefreshLayout
|
||||
android:id="@+id/examSwipe"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/examRecycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</android.support.v4.widget.SwipeRefreshLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/examEmpty"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/exams_fragment_tab_layout" />
|
||||
</RelativeLayout>-->
|
||||
</android.support.design.widget.CoordinatorLayout>
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
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_exam_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/exam_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/examPreviousButton"
|
||||
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/examNavDate"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="@string/app_name" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/examNextButton"
|
||||
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,64 +0,0 @@
|
||||
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/exams_tab_fragment_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="io.github.wulkanowy.ui.main.grades.GradesFragment">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/exams_tab_fragment_progress_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:visibility="gone">
|
||||
|
||||
<ProgressBar
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminate="true" />
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/exams_tab_fragment_no_item_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center">
|
||||
|
||||
<android.support.v7.widget.AppCompatImageView
|
||||
android:id="@+id/exams_tab_fragment_no_item_image"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/exams_tab_fragment_no_item_text"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="40dp"
|
||||
android:minHeight="100dp"
|
||||
android:minWidth="100dp"
|
||||
app:srcCompat="@drawable/ic_menu_main_exam_24dp"
|
||||
app:tint="?android:attr/textColorPrimary"
|
||||
tools:ignore="contentDescription" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/exams_tab_fragment_no_item_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="46dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/exam_no_items"
|
||||
android:textSize="20sp" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<android.support.v4.widget.SwipeRefreshLayout
|
||||
android:id="@+id/exams_tab_fragment_swipe_refresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/exams_tab_fragment_recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</android.support.v4.widget.SwipeRefreshLayout>
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
@ -10,7 +10,7 @@
|
||||
android:paddingTop="10dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/exams_header_name"
|
||||
android:id="@+id/examHeaderDay"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
@ -18,7 +18,7 @@
|
||||
android:textSize="18sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/exams_header_date"
|
||||
android:id="@+id/examHeaderDate"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
@ -26,8 +26,8 @@
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_toEndOf="@id/exams_header_name"
|
||||
android:layout_toRightOf="@id/exams_header_name"
|
||||
android:layout_toEndOf="@id/examHeaderDay"
|
||||
android:layout_toRightOf="@id/examHeaderDay"
|
||||
android:gravity="end"
|
||||
android:text="@string/app_name"
|
||||
android:textSize="13sp" />
|
||||
|
@ -1,56 +1,47 @@
|
||||
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/exams_subitem_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="60dp"
|
||||
card_view:cardElevation="0dp">
|
||||
android:foreground="?attr/selectableItemBackgroundBorderless">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/ic_all_divider"
|
||||
android:foreground="?attr/selectableItemBackgroundBorderless">
|
||||
<TextView
|
||||
android:id="@+id/examItemSubject"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/app_name"
|
||||
android:textSize="15sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/exams_subitem_subject"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/app_name"
|
||||
android:textSize="15sp" />
|
||||
<TextView
|
||||
android:id="@+id/examItemType"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignLeft="@id/examItemSubject"
|
||||
android:layout_alignStart="@id/examItemSubject"
|
||||
android:layout_below="@id/examItemSubject"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:text="@string/app_name"
|
||||
android:textSize="13sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/exams_subitems_type"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignLeft="@id/exams_subitem_subject"
|
||||
android:layout_alignStart="@id/exams_subitem_subject"
|
||||
android:layout_below="@id/exams_subitem_subject"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:text="@string/app_name"
|
||||
android:textSize="13sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/exams_subitems_teacher"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@id/exams_subitem_subject"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginRight="20dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_toEndOf="@id/exams_subitems_type"
|
||||
android:layout_toRightOf="@id/exams_subitems_type"
|
||||
android:gravity="end"
|
||||
android:text="@string/app_name"
|
||||
android:textSize="13sp" />
|
||||
</RelativeLayout>
|
||||
</android.support.v7.widget.CardView>
|
||||
<TextView
|
||||
android:id="@+id/examItemTeacher"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@id/examItemSubject"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginRight="20dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_toEndOf="@id/examItemType"
|
||||
android:layout_toRightOf="@id/examItemType"
|
||||
android:gravity="end"
|
||||
android:text="@string/app_name"
|
||||
android:textSize="13sp" />
|
||||
</RelativeLayout>
|
||||
|
@ -163,4 +163,7 @@
|
||||
<string name="all_sync_fail">Podczas synchronizacji wystąpił błąd</string>
|
||||
<string name="all_timeout">Zbyt długie oczekiwanie na połączenie</string>
|
||||
<string name="all_login_failed">Logowanie nie powiodło się. Spróbuj ponownie lub zrestartuj aplikację</string>
|
||||
|
||||
<string name="prev">Poprzedni</string>
|
||||
<string name="next">Następny</string>
|
||||
</resources>
|
||||
|
@ -156,4 +156,6 @@
|
||||
<string name="all_sync_fail">There was an error during synchronization</string>
|
||||
<string name="all_timeout">Too long wait for connection</string>
|
||||
<string name="all_login_failed">Login is failed. Try again or restart the app</string>
|
||||
<string name="prev">Prev</string>
|
||||
<string name="next">Next</string>
|
||||
</resources>
|
||||
|
@ -36,4 +36,12 @@
|
||||
<item name="android:windowBackground">@drawable/layer_splash_background</item>
|
||||
</style>
|
||||
|
||||
<style name="DialogFragmentTheme" parent="Theme.AppCompat.DayNight.Dialog.Alert">
|
||||
<item name="android:textColorTertiary">@android:color/primary_text_light</item>
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">false</item>
|
||||
<item name="android:windowActionBar">false</item>
|
||||
<item name="android:windowNoTitle">false</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
@ -0,0 +1,56 @@
|
||||
package io.github.wulkanowy.data.repositories.remote
|
||||
|
||||
import io.github.wulkanowy.api.Api
|
||||
import io.github.wulkanowy.api.exams.Exam
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.reactivex.Single
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
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 java.sql.Date
|
||||
|
||||
class ExamRemoteTest {
|
||||
|
||||
@Mock
|
||||
private lateinit var mockApi: Api
|
||||
|
||||
@Mock
|
||||
private lateinit var semesterMock: Semester
|
||||
|
||||
@Before
|
||||
fun initApi() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getExamsTest() {
|
||||
doReturn(Single.just(listOf(
|
||||
getExam("2018-09-10"),
|
||||
getExam("2018-09-17")
|
||||
))).`when`(mockApi).getExams(any())
|
||||
|
||||
doReturn("1").`when`(semesterMock).studentId
|
||||
doReturn("1").`when`(semesterMock).diaryId
|
||||
|
||||
val exams = ExamRemote(mockApi).getExams(semesterMock, LocalDate.of(2018, 9, 10)).blockingGet()
|
||||
assertEquals(2, exams.size)
|
||||
}
|
||||
|
||||
private fun getExam(dateString: String): Exam {
|
||||
return Exam().apply {
|
||||
subject = ""
|
||||
group = ""
|
||||
type = ""
|
||||
description = ""
|
||||
teacher = ""
|
||||
teacherSymbol = ""
|
||||
date = Date.valueOf(dateString)
|
||||
entryDate = Date.valueOf(dateString)
|
||||
}
|
||||
}
|
||||
}
|
@ -25,7 +25,7 @@ class StudentRemoteTest {
|
||||
doReturn(Single.just(listOf(Pupil("", "", "", "test", "", ""))))
|
||||
.`when`(mockApi).getPupils()
|
||||
|
||||
val students = StudentRemote(mockApi).getConnectedStudents("", "", "").blockingGet()
|
||||
val students = SessionRemote(mockApi).getConnectedStudents("", "", "").blockingGet()
|
||||
assertEquals(1, students.size)
|
||||
assertEquals("test", students.first().studentName)
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ package io.github.wulkanowy.ui.login.form
|
||||
|
||||
import io.github.wulkanowy.TestSchedulers
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||
import io.github.wulkanowy.data.repositories.SessionRepository
|
||||
import io.github.wulkanowy.ui.login.LoginErrorHandler
|
||||
import io.reactivex.Single
|
||||
import org.junit.Before
|
||||
@ -18,7 +18,7 @@ class LoginFormPresenterTest {
|
||||
lateinit var loginFormView: LoginFormView
|
||||
|
||||
@Mock
|
||||
lateinit var repository: StudentRepository
|
||||
lateinit var repository: SessionRepository
|
||||
|
||||
@Mock
|
||||
lateinit var errorHandler: LoginErrorHandler
|
||||
|
@ -3,7 +3,7 @@ package io.github.wulkanowy.ui.login.options
|
||||
import io.github.wulkanowy.TestSchedulers
|
||||
import io.github.wulkanowy.data.ErrorHandler
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||
import io.github.wulkanowy.data.repositories.SessionRepository
|
||||
import io.reactivex.Completable
|
||||
import io.reactivex.Single
|
||||
import org.junit.Before
|
||||
@ -21,7 +21,7 @@ class LoginOptionsPresenterTest {
|
||||
lateinit var loginOptionsView: LoginOptionsView
|
||||
|
||||
@Mock
|
||||
lateinit var repository: StudentRepository
|
||||
lateinit var repository: SessionRepository
|
||||
|
||||
private lateinit var presenter: LoginOptionsPresenter
|
||||
|
||||
@ -62,7 +62,7 @@ class LoginOptionsPresenterTest {
|
||||
|
||||
@Test
|
||||
fun onSelectedStudentTest() {
|
||||
doReturn(Completable.complete()).`when`(repository).save(testStudent)
|
||||
doReturn(Completable.complete()).`when`(repository).saveStudent(testStudent)
|
||||
presenter.onSelectStudent(testStudent)
|
||||
verify(loginOptionsView).showLoginProgress(true)
|
||||
verify(loginOptionsView).openMainView()
|
||||
@ -71,9 +71,9 @@ class LoginOptionsPresenterTest {
|
||||
|
||||
@Test
|
||||
fun onSelectedStudentErrorTest() {
|
||||
doReturn(Completable.error(testException)).`when`(repository).save(testStudent)
|
||||
doReturn(Completable.error(testException)).`when`(repository).saveStudent(testStudent)
|
||||
presenter.onSelectStudent(testStudent)
|
||||
verify(loginOptionsView).showLoginProgress(true)
|
||||
verify(errorHandler).proceed(testException)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package io.github.wulkanowy.ui.splash
|
||||
|
||||
import io.github.wulkanowy.data.ErrorHandler
|
||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||
import io.github.wulkanowy.data.repositories.SessionRepository
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.mockito.Mock
|
||||
@ -15,7 +15,7 @@ class SplashPresenterTest {
|
||||
lateinit var splashView: SplashView
|
||||
|
||||
@Mock
|
||||
lateinit var studentRepository: StudentRepository
|
||||
lateinit var studentRepository: SessionRepository
|
||||
|
||||
@Mock
|
||||
lateinit var errorHandler: ErrorHandler
|
||||
@ -30,15 +30,15 @@ class SplashPresenterTest {
|
||||
|
||||
@Test
|
||||
fun testOpenLoginView() {
|
||||
doReturn(false).`when`(studentRepository).isStudentLoggedIn
|
||||
doReturn(false).`when`(studentRepository).isSessionSaved
|
||||
presenter.attachView(splashView)
|
||||
verify(splashView).openLoginActivity()
|
||||
verify(splashView).openLoginView()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMainMainView() {
|
||||
doReturn(true).`when`(studentRepository).isStudentLoggedIn
|
||||
doReturn(true).`when`(studentRepository).isSessionSaved
|
||||
presenter.attachView(splashView)
|
||||
verify(splashView).openMainActivity()
|
||||
verify(splashView).openMainView()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -86,55 +86,55 @@ class TimeUtilsTest {
|
||||
}
|
||||
|
||||
@Test fun isHolidaysInSchoolEndTest() {
|
||||
assertFalse(isHolidays(LocalDate.of(2017, 6, 23), 2017))
|
||||
assertFalse(isHolidays(LocalDate.of(2018, 6, 22), 2018))
|
||||
assertFalse(isHolidays(LocalDate.of(2019, 6, 21), 2019))
|
||||
assertFalse(isHolidays(LocalDate.of(2020, 6, 26), 2020))
|
||||
assertFalse(isHolidays(LocalDate.of(2021, 6, 25), 2021))
|
||||
assertFalse(isHolidays(LocalDate.of(2022, 6, 24), 2022))
|
||||
assertFalse(isHolidays(LocalDate.of(2023, 6, 23), 2023))
|
||||
assertFalse(isHolidays(LocalDate.of(2024, 6, 21), 2024))
|
||||
assertFalse(isHolidays(LocalDate.of(2025, 6, 27), 2025))
|
||||
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), 2017))
|
||||
assertTrue(isHolidays(LocalDate.of(2018, 6, 23), 2018))
|
||||
assertTrue(isHolidays(LocalDate.of(2019, 6, 22), 2019))
|
||||
assertTrue(isHolidays(LocalDate.of(2020, 6, 27), 2020))
|
||||
assertTrue(isHolidays(LocalDate.of(2021, 6, 26), 2021))
|
||||
assertTrue(isHolidays(LocalDate.of(2022, 6, 25), 2022))
|
||||
assertTrue(isHolidays(LocalDate.of(2023, 6, 24), 2023))
|
||||
assertTrue(isHolidays(LocalDate.of(2024, 6, 22), 2024))
|
||||
assertTrue(isHolidays(LocalDate.of(2025, 6, 28), 2025))
|
||||
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), 2017)) // friday
|
||||
assertTrue(isHolidays(LocalDate.of(2017, 9, 2), 2017)) // saturday
|
||||
assertTrue(isHolidays(LocalDate.of(2017, 9, 3), 2017)) // sunday
|
||||
assertTrue(isHolidays(LocalDate.of(2018, 9, 1), 2018)) // saturday
|
||||
assertTrue(isHolidays(LocalDate.of(2018, 9, 2), 2018)) // sunday
|
||||
assertTrue(isHolidays(LocalDate.of(2019, 9, 1), 2019)) // sunday
|
||||
assertTrue(isHolidays(LocalDate.of(2020, 8, 31), 2020)) // monday
|
||||
assertTrue(isHolidays(LocalDate.of(2021, 8, 31), 2021)) // tuesday
|
||||
assertTrue(isHolidays(LocalDate.of(2022, 8, 31), 2022)) // wednesday
|
||||
assertTrue(isHolidays(LocalDate.of(2023, 9, 1), 2023)) // friday
|
||||
assertTrue(isHolidays(LocalDate.of(2023, 9, 2), 2023)) // saturday
|
||||
assertTrue(isHolidays(LocalDate.of(2023, 9, 3), 2023)) // sunday
|
||||
assertTrue(isHolidays(LocalDate.of(2024, 9, 1), 2024)) // sunday
|
||||
assertTrue(isHolidays(LocalDate.of(2025, 8, 31), 2025)) // sunday
|
||||
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), 2017)) // monday
|
||||
assertFalse(isHolidays(LocalDate.of(2018, 9, 3), 2018)) // monday
|
||||
assertFalse(isHolidays(LocalDate.of(2019, 9, 2), 2019)) // monday
|
||||
assertFalse(isHolidays(LocalDate.of(2020, 9, 1), 2020)) // tuesday
|
||||
assertFalse(isHolidays(LocalDate.of(2021, 9, 1), 2021)) // wednesday
|
||||
assertFalse(isHolidays(LocalDate.of(2022, 9, 1), 2022)) // thursday
|
||||
assertFalse(isHolidays(LocalDate.of(2023, 9, 4), 2023)) // monday
|
||||
assertFalse(isHolidays(LocalDate.of(2024, 9, 2), 2024)) // monday
|
||||
assertFalse(isHolidays(LocalDate.of(2025, 9, 1), 2025)) // monday
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.2.61'
|
||||
ext.kotlin_version = '1.2.70'
|
||||
repositories {
|
||||
mavenCentral()
|
||||
google()
|
||||
|
Loading…
x
Reference in New Issue
Block a user