Fix loading bug
This commit is contained in:
@ -12,11 +12,9 @@ import androidx.compose.ui.graphics.graphicsLayer
|
|||||||
import androidx.compose.ui.layout.layout
|
import androidx.compose.ui.layout.layout
|
||||||
import androidx.compose.ui.text.font.FontStyle
|
import androidx.compose.ui.text.font.FontStyle
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.input.TextFieldValue
|
|
||||||
import androidx.compose.ui.text.rememberTextMeasurer
|
import androidx.compose.ui.text.rememberTextMeasurer
|
||||||
import androidx.compose.ui.unit.Constraints
|
import androidx.compose.ui.unit.Constraints
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.jaytux.grader.data.GroupAssignment
|
|
||||||
import com.jaytux.grader.data.GroupAssignmentCriterion
|
import com.jaytux.grader.data.GroupAssignmentCriterion
|
||||||
import com.jaytux.grader.data.SoloAssignmentCriterion
|
import com.jaytux.grader.data.SoloAssignmentCriterion
|
||||||
import com.jaytux.grader.data.Student
|
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.model.rememberRichTextState
|
||||||
import com.mohamedrejeb.richeditor.ui.material3.OutlinedRichTextEditor
|
import com.mohamedrejeb.richeditor.ui.material3.OutlinedRichTextEditor
|
||||||
import kotlinx.datetime.LocalDateTime
|
import kotlinx.datetime.LocalDateTime
|
||||||
import org.jetbrains.exposed.sql.transactions.inTopLevelTransaction
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun GroupAssignmentView(state: GroupAssignmentState) {
|
fun GroupAssignmentView(state: GroupAssignmentState) {
|
||||||
@ -189,7 +186,7 @@ fun groupTaskWidget(
|
|||||||
@Composable
|
@Composable
|
||||||
fun groupFeedback(state: GroupAssignmentState, fdbk: GroupAssignmentState.LocalGFeedback) {
|
fun groupFeedback(state: GroupAssignmentState, fdbk: GroupAssignmentState.LocalGFeedback) {
|
||||||
val (group, feedback, individual) = fdbk
|
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) }
|
var critIdx by remember(fdbk) { mutableStateOf(0) }
|
||||||
val criteria by state.criteria.entities
|
val criteria by state.criteria.entities
|
||||||
val suggestions by state.autofill.entities
|
val suggestions by state.autofill.entities
|
||||||
@ -199,8 +196,8 @@ fun groupFeedback(state: GroupAssignmentState, fdbk: GroupAssignmentState.LocalG
|
|||||||
LazyColumn(Modifier.fillMaxHeight().padding(10.dp)) {
|
LazyColumn(Modifier.fillMaxHeight().padding(10.dp)) {
|
||||||
item {
|
item {
|
||||||
Surface(
|
Surface(
|
||||||
Modifier.fillMaxWidth().clickable { idx = 0 },
|
Modifier.fillMaxWidth().clickable { studentIdx = 0 },
|
||||||
tonalElevation = if (idx == 0) 50.dp else 0.dp,
|
tonalElevation = if (studentIdx == 0) 50.dp else 0.dp,
|
||||||
shape = MaterialTheme.shapes.medium
|
shape = MaterialTheme.shapes.medium
|
||||||
) {
|
) {
|
||||||
Text("Group feedback", Modifier.padding(5.dp), fontStyle = FontStyle.Italic)
|
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) ->
|
itemsIndexed(individual.toList()) { i, (student, details) ->
|
||||||
val (role, _) = details
|
val (role, _) = details
|
||||||
Surface(
|
Surface(
|
||||||
Modifier.fillMaxWidth().clickable { idx = i + 1 },
|
Modifier.fillMaxWidth().clickable { studentIdx = i + 1 },
|
||||||
tonalElevation = if (idx == i + 1) 50.dp else 0.dp,
|
tonalElevation = if (studentIdx == i + 1) 50.dp else 0.dp,
|
||||||
shape = MaterialTheme.shapes.medium
|
shape = MaterialTheme.shapes.medium
|
||||||
) {
|
) {
|
||||||
Text("${student.name} (${role ?: "no role"})", Modifier.padding(5.dp))
|
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 ->
|
val onSave = { grade: String, fdbk: String ->
|
||||||
if(idx == 0) {
|
when {
|
||||||
state.upsertGroupFeedback(group, feedback.global?.feedback ?: "", grade)
|
studentIdx == 0 && critIdx == 0 -> state.upsertGroupFeedback(group, fdbk, grade)
|
||||||
}
|
studentIdx == 0 && critIdx != 0 -> state.upsertGroupFeedback(group, fdbk, grade, criteria[critIdx - 1])
|
||||||
else {
|
studentIdx != 0 && critIdx == 0 -> state.upsertIndividualFeedback(individual[studentIdx - 1].first, group, fdbk, grade)
|
||||||
val ind = individual[idx - 1]
|
else -> state.upsertIndividualFeedback(individual[studentIdx - 1].first, group, fdbk, grade, criteria[critIdx - 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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
groupFeedbackPane(
|
groupFeedbackPane(
|
||||||
criteria, critIdx, { critIdx = it }, feedback.global,
|
criteria, critIdx, { critIdx = it },
|
||||||
if(critIdx == 0) feedback.global else feedback.byCriterion[critIdx - 1].entry,
|
when {
|
||||||
suggestions, updateGrade, updateFeedback, Modifier.weight(0.75f).padding(10.dp),
|
studentIdx == 0 && critIdx == 0 -> feedback.global
|
||||||
key = idx to critIdx
|
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>,
|
criteria: List<GroupAssignmentCriterion>,
|
||||||
currentCriterion: Int,
|
currentCriterion: Int,
|
||||||
onSelectCriterion: (Int) -> Unit,
|
onSelectCriterion: (Int) -> Unit,
|
||||||
globFeedback: GroupAssignmentState.FeedbackEntry?,
|
rawFeedback: GroupAssignmentState.FeedbackEntry?,
|
||||||
criterionFeedback: GroupAssignmentState.FeedbackEntry?,
|
|
||||||
autofill: List<String>,
|
autofill: List<String>,
|
||||||
onSetGrade: (String) -> Unit,
|
onSave: (String, String) -> Unit,
|
||||||
onSetFeedback: (String) -> Unit,
|
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
key: Any? = null
|
key: Any? = null
|
||||||
) {
|
) {
|
||||||
var grade by remember(globFeedback, key) { mutableStateOf(globFeedback?.grade ?: "") }
|
var grade by remember(rawFeedback, key) { mutableStateOf(rawFeedback?.grade ?: "") }
|
||||||
val feedback = rememberRichTextState()
|
val feedback = rememberRichTextState()
|
||||||
|
|
||||||
LaunchedEffect(currentCriterion, criteria, criterionFeedback, key) {
|
LaunchedEffect(currentCriterion, criteria, rawFeedback, key) {
|
||||||
feedback.setMarkdown(criterionFeedback?.feedback ?: "")
|
feedback.setMarkdown(rawFeedback?.feedback ?: "")
|
||||||
}
|
}
|
||||||
|
|
||||||
Column(modifier) {
|
Column(modifier) {
|
||||||
@ -289,7 +264,7 @@ fun groupFeedbackPane(
|
|||||||
OutlinedTextField(grade, { grade = it }, Modifier.weight(0.2f))
|
OutlinedTextField(grade, { grade = it }, Modifier.weight(0.2f))
|
||||||
Spacer(Modifier.weight(0.6f))
|
Spacer(Modifier.weight(0.6f))
|
||||||
Button(
|
Button(
|
||||||
{ onSetGrade(grade); onSetFeedback(feedback.toMarkdown()) },
|
{ onSave(grade, feedback.toMarkdown()) },
|
||||||
Modifier.weight(0.2f).align(Alignment.CenterVertically)
|
Modifier.weight(0.2f).align(Alignment.CenterVertically)
|
||||||
) {
|
) {
|
||||||
Text("Save")
|
Text("Save")
|
||||||
|
@ -171,10 +171,14 @@ class EditionState(val edition: Edition) {
|
|||||||
|
|
||||||
fun newSoloAssignment(name: String) {
|
fun newSoloAssignment(name: String) {
|
||||||
transaction {
|
transaction {
|
||||||
SoloAssignment.new {
|
val assign = SoloAssignment.new {
|
||||||
this.name = name; this.edition = this@EditionState.edition; assignment = ""; deadline = now()
|
this.name = name; this.edition = this@EditionState.edition; assignment = ""; deadline = now()
|
||||||
this.number = nextIdx()
|
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()
|
solo.refresh()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -186,10 +190,14 @@ class EditionState(val edition: Edition) {
|
|||||||
}
|
}
|
||||||
fun newGroupAssignment(name: String) {
|
fun newGroupAssignment(name: String) {
|
||||||
transaction {
|
transaction {
|
||||||
GroupAssignment.new {
|
val assign = GroupAssignment.new {
|
||||||
this.name = name; this.edition = this@EditionState.edition; assignment = ""; deadline = now()
|
this.name = name; this.edition = this@EditionState.edition; assignment = ""; deadline = now()
|
||||||
this.number = nextIdx()
|
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()
|
groupAs.refresh()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -494,7 +502,7 @@ class GroupAssignmentState(val assignment: GroupAssignment) {
|
|||||||
private fun Transaction.loadFeedback(): List<Pair<Group, LocalGFeedback>> {
|
private fun Transaction.loadFeedback(): List<Pair<Group, LocalGFeedback>> {
|
||||||
val allCrit = GroupAssignmentCriterion.find {
|
val allCrit = GroupAssignmentCriterion.find {
|
||||||
GroupAssignmentCriteria.assignmentId eq assignment.id
|
GroupAssignmentCriteria.assignmentId eq assignment.id
|
||||||
}.filter { it.id != assignment.globalCriterion.id }
|
}//.filter { it.id != assignment.globalCriterion.id }
|
||||||
|
|
||||||
return Group.find {
|
return Group.find {
|
||||||
(Groups.editionId eq assignment.edition.id)
|
(Groups.editionId eq assignment.edition.id)
|
||||||
@ -525,11 +533,12 @@ class GroupAssignmentState(val assignment: GroupAssignment) {
|
|||||||
val student = it.student
|
val student = it.student
|
||||||
val role = it.role
|
val role = it.role
|
||||||
|
|
||||||
val forSt = (IndividualFeedbacks innerJoin Groups innerJoin GroupStudents)
|
val forSt = (IndividualFeedbacks innerJoin Groups)
|
||||||
.selectAll().where {
|
.selectAll().where {
|
||||||
(IndividualFeedbacks.assignmentId eq assignment.id) and
|
(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 ->
|
}.map { row ->
|
||||||
|
val stdId = row[IndividualFeedbacks.studentId]
|
||||||
val crit = GroupAssignmentCriterion[row[IndividualFeedbacks.criterionId]]
|
val crit = GroupAssignmentCriterion[row[IndividualFeedbacks.criterionId]]
|
||||||
val fdbk = row[IndividualFeedbacks.feedback]
|
val fdbk = row[IndividualFeedbacks.feedback]
|
||||||
val grade = row[IndividualFeedbacks.grade]
|
val grade = row[IndividualFeedbacks.grade]
|
||||||
@ -537,7 +546,7 @@ class GroupAssignmentState(val assignment: GroupAssignment) {
|
|||||||
crit to FeedbackEntry(fdbk, grade)
|
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
|
val byCrit_ = forSt
|
||||||
.filter { it.first != assignment.globalCriterion.id }
|
.filter { it.first != assignment.globalCriterion.id }
|
||||||
.map { LocalCriterionFeedback(it.first, it.second) }
|
.map { LocalCriterionFeedback(it.first, it.second) }
|
||||||
|
Reference in New Issue
Block a user