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 groupId = reference("group_id", Groups.id)
val studentId = reference("student_id", Students.id) val studentId = reference("student_id", Students.id)
val feedbackId = reference("feedback_id", BaseFeedbacks.id) val feedbackId = reference("feedback_id", BaseFeedbacks.id)
val overrides = reference("overrides", GroupFeedbacks.feedbackId) val overrides = reference("overrides", BaseFeedbacks.id)
} }
object SoloFeedbacks : CompositeIdTable("soloFdbks") { 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) } val selectedGroup = remember(focus, groups) { groups.getOrNull(focus) }
Column(Modifier.padding(10.dp)) { 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}") Text("Group assignment in ${vm.course.name} - ${vm.edition.name}")
Spacer(Modifier.height(5.dp)) Spacer(Modifier.height(5.dp))
Row(Modifier.fillMaxSize()) { Row(Modifier.fillMaxSize()) {
@@ -104,7 +104,7 @@ fun GroupsGradingView(data: GroupGrading, token: Navigator.NavToken) {
items(byCriteria ?: listOf()) { (crit, fdbk) -> items(byCriteria ?: listOf()) { (crit, fdbk) ->
var isOpen by remember(selectedGroup) { mutableStateOf(false) } var isOpen by remember(selectedGroup) { mutableStateOf(false) }
Column(Modifier.padding(5.dp)) { 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)) Spacer(Modifier.height(5.dp))
} }
} }
@@ -113,11 +113,11 @@ fun GroupsGradingView(data: GroupGrading, token: Navigator.NavToken) {
Box(Modifier.padding(5.dp)) { Box(Modifier.padding(5.dp)) {
GFWidget( GFWidget(
vm.global, selectedGroup.group, fdbk, vm, global to byCriteria, true, vm.global, selectedGroup.group, fdbk, vm, global to byCriteria, true,
(byCriteria ?: listOf()).flatMap { (_, it) -> markOverridden = (byCriteria ?: listOf()).flatMap { (_, it) ->
it.overrides.mapNotNull { o -> it.overrides.mapNotNull { o ->
o.second?.let { _ -> o.first.id.value } o.second?.let { _ -> o.first.id.value }
} }
}.toSet() }.toSet(), overrideName = "Global grade"
) {} ) {}
} }
} }
@@ -158,17 +158,19 @@ private fun gradeState(crit: GroupsGradingVM.CritData, current: Grade?): Grade =
} }
@Composable @Composable
fun GFWidget(crit: GroupsGradingVM.CritData, gr: Group, feedback: GroupsGradingVM.FeedbackData, vm: GroupsGradingVM, key: Any, isOpen: Boolean, markOverridden: Set<UUID> = setOf(), onToggle: () -> Unit) = Surface( fun GFWidget(
Modifier.fillMaxWidth(), crit: GroupsGradingVM.CritData, gr: Group, feedback: GroupsGradingVM.FeedbackData, vm: GroupsGradingVM, key: Any,
shape = MaterialTheme.shapes.medium, isOpen: Boolean, showDesc: Boolean = false, overrideName: String? = null, markOverridden: Set<UUID> = setOf(),
shadowElevation = 3.dp onToggle: () -> Unit
) { ) = Surface(Modifier.fillMaxWidth(), shape = MaterialTheme.shapes.medium, shadowElevation = 3.dp) {
Column { Column {
Surface(tonalElevation = 5.dp) { Surface(tonalElevation = 5.dp) {
Row(Modifier.fillMaxWidth().clickable { onToggle() }.padding(10.dp)) { Row(Modifier.fillMaxWidth().clickable { onToggle() }.padding(10.dp)) {
Icon(if(isOpen) ChevronDown else ChevronRight, "Toggle criterion detail grading", Modifier.align(Alignment.CenterVertically)) Icon(if(isOpen) ChevronDown else ChevronRight, "Toggle criterion detail grading", Modifier.align(Alignment.CenterVertically))
Spacer(Modifier.width(5.dp)) Spacer(Modifier.width(5.dp))
Text(crit.criterion.name, Modifier.align(Alignment.CenterVertically), style = MaterialTheme.typography.bodyLarge) Column(Modifier.align(Alignment.CenterVertically)) {
Row {
Text(overrideName ?: crit.criterion.name, style = MaterialTheme.typography.bodyLarge)
Spacer(Modifier.width(5.dp)) Spacer(Modifier.width(5.dp))
feedback.groupLevel?.grade?.let { feedback.groupLevel?.grade?.let {
Row(Modifier.align(Alignment.Bottom)) { Row(Modifier.align(Alignment.Bottom)) {
@@ -180,6 +182,11 @@ fun GFWidget(crit: GroupsGradingVM.CritData, gr: Group, feedback: GroupsGradingV
} }
} }
} }
if(showDesc) {
Text(crit.criterion.desc, fontStyle = FontStyle.Italic, modifier = Modifier.padding(horizontal = 10.dp, vertical = 5.dp).fillMaxWidth())
}
}
}
} }
if(isOpen) { if(isOpen) {
@@ -204,7 +211,7 @@ fun GFWidget(crit: GroupsGradingVM.CritData, gr: Group, feedback: GroupsGradingV
Column(Modifier.padding(10.dp)) { Column(Modifier.padding(10.dp)) {
Text("Individual overrides", style = MaterialTheme.typography.bodyLarge) Text("Individual overrides", style = MaterialTheme.typography.bodyLarge)
feedback.overrides.forEach { (student, it) -> 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 maybeRemoving by remember(key, it) { mutableStateOf(false) }
var sGrade by remember(key, it) { mutableStateOf(gradeState(crit, it?.grade ?: grade)) } var sGrade by remember(key, it) { mutableStateOf(gradeState(crit, it?.grade ?: grade)) }
var sText by remember(key, it) { mutableStateOf(it?.feedback ?: "") } 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)) { Column(Modifier.weight(0.5f)) {
Text("Grade Summary: ", style = MaterialTheme.typography.headlineSmall) Text("Grade Summary: ", style = MaterialTheme.typography.headlineSmall)
Surface(shape = MaterialTheme.shapes.medium, color = Color.White) { Surface(shape = MaterialTheme.shapes.medium, color = Color.White, shadowElevation = 1.dp) {
LazyColumn { LazyColumn(Modifier.fillMaxHeight()) {
item { item {
Surface(tonalElevation = 15.dp) { Surface(tonalElevation = 15.dp) {
Row(Modifier.padding(10.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) { val (grade, memberOf, override) = when(asg.type) {
AssignmentType.GROUP -> { AssignmentType.GROUP -> {
val asGroup = asg.globalCriterion.feedbacks.find { it.asGroupFeedback?.id in groupIds } 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) } val gr = (solo ?: asGroup)?.let { Grade.fromAssignment(asg.globalCriterion, it) }
gr to asGroup?.asGroupFeedback app (solo != null) 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?>> { 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 } val feedbacks = fd.forStudentsOverrideIfGroup.filter { it.group.id == group.id }.associateBy { it.student.id }
//
// return group.students.map { return group.students.map {
// it.student to feedbacks[it.student.id]?.let { sof -> FeedbackItem.fromDb(sof.feedback) } it.student to feedbacks[it.student.id]?.let { sof -> FeedbackItem.fromDb(sof.feedback) }
// } }
return listOf() // TODO!!!
} }
fun focusGroup(idx: Int) { fun focusGroup(idx: Int) {