Allows continuing editing on FieldList even after closing the form. A red color indicates errors and non-saved items. Still needs to prevent this in case no change was made on Form.

This commit is contained in:
mateuswetah 2018-03-19 17:11:24 -03:00
parent 3fe487b703
commit 8775239945
8 changed files with 145 additions and 55 deletions

View File

@ -98,10 +98,10 @@
<div class="field is-grouped form-submit">
<div class="control">
<button class="button is-outlined" @click.prevent="cancelEdition()" slot="trigger">Cancel</button>
<button class="button is-outlined" @click.prevent="cancelEdition()" slot="trigger">{{ $i18n.get('cancel')}}</button>
</div>
<div class="control">
<button class="button is-success" type="submit">Submit</button>
<button class="button is-success" type="submit">{{ $i18n.get('save')}}</button>
</div>
</div>
<p class="help is-danger">{{formErrorMessage}}</p>

View File

@ -55,10 +55,10 @@
<div class="field is-grouped form-submit">
<div class="control">
<button class="button is-outlined" @click.prevent="cancelEdition()" slot="trigger">Cancel</button>
<button class="button is-outlined" @click.prevent="cancelEdition()" slot="trigger">{{ $i18n.get('cancel')}}</button>
</div>
<div class="control">
<button class="button is-success" type="submit">Submit</button>
<button class="button is-success" type="submit">{{ $i18n.get('save')}}</button>
</div>
</div>
<p class="help is-danger">{{formErrorMessage}}</p>

View File

@ -22,8 +22,12 @@
:class="{'not-sortable-item': field.id == undefined || openedFieldId == field.id, 'not-focusable-item': openedFieldId == field.id, 'disabled-field': field.enabled == false}"
v-for="(field, index) in activeFieldList" :key="index">
<div class="handle">
<b-icon type="is-gray" class="is-pulled-left" icon="drag"></b-icon>
<span class="field-name" :class="{'is-danger': formWithErrors == field.id}">{{ field.name }}</span>
<grip-icon></grip-icon>
<span
class="field-name"
:class="{'is-danger': formWithErrors == field.id || (editForms[field.id] != undefined && openedFieldId != field.id)}">
{{ field.name }}
</span>
<span v-if="field.id !== undefined" class="label-details">({{ $i18n.get(field.field_type_object.component)}})</span><span class="loading-spinner" v-if="field.id == undefined"></span>
<span class="controls" v-if="field.id !== undefined">
<b-switch size="is-small" v-model="field.enabled" @input="onChangeEnable($event, index)"></b-switch>
@ -52,7 +56,7 @@
@onEditionFinished="onEditionFinished()"
@onEditionCanceled="onEditionCanceled()"
@onErrorFound="formWithErrors = field.id"
:field="editForm"></field-edition-form>
:field="editForms[field.id]"></field-edition-form>
</div>
</div>
</draggable>
@ -74,7 +78,7 @@
:class="{ 'hightlighted-field' : hightlightedField == field.name }"
v-for="(field, index) in availableFieldList"
:key="index">
<b-icon type="is-gray" class="is-pulled-left" icon="drag"></b-icon> <span class="field-name">{{ field.name }}</span>
<grip-icon></grip-icon> <span class="field-name">{{ field.name }}</span>
</div>
</draggable>
</div>
@ -85,6 +89,7 @@
<script>
import { mapActions, mapGetters } from 'vuex';
import GripIcon from '../other/grip-icon.vue';
import FieldEditionForm from './../edition/field-edition-form.vue';
export default {
@ -100,11 +105,12 @@ export default {
openedFieldId: '',
formWithErrors: '',
hightlightedField: '',
editForm: {},
editForms: {}
}
},
components: {
FieldEditionForm
FieldEditionForm,
GripIcon
},
methods: {
...mapActions('fields', [
@ -180,22 +186,28 @@ export default {
});
},
editField(field) {
if (this.openedFieldId == field.id) {
if (this.openedFieldId == field.id) {
if (this.editForms[this.openedFieldId] == JSON.parse(JSON.stringify(field))) {
delete this.editForms[this.openedFieldId];
}
this.openedFieldId = '';
this.editForm = {};
} else {
this.openedFieldId = field.id;
this.editForm = JSON.parse(JSON.stringify(field));
this.editForm.status = 'publish';
}
if (this.editForms[this.openedFieldId] == undefined || this.editForms[this.openedFieldId] == null) {
this.editForms[this.openedFieldId] = JSON.parse(JSON.stringify(field));
this.editForms[this.openedFieldId].status = 'publish';
}
}
},
onEditionFinished() {
this.formWithErrors = '';
delete this.editForms[this.openedFieldId];
this.openedFieldId = '';
this.fetchFields({collectionId: this.collectionId, isRepositoryLevel: this.isRepositoryLevel});
},
onEditionCanceled() {
this.formWithErrors = '';
delete this.editForms[this.openedFieldId];
this.openedFieldId = '';
}
@ -289,7 +301,12 @@ export default {
position: relative;
transition: top 0.1s linear;
cursor: grab;
.grip-icon {
fill: $gray;
top: 2px;
position: relative;
}
.field-name {
text-overflow: ellipsis;
overflow-x: hidden;
@ -297,6 +314,10 @@ export default {
font-weight: bold;
margin-left: 0.4em;
margin-right: 0.4em;
&.is-danger {
color: $danger !important;
}
}
.label-details {
font-weight: normal;
@ -333,9 +354,6 @@ export default {
.field-name {
color: $primary !important;
&.is-danger {
color: $danger !important;
}
}
.label-details, .icon {
color: $gray !important;
@ -355,6 +373,10 @@ export default {
color: white !important;
}
.grip-icon {
fill: white;
}
.switch.is-small {
input[type="checkbox"] + .check {
border: 1.5px solid white !important;
@ -416,6 +438,11 @@ export default {
border-radius: 1px;
transition: left 0.2s ease;
.grip-icon {
fill: $gray;
top: 2px;
position: relative;
}
.icon {
position: relative;
bottom: 3px;
@ -482,10 +509,10 @@ export default {
}
}
@keyframes hightlighten-icon {
0% { color: #b1b1b1; }
25% { color: white; }
75% { color: white; }
100% { color: #b1b1b1; }
0% { fill: #b1b1b1; }
25% { fill: white; }
75% { fill: white; }
100% { fill: #b1b1b1; }
}
@keyframes hightlighten-arrow {
0% {
@ -513,7 +540,7 @@ export default {
animation-duration: 1.0s;
animation-iteration-count: 2;
.icon{
.grip-icon{
animation-name: hightlighten-icon;
animation-duration: 1.0s;
animation-iteration-count: 2;
@ -542,6 +569,11 @@ export default {
.icon {
color: white !important;
}
.grip-icon {
fill: white;
}
}
}

View File

@ -19,10 +19,10 @@
animation: '250'}">
<div
class="active-filter-item"
:class="{'not-sortable-item': filter.id == undefined || openedFilterId == filter.id, 'not-focusable-item': openedFilterId == filter.id, 'disabled-filter': filter.enabled == false}"
:class="{'not-sortable-item': filter.id == undefined || openedFilterId == filter.id || choosenField.name == filter.name, 'not-focusable-item': openedFilterId == filter.id, 'disabled-filter': filter.enabled == false}"
v-for="(filter, index) in activeFilterList" :key="index">
<div class="handle">
<b-icon type="is-gray" class="is-pulled-left" icon="drag"></b-icon>
<grip-icon></grip-icon>
<span v-if="filter.id !== undefined" class="filter-name">{{ filter.name }}</span>
<span v-if="filter.id !== undefined" class="label-details"><span class="loading-spinner" v-if="filter.id == undefined"></span>
<span class="controls" v-if="filter.id != undefined">
@ -36,8 +36,8 @@
<b-icon icon="pencil"></b-icon>
</a>
</span>
<b-modal :active.sync="isModalOpened" :width="320" scroll="keep">
<div class="filter-selection-modal">
<div v-if="choosenField.name == filter.name">
<form class="tainacan-form">
<b-field :label="$i18n.get('label_filter_type')">
<b-select
v-model="selectedFilterType"
@ -50,23 +50,24 @@
{{ filterType.name }}</option>
</b-select>
</b-field>
<div class="field is-grouped is-grouped-centered">
<div class="field is-grouped form-submit">
<div class="control">
<button
class="button is-outlined"
@click.prevent="cancelFilterTypeSelection()"
slot="trigger">{{ $i18n.get('cancel')}}</button>
</div>
<div class="control">
<button
class="button is-secondary"
class="button is-success"
type="submit"
:disabled="Object.keys(selectedFilterType).length == 0"
@click.prevent="confirmSelectedFilterType()">Submit</button>
</div>
<div class="control">
<button
class="button is-text"
@click.prevent="cancelFilterTypeSelection()"
slot="trigger">Cancel</button>
@click.prevent="confirmSelectedFilterType()">{{ $i18n.get('next')}}</button>
</div>
</div>
</form>
</div>
</b-modal>
</div>
<b-field v-if="openedFilterId == filter.id">
<filter-edition-form
@ -93,7 +94,7 @@
v-for="(field, index) in availableFieldList"
:key="index"
@click.prevent="addFieldViaButton(field)">
<b-icon type="is-gray" class="is-pulled-left" icon="drag"></b-icon> <span class="field-name">{{ field.name }}</span>
<grip-icon></grip-icon> <span class="field-name">{{ field.name }}</span>
</div>
</draggable>
</div>
@ -104,6 +105,7 @@
<script>
import { mapActions, mapGetters } from 'vuex';
import GripIcon from '../other/grip-icon.vue';
import FilterEditionForm from './../edition/filter-edition-form.vue';
export default {
@ -124,11 +126,12 @@ export default {
allowedFilterTypes: [],
selectedFilterType: {},
choosenField: {},
newIndex: 0
newIndex: 0
}
},
components: {
FilterEditionForm
FilterEditionForm,
GripIcon
},
methods: {
...mapActions('filter', [
@ -271,7 +274,7 @@ export default {
this.openedFilterId = filter.id;
}
},
onEditionFinished() {
onEditionFinished() {
this.openedFilterId = '';
this.fetchFilters({collectionId: this.collectionId, isRepositoryLevel: this.isRepositoryLevel});
},
@ -380,12 +383,6 @@ export default {
display: initial;
}
.filter-selection-modal{
padding: 20px;
background-color: white;
border-radius: 3px;
}
.active-filter-item {
background-color: white;
padding: 0.8em;
@ -396,6 +393,11 @@ export default {
transition: top 0.1s ease;
cursor: grab;
.grip-icon {
fill: $gray;
top: 2px;
position: relative;
}
.filter-name {
text-overflow: ellipsis;
overflow-x: hidden;
@ -431,6 +433,12 @@ export default {
height: 1em;
width: 1em;
}
form {
padding: 1.0em 2.0em;
border-top: 1px solid $draggable-border-color;
border-bottom: 1px solid $draggable-border-color;
margin-top: 1.0em;
}
&.not-sortable-item, &.not-sortable-item:hover, &.not-focusable-item, &.not-focusable-item:hover {
box-shadow: none !important;
top: 0px !important;
@ -454,6 +462,10 @@ export default {
color: white !important;
top: -2px;
.grip-icon {
fill: $white;
}
.label-details, .icon {
color: white !important;
}
@ -519,6 +531,12 @@ export default {
border-radius: 1px;
transition: left 0.2s ease;
.grip-icon {
fill: $gray;
top: 2px;
position: relative;
}
.icon {
position: relative;
bottom: 3px;
@ -584,10 +602,10 @@ export default {
}
}
@keyframes hightlighten-icon {
0% { color: #b1b1b1; }
25% { color: white; }
75% { color: white; }
100% { color: #b1b1b1; }
0% { fill: #b1b1b1; }
25% { fill: white; }
75% { fill: white; }
100% { fill: #b1b1b1; }
}
@keyframes hightlighten-arrow {
0% {
@ -615,7 +633,7 @@ export default {
animation-duration: 1.0s;
animation-iteration-count: 2;
.icon{
.grip-icon{
animation-name: hightlighten-icon;
animation-duration: 1.0s;
animation-iteration-count: 2;
@ -641,8 +659,8 @@ export default {
&:before {
border-color: transparent $secondary transparent transparent;
}
.icon {
color: white !important;
.grip-icon {
fill: white !important;
}
}
}

View File

@ -0,0 +1,11 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 12.8 12.8" class="grip-icon"><circle cx="1.5" cy="1.5" r="1.5" class="undefined"/><circle cx="6.4" cy="1.5" r="1.5" class="undefined"/><circle cx="11.3" cy="1.5" r="1.5" class="undefined"/><circle cx="1.5" cy="6.4" r="1.5" class="undefined"/><circle cx="6.4" cy="6.4" r="1.5" class="undefined"/><circle cx="11.3" cy="6.4" r="1.5" class="undefined"/><circle cx="1.5" cy="11.3" r="1.5" class="undefined"/><circle cx="6.4" cy="11.3" r="1.5" class="undefined"/><circle cx="11.3" cy="11.3" r="1.5" class="undefined"/></svg>
</template>
<script>
export default {
name: 'GripIcon'
}
</script>

View File

@ -0,0 +1,11 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 12.8 12.8" class="grip-icon"><circle cx="1.5" cy="1.5" r="1.5" class="undefined"/><circle cx="6.4" cy="1.5" r="1.5" class="undefined"/><circle cx="11.3" cy="1.5" r="1.5" class="undefined"/><circle cx="1.5" cy="6.4" r="1.5" class="undefined"/><circle cx="6.4" cy="6.4" r="1.5" class="undefined"/><circle cx="11.3" cy="6.4" r="1.5" class="undefined"/><circle cx="1.5" cy="11.3" r="1.5" class="undefined"/><circle cx="6.4" cy="11.3" r="1.5" class="undefined"/><circle cx="11.3" cy="11.3" r="1.5" class="undefined"/></svg>
</template>
<script>
export default {
name: 'GripIcon'
}
</script>

View File

@ -23,6 +23,7 @@ return [
'export' => __('Export', 'tainacan'),
'cancel' => __('Cancel', 'tainacan'),
'save' => __('Save', 'tainacan'),
'next' => __('Next', 'tainacan'),
'see' => __('See', 'tainacan'),
'search' => __('Search', 'tainacan'),
'advanced_search' => __('Advanced Search', 'tainacan'),

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Camada_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="12.815px" height="12.815px" viewBox="0 0 12.815 12.815" enable-background="new 0 0 12.815 12.815" xml:space="preserve">
<g>
<circle cx="1.469" cy="1.469" r="1.469"/>
<circle cx="6.407" cy="1.469" r="1.469"/>
<circle cx="11.346" cy="1.469" r="1.469"/>
<circle cx="1.469" cy="6.407" r="1.469"/>
<circle cx="6.407" cy="6.407" r="1.469"/>
<circle cx="11.346" cy="6.407" r="1.469"/>
<circle cx="1.469" cy="11.346" r="1.469"/>
<circle cx="6.407" cy="11.346" r="1.469"/>
<circle cx="11.346" cy="11.346" r="1.469"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 915 B