Skip to content
Snippets Groups Projects
LessonSummary.vue 8.07 KiB
Newer Older
permcu's avatar
permcu committed
<template>
    <!-- compact -->
      class="d-flex flex-column flex-md-row align-stretch align-md-center gap justify-start fill-height"
      <documentation-compact-details
        v-bind="dialogActivator.attrs"
        v-on="dialogActivator.on"
        v-if="
          !documentation.canEdit &&
          (documentation.topic ||
            documentation.homework ||
            documentation.groupNote)
        "
        :documentation="documentation"
        @click="$emit('open')"
        :class="{
          'flex-grow-1 min-width pa-1 read-only-grid': true,
          'full-width': $vuetify.breakpoint.mobile,
        }"
      />
      <v-alert
        v-else-if="documentation.futureNotice"
        type="warning"
        outlined
        class="min-width flex-grow-1 mb-0"
      >
        {{ $t("alsijil.coursebook.notices.future") }}
      </v-alert>
      <v-alert
        v-else-if="!documentation.canEdit"
        type="info"
        outlined
        class="min-width flex-grow-1 mb-0"
      >
        {{ $t("alsijil.coursebook.notices.no_entry") }}
      </v-alert>

      <v-text-field
Hangzhi Yu's avatar
Hangzhi Yu committed
        :class="{
          'flex-grow-1 min-width': true,
          'full-width': $vuetify.breakpoint.mobile,
        }"
        hide-details
Julian's avatar
Julian committed
        outlined
        :label="$t('alsijil.coursebook.summary.topic.label')"
        :value="documentation.topic"
        @input="topic = $event"
        @focusout="save"
        @keydown.enter="saveAndBlur"
        :loading="loading"
Hangzhi Yu's avatar
Hangzhi Yu committed
      >
        <template #append>
Hangzhi Yu's avatar
Hangzhi Yu committed
          <v-tooltip bottom>
Julian's avatar
Julian committed
            <template #activator="{ on, attrs }">
Hangzhi Yu's avatar
Hangzhi Yu committed
              <v-scroll-x-transition>
                <v-icon
                  v-if="appendIcon"
                  :color="appendIconColor"
                  v-on="on"
                  v-bind="attrs"
                  >{{ appendIcon }}</v-icon
                >
              </v-scroll-x-transition>
            </template>
            <span>{{ appendIconTooltip }}</span>
          </v-tooltip>
        </template>
      </v-text-field>
Hangzhi Yu's avatar
Hangzhi Yu committed
      <div
        :class="{
          'flex-grow-1 max-width': true,
          'full-width': $vuetify.breakpoint.mobile,
        }"
Hangzhi Yu's avatar
Hangzhi Yu committed
      >
          v-bind="dialogActivator.attrs"
          v-on="dialogActivator.on"
          @click="$emit('open')"
          class="max-width grid-layout pa-1"
Julian's avatar
Julian committed
          dense
        >
          <span class="max-width text-truncate">{{
            documentation.homework
              ? $t("alsijil.coursebook.summary.homework.value", documentation)
              : $t("alsijil.coursebook.summary.homework.empty")
          }}</span>
          <v-icon right class="float-right">{{ homeworkIcon }}</v-icon>
          <span class="max-width text-truncate">{{
            documentation.groupNote
              ? $t("alsijil.coursebook.summary.group_note.value", documentation)
              : $t("alsijil.coursebook.summary.group_note.empty")
          }}</span>
          <v-icon right class="float-right">{{ groupNoteIcon }}</v-icon>
        </v-card>
      </div>
    </div>
    <!-- not compact -->
    <!-- Are focusout & enter enough trigger? -->
    <v-text-field
      filled
      :label="$t('alsijil.coursebook.summary.topic.label')"
      :value="documentation.topic"
Julian's avatar
Julian committed
      @input="topic = $event"
    />
    <v-textarea
      filled
      auto-grow
Julian's avatar
Julian committed
      :label="$t('alsijil.coursebook.summary.homework.label')"
      :value="documentation.homework"
      @input="homework = $event ? $event : ''"
    />
    <v-textarea
      filled
      auto-grow
Julian's avatar
Julian committed
      :label="$t('alsijil.coursebook.summary.group_note.label')"
      :value="documentation.groupNote"
      @input="groupNote = $event ? $event : ''"
    />

    <documentation-full-details
      v-if="!compact && !documentation.canEdit"
      :documentation="documentation"
Julian's avatar
Julian committed
    />
permcu's avatar
permcu committed
</template>

<script setup>
import DocumentationCompactDetails from "./DocumentationCompactDetails.vue";
import DocumentationFullDetails from "./DocumentationFullDetails.vue";
</script>

permcu's avatar
permcu committed
<script>
import createOrPatchMixin from "aleksis.core/mixins/createOrPatchMixin.js";
import documentationPartMixin from "./documentationPartMixin";
permcu's avatar
permcu committed
export default {
  name: "LessonSummary",
  mixins: [createOrPatchMixin, documentationPartMixin],
  emits: ["open"],
      topic: null,
      homework: null,
      groupNote: null,
      appendIcon: null,
      topicError: null,
Julian's avatar
Julian committed
    handleUpdateAfterCreateOrPatch(itemId) {
permcu's avatar
permcu committed
      return (cached, incoming) => {
        for (const object of incoming) {
Julian's avatar
Julian committed
          console.log("summary: handleUpdateAfterCreateOrPatch", object);
permcu's avatar
permcu committed
          // Replace the current documentation
Julian's avatar
Julian committed
          const index = cached.findIndex(
            (o) => o[itemId] === this.documentation.id,
          );
permcu's avatar
permcu committed
          // merged with the incoming partial documentation
Hangzhi Yu's avatar
Hangzhi Yu committed
          // if creation of proper documentation from dummy one, set ID of documentation currently being edited as oldID so that key in coursebook doesn't change
Hangzhi Yu's avatar
Hangzhi Yu committed
          cached[index] = {
            ...this.documentation,
            ...object,
Jonathan Weth's avatar
Jonathan Weth committed
            oldId:
              this.documentation.id !== object.id
                ? this.documentation.id
                : this.documentation.oldId,
Hangzhi Yu's avatar
Hangzhi Yu committed
          };
permcu's avatar
permcu committed
        }
        return cached;
      };
    },
    handleAppendIconSuccess() {
      this.topicError = null;
      this.appendIcon = "$success";
Hangzhi Yu's avatar
Hangzhi Yu committed
      setTimeout(() => {
        this.appendIcon = "";
      }, 3000);
Hangzhi Yu's avatar
Hangzhi Yu committed
      if (
        this.topic !== null ||
        this.homework !== null ||
        this.groupNote !== null
      ) {
Julian's avatar
Julian committed
        this.createOrPatch([
          {
            id: this.documentation.id,
Hangzhi Yu's avatar
Hangzhi Yu committed
            ...(this.topic !== null && { topic: this.topic }),
            ...(this.homework !== null && { homework: this.homework }),
            ...(this.groupNote !== null && { groupNote: this.groupNote }),
Julian's avatar
Julian committed
          },
        ]);
        this.topic = null;
        this.homework = null;
        this.groupNote = null;
    saveAndBlur(event) {
      this.save();
      event.target.blur();
    handleError(error) {
      this.appendIcon = "$error";
      this.topicError = error;
  computed: {
    homeworkIcon() {
      if (this.documentation.homework) {
Julian's avatar
Julian committed
        return this.documentation.canEdit
          ? "mdi-book-edit-outline"
          : "mdi-book-alert-outline";
Julian's avatar
Julian committed
      return this.documentation.canEdit
        ? "mdi-book-plus-outline"
        : "mdi-book-off-outline";
    },
    groupNoteIcon() {
      if (this.documentation.groupNote) {
Julian's avatar
Julian committed
        return this.documentation.canEdit
          ? "mdi-note-edit-outline"
          : "mdi-note-alert-outline";
Julian's avatar
Julian committed
      return this.documentation.canEdit
        ? "mdi-note-plus-outline"
        : "mdi-note-off-outline";
    minWidth() {
      return Math.min(this.documentation?.topic?.length || 15, 15) + "ch";
    },
    maxWidth() {
      return this.$vuetify.breakpoint.mobile ? "100%" : "20ch";
    },
    appendIconColor() {
Hangzhi Yu's avatar
Hangzhi Yu committed
      return (
        { $success: "success", $error: "error" }[this.appendIcon] || "primary"
      );
    },
    appendIconTooltip() {
      return (
Hangzhi Yu's avatar
Hangzhi Yu committed
        {
          $success: this.$t("alsijil.coursebook.summary.topic.status.success"),
          $error: this.$t("alsijil.coursebook.summary.topic.status.error", {
            error: this.topicError,
          }),
        }[this.appendIcon] || ""
  mounted() {
    this.$on("save", this.handleAppendIconSuccess);
  },
permcu's avatar
permcu committed
};
</script>

<style scoped>
.min-width {
  min-width: v-bind(minWidth);
Hangzhi Yu's avatar
Hangzhi Yu committed
  max-width: v-bind(maxWidth);

.grid-layout {
  display: grid;
  grid-template-columns: auto min-content;
}

.read-only-grid {
  display: grid;
  grid-template-columns: min-content auto;
  grid-template-rows: auto;
}