[WIP] implemented API class to connect the database and the HTTP server

This commit is contained in:
Faraphel 2024-05-08 00:10:04 +02:00
parent a604e01c12
commit 8c11e18e0d
29 changed files with 280 additions and 132 deletions

View file

@ -4,18 +4,6 @@
<value>
<entry key="app">
<State>
<runningDeviceTargetSelectedWithDropDown>
<Target>
<type value="RUNNING_DEVICE_TARGET" />
<deviceKey>
<Key>
<type value="SERIAL_NUMBER" />
<value value="2XJDU17923000406" />
</Key>
</deviceKey>
</Target>
</runningDeviceTargetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2024-05-05T12:21:32.176293Z" />
<runningDeviceTargetsSelectedWithDialog>
<Target>
<type value="RUNNING_DEVICE_TARGET" />

View file

@ -1,8 +1,6 @@
package com.faraphel.tasks_valider.connectivity.task
import android.util.Log
import com.faraphel.tasks_valider.database.TaskDatabase
import com.faraphel.tasks_valider.database.entities.Task
import com.google.gson.Gson
import fi.iki.elonen.NanoHTTPD
@ -24,31 +22,19 @@ class TaskServer(
// remove the first slash
val daoName: String = uri.substring(1)
// get the matching DAO in the database
TODO("Faraphel: get the correct DAO from the database")
TODO("Faraphel: pass more direct arguments to the API handler ?")
// handle the request
when (method) {
// get the data from the database
Method.GET -> {
return newFixedLengthResponse(
Response.Status.OK,
"application/json",
jsonParser.toJson( database.taskDao().getAll() )
)
}
// check if the data is in the database
Method.HEAD -> { TODO() }
// get the data from the dao
Method.GET -> { TODO() }
// insert the data into the database
Method.POST -> {
val task = jsonParser.fromJson(
session.inputStream.bufferedReader(),
Task::class.java
)
database.taskDao().insert(task)
return newFixedLengthResponse(
Response.Status.CREATED,
"application/json",
jsonParser.toJson(task)
)
}
Method.POST -> { TODO() }
// other methods are not allowed
else -> {
return newFixedLengthResponse(

View file

@ -10,13 +10,12 @@ import com.faraphel.tasks_valider.database.dao.StudentDao
import com.faraphel.tasks_valider.database.dao.TaskDao
import com.faraphel.tasks_valider.database.dao.TaskGroupDao
import com.faraphel.tasks_valider.database.dao.TeacherDao
import com.faraphel.tasks_valider.database.dao.base.BaseDao
import com.faraphel.tasks_valider.database.entities.Group
import com.faraphel.tasks_valider.database.entities.GroupStudent
import com.faraphel.tasks_valider.database.entities.Student
import com.faraphel.tasks_valider.database.entities.Task
import com.faraphel.tasks_valider.database.entities.TaskGroup
import com.faraphel.tasks_valider.database.entities.Teacher
import com.faraphel.tasks_valider.database.entities.GroupEntity
import com.faraphel.tasks_valider.database.entities.GroupStudentEntity
import com.faraphel.tasks_valider.database.entities.StudentEntity
import com.faraphel.tasks_valider.database.entities.TaskEntity
import com.faraphel.tasks_valider.database.entities.TaskGroupEntity
import com.faraphel.tasks_valider.database.entities.TeacherEntity
/**
@ -25,13 +24,13 @@ import com.faraphel.tasks_valider.database.entities.Teacher
*/
@Database(
entities = [
Group::class,
Student::class,
Teacher::class,
Task::class,
GroupEntity::class,
StudentEntity::class,
TeacherEntity::class,
TaskEntity::class,
GroupStudent::class,
TaskGroup::class,
GroupStudentEntity::class,
TaskGroupEntity::class,
],
version = 1
)
@ -48,20 +47,4 @@ abstract class TaskDatabase : RoomDatabase() {
// relations
abstract fun groupStudentDao(): GroupStudentDao
abstract fun taskGroupDao(): TaskGroupDao
/**
* Get the DAO from the name of the dao.
*/
@Suppress("UNCHECKED_CAST")
fun <Entity> daoFromName(name: String): BaseDao<Entity>? {
return when (name) {
"group" -> groupDao()
"student" -> studentDao()
"teacher" -> teacherDao()
"task" -> taskDao()
"group_student" -> groupStudentDao()
"task_group" -> taskGroupDao()
else -> null
} as BaseDao<Entity>?
}
}

View file

@ -0,0 +1,10 @@
package com.faraphel.tasks_valider.database.api
import com.faraphel.tasks_valider.database.TaskDatabase
import com.faraphel.tasks_valider.database.api.base.BaseJsonApi
import com.faraphel.tasks_valider.database.dao.GroupDao
import com.faraphel.tasks_valider.database.entities.GroupEntity
class GroupApi : BaseJsonApi<GroupEntity>() {
override fun getDao(database: TaskDatabase): GroupDao = database.groupDao()
}

View file

@ -0,0 +1,10 @@
package com.faraphel.tasks_valider.database.api
import com.faraphel.tasks_valider.database.TaskDatabase
import com.faraphel.tasks_valider.database.api.base.BaseJsonApi
import com.faraphel.tasks_valider.database.dao.GroupStudentDao
import com.faraphel.tasks_valider.database.entities.GroupStudentEntity
class GroupStudentApi : BaseJsonApi<GroupStudentEntity>() {
override fun getDao(database: TaskDatabase): GroupStudentDao = database.groupStudentDao()
}

View file

@ -0,0 +1,10 @@
package com.faraphel.tasks_valider.database.api
import com.faraphel.tasks_valider.database.TaskDatabase
import com.faraphel.tasks_valider.database.api.base.BaseJsonApi
import com.faraphel.tasks_valider.database.dao.StudentDao
import com.faraphel.tasks_valider.database.entities.StudentEntity
class StudentApi : BaseJsonApi<StudentEntity>() {
override fun getDao(database: TaskDatabase): StudentDao = database.studentDao()
}

View file

@ -0,0 +1,10 @@
package com.faraphel.tasks_valider.database.api
import com.faraphel.tasks_valider.database.TaskDatabase
import com.faraphel.tasks_valider.database.api.base.BaseJsonApi
import com.faraphel.tasks_valider.database.dao.TaskDao
import com.faraphel.tasks_valider.database.entities.TaskEntity
class TaskApi : BaseJsonApi<TaskEntity>() {
override fun getDao(database: TaskDatabase): TaskDao = database.taskDao()
}

View file

@ -0,0 +1,10 @@
package com.faraphel.tasks_valider.database.api
import com.faraphel.tasks_valider.database.TaskDatabase
import com.faraphel.tasks_valider.database.api.base.BaseJsonApi
import com.faraphel.tasks_valider.database.dao.TaskGroupDao
import com.faraphel.tasks_valider.database.entities.TaskGroupEntity
class TaskGroupApi : BaseJsonApi<TaskGroupEntity>() {
override fun getDao(database: TaskDatabase): TaskGroupDao = database.taskGroupDao()
}

View file

@ -0,0 +1,10 @@
package com.faraphel.tasks_valider.database.api
import com.faraphel.tasks_valider.database.TaskDatabase
import com.faraphel.tasks_valider.database.api.base.BaseJsonApi
import com.faraphel.tasks_valider.database.dao.TeacherDao
import com.faraphel.tasks_valider.database.entities.TeacherEntity
class TeacherApi : BaseJsonApi<TeacherEntity>() {
override fun getDao(database: TaskDatabase): TeacherDao = database.teacherDao()
}

View file

@ -0,0 +1,33 @@
package com.faraphel.tasks_valider.database.api.base
import com.faraphel.tasks_valider.database.TaskDatabase
import fi.iki.elonen.NanoHTTPD
/**
* A base for the API to handle the database operations with an HTTP server.
*/
interface BaseApi {
/**
* Handle the HEAD request
* This is used to check if a data exists in the database
*/
fun head(database: TaskDatabase, session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response
/**
* Handle the GET request
* This is used to get data from the database
*/
fun get(database: TaskDatabase, session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response
/**
* Handle the POST request
* This is used to insert data into the database
*/
fun post(database: TaskDatabase, session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response
/**
* Handle the PUT request
* This is used to delete data from the database
*/
fun delete(database: TaskDatabase, session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response
}

View file

@ -0,0 +1,79 @@
package com.faraphel.tasks_valider.database.api.base
import com.faraphel.tasks_valider.database.TaskDatabase
import com.faraphel.tasks_valider.database.dao.base.BaseDao
import com.faraphel.tasks_valider.database.entities.GroupEntity
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 JSON data.
* @param Entity the entity type to handle
*/
abstract class BaseJsonApi<Entity: BaseEntity> : BaseApi {
companion object {
private val parser = Gson() ///< The JSON parser
}
/**
* Get the DAO for the entity
* @param database the database to get the DAO from
* @return the DAO for the entity
*/
abstract fun getDao(database: TaskDatabase): BaseDao<Entity>
/**
* Get the type token for the entity
* @return the type token for the entity
*/
private fun getEntityTypeToken(): TypeToken<Entity> = object: TypeToken<Entity>() {}
// Requests
override fun head(database: TaskDatabase, session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
val obj = parser.fromJson<Entity>(
session.inputStream.bufferedReader().readText(),
getEntityTypeToken().type
)
val exists = this.getDao(database).exists(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(database: TaskDatabase, session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
return NanoHTTPD.newFixedLengthResponse(
NanoHTTPD.Response.Status.OK,
"application/json",
parser.toJson(database.groupDao().getAll())
)
}
override fun post(database: TaskDatabase, session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
val obj = parser.fromJson(session.inputStream.bufferedReader().readText(), GroupEntity::class.java)
val id = database.groupDao().insert(obj)
return NanoHTTPD.newFixedLengthResponse(
NanoHTTPD.Response.Status.CREATED,
"text/plain",
id.toString()
)
}
override fun delete(database: TaskDatabase, session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response {
val obj = parser.fromJson(session.inputStream.bufferedReader().readText(), GroupEntity::class.java)
val count = database.groupDao().delete(obj)
return NanoHTTPD.newFixedLengthResponse(
if (count > 0) NanoHTTPD.Response.Status.OK else NanoHTTPD.Response.Status.NOT_FOUND,
"text/plain",
count.toString()
)
}
}

View file

@ -4,17 +4,16 @@ import androidx.room.Dao
import androidx.room.Query
import androidx.room.RewriteQueriesToDropUnusedColumns
import com.faraphel.tasks_valider.database.dao.base.BaseDao
import com.faraphel.tasks_valider.database.entities.Group
import com.faraphel.tasks_valider.database.entities.Student
import com.faraphel.tasks_valider.database.entities.GroupEntity
@Dao
interface GroupDao : BaseDao<Group> {
interface GroupDao : BaseDao<GroupEntity> {
@Query("SELECT * FROM `groups`")
override fun getAll(): List<Group>
override fun getAll(): List<GroupEntity>
@Query("SELECT * FROM `groups` WHERE id = :id")
fun getById(id: Long): Group
fun getById(id: Long): GroupEntity
/**
Allow to get all groups with a specific student
@ -25,5 +24,5 @@ interface GroupDao : BaseDao<Group> {
"WHERE `group_student`.student_id = :studentId"
)
@RewriteQueriesToDropUnusedColumns
fun filterByStudentId(studentId: Long): List<Group>
fun filterByStudentId(studentId: Long): List<GroupEntity>
}

View file

@ -2,18 +2,15 @@ package com.faraphel.tasks_valider.database.dao
import androidx.room.Dao
import androidx.room.Query
import androidx.room.RewriteQueriesToDropUnusedColumns
import com.faraphel.tasks_valider.database.dao.base.BaseDao
import com.faraphel.tasks_valider.database.entities.Group
import com.faraphel.tasks_valider.database.entities.GroupStudent
import com.faraphel.tasks_valider.database.entities.Student
import com.faraphel.tasks_valider.database.entities.GroupStudentEntity
@Dao
interface GroupStudentDao : BaseDao<GroupStudent> {
interface GroupStudentDao : BaseDao<GroupStudentEntity> {
@Query("SELECT * FROM `group_student`")
override fun getAll(): List<GroupStudent>
override fun getAll(): List<GroupStudentEntity>
@Query("SELECT * FROM `group_student` WHERE group_id = :groupId AND student_id = :studentId")
fun getById(groupId: Long, studentId: Long): GroupStudent
fun getById(groupId: Long, studentId: Long): GroupStudentEntity
}

View file

@ -1,22 +1,19 @@
package com.faraphel.tasks_valider.database.dao
import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Query
import androidx.room.RewriteQueriesToDropUnusedColumns
import com.faraphel.tasks_valider.database.dao.base.BaseDao
import com.faraphel.tasks_valider.database.entities.Group
import com.faraphel.tasks_valider.database.entities.Person
import com.faraphel.tasks_valider.database.entities.Student
import com.faraphel.tasks_valider.database.entities.StudentEntity
@Dao
interface StudentDao : BaseDao<Student> {
interface StudentDao : BaseDao<StudentEntity> {
@Query("SELECT * FROM `students`")
override fun getAll(): List<Student>
override fun getAll(): List<StudentEntity>
@Query("SELECT * FROM `students` WHERE id = :id")
fun getById(id: Long): Student
fun getById(id: Long): StudentEntity
/**
@ -28,5 +25,5 @@ interface StudentDao : BaseDao<Student> {
"WHERE `group_student`.group_id = :groupId"
)
@RewriteQueriesToDropUnusedColumns
fun filterByGroupId(groupId: Long): List<Student>
fun filterByGroupId(groupId: Long): List<StudentEntity>
}

View file

@ -4,17 +4,16 @@ import androidx.room.Dao
import androidx.room.Query
import androidx.room.RewriteQueriesToDropUnusedColumns
import com.faraphel.tasks_valider.database.dao.base.BaseDao
import com.faraphel.tasks_valider.database.entities.Group
import com.faraphel.tasks_valider.database.entities.Task
import com.faraphel.tasks_valider.database.entities.TaskEntity
@Dao
interface TaskDao : BaseDao<Task> {
interface TaskDao : BaseDao<TaskEntity> {
@Query("SELECT * FROM `tasks`")
override fun getAll(): List<Task>
override fun getAll(): List<TaskEntity>
@Query("SELECT * FROM `tasks` WHERE id = :id")
fun getById(id: Long): Task
fun getById(id: Long): TaskEntity
/**
Get all the tasks for a specific group
@ -25,5 +24,5 @@ interface TaskDao : BaseDao<Task> {
"WHERE `task_group`.group_id = :groupId"
)
@RewriteQueriesToDropUnusedColumns
fun filterByGroupId(groupId: Long): List<Task>
fun filterByGroupId(groupId: Long): List<TaskEntity>
}

View file

@ -3,14 +3,14 @@ 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.entities.TaskGroup
import com.faraphel.tasks_valider.database.entities.TaskGroupEntity
@Dao
interface TaskGroupDao : BaseDao<TaskGroup> {
interface TaskGroupDao : BaseDao<TaskGroupEntity> {
@Query("SELECT * FROM `task_group`")
override fun getAll(): List<TaskGroup>
override fun getAll(): List<TaskGroupEntity>
@Query("SELECT * FROM `task_group` WHERE task_id = :taskId AND group_id = :groupId")
fun getById(taskId: Long, groupId: Long): TaskGroup
fun getById(taskId: Long, groupId: Long): TaskGroupEntity
}

View file

@ -3,16 +3,14 @@ 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.entities.Person
import com.faraphel.tasks_valider.database.entities.Student
import com.faraphel.tasks_valider.database.entities.Teacher
import com.faraphel.tasks_valider.database.entities.TeacherEntity
@Dao
interface TeacherDao : BaseDao<Teacher> {
interface TeacherDao : BaseDao<TeacherEntity> {
@Query("SELECT * FROM `teachers`")
override fun getAll(): List<Teacher>
override fun getAll(): List<TeacherEntity>
@Query("SELECT * FROM `teachers` WHERE id = :id")
fun getById(id: Long): Teacher
fun getById(id: Long): TeacherEntity
}

View file

@ -2,18 +2,40 @@ 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.
* @param Entity the entity to handle
*/
interface BaseDao<Entity> {
@Insert
/**
* Check if the entities exists in the database.
*/
fun exists(vararg entities: Entity): Boolean {
return this.getAll().containsAll(entities.toList())
}
/**
* Insert the entities into the database.
*/
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(vararg entities: Entity): List<Long>
@Update
fun update(vararg entities: Entity): Int
/**
* Delete the entities from the database.
*/
@Delete
fun delete(vararg entities: Entity): Int
/**
* Get all the entities from the database.
* TODO(Faraphel): support filters ?
*/
fun getAll(): List<Entity>
}

View file

@ -3,10 +3,11 @@ package com.faraphel.tasks_valider.database.entities
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.faraphel.tasks_valider.database.entities.base.BaseEntity
@Entity(tableName = "groups")
data class Group (
data class GroupEntity (
@ColumnInfo("id") @PrimaryKey(autoGenerate = true) val id: Long = 0,
@ColumnInfo("name") val name: String? = null,
)
) : BaseEntity()

View file

@ -3,8 +3,7 @@ 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.Group
import com.faraphel.tasks_valider.database.entities.Student
import com.faraphel.tasks_valider.database.entities.base.BaseEntity
@Entity(
tableName = "group_student",
@ -14,20 +13,20 @@ import com.faraphel.tasks_valider.database.entities.Student
],
foreignKeys = [
ForeignKey(
entity = Group::class,
entity = GroupEntity::class,
parentColumns = ["id"],
childColumns = ["group_id"],
onDelete = ForeignKey.CASCADE
),
ForeignKey(
entity = Student::class,
entity = StudentEntity::class,
parentColumns = ["id"],
childColumns = ["student_id"],
onDelete = ForeignKey.CASCADE
)
]
)
data class GroupStudent(
data class GroupStudentEntity(
@ColumnInfo("group_id", index = true) val groupId: Long,
@ColumnInfo("student_id", index = true) val studentId: Long,
)
) : BaseEntity()

View file

@ -1,13 +1,14 @@
package com.faraphel.tasks_valider.database.entities
import java.util.Locale
import com.faraphel.tasks_valider.database.entities.base.BaseEntity
open class Person (
open class PersonEntity (
open val id: Long = 0,
open val firstName: String,
open val lastName: String,
) {
) : BaseEntity() {
/**
Get the full name of the person
*/

View file

@ -5,8 +5,8 @@ import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "students")
class Student(
class StudentEntity(
@ColumnInfo("id") @PrimaryKey(autoGenerate = true) override val id: Long = 0,
@ColumnInfo("first_name") override val firstName: String,
@ColumnInfo("last_name") override val lastName: String
) : Person(id, firstName, lastName)
) : PersonEntity(id, firstName, lastName)

View file

@ -3,10 +3,11 @@ package com.faraphel.tasks_valider.database.entities
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.faraphel.tasks_valider.database.entities.base.BaseEntity
@Entity(tableName = "tasks")
data class Task (
data class TaskEntity (
@ColumnInfo("id") @PrimaryKey(autoGenerate = true) val id: Long = 0,
@ColumnInfo("title") val title: String,
@ColumnInfo("description") val description: String,
)
) : BaseEntity()

View file

@ -3,6 +3,7 @@ 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
import java.time.Instant
@ -14,29 +15,30 @@ import java.time.Instant
],
foreignKeys = [
ForeignKey(
entity = Group::class,
entity = GroupEntity::class,
parentColumns = ["id"],
childColumns = ["group_id"],
onDelete = ForeignKey.CASCADE
),
ForeignKey(
entity = Task::class,
entity = TaskEntity::class,
parentColumns = ["id"],
childColumns = ["task_id"],
onDelete = ForeignKey.CASCADE
),
ForeignKey(
entity = Teacher::class,
entity = TeacherEntity::class,
parentColumns = ["id"],
childColumns = ["approval_teacher_id"],
onDelete = ForeignKey.CASCADE
),
]
)
data class TaskGroup (
data class TaskGroupEntity (
@ColumnInfo("task_id") val taskId: Long,
@ColumnInfo("group_id") val groupId: Long,
@ColumnInfo("approval_status") var approvalStatus: Boolean = false,
@ColumnInfo("approval_teacher_id") val approvalTeacherId: Long? = null,
@ColumnInfo("approval_time") val approvalTime: Instant? = null
)
) : BaseEntity()

View file

@ -5,8 +5,8 @@ import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "teachers")
class Teacher(
class TeacherEntity(
@ColumnInfo("id") @PrimaryKey(autoGenerate = true) override val id: Long = 0,
@ColumnInfo("first_name") override val firstName: String,
@ColumnInfo("last_name") override val lastName: String
) : Person(id, firstName, lastName)
) : PersonEntity(id, firstName, lastName)

View file

@ -0,0 +1,3 @@
package com.faraphel.tasks_valider.database.entities.base
open class BaseEntity

View file

@ -3,10 +3,10 @@ package com.faraphel.tasks_valider.ui.widgets.task
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import com.faraphel.tasks_valider.database.entities.Group
import com.faraphel.tasks_valider.database.entities.GroupEntity
@Composable
fun WidgetGroup(group: Group) {
fun WidgetGroup(group: GroupEntity) {
// TODO
Column {
Text(text = group.name!!)

View file

@ -3,10 +3,10 @@ package com.faraphel.tasks_valider.ui.widgets.task
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import com.faraphel.tasks_valider.database.entities.Task
import com.faraphel.tasks_valider.database.entities.TaskEntity
@Composable
fun WidgetTask(task: Task) {
fun WidgetTask(task: TaskEntity) {
// task information
Column {
Text(text = task.title)

View file

@ -12,11 +12,11 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.faraphel.tasks_valider.database.TaskDatabase
import com.faraphel.tasks_valider.database.entities.TaskGroup
import com.faraphel.tasks_valider.database.entities.TaskGroupEntity
@Composable
fun WidgetTaskStudent(database: TaskDatabase, taskStudent: TaskGroup) {
fun WidgetTaskStudent(database: TaskDatabase, taskStudent: TaskGroupEntity) {
val teacherDao = database.teacherDao()
Column {