diff --git a/public/js/components/Tempus/TagsAssignmentModal.js b/public/js/components/Tempus/TagsAssignmentModal.js new file mode 100644 index 000000000..3c57b208d --- /dev/null +++ b/public/js/components/Tempus/TagsAssignmentModal.js @@ -0,0 +1,193 @@ +/** + * Copyright (C) 2024 fhcomplete.org + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +import BsModal from "../Bootstrap/Modal.js"; +import FormInput from "../Form/Input.js"; +import CoreTag from "../Tag/Tag.js"; +import ApiTempusTag from "../../api/factory/tempus/tag.js"; + +export default { + name: "TagsAssignmentModal", + components: { + BsModal, + FormInput, + CoreTag, + }, + emits: ["tagsChanged"], + data() { + return { + calendar: null, + availableTags: [], + filteredAvailableTags: [], + selectedAvailableTag: null, + assignedTags: [], + tagEndpoint: ApiTempusTag, + }; + }, + computed: { + dropdownParsedAvailableTags() { + return this.availableTags.map((tag) => ({ + label: tag.bezeichnung, + value: tag.tag_typ_kurzbz, + data: tag, + })); + }, + }, + methods: { + async open(calendar) { + if (!calendar?.kalender_id) return; + + this.calendar = calendar; + this.availableTags = await this.fetchAvailableTags(); + this.filteredAvailableTags = [...this.dropdownParsedAvailableTags]; + this.assignedTags = await this.fetchAssignedTagsByCalender( + calendar.eindeutige_gruppen_id, + ); + + this.show(); + }, + show() { + this.$refs.modal.show(); + }, + hide() { + this.$refs.modal.hide(); + }, + reset() { + this.calendar = null; + this.availableTags = []; + this.filteredAvailableTags = []; + this.selectedAvailableTag = null; + this.assignedTags = []; + }, + async fetchAvailableTags() { + const result = await this.$api.call(ApiTempusTag.getTags()); + + if (result.meta.status === "success") return result.data; + + this.$fhcAlert.alertError( + this.$p.t("ui", "failed_available_tags_fetch_error_message"), + ); + return []; + }, + async fetchAssignedTagsByCalender(calendarGroupId) { + const result = await this.$api.call( + ApiTempusTag.getTagsByCalendar(calendarGroupId), + ); + + if (result.meta.status === "success") { + return result.data.filter((tag) => !!tag); + } + + this.$fhcAlert.alertError( + this.$p.t("ui", "failed_assigned_tags_fetch_error_message"), + ); + return []; + }, + filterAvailableTags(event) { + const query = event.query.toLowerCase(); + const unassignedTags = this.dropdownParsedAvailableTags.filter( + (tag) => + !this.assignedTags.some( + (assigned) => assigned.tag_id === tag.value, + ), + ); + + this.filteredAvailableTags = query + ? unassignedTags.filter((tag) => + tag.label.toLowerCase().includes(query), + ) + : unassignedTags; + }, + selectTag(event) { + this.selectedAvailableTag = event.value; + this.$refs.tagComponent?.openModal(event.value.data); + }, + editTag(tag) { + this.$refs.tagComponent?.editTag(tag.notiz_id); + }, + async handleCalendarTagChange() { + const calendarGroupId = this.calendar?.eindeutige_gruppen_id; + if (!calendarGroupId) return; + + this.assignedTags = + await this.fetchAssignedTagsByCalender(calendarGroupId); + this.$emit("tagsChanged"); + }, + }, + template: /* html */` + + + + + + `, +}; diff --git a/public/js/components/Tempus/Tempus.js b/public/js/components/Tempus/Tempus.js index 3774d98f9..f6effc5c6 100644 --- a/public/js/components/Tempus/Tempus.js +++ b/public/js/components/Tempus/Tempus.js @@ -28,7 +28,6 @@ import ApiSearchbar from "../../api/factory/searchbar.js"; import ApiRenderers from "../../api/factory/renderers.js"; import ApiTempusConfig from "../../api/factory/tempus/config.js"; import ApiBetriebsmittel from "../../api/factory/betriebsmittel.js"; -import ApiTempusTag from "../../api/factory/tempus/tag.js"; import AppMenu from "../AppMenu.js"; import drop from "../../directives/drop.js"; import AppConfig from "../AppConfig.js"; @@ -39,7 +38,6 @@ import StvVerband from "../Stv/Studentenverwaltung/Verband.js"; import ApiStudiengangTree from "../../api/factory/tempus/studiengangtree.js"; import ApiInfo from "../../api/factory/tempus/info.js"; import StvStudiensemester from "../Stv/Studentenverwaltung/Studiensemester.js"; -import FormInput from "../../../js/components/Form/Input.js"; import Reservierung from "./Reservierung.js"; import { getTempusShortcuts } from "./shortcuts.js"; import KeyboardShortcuts from "./KeyboardShortcuts.js"; @@ -47,8 +45,8 @@ import { useContextMenuActions } from "../../composables/Tempus/ContextMenuActio import MultiWeekPlanModal from "./MultiWeekPlanModal.js"; import HistoryModal from "./HistoryModal.js"; import ResourcesAssignmentModal from "./ResourcesAssignmentModal.js"; +import TagsAssignmentModal from "./TagsAssignmentModal.js"; import { getTempusSearchbarOptions } from "./Filters/searchbarOptions.js"; -import CoreTag from '../Tag/Tag.js'; export default { name: "Tempus", @@ -68,13 +66,12 @@ export default { StvVerband, StvStudiensemester, Multiselect: primevue.multiselect, - FormInput, Reservierung, KeyboardShortcuts, MultiWeekPlanModal, HistoryModal, ResourcesAssignmentModal, - CoreTag, + TagsAssignmentModal, }, props: { defaultSemester: String, @@ -101,7 +98,7 @@ export default { openRaumauswahl: (orig) => this.openRaumauswahl(orig), openResourcesAssignmentModal: (orig) => this.$refs.resourcesAssignmentModal?.open(orig), - openTagsModal: (orig) => this.openTagsAssignmentModal(orig), + openTagsModal: (orig) => this.$refs.tagsAssignmentModal?.open(orig), openHistory: (orig) => this.openHistory(orig), deleteEntry: (orig) => this.deleteEntry(orig), syncToLecturer: (orig) => this.syncToLecturer(orig), @@ -170,15 +167,6 @@ export default { endTime: null, }, studiengaenge_all: [], - tagsAssignmentModal: { - calendar: null, - availableTags: [], - filteredAvailableTags: [], - selectedAvailableTag: null, - assignedTags: [], - areFormButtonsDisplayed: false, - }, - tagEndpoint: ApiTempusTag, }; }, computed: { @@ -213,16 +201,6 @@ export default { searchbaroptions() { return getTempusSearchbarOptions(this); }, - dropdownParsedAvailableTags() { - return this.tagsAssignmentModal.availableTags - .map((tag) => { - return { - label: tag.bezeichnung, - value: tag.tag_typ_kurzbz, - data: tag, - }; - }); - }, }, methods: { async openRaumauswahl(orig) { @@ -236,19 +214,6 @@ export default { this.$refs.raumModal.show(); }); }, - async openTagsAssignmentModal(orig) { - console.log("openTagsAssignmentModal called with orig:", orig); - if (!orig?.kalender_id) return; - - this.tagsAssignmentModal.calendar = orig; - this.tagsAssignmentModal.availableTags = await this.fetchAvailableTags(); - this.tagsAssignmentModal.filteredAvailableTags = [ - ...this.dropdownParsedAvailableTags, - ]; - - this.tagsAssignmentModal.assignedTags = await this.fetchAssignedTagsByCalender(orig.eindeutige_gruppen_id); - this.$refs.tagsAssignmentModal.show(); - }, async deleteEntry(orig) { if (!orig?.kalender_id) return; @@ -794,114 +759,6 @@ export default { this.extraBackgrounds = res; }, - async fetchAvailableTags() { - let getAvailableTags = await this.$api.call( - ApiTempusTag.getTags(), - ); - if (getAvailableTags.meta.status === "success") { - return getAvailableTags.data; - } else { - this.$fhcAlert.alertError( - this.$p.t("ui", "failed_available_tags_fetch_error_message"), - ); - } - - return []; - }, - async fetchAssignedTagsByCalender(calenderId) { - let getAssignedTags = await this.$api.call( - ApiTempusTag.getTagsByCalendar(calenderId), - ); - if (getAssignedTags.meta.status === "success") { - return getAssignedTags.data.filter((unit) => !!unit); - } else { - this.$fhcAlert.alertError( - this.$p.t("ui", "failed_assigned_tags_fetch_error_message"), - ); - } - - return []; - }, - filterAvailableTags(event) { - this.tagsAssignmentModal.filteredAvailableTags; - const query = event.query.toLowerCase(); - if (!query) { - return (this.tagsAssignmentModal.filteredAvailableTags = [ - ...this.dropdownParsedAvailableTags.filter((tag) => { - return !this.tagsAssignmentModal.assignedTags.some( - (assigned) => assigned.tag_id === tag.value, - ); - }), - ]); - } - - return (this.tagsAssignmentModal.filteredAvailableTags = - this.dropdownParsedAvailableTags - .filter((tag) => { - return !this.tagsAssignmentModal.assignedTags.some( - (assigned) => assigned.tag_id === tag.value, - ); - }) - .filter((tag) => { - return tag.label.toLowerCase().includes(query); - })); - }, - removeAssignedTag(tag) { - this.tagsAssignmentModal.assignedTags = - this.tagsAssignmentModal.assignedTags.filter( - (assigned) => assigned.tag_id !== tag.tag_id, - ); - - this.tagsAssignmentModal.areFormButtonsDisplayed = true; - }, - async refreshTagsAssignmentModalData(calenderItem) { - this.tagsAssignmentModal.availableTags = - await this.fetchAvailableTags(); - this.tagsAssignmentModal.filteredAvailableTags = [ - ...this.dropdownParsedAvailableTags, - ]; - - this.tagsAssignmentModal.assignedTags = - await this.fetchAssignedTagsByCalender(calenderItem.eindeutige_gruppen_id); - this.tagsAssignmentModal.selectedAvailableTag = null; - this.tagsAssignmentModal.areFormButtonsDisplayed = false; - }, - async saveAssignedTagsToCalendarItem(calenderItem, assignedTags) { - let saveAssignedTagsByCalender = await this.$api.call( - ApiTempusTag.getTags( - calenderItem.eindeutige_gruppen_id, - assignedTags, - ), - ); - if (saveAssignedTagsByCalender.meta.status === "success") { - this.$fhcAlert.alertSuccess( - this.$p.t("ui", "assigned_tags_save_success_message"), - ); - await this.refreshTagsAssignmentModalData(calenderItem); - } else { - this.$fhcAlert.alertError( - this.$p.t("ui", "failed_assigned_tags_save_error_message"), - ); - } - - this.$refs.calendar.resetEventLoader(); - this.$refs.tagsAssignmentModal.hide(); - }, - closeTagsAssignmentModal() { - this.tagsAssignmentModal = { - availableTags: [], - filteredAvailableTags: [], - selectedAvailableTag: null, - assignedTags: [], - areFormButtonsDisplayed: false, - }; - }, - async handleCalenderTagChange(calenderID) { - this.tagsAssignmentModal.assignedTags = - await this.fetchAssignedTagsByCalender(calenderID); - - this.$refs.calendar.resetEventLoader(); - }, removeLecturer(uid) { if (uid == null) { for (const lect of this.lecturers) delete this.overlayCache[lect.uid]; @@ -1283,66 +1140,11 @@ export default { ref="resourcesAssignmentModal" @save-finished="$refs.calendar.resetEventLoader()" /> - - - - + @tags-changed="$refs.calendar.resetEventLoader()" + /> -