feat: bezig met edit groups
This commit is contained in:
parent
cc31effd61
commit
936a34b709
4 changed files with 351 additions and 266 deletions
|
@ -27,6 +27,7 @@
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
"vue-i18n": "^11.1.2",
|
"vue-i18n": "^11.1.2",
|
||||||
"vue-router": "^4.5.0",
|
"vue-router": "^4.5.0",
|
||||||
|
"vuedraggable": "^2.24.3",
|
||||||
"vuetify": "^3.7.12",
|
"vuetify": "^3.7.12",
|
||||||
"wait-on": "^8.0.3"
|
"wait-on": "^8.0.3"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,75 +1,114 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from "vue";
|
import { ref, } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import draggable from "vuedraggable";
|
||||||
import UsingQueryResult from "@/components/UsingQueryResult.vue";
|
import { useI18n } from "vue-i18n";
|
||||||
import type { StudentsResponse } from "@/controllers/students.ts";
|
|
||||||
import { useClassStudentsQuery } from "@/queries/classes.ts";
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
classId: string | undefined;
|
classId: string | undefined;
|
||||||
groups: string[][];
|
groups: string[][];
|
||||||
}>();
|
}>();
|
||||||
const emit = defineEmits(["groupCreated"]);
|
const emit = defineEmits(["done", "groupsUpdated"]);
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const selectedStudents = ref([]);
|
const groupList = ref(props.groups.map(g => [...g])); // deep copy
|
||||||
|
const unassigned = ref<string[]>([]); // voor vrije studenten
|
||||||
|
|
||||||
const studentQueryResult = useClassStudentsQuery(() => props.classId, true);
|
function addNewGroup() {
|
||||||
|
groupList.value.push([]);
|
||||||
|
}
|
||||||
|
|
||||||
function filterStudents(data: StudentsResponse): { title: string; value: string }[] {
|
function removeGroup(index: number) {
|
||||||
const students = data.students;
|
unassigned.value.push(...groupList.value[index]);
|
||||||
const studentsInGroups = props.groups.flat();
|
groupList.value.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
return students
|
function saveChanges() {
|
||||||
?.map((st) => ({
|
emit("groupsUpdated", groupList.value);
|
||||||
title: `${st.firstName} ${st.lastName}`,
|
emit("done");
|
||||||
value: st.username,
|
}
|
||||||
}))
|
|
||||||
.filter((student) => !studentsInGroups.includes(student.value));
|
|
||||||
}
|
|
||||||
|
|
||||||
function createGroup(): void {
|
|
||||||
if (selectedStudents.value.length) {
|
|
||||||
// Extract only usernames (student.value)
|
|
||||||
const usernames = selectedStudents.value.map((student) => student.value);
|
|
||||||
emit("groupCreated", usernames);
|
|
||||||
selectedStudents.value = []; // Reset selection after creating group
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<using-query-result
|
<v-card>
|
||||||
:query-result="studentQueryResult"
|
<v-card-title>{{ t("edit-groups") }}</v-card-title>
|
||||||
v-slot="{ data }: { data: StudentsResponse }"
|
|
||||||
>
|
|
||||||
<h3>{{ t("create-groups") }}</h3>
|
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-combobox
|
<v-row>
|
||||||
v-model="selectedStudents"
|
<!-- Ongegroepeerde studenten -->
|
||||||
:items="filterStudents(data)"
|
<v-col cols="12" sm="4">
|
||||||
item-title="title"
|
<h4>{{ t("unassigned") }}</h4>
|
||||||
item-value="value"
|
<draggable
|
||||||
:label="t('choose-students')"
|
v-model="unassigned"
|
||||||
variant="outlined"
|
group="students"
|
||||||
clearable
|
item-key="username"
|
||||||
multiple
|
class="group-box"
|
||||||
hide-details
|
>
|
||||||
density="compact"
|
<template #item="{ element }">
|
||||||
chips
|
<v-chip>{{ element }}</v-chip>
|
||||||
append-inner-icon="mdi-magnify"
|
</template>
|
||||||
></v-combobox>
|
</draggable>
|
||||||
|
</v-col>
|
||||||
|
|
||||||
|
<!-- Bestaande groepen -->
|
||||||
|
<v-col
|
||||||
|
v-for="(group, i) in groupList"
|
||||||
|
:key="i"
|
||||||
|
cols="12"
|
||||||
|
sm="4"
|
||||||
|
>
|
||||||
|
<h4>{{ t("group") }} {{ i + 1 }}</h4>
|
||||||
|
<draggable
|
||||||
|
v-model="groupList[i]"
|
||||||
|
group="students"
|
||||||
|
item-key="username"
|
||||||
|
class="group-box"
|
||||||
|
>
|
||||||
|
<template #item="{ element }">
|
||||||
|
<v-chip>{{ element }}</v-chip>
|
||||||
|
</template>
|
||||||
|
</draggable>
|
||||||
|
|
||||||
|
<v-btn
|
||||||
|
color="error"
|
||||||
|
size="x-small"
|
||||||
|
@click="removeGroup(i)"
|
||||||
|
class="mt-2"
|
||||||
|
>
|
||||||
|
{{ t("remove-group") }}
|
||||||
|
</v-btn>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
|
||||||
<v-btn
|
<v-btn
|
||||||
@click="createGroup"
|
|
||||||
color="primary"
|
color="primary"
|
||||||
class="mt-2"
|
class="mt-4"
|
||||||
size="small"
|
@click="addNewGroup"
|
||||||
>
|
>
|
||||||
{{ t("create-group") }}
|
{{ t("add-group") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
</using-query-result>
|
<v-card-actions>
|
||||||
|
<v-btn
|
||||||
|
color="success"
|
||||||
|
@click="saveChanges"
|
||||||
|
>
|
||||||
|
{{ t("save") }}
|
||||||
|
</v-btn>
|
||||||
|
<v-btn
|
||||||
|
@click="$emit('done')"
|
||||||
|
variant="text"
|
||||||
|
>
|
||||||
|
{{ t("cancel") }}
|
||||||
|
</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped>
|
||||||
|
.group-box {
|
||||||
|
min-height: 100px;
|
||||||
|
border: 1px dashed #ccc;
|
||||||
|
padding: 8px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
background-color: #fafafa;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -17,7 +17,7 @@ import {descriptionRules, learningPathRules} from "@/utils/assignment-rules.ts";
|
||||||
import GroupSubmissionStatus from "@/components/GroupSubmissionStatus.vue"
|
import GroupSubmissionStatus from "@/components/GroupSubmissionStatus.vue"
|
||||||
import GroupProgressRow from "@/components/GroupProgressRow.vue"
|
import GroupProgressRow from "@/components/GroupProgressRow.vue"
|
||||||
import type {AssignmentDTO} from "@dwengo-1/common/dist/interfaces/assignment.ts";
|
import type {AssignmentDTO} from "@dwengo-1/common/dist/interfaces/assignment.ts";
|
||||||
import router from "@/router";
|
import GroupSelector from "@/components/assignments/GroupSelector.vue";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
classId: string;
|
classId: string;
|
||||||
|
@ -35,9 +35,12 @@ const {t} = useI18n();
|
||||||
const lang = ref();
|
const lang = ref();
|
||||||
const groups = ref<GroupDTO[] | GroupDTOId[]>([]);
|
const groups = ref<GroupDTO[] | GroupDTOId[]>([]);
|
||||||
const learningPath = ref();
|
const learningPath = ref();
|
||||||
|
const form = ref();
|
||||||
|
|
||||||
|
|
||||||
const editingLearningPath = ref(learningPath);
|
const editingLearningPath = ref(learningPath);
|
||||||
const description = ref("");
|
const description = ref("");
|
||||||
|
const editGroups = ref(false);
|
||||||
|
|
||||||
|
|
||||||
const assignmentQueryResult = useAssignmentQuery(() => props.classId, props.assignmentId);
|
const assignmentQueryResult = useAssignmentQuery(() => props.classId, props.assignmentId);
|
||||||
|
@ -111,7 +114,7 @@ function goToGroupSubmissionLink(groupNo: number): string | undefined {
|
||||||
|
|
||||||
const learningPathsQueryResults = useGetAllLearningPaths(lang);
|
const learningPathsQueryResults = useGetAllLearningPaths(lang);
|
||||||
|
|
||||||
const { mutate, data, isSuccess } = useUpdateAssignmentMutation();
|
const {mutate, data, isSuccess} = useUpdateAssignmentMutation();
|
||||||
|
|
||||||
watch([isSuccess, data], ([success, newData]) => {
|
watch([isSuccess, data], ([success, newData]) => {
|
||||||
if (success && newData?.assignment) {
|
if (success && newData?.assignment) {
|
||||||
|
@ -120,9 +123,10 @@ watch([isSuccess, data], ([success, newData]) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
async function saveChanges(): Promise<void> {
|
async function saveChanges(): Promise<void> {
|
||||||
|
const {valid} = await form.value.validate();
|
||||||
|
if (!valid) return;
|
||||||
|
|
||||||
isEditing.value = false;
|
isEditing.value = false;
|
||||||
//const { valid } = await form.value.validate();
|
|
||||||
//if (!valid) return;
|
|
||||||
|
|
||||||
const lp = learningPath.value;
|
const lp = learningPath.value;
|
||||||
|
|
||||||
|
@ -133,8 +137,14 @@ async function saveChanges(): Promise<void> {
|
||||||
deadline: new Date(),
|
deadline: new Date(),
|
||||||
};
|
};
|
||||||
|
|
||||||
mutate({ cid: assignmentQueryResult.data.value?.assignment.within, an: assignmentQueryResult.data.value?.assignment.id, data: assignmentDTO });
|
mutate({
|
||||||
|
cid: assignmentQueryResult.data.value?.assignment.within,
|
||||||
|
an: assignmentQueryResult.data.value?.assignment.id,
|
||||||
|
data: assignmentDTO
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -157,237 +167,256 @@ async function saveChanges(): Promise<void> {
|
||||||
md="6"
|
md="6"
|
||||||
class="responsive-col"
|
class="responsive-col"
|
||||||
>
|
>
|
||||||
<v-card
|
<v-form ref="form" validate-on="submit lazy" @submit.prevent="saveChanges">
|
||||||
v-if="assignmentResponse"
|
<v-card
|
||||||
class="assignment-card"
|
v-if="assignmentResponse"
|
||||||
>
|
class="assignment-card"
|
||||||
<div class="top-buttons">
|
>
|
||||||
<div class="top-buttons-wrapper">
|
<div class="top-buttons">
|
||||||
<v-btn
|
<div class="top-buttons-wrapper">
|
||||||
icon
|
|
||||||
variant="text"
|
|
||||||
class="back-btn"
|
|
||||||
to="/user/assignment"
|
|
||||||
>
|
|
||||||
<v-icon>mdi-arrow-left</v-icon>
|
|
||||||
</v-btn>
|
|
||||||
<div class="right-buttons">
|
|
||||||
<v-btn
|
<v-btn
|
||||||
v-if="!isEditing"
|
|
||||||
icon
|
icon
|
||||||
variant="text"
|
variant="text"
|
||||||
class="top_next_to_right_button"
|
class="back-btn"
|
||||||
@click="
|
to="/user/assignment"
|
||||||
|
>
|
||||||
|
<v-icon>mdi-arrow-left</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
<div class="right-buttons">
|
||||||
|
<v-btn
|
||||||
|
v-if="!isEditing"
|
||||||
|
icon
|
||||||
|
variant="text"
|
||||||
|
class="top_next_to_right_button"
|
||||||
|
@click="
|
||||||
() => {
|
() => {
|
||||||
isEditing = true;
|
isEditing = true;
|
||||||
description = assignmentResponse.data.assignment.description;
|
description = assignmentResponse.data.assignment.description;
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<v-icon>mdi-pencil</v-icon>
|
<v-icon>mdi-pencil</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn
|
<v-btn
|
||||||
v-else
|
v-else
|
||||||
variant="text"
|
variant="text"
|
||||||
class="top-right-btn"
|
class="top-right-btn"
|
||||||
@click="() => {isEditing = false; editingLearningPath=learningPath}"
|
@click="() => {isEditing = false; editingLearningPath=learningPath}"
|
||||||
>{{ t("cancel") }}
|
>{{ t("cancel") }}
|
||||||
</v-btn
|
</v-btn
|
||||||
>
|
>
|
||||||
|
|
||||||
<v-btn
|
<v-btn
|
||||||
v-if="!isEditing"
|
v-if="!isEditing"
|
||||||
icon
|
icon
|
||||||
variant="text"
|
variant="text"
|
||||||
class="top-right-btn"
|
class="top-right-btn"
|
||||||
@click="
|
@click="
|
||||||
deleteAssignment(
|
deleteAssignment(
|
||||||
assignmentResponse.data.assignment.id,
|
assignmentResponse.data.assignment.id,
|
||||||
assignmentResponse.data.assignment.within,
|
assignmentResponse.data.assignment.within,
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<v-icon>mdi-delete</v-icon>
|
<v-icon>mdi-delete</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn
|
<v-btn
|
||||||
v-else
|
v-else
|
||||||
icon
|
icon
|
||||||
variant="text"
|
variant="text"
|
||||||
class="top_next_to_right_button"
|
class="top_next_to_right_button"
|
||||||
@click="saveChanges"
|
@click="saveChanges"
|
||||||
>
|
>
|
||||||
<v-icon>mdi-content-save-edit-outline</v-icon>
|
<v-icon>mdi-content-save-edit-outline</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<v-card-title class="text-h4 assignmentTopTitle">{{
|
<v-card-title class="text-h4 assignmentTopTitle">{{
|
||||||
assignmentResponse.data.assignment.title
|
assignmentResponse.data.assignment.title
|
||||||
}}
|
}}
|
||||||
</v-card-title>
|
</v-card-title>
|
||||||
<v-card-subtitle
|
<v-card-subtitle
|
||||||
v-if="!isEditing"
|
v-if="!isEditing"
|
||||||
class="subtitle-section"
|
class="subtitle-section"
|
||||||
>
|
|
||||||
<using-query-result
|
|
||||||
:query-result="lpQueryResult"
|
|
||||||
v-slot="{ data: lpData }"
|
|
||||||
>
|
>
|
||||||
<v-btn
|
<using-query-result
|
||||||
v-if="lpData"
|
:query-result="lpQueryResult"
|
||||||
:to="goToLearningPathLink()"
|
v-slot="{ data: lpData }"
|
||||||
variant="tonal"
|
|
||||||
color="primary"
|
|
||||||
>
|
>
|
||||||
{{ t("learning-path") }}
|
<v-btn
|
||||||
</v-btn>
|
v-if="lpData"
|
||||||
</using-query-result>
|
:to="goToLearningPathLink()"
|
||||||
</v-card-subtitle>
|
variant="tonal"
|
||||||
<using-query-result
|
color="primary"
|
||||||
v-else
|
>
|
||||||
:query-result="learningPathsQueryResults"
|
{{ t("learning-path") }}
|
||||||
v-slot="{ data }: { data: LearningPath[] }"
|
</v-btn>
|
||||||
>
|
</using-query-result>
|
||||||
<v-card-text>
|
</v-card-subtitle>
|
||||||
<v-combobox
|
<using-query-result
|
||||||
v-model="editingLearningPath"
|
v-else
|
||||||
:items="data"
|
:query-result="learningPathsQueryResults"
|
||||||
:label="t('choose-lp')"
|
v-slot="{ data }: { data: LearningPath[] }"
|
||||||
:rules="learningPathRules"
|
>
|
||||||
variant="outlined"
|
<v-card-text>
|
||||||
clearable
|
<v-combobox
|
||||||
hide-details
|
v-model="editingLearningPath"
|
||||||
density="compact"
|
:items="data"
|
||||||
append-inner-icon="mdi-magnify"
|
:label="t('choose-lp')"
|
||||||
item-title="title"
|
:rules="learningPathRules"
|
||||||
item-value="hruid"
|
variant="outlined"
|
||||||
required
|
clearable
|
||||||
:filter="
|
hide-details
|
||||||
|
density="compact"
|
||||||
|
append-inner-icon="mdi-magnify"
|
||||||
|
item-title="title"
|
||||||
|
item-value="hruid"
|
||||||
|
required
|
||||||
|
:filter="
|
||||||
(item, query: string) =>
|
(item, query: string) =>
|
||||||
item.title.toLowerCase().includes(query.toLowerCase())
|
item.title.toLowerCase().includes(query.toLowerCase())
|
||||||
"
|
"
|
||||||
></v-combobox>
|
></v-combobox>
|
||||||
</v-card-text>
|
|
||||||
</using-query-result>
|
|
||||||
|
|
||||||
<v-card-text
|
|
||||||
v-if="!isEditing"
|
|
||||||
class="description"
|
|
||||||
>
|
|
||||||
{{ assignmentResponse.data.assignment.description }}
|
|
||||||
</v-card-text>
|
|
||||||
<v-card-text v-else>
|
|
||||||
<v-textarea
|
|
||||||
v-model="description"
|
|
||||||
:label="t('description')"
|
|
||||||
variant="outlined"
|
|
||||||
density="compact"
|
|
||||||
auto-grow
|
|
||||||
rows="3"
|
|
||||||
:rules="descriptionRules"
|
|
||||||
></v-textarea>
|
|
||||||
</v-card-text>
|
|
||||||
|
|
||||||
|
|
||||||
<v-dialog
|
|
||||||
v-model="dialog"
|
|
||||||
max-width="50%"
|
|
||||||
>
|
|
||||||
<v-card>
|
|
||||||
<v-card-title class="headline">{{ t("members") }}</v-card-title>
|
|
||||||
<v-card-text>
|
|
||||||
<v-list>
|
|
||||||
<v-list-item
|
|
||||||
v-for="(member, index) in selectedGroup.members"
|
|
||||||
:key="index"
|
|
||||||
>
|
|
||||||
<v-list-item-content>
|
|
||||||
<v-list-item-title
|
|
||||||
>{{ member.firstName + " " + member.lastName }}
|
|
||||||
</v-list-item-title>
|
|
||||||
</v-list-item-content>
|
|
||||||
</v-list-item>
|
|
||||||
</v-list>
|
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-card-actions>
|
</using-query-result>
|
||||||
<v-btn
|
|
||||||
color="primary"
|
<v-card-text
|
||||||
@click="dialog = false"
|
v-if="!isEditing"
|
||||||
>Close
|
class="description"
|
||||||
</v-btn
|
>
|
||||||
|
{{ assignmentResponse.data.assignment.description }}
|
||||||
|
</v-card-text>
|
||||||
|
<v-card-text v-else>
|
||||||
|
<v-textarea
|
||||||
|
v-model="description"
|
||||||
|
:label="t('description')"
|
||||||
|
variant="outlined"
|
||||||
|
density="compact"
|
||||||
|
auto-grow
|
||||||
|
rows="3"
|
||||||
|
:rules="descriptionRules"
|
||||||
|
></v-textarea>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</v-form>
|
||||||
|
|
||||||
|
<!-- A pop up to show group members -->
|
||||||
|
<v-dialog
|
||||||
|
v-model="dialog"
|
||||||
|
max-width="50%"
|
||||||
|
>
|
||||||
|
<v-card>
|
||||||
|
<v-card-title class="headline">{{ t("members") }}</v-card-title>
|
||||||
|
<v-card-text>
|
||||||
|
<v-list>
|
||||||
|
<v-list-item
|
||||||
|
v-for="(member, index) in selectedGroup.members"
|
||||||
|
:key="index"
|
||||||
>
|
>
|
||||||
</v-card-actions>
|
<v-list-item-content>
|
||||||
</v-card>
|
<v-list-item-title
|
||||||
</v-dialog>
|
>{{ member.firstName + " " + member.lastName }}
|
||||||
</v-card>
|
</v-list-item-title>
|
||||||
</v-col>
|
</v-list-item-content>
|
||||||
<v-col
|
</v-list-item>
|
||||||
cols="12"
|
</v-list>
|
||||||
sm="6"
|
</v-card-text>
|
||||||
md="6"
|
<v-card-actions>
|
||||||
class="responsive-col"
|
|
||||||
>
|
|
||||||
<v-table class="table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th class="header">{{ t("group") }}</th>
|
|
||||||
<th class="header">{{ t("progress") }}</th>
|
|
||||||
<th class="header">{{ t("submission") }}</th>
|
|
||||||
<th class="header">
|
|
||||||
<v-icon>mdi-pencil</v-icon>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr
|
|
||||||
v-for="g in allGroups"
|
|
||||||
:key="g.originalGroupNo"
|
|
||||||
>
|
|
||||||
<td>
|
|
||||||
<v-btn
|
<v-btn
|
||||||
@click="openGroupDetails(g)"
|
color="primary"
|
||||||
variant="text"
|
@click="dialog = false"
|
||||||
|
>Close
|
||||||
|
</v-btn
|
||||||
>
|
>
|
||||||
{{ g.name }}
|
</v-card-actions>
|
||||||
<v-icon end>mdi-menu-right</v-icon>
|
</v-card>
|
||||||
</v-btn>
|
</v-dialog>
|
||||||
</td>
|
|
||||||
|
|
||||||
<td>
|
|
||||||
<GroupProgressRow
|
|
||||||
:group-number="g.originalGroupNo"
|
|
||||||
:learning-path="learningPath"
|
|
||||||
:language="lang"
|
|
||||||
:assignment-id="assignmentId"
|
|
||||||
:class-id="classId"
|
|
||||||
/>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td>
|
|
||||||
<GroupSubmissionStatus
|
|
||||||
:group="g"
|
|
||||||
:assignment-id="assignmentId"
|
|
||||||
:class-id="classId"
|
|
||||||
:language="lang"
|
|
||||||
:go-to-group-submission-link="goToGroupSubmissionLink"
|
|
||||||
/>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<!-- Edit icon -->
|
|
||||||
<td>
|
|
||||||
<v-btn
|
|
||||||
to="/user"
|
|
||||||
variant="text"
|
|
||||||
>
|
|
||||||
<v-icon color="red"> mdi-delete</v-icon>
|
|
||||||
</v-btn>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</v-table>
|
|
||||||
|
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
|
<!-- The second column of the screen -->
|
||||||
|
<template v-if="!editGroups">
|
||||||
|
<v-col
|
||||||
|
cols="12"
|
||||||
|
sm="6"
|
||||||
|
md="6"
|
||||||
|
class="responsive-col"
|
||||||
|
>
|
||||||
|
<v-table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="header">{{ t("group") }}</th>
|
||||||
|
<th class="header">{{ t("progress") }}</th>
|
||||||
|
<th class="header">{{ t("submission") }}</th>
|
||||||
|
<th class="header">
|
||||||
|
<v-btn
|
||||||
|
@click="editGroups = true"
|
||||||
|
variant="text"
|
||||||
|
>
|
||||||
|
<v-icon>mdi-pencil</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr
|
||||||
|
v-for="g in allGroups"
|
||||||
|
:key="g.originalGroupNo"
|
||||||
|
>
|
||||||
|
<td>
|
||||||
|
<v-btn
|
||||||
|
@click="openGroupDetails(g)"
|
||||||
|
variant="text"
|
||||||
|
>
|
||||||
|
{{ g.name }}
|
||||||
|
<v-icon end>mdi-menu-right</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<GroupProgressRow
|
||||||
|
:group-number="g.originalGroupNo"
|
||||||
|
:learning-path="learningPath"
|
||||||
|
:language="lang"
|
||||||
|
:assignment-id="assignmentId"
|
||||||
|
:class-id="classId"
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<GroupSubmissionStatus
|
||||||
|
:group="g"
|
||||||
|
:assignment-id="assignmentId"
|
||||||
|
:class-id="classId"
|
||||||
|
:language="lang"
|
||||||
|
:go-to-group-submission-link="goToGroupSubmissionLink"
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<!-- Edit icon -->
|
||||||
|
<td>
|
||||||
|
<v-btn
|
||||||
|
@click=""
|
||||||
|
variant="text"
|
||||||
|
>
|
||||||
|
<v-icon color="red">mdi-delete</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</v-table>
|
||||||
|
</v-col>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<GroupSelector
|
||||||
|
:groups="allGroups"
|
||||||
|
:class-id="classId"
|
||||||
|
@groupsUpdated="handleUpdatedGroups"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
</v-row>
|
</v-row>
|
||||||
</v-container>
|
</v-container>
|
||||||
</using-query-result>
|
</using-query-result>
|
||||||
|
|
16
package-lock.json
generated
16
package-lock.json
generated
|
@ -107,6 +107,7 @@
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
"vue-i18n": "^11.1.2",
|
"vue-i18n": "^11.1.2",
|
||||||
"vue-router": "^4.5.0",
|
"vue-router": "^4.5.0",
|
||||||
|
"vuedraggable": "^2.24.3",
|
||||||
"vuetify": "^3.7.12",
|
"vuetify": "^3.7.12",
|
||||||
"wait-on": "^8.0.3"
|
"wait-on": "^8.0.3"
|
||||||
},
|
},
|
||||||
|
@ -7599,6 +7600,12 @@
|
||||||
"node": ">= 6.0.0"
|
"node": ">= 6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/sortablejs": {
|
||||||
|
"version": "1.10.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.10.2.tgz",
|
||||||
|
"integrity": "sha512-YkPGufevysvfwn5rfdlGyrGjt7/CRHwvRPogD/lC+TnvcN29jDpCifKP+rBqf+LRldfXSTh+0CGLcSg0VIxq3A==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/source-map-js": {
|
"node_modules/source-map-js": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
|
@ -8970,6 +8977,15 @@
|
||||||
"typescript": ">=5.0.0"
|
"typescript": ">=5.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/vuedraggable": {
|
||||||
|
"version": "2.24.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-2.24.3.tgz",
|
||||||
|
"integrity": "sha512-6/HDXi92GzB+Hcs9fC6PAAozK1RLt1ewPTLjK0anTYguXLAeySDmcnqE8IC0xa7shvSzRjQXq3/+dsZ7ETGF3g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"sortablejs": "1.10.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/vuetify": {
|
"node_modules/vuetify": {
|
||||||
"version": "3.8.2",
|
"version": "3.8.2",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue