Fix loading bug

This commit is contained in:
2025-06-10 16:41:02 +02:00
parent f7b4f29e2e
commit 0883d2332e
2 changed files with 41 additions and 57 deletions

View File

@ -12,11 +12,9 @@ import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.layout
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.rememberTextMeasurer
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.dp
import com.jaytux.grader.data.GroupAssignment
import com.jaytux.grader.data.GroupAssignmentCriterion
import com.jaytux.grader.data.SoloAssignmentCriterion
import com.jaytux.grader.data.Student
@ -26,7 +24,6 @@ import com.jaytux.grader.viewmodel.SoloAssignmentState
import com.mohamedrejeb.richeditor.model.rememberRichTextState
import com.mohamedrejeb.richeditor.ui.material3.OutlinedRichTextEditor
import kotlinx.datetime.LocalDateTime
import org.jetbrains.exposed.sql.transactions.inTopLevelTransaction
@Composable
fun GroupAssignmentView(state: GroupAssignmentState) {
@ -189,7 +186,7 @@ fun groupTaskWidget(
@Composable
fun groupFeedback(state: GroupAssignmentState, fdbk: GroupAssignmentState.LocalGFeedback) {
val (group, feedback, individual) = fdbk
var idx by remember(fdbk) { mutableStateOf(0) }
var studentIdx by remember(fdbk) { mutableStateOf(0) }
var critIdx by remember(fdbk) { mutableStateOf(0) }
val criteria by state.criteria.entities
val suggestions by state.autofill.entities
@ -199,8 +196,8 @@ fun groupFeedback(state: GroupAssignmentState, fdbk: GroupAssignmentState.LocalG
LazyColumn(Modifier.fillMaxHeight().padding(10.dp)) {
item {
Surface(
Modifier.fillMaxWidth().clickable { idx = 0 },
tonalElevation = if (idx == 0) 50.dp else 0.dp,
Modifier.fillMaxWidth().clickable { studentIdx = 0 },
tonalElevation = if (studentIdx == 0) 50.dp else 0.dp,
shape = MaterialTheme.shapes.medium
) {
Text("Group feedback", Modifier.padding(5.dp), fontStyle = FontStyle.Italic)
@ -210,8 +207,8 @@ fun groupFeedback(state: GroupAssignmentState, fdbk: GroupAssignmentState.LocalG
itemsIndexed(individual.toList()) { i, (student, details) ->
val (role, _) = details
Surface(
Modifier.fillMaxWidth().clickable { idx = i + 1 },
tonalElevation = if (idx == i + 1) 50.dp else 0.dp,
Modifier.fillMaxWidth().clickable { studentIdx = i + 1 },
tonalElevation = if (studentIdx == i + 1) 50.dp else 0.dp,
shape = MaterialTheme.shapes.medium
) {
Text("${student.name} (${role ?: "no role"})", Modifier.padding(5.dp))
@ -220,45 +217,25 @@ fun groupFeedback(state: GroupAssignmentState, fdbk: GroupAssignmentState.LocalG
}
}
val updateGrade = { grade: String ->
if(idx == 0) {
state.upsertGroupFeedback(group, feedback.global?.feedback ?: "", grade)
}
else {
val ind = individual[idx - 1]
val glob = ind.second.second.global
state.upsertIndividualFeedback(ind.first, group, glob?.feedback ?: "", grade)
}
}
val updateFeedback = { fdbk: String ->
if(idx == 0) {
if(critIdx == 0) {
state.upsertGroupFeedback(group, fdbk, feedback.global?.grade ?: "", null)
}
else {
val current = feedback.byCriterion[critIdx - 1]
state.upsertGroupFeedback(group, fdbk, current.entry?.grade ?: "", current.criterion)
}
}
else {
val ind = individual[idx - 1]
if(critIdx == 0) {
val entry = ind.second.second
state.upsertIndividualFeedback(ind.first, group, fdbk, entry.global?.grade ?: "", null)
}
else {
val entry = ind.second.second.byCriterion[critIdx - 1]
state.upsertIndividualFeedback(ind.first, group, fdbk, entry.entry?.grade ?: "", entry.criterion)
}
val onSave = { grade: String, fdbk: String ->
when {
studentIdx == 0 && critIdx == 0 -> state.upsertGroupFeedback(group, fdbk, grade)
studentIdx == 0 && critIdx != 0 -> state.upsertGroupFeedback(group, fdbk, grade, criteria[critIdx - 1])
studentIdx != 0 && critIdx == 0 -> state.upsertIndividualFeedback(individual[studentIdx - 1].first, group, fdbk, grade)
else -> state.upsertIndividualFeedback(individual[studentIdx - 1].first, group, fdbk, grade, criteria[critIdx - 1])
}
}
groupFeedbackPane(
criteria, critIdx, { critIdx = it }, feedback.global,
if(critIdx == 0) feedback.global else feedback.byCriterion[critIdx - 1].entry,
suggestions, updateGrade, updateFeedback, Modifier.weight(0.75f).padding(10.dp),
key = idx to critIdx
criteria, critIdx, { critIdx = it },
when {
studentIdx == 0 && critIdx == 0 -> feedback.global
studentIdx == 0 && critIdx != 0 -> feedback.byCriterion[critIdx - 1].entry
studentIdx != 0 && critIdx == 0 -> individual[studentIdx - 1].second.second.global
else -> individual[studentIdx - 1].second.second.byCriterion[critIdx - 1].entry
},
suggestions, onSave, Modifier.weight(0.75f).padding(10.dp),
key = studentIdx to critIdx
)
}
}
@ -268,19 +245,17 @@ fun groupFeedbackPane(
criteria: List<GroupAssignmentCriterion>,
currentCriterion: Int,
onSelectCriterion: (Int) -> Unit,
globFeedback: GroupAssignmentState.FeedbackEntry?,
criterionFeedback: GroupAssignmentState.FeedbackEntry?,
rawFeedback: GroupAssignmentState.FeedbackEntry?,
autofill: List<String>,
onSetGrade: (String) -> Unit,
onSetFeedback: (String) -> Unit,
onSave: (String, String) -> Unit,
modifier: Modifier = Modifier,
key: Any? = null
) {
var grade by remember(globFeedback, key) { mutableStateOf(globFeedback?.grade ?: "") }
var grade by remember(rawFeedback, key) { mutableStateOf(rawFeedback?.grade ?: "") }
val feedback = rememberRichTextState()
LaunchedEffect(currentCriterion, criteria, criterionFeedback, key) {
feedback.setMarkdown(criterionFeedback?.feedback ?: "")
LaunchedEffect(currentCriterion, criteria, rawFeedback, key) {
feedback.setMarkdown(rawFeedback?.feedback ?: "")
}
Column(modifier) {
@ -289,7 +264,7 @@ fun groupFeedbackPane(
OutlinedTextField(grade, { grade = it }, Modifier.weight(0.2f))
Spacer(Modifier.weight(0.6f))
Button(
{ onSetGrade(grade); onSetFeedback(feedback.toMarkdown()) },
{ onSave(grade, feedback.toMarkdown()) },
Modifier.weight(0.2f).align(Alignment.CenterVertically)
) {
Text("Save")

View File

@ -171,10 +171,14 @@ class EditionState(val edition: Edition) {
fun newSoloAssignment(name: String) {
transaction {
SoloAssignment.new {
val assign = SoloAssignment.new {
this.name = name; this.edition = this@EditionState.edition; assignment = ""; deadline = now()
this.number = nextIdx()
}
val global = SoloAssignmentCriterion.new {
this.name = "_global"; this.description = "[Global] Meta-criterion for $name"; this.assignment = assign
}
assign.globalCriterion = global
solo.refresh()
}
}
@ -186,10 +190,14 @@ class EditionState(val edition: Edition) {
}
fun newGroupAssignment(name: String) {
transaction {
GroupAssignment.new {
val assign = GroupAssignment.new {
this.name = name; this.edition = this@EditionState.edition; assignment = ""; deadline = now()
this.number = nextIdx()
}
val global = GroupAssignmentCriterion.new {
this.name = "_global"; this.description = "[Global] Meta-criterion for $name"; this.assignment = assign
}
assign.globalCriterion = global
groupAs.refresh()
}
}
@ -494,7 +502,7 @@ class GroupAssignmentState(val assignment: GroupAssignment) {
private fun Transaction.loadFeedback(): List<Pair<Group, LocalGFeedback>> {
val allCrit = GroupAssignmentCriterion.find {
GroupAssignmentCriteria.assignmentId eq assignment.id
}.filter { it.id != assignment.globalCriterion.id }
}//.filter { it.id != assignment.globalCriterion.id }
return Group.find {
(Groups.editionId eq assignment.edition.id)
@ -525,11 +533,12 @@ class GroupAssignmentState(val assignment: GroupAssignment) {
val student = it.student
val role = it.role
val forSt = (IndividualFeedbacks innerJoin Groups innerJoin GroupStudents)
val forSt = (IndividualFeedbacks innerJoin Groups)
.selectAll().where {
(IndividualFeedbacks.assignmentId eq assignment.id) and
(GroupStudents.studentId eq student.id) and (Groups.id eq group.id)
(IndividualFeedbacks.studentId eq student.id) and (Groups.id eq group.id)
}.map { row ->
val stdId = row[IndividualFeedbacks.studentId]
val crit = GroupAssignmentCriterion[row[IndividualFeedbacks.criterionId]]
val fdbk = row[IndividualFeedbacks.feedback]
val grade = row[IndividualFeedbacks.grade]
@ -537,7 +546,7 @@ class GroupAssignmentState(val assignment: GroupAssignment) {
crit to FeedbackEntry(fdbk, grade)
}
val global = forSt.firstOrNull { it.first == assignment.globalCriterion.id }?.second
val global = forSt.firstOrNull { it.first.id == assignment.globalCriterion.id }?.second
val byCrit_ = forSt
.filter { it.first != assignment.globalCriterion.id }
.map { LocalCriterionFeedback(it.first, it.second) }