scinote-web/app/javascript/vue/forms/show.vue
andrej-scinote 705fc4da14 Merge pull request #8093 from andrej-scinote/aj_SCI_11354
Fix reordering of the form fields [SCI-11354]
2024-12-10 15:59:39 +01:00

169 lines
5 KiB
Vue

<template>
<div v-if="form" class="content-pane flexible with-grey-background">
<div class="content-header flex items-center mb-4">
<div class="title-row">
<h1>
<InlineEdit
v-if="canManage"
:value="form.attributes.name"
:characterLimit="255"
:characterMinLimit="2"
:allowBlank="false"
@editingEnabled="editingName = true"
@editingDisabled="editingName = false"
@update="updateName"
/>
<template v-else>
{{ form.attributes.name }}
</template>
</h1>
</div>
<div class="flex items-center gap-4 ml-auto">
<button class="btn btn-secondary">
<i class="sn-icon sn-icon-visibility-show"></i>
{{ i18n.t('forms.show.test_form') }}
</button>
<button class="btn btn-primary">
{{ i18n.t('forms.show.publish') }}
</button>
</div>
</div>
<div class="content-body">
<div class="bg-white rounded-xl grid grid-cols-[360px_auto] min-h-[calc(100vh_-_200px)]">
<div class="p-6 border-transparent border-r-sn-sleepy-grey border-solid border-r">
<h3 class="mb-3">{{ i18n.t('forms.show.build_form') }}</h3>
<div class="mb-3 flex flex-col gap-3">
<div v-for="(field) in fields"
@click="activeField = field"
:key="field.id"
class="font-bold p-3 rounded-lg border-sn-grey-100 cursor-pointer border"
:class="{ '!border-sn-blue bg-sn-super-light-blue': activeField.id === field.id }"
>
{{ field.attributes.name }}
</div>
</div>
<GeneralDropdown>
<template v-slot:field>
<button class="btn btn-secondary w-full">
<i class="sn-icon sn-icon-new-task"></i>
{{ i18n.t('forms.show.add_block') }}
</button>
</template>
<template v-slot:flyout>
<div v-for="e in newFields" :key="e.type" @click="addField(e.type)" class="py-2.5 px-3 hover:bg-sn-super-light-grey cursor-pointer">
{{ e.name }}
</div>
</template>
</GeneralDropdown>
</div>
<div class="p-6">
<EditField
:key="activeField.id"
v-if="activeField.id"
:field="activeField"
@update="updateField"
@delete="deleteField"
/>
</div>
</div>
</div>
</div>
</template>
<script>
import InlineEdit from '../shared/inline_edit.vue';
import axios from '../../packs/custom_axios.js';
import GeneralDropdown from '../shared/general_dropdown.vue';
import EditField from './edit_field.vue';
export default {
name: 'ShowForm',
props: {
formUrl: String
},
components: {
InlineEdit,
GeneralDropdown,
EditField
},
computed: {
canManage() {
return true;
},
newFields() {
return [
{ name: this.i18n.t('forms.show.blocks.text'), type: 'text' },
{ name: this.i18n.t('forms.show.blocks.number'), type: 'number' },
{ name: this.i18n.t('forms.show.blocks.single_choice'), type: 'single_choice' },
{ name: this.i18n.t('forms.show.blocks.multiple_choice'), type: 'multiple_choice' },
{ name: this.i18n.t('forms.show.blocks.datetime'), type: 'datetime' }
];
}
},
created() {
this.loadForm();
},
data() {
return {
form: null,
fields: [],
activeField: {}
};
},
methods: {
loadForm() {
axios.get(this.formUrl).then((response) => {
this.form = response.data.data;
this.fields = response.data.included || [];
if (this.fields.length > 0) {
[this.activeField] = this.fields;
}
});
},
addField(type) {
axios.post(this.form.attributes.urls.create_field, {
form_field: {
name: this.i18n.t(`forms.show.blocks.${type}`),
data: {
type
}
}
}).then((response) => {
this.fields.push(response.data.data);
if (this.fields.length === 1) {
[this.activeField] = this.fields;
}
});
},
updateName(name) {
axios.put(this.formUrl, {
form: {
name
}
}).then(() => {
this.form.attributes.name = name;
});
},
updateField(field) {
const index = this.fields.findIndex((f) => f.id === field.id);
axios.put(field.attributes.urls.show, {
form_field: field.attributes
}).then((response) => {
this.fields.splice(index, 1, response.data.data);
});
},
deleteField(field) {
const index = this.fields.findIndex((f) => f.id === field.id);
axios.delete(field.attributes.urls.show).then(() => {
this.fields.splice(index, 1);
if (this.fields.length > 0) {
[this.activeField] = this.fields;
} else {
this.activeField = {};
}
});
}
}
};
</script>