From a36cfade33ea2b76908a5d4322a557d458e48ddc Mon Sep 17 00:00:00 2001
From: Michael Bauer <michael-bauer@posteo.de>
Date: Fri, 22 Sep 2023 21:53:38 +0200
Subject: [PATCH] Move amend lesson (substitution ui) to own component

---
 .../frontend/components/AmendLesson.vue       | 189 ++++++++++++++++++
 .../calendar_feeds/details/LessonDetails.vue  | 183 +----------------
 2 files changed, 194 insertions(+), 178 deletions(-)
 create mode 100644 aleksis/apps/chronos/frontend/components/AmendLesson.vue

diff --git a/aleksis/apps/chronos/frontend/components/AmendLesson.vue b/aleksis/apps/chronos/frontend/components/AmendLesson.vue
new file mode 100644
index 00000000..aae3630e
--- /dev/null
+++ b/aleksis/apps/chronos/frontend/components/AmendLesson.vue
@@ -0,0 +1,189 @@
+<template>
+  <v-card-actions v-if="checkPermission('chronos.edit_substitution_rule')">
+    <edit-button
+      i18n-key="chronos.event.amend.edit_button"
+      @click="amendEvent.open = true"
+      />
+    <delete-button
+      v-if="selectedEvent.meta.amended"
+      i18n-key="chronos.event.amend.delete_button"
+      @click="amendEvent.delete = true"
+      />
+    <dialog-object-form
+      v-model="amendEvent.open"
+      :fields="amendEvent.fields"
+      :is-create="!selectedEvent.meta.amended"
+      createItemI18nKey="chronos.event.amend.title"
+      :gql-create-mutation="amendEvent.gqlCreateMutation"
+      :get-create-data="transformCreateData"
+      :default-item="amendEvent.default"
+      editItemI18nKey="chronos.event.amend.title"
+      :gql-patch-mutation="amendEvent.gqlPatchMutation"
+      :get-patch-data="transformPatchData"
+      :edit-item="initPatchData"
+      @cancel="amendEvent.open = false"
+      @save="updateOnSave()"
+      >
+      <template #subject.field="{ attrs, on, item }">
+        <v-autocomplete
+          :disabled="item.cancelled"
+          :items="amendableSubjects"
+          item-text="name"
+          item-value="id"
+          v-bind="attrs"
+          v-on="on"
+          />
+      </template>
+      <template #teachers.field="{ attrs, on, item }">
+        <v-autocomplete
+          :disabled="item.cancelled"
+          multiple
+          :items="amendableTeachers"
+          item-text="fullName"
+          item-value="id"
+          v-bind="attrs"
+          v-on="on"
+          chips
+          deletable-chips
+          />
+      </template>
+      <template #rooms.field="{ attrs, on, item }">
+        <v-autocomplete
+          :disabled="item.cancelled"
+          multiple
+          :items="amendableRooms"
+          item-text="name"
+          item-value="id"
+          v-bind="attrs"
+          v-on="on"
+          chips
+          deletable-chips
+          />
+      </template>
+      <template #cancelled.field="{ attrs, on }">
+        <v-checkbox v-bind="attrs" v-on="on" />
+      </template>
+      <template #comment.field="{ attrs, on }">
+        <v-textarea v-bind="attrs" v-on="on" />
+      </template>
+    </dialog-object-form>
+    <delete-dialog
+      deleteSuccessMessageI18nKey="chronos.event.amend.delete_success"
+      :gql-mutation="amendEvent.gqlDeleteMutation"
+      v-model="amendEvent.delete"
+      :item="selectedEvent.meta"
+      @success="updateOnSave()"
+      >
+      <template #title>
+        {{ $t("chronos.event.amend.delete_dialog") }}
+      </template>
+    </delete-dialog>
+  </v-card-actions>
+</template>
+
+<script>
+import permissionsMixin from "aleksis.core/mixins/permissions.js";
+import EditButton from "aleksis.core/components/generic/buttons/EditButton.vue";
+import DialogObjectForm from "aleksis.core/components/generic/dialogs/DialogObjectForm.vue";
+import DeleteButton from "aleksis.core/components/generic/buttons/DeleteButton.vue";
+import DeleteDialog from "aleksis.core/components/generic/dialogs/DeleteDialog.vue";
+import {
+  gqlSubjects,
+  gqlPersons,
+  gqlRooms,
+  createAmendLesson,
+  patchAmendLesson,
+  deleteAmendLesson,
+} from "./amendLesson.graphql";
+
+export default {
+  name: "AmendLesson",
+  components: {
+    EditButton,
+    DialogObjectForm,
+    DeleteButton,
+    DeleteDialog,
+  },
+  mixins: [permissionsMixin],
+  data() {
+    return {
+      amendEvent: {
+        open: false,
+        fields: [
+          {
+            text: this.$t("chronos.event.amend.subject"),
+            value: "subject",
+          },
+          {
+            text: this.$t("chronos.event.amend.teachers"),
+            value: "teachers",
+          },
+          {
+            text: this.$t("chronos.event.amend.rooms"),
+            value: "rooms",
+          },
+          {
+            text: this.$t("chronos.event.amend.cancelled"),
+            value: "cancelled",
+          },
+          {
+            text: this.$t("chronos.event.amend.comment"),
+            value: "comment",
+          },
+        ],
+        default: {
+          cancelled: this.selectedEvent.meta.cancelled,
+          comment: this.selectedEvent.meta.comment,
+        },
+        gqlCreateMutation: createAmendLesson,
+        gqlPatchMutation: patchAmendLesson,
+        delete: false,
+        gqlDeleteMutation: deleteAmendLesson,
+      },
+    };
+  },
+  methods: {
+    transformCreateData(item) {
+      return {
+        ...item,
+        amends: this.selectedEvent.meta.id,
+        datetimeStart: this.selectedEvent.startDateTime.toUTC().toISO(),
+        datetimeEnd: this.selectedEvent.endDateTime.toUTC().toISO(),
+      };
+    },
+    transformPatchData(item) {
+      let { id, __typename, cancelled, ...patchItem } = item;
+      return {
+        ...patchItem,
+        // Normalize cancelled, v-checkbox returns null & does not
+        // honor false-value.
+        cancelled: cancelled ? true : false,
+      };
+    },
+    updateOnSave() {
+      this.$emit('refreshCalendar');
+      this.model = false;
+    },
+  },
+  computed: {
+    initPatchData() {
+      return {
+        id: this.selectedEvent.meta.id,
+        subject: this.selectedEvent.meta.subject?.id.toString(),
+        teachers: this.selectedEvent.meta.teachers.map((teacher) => teacher.id.toString()),
+        rooms: this.selectedEvent.meta.rooms.map((room) => room.id.toString()),
+        cancelled: this.selectedEvent.meta.cancelled,
+        comment: this.selectedEvent.meta.comment,
+      };
+    },
+  },
+  apollo: {
+    amendableSubjects: gqlSubjects,
+    amendableTeachers: gqlPersons,
+    amendableRooms: gqlRooms,
+  },
+  mounted() {
+    this.addPermissions(["chronos.edit_substitution_rule"]);
+  },
+};
+</script>
diff --git a/aleksis/apps/chronos/frontend/components/calendar_feeds/details/LessonDetails.vue b/aleksis/apps/chronos/frontend/components/calendar_feeds/details/LessonDetails.vue
index 110a40cd..c8df491e 100644
--- a/aleksis/apps/chronos/frontend/components/calendar_feeds/details/LessonDetails.vue
+++ b/aleksis/apps/chronos/frontend/components/calendar_feeds/details/LessonDetails.vue
@@ -96,113 +96,23 @@
           </v-list-item-title>
         </v-list-item-content>
       </v-list-item>
-      <v-card-actions v-if="checkPermission('chronos.edit_substitution_rule')">
-        <edit-button
-          i18n-key="chronos.event.amend.edit_button"
-          @click="amendEvent.open = true"
-        />
-        <delete-button
-          v-if="selectedEvent.meta.amended"
-          i18n-key="chronos.event.amend.delete_button"
-          @click="amendEvent.delete = true"
-        />
-        <dialog-object-form
-          v-model="amendEvent.open"
-          :fields="amendEvent.fields"
-          :is-create="!selectedEvent.meta.amended"
-          createItemI18nKey="chronos.event.amend.title"
-          :gql-create-mutation="amendEvent.gqlCreateMutation"
-          :get-create-data="transformCreateData"
-          :default-item="amendEvent.default"
-          editItemI18nKey="chronos.event.amend.title"
-          :gql-patch-mutation="amendEvent.gqlPatchMutation"
-          :get-patch-data="transformPatchData"
-          :edit-item="initPatchData"
-          @cancel="amendEvent.open = false"
-          @save="updateOnSave()"
-        >
-          <template #subject.field="{ attrs, on, item }">
-            <v-autocomplete
-              :disabled="item.cancelled"
-              :items="amendableSubjects"
-              item-text="name"
-              item-value="id"
-              v-bind="attrs"
-              v-on="on"
-            />
-          </template>
-          <template #teachers.field="{ attrs, on, item }">
-            <v-autocomplete
-              :disabled="item.cancelled"
-              multiple
-              :items="amendableTeachers"
-              item-text="fullName"
-              item-value="id"
-              v-bind="attrs"
-              v-on="on"
-              chips
-              deletable-chips
-            />
-          </template>
-          <template #rooms.field="{ attrs, on, item }">
-            <v-autocomplete
-              :disabled="item.cancelled"
-              multiple
-              :items="amendableRooms"
-              item-text="name"
-              item-value="id"
-              v-bind="attrs"
-              v-on="on"
-              chips
-              deletable-chips
-            />
-          </template>
-          <template #cancelled.field="{ attrs, on }">
-            <v-checkbox v-bind="attrs" v-on="on" />
-          </template>
-          <template #comment.field="{ attrs, on }">
-            <v-textarea v-bind="attrs" v-on="on" />
-          </template>
-        </dialog-object-form>
-        <delete-dialog
-          deleteSuccessMessageI18nKey="chronos.event.amend.delete_success"
-          :gql-mutation="amendEvent.gqlDeleteMutation"
-          v-model="amendEvent.delete"
-          :item="selectedEvent.meta"
-          @success="updateOnSave()"
-        >
-          <template #title>
-            {{ $t("chronos.event.amend.delete_dialog") }}
-          </template>
-        </delete-dialog>
-      </v-card-actions>
+      <amend-lesson />
     </template>
   </base-calendar-feed-details>
 </template>
 
 <script>
