[WIP] trying to implement the student UI
This commit is contained in:
parent
f821406578
commit
7545e6aca9
16 changed files with 234 additions and 57 deletions
|
@ -3,8 +3,8 @@ package com.faraphel.tasks_valider.connectivity.task
|
||||||
import okhttp3.HttpUrl
|
import okhttp3.HttpUrl
|
||||||
import okhttp3.MediaType.Companion.toMediaType
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.RequestBody
|
|
||||||
import okhttp3.RequestBody.Companion.toRequestBody
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
|
import okhttp3.logging.HttpLoggingInterceptor
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,19 +19,21 @@ class TaskClient(
|
||||||
private val baseCookies: List<okhttp3.Cookie> = listOf()
|
private val baseCookies: List<okhttp3.Cookie> = listOf()
|
||||||
) {
|
) {
|
||||||
private val baseUrl = "http://$address:$port"
|
private val baseUrl = "http://$address:$port"
|
||||||
private val client = OkHttpClient().newBuilder().cookieJar(
|
private val client = OkHttpClient().newBuilder()
|
||||||
// TODO(Faraphel): should be moved into another object
|
.cookieJar(
|
||||||
object : okhttp3.CookieJar {
|
// TODO(Faraphel): should be moved into another object
|
||||||
private val cookies = baseCookies.toMutableList() ///< list of cookies
|
object : okhttp3.CookieJar {
|
||||||
|
private val cookies = baseCookies.toMutableList() ///< list of cookies
|
||||||
|
|
||||||
override fun loadForRequest(url: HttpUrl): List<okhttp3.Cookie> {
|
override fun loadForRequest(url: HttpUrl): List<okhttp3.Cookie> {
|
||||||
return this.cookies
|
return this.cookies
|
||||||
|
}
|
||||||
|
override fun saveFromResponse(url: HttpUrl, cookies: List<okhttp3.Cookie>) {
|
||||||
|
this.cookies.addAll(cookies)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
override fun saveFromResponse(url: HttpUrl, cookies: List<okhttp3.Cookie>) {
|
)
|
||||||
this.cookies.addAll(cookies)
|
.build()
|
||||||
}
|
|
||||||
}
|
|
||||||
).build()
|
|
||||||
|
|
||||||
// TODO(Faraphel): automatically convert content to the correct type ?
|
// TODO(Faraphel): automatically convert content to the correct type ?
|
||||||
|
|
||||||
|
@ -83,7 +85,7 @@ class TaskClient(
|
||||||
this.client.newCall(
|
this.client.newCall(
|
||||||
this.baseRequestBuilder(endpoint)
|
this.baseRequestBuilder(endpoint)
|
||||||
.patch(content.toRequestBody(type.toMediaType()))
|
.patch(content.toRequestBody(type.toMediaType()))
|
||||||
.build()
|
.build()
|
||||||
).execute()
|
).execute()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -96,6 +98,6 @@ class TaskClient(
|
||||||
this.client.newCall(
|
this.client.newCall(
|
||||||
this.baseRequestBuilder(endpoint)
|
this.baseRequestBuilder(endpoint)
|
||||||
.delete(content.toRequestBody(type.toMediaType()))
|
.delete(content.toRequestBody(type.toMediaType()))
|
||||||
.build()
|
.build()
|
||||||
).execute()
|
).execute()
|
||||||
}
|
}
|
|
@ -4,6 +4,11 @@ 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.dao.base.BaseTaskDao
|
||||||
import com.faraphel.tasks_valider.database.entities.ClassEntity
|
import com.faraphel.tasks_valider.database.entities.ClassEntity
|
||||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||||
|
import com.google.gson.reflect.TypeToken
|
||||||
|
|
||||||
class ClassApi(dao: BaseTaskDao<ClassEntity>, session: SessionEntity) :
|
class ClassApi(dao: BaseTaskDao<ClassEntity>, session: SessionEntity) :
|
||||||
BaseTaskApi<ClassEntity>(dao, session)
|
BaseTaskApi<ClassEntity>(
|
||||||
|
dao,
|
||||||
|
object: TypeToken<ClassEntity>() {},
|
||||||
|
session
|
||||||
|
)
|
||||||
|
|
|
@ -4,6 +4,11 @@ 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.dao.base.BaseTaskDao
|
||||||
import com.faraphel.tasks_valider.database.entities.PersonEntity
|
import com.faraphel.tasks_valider.database.entities.PersonEntity
|
||||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||||
|
import com.google.gson.reflect.TypeToken
|
||||||
|
|
||||||
class PersonApi(dao: BaseTaskDao<PersonEntity>, session: SessionEntity) :
|
class PersonApi(dao: BaseTaskDao<PersonEntity>, session: SessionEntity) :
|
||||||
BaseTaskApi<PersonEntity>(dao, session)
|
BaseTaskApi<PersonEntity>(
|
||||||
|
dao,
|
||||||
|
object: TypeToken<PersonEntity>() {},
|
||||||
|
session
|
||||||
|
)
|
||||||
|
|
|
@ -4,7 +4,12 @@ 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.dao.base.BaseTaskDao
|
||||||
import com.faraphel.tasks_valider.database.entities.RelationClassPersonEntity
|
import com.faraphel.tasks_valider.database.entities.RelationClassPersonEntity
|
||||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||||
|
import com.google.gson.reflect.TypeToken
|
||||||
|
|
||||||
|
|
||||||
class RelationClassPersonApi(dao: BaseTaskDao<RelationClassPersonEntity>, session: SessionEntity) :
|
class RelationClassPersonApi(dao: BaseTaskDao<RelationClassPersonEntity>, session: SessionEntity) :
|
||||||
BaseTaskApi<RelationClassPersonEntity>(dao, session)
|
BaseTaskApi<RelationClassPersonEntity>(
|
||||||
|
dao,
|
||||||
|
object: TypeToken<RelationClassPersonEntity>() {},
|
||||||
|
session
|
||||||
|
)
|
||||||
|
|
|
@ -4,7 +4,12 @@ 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.dao.base.BaseTaskDao
|
||||||
import com.faraphel.tasks_valider.database.entities.RelationPersonSessionSubjectEntity
|
import com.faraphel.tasks_valider.database.entities.RelationPersonSessionSubjectEntity
|
||||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||||
|
import com.google.gson.reflect.TypeToken
|
||||||
|
|
||||||
|
|
||||||
class RelationPersonSessionSubjectApi(dao: BaseTaskDao<RelationPersonSessionSubjectEntity>, session: SessionEntity) :
|
class RelationPersonSessionSubjectApi(dao: BaseTaskDao<RelationPersonSessionSubjectEntity>, session: SessionEntity) :
|
||||||
BaseTaskApi<RelationPersonSessionSubjectEntity>(dao, session)
|
BaseTaskApi<RelationPersonSessionSubjectEntity>(
|
||||||
|
dao,
|
||||||
|
object: TypeToken<RelationPersonSessionSubjectEntity>() {},
|
||||||
|
session
|
||||||
|
)
|
||||||
|
|
|
@ -3,6 +3,11 @@ package com.faraphel.tasks_valider.database.api.entities
|
||||||
import com.faraphel.tasks_valider.database.api.entities.base.BaseTaskApi
|
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.dao.base.BaseTaskDao
|
||||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||||
|
import com.google.gson.reflect.TypeToken
|
||||||
|
|
||||||
class SessionApi(dao: BaseTaskDao<SessionEntity>, session: SessionEntity) :
|
class SessionApi(dao: BaseTaskDao<SessionEntity>, session: SessionEntity) :
|
||||||
BaseTaskApi<SessionEntity>(dao, session)
|
BaseTaskApi<SessionEntity>(
|
||||||
|
dao,
|
||||||
|
object: TypeToken<SessionEntity>() {},
|
||||||
|
session
|
||||||
|
)
|
||||||
|
|
|
@ -4,7 +4,12 @@ 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.dao.base.BaseTaskDao
|
||||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||||
import com.faraphel.tasks_valider.database.entities.SubjectEntity
|
import com.faraphel.tasks_valider.database.entities.SubjectEntity
|
||||||
|
import com.google.gson.reflect.TypeToken
|
||||||
|
|
||||||
|
|
||||||
class SubjectApi(dao: BaseTaskDao<SubjectEntity>, session: SessionEntity) :
|
class SubjectApi(dao: BaseTaskDao<SubjectEntity>, session: SessionEntity) :
|
||||||
BaseTaskApi<SubjectEntity>(dao, session)
|
BaseTaskApi<SubjectEntity>(
|
||||||
|
dao,
|
||||||
|
object: TypeToken<SubjectEntity>() {},
|
||||||
|
session
|
||||||
|
)
|
||||||
|
|
|
@ -4,7 +4,12 @@ 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.dao.base.BaseTaskDao
|
||||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||||
import com.faraphel.tasks_valider.database.entities.TaskEntity
|
import com.faraphel.tasks_valider.database.entities.TaskEntity
|
||||||
|
import com.google.gson.reflect.TypeToken
|
||||||
|
|
||||||
|
|
||||||
class TaskApi(dao: BaseTaskDao<TaskEntity>, session: SessionEntity) :
|
class TaskApi(dao: BaseTaskDao<TaskEntity>, session: SessionEntity) :
|
||||||
BaseTaskApi<TaskEntity>(dao, session)
|
BaseTaskApi<TaskEntity>(
|
||||||
|
dao,
|
||||||
|
object: TypeToken<TaskEntity>() {},
|
||||||
|
session
|
||||||
|
)
|
||||||
|
|
|
@ -4,7 +4,12 @@ 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.dao.base.BaseTaskDao
|
||||||
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
import com.faraphel.tasks_valider.database.entities.SessionEntity
|
||||||
import com.faraphel.tasks_valider.database.entities.ValidationEntity
|
import com.faraphel.tasks_valider.database.entities.ValidationEntity
|
||||||
|
import com.google.gson.reflect.TypeToken
|
||||||
|
|
||||||
|
|
||||||
class ValidationApi(dao: BaseTaskDao<ValidationEntity>, session: SessionEntity) :
|
class ValidationApi(dao: BaseTaskDao<ValidationEntity>, session: SessionEntity) :
|
||||||
BaseTaskApi<ValidationEntity>(dao, session)
|
BaseTaskApi<ValidationEntity>(
|
||||||
|
dao,
|
||||||
|
object: TypeToken<ValidationEntity>() {},
|
||||||
|
session
|
||||||
|
)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.faraphel.tasks_valider.database.api.entities.base
|
package com.faraphel.tasks_valider.database.api.entities.base
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import com.faraphel.tasks_valider.database.dao.base.BaseCronDao
|
import com.faraphel.tasks_valider.database.dao.base.BaseCronDao
|
||||||
import com.faraphel.tasks_valider.database.entities.base.BaseEntity
|
import com.faraphel.tasks_valider.database.entities.base.BaseEntity
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
|
@ -11,13 +12,14 @@ import fi.iki.elonen.NanoHTTPD
|
||||||
* This is preconfigured to handle JSON data.
|
* This is preconfigured to handle JSON data.
|
||||||
* @param Entity the entity type to handle
|
* @param Entity the entity type to handle
|
||||||
*/
|
*/
|
||||||
abstract class BaseJsonApi<Entity: BaseEntity>(private val dao: BaseCronDao<Entity>) : BaseApi {
|
abstract class BaseJsonApi<Entity: BaseEntity>(
|
||||||
|
private val dao: BaseCronDao<Entity>,
|
||||||
|
private val entityTypeToken: TypeToken<Entity>,
|
||||||
|
) : BaseApi {
|
||||||
companion object {
|
companion object {
|
||||||
private val parser = Gson() ///< The JSON parser
|
private val parser = Gson() ///< The JSON parser
|
||||||
}
|
}
|
||||||
|
|
||||||
private val entityTypeToken: TypeToken<Entity> = object: TypeToken<Entity>() {} ///< the type of the managed entity
|
|
||||||
|
|
||||||
// Requests
|
// Requests
|
||||||
|
|
||||||
override fun head(httpSession: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
|
override fun head(httpSession: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
|
||||||
|
@ -43,10 +45,16 @@ abstract class BaseJsonApi<Entity: BaseEntity>(private val dao: BaseCronDao<Enti
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun post(httpSession: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
|
override fun post(httpSession: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
|
||||||
|
val data = httpSession.inputStream.bufferedReader().readText()
|
||||||
|
Log.i("post data", "data raw : $data")
|
||||||
|
|
||||||
val obj = parser.fromJson<Entity>(
|
val obj = parser.fromJson<Entity>(
|
||||||
httpSession.inputStream.bufferedReader().readText(),
|
data,
|
||||||
this.entityTypeToken.type
|
this.entityTypeToken.type
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Log.i("post data", "data parsed : $obj")
|
||||||
|
|
||||||
val id = this.dao.insert(obj)
|
val id = this.dao.insert(obj)
|
||||||
|
|
||||||
return NanoHTTPD.newFixedLengthResponse(
|
return NanoHTTPD.newFixedLengthResponse(
|
||||||
|
|
|
@ -14,14 +14,16 @@ import fi.iki.elonen.NanoHTTPD
|
||||||
*/
|
*/
|
||||||
abstract class BaseTaskApi<Entity: BaseEntity>(
|
abstract class BaseTaskApi<Entity: BaseEntity>(
|
||||||
private val dao: BaseTaskDao<Entity>,
|
private val dao: BaseTaskDao<Entity>,
|
||||||
|
private val entityTypeToken: TypeToken<Entity>,
|
||||||
private val session: SessionEntity,
|
private val session: SessionEntity,
|
||||||
) : BaseJsonApi<Entity>(dao) {
|
) : BaseJsonApi<Entity>(
|
||||||
|
dao,
|
||||||
|
entityTypeToken,
|
||||||
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
private val parser = Gson() ///< The JSON parser
|
private val parser = Gson() ///< The JSON parser
|
||||||
}
|
}
|
||||||
|
|
||||||
private val entityTypeToken: TypeToken<Entity> = object: TypeToken<Entity>() {} ///< the type of the managed entity
|
|
||||||
|
|
||||||
// Requests
|
// Requests
|
||||||
|
|
||||||
override fun head(httpSession: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
|
override fun head(httpSession: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package com.faraphel.tasks_valider.ui.screen.communication.internet
|
package com.faraphel.tasks_valider.ui.screen.communication.internet
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
|
import android.os.Build
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
|
@ -19,12 +21,14 @@ import com.faraphel.tasks_valider.ui.screen.communication.RANGE_SERVER_PORT
|
||||||
import com.faraphel.tasks_valider.ui.screen.task.TaskSessionScreen
|
import com.faraphel.tasks_valider.ui.screen.task.TaskSessionScreen
|
||||||
|
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
@Composable
|
@Composable
|
||||||
fun CommunicationInternetClientScreen(activity: Activity) {
|
fun CommunicationInternetClientScreen(activity: Activity) {
|
||||||
val client = remember { mutableStateOf<TaskClient?>(null) }
|
val client = remember { mutableStateOf<TaskClient?>(null) }
|
||||||
|
|
||||||
if (client.value == null) CommunicationInternetClientContent(client)
|
// TODO(Faraphel): fix and get a user
|
||||||
else TaskSessionScreen(activity, client.value!!)
|
// if (client.value == null) CommunicationInternetClientContent(client)
|
||||||
|
// else TaskSessionScreen(activity, client.value!!, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ import com.faraphel.tasks_valider.ui.screen.authentification.AuthentificationSer
|
||||||
import com.faraphel.tasks_valider.ui.screen.communication.DEFAULT_SERVER_PORT
|
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.communication.RANGE_SERVER_PORT
|
||||||
import com.faraphel.tasks_valider.ui.screen.task.TaskSessionScreen
|
import com.faraphel.tasks_valider.ui.screen.task.TaskSessionScreen
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,26 +43,32 @@ fun CommunicationInternetServerScreen(
|
||||||
) {
|
) {
|
||||||
val controller = rememberNavController()
|
val controller = rememberNavController()
|
||||||
|
|
||||||
|
val adminPersonEntityRaw = remember { mutableStateOf<PersonEntity?>(null) }
|
||||||
val adminPersonEntity = remember { mutableStateOf<PersonEntity?>(null) }
|
val adminPersonEntity = remember { mutableStateOf<PersonEntity?>(null) }
|
||||||
val client = remember { mutableStateOf<TaskClient?>(null) }
|
val client = remember { mutableStateOf<TaskClient?>(null) }
|
||||||
|
|
||||||
NavHost(navController = controller, startDestination = "authentication") {
|
NavHost(navController = controller, startDestination = "authentication") {
|
||||||
composable("authentication") {
|
composable("authentication") {
|
||||||
// if the admin person is not created, prompt the user for the admin information
|
// if the admin person is not created, prompt the user for the admin information
|
||||||
if (adminPersonEntity.value == null) AuthentificationServerScreen(adminPersonEntity)
|
if (adminPersonEntityRaw.value == null) AuthentificationServerScreen(adminPersonEntityRaw)
|
||||||
else controller.navigate("configuration")
|
else controller.navigate("configuration")
|
||||||
}
|
}
|
||||||
composable("configuration") {
|
composable("configuration") {
|
||||||
if (client.value == null)
|
if (client.value == null)
|
||||||
CommunicationInternetServerContent(
|
CommunicationInternetServerContent(
|
||||||
database,
|
database,
|
||||||
adminPersonEntity.value!!,
|
adminPersonEntityRaw,
|
||||||
client
|
adminPersonEntity,
|
||||||
|
client,
|
||||||
)
|
)
|
||||||
else controller.navigate("session")
|
else controller.navigate("session")
|
||||||
}
|
}
|
||||||
composable("session") {
|
composable("session") {
|
||||||
TaskSessionScreen(activity, client.value!!)
|
TaskSessionScreen(
|
||||||
|
activity,
|
||||||
|
client.value!!,
|
||||||
|
adminPersonEntity.value!!
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,7 +78,8 @@ fun CommunicationInternetServerScreen(
|
||||||
@Composable
|
@Composable
|
||||||
fun CommunicationInternetServerContent(
|
fun CommunicationInternetServerContent(
|
||||||
database: TaskDatabase,
|
database: TaskDatabase,
|
||||||
adminPersonEntity: PersonEntity,
|
adminPersonEntityRaw: MutableState<PersonEntity?>,
|
||||||
|
adminPersonEntity: MutableState<PersonEntity?>,
|
||||||
client: MutableState<TaskClient?>
|
client: MutableState<TaskClient?>
|
||||||
) {
|
) {
|
||||||
val classes = remember { mutableStateOf<List<ClassEntity>?>(null) }
|
val classes = remember { mutableStateOf<List<ClassEntity>?>(null) }
|
||||||
|
@ -129,16 +137,17 @@ fun CommunicationInternetServerContent(
|
||||||
Button(onClick = {
|
Button(onClick = {
|
||||||
Thread { // a thread is used for networking
|
Thread { // a thread is used for networking
|
||||||
|
|
||||||
// Insert the admin in the database
|
// Insert the admin in the database and get its id
|
||||||
database.personDao().insert(adminPersonEntity)
|
val (adminPersonEntityId) = database.personDao().insert(adminPersonEntityRaw.value!!)
|
||||||
|
adminPersonEntity.value = database.personDao().getById(adminPersonEntityId)!!
|
||||||
|
|
||||||
// Create a new session
|
// Create a new session
|
||||||
// TODO(Faraphel): name
|
// TODO(Faraphel): name
|
||||||
val (sessionId) = database.sessionDao().insert(
|
val (sessionId) = database.sessionDao().insert(
|
||||||
SessionEntity(
|
SessionEntity(
|
||||||
name="NOM",
|
name="NOM",
|
||||||
start=Instant.now(),
|
start=Instant.now(),
|
||||||
classId=selectedClass.value!!.id,
|
classId=selectedClass.value!!.id,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val session = database.sessionDao().getById(sessionId)!!
|
val session = database.sessionDao().getById(sessionId)!!
|
||||||
|
@ -157,7 +166,7 @@ fun CommunicationInternetServerContent(
|
||||||
serverPort.intValue,
|
serverPort.intValue,
|
||||||
database,
|
database,
|
||||||
session,
|
session,
|
||||||
adminPersonEntity,
|
adminPersonEntity.value!!,
|
||||||
)
|
)
|
||||||
server.start()
|
server.start()
|
||||||
|
|
||||||
|
|
|
@ -30,10 +30,11 @@ import com.faraphel.tasks_valider.ui.screen.task.TaskSessionScreen
|
||||||
fun CommunicationWifiP2pServerScreen(activity: Activity, bwfManager: BwfManager) {
|
fun CommunicationWifiP2pServerScreen(activity: Activity, bwfManager: BwfManager) {
|
||||||
val client = remember { mutableStateOf<TaskClient?>(null) }
|
val client = remember { mutableStateOf<TaskClient?>(null) }
|
||||||
|
|
||||||
|
// TODO(Faraphel): fix and get a user
|
||||||
// if the server is not created, prompt the user for the server configuration
|
// if the server is not created, prompt the user for the server configuration
|
||||||
if (client.value == null) CommunicationWifiP2pServerContent(activity, bwfManager, client)
|
// if (client.value == null) CommunicationWifiP2pServerContent(activity, bwfManager, client)
|
||||||
// else, go to the base tasks screen
|
// else, go to the base tasks screen
|
||||||
else TaskSessionScreen(activity, client.value!!)
|
// else TaskSessionScreen(activity, client.value!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package com.faraphel.tasks_valider.ui.screen.task
|
package com.faraphel.tasks_valider.ui.screen.task
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
|
import android.os.Build
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
|
@ -20,8 +22,13 @@ import com.google.gson.reflect.TypeToken
|
||||||
* @param activity the android activity
|
* @param activity the android activity
|
||||||
* @param client an HTTP client that can communicate with the server
|
* @param client an HTTP client that can communicate with the server
|
||||||
*/
|
*/
|
||||||
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
@Composable
|
@Composable
|
||||||
fun TaskSessionScreen(activity: Activity, client: TaskClient) {
|
fun TaskSessionScreen(
|
||||||
|
activity: Activity,
|
||||||
|
client: TaskClient,
|
||||||
|
user: PersonEntity,
|
||||||
|
) {
|
||||||
val students = remember { mutableStateOf<List<PersonEntity>?>(null) }
|
val students = remember { mutableStateOf<List<PersonEntity>?>(null) }
|
||||||
val selectedStudent = remember { mutableStateOf<PersonEntity?>(null) }
|
val selectedStudent = remember { mutableStateOf<PersonEntity?>(null) }
|
||||||
|
|
||||||
|
@ -30,7 +37,12 @@ fun TaskSessionScreen(activity: Activity, client: TaskClient) {
|
||||||
return Thread { refreshStudents(activity, client, students) }.start()
|
return Thread { refreshStudents(activity, client, students) }.start()
|
||||||
|
|
||||||
if (selectedStudent.value != null)
|
if (selectedStudent.value != null)
|
||||||
return TaskStudentScreen(activity, client, selectedStudent.value!!)
|
return TaskStudentScreen(
|
||||||
|
activity,
|
||||||
|
client,
|
||||||
|
user,
|
||||||
|
selectedStudent.value!!
|
||||||
|
)
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
// if the groups have already been defined, display them
|
// if the groups have already been defined, display them
|
||||||
|
@ -44,7 +56,11 @@ fun TaskSessionScreen(activity: Activity, client: TaskClient) {
|
||||||
|
|
||||||
|
|
||||||
// TODO(Faraphel): template this function ?
|
// TODO(Faraphel): template this function ?
|
||||||
fun refreshStudents(activity: Activity, client: TaskClient, students: MutableState<List<PersonEntity>?>) {
|
fun refreshStudents(
|
||||||
|
activity: Activity,
|
||||||
|
client: TaskClient,
|
||||||
|
students: MutableState<List<PersonEntity>?>
|
||||||
|
) {
|
||||||
// TODO(Faraphel): global variable ?
|
// TODO(Faraphel): global variable ?
|
||||||
val jsonParser = Gson()
|
val jsonParser = Gson()
|
||||||
|
|
||||||
|
|
|
@ -1,49 +1,103 @@
|
||||||
package com.faraphel.tasks_valider.ui.screen.task
|
package com.faraphel.tasks_valider.ui.screen.task
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
|
import android.os.Build
|
||||||
|
import android.util.Log
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.Checkbox
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import com.faraphel.tasks_valider.connectivity.task.TaskClient
|
import com.faraphel.tasks_valider.connectivity.task.TaskClient
|
||||||
|
import com.faraphel.tasks_valider.connectivity.task.session.TaskPermission
|
||||||
import com.faraphel.tasks_valider.database.entities.*
|
import com.faraphel.tasks_valider.database.entities.*
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.google.gson.reflect.TypeToken
|
import com.google.gson.reflect.TypeToken
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This screen represent a student
|
* This screen represent a student
|
||||||
* @param student the student object
|
* @param student the student object
|
||||||
*/
|
*/
|
||||||
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
@Composable
|
@Composable
|
||||||
fun TaskStudentScreen(activity: Activity, client: TaskClient, student: PersonEntity) {
|
fun TaskStudentScreen(
|
||||||
|
activity: Activity,
|
||||||
|
client: TaskClient,
|
||||||
|
user: PersonEntity,
|
||||||
|
student: PersonEntity,
|
||||||
|
) {
|
||||||
val tasks = remember { mutableStateOf<List<TaskEntity>?>(null) }
|
val tasks = remember { mutableStateOf<List<TaskEntity>?>(null) }
|
||||||
|
val validations = remember { mutableStateOf<List<ValidationEntity>?>(null) }
|
||||||
|
|
||||||
if (tasks.value == null)
|
if (tasks.value == null || validations.value == null)
|
||||||
Thread { refreshTasks(activity, client, student, tasks) }.start()
|
Thread {
|
||||||
|
refreshTasksValidations(
|
||||||
|
activity,
|
||||||
|
client,
|
||||||
|
student,
|
||||||
|
tasks,
|
||||||
|
validations
|
||||||
|
)
|
||||||
|
}.start()
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
Text(text = student.fullName())
|
Text(text = student.fullName())
|
||||||
|
|
||||||
tasks.value?.forEach { task ->
|
// if both the list of tasks and validations are loaded
|
||||||
Button(onClick = {}) {
|
if (!(tasks.value == null || validations.value == null)) {
|
||||||
Column {
|
tasks.value?.forEach { task ->
|
||||||
Text(task.title)
|
// get the validation
|
||||||
task.description?.let { description -> Text(description) }
|
val validation = validations.value!!.firstOrNull { validation -> validation.taskId == task.id }
|
||||||
|
|
||||||
|
Button(onClick = {}) {
|
||||||
|
Row {
|
||||||
|
Column {
|
||||||
|
// task title
|
||||||
|
Text(task.title)
|
||||||
|
// task description
|
||||||
|
task.description?.let { description -> Text(description) }
|
||||||
|
// if the task have been validated, show the date
|
||||||
|
if (validation != null) Text(validation.date.toString())
|
||||||
|
}
|
||||||
|
// the validation state
|
||||||
|
Checkbox(
|
||||||
|
checked = validation != null,
|
||||||
|
enabled = user.role.permissions.contains(TaskPermission.WRITE),
|
||||||
|
onCheckedChange = { state ->
|
||||||
|
Thread {
|
||||||
|
updateValidation(
|
||||||
|
client,
|
||||||
|
state,
|
||||||
|
validation ?: ValidationEntity(
|
||||||
|
Instant.now(),
|
||||||
|
user.id,
|
||||||
|
student.id,
|
||||||
|
task.id,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}.start()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun refreshTasks(
|
fun refreshTasksValidations(
|
||||||
activity: Activity,
|
activity: Activity,
|
||||||
client: TaskClient,
|
client: TaskClient,
|
||||||
student: PersonEntity,
|
student: PersonEntity,
|
||||||
tasks: MutableState<List<TaskEntity>?>
|
tasks: MutableState<List<TaskEntity>?>,
|
||||||
|
validations: MutableState<List<ValidationEntity>?>,
|
||||||
) {
|
) {
|
||||||
val jsonParser = Gson()
|
val jsonParser = Gson()
|
||||||
|
|
||||||
|
@ -86,4 +140,45 @@ fun refreshTasks(
|
||||||
}.sortedBy { task ->
|
}.sortedBy { task ->
|
||||||
task.order
|
task.order
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// try to obtain the list of validations
|
||||||
|
val responseValidations = client.get("entities/" + ValidationEntity.TABLE_NAME)
|
||||||
|
|
||||||
|
// in case of error, notify it
|
||||||
|
if (!responseValidations.isSuccessful)
|
||||||
|
return activity.runOnUiThread { Toast.makeText(activity, responseTasks.message, Toast.LENGTH_LONG).show() }
|
||||||
|
|
||||||
|
// parse the list of validations
|
||||||
|
val allValidations = jsonParser.fromJson<List<ValidationEntity>>(
|
||||||
|
responseValidations.body.string(),
|
||||||
|
object : TypeToken<List<ValidationEntity>>(){}.type
|
||||||
|
)
|
||||||
|
|
||||||
|
// filter only the interesting validations
|
||||||
|
validations.value = allValidations.filter { validation ->
|
||||||
|
validation.studentId == student.id &&
|
||||||
|
validation.taskId in allTasks.map { task -> task.id }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun updateValidation(client: TaskClient, checked: Boolean, validation: ValidationEntity) {
|
||||||
|
val jsonParser = Gson()
|
||||||
|
|
||||||
|
if (checked) {
|
||||||
|
// if the validation is not set, create it
|
||||||
|
client.post(
|
||||||
|
"entities/" + ValidationEntity.TABLE_NAME,
|
||||||
|
jsonParser.toJson(validation),
|
||||||
|
"application/json"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// if the validation is set, delete it
|
||||||
|
client.delete(
|
||||||
|
"entities/" + ValidationEntity.TABLE_NAME,
|
||||||
|
jsonParser.toJson(validation),
|
||||||
|
"application/json"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue