Path: blob/main/frontend/vue/components/Syllabus/SyllabusForm.vue
3375 views
<template> <section class="syllabus-form"> <bx-tabs :value="defaultActiveTab"> <bx-tab id="tab-write" class="syllabus-form__tab" target="panel-write" value="write"> {{ $translate('Write') }} </bx-tab> </bx-tabs> <div id="panel-write" class="syllabus-form__tab-panel" role="tabpanel" aria-labelledby="tab-write"> <SyllabusFormCourseInfo :syllabus="syllabus" @change="syllabusInfoChanged" /> <SyllabusFormModule v-for="(course, index) in syllabus.courseList" :key="index" :show-close-button="syllabus.courseList.length > 1" :course="course" @removeModuleAction="removeContentBlock(course)" @change="newCourse => courseInfoChanged(newCourse, index)" /> <div class="syllabus-form__add-content"> <BasicLink class="syllabus-form__add-content__link" v-bind="addContentLink" @click="addContentBlock" > {{ addContentLink.label }} </BasicLink> </div> <SyllabusInlineNotification v-if="lastDeletedCourse" @on-close-notification="closeNotification" @undo-deletion="undoDeleteAction" /> <div class="syllabus-form__actions"> <AppCta class="syllabus-form__actions__cancel" v-bind="cancelAction" target="_self" kind="ghost" /> <AppCta ref="submitForm" :label="submitAction.label" :segment="submitAction.segment" target="_self" @click="submitForm($event)" /> </div> </div> </section> </template> <script lang="ts"> import { defineComponent } from 'vue-demi' import 'carbon-web-components/es/components/tabs/tabs.js' import 'carbon-web-components/es/components/tabs/tab.js' import AppCta from '../common/AppCta.vue' import BasicLink from '../common/BasicLink.vue' import { Syllabus, SyllabusCourse, emptySyllabus, getActiveSyllabus } from '../../../ts/syllabus' import SyllabusFormCourseInfo from './SyllabusFormCourseInfo.vue' import SyllabusFormModule from './SyllabusFormModule.vue' import SyllabusInlineNotification from './SyllabusInlineNotification.vue' interface DeletedCourse { index: number, course: SyllabusCourse } export default defineComponent({ name: 'SyllabusForm', components: { AppCta, BasicLink, SyllabusFormCourseInfo, SyllabusFormModule, SyllabusInlineNotification }, data () { return { editMode: false, defaultActiveTab: 'write', lastDeletedCourse: undefined as DeletedCourse|undefined, addContentLink: { label: 'Add content', url: '#' }, cancelAction: { url: '/account/classroom', label: this.$translate('Cancel'), segment: { cta: 'cancel', location: 'create-syllabus' } }, submitAction: { label: 'Publish syllabus', url: '#', segment: { cta: 'publish-syllabus', location: 'create-syllabus' } }, syllabus: emptySyllabus() } }, mounted () { const activeSyllabus = getActiveSyllabus() if (activeSyllabus) { this.syllabus = activeSyllabus this.editMode = true } this.syllabusInfoChanged(this.syllabus) }, methods: { addContentBlock () { this.syllabus.courseList.push({ title: '', description: '', unitList: [] }) }, removeContentBlock (course: SyllabusCourse) { const index = this.syllabus.courseList.indexOf(course) this.lastDeletedCourse = { index, course } this.syllabus.courseList.splice(index, 1) }, closeNotification () { this.lastDeletedCourse = undefined }, submitForm () { const url = this.editMode ? `/syllabus/${this.syllabus.id}` : '/syllabus' const csrfToken = { _csrf: window.csrfToken } fetch(url, { method: 'POST', // *GET, POST, PUT, DELETE, etc. headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ ...csrfToken, ...this.syllabus }) }).then((res) => { if (res.status === 200) { res.json().then((jsonResult: Syllabus) => { window.location.href = `/syllabus/${jsonResult.code}` }) } else { // TODO: Manage this error (and improve backend feedback) console.error(res) } }) }, undoDeleteAction () { if (!this.lastDeletedCourse) { return } const index = this.lastDeletedCourse.index this.syllabus.courseList.splice(index, 0, this.lastDeletedCourse.course) this.lastDeletedCourse = undefined }, syllabusInfoChanged (data: Syllabus) { this.syllabus = data if (this.syllabus.name && this.syllabus.instructor) { ((this.$refs.submitForm as AppCta).$el as HTMLElement).removeAttribute('disabled') } else { ((this.$refs.submitForm as AppCta).$el as HTMLElement).setAttribute('disabled', 'true') } }, courseInfoChanged (data: SyllabusCourse, index: number) { this.syllabus.courseList[index] = data } } }) </script> <style lang="scss" scoped> @import 'carbon-components/scss/globals/scss/typography'; @import '~/../scss/variables/mq.scss'; @import '~/../scss/mixins/mixins.scss'; @import '~/../scss/variables/colors.scss'; .syllabus-form { margin-top: $spacing-06; &__tab { --cds-interactive-01: #{$border-color-secondary}; max-width: 6rem; } &__add-content { display: flex; padding: $spacing-03 $spacing-05; background-color: $background-color-lighter; margin-bottom: $spacing-05; &__link { color: $text-active-color; @include type-style('body-long-01'); } } &__actions { display: flex; justify-content: flex-end; padding-top: $spacing-05; &__cancel { display: flex; justify-content: space-between; padding: $spacing-05; background-color: $background-color-lighter; margin-right: $spacing-05; :deep() > .app-cta__icon { transform: rotate(180deg); } } &__container { display: flex; flex-direction: column; align-items: flex-end; padding: $spacing-07 0; } } } </style>