Fix database schema bug, fix UI glitch

This commit is contained in:
jay-tux 2025-03-20 17:21:05 +01:00
parent 4da4b0bb85
commit 034b018e2d
Signed by: jay-tux
GPG Key ID: 84302006B056926E
5 changed files with 27 additions and 23 deletions

View File

@ -115,7 +115,7 @@ object StudentToGroupEvaluation : CompositeIdTable("stToGrEv") {
val grade = varchar("grade", 32) val grade = varchar("grade", 32)
val note = text("note") val note = text("note")
override val primaryKey = PrimaryKey(peerEvaluationId) override val primaryKey = PrimaryKey(peerEvaluationId, studentId)
} }
object StudentToStudentEvaluation : CompositeIdTable("stToStEv") { object StudentToStudentEvaluation : CompositeIdTable("stToStEv") {

View File

@ -255,11 +255,11 @@ fun PeerEvaluationView(state: PeerEvaluationState) {
Column(Modifier.padding(10.dp)) { Column(Modifier.padding(10.dp)) {
TabRow(idx) { TabRow(idx) {
contents.forEachIndexed { i, it -> contents.forEachIndexed { i, it ->
Tab(idx == i, { idx = i }) { Text(it.group.name) } Tab(idx == i, { idx = i; editing = null }) { Text(it.group.name) }
} }
} }
Spacer(Modifier.height(10.dp)) Spacer(Modifier.height(10.dp))
Row { Row {
val current = contents[idx] val current = contents[idx]
val horScroll = rememberLazyListState() val horScroll = rememberLazyListState()
@ -316,7 +316,7 @@ fun PeerEvaluationView(state: PeerEvaluationState) {
item { VLine() } item { VLine() }
} }
} }
MeasuredLazyColumn { MeasuredLazyColumn(key = idx) {
measuredItem { HLine() } measuredItem { HLine() }
items(current.students) { (from, glob, map) -> items(current.students) { (from, glob, map) ->
Row(Modifier.height(cellSize)) { Row(Modifier.height(cellSize)) {
@ -348,8 +348,9 @@ fun PeerEvaluationView(state: PeerEvaluationState) {
editing?.let { editing?.let {
Column(Modifier.weight(0.5f)) { Column(Modifier.weight(0.5f)) {
val (from, to, data) = it val (from, to, data) = it
var sGrade by remember(idx) { mutableStateOf(data?.grade ?: "") }
var sMsg by remember(idx) { mutableStateOf(data?.feedback ?: "") } var sGrade by remember(editing) { mutableStateOf(data?.grade ?: "") }
var sMsg by remember(editing) { mutableStateOf(data?.feedback ?: "") }
Box(Modifier.padding(5.dp)) { Box(Modifier.padding(5.dp)) {
to?.let { s2 -> to?.let { s2 ->
@ -365,7 +366,7 @@ fun PeerEvaluationView(state: PeerEvaluationState) {
OutlinedTextField(sGrade, { sGrade = it }, Modifier.weight(0.2f)) OutlinedTextField(sGrade, { sGrade = it }, Modifier.weight(0.2f))
Spacer(Modifier.weight(0.6f)) Spacer(Modifier.weight(0.6f))
Button( Button(
{ state.upsertIndividualFeedback(from, to, sMsg, sGrade) }, { state.upsertIndividualFeedback(from, to, sGrade, sMsg); editing = null },
Modifier.weight(0.2f).align(Alignment.CenterVertically), Modifier.weight(0.2f).align(Alignment.CenterVertically),
enabled = sGrade.isNotBlank() || sMsg.isNotBlank() enabled = sGrade.isNotBlank() || sMsg.isNotBlank()
) { ) {
@ -386,7 +387,7 @@ fun PeerEvaluationView(state: PeerEvaluationState) {
Row { Row {
Text("Group-level notes", Modifier.weight(1f).align(Alignment.CenterVertically), fontWeight = FontWeight.Bold) Text("Group-level notes", Modifier.weight(1f).align(Alignment.CenterVertically), fontWeight = FontWeight.Bold)
Button( Button(
{ state.upsertGroupFeedback(current.group, groupLevel) }, { state.upsertGroupFeedback(current.group, groupLevel); editing = null },
enabled = groupLevel != contents[idx].content enabled = groupLevel != contents[idx].content
) { Text("Update") } ) { Text("Update") }
} }

View File

@ -24,8 +24,8 @@ interface MeasuredLazyItemScope : LazyItemScope {
} }
@Composable @Composable
fun MeasuredLazyColumn(modifier: Modifier = Modifier, content: MeasuredLazyListScope.() -> Unit) { fun MeasuredLazyColumn(modifier: Modifier = Modifier, key: Any? = null, content: MeasuredLazyListScope.() -> Unit) {
val measuredWidth = remember { mutableStateOf(0.dp) } val measuredWidth = remember(key) { mutableStateOf(0.dp) }
LazyColumn(modifier.onGloballyPositioned { LazyColumn(modifier.onGloballyPositioned {
measuredWidth.value = it.size.width.dp measuredWidth.value = it.size.width.dp
}) { }) {

View File

@ -415,19 +415,22 @@ fun SelectEditDeleteRow(
@Composable @Composable
fun FromTo(size: Dp) { fun FromTo(size: Dp) {
Box(Modifier.width(size).height(size)) { var w by remember { mutableStateOf(0) }
var h by remember { mutableStateOf(0) }
Box(Modifier.width(size).height(size).onGloballyPositioned {
w = it.size.width
h = it.size.height
}) {
Box(Modifier.align(Alignment.BottomStart)) { Box(Modifier.align(Alignment.BottomStart)) {
Text("Evaluator", fontWeight = FontWeight.Bold) Text("Evaluator", fontWeight = FontWeight.Bold)
} }
Box( Box {
Modifier.align(Alignment.TopEnd)
) {
Text("Evaluated", Modifier.graphicsLayer { Text("Evaluated", Modifier.graphicsLayer {
rotationZ = -90f rotationZ = -90f
translationX = w - 15f
translationY = h - 15f
transformOrigin = TransformOrigin(0f, 0.5f) transformOrigin = TransformOrigin(0f, 0.5f)
translationX = size.value / 2f - 15f
translationY = size.value - 15f
}, fontWeight = FontWeight.Bold) }, fontWeight = FontWeight.Bold)
} }
} }
@ -442,7 +445,7 @@ fun PEGradeWidget(
) = Box(modifier.padding(2.dp)) { ) = Box(modifier.padding(2.dp)) {
Selectable(isSelected, onSelect, onDeselect) { Selectable(isSelected, onSelect, onDeselect) {
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Text(grade?.let { if(it.grade.isNotBlank()) it.grade else if(it.feedback.isNotBlank()) "n/a" else null } ?: "none") Text(grade?.let { if(it.grade.isNotBlank()) it.grade else if(it.feedback.isNotBlank()) "(other)" else null } ?: "none")
} }
} }
} }

View File

@ -604,17 +604,17 @@ class PeerEvaluationState(val evaluation: PeerEvaluation) {
val contents = RawDbState { loadContents() } val contents = RawDbState { loadContents() }
private fun Transaction.loadContents(): List<GroupEntry> { private fun Transaction.loadContents(): List<GroupEntry> {
val found = PeerEvaluationContents.selectAll().where { val found = (Groups leftJoin PeerEvaluationContents).selectAll().where {
PeerEvaluationContents.peerEvaluationId eq evaluation.id Groups.editionId eq evaluation.edition.id
}.associate { gc -> }.associate { gc ->
val group = Group[gc[PeerEvaluationContents.groupId]] val group = Group[gc[Groups.id]]
val content = gc[PeerEvaluationContents.content] val content = gc[PeerEvaluationContents.content] ?: ""
val students = group.students.map { student1 -> val students = group.students.map { student1 ->
val others = group.students.map { student2 -> val others = group.students.map { student2 ->
val eval = StudentToStudentEvaluation.selectAll().where { val eval = StudentToStudentEvaluation.selectAll().where {
StudentToStudentEvaluation.peerEvaluationId eq evaluation.id and StudentToStudentEvaluation.peerEvaluationId eq evaluation.id and
(StudentToStudentEvaluation.studentIdTo eq student1.id) and (StudentToStudentEvaluation.studentIdFrom eq student1.id) and
(StudentToStudentEvaluation.studentIdFrom eq student2.id) (StudentToStudentEvaluation.studentIdTo eq student2.id)
}.firstOrNull() }.firstOrNull()
student2 to eval?.let { student2 to eval?.let {
Student2StudentEntry( Student2StudentEntry(