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-i18n": "^11.1.2", | ||||
|         "vue-router": "^4.5.0", | ||||
|         "vuedraggable": "^2.24.3", | ||||
|         "vuetify": "^3.7.12", | ||||
|         "wait-on": "^8.0.3" | ||||
|     }, | ||||
|  |  | |||
|  | @ -1,75 +1,114 @@ | |||
| <script setup lang="ts"> | ||||
|     import { ref } from "vue"; | ||||
|     import { useI18n } from "vue-i18n"; | ||||
|     import UsingQueryResult from "@/components/UsingQueryResult.vue"; | ||||
|     import type { StudentsResponse } from "@/controllers/students.ts"; | ||||
|     import { useClassStudentsQuery } from "@/queries/classes.ts"; | ||||
| import { ref, } from "vue"; | ||||
| import draggable from "vuedraggable"; | ||||
| import { useI18n } from "vue-i18n"; | ||||
| 
 | ||||
|     const props = defineProps<{ | ||||
|         classId: string | undefined; | ||||
|         groups: string[][]; | ||||
|     }>(); | ||||
|     const emit = defineEmits(["groupCreated"]); | ||||
|     const { t } = useI18n(); | ||||
| const props = defineProps<{ | ||||
|     classId: string | undefined; | ||||
|     groups: string[][]; | ||||
| }>(); | ||||
| const emit = defineEmits(["done", "groupsUpdated"]); | ||||
| 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 }[] { | ||||
|         const students = data.students; | ||||
|         const studentsInGroups = props.groups.flat(); | ||||
| function removeGroup(index: number) { | ||||
|     unassigned.value.push(...groupList.value[index]); | ||||
|     groupList.value.splice(index, 1); | ||||
| } | ||||
| 
 | ||||
|         return students | ||||
|             ?.map((st) => ({ | ||||
|                 title: `${st.firstName} ${st.lastName}`, | ||||
|                 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 | ||||
|         } | ||||
|     } | ||||
| function saveChanges() { | ||||
|     emit("groupsUpdated", groupList.value); | ||||
|     emit("done"); | ||||
| } | ||||
| </script> | ||||
| 
 | ||||
| <template> | ||||
|     <using-query-result | ||||
|         :query-result="studentQueryResult" | ||||
|         v-slot="{ data }: { data: StudentsResponse }" | ||||
|     > | ||||
|         <h3>{{ t("create-groups") }}</h3> | ||||
|     <v-card> | ||||
|         <v-card-title>{{ t("edit-groups") }}</v-card-title> | ||||
|         <v-card-text> | ||||
|             <v-combobox | ||||
|                 v-model="selectedStudents" | ||||
|                 :items="filterStudents(data)" | ||||
|                 item-title="title" | ||||
|                 item-value="value" | ||||
|                 :label="t('choose-students')" | ||||
|                 variant="outlined" | ||||
|                 clearable | ||||
|                 multiple | ||||
|                 hide-details | ||||
|                 density="compact" | ||||
|                 chips | ||||
|                 append-inner-icon="mdi-magnify" | ||||
|             ></v-combobox> | ||||
|             <v-row> | ||||
|                 <!-- Ongegroepeerde studenten --> | ||||
|                 <v-col cols="12" sm="4"> | ||||
|                     <h4>{{ t("unassigned") }}</h4> | ||||
|                     <draggable | ||||
|                         v-model="unassigned" | ||||
|                         group="students" | ||||
|                         item-key="username" | ||||
|                         class="group-box" | ||||
|                     > | ||||
|                         <template #item="{ element }"> | ||||
|                             <v-chip>{{ element }}</v-chip> | ||||
|                         </template> | ||||
|                     </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 | ||||
|                 @click="createGroup" | ||||
|                 color="primary" | ||||
|                 class="mt-2" | ||||
|                 size="small" | ||||
|                 class="mt-4" | ||||
|                 @click="addNewGroup" | ||||
|             > | ||||
|                 {{ t("create-group") }} | ||||
|                 {{ t("add-group") }} | ||||
|             </v-btn> | ||||
|         </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> | ||||
| 
 | ||||
| <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 GroupProgressRow from "@/components/GroupProgressRow.vue" | ||||
| 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<{ | ||||
|     classId: string; | ||||
|  | @ -35,9 +35,12 @@ const {t} = useI18n(); | |||
| const lang = ref(); | ||||
| const groups = ref<GroupDTO[] | GroupDTOId[]>([]); | ||||
| const learningPath = ref(); | ||||
| const form = ref(); | ||||
| 
 | ||||
| 
 | ||||
| const editingLearningPath = ref(learningPath); | ||||
| const description = ref(""); | ||||
| const editGroups = ref(false); | ||||
| 
 | ||||
| 
 | ||||
| const assignmentQueryResult = useAssignmentQuery(() => props.classId, props.assignmentId); | ||||
|  | @ -111,7 +114,7 @@ function goToGroupSubmissionLink(groupNo: number): string | undefined { | |||
| 
 | ||||
| const learningPathsQueryResults = useGetAllLearningPaths(lang); | ||||
| 
 | ||||
| const { mutate, data, isSuccess } = useUpdateAssignmentMutation(); | ||||
| const {mutate, data, isSuccess} = useUpdateAssignmentMutation(); | ||||
| 
 | ||||
| watch([isSuccess, data], ([success, newData]) => { | ||||
|     if (success && newData?.assignment) { | ||||
|  | @ -120,9 +123,10 @@ watch([isSuccess, data], ([success, newData]) => { | |||
| }); | ||||
| 
 | ||||
| async function saveChanges(): Promise<void> { | ||||
|     const {valid} = await form.value.validate(); | ||||
|     if (!valid) return; | ||||
| 
 | ||||
|     isEditing.value = false; | ||||
|     //const { valid } = await form.value.validate(); | ||||
|     //if (!valid) return; | ||||
| 
 | ||||
|     const lp = learningPath.value; | ||||
| 
 | ||||
|  | @ -133,8 +137,14 @@ async function saveChanges(): Promise<void> { | |||
|         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> | ||||
| 
 | ||||
| <template> | ||||
|  | @ -157,237 +167,256 @@ async function saveChanges(): Promise<void> { | |||
|                         md="6" | ||||
|                         class="responsive-col" | ||||
|                     > | ||||
|                         <v-card | ||||
|                             v-if="assignmentResponse" | ||||
|                             class="assignment-card" | ||||
|                         > | ||||
|                             <div class="top-buttons"> | ||||
|                                 <div class="top-buttons-wrapper"> | ||||
|                                     <v-btn | ||||
|                                         icon | ||||
|                                         variant="text" | ||||
|                                         class="back-btn" | ||||
|                                         to="/user/assignment" | ||||
|                                     > | ||||
|                                         <v-icon>mdi-arrow-left</v-icon> | ||||
|                                     </v-btn> | ||||
|                                     <div class="right-buttons"> | ||||
|                         <v-form ref="form" validate-on="submit lazy" @submit.prevent="saveChanges"> | ||||
|                             <v-card | ||||
|                                 v-if="assignmentResponse" | ||||
|                                 class="assignment-card" | ||||
|                             > | ||||
|                                 <div class="top-buttons"> | ||||
|                                     <div class="top-buttons-wrapper"> | ||||
|                                         <v-btn | ||||
|                                             v-if="!isEditing" | ||||
|                                             icon | ||||
|                                             variant="text" | ||||
|                                             class="top_next_to_right_button" | ||||
|                                             @click=" | ||||
|                                             class="back-btn" | ||||
|                                             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; | ||||
|                                                     description = assignmentResponse.data.assignment.description; | ||||
|                                                 } | ||||
|                                             " | ||||
|                                         > | ||||
|                                             <v-icon>mdi-pencil</v-icon> | ||||
|                                         </v-btn> | ||||
|                                         <v-btn | ||||
|                                             v-else | ||||
|                                             variant="text" | ||||
|                                             class="top-right-btn" | ||||
|                                             @click="() => {isEditing = false; editingLearningPath=learningPath}" | ||||
|                                         >{{ t("cancel") }} | ||||
|                                         </v-btn | ||||
|                                         > | ||||
|                                             > | ||||
|                                                 <v-icon>mdi-pencil</v-icon> | ||||
|                                             </v-btn> | ||||
|                                             <v-btn | ||||
|                                                 v-else | ||||
|                                                 variant="text" | ||||
|                                                 class="top-right-btn" | ||||
|                                                 @click="() => {isEditing = false; editingLearningPath=learningPath}" | ||||
|                                             >{{ t("cancel") }} | ||||
|                                             </v-btn | ||||
|                                             > | ||||
| 
 | ||||
|                                         <v-btn | ||||
|                                             v-if="!isEditing" | ||||
|                                             icon | ||||
|                                             variant="text" | ||||
|                                             class="top-right-btn" | ||||
|                                             @click=" | ||||
|                                             <v-btn | ||||
|                                                 v-if="!isEditing" | ||||
|                                                 icon | ||||
|                                                 variant="text" | ||||
|                                                 class="top-right-btn" | ||||
|                                                 @click=" | ||||
|                                                 deleteAssignment( | ||||
|                                                     assignmentResponse.data.assignment.id, | ||||
|                                                     assignmentResponse.data.assignment.within, | ||||
|                                                 ) | ||||
|                                             " | ||||
|                                         > | ||||
|                                             <v-icon>mdi-delete</v-icon> | ||||
|                                         </v-btn> | ||||
|                                         <v-btn | ||||
|                                             v-else | ||||
|                                             icon | ||||
|                                             variant="text" | ||||
|                                             class="top_next_to_right_button" | ||||
|                                             @click="saveChanges" | ||||
|                                         > | ||||
|                                             <v-icon>mdi-content-save-edit-outline</v-icon> | ||||
|                                         </v-btn> | ||||
|                                             > | ||||
|                                                 <v-icon>mdi-delete</v-icon> | ||||
|                                             </v-btn> | ||||
|                                             <v-btn | ||||
|                                                 v-else | ||||
|                                                 icon | ||||
|                                                 variant="text" | ||||
|                                                 class="top_next_to_right_button" | ||||
|                                                 @click="saveChanges" | ||||
|                                             > | ||||
|                                                 <v-icon>mdi-content-save-edit-outline</v-icon> | ||||
|                                             </v-btn> | ||||
|                                         </div> | ||||
|                                     </div> | ||||
|                                 </div> | ||||
|                             </div> | ||||
| 
 | ||||
|                             <v-card-title class="text-h4 assignmentTopTitle">{{ | ||||
|                                     assignmentResponse.data.assignment.title | ||||
|                                 }} | ||||
|                             </v-card-title> | ||||
|                             <v-card-subtitle | ||||
|                                 v-if="!isEditing" | ||||
|                                 class="subtitle-section" | ||||
|                             > | ||||
|                                 <using-query-result | ||||
|                                     :query-result="lpQueryResult" | ||||
|                                     v-slot="{ data: lpData }" | ||||
|                                 <v-card-title class="text-h4 assignmentTopTitle">{{ | ||||
|                                         assignmentResponse.data.assignment.title | ||||
|                                     }} | ||||
|                                 </v-card-title> | ||||
|                                 <v-card-subtitle | ||||
|                                     v-if="!isEditing" | ||||
|                                     class="subtitle-section" | ||||
|                                 > | ||||
|                                     <v-btn | ||||
|                                         v-if="lpData" | ||||
|                                         :to="goToLearningPathLink()" | ||||
|                                         variant="tonal" | ||||
|                                         color="primary" | ||||
|                                     <using-query-result | ||||
|                                         :query-result="lpQueryResult" | ||||
|                                         v-slot="{ data: lpData }" | ||||
|                                     > | ||||
|                                         {{ t("learning-path") }} | ||||
|                                     </v-btn> | ||||
|                                 </using-query-result> | ||||
|                             </v-card-subtitle> | ||||
|                             <using-query-result | ||||
|                                 v-else | ||||
|                                 :query-result="learningPathsQueryResults" | ||||
|                                 v-slot="{ data }: { data: LearningPath[] }" | ||||
|                             > | ||||
|                                 <v-card-text> | ||||
|                                     <v-combobox | ||||
|                                         v-model="editingLearningPath" | ||||
|                                         :items="data" | ||||
|                                         :label="t('choose-lp')" | ||||
|                                         :rules="learningPathRules" | ||||
|                                         variant="outlined" | ||||
|                                         clearable | ||||
|                                         hide-details | ||||
|                                         density="compact" | ||||
|                                         append-inner-icon="mdi-magnify" | ||||
|                                         item-title="title" | ||||
|                                         item-value="hruid" | ||||
|                                         required | ||||
|                                         :filter=" | ||||
|                                         <v-btn | ||||
|                                             v-if="lpData" | ||||
|                                             :to="goToLearningPathLink()" | ||||
|                                             variant="tonal" | ||||
|                                             color="primary" | ||||
|                                         > | ||||
|                                             {{ t("learning-path") }} | ||||
|                                         </v-btn> | ||||
|                                     </using-query-result> | ||||
|                                 </v-card-subtitle> | ||||
|                                 <using-query-result | ||||
|                                     v-else | ||||
|                                     :query-result="learningPathsQueryResults" | ||||
|                                     v-slot="{ data }: { data: LearningPath[] }" | ||||
|                                 > | ||||
|                                     <v-card-text> | ||||
|                                         <v-combobox | ||||
|                                             v-model="editingLearningPath" | ||||
|                                             :items="data" | ||||
|                                             :label="t('choose-lp')" | ||||
|                                             :rules="learningPathRules" | ||||
|                                             variant="outlined" | ||||
|                                             clearable | ||||
|                                             hide-details | ||||
|                                             density="compact" | ||||
|                                             append-inner-icon="mdi-magnify" | ||||
|                                             item-title="title" | ||||
|                                             item-value="hruid" | ||||
|                                             required | ||||
|                                             :filter=" | ||||
|                                             (item, query: string) => | ||||
|                                                 item.title.toLowerCase().includes(query.toLowerCase()) | ||||
|                                         " | ||||
|                                     ></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-combobox> | ||||
|                                     </v-card-text> | ||||
|                                     <v-card-actions> | ||||
|                                         <v-btn | ||||
|                                             color="primary" | ||||
|                                             @click="dialog = false" | ||||
|                                         >Close | ||||
|                                         </v-btn | ||||
|                                 </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-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-card> | ||||
|                             </v-dialog> | ||||
|                         </v-card> | ||||
|                     </v-col> | ||||
|                     <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-icon>mdi-pencil</v-icon> | ||||
|                                 </th> | ||||
|                             </tr> | ||||
|                             </thead> | ||||
|                             <tbody> | ||||
|                             <tr | ||||
|                                 v-for="g in allGroups" | ||||
|                                 :key="g.originalGroupNo" | ||||
|                             > | ||||
|                                 <td> | ||||
|                                             <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-actions> | ||||
|                                     <v-btn | ||||
|                                         @click="openGroupDetails(g)" | ||||
|                                         variant="text" | ||||
|                                         color="primary" | ||||
|                                         @click="dialog = false" | ||||
|                                     >Close | ||||
|                                     </v-btn | ||||
|                                     > | ||||
|                                         {{ 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 | ||||
|                                         to="/user" | ||||
|                                         variant="text" | ||||
|                                     > | ||||
|                                         <v-icon color="red"> mdi-delete</v-icon> | ||||
|                                     </v-btn> | ||||
|                                 </td> | ||||
|                             </tr> | ||||
|                             </tbody> | ||||
|                         </v-table> | ||||
| 
 | ||||
|                                 </v-card-actions> | ||||
|                             </v-card> | ||||
|                         </v-dialog> | ||||
|                     </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-container> | ||||
|         </using-query-result> | ||||
|  |  | |||
							
								
								
									
										16
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										16
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							|  | @ -107,6 +107,7 @@ | |||
|                 "vue": "^3.5.13", | ||||
|                 "vue-i18n": "^11.1.2", | ||||
|                 "vue-router": "^4.5.0", | ||||
|                 "vuedraggable": "^2.24.3", | ||||
|                 "vuetify": "^3.7.12", | ||||
|                 "wait-on": "^8.0.3" | ||||
|             }, | ||||
|  | @ -7599,6 +7600,12 @@ | |||
|                 "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": { | ||||
|             "version": "1.2.1", | ||||
|             "license": "BSD-3-Clause", | ||||
|  | @ -8970,6 +8977,15 @@ | |||
|                 "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": { | ||||
|             "version": "3.8.2", | ||||
|             "license": "MIT", | ||||
|  |  | |||
		Reference in a new issue
	
	 Joyelle Ndagijimana
						Joyelle Ndagijimana