From be801d5b31efabb4a314517bcf4c938c84773922 Mon Sep 17 00:00:00 2001 From: Faraphel Date: Tue, 28 May 2024 12:53:34 +0200 Subject: [PATCH] [WIP] - Base for session and student view in the UI --- .../database/api/TaskDatabaseApi.kt | 8 +- .../database/entities/TaskEntity.kt | 1 + .../faraphel/tasks_valider/database/test.kt | 117 ++++++++++++++++++ .../internet/{client/screen.kt => client.kt} | 2 +- .../communication/internet/selection.kt | 2 - .../internet/{server/screen.kt => server.kt} | 10 +- .../tasks_valider/ui/screen/task/screen.kt | 67 ---------- .../tasks_valider/ui/screen/task/session.kt | 63 ++++++++++ .../tasks_valider/ui/screen/task/student.kt | 14 +++ 9 files changed, 208 insertions(+), 76 deletions(-) create mode 100644 app/src/main/java/com/faraphel/tasks_valider/database/test.kt rename app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/internet/{client/screen.kt => client.kt} (99%) rename app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/internet/{server/screen.kt => server.kt} (93%) delete mode 100644 app/src/main/java/com/faraphel/tasks_valider/ui/screen/task/screen.kt create mode 100644 app/src/main/java/com/faraphel/tasks_valider/ui/screen/task/session.kt create mode 100644 app/src/main/java/com/faraphel/tasks_valider/ui/screen/task/student.kt diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/api/TaskDatabaseApi.kt b/app/src/main/java/com/faraphel/tasks_valider/database/api/TaskDatabaseApi.kt index 84ca7c0..90312e4 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/database/api/TaskDatabaseApi.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/database/api/TaskDatabaseApi.kt @@ -61,7 +61,7 @@ class TaskDatabaseApi(private val database: TaskDatabase) { // TODO(Faraphel): should only be allowed to read data concerning the current class session NanoHTTPD.Method.HEAD -> { // check the permission of the session - if (taskSession.person.role.permissions.contains(TaskPermission.READ)) + if (!taskSession.person.role.permissions.contains(TaskPermission.READ)) return NanoHTTPD.newFixedLengthResponse( NanoHTTPD.Response.Status.FORBIDDEN, "text/plain", @@ -73,7 +73,7 @@ class TaskDatabaseApi(private val database: TaskDatabase) { // get the data from the database NanoHTTPD.Method.GET -> { // check the permission of the session - if (taskSession.person.role.permissions.contains(TaskPermission.READ)) + if (!taskSession.person.role.permissions.contains(TaskPermission.READ)) return NanoHTTPD.newFixedLengthResponse( NanoHTTPD.Response.Status.FORBIDDEN, "text/plain", @@ -85,7 +85,7 @@ class TaskDatabaseApi(private val database: TaskDatabase) { // insert the data into the database NanoHTTPD.Method.POST -> { // check the permission of the session - if (taskSession.person.role.permissions.contains(TaskPermission.WRITE)) + if (!taskSession.person.role.permissions.contains(TaskPermission.WRITE)) return NanoHTTPD.newFixedLengthResponse( NanoHTTPD.Response.Status.FORBIDDEN, "text/plain", @@ -97,7 +97,7 @@ class TaskDatabaseApi(private val database: TaskDatabase) { // delete the data from the database NanoHTTPD.Method.DELETE -> { // check the permission of the session - if (taskSession.person.role.permissions.contains(TaskPermission.WRITE)) + if (!taskSession.person.role.permissions.contains(TaskPermission.WRITE)) return NanoHTTPD.newFixedLengthResponse( NanoHTTPD.Response.Status.FORBIDDEN, "text/plain", diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/entities/TaskEntity.kt b/app/src/main/java/com/faraphel/tasks_valider/database/entities/TaskEntity.kt index 4548c36..255fce3 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/database/entities/TaskEntity.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/database/entities/TaskEntity.kt @@ -21,6 +21,7 @@ data class TaskEntity ( @ColumnInfo("id") @PrimaryKey(autoGenerate = true) val id: Long = 0, @ColumnInfo("title") val title: String, @ColumnInfo("description") val description: String? = null, + @ColumnInfo("order") val order: Int, ///< the order of the task in the list of the subject @ColumnInfo("subject_id", index = true) val subjectId: Long, ) : BaseEntity() { diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/test.kt b/app/src/main/java/com/faraphel/tasks_valider/database/test.kt new file mode 100644 index 0000000..22b5f02 --- /dev/null +++ b/app/src/main/java/com/faraphel/tasks_valider/database/test.kt @@ -0,0 +1,117 @@ +package com.faraphel.tasks_valider.database + +import com.faraphel.tasks_valider.connectivity.task.session.TaskRole +import com.faraphel.tasks_valider.database.entities.* + +fun populateTaskDatabaseTest(database: TaskDatabase) { + // classes + val ( + classMiageId, + classIsriId, + ) = database.classDao().insert( + ClassEntity(name="MIAGE"), + ClassEntity(name="ISRI") + ) + + val classMiage = database.classDao().getById(classMiageId)!! + val classIrsi = database.classDao().getById(classIsriId)!! + + // persons + val ( + personBillyId, + personBobbyId, + personBettyId, + ) = database.personDao().insert( + PersonEntity( + "Billy", "Bob", + null, + "1234", + TaskRole.STUDENT + ), + PersonEntity( + "Bobby", "Bob", + null, + "1234", + TaskRole.STUDENT + ), + PersonEntity( + "Betty", "Bob", + null, + "1234", + TaskRole.STUDENT + ) + ) + + val personBilly = database.personDao().getById(personBillyId)!! + val personBobby = database.personDao().getById(personBobbyId)!! + val personBetty = database.personDao().getById(personBettyId)!! + + // relations class <=> persons + database.relationClassPersonDao().insert( + RelationClassPersonEntity(personBobby.id, classMiage.id), + RelationClassPersonEntity(personBilly.id, classMiage.id), + RelationClassPersonEntity(personBetty.id, classIrsi.id), + ) + + // subjects + val ( + subjectAId, + subjectBId + ) = database.subjectDao().insert( + SubjectEntity( + name="Type A" + ), + SubjectEntity( + name="Type B" + ) + ) + + val subjectA = database.subjectDao().getById(subjectAId)!! + val subjectB = database.subjectDao().getById(subjectBId)!! + + // tasks + val ( + taskA1Id, + taskA2Id, + taskA3Id, + taskB1Id, + taskB2Id, + ) = database.taskDao().insert( + TaskEntity( + title = "Commencer A", + description = "Description 1", + order = 1, + subjectId = subjectA.id, + ), + TaskEntity( + title = "Continuer A", + description = "Description 2", + order = 2, + subjectId = subjectA.id + ), + TaskEntity( + title = "Finir A", + description = "Description 3", + order = 3, + subjectId = subjectA.id + ), + TaskEntity( + title = "Commencer B", + description = "Description 1", + order = 1, + subjectId = subjectB.id, + ), + TaskEntity( + title = "Finir B", + description = "Description 2", + order = 2, + subjectId = subjectB.id, + ) + ) + + val taskA1 = database.taskDao().getById(taskA1Id)!! + val taskA2 = database.taskDao().getById(taskA2Id)!! + val taskA3 = database.taskDao().getById(taskA3Id)!! + val taskB1 = database.taskDao().getById(taskB1Id)!! + val taskB2 = database.taskDao().getById(taskB2Id)!! +} \ No newline at end of file diff --git a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/internet/client/screen.kt b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/internet/client.kt similarity index 99% rename from app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/internet/client/screen.kt rename to app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/internet/client.kt index 2cc75b7..5c0e98f 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/internet/client/screen.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/internet/client.kt @@ -1,4 +1,4 @@ -package com.faraphel.tasks_valider.ui.screen.communication.internet.client +package com.faraphel.tasks_valider.ui.screen.communication.internet import android.app.Activity import androidx.compose.foundation.layout.Column diff --git a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/internet/selection.kt b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/internet/selection.kt index 262be98..085df9f 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/internet/selection.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/internet/selection.kt @@ -9,8 +9,6 @@ import androidx.navigation.NavController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController -import com.faraphel.tasks_valider.ui.screen.communication.internet.client.CommunicationInternetClientScreen -import com.faraphel.tasks_valider.ui.screen.communication.internet.server.CommunicationInternetServerScreen @Composable diff --git a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/internet/server/screen.kt b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/internet/server.kt similarity index 93% rename from app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/internet/server/screen.kt rename to app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/internet/server.kt index e4b888d..dc6c275 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/internet/server/screen.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/internet/server.kt @@ -1,4 +1,4 @@ -package com.faraphel.tasks_valider.ui.screen.communication.internet.server +package com.faraphel.tasks_valider.ui.screen.communication.internet import android.app.Activity import android.util.Log @@ -19,7 +19,9 @@ import androidx.room.Room 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.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 @@ -72,6 +74,7 @@ fun CommunicationInternetServerContent( expanded = expandedStudentList.value, onDismissRequest = { expandedStudentList.value = false } ) { + // TODO(Faraphel): student lists should be loaded from the database or a file DropdownMenuItem( text = { Text("ISRI") }, onClick = {} @@ -80,7 +83,6 @@ fun CommunicationInternetServerContent( text = { Text("MIAGE") }, onClick = {} ) - // TODO(Faraphel): student lists should be loaded from the database or a file } // server port @@ -107,6 +109,10 @@ fun CommunicationInternetServerContent( "local" ).build() + // Populate the database with test data + // TODO(Faraphel): remove test data + populateTaskDatabaseTest(database) + // Insert the admin in the database database.personDao().insert(adminPersonEntity) diff --git a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/task/screen.kt b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/task/screen.kt deleted file mode 100644 index 0469c38..0000000 --- a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/task/screen.kt +++ /dev/null @@ -1,67 +0,0 @@ -package com.faraphel.tasks_valider.ui.screen.task - -import android.app.Activity -import android.widget.Toast -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -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.connectivity.task.session.TaskSession -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken - - -/** - * This screen represent a session - * @param activity the android activity - * @param client an HTTP client that can communicate with the server - */ -@Composable -fun TaskSessionScreen(activity: Activity, client: TaskClient) { - Text("WIP : Session Screen") - - val session = remember { mutableStateOf(null) } - - if (session.value == null) - return Thread { refreshGroups(activity, client, session) }.start() - - Text("Session: ${session.value!!}") - - /* - val students = remember { mutableStateOf?>(null) } - - // title - Text(text = "Task Group") - - // if the groups are not yet defined, refresh the list - if (groups.value == null) { - Thread { refreshGroups(activity, client, groups) }.start() - return - } - - // if the groups have already been defined, display them - for (group in groups.value!!) { - Text(text = group.toString()) - } - */ -} - - -fun refreshGroups(activity: Activity, client: TaskClient, session: MutableState) { - val jsonParser = Gson() - - // try to obtain the list of groups - val response = client.get("sessions/self") - - // in case of error, notify it - if (!response.isSuccessful) - return activity.runOnUiThread { Toast.makeText(activity, response.message, Toast.LENGTH_LONG).show() } - - // parse the list of groups - session.value = jsonParser.fromJson( - response.body.string(), - object : TypeToken(){}.type - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/task/session.kt b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/task/session.kt new file mode 100644 index 0000000..c77eefc --- /dev/null +++ b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/task/session.kt @@ -0,0 +1,63 @@ +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 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.PersonEntity +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + + +/** + * This screen represent a session + * @param activity the android activity + * @param client an HTTP client that can communicate with the server + */ +@Composable +fun TaskSessionScreen(activity: Activity, client: TaskClient) { + val students = remember { mutableStateOf?>(null) } + val selected_student = remember { mutableStateOf(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!!) + + Column { + // if the groups have already been defined, display them + for (student in students.value!!) { + Button(onClick = { selected_student.value = student }) { + Text(text = student.fullName()) + } + } + } +} + + +// TODO(Faraphel): template this function ? +fun refreshStudents(activity: Activity, client: TaskClient, students: MutableState?>) { + // TODO(Faraphel): global variable ? + val jsonParser = Gson() + + // try to obtain the list of groups + val response = client.get("entities/" + PersonEntity.TABLE_NAME) + + // in case of error, notify it + if (!response.isSuccessful) + return activity.runOnUiThread { Toast.makeText(activity, response.message, Toast.LENGTH_LONG).show() } + + // parse the list of groups + students.value = jsonParser.fromJson( + response.body.string(), + object : TypeToken>(){}.type + ) +} diff --git a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/task/student.kt b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/task/student.kt new file mode 100644 index 0000000..1fffe77 --- /dev/null +++ b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/task/student.kt @@ -0,0 +1,14 @@ +package com.faraphel.tasks_valider.ui.screen.task + +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import com.faraphel.tasks_valider.database.entities.PersonEntity + +/** + * This screen represent a student + * @param student the student object + */ +@Composable +fun TaskStudentScreen(student: PersonEntity) { + Text(text = student.fullName()) +}