-import permissionsMixin from "aleksis.core/mixins/permissions.js";
 import calendarFeedDetailsMixin from "aleksis.core/mixins/calendarFeedDetails.js";
 import BaseCalendarFeedDetails from "aleksis.core/components/calendar/BaseCalendarFeedDetails.vue";
 import CalendarStatusChip from "aleksis.core/components/calendar/CalendarStatusChip.vue";
 import CancelledCalendarStatusChip from "aleksis.core/components/calendar/CancelledCalendarStatusChip.vue";
-import EditButton from "aleksis.core/components/generic/buttons/EditButton.vue";
-import DialogObjectForm from "aleksis.core/components/generic/dialogs/DialogObjectForm.vue";
-import DeleteButton from "aleksis.core/components/generic/buttons/DeleteButton.vue";
-import DeleteDialog from "aleksis.core/components/generic/dialogs/DeleteDialog.vue";
 
 import LessonRelatedObjectChip from "../../LessonRelatedObjectChip.vue";
 
 import lessonEvent from "../mixins/lessonEvent";
 import LessonEventSubject from "../../LessonEventSubject.vue";
-import {
-  gqlSubjects,
-  gqlPersons,
-  gqlRooms,
-  createAmendLesson,
-  patchAmendLesson,
-  deleteAmendLesson,
-} from "../../amendLesson.graphql";
+
+import AmendLesson from "../../AmendLesson.vue";
 
 export default {
   name: "LessonDetails",
@@ -212,91 +122,8 @@ export default {
     BaseCalendarFeedDetails,
     CalendarStatusChip,
     CancelledCalendarStatusChip,
-    EditButton,
-    DialogObjectForm,
-    DeleteButton,
-    DeleteDialog,
-  },
-  mixins: [permissionsMixin, calendarFeedDetailsMixin, lessonEvent],
-  data() {
-    return {
-      amendEvent: {
-        open: false,
-        fields: [
-          {
-            text: this.$t("chronos.event.amend.subject"),
-            value: "subject",
-          },
-          {
-            text: this.$t("chronos.event.amend.teachers"),
-            value: "teachers",
-          },
-          {
-            text: this.$t("chronos.event.amend.rooms"),
-            value: "rooms",
-          },
-          {
-            text: this.$t("chronos.event.amend.cancelled"),
-            value: "cancelled",
-          },
-          {
-            text: this.$t("chronos.event.amend.comment"),
-            value: "comment",
-          },
-        ],
-        default: {
-          cancelled: this.selectedEvent.meta.cancelled,
-          comment: this.selectedEvent.meta.comment,
-        },
-        gqlCreateMutation: createAmendLesson,
-        gqlPatchMutation: patchAmendLesson,
-        delete: false,
-        gqlDeleteMutation: deleteAmendLesson,
-      },
-    };
-  },
-  methods: {
-    transformCreateData(item) {
-      return {
-        ...item,
-        amends: this.selectedEvent.meta.id,
-        datetimeStart: this.selectedEvent.startDateTime.toUTC().toISO(),
-        datetimeEnd: this.selectedEvent.endDateTime.toUTC().toISO(),
-      };
-    },
-    transformPatchData(item) {
-      let { id, __typename, cancelled, ...patchItem } = item;
-      return {
-        ...patchItem,
-        // Normalize cancelled, v-checkbox returns null & does not
-        // honor false-value.
-        cancelled: cancelled ? true : false,
-      };
-    },
-    updateOnSave() {
-      this.$emit('refreshCalendar');
-      this.model = false;
-    },
-  },
-  computed: {
-    initPatchData() {
-      return {
-        id: this.selectedEvent.meta.id,
-        subject: this.selectedEvent.meta.subject?.id.toString(),
-        teachers: this.selectedEvent.meta.teachers.map((teacher) => teacher.id.toString()),
-        rooms: this.selectedEvent.meta.rooms.map((room) => room.id.toString()),
-        cancelled: this.selectedEvent.meta.cancelled,
-        comment: this.selectedEvent.meta.comment,
-      };
-    },
-  },
-  apollo: {
-    amendableSubjects: gqlSubjects,
-    amendableTeachers: gqlPersons,
-    amendableRooms: gqlRooms,
-  },
-  mounted() {
-    this.addPermissions(["chronos.edit_substitution_rule"]);
+    AmendLesson,
   },
+  mixins: [calendarFeedDetailsMixin, lessonEvent],
 };
 </script>
-- 
GitLab