diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/Coursebook.vue b/aleksis/apps/alsijil/frontend/components/coursebook/Coursebook.vue index 366681af084c8fb0011f9ecd8c9b4b8182aeb617..f26ebf0b97864eba43ac2cd583b7990921cb09e8 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/Coursebook.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/Coursebook.vue @@ -13,48 +13,7 @@ use-deep-search > <template #additionalActions="{ attrs, on }"> - <div class="d-flex flex-grow-1 justify-end"> - <v-autocomplete - :items="selectable" - item-text="name" - clearable - return-object - filled - dense - hide-details - :placeholder="$t('alsijil.coursebook.filter.filter_for_obj')" - :loading="selectLoading" - :value="currentObj" - @input="changeSelection" - @click:clear="changeSelection" - class="max-width" - /> - <div class="ml-6"> - <v-switch - :loading="selectLoading" - :label="$t('alsijil.coursebook.filter.own')" - :input-value="filterType === 'my'" - @change=" - changeSelection({ - filterType: $event ? 'my' : 'all', - type: objType, - id: objId, - }) - " - dense - inset - hide-details - /> - <v-switch - :loading="selectLoading" - :label="$t('alsijil.coursebook.filter.missing')" - v-model="incomplete" - dense - inset - hide-details - /> - </div> - </div> + <coursebook-filters v-model="filters" /> </template> <template #default="{ items }"> <v-list-item @@ -107,11 +66,8 @@ import CRUDIterator from "aleksis.core/components/generic/CRUDIterator.vue"; import DateSelectFooter from "aleksis.core/components/generic/DateSelectFooter.vue"; import DocumentationModal from "./documentation/DocumentationModal.vue"; import { DateTime } from "luxon"; -import { - coursesOfPerson, - documentationsForCoursebook, - groupsByPerson, -} from "./coursebook.graphql"; +import { documentationsForCoursebook } from "./coursebook.graphql"; +import CoursebookFilters from "./CoursebookFilters.vue"; import CoursebookLoader from "./CoursebookLoader.vue"; import CoursebookEmptyMessage from "./CoursebookEmptyMessage.vue"; @@ -119,6 +75,7 @@ export default { name: "Coursebook", components: { CoursebookEmptyMessage, + CoursebookFilters, CoursebookLoader, CRUDIterator, DateSelectFooter, @@ -158,14 +115,6 @@ export default { incomplete: false, }; }, - apollo: { - groups: { - query: groupsByPerson, - }, - courses: { - query: coursesOfPerson, - }, - }, computed: { gqlQueryArgs() { return { @@ -180,40 +129,30 @@ export default { incomplete: !!this.incomplete, }; }, - selectable() { - return [ - { header: this.$t("alsijil.coursebook.filter.groups") }, - ...this.groups.map((group) => ({ type: "group", ...group })), - { header: this.$t("alsijil.coursebook.filter.courses") }, - ...this.courses.map((course) => ({ type: "course", ...course })), - ]; - }, - currentObj() { - return this.selectable.find( - (o) => o.type === this.objType && o.id === this.objId, - ); - }, - selectLoading() { - return ( - this.$apollo.queries.groups.loading || - this.$apollo.queries.courses.loading - ); - }, + filters: { + get() { + return { objType: this.objType, objId: this.objId, filterType: this.filterType, incomplete: this.incomplete }; + }, + set(selectedFilters) { + if (Object.hasOwn(selectedFilters, "incomplete")) { + this.incomplete = selectedFilters.incomplete; + } else if (Object.hasOwn(selectedFilters, "filterType") || Object.hasOwn(selectedFilters, "objId") || Object.hasOwn(selectedFilters, "objType")) { + this.$router.push({ + name: "alsijil.coursebook_by_type_and_date", + params: { + filterType: selectedFilters.filterType + ? selectedFilters.filterType + : this.filterType, + objType: selectedFilters.objType, + objId: selectedFilters.objId, + date: this.date, + }, + }); + } + } + } }, methods: { - changeSelection(selection) { - this.$router.push({ - name: "alsijil.coursebook_by_type_and_date", - params: { - filterType: selection.filterType - ? selection.filterType - : this.filterType, - objType: selection.type, - objId: selection.id, - date: this.date, - }, - }); - }, // => [[dt doc ...] ...] groupDocsByDay(docs) { const byDay = docs.reduce((byDay, doc) => { diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/CoursebookFilters.vue b/aleksis/apps/alsijil/frontend/components/coursebook/CoursebookFilters.vue new file mode 100644 index 0000000000000000000000000000000000000000..909cf3a20ade0b8aac02241e50be7ff462acd239 --- /dev/null +++ b/aleksis/apps/alsijil/frontend/components/coursebook/CoursebookFilters.vue @@ -0,0 +1,105 @@ +<template> + <div class="d-flex flex-grow-1 justify-end"> + <v-autocomplete + :items="selectable" + item-text="name" + clearable + return-object + filled + dense + hide-details + :placeholder="$t('alsijil.coursebook.filter.filter_for_obj')" + :loading="selectLoading" + :value="currentObj" + @input="selectObject" + @click:clear="selectObject" + class="max-width" + /> + <div class="ml-6"> + <v-switch + :loading="selectLoading" + :label="$t('alsijil.coursebook.filter.own')" + :input-value="value.filterType === 'my'" + @change="selectFilterType($event)" + dense + inset + hide-details + /> + <v-switch + :loading="selectLoading" + :label="$t('alsijil.coursebook.filter.missing')" + :input-value="value.incomplete" + @change=" + $emit('input', { + incomplete: $event + }) + " + dense + inset + hide-details + /> + </div> + </div> +</template> + +<script> +import { + coursesOfPerson, + groupsByPerson, +} from "./coursebook.graphql"; + +export default { + name: "CoursebookFilters", + data() { + return { + // Placeholder values while query isn't completed yet + groups: [], + courses: [], + }; + }, + props: { + value: { + type: Object, + required: true, + }, + }, + emits: ["input"], + apollo: { + groups: { + query: groupsByPerson, + }, + courses: { + query: coursesOfPerson, + }, + }, + computed: { + selectable() { + return [ + { header: this.$t("alsijil.coursebook.filter.groups") }, + ...this.groups.map((group) => ({ type: "group", ...group })), + { header: this.$t("alsijil.coursebook.filter.courses") }, + ...this.courses.map((course) => ({ type: "course", ...course })), + ]; + }, + selectLoading() { + return ( + this.$apollo.queries.groups.loading || + this.$apollo.queries.courses.loading + ); + }, + currentObj() { + return this.selectable.find( + (o) => o.type === this.value.objType && o.id === this.value.objId, + ); + }, + }, + methods: { + selectObject(selection) { + this.$emit("input", { objType: selection ? selection.type : null, objId: selection ? selection.id : null }) + }, + selectFilterType(switchValue) { + this.$emit("input", { filterType: switchValue ? "my" : "all", objType: this.value.objType, objId: this.value.objId }); + } + }, +}; +</script>