Skip to content
Snippets Groups Projects

Draft: Resolve "[TCC planning] Frontend is incredibly slow with large amounts of entries"

4 unresolved threads
Compare and
7 files
+ 193
152
Compare changes
  • Side-by-side
  • Inline
Files
7
@@ -14,7 +14,8 @@ import SubjectChip from "aleksis.apps.cursus/components/SubjectChip.vue";
disable-pagination
hide-default-footer
:headers="headers"
:items="tableItems"
:items="items"
:loading="$apollo.queries.subjects.loading"
>
<template #top>
<v-row>
@@ -48,26 +49,31 @@ import SubjectChip from "aleksis.apps.cursus/components/SubjectChip.vue";
<validity-range-field
outlined
filled
label="Select Validity Range"
hide-details
v-model="internalValidityRange"
:loading="$apollo.queries.currentValidityRange.loading"
/>
</v-col>
<v-spacer />
<v-col
cols="8"
lg="3"
cols="6"
lg="2"
class="d-flex justify-space-between flex-wrap align-center"
>
<secondary-action-button
i18n-key="actions.copy_last_configuration"
block
class="mr-4"
/>
<v-switch
v-model="includeChildGroups"
inset
:label="
$t(
'lesrooster.timebound_course_config.filters.include_child_groups',
)
"
:loading="$apollo.queries.subjects.loading"
></v-switch>
</v-col>
<v-spacer />
<v-col
cols="4"
lg="1"
@@ -79,6 +85,7 @@ import SubjectChip from "aleksis.apps.cursus/components/SubjectChip.vue";
!createdCourseConfigs.length &&
!createdCourses.length
"
:loading="loading"
@click="save"
/>
</v-col>
@@ -190,18 +197,12 @@ import {
subjects,
createTimeboundCourseConfigs,
updateTimeboundCourseConfigs,
createCoursesForSchoolTerm,
createCoursesForValidityRange,
} from "./timeboundCourseConfig.graphql";
import { currentValidityRange as gqlCurrentValidityRange } from "../validity_range/validityRange.graphql";
import {
gqlGroupsForPlanning,
gqlGroups,
gqlTeachers,
} from "../helper.graphql";
import { createCourses } from "aleksis.apps.cursus/components/course.graphql";
import { gqlGroupsForPlanning, gqlTeachers } from "../helper.graphql";
export default {
name: "TimeboungCourseConfigRaster",
@@ -230,11 +231,14 @@ export default {
subjects: [],
editedCourseConfigs: [],
createdCourseConfigs: [],
newCourses: [],
createdCourses: [],
currentCourse: null,
currentSubject: null,
loading: false,
includeChildGroups: true,
selectedGroupHeaders: [],
items: [],
groupCombinationsSet: new Set(),
};
},
methods: {
@@ -243,15 +247,7 @@ export default {
},
getCurrentCourseConfig(course) {
if (course.lrTimeboundCourseConfigs?.length) {
let currentCourseConfigs = course.lrTimeboundCourseConfigs.filter(
(timeboundConfig) =>
timeboundConfig.validityRange.id === this.internalValidityRange.id,
);
if (currentCourseConfigs.length) {
return currentCourseConfigs[0];
} else {
return null;
}
return course.lrTimeboundCourseConfigs[0];
} else {
return null;
}
@@ -274,11 +270,7 @@ export default {
Object.assign(existingCreatedCourse, newValue);
}
} else {
if (
!course.lrTimeboundCourseConfigs?.filter(
(c) => c.validityRange.id === this.internalValidityRange?.id,
).length
) {
if (!course.lrTimeboundCourseConfigs?.length) {
let existingCreatedCourseConfig = this.createdCourseConfigs.find(
(c) =>
c.course === course.id &&
@@ -322,7 +314,7 @@ export default {
},
{
data: this.createdCourses,
mutation: createCoursesForSchoolTerm,
mutation: createCoursesForValidityRange,
},
]) {
if (mutationCombination.data.length) {
@@ -331,6 +323,10 @@ export default {
mutation: mutationCombination.mutation,
variables: {
input: mutationCombination.data,
...(mutationCombination.mutation ===
createCoursesForValidityRange && {
validityRange: this.internalValidityRange.id,
}),
},
})
.catch(() => {}); // FIXME Error Handling
@@ -362,66 +358,91 @@ export default {
];
},
addCourse(subject, groups) {
let courseSubjectGroup = this.newCourses.find(
(courseSubject) => courseSubject.subject === subject,
this.$set(
this.items.find((i) => i.subject.id === subject),
groups,
[{ teachers: [], newCourse: true }],
);
if (courseSubjectGroup) {
if (courseSubjectGroup.groupCombinations) {
this.$set(courseSubjectGroup.groupCombinations, groups, [
{ teachers: [], newCourse: true },
]);
} else {
courseSubjectGroup.groupCombinations = {
[groups]: [{ teachers: [], newCourse: true }],
};
}
} else {
this.newCourses.push({
subject: subject,
groupCombinations: { [groups]: [{ teachers: [], newCourse: true }] },
},
generateTableItems(subjects) {
return subjects.map((subject) => {
let { courses, ...reducedSubject } = subject;
let groupCombinations = {};
courses.forEach((course) => {
const ownGroupIDs = course.groups.map((group) => group.id);
let groupIDs;
if (
this.includeChildGroups &&
ownGroupIDs.some((groupID) => !this.groupIDSet.has(groupID))
) {
groupIDs = JSON.stringify(
course.groups
.flatMap((group) =>
group.parentGroups.map((parentGroup) => parentGroup.id),
)
.sort(),
);
} else {
groupIDs = JSON.stringify(ownGroupIDs.sort());
}
if (!groupCombinations[groupIDs]) {
groupCombinations[groupIDs] = [];
if (course.groups.length > 1) {
this.groupCombinationsSet.add(groupIDs);
}
groupCombinations[groupIDs].push({
...course,
});
} else if (
!groupCombinations[groupIDs].some((c) => c.id === course.id)
) {
groupCombinations[groupIDs].push({
...course,
});
}
});
}
return {
subject: reducedSubject,
...Object.fromEntries(
this.groupHeaders.map((header) => [header.value, []]),
),
...groupCombinations,
};
});
},
},
computed: {
groupIDList() {
return this.selectedGroups.map((group) => group.id);
groupIDSet() {
return new Set(this.selectedGroups.map((group) => group.id));
},
subjectGroupCombinations() {
return [].concat.apply(
[],
this.items.map((subject) => Object.keys(subject.groupCombinations)),
);
groupCombinationHeaders() {
return this.subjectGroupCombinations.map((combination) => {
let parsedCombination = JSON.parse(combination);
return {
text: parsedCombination
.map(
(groupID) =>
this.selectedGroups.find((group) => group.id === groupID)
?.shortName ||
this.selectedGroups.find((group) => group.id === groupID)
?.shortName,
)
.join(", "),
value: combination,
};
});
},
groupHeaders() {
return this.selectedGroups
.map((group) => ({
text: group.shortName,
value: JSON.stringify([group.id]),
}))
.concat(
this.subjectGroupCombinations.map((combination) => {
let parsedCombination = JSON.parse(combination);
return {
text: parsedCombination
.map(
(groupID) =>
this.groups.find((group) => group.id === groupID).shortName,
)
.join(", "),
value: combination,
};
}),
)
.filter(
(obj, index, self) =>
index === self.findIndex((o) => o.value === obj.value),
);
return [...this.selectedGroupHeaders, ...this.groupCombinationHeaders];
},
headers() {
let groupHeadersWithWidth = this.groupHeaders.map((header) => ({
...header,
width: `${Math.max(95 / this.groupHeaders.length, 15)}vw`,
width: "20vw",
}));
return [
{
@@ -431,52 +452,16 @@ export default {
},
].concat(groupHeadersWithWidth);
},
items() {
return this.subjects.map((subject) => {
let groupCombinations = {};
subject.courses.forEach((course) => {
let groupIds = JSON.stringify(
course.groups.map((group) => group.id).sort(),
);
if (!groupCombinations[groupIds]) {
groupCombinations[groupIds] = [];
}
if (!groupCombinations[groupIds].find((c) => c.id === course.id)) {
groupCombinations[groupIds].push({
...course,
});
}
});
subject = {
...subject,
groupCombinations: { ...groupCombinations },
newCourses: {
...this.newCourses.find(
(courseSubject) => courseSubject.subject === subject.id,
)?.groupCombinations,
},
};
return subject;
});
subjectGroupCombinations() {
return Array.from(this.groupCombinationsSet);
},
tableItems() {
return this.items.map((subject) => {
// eslint-disable-next-line no-unused-vars
let { courses, groupCombinations, ...reducedSubject } = subject;
return {
subject: reducedSubject,
...Object.fromEntries(
this.groupHeaders.map((header) => [header.value, []]),
),
...subject.groupCombinations,
...subject.newCourses,
};
});
},
watch: {
selectedGroups(newValue) {
this.selectedGroupHeaders = newValue.map((group) => ({
text: group.shortName,
value: JSON.stringify([group.id]),
}));
},
},
apollo: {
@@ -487,27 +472,32 @@ export default {
this.internalValidityRange = data.currentValidityRange;
},
},
groups: {
query: gqlGroups,
},
groupsForPlanning: {
query: gqlGroupsForPlanning,
result({ data }) {
if (!data) return;
console.log(data.groups);
this.selectedGroups = data.groupsForPlanning;
},
},
subjects: {
query: subjects,
skip() {
return !this.groupIDList.length;
return (
!this.groupIDSet.size ||
!this.internalValidityRange ||
!this.persons.length
);
},
variables() {
return {
groups: this.groupIDList,
groups: Array.from(this.groupIDSet),
includeChildGroups: this.includeChildGroups,
};
},
result({ data }) {
if (!data) return;
this.items = this.generateTableItems(data.subjects);
},
},
persons: {
query: gqlTeachers,
Loading