fix: kleine fixes
This commit is contained in:
parent
0abe9b1bce
commit
7f1c66c757
5 changed files with 131 additions and 44 deletions
|
@ -3,6 +3,7 @@
|
||||||
import UsingQueryResult from "@/components/UsingQueryResult.vue";
|
import UsingQueryResult from "@/components/UsingQueryResult.vue";
|
||||||
import { useAssignmentSubmissionsQuery } from "@/queries/assignments.ts";
|
import { useAssignmentSubmissionsQuery } from "@/queries/assignments.ts";
|
||||||
import type { SubmissionsResponse } from "@/controllers/submissions.ts";
|
import type { SubmissionsResponse } from "@/controllers/submissions.ts";
|
||||||
|
import {watch} from "vue";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
group: object;
|
group: object;
|
||||||
|
@ -11,6 +12,8 @@
|
||||||
goToGroupSubmissionLink: (groupNo: number) => void;
|
goToGroupSubmissionLink: (groupNo: number) => void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<(e: "update:hasSubmission", hasSubmission: boolean) => void>();
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const submissionsQuery = useAssignmentSubmissionsQuery(
|
const submissionsQuery = useAssignmentSubmissionsQuery(
|
||||||
() => props.classId,
|
() => props.classId,
|
||||||
|
@ -18,6 +21,16 @@
|
||||||
() => props.group.originalGroupNo,
|
() => props.group.originalGroupNo,
|
||||||
() => true,
|
() => true,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => submissionsQuery.data.value,
|
||||||
|
(data) => {
|
||||||
|
if (data) {
|
||||||
|
emit("update:hasSubmission", data.submissions.length > 0);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -355,7 +355,7 @@ function removeStudent(groupIndex: number, student: StudentItem): void {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-card class="pa-4">
|
<v-card class="pa-4 minimal-card">
|
||||||
<!-- Current groups and unassigned students Preview -->
|
<!-- Current groups and unassigned students Preview -->
|
||||||
<div v-if="showGroupsPreview" class="mb-6">
|
<div v-if="showGroupsPreview" class="mb-6">
|
||||||
<h3 class="mb-2">{{ t("current-groups") }}</h3>
|
<h3 class="mb-2">{{ t("current-groups") }}</h3>
|
||||||
|
@ -364,20 +364,13 @@ function removeStudent(groupIndex: number, student: StudentItem): void {
|
||||||
<label>{{ currentGroups.length }}</label>
|
<label>{{ currentGroups.length }}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="unassignedStudents.length > 0" class="mt-3">
|
|
||||||
<strong>{{ t("unassigned-students") }}:</strong>
|
|
||||||
<div class="d-flex flex-wrap">
|
|
||||||
<label>{{ unassignedStudents.length }}</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<v-row justify="center" class="mb-4">
|
<v-row justify="center" class="mb-4">
|
||||||
<v-btn color="primary" @click="activeDialog = 'random'">
|
<v-btn color="primary" @click="activeDialog = 'random'" prepend-icon="mdi-shuffle">
|
||||||
{{ t("randomly-create-groups") }}
|
{{ t("random-grouping") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn color="secondary" class="ml-4" @click="activeDialog = 'dragdrop'">
|
<v-btn color="secondary" class="ml-4" @click="activeDialog = 'dragdrop'" prepend-icon="mdi-drag">
|
||||||
{{ t("drag-and-drop") }}
|
{{ t("drag-and-drop") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
@ -388,8 +381,8 @@ function removeStudent(groupIndex: number, student: StudentItem): void {
|
||||||
@update:model-value="(val) => (val ? (activeDialog = 'random') : (activeDialog = null))"
|
@update:model-value="(val) => (val ? (activeDialog = 'random') : (activeDialog = null))"
|
||||||
max-width="600"
|
max-width="600"
|
||||||
>
|
>
|
||||||
<v-card>
|
<v-card class="custom-dialog">
|
||||||
<v-card-title>{{ t("randomly-create-groups") }}</v-card-title>
|
<v-card-title class="dialog-title">{{ t("auto-generate-groups") }}</v-card-title>
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-row align="center">
|
<v-row align="center">
|
||||||
<v-col cols="6">
|
<v-col cols="6">
|
||||||
|
@ -442,7 +435,7 @@ function removeStudent(groupIndex: number, student: StudentItem): void {
|
||||||
</div>
|
</div>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
|
|
||||||
<v-card-actions>
|
<v-card-actions class="dialog-actions">
|
||||||
<v-spacer/>
|
<v-spacer/>
|
||||||
<v-btn text @click="activeDialog = null">{{ t("cancel") }}</v-btn>
|
<v-btn text @click="activeDialog = null">{{ t("cancel") }}</v-btn>
|
||||||
<v-btn
|
<v-btn
|
||||||
|
@ -462,8 +455,8 @@ function removeStudent(groupIndex: number, student: StudentItem): void {
|
||||||
@update:model-value="(val) => (val ? (activeDialog = 'dragdrop') : (activeDialog = null))"
|
@update:model-value="(val) => (val ? (activeDialog = 'dragdrop') : (activeDialog = null))"
|
||||||
max-width="900"
|
max-width="900"
|
||||||
>
|
>
|
||||||
<v-card>
|
<v-card class="custom-dialog">
|
||||||
<v-card-title class="d-flex justify-space-between align-center">
|
<v-card-title class=" dialog-title d-flex justify-space-between align-center">
|
||||||
<div>{{ t("drag-and-drop") }}</div>
|
<div>{{ t("drag-and-drop") }}</div>
|
||||||
<v-btn color="primary" small @click="addNewGroup">+</v-btn>
|
<v-btn color="primary" small @click="addNewGroup">+</v-btn>
|
||||||
</v-card-title>
|
</v-card-title>
|
||||||
|
@ -603,4 +596,60 @@ function removeStudent(groupIndex: number, student: StudentItem): void {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.custom-dialog {
|
||||||
|
border-radius: 16px;
|
||||||
|
padding: 24px;
|
||||||
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-title {
|
||||||
|
color: #00796b; /* teal-like green */
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 12px;
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-btn.custom-green {
|
||||||
|
background-color: #43a047;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-btn.custom-green:hover {
|
||||||
|
background-color: #388e3c
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-btn.custom-blue {
|
||||||
|
background-color: #1e88e5;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-btn.custom-blue:hover {
|
||||||
|
background-color: #1565c0 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-btn.cancel-button {
|
||||||
|
background-color: #e0f2f1;
|
||||||
|
color: #00695c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.minimal-card {
|
||||||
|
box-shadow: none; /* remove card shadow */
|
||||||
|
border: none; /* remove border */
|
||||||
|
background-color: transparent; /* make background transparent */
|
||||||
|
padding: 0; /* reduce padding */
|
||||||
|
margin-bottom: 1rem; /* keep some spacing below */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Optionally, keep some padding only around buttons */
|
||||||
|
.minimal-card > .v-row {
|
||||||
|
padding: 1rem 0; /* give vertical padding around buttons */
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -36,6 +36,7 @@ const assignmentTitle = ref("");
|
||||||
|
|
||||||
const selectedLearningPath = ref<LearningPath | undefined>(undefined);
|
const selectedLearningPath = ref<LearningPath | undefined>(undefined);
|
||||||
const lpIsSelected = ref(false);
|
const lpIsSelected = ref(false);
|
||||||
|
|
||||||
watch(learningPathsQueryResults.data, (data) => {
|
watch(learningPathsQueryResults.data, (data) => {
|
||||||
const hruidFromRoute = route.query.hruid?.toString();
|
const hruidFromRoute = route.query.hruid?.toString();
|
||||||
if (!hruidFromRoute || !data) return;
|
if (!hruidFromRoute || !data) return;
|
||||||
|
@ -61,9 +62,8 @@ async function submitFormHandler(): Promise<void> {
|
||||||
if (!valid) return;
|
if (!valid) return;
|
||||||
|
|
||||||
const lp = lpIsSelected.value
|
const lp = lpIsSelected.value
|
||||||
? route.query.hruid
|
? route.query.hruid?.toString()
|
||||||
: selectedLearningPath.value?.hruid;
|
: selectedLearningPath.value?.hruid;
|
||||||
|
|
||||||
if (!lp) {
|
if (!lp) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -71,10 +71,10 @@ async function submitFormHandler(): Promise<void> {
|
||||||
const assignmentDTO: AssignmentDTO = {
|
const assignmentDTO: AssignmentDTO = {
|
||||||
id: 0,
|
id: 0,
|
||||||
within: selectedClass.value?.id || "",
|
within: selectedClass.value?.id || "",
|
||||||
title: assignmentTitle.value.toString(),
|
title: assignmentTitle.value,
|
||||||
description: "",
|
description: "",
|
||||||
learningPath: lp.toString(),
|
learningPath: lp,
|
||||||
language: language.value.toString(),
|
language: language.value,
|
||||||
deadline: null,
|
deadline: null,
|
||||||
groups: [],
|
groups: [],
|
||||||
};
|
};
|
||||||
|
@ -83,9 +83,9 @@ async function submitFormHandler(): Promise<void> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const learningPathRules = [
|
const learningPathRules = [
|
||||||
(value: any) => {
|
(value: LearningPath): string | boolean => {
|
||||||
|
|
||||||
if(lpIsSelected.value) return;
|
if(lpIsSelected.value) return true;
|
||||||
|
|
||||||
if (!value) return t("lp-required");
|
if (!value) return t("lp-required");
|
||||||
|
|
||||||
|
@ -146,17 +146,17 @@ const classRules = [
|
||||||
v-slot="{ data }: { data: LearningPath[] }"
|
v-slot="{ data }: { data: LearningPath[] }"
|
||||||
>
|
>
|
||||||
<v-combobox
|
<v-combobox
|
||||||
|
v-model="selectedLearningPath"
|
||||||
:items="data"
|
:items="data"
|
||||||
:label="t('choose-lp')"
|
:label="t('choose-lp')"
|
||||||
:rules="lpIsSelected ? [] : learningPathRules"
|
:rules="lpIsSelected ? [] : learningPathRules"
|
||||||
variant="solo-filled"
|
variant="solo-filled"
|
||||||
clearable
|
clearable
|
||||||
:model-value="lpIsSelected ? data.find(lp => lp.hruid === route.query.hruid?.toString()) : selectedLearningPath"
|
|
||||||
item-title="title"
|
item-title="title"
|
||||||
item-value="hruid"
|
|
||||||
:disabled="lpIsSelected"
|
:disabled="lpIsSelected"
|
||||||
return-object
|
return-object
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</using-query-result>
|
</using-query-result>
|
||||||
|
|
||||||
<!-- Klas keuze -->
|
<!-- Klas keuze -->
|
||||||
|
|
|
@ -60,6 +60,9 @@ watchEffect(() => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const hasSubmissions = ref<boolean>(false);
|
||||||
|
|
||||||
|
|
||||||
const allGroups = computed(() => {
|
const allGroups = computed(() => {
|
||||||
const groups = groupsQueryResult.data.value?.groups;
|
const groups = groupsQueryResult.data.value?.groups;
|
||||||
|
|
||||||
|
@ -73,7 +76,7 @@ const allGroups = computed(() => {
|
||||||
groupNo: index + 1, // New group number that will be used
|
groupNo: index + 1, // New group number that will be used
|
||||||
name: `${t("group")} ${index + 1}`,
|
name: `${t("group")} ${index + 1}`,
|
||||||
members: group.members,
|
members: group.members,
|
||||||
originalGroupNo: group.groupNumber, // Keep original number if needed
|
originalGroupNo: group.groupNumber
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -298,29 +301,42 @@ async function handleGroupsUpdated(updatedGroups: string[][]): Promise<void> {
|
||||||
<!-- A pop up to show group members -->
|
<!-- A pop up to show group members -->
|
||||||
<v-dialog
|
<v-dialog
|
||||||
v-model="dialog"
|
v-model="dialog"
|
||||||
max-width="50%"
|
max-width="600"
|
||||||
|
persistent
|
||||||
>
|
>
|
||||||
<v-card>
|
<v-card class="pa-4 rounded-xl elevation-6 group-members-dialog">
|
||||||
<v-card-title class="headline">{{ t("members") }}</v-card-title>
|
<v-card-title class="text-h6 font-weight-bold">
|
||||||
|
{{ t("members") }}
|
||||||
|
</v-card-title>
|
||||||
|
|
||||||
|
<v-divider class="my-2" />
|
||||||
|
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-list>
|
<v-list>
|
||||||
<v-list-item
|
<v-list-item
|
||||||
v-for="(member, index) in selectedGroup.members"
|
v-for="(member, index) in selectedGroup.members"
|
||||||
:key="index"
|
:key="index"
|
||||||
|
class="py-2"
|
||||||
>
|
>
|
||||||
<v-list-item-content>
|
<v-list-item-content>
|
||||||
<v-list-item-title
|
<v-list-item-title class="text-body-1">
|
||||||
>{{ member.firstName + " " + member.lastName }}
|
{{ member.firstName }} {{ member.lastName }}
|
||||||
</v-list-item-title>
|
</v-list-item-title>
|
||||||
</v-list-item-content>
|
</v-list-item-content>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
</v-list>
|
</v-list>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-card-actions>
|
|
||||||
|
<v-divider class="my-2" />
|
||||||
|
|
||||||
|
<v-card-actions class="justify-end">
|
||||||
<v-btn
|
<v-btn
|
||||||
color="primary"
|
color="primary"
|
||||||
|
variant="outlined"
|
||||||
@click="dialog = false"
|
@click="dialog = false"
|
||||||
>Close
|
prepend-icon="mdi-close-circle"
|
||||||
|
>
|
||||||
|
{{ t("close") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
|
@ -345,6 +361,7 @@ async function handleGroupsUpdated(updatedGroups: string[][]): Promise<void> {
|
||||||
<v-btn
|
<v-btn
|
||||||
@click="editGroups = true"
|
@click="editGroups = true"
|
||||||
variant="text"
|
variant="text"
|
||||||
|
:disabled="hasSubmissions"
|
||||||
>
|
>
|
||||||
<v-icon>mdi-pencil</v-icon>
|
<v-icon>mdi-pencil</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
@ -358,11 +375,9 @@ async function handleGroupsUpdated(updatedGroups: string[][]): Promise<void> {
|
||||||
>
|
>
|
||||||
<td>
|
<td>
|
||||||
<v-btn
|
<v-btn
|
||||||
@click="openGroupDetails(g)"
|
|
||||||
variant="text"
|
variant="text"
|
||||||
>
|
>
|
||||||
{{ g.name }}
|
{{ g.name }}
|
||||||
<v-icon end>mdi-menu-right</v-icon>
|
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
@ -383,16 +398,18 @@ async function handleGroupsUpdated(updatedGroups: string[][]): Promise<void> {
|
||||||
:class-id="classId"
|
:class-id="classId"
|
||||||
:language="lang"
|
:language="lang"
|
||||||
:go-to-group-submission-link="goToGroupSubmissionLink"
|
:go-to-group-submission-link="goToGroupSubmissionLink"
|
||||||
|
@update:hasSubmission="(hasSubmission) => hasSubmissions = hasSubmission"
|
||||||
|
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<!-- Edit icon -->
|
<!-- Edit icon -->
|
||||||
<td>
|
<td>
|
||||||
<v-btn
|
<v-btn
|
||||||
@click=""
|
@click="openGroupDetails(g)"
|
||||||
variant="text"
|
variant="text"
|
||||||
>
|
>
|
||||||
<v-icon color="red">mdi-delete</v-icon>
|
<v-icon>mdi-eye</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -416,16 +433,18 @@ async function handleGroupsUpdated(updatedGroups: string[][]): Promise<void> {
|
||||||
@close="editGroups = false"
|
@close="editGroups = false"
|
||||||
/>
|
/>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
|
|
||||||
|
<v-divider></v-divider>
|
||||||
|
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-btn
|
<v-spacer></v-spacer>
|
||||||
text
|
<v-btn text @click="editGroups = false">
|
||||||
@click="editGroups = false"
|
{{ t("cancel") }}
|
||||||
>{{ t("cancel") }}
|
</v-btn>
|
||||||
</v-btn
|
|
||||||
>
|
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
|
|
||||||
</v-container>
|
</v-container>
|
||||||
</using-query-result>
|
</using-query-result>
|
||||||
</div>
|
</div>
|
||||||
|
@ -557,4 +576,10 @@ main {
|
||||||
flex-basis: 100% !important;
|
flex-basis: 100% !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.group-members-dialog {
|
||||||
|
max-height: 80vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -146,7 +146,7 @@
|
||||||
|
|
||||||
<v-btn
|
<v-btn
|
||||||
v-if="isTeacher"
|
v-if="isTeacher"
|
||||||
color="primary"
|
:style="{ backgroundColor: '#0E6942' }"
|
||||||
class="mb-4 center-btn"
|
class="mb-4 center-btn"
|
||||||
@click="goToCreateAssignment"
|
@click="goToCreateAssignment"
|
||||||
>
|
>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue