This commit is contained in:
2026-03-11 16:46:16 +01:00
parent 8786cc6072
commit 52ff467d9c
5 changed files with 34 additions and 28 deletions

View File

@@ -96,7 +96,7 @@ object StudentOverrideFeedbacks : UUIDTable("studOvrFdbks") {
val groupId = reference("group_id", Groups.id)
val studentId = reference("student_id", Students.id)
val feedbackId = reference("feedback_id", BaseFeedbacks.id)
val overrides = reference("overrides", GroupFeedbacks.feedbackId)
val overrides = reference("overrides", BaseFeedbacks.id)
}
object SoloFeedbacks : CompositeIdTable("soloFdbks") {

View File

@@ -65,7 +65,7 @@ fun GroupsGradingView(data: GroupGrading, token: Navigator.NavToken) {
val selectedGroup = remember(focus, groups) { groups.getOrNull(focus) }
Column(Modifier.padding(10.dp)) {
Text("Grading ${vm.base.name}", Modifier.weight(1f), style = MaterialTheme.typography.headlineMedium)
Text("Grading ${vm.base.name}", style = MaterialTheme.typography.headlineMedium)
Text("Group assignment in ${vm.course.name} - ${vm.edition.name}")
Spacer(Modifier.height(5.dp))
Row(Modifier.fillMaxSize()) {
@@ -104,7 +104,7 @@ fun GroupsGradingView(data: GroupGrading, token: Navigator.NavToken) {
items(byCriteria ?: listOf()) { (crit, fdbk) ->
var isOpen by remember(selectedGroup) { mutableStateOf(false) }
Column(Modifier.padding(5.dp)) {
GFWidget(crit, selectedGroup.group, fdbk, vm, global to byCriteria, isOpen) { isOpen = !isOpen }
GFWidget(crit, selectedGroup.group, fdbk, vm, global to byCriteria, isOpen, showDesc = true) { isOpen = !isOpen }
Spacer(Modifier.height(5.dp))
}
}
@@ -113,11 +113,11 @@ fun GroupsGradingView(data: GroupGrading, token: Navigator.NavToken) {
Box(Modifier.padding(5.dp)) {
GFWidget(
vm.global, selectedGroup.group, fdbk, vm, global to byCriteria, true,
(byCriteria ?: listOf()).flatMap { (_, it) ->
markOverridden = (byCriteria ?: listOf()).flatMap { (_, it) ->
it.overrides.mapNotNull { o ->
o.second?.let { _ -> o.first.id.value }
}
}.toSet()
}.toSet(), overrideName = "Global grade"
) {}
}
}
@@ -158,26 +158,33 @@ private fun gradeState(crit: GroupsGradingVM.CritData, current: Grade?): Grade =
}
@Composable
fun GFWidget(crit: GroupsGradingVM.CritData, gr: Group, feedback: GroupsGradingVM.FeedbackData, vm: GroupsGradingVM, key: Any, isOpen: Boolean, markOverridden: Set<UUID> = setOf(), onToggle: () -> Unit) = Surface(
Modifier.fillMaxWidth(),
shape = MaterialTheme.shapes.medium,
shadowElevation = 3.dp
) {
fun GFWidget(
crit: GroupsGradingVM.CritData, gr: Group, feedback: GroupsGradingVM.FeedbackData, vm: GroupsGradingVM, key: Any,
isOpen: Boolean, showDesc: Boolean = false, overrideName: String? = null, markOverridden: Set<UUID> = setOf(),
onToggle: () -> Unit
) = Surface(Modifier.fillMaxWidth(), shape = MaterialTheme.shapes.medium, shadowElevation = 3.dp) {
Column {
Surface(tonalElevation = 5.dp) {
Row(Modifier.fillMaxWidth().clickable { onToggle() }.padding(10.dp)) {
Icon(if(isOpen) ChevronDown else ChevronRight, "Toggle criterion detail grading", Modifier.align(Alignment.CenterVertically))
Spacer(Modifier.width(5.dp))
Text(crit.criterion.name, Modifier.align(Alignment.CenterVertically), style = MaterialTheme.typography.bodyLarge)
Spacer(Modifier.width(5.dp))
feedback.groupLevel?.grade?.let {
Row(Modifier.align(Alignment.Bottom)) {
ProvideTextStyle(MaterialTheme.typography.bodySmall) {
Text("(Grade: ")
it.render()
Text(")")
Column(Modifier.align(Alignment.CenterVertically)) {
Row {
Text(overrideName ?: crit.criterion.name, style = MaterialTheme.typography.bodyLarge)
Spacer(Modifier.width(5.dp))
feedback.groupLevel?.grade?.let {
Row(Modifier.align(Alignment.Bottom)) {
ProvideTextStyle(MaterialTheme.typography.bodySmall) {
Text("(Grade: ")
it.render()
Text(")")
}
}
}
}
if(showDesc) {
Text(crit.criterion.desc, fontStyle = FontStyle.Italic, modifier = Modifier.padding(horizontal = 10.dp, vertical = 5.dp).fillMaxWidth())
}
}
}
}
@@ -204,7 +211,7 @@ fun GFWidget(crit: GroupsGradingVM.CritData, gr: Group, feedback: GroupsGradingV
Column(Modifier.padding(10.dp)) {
Text("Individual overrides", style = MaterialTheme.typography.bodyLarge)
feedback.overrides.forEach { (student, it) ->
var enable by remember(key, it) { mutableStateOf(false) }
var enable by remember(key, it) { mutableStateOf(it != null) }
var maybeRemoving by remember(key, it) { mutableStateOf(false) }
var sGrade by remember(key, it) { mutableStateOf(gradeState(crit, it?.grade ?: grade)) }
var sText by remember(key, it) { mutableStateOf(it?.feedback ?: "") }

View File

@@ -137,8 +137,8 @@ fun GroupsView(vm: EditionVM) = Row(Modifier.fillMaxSize()) {
Column(Modifier.weight(0.5f)) {
Text("Grade Summary: ", style = MaterialTheme.typography.headlineSmall)
Surface(shape = MaterialTheme.shapes.medium, color = Color.White) {
LazyColumn {
Surface(shape = MaterialTheme.shapes.medium, color = Color.White, shadowElevation = 1.dp) {
LazyColumn(Modifier.fillMaxHeight()) {
item {
Surface(tonalElevation = 15.dp) {
Row(Modifier.padding(10.dp)) {

View File

@@ -77,7 +77,7 @@ class EditionVM(val edition: Edition, val course: Course) : ViewModel() {
val (grade, memberOf, override) = when(asg.type) {
AssignmentType.GROUP -> {
val asGroup = asg.globalCriterion.feedbacks.find { it.asGroupFeedback?.id in groupIds }
val solo = null // asg.globalCriterion.feedbacks.find { it.forStudentsOverrideIfGroup.any { over -> over.student == st } } // TODO
val solo = asg.globalCriterion.feedbacks.find { it.forStudentsOverrideIfGroup.any { over -> over.student == st } }
val gr = (solo ?: asGroup)?.let { Grade.fromAssignment(asg.globalCriterion, it) }
gr to asGroup?.asGroupFeedback app (solo != null)
}

View File

@@ -78,12 +78,11 @@ class GroupsGradingVM(val course: Course, val edition: Edition, val base: BaseAs
}
private fun Transaction.getOverrides(group: Group, fd: BaseFeedback): List<Pair<Student, FeedbackItem?>> {
// val feedbacks = fd.forStudentsOverrideIfGroup.filter { it.group.id == group.id }.associateBy { it.student.id }
//
// return group.students.map {
// it.student to feedbacks[it.student.id]?.let { sof -> FeedbackItem.fromDb(sof.feedback) }
// }
return listOf() // TODO!!!
val feedbacks = fd.forStudentsOverrideIfGroup.filter { it.group.id == group.id }.associateBy { it.student.id }
return group.students.map {
it.student to feedbacks[it.student.id]?.let { sof -> FeedbackItem.fromDb(sof.feedback) }
}
}
fun focusGroup(idx: Int) {