mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-11-10 17:36:33 +08:00
Add name prompt for tables with empty names [SCI-7082] (#4348)
* Add name prompt for tables with empty names [SCI-7082] * Move to separate component [SCI-7082]
This commit is contained in:
parent
32c53e223b
commit
e4a7aa3dad
6 changed files with 128 additions and 4 deletions
|
@ -2,6 +2,10 @@
|
|||
width: 370px;
|
||||
}
|
||||
|
||||
.modal-md {
|
||||
width: 450px;
|
||||
}
|
||||
|
||||
.modal {
|
||||
.modal-absolute-close-button {
|
||||
position: absolute;
|
||||
|
|
|
@ -68,4 +68,9 @@
|
|||
margin-left: .5em;
|
||||
}
|
||||
}
|
||||
|
||||
.table-name-error {
|
||||
color: $brand-danger;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
|
80
app/javascript/vue/protocol/modals/table_name_modal.vue
Normal file
80
app/javascript/vue/protocol/modals/table_name_modal.vue
Normal file
|
@ -0,0 +1,80 @@
|
|||
<template>
|
||||
<div ref="modal" class="modal" :id="`tableNameModal${element.attributes.orderable.id}`" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-md" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" @click="cancel" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title" id="modal-destroy-team-label">
|
||||
{{ i18n.t('protocols.steps.table.name_modal.title')}}
|
||||
</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>{{ i18n.t('protocols.steps.table.name_modal.description')}}</p>
|
||||
<div class="sci-input-container" :class="{ 'error': error }">
|
||||
<input ref="input" v-model="name" type="text" class="sci-input-field" @keyup.enter="!error && update(name)" required="true" />
|
||||
<div v-if="error" class="table-name-error">
|
||||
{{ i18n.t('protocols.steps.table.name_modal.error') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" @click="cancel">{{ i18n.t('general.cancel') }}</button>
|
||||
<button class="btn btn-primary" @click="update(name)">{{ i18n.t('protocols.steps.table.name_modal.save')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'TableNameModal',
|
||||
props: {
|
||||
element: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
name: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
defaultName() {
|
||||
return this.i18n.t('protocols.steps.table.default_name', { position: this.element.attributes.position + 1 });
|
||||
},
|
||||
error() {
|
||||
return !this.name;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initModal();
|
||||
$(this.$refs.modal).modal('show');
|
||||
},
|
||||
methods: {
|
||||
initModal() {
|
||||
this.name = this.defaultName;
|
||||
$(this.$refs.modal).on('shown.bs.modal', () => {
|
||||
$(this.$refs.input).focus();
|
||||
});
|
||||
},
|
||||
cancel() {
|
||||
this.hide(() => {
|
||||
this.$emit('cancel');
|
||||
});
|
||||
},
|
||||
update() {
|
||||
this.hide(() => {
|
||||
this.$emit('update', this.name);
|
||||
})
|
||||
},
|
||||
hide(callback) {
|
||||
$(this.$refs.modal).on('hidden.bs.modal', () => {
|
||||
callback();
|
||||
});
|
||||
$(this.$refs.modal).modal('hide');
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -327,7 +327,7 @@
|
|||
this.reorderElements(unorderedElements)
|
||||
this.$emit('stepUpdated')
|
||||
},
|
||||
updateElement(element, skipRequest=false) {
|
||||
updateElement(element, skipRequest=false, callback) {
|
||||
let index = this.elements.findIndex((e) => e.id === element.id);
|
||||
this.elements[index].isNew = false;
|
||||
|
||||
|
@ -342,6 +342,11 @@
|
|||
success: (result) => {
|
||||
this.elements[index].attributes.orderable = result.data.attributes;
|
||||
this.$emit('stepUpdated');
|
||||
|
||||
// optional callback after successful update
|
||||
if(typeof callback === 'function') {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
}).error(() => {
|
||||
HelperModule.flashAlertMsg(this.i18n.t('errors.general'), 'danger');
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<i class="fas fas-rotated-90 fa-exchange-alt"></i>
|
||||
</div>
|
||||
<div v-else class="step-element-grip-placeholder"></div>
|
||||
<div v-if="!locked || element.attributes.orderable.name" class="step-element-name">
|
||||
<div v-if="!locked || element.attributes.orderable.name" :key="reloadHeader" class="step-element-name">
|
||||
<InlineEdit
|
||||
:value="element.attributes.orderable.name"
|
||||
:characterLimit="255"
|
||||
|
@ -51,6 +51,7 @@
|
|||
</button>
|
||||
</div>
|
||||
<deleteElementModal v-if="confirmingDelete" @confirm="deleteElement" @cancel="closeDeleteModal"/>
|
||||
<tableNameModal v-if="nameModalOpen" :element="element" @update="updateEmptyName" @cancel="nameModalOpen = false" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -58,10 +59,11 @@
|
|||
import DeleteMixin from 'vue/protocol/mixins/components/delete.js'
|
||||
import deleteElementModal from 'vue/protocol/modals/delete_element.vue'
|
||||
import InlineEdit from 'vue/shared/inline_edit.vue'
|
||||
import TableNameModal from 'vue/protocol/modals/table_name_modal.vue'
|
||||
|
||||
export default {
|
||||
name: 'StepTable',
|
||||
components: { deleteElementModal, InlineEdit },
|
||||
components: { deleteElementModal, InlineEdit, TableNameModal },
|
||||
mixins: [DeleteMixin],
|
||||
props: {
|
||||
element: {
|
||||
|
@ -83,7 +85,9 @@
|
|||
return {
|
||||
editingName: false,
|
||||
editingTable: false,
|
||||
tableObject: null
|
||||
tableObject: null,
|
||||
nameModalOpen: false,
|
||||
reloadHeader: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -104,6 +108,11 @@
|
|||
},
|
||||
methods: {
|
||||
enableTableEdit() {
|
||||
if (!this.element.attributes.orderable.name) {
|
||||
this.openNameModal();
|
||||
return;
|
||||
}
|
||||
|
||||
this.editingTable = true;
|
||||
this.$nextTick(() => this.tableObject.selectCell(0,0));
|
||||
},
|
||||
|
@ -120,6 +129,22 @@
|
|||
this.element.attributes.orderable.name = name;
|
||||
this.update();
|
||||
},
|
||||
openNameModal() {
|
||||
this.tableObject.deselectCell();
|
||||
this.nameModalOpen = true;
|
||||
},
|
||||
updateEmptyName(name) {
|
||||
this.disableNameEdit();
|
||||
|
||||
// force reload header to properly reset name inline edit
|
||||
this.reloadHeader = this.reloadHeader + 1;
|
||||
|
||||
this.element.attributes.orderable.name = name;
|
||||
this.$emit('update', this.element, false, () => {
|
||||
this.nameModalOpen = false;
|
||||
this.enableTableEdit();
|
||||
});
|
||||
},
|
||||
updateTable() {
|
||||
if (this.editingTable == false) return;
|
||||
|
||||
|
|
|
@ -2570,6 +2570,11 @@ en:
|
|||
table:
|
||||
default_name: 'Table %{position}'
|
||||
edit_message: 'Use right click for table options'
|
||||
name_modal:
|
||||
title: 'Please enter the table title'
|
||||
description: 'Tables have become content blocks and require a name. To be able to edit the table, please add the name now:'
|
||||
save: 'Save table title'
|
||||
error: "Table name can't be empty"
|
||||
checklist:
|
||||
default_name: 'Checklist %{position}'
|
||||
empty_checklist: 'Doesn’t contain any checklist items'
|
||||
|
|
Loading…
Reference in a new issue