cards #8

Merged
faraphel merged 12 commits from cards into main 2024-06-13 15:12:13 +02:00
7 changed files with 77 additions and 45 deletions
Showing only changes of commit 48a3932f64 - Show all commits

View file

@ -4,7 +4,7 @@ import com.faraphel.tasks_valider.connectivity.task.session.TaskPermission
import com.faraphel.tasks_valider.connectivity.task.session.TaskSession
import com.faraphel.tasks_valider.connectivity.task.session.TaskSessionManager
import com.faraphel.tasks_valider.database.TaskDatabase
import com.google.gson.Gson
import com.faraphel.tasks_valider.utils.parser
import com.google.gson.reflect.TypeToken
import fi.iki.elonen.NanoHTTPD
@ -16,8 +16,6 @@ class TaskSessionManagerApi(
private val sessionManager: TaskSessionManager,
private val database: TaskDatabase
) {
private val jsonParser = Gson() ///< the json parser
/**
* Handle a HTTP Api request
* @param taskSession the data of the client session
@ -66,14 +64,14 @@ class TaskSessionManagerApi(
return NanoHTTPD.newFixedLengthResponse(
NanoHTTPD.Response.Status.OK,
"application/json",
jsonParser.toJson(taskSession)
parser.toJson(taskSession)
)
}
// connect the user to the session
NanoHTTPD.Method.POST -> {
// get the user identifiers
val identifiers: Map<String, String> = jsonParser.fromJson(
val identifiers: Map<String, String> = parser.fromJson(
httpSession.inputStream.bufferedReader().readText(),
object : TypeToken<Map<String, String>>() {}.type
)
@ -177,7 +175,7 @@ class TaskSessionManagerApi(
// change a specific client session data
NanoHTTPD.Method.POST -> {
// parse the content of the request
val targetSession = jsonParser.fromJson(
val targetSession = parser.fromJson(
httpSession.inputStream.bufferedReader().readText(),
TaskSession::class.java
)

View file

@ -3,18 +3,15 @@ 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.utils.getBody
import com.google.gson.Gson
import com.faraphel.tasks_valider.utils.parser
import fi.iki.elonen.NanoHTTPD
abstract class BaseTaskApi<Entity> (
private val dao: BaseTaskDao<Entity>,
private val session: SessionEntity,
private val entityType: Class<Entity>,
) : BaseApi {
companion object {
private val parser = Gson() ///< The JSON parser
}
private fun parseJson(data: String): Entity =
parser.fromJson(data, entityType)

View file

@ -1,20 +1,48 @@
package com.faraphel.tasks_valider.database.converters
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.room.TypeConverter
import com.google.gson.*
import java.lang.reflect.Type
import java.time.Instant
class InstantConverter {
@RequiresApi(Build.VERSION_CODES.O)
/**
* Allow for automatically converting Instant values when using them in the database or in a json parser.
*/
class InstantConverter : JsonDeserializer<Instant>, JsonSerializer<Instant> {
/**
* Convert a long into an instant
* @param value the number of milliseconds since the epoch of the time
* @return the Instant object
*/
@TypeConverter
fun fromTimestamp(value: Long?): Instant? {
return value?.let { Instant.ofEpochMilli(it) }
fun deserialize(value: Long): Instant {
return Instant.ofEpochMilli(value)
}
@RequiresApi(Build.VERSION_CODES.O)
/**
* Convert a long into an instant
* @param instant the Instant object
* @return the number of milliseconds since the epoch of the time
*/
@TypeConverter
fun dateToTimestamp(instant: Instant?): Long? {
return instant?.toEpochMilli()
fun serialize(instant: Instant): Long {
return instant.toEpochMilli()
}
/**
* Convert a long into an instant
* @param json the json object
* @return the Instant object
*/
override fun deserialize(json: JsonElement, type: Type, context: JsonDeserializationContext): Instant =
this.deserialize(json.asLong)
/**
* Convert a long into an instant
* @param instant the instant object
* @return the json object
*/
override fun serialize(instant: Instant, type: Type, context: JsonSerializationContext): JsonElement =
JsonPrimitive(this.serialize(instant))
}

View file

@ -17,7 +17,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.faraphel.tasks_valider.connectivity.task.TaskClient
import com.faraphel.tasks_valider.database.entities.PersonEntity
import com.google.gson.Gson
import com.faraphel.tasks_valider.utils.parser
import com.google.gson.reflect.TypeToken
@ -26,7 +26,6 @@ import com.google.gson.reflect.TypeToken
* @param activity the android activity
* @param client an HTTP client that can communicate with the server
*/
@RequiresApi(Build.VERSION_CODES.O)
@Composable
fun TaskSessionScreen(
activity: Activity,
@ -80,9 +79,6 @@ fun refreshStudents(
client: TaskClient,
students: MutableState<List<PersonEntity>?>
) {
// TODO(Faraphel): global variable ?
val jsonParser = Gson()
// try to obtain the list of groups
val response = client.get("entities/" + PersonEntity.TABLE_NAME)
@ -91,7 +87,7 @@ fun refreshStudents(
return activity.runOnUiThread { Toast.makeText(activity, response.message, Toast.LENGTH_LONG).show() }
// parse the list of groups
students.value = jsonParser.fromJson(
students.value = parser.fromJson(
response.body.string(),
object : TypeToken<List<PersonEntity>>(){}.type
)

View file

@ -1,12 +1,8 @@
package com.faraphel.tasks_valider.ui.screen.task
import android.app.Activity
import android.os.Build
import android.util.Log
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.compose.foundation.layout.*
import androidx.compose.material3.Button
import androidx.compose.material3.Checkbox
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@ -21,10 +17,12 @@ import androidx.compose.ui.unit.sp
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.google.gson.Gson
import com.faraphel.tasks_valider.utils.dateTimeFormatter
import com.faraphel.tasks_valider.utils.parser
import com.google.gson.reflect.TypeToken
import java.time.Instant
/**
* This screen represent a student
* @param student the student object
@ -78,7 +76,7 @@ fun TaskStudentScreen(
// task description
task.description?.let { description -> Text(description) }
// if the task have been validated, show the date
if (validation != null) Text(validation.date.toString())
if (validation != null) Text(text = dateTimeFormatter.format(validation.date))
}
// separator
@ -97,10 +95,10 @@ fun TaskStudentScreen(
client,
state,
validation ?: ValidationEntity(
Instant.now(),
user.id,
student.id,
task.id,
date=Instant.now(),
teacherId=user.id,
studentId=student.id,
taskId=task.id,
)
)
// refresh the UI
@ -128,8 +126,6 @@ fun refreshTasksValidations(
tasks: MutableState<List<TaskEntity>?>,
validations: MutableState<List<ValidationEntity>?>,
) {
val jsonParser = Gson()
// try to obtain the list of subject
val responseSubjects = client.get("entities/" + RelationPersonSessionSubjectEntity.TABLE_NAME)
@ -138,7 +134,7 @@ fun refreshTasksValidations(
return activity.runOnUiThread { Toast.makeText(activity, responseSubjects.message, Toast.LENGTH_LONG).show() }
// parse the list of subjects
val allPersonSessionSubjects = jsonParser.fromJson<List<RelationPersonSessionSubjectEntity>>(
val allPersonSessionSubjects = parser.fromJson<List<RelationPersonSessionSubjectEntity>>(
responseSubjects.body.string(),
object : TypeToken<List<RelationPersonSessionSubjectEntity>>(){}.type
)
@ -158,7 +154,7 @@ fun refreshTasksValidations(
return activity.runOnUiThread { Toast.makeText(activity, responseTasks.message, Toast.LENGTH_LONG).show() }
// parse the list of subjects
val allTasks = jsonParser.fromJson<List<TaskEntity>>(
val allTasks = parser.fromJson<List<TaskEntity>>(
responseTasks.body.string(),
object : TypeToken<List<TaskEntity>>(){}.type
)
@ -178,7 +174,7 @@ fun refreshTasksValidations(
return activity.runOnUiThread { Toast.makeText(activity, responseTasks.message, Toast.LENGTH_LONG).show() }
// parse the list of validations
val allValidations = jsonParser.fromJson<List<ValidationEntity>>(
val allValidations = parser.fromJson<List<ValidationEntity>>(
responseValidations.body.string(),
object : TypeToken<List<ValidationEntity>>(){}.type
)
@ -192,13 +188,11 @@ fun refreshTasksValidations(
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),
parser.toJson(validation),
"application/json"
)
}
@ -206,7 +200,7 @@ fun updateValidation(client: TaskClient, checked: Boolean, validation: Validatio
// if the validation is set, delete it
client.delete(
"entities/" + ValidationEntity.TABLE_NAME,
jsonParser.toJson(validation),
parser.toJson(validation),
"application/json"
)
}

View file

@ -0,0 +1,11 @@
package com.faraphel.tasks_valider.utils
import com.faraphel.tasks_valider.database.converters.InstantConverter
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import java.time.Instant
val parser: Gson = GsonBuilder()
.registerTypeAdapter(Instant::class.java, InstantConverter())
.create()

View file

@ -0,0 +1,8 @@
package com.faraphel.tasks_valider.utils
import java.time.ZoneId
import java.time.format.DateTimeFormatter
var dateTimeFormatter: DateTimeFormatter =
DateTimeFormatter.ofPattern("yyyy/MM/dd hh:mm:ss").withZone(ZoneId.systemDefault())