Bug fixes and usability improvements on Add New Term component. Closes #129.

This commit is contained in:
Mateus Machado Luna 2018-09-14 10:10:41 -03:00
parent 74130c6bc0
commit 8f24756fd1
6 changed files with 201 additions and 58 deletions

View File

@ -936,7 +936,7 @@ export default {
position: absolute; position: absolute;
z-index: 99; z-index: 99;
right: 0; right: 0;
top: 70px; top: 148px;
max-width: 36px; max-width: 36px;
height: 36px; height: 36px;
width: 36px; width: 36px;

View File

@ -54,20 +54,27 @@
} }
.taginput-container { .taginput-container {
padding: 0 !important; padding: 0px !important;
background-color: white !important; background-color: white !important;
&:focus, &:active { &:focus, &:active {
border: none !important; border: none !important;
} }
.autocomplete .icon {
height: 2.2em !important;
}
.input { .input {
margin-bottom: 0px !important; margin-bottom: 0px !important;
height: 1.85rem !important; height: 1.85rem !important;
text-overflow: ellipsis;
} }
.input.has-selected, .input:focus, .input:active { .input.has-selected, .input:focus, .input:active {
background-color: white; background-color: white;
border: 1px solid $gray2 !important; border: 1px solid $gray2 !important;
} }
.tags {
margin: 0.17rem 0.25rem 0.08rem 0.25rem !important;
}
.tag { .tag {
background: white; background: white;
padding-right: 0; padding-right: 0;
@ -100,7 +107,7 @@
font-size: 0.75rem; font-size: 0.75rem;
.tags { .tags {
margin-right: 8px; margin: 4px 6px 0px 6px;
} }
.tag { .tag {
background: white; background: white;

View File

@ -191,7 +191,7 @@ return apply_filters( 'tainacan-admin-i18n', [
'label_collection_filters' => __( 'Collection Filters', 'tainacan' ), 'label_collection_filters' => __( 'Collection Filters', 'tainacan' ),
'label_parent_term' => __( 'Parent Term', 'tainacan' ), 'label_parent_term' => __( 'Parent Term', 'tainacan' ),
'label_children_terms' => __( 'children terms', 'tainacan' ), 'label_children_terms' => __( 'children terms', 'tainacan' ),
'label_new_term' => __( 'New Term', 'tainacan' ), 'label_new_term' => __( 'Create New Term', 'tainacan' ),
'label_new_child' => __( 'New Child', 'tainacan' ), 'label_new_child' => __( 'New Child', 'tainacan' ),
'label_taxonomy_terms' => __( 'Taxonomy Terms', 'tainacan' ), 'label_taxonomy_terms' => __( 'Taxonomy Terms', 'tainacan' ),
'label_no_parent_term' => __( 'No parent term', 'tainacan' ), 'label_no_parent_term' => __( 'No parent term', 'tainacan' ),
@ -339,6 +339,7 @@ return apply_filters( 'tainacan-admin-i18n', [
'instruction_select_collection_fetch_items' => __( 'Select a collection to fecth items', 'tainacan' ), 'instruction_select_collection_fetch_items' => __( 'Select a collection to fecth items', 'tainacan' ),
'instruction_select_a_action' => __( 'Select a action', 'tainacan' ), 'instruction_select_a_action' => __( 'Select a action', 'tainacan' ),
'instruction_parent_term' => __( 'Type to search a Parent Term to choose.', 'tainacan' ), 'instruction_parent_term' => __( 'Type to search a Parent Term to choose.', 'tainacan' ),
'instruction_type_existing_term' => __( 'Type to add an existing term...', 'tainacan' ),
// Info. Other feedback to user. // Info. Other feedback to user.
'info_search_results' => __( 'Search Results', 'tainacan' ), 'info_search_results' => __( 'Search Results', 'tainacan' ),

View File

@ -1,8 +1,8 @@
<template> <template>
<div> <div>
<span> <span v-if="!showForm">
<a <a
@click="showForm = !showForm" @click="toggleForm()"
class="is-inline add-link"> class="is-inline add-link">
<b-icon <b-icon
icon="plus-circle" icon="plus-circle"
@ -10,54 +10,121 @@
type="is-secondary"/> type="is-secondary"/>
&nbsp;{{ $i18n.get('label_new_term') }}</a> &nbsp;{{ $i18n.get('label_new_term') }}</a>
</span> </span>
<div> <transition name="appear">
<!-- <transition name="fade"> --> <section
v-if="showForm"
style="padding-left: 0px; margin-top: 12px; margin-bottom: -12px;">
<b-field
:addons="false"
:type="((formErrors.name !== '' || formErrors.repeated !== '') && (formErrors.name !== undefined || formErrors.repeated !== undefined )) ? 'is-danger' : ''"
:message="formErrors.name != undefined? formErrors : formErrors.repeated">
<label class="label is-inline">
{{ $i18n.get('label_name') }}
<span class="required-term-asterisk">*</span>
<help-button
:title="$i18n.get('label_name')"
:message="$i18n.get('info_help_term_name')"/>
</label>
<b-input
:class="{'has-content': name != undefined && name != ''}"
v-model="name"
@focus="clearErrors({ name: 'name', repeated: 'repeated' })"/>
</b-field>
<section <!-- <b-field :label="$i18n.get('label_parent_term')">
v-if="showForm" <b-select
style="padding-left: 0px;"> v-model="parent">
<option
:value="0"
selected> ---{{ $i18n.get('label_parent_term') }}--- </option>
<option
v-for="(option,index) in options"
:key="index"
:value="option.id"
v-html="setSpaces( option.level ) + option.name"/>
</b-select>
</b-field> -->
<!-- Parent -------------- -->
<b-field
:addons="false"
:type="((formErrors.parent !== '' || formErrors.repeated !== '') && (formErrors.parent !== undefined || formErrors.repeated !== undefined )) ? 'is-danger' : ''"
:message="formErrors.parent ? formErrors : formErrors.repeated">
<label class="label is-inline">
{{ $i18n.get('label_parent_term') }}
<b-switch
@input="onToggleSwitch()"
id="tainacan-checkbox-has-parent"
size="is-small"
v-model="hasParent" />
<help-button
:title="$i18n.get('label_parent_term')"
:message="$i18n.get('info_help_parent_term')"/>
</label>
<b-autocomplete
id="tainacan-text-cover-page"
:placeholder="$i18n.get('instruction_parent_term')"
:data="parentTerms"
field="name"
v-model="parentTermName"
@select="onSelectParentTerm($event)"
:loading="isFetchingParentTerms"
@input="fecthParentTerms($event)"
@focus="clearErrors('parent');"
:disabled="!hasParent">
<template slot-scope="props">
{{ props.option.name }}
</template>
<template slot="empty">{{ $i18n.get('info_no_parent_term_found') }}</template>
</b-autocomplete>
<transition name="fade">
<p
class="checkboxes-warning"
v-show="showCheckboxesWarning == true">
{{ $i18n.get('info_warning_changing_parent_term') }}
</p>
</transition>
</b-field>
<b-field :label="$i18n.get('label_name')"> <button
<b-input :class="{ 'is-loading': isAddingNewTerm }"
:class="{'has-content': name != undefined && name != ''}" class="button is-outlined"
v-model="name"/> @click="toggleForm()"
</b-field> type="button">
{{ $i18n.get('cancel') }}
</button>
<b-field :label="$i18n.get('label_parent_term')"> <button
<b-select :class="{ 'is-loading': isAddingNewTerm }"
v-model="parent"> class="button is-secondary"
<option @click="save"
:value="0" type="button">
selected> ---{{ $i18n.get('label_parent_term') }}--- </option> {{ $i18n.get('save') }}
<option </button>
v-for="(option,index) in options" </section>
:key="index"
:value="option.id"
v-html="setSpaces( option.level ) + option.name"/>
</b-select>
</b-field>
<a </transition>
class="button is-secondary"
@click="save">{{ $i18n.get('save') }}</a>
</section>
<!-- </transition> -->
</div>
</div> </div>
</template> </template>
<script> <script>
import { tainacan as axios } from '../../../js/axios/axios' import { tainacan as axios } from '../../../js/axios/axios'
import { mapActions } from 'vuex';
export default { export default {
data(){ data(){
return { return {
name: '', name: '',
parent: 0, parent: 0,
hasParent: false,
showForm: false, showForm: false,
metadatum_id: this.metadatum.metadatum.id parentTerms: [],
search: '',
parentTermName: '',
isAddingNewTerm: false,
isFetchingParentTerms: false,
metadatum_id: this.metadatum.metadatum.id,
formErrors: {}
} }
}, },
props: { props: {
@ -68,9 +135,25 @@
value:[ Array, Boolean, Number ], value:[ Array, Boolean, Number ],
options: { options: {
type: Array type: Array
} },
componentType: ''
}, },
methods: { methods: {
...mapActions('taxonomy', [
'fetchPossibleParentTerms'
]),
toggleForm() {
this.name = '';
this.parent = 0;
this.hasParent = false;
this.parentTerms = [];
this.search = '';
this.parentTermName = '';
this.isFetchingParentTerms = false;
this.isAddingNewTerm = false;
this.formErrors = {};
this.showForm = !this.showForm;
},
setSpaces( level ){ setSpaces( level ){
let result = ''; let result = '';
let space = '&nbsp;&nbsp;' let space = '&nbsp;&nbsp;'
@ -80,6 +163,39 @@
return result; return result;
}, },
fecthParentTerms(search) {
this.isFetchingParentTerms = true;
this.fetchPossibleParentTerms({
taxonomyId: this.taxonomy_id,
termId: 'new',
search: search })
.then((parentTerms) => {
this.parentTerms = parentTerms;
this.isFetchingParentTerms = false;
})
.catch((error) => {
this.$console.error(error);
this.isFetchingParentTerms = false;
});
},
onToggleSwitch() {
this.clearErrors('parent');
},
onSelectParentTerm(selectedParentTerm) {
this.parent = selectedParentTerm.id;
this.selectedParentTerm = selectedParentTerm;
this.parentTermName = selectedParentTerm.name;
},
clearErrors(attributes) {
if(attributes instanceof Object){
for(let attribute in attributes){
this.formErrors[attribute] = undefined;
}
} else {
this.formErrors[attributes] = undefined;
}
},
save(){ save(){
if( this.name.trim() === ''){ if( this.name.trim() === ''){
this.$toast.open({ this.$toast.open({
@ -89,15 +205,15 @@
type: 'is-danger' type: 'is-danger'
}) })
} else { } else {
const instance = this; this.isAddingNewTerm = true;
axios.post(`/taxonomy/${this.taxonomy_id}/terms?hideempty=0&order=asc`, { axios.post(`/taxonomy/${this.taxonomy_id}/terms?hideempty=0&order=asc`, {
name: this.name, name: this.name,
parent: this.parent parent: this.parent
}) })
.then( res => { .then( res => {
instance.name = '';
instance.parent = 0; this.isAddingNewTerm = false;
if( res.data && res.data.id || res.id ){ if( res.data && res.data.id || res.id ){
let id = ( res.id ) ? res.id : res.data.id; let id = ( res.id ) ? res.id : res.data.id;
@ -107,22 +223,37 @@
axios.patch(`/item/${this.item_id}/metadata/${this.metadatum_id}`, { axios.patch(`/item/${this.item_id}/metadata/${this.metadatum_id}`, {
values: id, values: id,
}).then(() => { }).then(() => {
instance.$emit('newTerm', id); this.$emit('newTerm', { values: id, taxonomyId: this.taxonomy_id, metadatumId: this.metadatum_id });
this.toggleForm();
}) })
} else { } else {
val = ( val ) ? val : []; val = ( val ) ? val : [];
val.push( id ); val.push( this.componentType == ('tainacan-taxonomy-checkbox' || 'tainacan-taxonomy-radio') ? id : {'label': this.name, 'value': id} );
axios.patch(`/item/${this.item_id}/metadata/${this.metadatum_id}`, { axios.patch(`/item/${this.item_id}/metadata/${this.metadatum_id}`, {
values: val, values: val,
}).then( () => { }).then(() => {
instance.$emit('newTerm', val); this.$emit('newTerm', { values: val, taxonomyId: this.taxonomy_id, metadatumId: this.metadatum_id });
this.toggleForm();
}) })
} }
} }
})
.catch((error) => {
let errors = { error_message: error['response']['data'].error_message, errors: error['response']['data'].errors };
for (let error of errors.errors) {
for (let metadatum of Object.keys(error)) {
this.$set(this.formErrors, metadatum, (this.formErrors[metadatum] !== undefined ? this.formErrors[metadatum] : '') + error[metadatum] + '\n');
}
}
this.isAddingNewTerm = false;
}); });
} }
} }
},
mounted() {
this.hasParent = this.parent != undefined && this.parent > 0;
} }
} }
</script> </script>

View File

@ -18,7 +18,8 @@
</a> </a>
<add-new-term <add-new-term
class="add-new-term" class="add-new-term"
v-if="getComponent !== 'tainacan-taxonomy-tag-input' && allowNew" v-if="allowNew"
:component-type="getComponent"
:taxonomy_id="taxonomy" :taxonomy_id="taxonomy"
:metadatum="metadatum" :metadatum="metadatum"
:item_id="metadatum.item.id" :item_id="metadatum.item.id"
@ -89,7 +90,7 @@
componentAttribute: { componentAttribute: {
type: String type: String
}, },
value: [ Number, String, Array,Object ], value: [ Number, String, Array, Object ],
id: '', id: '',
disabled: false, disabled: false,
forcedComponentType: '', forcedComponentType: '',
@ -171,12 +172,14 @@
this.$emit('input', this.inputValue); this.$emit('input', this.inputValue);
this.$emit('blur'); this.$emit('blur');
}, },
reload( val ){ reload( $event ) {
this.valueComponent = val; if ($event.taxonomyId == this.taxonomy && $event.metadatumId == this.metadatum.metadatum.id) {
this.valueComponent = $event.values;
this.terms = []; this.terms = [];
this.getTermsFromTaxonomy(); this.offset = 0;
this.getTermsId(); this.getTermsFromTaxonomy();
this.getTermsId();
}
} }
} }
} }

View File

@ -4,7 +4,7 @@
:disabled="disabled" :disabled="disabled"
size="is-small" size="is-small"
icon="magnify" icon="magnify"
:allow-new="allowNew" :allow-new="false"
:maxtags="maxtags" :maxtags="maxtags"
@add="emitAdd" @add="emitAdd"
@remove="emitRemove" @remove="emitRemove"
@ -13,14 +13,15 @@
field="label" field="label"
attached attached
ellipsis ellipsis
:placeholder="$i18n.get('instruction_type_existing_term')"
:loading="isFetching" :loading="isFetching"
:class="{'has-selected': selected != undefined && selected != []}" :class="{'has-selected': selected != undefined && selected != []}"
autocomplete autocomplete
@typing="autoCompleteTerm"/> @typing="autoCompleteTerm"/>
</div> </div>
</template> </template>
<script>
<script>
import { mapActions, mapGetters } from 'vuex'; import { mapActions, mapGetters } from 'vuex';
export default { export default {
@ -110,7 +111,7 @@
let val = this.selected; let val = this.selected;
let results = []; let results = [];
if(val.length > 0){ if (val.length > 0){
for( let term of val ){ for( let term of val ){
results.push( term.value ); results.push( term.value );
} }