cards #8
35 changed files with 583 additions and 151 deletions
|
@ -76,4 +76,5 @@ dependencies {
|
|||
debugImplementation("androidx.compose.ui:ui-tooling")
|
||||
debugImplementation("androidx.compose.ui:ui-test-manifest")
|
||||
ksp("androidx.room:room-compiler:2.6.1")
|
||||
implementation(kotlin("reflect"))
|
||||
}
|
||||
|
|
|
@ -6,24 +6,42 @@ import android.os.Bundle
|
|||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.room.Room
|
||||
import com.faraphel.tasks_valider.connectivity.bwf.BwfManager
|
||||
import com.faraphel.tasks_valider.database.TaskDatabase
|
||||
import com.faraphel.tasks_valider.database.populateTaskDatabaseTest
|
||||
import com.faraphel.tasks_valider.ui.screen.communication.CommunicationModeSelectionScreen
|
||||
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
private var bwfManager: BwfManager? = null ///< the WiFi-Direct helper
|
||||
|
||||
companion object {
|
||||
private lateinit var database: TaskDatabase ///< the database manager
|
||||
}
|
||||
private lateinit var database: TaskDatabase ///< the database manager
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
// Reset the database | TODO(Faraphel): only for testing purpose
|
||||
this.deleteDatabase("local")
|
||||
|
||||
// Create the database
|
||||
this.database = Room.databaseBuilder(
|
||||
this,
|
||||
TaskDatabase::class.java,
|
||||
"local"
|
||||
).build()
|
||||
|
||||
// Populate the database with test data
|
||||
// TODO(Faraphel): remove test data
|
||||
Thread {
|
||||
populateTaskDatabaseTest(database)
|
||||
}.let { thread ->
|
||||
thread.start()
|
||||
thread.join()
|
||||
}
|
||||
|
||||
this.setContent {
|
||||
CommunicationModeSelectionScreen(this)
|
||||
CommunicationModeSelectionScreen(this, database)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.faraphel.tasks_valider.connectivity.task
|
|||
import okhttp3.HttpUrl
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
|
||||
|
||||
|
|
|
@ -5,21 +5,25 @@ import com.faraphel.tasks_valider.connectivity.task.session.TaskSessionManager
|
|||
import com.faraphel.tasks_valider.database.TaskDatabase
|
||||
import com.faraphel.tasks_valider.database.api.TaskDatabaseApi
|
||||
import com.faraphel.tasks_valider.database.entities.PersonEntity
|
||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||
import fi.iki.elonen.NanoHTTPD
|
||||
|
||||
|
||||
/**
|
||||
* A server to handle the task API to allow clients to interact with the database.
|
||||
* @param port the port of the server
|
||||
* @param database the database to interact with
|
||||
* @param port the port of the server.
|
||||
* @param database the database to interact with.
|
||||
* @param session the current session.
|
||||
* @param adminPersonEntity the person that represent the host of the session.
|
||||
*/
|
||||
class TaskServer(
|
||||
private val port: Int,
|
||||
private val database: TaskDatabase,
|
||||
adminPersonEntity: PersonEntity,
|
||||
private val session: SessionEntity,
|
||||
private val adminPersonEntity: PersonEntity,
|
||||
) : NanoHTTPD(port) {
|
||||
private val sessionManager = TaskSessionManager(adminPersonEntity) ///< the session manager
|
||||
private val databaseApi = TaskDatabaseApi(this.database) ///< the api of the database
|
||||
private val databaseApi = TaskDatabaseApi(this.database, session) ///< the api of the database
|
||||
private val sessionManagerApi = TaskSessionManagerApi(this.sessionManager, this.database) ///< the api of the session manager
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,6 +22,7 @@ import com.faraphel.tasks_valider.database.entities.*
|
|||
ValidationEntity::class,
|
||||
|
||||
RelationClassPersonEntity::class,
|
||||
RelationPersonSessionSubjectEntity::class,
|
||||
],
|
||||
version = 1
|
||||
)
|
||||
|
@ -37,4 +38,5 @@ abstract class TaskDatabase: RoomDatabase() {
|
|||
abstract fun validationDao(): ValidationDao
|
||||
|
||||
abstract fun relationClassPersonDao(): RelationClassPersonDao
|
||||
abstract fun relationPersonSessionSubjectDao(): RelationPersonSessionSubjectDao
|
||||
}
|
||||
|
|
|
@ -8,16 +8,20 @@ import com.faraphel.tasks_valider.database.api.entities.base.BaseApi
|
|||
import com.faraphel.tasks_valider.database.entities.*
|
||||
import fi.iki.elonen.NanoHTTPD
|
||||
|
||||
class TaskDatabaseApi(private val database: TaskDatabase) {
|
||||
class TaskDatabaseApi(
|
||||
private val database: TaskDatabase,
|
||||
private val session: SessionEntity,
|
||||
) {
|
||||
private val api: Map<String, BaseApi> = mapOf(
|
||||
ClassEntity.TABLE_NAME to ClassApi(this.database.classDao()),
|
||||
PersonEntity.TABLE_NAME to PersonApi(this.database.personDao()),
|
||||
SessionEntity.TABLE_NAME to SessionApi(this.database.sessionDao()),
|
||||
SubjectEntity.TABLE_NAME to SubjectApi(this.database.subjectDao()),
|
||||
TaskEntity.TABLE_NAME to TaskApi(this.database.taskDao()),
|
||||
ValidationEntity.TABLE_NAME to ValidationApi(this.database.validationDao()),
|
||||
ClassEntity.TABLE_NAME to ClassApi(this.database.classDao(), session),
|
||||
PersonEntity.TABLE_NAME to PersonApi(this.database.personDao(), session),
|
||||
SessionEntity.TABLE_NAME to SessionApi(this.database.sessionDao(), session),
|
||||
SubjectEntity.TABLE_NAME to SubjectApi(this.database.subjectDao(), session),
|
||||
TaskEntity.TABLE_NAME to TaskApi(this.database.taskDao(), session),
|
||||
ValidationEntity.TABLE_NAME to ValidationApi(this.database.validationDao(), session),
|
||||
|
||||
RelationClassPersonEntity.TABLE_NAME to RelationClassPersonApi(this.database.relationClassPersonDao()),
|
||||
RelationClassPersonEntity.TABLE_NAME to RelationClassPersonApi(this.database.relationClassPersonDao(), session),
|
||||
RelationPersonSessionSubjectEntity.TABLE_NAME to RelationPersonSessionSubjectApi(this.database.relationPersonSessionSubjectDao(), session),
|
||||
)
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package com.faraphel.tasks_valider.database.api.entities
|
||||
|
||||
import com.faraphel.tasks_valider.database.api.entities.base.BaseJsonApi
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
||||
import com.faraphel.tasks_valider.database.api.entities.base.BaseTaskApi
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
||||
import com.faraphel.tasks_valider.database.entities.ClassEntity
|
||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||
|
||||
class ClassApi(dao: BaseDao<ClassEntity>) : BaseJsonApi<ClassEntity>(dao)
|
||||
class ClassApi(dao: BaseTaskDao<ClassEntity>, session: SessionEntity) :
|
||||
BaseTaskApi<ClassEntity>(dao, session)
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package com.faraphel.tasks_valider.database.api.entities
|
||||
|
||||
import com.faraphel.tasks_valider.database.api.entities.base.BaseJsonApi
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
||||
import com.faraphel.tasks_valider.database.api.entities.base.BaseTaskApi
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
||||
import com.faraphel.tasks_valider.database.entities.PersonEntity
|
||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||
|
||||
class PersonApi(dao: BaseDao<PersonEntity>) : BaseJsonApi<PersonEntity>(dao)
|
||||
class PersonApi(dao: BaseTaskDao<PersonEntity>, session: SessionEntity) :
|
||||
BaseTaskApi<PersonEntity>(dao, session)
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package com.faraphel.tasks_valider.database.api.entities
|
||||
|
||||
import com.faraphel.tasks_valider.database.api.entities.base.BaseJsonApi
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
||||
import com.faraphel.tasks_valider.database.api.entities.base.BaseTaskApi
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
||||
import com.faraphel.tasks_valider.database.entities.RelationClassPersonEntity
|
||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||
|
||||
class RelationClassPersonApi(dao: BaseDao<RelationClassPersonEntity>) : BaseJsonApi<RelationClassPersonEntity>(dao)
|
||||
|
||||
class RelationClassPersonApi(dao: BaseTaskDao<RelationClassPersonEntity>, session: SessionEntity) :
|
||||
BaseTaskApi<RelationClassPersonEntity>(dao, session)
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
package com.faraphel.tasks_valider.database.api.entities
|
||||
|
||||
import com.faraphel.tasks_valider.database.api.entities.base.BaseTaskApi
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
||||
import com.faraphel.tasks_valider.database.entities.RelationPersonSessionSubjectEntity
|
||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||
|
||||
|
||||
class RelationPersonSessionSubjectApi(dao: BaseTaskDao<RelationPersonSessionSubjectEntity>, session: SessionEntity) :
|
||||
BaseTaskApi<RelationPersonSessionSubjectEntity>(dao, session)
|
|
@ -1,7 +1,8 @@
|
|||
package com.faraphel.tasks_valider.database.api.entities
|
||||
|
||||
import com.faraphel.tasks_valider.database.api.entities.base.BaseJsonApi
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
||||
import com.faraphel.tasks_valider.database.api.entities.base.BaseTaskApi
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||
|
||||
class SessionApi(dao: BaseDao<SessionEntity>) : BaseJsonApi<SessionEntity>(dao)
|
||||
class SessionApi(dao: BaseTaskDao<SessionEntity>, session: SessionEntity) :
|
||||
BaseTaskApi<SessionEntity>(dao, session)
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package com.faraphel.tasks_valider.database.api.entities
|
||||
|
||||
import com.faraphel.tasks_valider.database.api.entities.base.BaseJsonApi
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
||||
import com.faraphel.tasks_valider.database.api.entities.base.BaseTaskApi
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||
import com.faraphel.tasks_valider.database.entities.SubjectEntity
|
||||
|
||||
class SubjectApi(dao: BaseDao<SubjectEntity>) : BaseJsonApi<SubjectEntity>(dao)
|
||||
|
||||
class SubjectApi(dao: BaseTaskDao<SubjectEntity>, session: SessionEntity) :
|
||||
BaseTaskApi<SubjectEntity>(dao, session)
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package com.faraphel.tasks_valider.database.api.entities
|
||||
|
||||
import com.faraphel.tasks_valider.database.api.entities.base.BaseJsonApi
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
||||
import com.faraphel.tasks_valider.database.api.entities.base.BaseTaskApi
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||
import com.faraphel.tasks_valider.database.entities.TaskEntity
|
||||
|
||||
class TaskApi(dao: BaseDao<TaskEntity>) : BaseJsonApi<TaskEntity>(dao)
|
||||
|
||||
class TaskApi(dao: BaseTaskDao<TaskEntity>, session: SessionEntity) :
|
||||
BaseTaskApi<TaskEntity>(dao, session)
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package com.faraphel.tasks_valider.database.api.entities
|
||||
|
||||
import com.faraphel.tasks_valider.database.api.entities.base.BaseJsonApi
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
||||
import com.faraphel.tasks_valider.database.api.entities.base.BaseTaskApi
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||
import com.faraphel.tasks_valider.database.entities.ValidationEntity
|
||||
|
||||
class ValidationApi(dao: BaseDao<ValidationEntity>) : BaseJsonApi<ValidationEntity>(dao)
|
||||
|
||||
class ValidationApi(dao: BaseTaskDao<ValidationEntity>, session: SessionEntity) :
|
||||
BaseTaskApi<ValidationEntity>(dao, session)
|
||||
|
|
|
@ -10,23 +10,23 @@ interface BaseApi {
|
|||
* Handle the HEAD request
|
||||
* This is used to check if a data exists in the database
|
||||
*/
|
||||
fun head(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response
|
||||
fun head(httpSession: NanoHTTPD.IHTTPSession): NanoHTTPD.Response
|
||||
|
||||
/**
|
||||
* Handle the GET request
|
||||
* This is used to get data from the database
|
||||
* This is used to get all the data of a table from the database
|
||||
*/
|
||||
fun get(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response
|
||||
fun get(httpSession: NanoHTTPD.IHTTPSession): NanoHTTPD.Response
|
||||
|
||||
/**
|
||||
* Handle the POST request
|
||||
* This is used to insert data into the database
|
||||
*/
|
||||
fun post(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response
|
||||
fun post(httpSession: NanoHTTPD.IHTTPSession): NanoHTTPD.Response
|
||||
|
||||
/**
|
||||
* Handle the PUT request
|
||||
* This is used to delete data from the database
|
||||
*/
|
||||
fun delete(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response
|
||||
fun delete(httpSession: NanoHTTPD.IHTTPSession): NanoHTTPD.Response
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
package com.faraphel.tasks_valider.database.api.entities.base
|
||||
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseCronDao
|
||||
import com.faraphel.tasks_valider.database.entities.base.BaseEntity
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
|
@ -11,7 +11,7 @@ import fi.iki.elonen.NanoHTTPD
|
|||
* This is preconfigured to handle JSON data.
|
||||
* @param Entity the entity type to handle
|
||||
*/
|
||||
abstract class BaseJsonApi<Entity: BaseEntity>(private val dao: BaseDao<Entity>) : BaseApi {
|
||||
abstract class BaseJsonApi<Entity: BaseEntity>(private val dao: BaseCronDao<Entity>) : BaseApi {
|
||||
companion object {
|
||||
private val parser = Gson() ///< The JSON parser
|
||||
}
|
||||
|
@ -20,9 +20,9 @@ abstract class BaseJsonApi<Entity: BaseEntity>(private val dao: BaseDao<Entity>)
|
|||
|
||||
// Requests
|
||||
|
||||
override fun head(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
|
||||
override fun head(httpSession: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
|
||||
val obj = parser.fromJson<Entity>(
|
||||
session.inputStream.bufferedReader().readText(),
|
||||
httpSession.inputStream.bufferedReader().readText(),
|
||||
this.entityTypeToken.type
|
||||
)
|
||||
val exists = this.dao.exists(obj)
|
||||
|
@ -34,7 +34,7 @@ abstract class BaseJsonApi<Entity: BaseEntity>(private val dao: BaseDao<Entity>)
|
|||
)
|
||||
}
|
||||
|
||||
override fun get(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
|
||||
override fun get(httpSession: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
|
||||
return NanoHTTPD.newFixedLengthResponse(
|
||||
NanoHTTPD.Response.Status.OK,
|
||||
"application/json",
|
||||
|
@ -42,9 +42,9 @@ abstract class BaseJsonApi<Entity: BaseEntity>(private val dao: BaseDao<Entity>)
|
|||
)
|
||||
}
|
||||
|
||||
override fun post(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
|
||||
override fun post(httpSession: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
|
||||
val obj = parser.fromJson<Entity>(
|
||||
session.inputStream.bufferedReader().readText(),
|
||||
httpSession.inputStream.bufferedReader().readText(),
|
||||
this.entityTypeToken.type
|
||||
)
|
||||
val id = this.dao.insert(obj)
|
||||
|
@ -56,9 +56,9 @@ abstract class BaseJsonApi<Entity: BaseEntity>(private val dao: BaseDao<Entity>)
|
|||
)
|
||||
}
|
||||
|
||||
override fun delete(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
|
||||
override fun delete(httpSession: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
|
||||
val obj = parser.fromJson<Entity>(
|
||||
session.inputStream.bufferedReader().readText(),
|
||||
httpSession.inputStream.bufferedReader().readText(),
|
||||
this.entityTypeToken.type
|
||||
)
|
||||
val count = this.dao.delete(obj)
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
package com.faraphel.tasks_valider.database.api.entities.base
|
||||
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||
import com.faraphel.tasks_valider.database.entities.base.BaseEntity
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import fi.iki.elonen.NanoHTTPD
|
||||
|
||||
/**
|
||||
* A base for the API to handle the database operations.
|
||||
* This is preconfigured to handle data for Task objects.
|
||||
* @param Entity the entity type to handle
|
||||
*/
|
||||
abstract class BaseTaskApi<Entity: BaseEntity>(
|
||||
private val dao: BaseTaskDao<Entity>,
|
||||
private val session: SessionEntity,
|
||||
) : BaseJsonApi<Entity>(dao) {
|
||||
companion object {
|
||||
private val parser = Gson() ///< The JSON parser
|
||||
}
|
||||
|
||||
private val entityTypeToken: TypeToken<Entity> = object: TypeToken<Entity>() {} ///< the type of the managed entity
|
||||
|
||||
// Requests
|
||||
|
||||
override fun head(httpSession: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
|
||||
val obj = parser.fromJson<Entity>(
|
||||
httpSession.inputStream.bufferedReader().readText(),
|
||||
this.entityTypeToken.type
|
||||
)
|
||||
// check if the object is in the object accessible from the session
|
||||
val exists = this.dao.getAllBySession(session.id).contains(obj)
|
||||
|
||||
return NanoHTTPD.newFixedLengthResponse(
|
||||
if (exists) NanoHTTPD.Response.Status.OK else NanoHTTPD.Response.Status.NOT_FOUND,
|
||||
"text/plain",
|
||||
if (exists) "Exists" else "Not found"
|
||||
)
|
||||
}
|
||||
|
||||
override fun get(httpSession: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
|
||||
return NanoHTTPD.newFixedLengthResponse(
|
||||
NanoHTTPD.Response.Status.OK,
|
||||
"application/json",
|
||||
parser.toJson(this.dao.getAllBySession(session.id))
|
||||
)
|
||||
}
|
||||
}
|
|
@ -2,17 +2,27 @@ package com.faraphel.tasks_valider.database.dao
|
|||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseCronDao
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseSessionDao
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
||||
import com.faraphel.tasks_valider.database.entities.ClassEntity
|
||||
import com.faraphel.tasks_valider.database.entities.PersonEntity
|
||||
import com.faraphel.tasks_valider.database.entities.RelationClassPersonEntity
|
||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||
|
||||
@Dao
|
||||
interface ClassDao : BaseDao<ClassEntity> {
|
||||
interface ClassDao : BaseTaskDao<ClassEntity> {
|
||||
@Query("SELECT * FROM ${ClassEntity.TABLE_NAME}")
|
||||
override fun getAll(): List<ClassEntity>
|
||||
|
||||
@Query(
|
||||
"SELECT * FROM ${ClassEntity.TABLE_NAME} " +
|
||||
"JOIN ${SessionEntity.TABLE_NAME} " +
|
||||
"ON ${SessionEntity.TABLE_NAME}.class_id = ${ClassEntity.TABLE_NAME}.id " +
|
||||
"WHERE ${SessionEntity.TABLE_NAME}.id = :sessionId"
|
||||
)
|
||||
override fun getAllBySession(sessionId: Long): List<ClassEntity>
|
||||
|
||||
/**
|
||||
* Get the object from its identifier
|
||||
*/
|
||||
|
@ -31,7 +41,7 @@ interface ClassDao : BaseDao<ClassEntity> {
|
|||
* @param id the id of the class
|
||||
*/
|
||||
@Query(
|
||||
"SELECT * FROM ${PersonEntity.TABLE_NAME} " +
|
||||
"SELECT ${PersonEntity.TABLE_NAME}.* FROM ${PersonEntity.TABLE_NAME} " +
|
||||
"JOIN ${RelationClassPersonEntity.TABLE_NAME} " +
|
||||
"ON ${PersonEntity.TABLE_NAME}.id = ${RelationClassPersonEntity.TABLE_NAME}.student_id " +
|
||||
"WHERE ${RelationClassPersonEntity.TABLE_NAME}.class_id = :id"
|
||||
|
|
|
@ -2,11 +2,13 @@ package com.faraphel.tasks_valider.database.dao
|
|||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseCronDao
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseSessionDao
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
||||
import com.faraphel.tasks_valider.database.entities.*
|
||||
|
||||
@Dao
|
||||
interface PersonDao : BaseDao<PersonEntity> {
|
||||
interface PersonDao : BaseTaskDao<PersonEntity> {
|
||||
@Query("SELECT * FROM ${PersonEntity.TABLE_NAME}")
|
||||
override fun getAll(): List<PersonEntity>
|
||||
|
||||
|
@ -16,6 +18,19 @@ interface PersonDao : BaseDao<PersonEntity> {
|
|||
@Query("SELECT * FROM ${PersonEntity.TABLE_NAME} WHERE id = :id")
|
||||
fun getById(id: Long): PersonEntity?
|
||||
|
||||
@Query(
|
||||
"SELECT * FROM ${PersonEntity.TABLE_NAME} " +
|
||||
"WHERE id IN (" +
|
||||
"SELECT student_id FROM ${RelationClassPersonEntity.TABLE_NAME} " +
|
||||
"JOIN ${ClassEntity.TABLE_NAME} " +
|
||||
"ON ${RelationClassPersonEntity.TABLE_NAME}.class_id = ${ClassEntity.TABLE_NAME}.id " +
|
||||
"JOIN ${SessionEntity.TABLE_NAME} " +
|
||||
"ON ${SessionEntity.TABLE_NAME}.class_id = ${ClassEntity.TABLE_NAME}.id " +
|
||||
"WHERE ${SessionEntity.TABLE_NAME}.id = :sessionId" +
|
||||
")"
|
||||
)
|
||||
override fun getAllBySession(sessionId: Long): List<PersonEntity>
|
||||
|
||||
/**
|
||||
* Allow to get all the classes the person is attending as a student
|
||||
*/
|
||||
|
|
|
@ -2,22 +2,35 @@ package com.faraphel.tasks_valider.database.dao
|
|||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseCronDao
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseSessionDao
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
||||
import com.faraphel.tasks_valider.database.entities.ClassEntity
|
||||
import com.faraphel.tasks_valider.database.entities.RelationClassPersonEntity
|
||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||
|
||||
@Dao
|
||||
interface RelationClassPersonDao : BaseDao<RelationClassPersonEntity> {
|
||||
interface RelationClassPersonDao : BaseTaskDao<RelationClassPersonEntity> {
|
||||
@Query("SELECT * FROM ${RelationClassPersonEntity.TABLE_NAME}")
|
||||
override fun getAll(): List<RelationClassPersonEntity>
|
||||
|
||||
@Query(
|
||||
"SELECT ${RelationClassPersonEntity.TABLE_NAME}.* FROM ${RelationClassPersonEntity.TABLE_NAME} " +
|
||||
"JOIN ${ClassEntity.TABLE_NAME} " +
|
||||
"ON ${RelationClassPersonEntity.TABLE_NAME}.class_id = ${ClassEntity.TABLE_NAME}.id " +
|
||||
"JOIN ${SessionEntity.TABLE_NAME} " +
|
||||
"ON ${SessionEntity.TABLE_NAME}.class_id = ${ClassEntity.TABLE_NAME}.id " +
|
||||
"WHERE ${SessionEntity.TABLE_NAME}.id = :sessionId"
|
||||
)
|
||||
override fun getAllBySession(sessionId: Long): List<RelationClassPersonEntity>
|
||||
|
||||
/**
|
||||
* Get the object from its identifiers
|
||||
*/
|
||||
@Query(
|
||||
"SELECT * FROM ${RelationClassPersonEntity.TABLE_NAME} " +
|
||||
"WHERE " +
|
||||
"class_id = :classId AND " +
|
||||
"student_id = :studentId"
|
||||
"WHERE class_id = :classId " +
|
||||
"AND student_id = :studentId"
|
||||
)
|
||||
fun getById(classId: Long, studentId: Long): RelationClassPersonEntity?
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package com.faraphel.tasks_valider.database.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseCronDao
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseSessionDao
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
||||
import com.faraphel.tasks_valider.database.entities.RelationPersonSessionSubjectEntity
|
||||
|
||||
|
||||
@Dao
|
||||
interface RelationPersonSessionSubjectDao : BaseTaskDao<RelationPersonSessionSubjectEntity> {
|
||||
@Query("SELECT * FROM ${RelationPersonSessionSubjectEntity.TABLE_NAME}")
|
||||
override fun getAll(): List<RelationPersonSessionSubjectEntity>
|
||||
|
||||
@Query(
|
||||
"SELECT * FROM ${RelationPersonSessionSubjectEntity.TABLE_NAME} " +
|
||||
"WHERE session_id = :sessionId"
|
||||
)
|
||||
override fun getAllBySession(sessionId: Long): List<RelationPersonSessionSubjectEntity>
|
||||
|
||||
/**
|
||||
* Get the object from its identifiers
|
||||
*/
|
||||
@Query(
|
||||
"SELECT * FROM ${RelationPersonSessionSubjectEntity.TABLE_NAME} " +
|
||||
"WHERE student_id = :studentId " +
|
||||
"AND session_id = :sessionId " +
|
||||
"AND subject_id = :subjectId"
|
||||
)
|
||||
fun getById(studentId: Long, sessionId: Long, subjectId: Long): RelationPersonSessionSubjectEntity?
|
||||
}
|
|
@ -2,14 +2,20 @@ package com.faraphel.tasks_valider.database.dao
|
|||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseCronDao
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseSessionDao
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
||||
import com.faraphel.tasks_valider.database.entities.ClassEntity
|
||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||
|
||||
@Dao
|
||||
interface SessionDao : BaseDao<SessionEntity> {
|
||||
interface SessionDao : BaseTaskDao<SessionEntity> {
|
||||
@Query("SELECT * FROM ${SessionEntity.TABLE_NAME}")
|
||||
override fun getAll(): List<SessionEntity>
|
||||
|
||||
@Query("SELECT * FROM ${SessionEntity.TABLE_NAME} WHERE id = :sessionId")
|
||||
override fun getAllBySession(sessionId: Long): List<SessionEntity>
|
||||
|
||||
/**
|
||||
* Get the object from its identifier
|
||||
*/
|
||||
|
|
|
@ -2,15 +2,28 @@ package com.faraphel.tasks_valider.database.dao
|
|||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseCronDao
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseSessionDao
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
||||
import com.faraphel.tasks_valider.database.entities.ClassEntity
|
||||
import com.faraphel.tasks_valider.database.entities.RelationPersonSessionSubjectEntity
|
||||
import com.faraphel.tasks_valider.database.entities.SubjectEntity
|
||||
import com.faraphel.tasks_valider.database.entities.TaskEntity
|
||||
|
||||
@Dao
|
||||
interface SubjectDao : BaseDao<SubjectEntity> {
|
||||
interface SubjectDao : BaseTaskDao<SubjectEntity> {
|
||||
@Query("SELECT * FROM ${SubjectEntity.TABLE_NAME}")
|
||||
override fun getAll(): List<SubjectEntity>
|
||||
|
||||
@Query(
|
||||
"SELECT * FROM ${SubjectEntity.TABLE_NAME} " +
|
||||
"WHERE id IN (" +
|
||||
"SELECT subject_id FROM ${RelationPersonSessionSubjectEntity.TABLE_NAME} " +
|
||||
"WHERE session_id = :sessionId" +
|
||||
")"
|
||||
)
|
||||
override fun getAllBySession(sessionId: Long): List<SubjectEntity>
|
||||
|
||||
/**
|
||||
* Get the object from its identifier
|
||||
*/
|
||||
|
|
|
@ -2,15 +2,27 @@ package com.faraphel.tasks_valider.database.dao
|
|||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseCronDao
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseSessionDao
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
||||
import com.faraphel.tasks_valider.database.entities.RelationPersonSessionSubjectEntity
|
||||
import com.faraphel.tasks_valider.database.entities.TaskEntity
|
||||
import com.faraphel.tasks_valider.database.entities.ValidationEntity
|
||||
|
||||
@Dao
|
||||
interface TaskDao : BaseDao<TaskEntity> {
|
||||
interface TaskDao : BaseTaskDao<TaskEntity> {
|
||||
@Query("SELECT * FROM ${TaskEntity.TABLE_NAME}")
|
||||
override fun getAll(): List<TaskEntity>
|
||||
|
||||
@Query(
|
||||
"SELECT * FROM ${TaskEntity.TABLE_NAME} " +
|
||||
"WHERE subject_id IN (" +
|
||||
"SELECT subject_id FROM ${RelationPersonSessionSubjectEntity.TABLE_NAME} " +
|
||||
"WHERE session_id = :sessionId" +
|
||||
")"
|
||||
)
|
||||
override fun getAllBySession(sessionId: Long): List<TaskEntity>
|
||||
|
||||
/**
|
||||
* Get the object from its identifier
|
||||
*/
|
||||
|
|
|
@ -2,14 +2,29 @@ package com.faraphel.tasks_valider.database.dao
|
|||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseDao
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseCronDao
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseSessionDao
|
||||
import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao
|
||||
import com.faraphel.tasks_valider.database.entities.RelationPersonSessionSubjectEntity
|
||||
import com.faraphel.tasks_valider.database.entities.TaskEntity
|
||||
import com.faraphel.tasks_valider.database.entities.ValidationEntity
|
||||
|
||||
@Dao
|
||||
interface ValidationDao : BaseDao<ValidationEntity> {
|
||||
interface ValidationDao : BaseTaskDao<ValidationEntity> {
|
||||
@Query("SELECT * FROM ${ValidationEntity.TABLE_NAME}")
|
||||
override fun getAll(): List<ValidationEntity>
|
||||
|
||||
@Query(
|
||||
"SELECT * FROM ${ValidationEntity.TABLE_NAME} " +
|
||||
"JOIN ${TaskEntity.TABLE_NAME} " +
|
||||
"ON ${ValidationEntity.TABLE_NAME}.task_id = ${TaskEntity.TABLE_NAME}.id " +
|
||||
"WHERE ${TaskEntity.TABLE_NAME}.subject_id IN (" +
|
||||
"SELECT subject_id FROM ${RelationPersonSessionSubjectEntity.TABLE_NAME} " +
|
||||
"WHERE session_id = :sessionId" +
|
||||
")"
|
||||
)
|
||||
override fun getAllBySession(sessionId: Long): List<ValidationEntity>
|
||||
|
||||
/**
|
||||
* Get the object from its identifiers
|
||||
*/
|
||||
|
|
|
@ -3,17 +3,13 @@ package com.faraphel.tasks_valider.database.dao.base
|
|||
import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Update
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A base DAO to handle the database operations.
|
||||
* A base DAO to handle the database operations (CRON).
|
||||
* @param Entity the entity to handle
|
||||
*/
|
||||
interface BaseDao<Entity> {
|
||||
interface BaseCronDao<Entity> {
|
||||
/**
|
||||
* Check if the entities exists in the database.
|
||||
*/
|
|
@ -0,0 +1,11 @@
|
|||
package com.faraphel.tasks_valider.database.dao.base
|
||||
|
||||
/**
|
||||
* The base for a DAO that is inside a session scope.
|
||||
*/
|
||||
interface BaseSessionDao<Entity> {
|
||||
/**
|
||||
* Return all the objects concerned by a session.
|
||||
*/
|
||||
fun getAllBySession(sessionId: Long): List<Entity>
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package com.faraphel.tasks_valider.database.dao.base
|
||||
|
||||
/**
|
||||
* The base for a DAO for the task project.
|
||||
*/
|
||||
interface BaseTaskDao<Entity>: BaseCronDao<Entity>, BaseSessionDao<Entity>
|
|
@ -0,0 +1,48 @@
|
|||
package com.faraphel.tasks_valider.database.entities
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.ForeignKey
|
||||
import com.faraphel.tasks_valider.database.entities.base.BaseEntity
|
||||
|
||||
|
||||
/**
|
||||
* Represent the relation that associate a subject to a person for a specific session.
|
||||
*/
|
||||
@Entity(
|
||||
tableName = RelationPersonSessionSubjectEntity.TABLE_NAME,
|
||||
primaryKeys = [
|
||||
"student_id",
|
||||
"session_id",
|
||||
"subject_id"
|
||||
],
|
||||
foreignKeys = [
|
||||
ForeignKey(
|
||||
entity = PersonEntity::class,
|
||||
parentColumns = ["id"],
|
||||
childColumns = ["student_id"],
|
||||
onDelete = ForeignKey.CASCADE
|
||||
),
|
||||
ForeignKey(
|
||||
entity = SessionEntity::class,
|
||||
parentColumns = ["id"],
|
||||
childColumns = ["session_id"],
|
||||
onDelete = ForeignKey.CASCADE
|
||||
),
|
||||
ForeignKey(
|
||||
entity = SubjectEntity::class,
|
||||
parentColumns = ["id"],
|
||||
childColumns = ["subject_id"],
|
||||
onDelete = ForeignKey.CASCADE
|
||||
),
|
||||
]
|
||||
)
|
||||
data class RelationPersonSessionSubjectEntity (
|
||||
@ColumnInfo("student_id", index = true) val studentId: Long,
|
||||
@ColumnInfo("session_id", index = true) val sessionId: Long,
|
||||
@ColumnInfo("subject_id", index = true) val subjectId: Long,
|
||||
) : BaseEntity() {
|
||||
companion object {
|
||||
const val TABLE_NAME = "relation_person_session_subject"
|
||||
}
|
||||
}
|
|
@ -115,3 +115,19 @@ fun populateTaskDatabaseTest(database: TaskDatabase) {
|
|||
val taskB1 = database.taskDao().getById(taskB1Id)!!
|
||||
val taskB2 = database.taskDao().getById(taskB2Id)!!
|
||||
}
|
||||
|
||||
|
||||
fun populateSubjectSessionPersonTest(database: TaskDatabase, session: SessionEntity) {
|
||||
// get the list of available subjects
|
||||
val subjects = database.subjectDao().getAll()
|
||||
|
||||
// give a random subject to everyone in the session
|
||||
database.personDao().getAllBySession(session.id).forEach { person ->
|
||||
// get a random subject
|
||||
val subject = subjects.random()
|
||||
// insert a new subject for a person for a specific session
|
||||
database.relationPersonSessionSubjectDao().insert(
|
||||
RelationPersonSessionSubjectEntity(person.id, session.id, subject.id)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
package com.faraphel.tasks_valider.ui.screen.communication.internet
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Text
|
||||
|
@ -9,16 +11,18 @@ import androidx.navigation.NavController
|
|||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import com.faraphel.tasks_valider.database.TaskDatabase
|
||||
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
@Composable
|
||||
fun CommunicationInternetSelectScreen(activity: Activity) {
|
||||
fun CommunicationInternetSelectScreen(activity: Activity, database: TaskDatabase) {
|
||||
val controller = rememberNavController()
|
||||
|
||||
NavHost(navController = controller, startDestination = "mode") {
|
||||
composable("mode") { CommunicationInternetSelectContent(controller) }
|
||||
composable("client") { CommunicationInternetClientScreen(activity) }
|
||||
composable("server") { CommunicationInternetServerScreen(activity) }
|
||||
composable("server") { CommunicationInternetServerScreen(activity, database) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,88 +1,114 @@
|
|||
package com.faraphel.tasks_valider.ui.screen.communication.internet
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.DropdownMenu
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextField
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.room.Room
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import com.faraphel.tasks_valider.connectivity.task.TaskClient
|
||||
import com.faraphel.tasks_valider.connectivity.task.TaskServer
|
||||
import com.faraphel.tasks_valider.database.TaskDatabase
|
||||
import com.faraphel.tasks_valider.database.entities.ClassEntity
|
||||
import com.faraphel.tasks_valider.database.entities.PersonEntity
|
||||
import com.faraphel.tasks_valider.database.populateTaskDatabaseTest
|
||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||
import com.faraphel.tasks_valider.database.populateSubjectSessionPersonTest
|
||||
import com.faraphel.tasks_valider.ui.screen.authentification.AuthentificationServerScreen
|
||||
import com.faraphel.tasks_valider.ui.screen.communication.DEFAULT_SERVER_PORT
|
||||
import com.faraphel.tasks_valider.ui.screen.communication.RANGE_SERVER_PORT
|
||||
import com.faraphel.tasks_valider.ui.screen.task.TaskSessionScreen
|
||||
import java.time.Instant
|
||||
|
||||
|
||||
/**
|
||||
* Screen for the host to configure the server
|
||||
*/
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
@Composable
|
||||
fun CommunicationInternetServerScreen(activity: Activity) {
|
||||
fun CommunicationInternetServerScreen(
|
||||
activity: Activity,
|
||||
database: TaskDatabase,
|
||||
) {
|
||||
val controller = rememberNavController()
|
||||
|
||||
val adminPersonEntity = remember { mutableStateOf<PersonEntity?>(null) }
|
||||
|
||||
// if the admin person is not created, prompt the user for the admin information
|
||||
if (adminPersonEntity.value == null) {
|
||||
return AuthentificationServerScreen(adminPersonEntity)
|
||||
}
|
||||
|
||||
val client = remember { mutableStateOf<TaskClient?>(null) }
|
||||
|
||||
// if the client to the server is not created, prompt the user for the server configuration
|
||||
if (client.value == null) {
|
||||
return CommunicationInternetServerContent(
|
||||
activity,
|
||||
adminPersonEntity.value!!,
|
||||
client
|
||||
)
|
||||
NavHost(navController = controller, startDestination = "authentication") {
|
||||
composable("authentication") {
|
||||
// if the admin person is not created, prompt the user for the admin information
|
||||
if (adminPersonEntity.value == null) AuthentificationServerScreen(adminPersonEntity)
|
||||
else controller.navigate("configuration")
|
||||
}
|
||||
composable("configuration") {
|
||||
if (client.value == null)
|
||||
CommunicationInternetServerContent(
|
||||
database,
|
||||
adminPersonEntity.value!!,
|
||||
client
|
||||
)
|
||||
else controller.navigate("session")
|
||||
}
|
||||
composable("session") {
|
||||
TaskSessionScreen(activity, client.value!!)
|
||||
}
|
||||
}
|
||||
|
||||
// otherwise, go to the base tasks screen
|
||||
return TaskSessionScreen(activity, client.value!!)
|
||||
}
|
||||
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
@Composable
|
||||
fun CommunicationInternetServerContent(
|
||||
activity: Activity,
|
||||
database: TaskDatabase,
|
||||
adminPersonEntity: PersonEntity,
|
||||
client: MutableState<TaskClient?>
|
||||
) {
|
||||
val expandedStudentList = remember { mutableStateOf(false) }
|
||||
val classes = remember { mutableStateOf<List<ClassEntity>?>(null) }
|
||||
val selectedClass = remember { mutableStateOf<ClassEntity?>(null) }
|
||||
val areClassesExpanded = remember { mutableStateOf(false) }
|
||||
|
||||
val serverPort = remember { mutableIntStateOf(DEFAULT_SERVER_PORT) }
|
||||
|
||||
LaunchedEffect(true) {
|
||||
// refresh the list of classes
|
||||
Thread { refreshClasses(database, classes) }.start()
|
||||
}
|
||||
|
||||
Column {
|
||||
// student list
|
||||
Button(onClick = { expandedStudentList.value = !expandedStudentList.value }) {
|
||||
Text(text = "Select Students List")
|
||||
// classes
|
||||
Button(onClick = { areClassesExpanded.value = !areClassesExpanded.value }) {
|
||||
Row {
|
||||
Text(text = "Class")
|
||||
// display the selected class, if selected
|
||||
if (selectedClass.value != null)
|
||||
Text(text = selectedClass.value!!.name)
|
||||
}
|
||||
}
|
||||
DropdownMenu(
|
||||
expanded = expandedStudentList.value,
|
||||
onDismissRequest = { expandedStudentList.value = false }
|
||||
expanded = areClassesExpanded.value,
|
||||
onDismissRequest = { areClassesExpanded.value = false }
|
||||
) {
|
||||
// TODO(Faraphel): student lists should be loaded from the database or a file
|
||||
DropdownMenuItem(
|
||||
text = { Text("ISRI") },
|
||||
onClick = {}
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = { Text("MIAGE") },
|
||||
onClick = {}
|
||||
)
|
||||
classes.value?.forEach { class_ ->
|
||||
DropdownMenuItem(
|
||||
text = { Text(class_.name) },
|
||||
onClick = {
|
||||
selectedClass.value = class_
|
||||
areClassesExpanded.value = false
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// server port
|
||||
|
@ -97,35 +123,57 @@ fun CommunicationInternetServerContent(
|
|||
}
|
||||
)
|
||||
|
||||
Button(onClick = {
|
||||
Thread { // a thread is used for networking
|
||||
// Reset the database | TODO(Faraphel): only for testing purpose
|
||||
activity.deleteDatabase("local")
|
||||
// check if a class is selected
|
||||
if (selectedClass.value != null)
|
||||
// button to create the server
|
||||
Button(onClick = {
|
||||
Thread { // a thread is used for networking
|
||||
|
||||
// Create the database
|
||||
val database = Room.databaseBuilder(
|
||||
activity,
|
||||
TaskDatabase::class.java,
|
||||
"local"
|
||||
).build()
|
||||
// Insert the admin in the database
|
||||
database.personDao().insert(adminPersonEntity)
|
||||
|
||||
// Populate the database with test data
|
||||
// TODO(Faraphel): remove test data
|
||||
populateTaskDatabaseTest(database)
|
||||
// Create a new session
|
||||
// TODO(Faraphel): name
|
||||
val (sessionId) = database.sessionDao().insert(
|
||||
SessionEntity(
|
||||
name="NOM",
|
||||
start=Instant.now(),
|
||||
classId=selectedClass.value!!.id,
|
||||
)
|
||||
)
|
||||
val session = database.sessionDao().getById(sessionId)!!
|
||||
|
||||
// Insert the admin in the database
|
||||
database.personDao().insert(adminPersonEntity)
|
||||
// TODO(Faraphel): remove, this is a test function
|
||||
Thread {
|
||||
populateSubjectSessionPersonTest(database, session)
|
||||
}.let { thread ->
|
||||
thread.start()
|
||||
thread.join()
|
||||
}
|
||||
|
||||
// Create the server
|
||||
Log.i("room-server", "creating the server")
|
||||
val server = TaskServer(serverPort.intValue, database, adminPersonEntity)
|
||||
server.start()
|
||||
// Create the server
|
||||
Log.i("room-server", "creating the server")
|
||||
val server = TaskServer(
|
||||
serverPort.intValue,
|
||||
database,
|
||||
session,
|
||||
adminPersonEntity,
|
||||
)
|
||||
server.start()
|
||||
|
||||
// Get the client from the server
|
||||
client.value = server.getAdminClient()
|
||||
}.start()
|
||||
}) {
|
||||
Text("Create")
|
||||
}
|
||||
// Get the client from the server
|
||||
client.value = server.getAdminClient()
|
||||
}.start()
|
||||
}) {
|
||||
Text("Create")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Refresh the list of classes
|
||||
*/
|
||||
fun refreshClasses(database: TaskDatabase, classes: MutableState<List<ClassEntity>?>) {
|
||||
classes.value = database.classDao().getAll()
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package com.faraphel.tasks_valider.ui.screen.communication
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Build
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
|
@ -13,6 +15,7 @@ import androidx.navigation.compose.NavHost
|
|||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import com.faraphel.tasks_valider.connectivity.bwf.BwfManager
|
||||
import com.faraphel.tasks_valider.database.TaskDatabase
|
||||
import com.faraphel.tasks_valider.ui.screen.communication.internet.CommunicationInternetSelectScreen
|
||||
import com.faraphel.tasks_valider.ui.screen.communication.wifiP2p.CommunicationWifiP2pScreen
|
||||
|
||||
|
@ -21,10 +24,13 @@ import com.faraphel.tasks_valider.ui.screen.communication.wifiP2p.CommunicationW
|
|||
* CommunicationController is the main controller for the communication screen.
|
||||
* It is responsible for handling the navigation between the different communication methods.
|
||||
* It is also responsible for initializing the communication methods.
|
||||
*
|
||||
* @param activity: The activity that hosts the communication screen.
|
||||
* @param database: the database.
|
||||
*/
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
@Composable
|
||||
fun CommunicationModeSelectionScreen(activity: Activity) {
|
||||
fun CommunicationModeSelectionScreen(activity: Activity, database: TaskDatabase) {
|
||||
val controller = rememberNavController()
|
||||
|
||||
NavHost(
|
||||
|
@ -35,7 +41,7 @@ fun CommunicationModeSelectionScreen(activity: Activity) {
|
|||
CommunicationSelectContent(controller, activity)
|
||||
}
|
||||
composable("internet") {
|
||||
CommunicationInternetSelectScreen(activity)
|
||||
CommunicationInternetSelectScreen(activity, database)
|
||||
}
|
||||
composable("wifi-p2p") {
|
||||
val bwfManager = BwfManager.fromActivity(activity)
|
||||
|
|
|
@ -23,19 +23,19 @@ import com.google.gson.reflect.TypeToken
|
|||
@Composable
|
||||
fun TaskSessionScreen(activity: Activity, client: TaskClient) {
|
||||
val students = remember { mutableStateOf<List<PersonEntity>?>(null) }
|
||||
val selected_student = remember { mutableStateOf<PersonEntity?>(null) }
|
||||
val selectedStudent = remember { mutableStateOf<PersonEntity?>(null) }
|
||||
|
||||
// if the groups are not yet defined, refresh the list
|
||||
if (students.value == null)
|
||||
return Thread { refreshStudents(activity, client, students) }.start()
|
||||
|
||||
if (selected_student.value != null)
|
||||
return TaskStudentScreen(selected_student.value!!)
|
||||
if (selectedStudent.value != null)
|
||||
return TaskStudentScreen(activity, client, selectedStudent.value!!)
|
||||
|
||||
Column {
|
||||
// if the groups have already been defined, display them
|
||||
for (student in students.value!!) {
|
||||
Button(onClick = { selected_student.value = student }) {
|
||||
Button(onClick = { selectedStudent.value = student }) {
|
||||
Text(text = student.fullName())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,89 @@
|
|||
package com.faraphel.tasks_valider.ui.screen.task
|
||||
|
||||
import android.app.Activity
|
||||
import android.widget.Toast
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.faraphel.tasks_valider.database.entities.PersonEntity
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import com.faraphel.tasks_valider.connectivity.task.TaskClient
|
||||
import com.faraphel.tasks_valider.database.entities.*
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
|
||||
/**
|
||||
* This screen represent a student
|
||||
* @param student the student object
|
||||
*/
|
||||
@Composable
|
||||
fun TaskStudentScreen(student: PersonEntity) {
|
||||
Text(text = student.fullName())
|
||||
fun TaskStudentScreen(activity: Activity, client: TaskClient, student: PersonEntity) {
|
||||
val tasks = remember { mutableStateOf<List<TaskEntity>?>(null) }
|
||||
|
||||
if (tasks.value == null)
|
||||
Thread { refreshTasks(activity, client, student, tasks) }.start()
|
||||
|
||||
Column {
|
||||
Text(text = student.fullName())
|
||||
|
||||
tasks.value?.forEach { task ->
|
||||
Button(onClick = {}) {
|
||||
Column {
|
||||
Text(task.title)
|
||||
task.description?.let { description -> Text(description) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun refreshTasks(
|
||||
activity: Activity,
|
||||
client: TaskClient,
|
||||
student: PersonEntity,
|
||||
tasks: MutableState<List<TaskEntity>?>
|
||||
) {
|
||||
val jsonParser = Gson()
|
||||
|
||||
// try to obtain the list of subject
|
||||
val responseSubjects = client.get("entities/" + RelationPersonSessionSubjectEntity.TABLE_NAME)
|
||||
|
||||
// in case of error, notify it
|
||||
if (!responseSubjects.isSuccessful)
|
||||
return activity.runOnUiThread { Toast.makeText(activity, responseSubjects.message, Toast.LENGTH_LONG).show() }
|
||||
|
||||
// parse the list of subjects
|
||||
val allPersonSessionSubjects = jsonParser.fromJson<List<RelationPersonSessionSubjectEntity>>(
|
||||
responseSubjects.body.string(),
|
||||
object : TypeToken<List<RelationPersonSessionSubjectEntity>>(){}.type
|
||||
)
|
||||
|
||||
// get the subject that the student is using
|
||||
val relationPersonSessionSubjects = allPersonSessionSubjects.firstOrNull { relation -> relation.studentId == student.id }
|
||||
|
||||
if (relationPersonSessionSubjects == null)
|
||||
// TODO(Faraphel): should be able to assign a subject ?
|
||||
return activity.runOnUiThread { Toast.makeText(activity, "No subject assigned", Toast.LENGTH_LONG).show() }
|
||||
|
||||
// try to obtain the list of tasks
|
||||
val responseTasks = client.get("entities/" + TaskEntity.TABLE_NAME)
|
||||
|
||||
// in case of error, notify it
|
||||
if (!responseTasks.isSuccessful)
|
||||
return activity.runOnUiThread { Toast.makeText(activity, responseTasks.message, Toast.LENGTH_LONG).show() }
|
||||
|
||||
// parse the list of subjects
|
||||
val allTasks = jsonParser.fromJson<List<TaskEntity>>(
|
||||
responseTasks.body.string(),
|
||||
object : TypeToken<List<TaskEntity>>(){}.type
|
||||
)
|
||||
|
||||
// get the tasks that are linked to this subject
|
||||
tasks.value = allTasks.filter { task ->
|
||||
task.subjectId == relationPersonSessionSubjects.subjectId
|
||||
}.sortedBy { task ->
|
||||
task.order
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue