<template> <modal-inner class="modal__inner-1--templates" aria-label="管理模板"> <div class="modal__content"> <div class="form-entry"> <label class="form-entry__label" for="template">模板</label> <div class="form-entry__field"> <input v-if="isEditing" id="template" type="text" class="textfield" v-focus @blur="submitEdit()" @keydown.enter="submitEdit()" @keydown.esc.stop="submitEdit(true)" v-model="editingName"> <select v-else id="template" v-model="selectedId" class="textfield"> <option v-for="(template, id) in templates" :key="id" :value="id"> {{ template.name }} </option> </select> </div> <div class="form-entry__actions flex flex--row flex--end"> <button class="form-entry__button button" @click="create" v-title="'新建模板'"> <icon-file-plus></icon-file-plus> </button> <button class="form-entry__button button" @click="copy" v-title="'复制模板'"> <icon-file-multiple></icon-file-multiple> </button> <button v-if="!isReadOnly" class="form-entry__button button" @click="isEditing = true" v-title="'重命名模板'"> <icon-pen></icon-pen> </button> <button v-if="!isReadOnly" class="form-entry__button button" @click="remove" v-title="'删除模板'"> <icon-delete></icon-delete> </button> </div> </div> <div class="form-entry"> <label class="form-entry__label">值</label> <div class="form-entry__field" v-for="(template, id) in templates" :key="id" v-if="id === selectedId"> <code-editor lang="handlebars" :value="template.value" :disabled="isReadOnly" @changed="template.value = $event"></code-editor> </div> </div> <div v-if="!isReadOnly"> <a href="javascript:void(0)" v-if="!showHelpers" @click="showHelpers = true">添加帮助</a> <div class="form-entry" v-else> <br> <label class="form-entry__label">帮助</label> <div class="form-entry__field" v-for="(template, id) in templates" :key="id" v-if="id === selectedId"> <code-editor lang="javascript" :value="template.helpers" @changed="template.helpers = $event"></code-editor> </div> </div> </div> </div> <div class="modal__button-bar"> <button class="button" @click="config.reject()">取消</button> <button class="button button--resolve" @click="resolve()">确认</button> </div> </modal-inner> </template> <script> import { mapGetters } from 'vuex'; import utils from '../../services/utils'; import badgeSvc from '../../services/badgeSvc'; import ModalInner from './common/ModalInner'; import CodeEditor from '../CodeEditor'; import emptyTemplateValue from '../../data/empties/emptyTemplateValue.html'; import emptyTemplateHelpers from '!raw-loader!../../data/empties/emptyTemplateHelpers.js'; // eslint-disable-line import store from '../../store'; const collator = new Intl.Collator(undefined, { sensitivity: 'base' }); function fillEmptyFields(template) { if (template.value === '\n') { template.value = emptyTemplateValue; } if (template.helpers === '\n') { template.helpers = emptyTemplateHelpers; } } export default { components: { ModalInner, CodeEditor, }, data: () => ({ selectedId: '', templates: {}, showHelpers: false, isEditing: false, editingName: '', }), computed: { ...mapGetters('modal', [ 'config', ]), isReadOnly() { return this.templates[this.selectedId].isAdditional; }, }, created() { this.$watch( () => store.getters['data/allTemplatesById'], (allTemplatesById) => { const templates = {}; // Sort templates by name Object.entries(allTemplatesById) .sort(([, template1], [, template2]) => collator.compare(template1.name, template2.name)) .forEach(([id, template]) => { const templateClone = utils.deepCopy(template); fillEmptyFields(templateClone); templates[id] = templateClone; }); this.templates = templates; this.selectedId = this.config.selectedId; if (!templates[this.selectedId]) { [this.selectedId] = Object.keys(templates); } this.isEditing = false; }, { immediate: true }, ); this.$watch('selectedId', (selectedId) => { const template = this.templates[selectedId]; this.showHelpers = template.helpers !== emptyTemplateHelpers; this.editingName = template.name; }, { immediate: true }); }, methods: { create() { const template = { name: 'New template', value: '\n', helpers: '\n', }; fillEmptyFields(template); this.selectedId = utils.uid(); this.templates[this.selectedId] = template; this.isEditing = true; }, copy() { const template = utils.deepCopy(this.templates[this.selectedId]); template.name += ' copy'; delete template.isAdditional; this.selectedId = utils.uid(); this.templates[this.selectedId] = template; this.isEditing = true; }, remove() { delete this.templates[this.selectedId]; [this.selectedId] = Object.keys(this.templates); }, submitEdit(cancel) { const template = this.templates[this.selectedId]; if (!cancel && this.editingName) { template.name = utils.sanitizeName(this.editingName); } else { this.editingName = template.name; } setTimeout(() => { // For the form-entry to get the blur event this.isEditing = false; }, 1); }, async resolve() { const oldTemplateIds = Object.keys(store.getters['data/templatesById']); await store.dispatch('data/setTemplatesById', this.templates); const newTemplateIds = Object.keys(store.getters['data/templatesById']); const createdCount = newTemplateIds .filter(id => !oldTemplateIds.includes(id)) .length; const removedCount = oldTemplateIds .filter(id => !newTemplateIds.includes(id)) .length; if (createdCount) { badgeSvc.addBadge('addTemplate'); } if (removedCount) { badgeSvc.addBadge('removeTemplate'); } this.config.resolve({ templates: this.templates, selectedId: this.selectedId, }); }, }, }; </script> <style lang="scss"> .modal__inner-1.modal__inner-1--templates { max-width: 600px; } </style>