Several improvements on Terms List refactoring.

This commit is contained in:
Mateus Machado Luna 2018-08-10 16:48:58 -03:00
parent a1ad3eeaf3
commit 8c912a0cc4
8 changed files with 248 additions and 148 deletions

View File

@ -35,7 +35,7 @@
class="button is-rounded is-secondary" class="button is-rounded is-secondary"
id="button-delete-header" id="button-delete-header"
:aria-label="$i18n.get('label_button_delete_thumb')" :aria-label="$i18n.get('label_button_delete_thumb')"
@click="deleteThumbnail()"> @click="deleteHeaderImage()">
<b-icon <b-icon
size="is-small" size="is-small"
icon="delete" /> icon="delete" />
@ -131,7 +131,7 @@
methods: { methods: {
...mapActions('taxonomy', [ ...mapActions('taxonomy', [
'sendTerm', 'sendTerm',
'updateTerm', 'updateChildTerm',
]), ]),
...mapGetters('taxonomy', [ ...mapGetters('taxonomy', [
'getTerms' 'getTerms'
@ -149,7 +149,7 @@
.then(() => { .then(() => {
this.editForm = {}; this.editForm = {};
this.formErrors = {}; this.formErrors = {};
this.$termsListBus.onTermEditionSaved(this.editForm); this.$emit('onEditionFinished');
}) })
.catch((errors) => { .catch((errors) => {
for (let error of errors.errors) { for (let error of errors.errors) {
@ -161,7 +161,7 @@
}); });
} else { } else {
this.updateTerm({ this.updateChildTerm({
taxonomyId: this.taxonomyId, taxonomyId: this.taxonomyId,
termId: this.editForm.id, termId: this.editForm.id,
name: this.editForm.name, name: this.editForm.name,
@ -172,7 +172,7 @@
.then(() => { .then(() => {
this.editForm.saved = true; this.editForm.saved = true;
this.formErrors = {}; this.formErrors = {};
this.$termsListBus.onTermEditionSaved(this.editForm); this.$emit('onEditionFinished', this.editForm);
}) })
.catch((errors) => { .catch((errors) => {
for (let error of errors.errors) { for (let error of errors.errors) {
@ -185,7 +185,7 @@
} }
}, },
cancelEdition() { cancelEdition() {
this.$termsListBus.onTermEditionCanceled(this.editForm); this.$emit('onEditionCanceled', this.editForm);
}, },
deleteHeaderImage() { deleteHeaderImage() {
this.editForm = Object.assign({}, this.editForm = Object.assign({},
@ -197,7 +197,6 @@
); );
}, },
initializeMediaFrames() { initializeMediaFrames() {
this.headerImageMediaFrame = new wpMediaFrames.headerImageControl( this.headerImageMediaFrame = new wpMediaFrames.headerImageControl(
'my-header-image-media-frame', { 'my-header-image-media-frame', {
button_labels: { button_labels: {
@ -226,7 +225,7 @@
} }
}, },
}, },
created() { mounted() {
this.initializeMediaFrames(); this.initializeMediaFrames();
} }
} }

View File

@ -1,5 +1,5 @@
<template> <template>
<div> <div style="width: 100%;">
<div <div
class="term-item" class="term-item"
:class="{ :class="{
@ -13,7 +13,7 @@
<span <span
class="term-name" class="term-name"
:class="{'is-danger': formWithErrors == term.id }"> :class="{'is-danger': formWithErrors == term.id }">
{{ term.saved && !term.opened ? term.name : getUnsavedTermName(term) }} {{ term.name }}
</span> </span>
<span <span
v-if="term.id != undefined" v-if="term.id != undefined"
@ -26,36 +26,35 @@
</span> </span>
<span <span
class="children-dropdown" class="children-dropdown"
:class="{'is-disabled': isEditingTerm}"
v-if="!isEditingTerm && term.total_children > 0" v-if="!isEditingTerm && term.total_children > 0"
@click.prevent="loadChildTerms(term.id, index)"> @click.prevent="loadChildTerms(term.id, index)">
<span class="icon"> <span class="icon">
<i <i
:class="{ :class="{
'mdi-menu-right': !term.hasLoadedChildren || (term.hasCollapsedChildren && term.hasLoadedChildren), 'mdi-menu-right': !showChildren,
'mdi-menu-down': (!term.hasCollapsedChildren && term.hasLoadedChildren) || (term.hasCollapsedChildren != undefined && term.hasCollapsedChildren) }" 'mdi-menu-down': showChildren }"
class="mdi mdi-24px"/> class="mdi mdi-24px"/>
</span> </span>
<span>{{ term.total_children + ' ' + $i18n.get('label_children_terms') }}</span> <span>{{ term.total_children + ' ' + $i18n.get('label_children_terms') }}</span>
</span> </span>
<span class="controls" > <span
<a class="controls"
@click="addNewChildTerm(term, index)" :class="{'is-disabled': isEditingTerm}">
:disabled="isEditingTerm"> <a @click="addNewChildTerm(term, index)">
<b-icon <b-icon
size="is-small" size="is-small"
icon="plus-circle"/> icon="plus-circle"/>
</a> </a>
<a <a
v-if="!isEditingTerm"
@click.prevent="editTerm()"> @click.prevent="editTerm()">
<b-icon <b-icon
type="is-secondary" size="is-small"
icon="pencil"/> icon="pencil"/>
</a> </a>
<a <a @click.prevent="tryToRemoveTerm()">
@click.prevent="tryToRemoveTerm(term)">
<b-icon <b-icon
type="is-secondary" size="is-small"
icon="delete"/> icon="delete"/>
</a> </a>
</span> </span>
@ -80,6 +79,7 @@
<script> <script>
import { mapActions, mapGetters } from 'vuex'; import { mapActions, mapGetters } from 'vuex';
import RecursiveTermsList from './recursive-terms-list.vue'; import RecursiveTermsList from './recursive-terms-list.vue';
import CustomDialog from '../other/custom-dialog.vue';
export default { export default {
name: 'RecursiveTermsList', name: 'RecursiveTermsList',
@ -102,36 +102,13 @@ export default {
}, },
methods: { methods: {
...mapActions('taxonomy', [ ...mapActions('taxonomy', [
'updateTerm', 'updateChildTerm',
'deleteTerm', 'deleteChildTerm',
'fetchChildTerms', 'fetchChildTerms',
'fetchTerms' 'fetchTerms'
]), ]),
addNewChildTerm(parent, parentIndex) { addNewChildTerm() {
if (this.isEditingTerm) { this.$termsListBus.onAddNewChildTerm(this.term.id);
let editingTermIndex = this.orderedTermsList.findIndex(anEditingTerm => anEditingTerm.opened == true);
if (editingTermIndex >= 0)
this.onTermEditionCanceled(this.orderedTermsList[editingTermIndex]);
}
let newTerm = {
taxonomyId: this.taxonomyId,
name: this.$i18n.get('label_term_without_name'),
description: '',
parent: parent.id,
id: 'new',
saved: false,
depth: parent.depth + 1
}
this.orderedTermsList.splice(parentIndex + 1, 0, newTerm);
this.editTerm(newTerm, parentIndex + 1);
},
getUnsavedTermName(term) {
// let originalIndex = this.termsList.findIndex(anOriginalTerm => anOriginalTerm.id == term.id);
// if (originalIndex >= 0)
// return this.termsList[originalIndex].name;
// else
return term.name;
}, },
loadChildTerms(parentId, parentIndex) { loadChildTerms(parentId, parentIndex) {
@ -167,6 +144,69 @@ export default {
// this.orderedTermsList.splice(index, 1, term); // this.orderedTermsList.splice(index, 1, term);
}, },
tryToRemoveTerm() {
// Checks if user is deleting a term with unsaved info.
if (this.term.id == 'new' || !this.term.saved) {
this.$modal.open({
parent: this,
component: CustomDialog,
props: {
icon: 'alert',
title: this.$i18n.get('label_warning'),
message: this.$i18n.get('info_warning_terms_not_saved'),
onConfirm: () => { this.removeTerm(); },
}
});
} else {
this.removeTerm();
}
},
removeTerm() {
this.$modal.open({
parent: this,
component: CustomDialog,
props: {
icon: 'alert',
title: this.$i18n.get('label_warning'),
message: this.$i18n.get('info_warning_selected_term_delete'),
onConfirm: () => {
// If all checks passed, term can be deleted
if (this.term.id == 'new') {
let index = this.orderedTermsList.findIndex(deletedTerm => deletedTerm.id == 'new');
if (index >= 0) {
this.orderedTermsList.splice(index, 1);
}
} else {
this.deleteChildTerm({taxonomyId: this.taxonomyId, termId: this.term.id, parent: this.term.parent })
.then(() => {})
.catch((error) => {
this.$console.log(error);
});
// // Updates parent IDs for orphans
// for (let orphanTerm of this.termsList) {
// if (orphanTerm.parent == this.term.id) {
// this.updateTerm({
// taxonomyId: this.taxonomyId,
// termId: orphanTerm.id,
// name: orphanTerm.name,
// description: orphanTerm.description,
// parent: this.term.parent
// })
// .catch((error) => {
// this.$console.log(error);
// });
// }
// }
}
},
}
});
}
}, },
created() { created() {
this.$termsListBus.$on('editTerm', (term) => { this.$termsListBus.$on('editTerm', (term) => {
@ -199,8 +239,9 @@ export default {
visibility: visible; visibility: visible;
opacity: 1; opacity: 1;
transition: display 0.3s, visibility 0.3s, opacity 0.3s; transition: display 0.3s, visibility 0.3s, opacity 0.3s;
width: 100%;
&:hover { &:first-child:hover {
background-color: $gray1 !important; background-color: $gray1 !important;
.controls { .controls {
visibility: visible; visibility: visible;
@ -253,23 +294,29 @@ export default {
.controls { .controls {
visibility: hidden; visibility: hidden;
opacity: 0.0; opacity: 0.0;
display: flex;
justify-content: space-between;
background-color: $gray2; background-color: $gray2;
padding: 0.4375rem 0.875rem; padding: 0.76rem 0.875rem;
a { a {
display: flex;
align-items: center;
margin: 0 0.375rem; margin: 0 0.375rem;
.icon { .icon {
bottom: 1px; bottom: 1px;
position: relative; position: relative;
i, i:before { font-size: 20px; } i, i:before { font-size: 20px; }
a {
margin-right: 8px;
} }
} }
} }
.controls.is-disabled a, .children-dropdown.is-disabled {
color: $gray4 !important;
cursor: not-allowed !important;
user-select: none;
} }
&.opened-term { &.opened-term:first-child {
cursor: default; cursor: default;
background-color: $blue1; background-color: $blue1;

View File

@ -6,7 +6,7 @@
<button <button
class="button is-secondary" class="button is-secondary"
type="button" type="button"
@click="addNewTerm()" @click="addNewTerm(0)"
:disabled="isEditingTerm"> :disabled="isEditingTerm">
{{ $i18n.get('label_new_term') }} {{ $i18n.get('label_new_term') }}
</button> </button>
@ -68,11 +68,11 @@
</div> </div>
<div <div
class="column is-4 edit-forms-list" class="column is-4 edit-forms-list"
v-show="isEditingTerm"> v-if="isEditingTerm">
<term-edition-form <term-edition-form
:style="{ 'top': termEditionFormTop + 'px'}" :style="{ 'top': termEditionFormTop + 'px'}"
:taxonomy-id="taxonomyId" :taxonomy-id="taxonomyId"
@onEditionFinished="onTermEditionFinished()" @onEditionFinished="onTermEditionFinished(editTerm)"
@onEditionCanceled="onTermEditionCanceled(editTerm)" @onEditionCanceled="onTermEditionCanceled(editTerm)"
@onErrorFound="formWithErrors = editTerm.id" @onErrorFound="formWithErrors = editTerm.id"
:edit-form="editTerm"/> :edit-form="editTerm"/>
@ -91,7 +91,7 @@
<button <button
id="button-create-term" id="button-create-term"
class="button is-secondary" class="button is-secondary"
@click="addNewTerm()"> @click="addNewTerm(0)">
{{ $i18n.get('label_new_term') }} {{ $i18n.get('label_new_term') }}
</button> </button>
</div> </div>
@ -103,8 +103,8 @@
<script> <script>
import { mapActions, mapGetters } from 'vuex'; import { mapActions, mapGetters } from 'vuex';
import TermEditionForm from '../edition/term-edition-form.vue'; import TermEditionForm from '../edition/term-edition-form.vue';
import CustomDialog from '../other/custom-dialog.vue';
import RecursiveTermsList from './recursive-terms-list.vue' import RecursiveTermsList from './recursive-terms-list.vue'
import t from 't';
export default { export default {
name: 'TermsList', name: 'TermsList',
@ -126,12 +126,21 @@ export default {
}, },
computed: { computed: {
termsList() { termsList() {
console.log("Computei")
return this.getTerms(); return this.getTerms();
} }
}, },
watch: { watch: {
termsList() { termsList: {
handler() {
console.log("Senti")
this.localTerms = JSON.parse(JSON.stringify(this.termsList)); this.localTerms = JSON.parse(JSON.stringify(this.termsList));
t.dfs(this.localTerms, [], term => {
term.opened = false;
term.saved = true
});
},
deep: true
}, },
taxonomyId() { taxonomyId() {
this.loadTerms(0); this.loadTerms(0);
@ -143,10 +152,10 @@ export default {
}, },
methods: { methods: {
...mapActions('taxonomy', [ ...mapActions('taxonomy', [
'updateTerm',
'deleteTerm', 'deleteTerm',
'fetchChildTerms', 'fetchChildTerms',
'fetchTerms' 'fetchTerms',
'clearTerms'
]), ]),
...mapGetters('taxonomy',[ ...mapGetters('taxonomy',[
'getTerms' 'getTerms'
@ -155,84 +164,36 @@ export default {
this.order = newOrder; this.order = newOrder;
this.loadTerms(0); this.loadTerms(0);
}, },
addNewTerm() { addNewTerm(parent) {
let newTerm = { let newTerm = {
taxonomyId: this.taxonomyId, taxonomyId: this.taxonomyId,
name: this.$i18n.get('label_term_without_name'), name: this.$i18n.get('label_term_without_name'),
description: '', description: '',
parent: 0, parent: parent,
id: 'new', id: 'new',
saved: false, saved: false,
depth: 0 opened: true
} }
this.localTerms.push(newTerm); if (parent == 0) {
this.editTerm(newTerm, this.orderedTermsList.length - 1); this.localTerms.unshift(newTerm);
},
tryToRemoveTerm(term) {
// Checks if user is deleting a term with unsaved info.
if (term.id == 'new' || !term.saved || term.opened) {
this.$modal.open({
parent: this,
component: CustomDialog,
props: {
icon: 'alert',
title: this.$i18n.get('label_warning'),
message: this.$i18n.get('info_warning_terms_not_saved'),
onConfirm: () => { this.removeTerm(term); },
}
});
} else { } else {
this.removeTerm(term); console.log(parent)
} for (let term of this.localTerms) {
let parentTerm = t.find(term, [], (node, par) => { return node.id == parent; });
if (parentTerm != undefined) {
if (parentTerm['children'] == undefined)
this.$set(parentTerm, 'children', []);
parentTerm['children'].unshift(newTerm);
}
console.log(parentTerm)
}
}
this.$termsListBus.onEditTerm(newTerm);
}, },
removeTerm(term) { onTermEditionFinished(term) {
this.$termsListBus.onTermEditionSaved(term);
this.$modal.open({
parent: this,
component: CustomDialog,
props: {
icon: 'alert',
title: this.$i18n.get('label_warning'),
message: this.$i18n.get('info_warning_selected_term_delete'),
onConfirm: () => {
// If all checks passed, term can be deleted
if (term.id == 'new') {
let index = this.orderedTermsList.findIndex(deletedTerm => deletedTerm.id == 'new');
if (index >= 0) {
this.orderedTermsList.splice(index, 1);
}
} else {
this.deleteTerm({taxonomyId: this.taxonomyId, termId: term.id})
.then(() => {
})
.catch((error) => {
this.$console.log(error);
});
// Updates parent IDs for orphans
for (let orphanTerm of this.termsList) {
if (orphanTerm.parent == term.id) {
this.updateTerm({
taxonomyId: this.taxonomyId,
termId: orphanTerm.id,
name: orphanTerm.name,
description: orphanTerm.description,
parent: term.parent
})
.catch((error) => {
this.$console.log(error);
});
}
}
}
},
}
});
}, },
onTermEditionCanceled(term) { onTermEditionCanceled(term) {
@ -245,10 +206,12 @@ export default {
if (term.id == 'new') if (term.id == 'new')
this.removeTerm(term); this.removeTerm(term);
} }
this.isEditingTerm = false; this.$termsListBus.onTermEditionCanceled(term);
}, },
loadTerms(parentId, parentIndex) { loadTerms(parentId, parentIndex) {
this.clearTerms();
this.isLoadingTerms = true; this.isLoadingTerms = true;
let search = (this.searchQuery != undefined && this.searchQuery != '') ? { searchterm: this.searchQuery } : ''; let search = (this.searchQuery != undefined && this.searchQuery != '') ? { searchterm: this.searchQuery } : '';
this.fetchChildTerms({ parentId: parentId, taxonomyId: this.taxonomyId, fetchOnly: '', search: search, all: '', order: this.order}) this.fetchChildTerms({ parentId: parentId, taxonomyId: this.taxonomyId, fetchOnly: '', search: search, all: '', order: this.order})
@ -276,7 +239,9 @@ export default {
this.$termsListBus.$on('termEditionCanceled', (term) => { this.$termsListBus.$on('termEditionCanceled', (term) => {
this.isEditingTerm = false; this.isEditingTerm = false;
this.editTerm = null; this.editTerm = null;
this.onTermEditionCanceled(); });
this.$termsListBus.$on('addNewChildTerm', (parentId) => {
this.addNewTerm(parentId);
}); });
} }

View File

@ -8,7 +8,6 @@ import Buefy from 'buefy';
import VTooltip from 'v-tooltip'; import VTooltip from 'v-tooltip';
import { VueHammer } from 'vue2-hammer'; import { VueHammer } from 'vue2-hammer';
import VueMasonry from 'vue-masonry-css'; import VueMasonry from 'vue-masonry-css';
import t from 't';
// Custom elements // Custom elements
import Text from '../../classes/metadata-types/text/Text.vue'; import Text from '../../classes/metadata-types/text/Text.vue';
@ -51,7 +50,6 @@ import VueTheMask from 'vue-the-mask';
// Configure and Register Plugins // Configure and Register Plugins
Vue.use(Buefy); Vue.use(Buefy);
Vue.use(VTooltip); Vue.use(VTooltip);
Vue.use(t);
Vue.use(VueHammer); Vue.use(VueHammer);
Vue.use(VueMasonry); Vue.use(VueMasonry);
Vue.use(I18NPlugin); Vue.use(I18NPlugin);

View File

@ -15,6 +15,9 @@ export default {
}, },
onTermEditionCanceled(term) { onTermEditionCanceled(term) {
this.$emit('termEditionCanceled', term); this.$emit('termEditionCanceled', term);
},
onAddNewChildTerm(parentId) {
this.$emit('addNewChildTerm', parentId);
} }
} }
}); });

View File

@ -158,6 +158,16 @@ export default {
components: { components: {
CollectionsList CollectionsList
}, },
computed: {
metadatum_mappers: {
get() {
return this.getMetadatumMappers();
}
},
collections() {
return this.getCollections();
}
},
methods: { methods: {
...mapActions('collection', [ ...mapActions('collection', [
'fetchCollections', 'fetchCollections',
@ -214,16 +224,6 @@ export default {
}); });
} }
}, },
computed: {
metadatum_mappers: {
get() {
return this.getMetadatumMappers();
}
},
collections() {
return this.getCollections();
}
},
created() { created() {
this.collectionsPerPage = this.$userPrefs.get('collections_per_page'); this.collectionsPerPage = this.$userPrefs.get('collections_per_page');
this.isLoadingMetadatumTypes = true; this.isLoadingMetadatumTypes = true;

View File

@ -200,6 +200,7 @@ export const fetchTerms = ({ commit }, {taxonomyId, fetchOnly, search, all, orde
}); });
}; };
// Hierarchy usage of terms list -----------------
export const fetchChildTerms = ({ commit }, { parentId, taxonomyId, fetchOnly, search, all, order }) => { export const fetchChildTerms = ({ commit }, { parentId, taxonomyId, fetchOnly, search, all, order }) => {
let query = ''; let query = '';
@ -230,3 +231,41 @@ export const fetchChildTerms = ({ commit }, { parentId, taxonomyId, fetchOnly, s
}); });
}); });
}; };
export const updateChildTerm = ({ commit }, { taxonomyId, termId, name, description, parent, headerImageId }) => {
return new Promise(( resolve, reject ) => {
axios.tainacan.patch(`/taxonomy/${taxonomyId}/terms/${termId}`, {
name: name,
description: description,
parent: parent,
header_image_id: headerImageId,
})
.then( res => {
let term = res.data;
commit('updateChildTerm', {term: term, parent: parent });
resolve( term );
})
.catch(error => {
reject({ error_message: error['response']['data'].error_message, errors: error['response']['data'].errors });
});
});
};
export const deleteChildTerm = ({ commit }, { taxonomyId, termId, parent }) => {
return new Promise(( resolve, reject ) => {
axios.tainacan.delete(`/taxonomy/${taxonomyId}/terms/${termId}?permanently=1`)
.then(res => {
let term = res.data;
commit('deleteChildTerm', { termId: termId, parent: parent });
resolve( term );
})
.catch(error => {
reject({ error_message: error['response']['data'].error_message, errors: error['response']['data'].errors });
});
});
};
export const clearTerms = ({ commit }) => {
commit('clearTerms');
};

View File

@ -37,6 +37,11 @@ export const setTerms = (state, terms) => {
state.terms = terms; state.terms = terms;
}; };
export const clearTerms = (state) => {
state.terms = [];
};
export const setChildTerms = (state, { terms, parent }) => { export const setChildTerms = (state, { terms, parent }) => {
if (parent > 0 ) { if (parent > 0 ) {
@ -47,7 +52,7 @@ export const setChildTerms = (state, { terms, parent }) => {
Vue.set(parentTerm, 'children', []); Vue.set(parentTerm, 'children', []);
for (let term of terms){ for (let term of terms){
parentTerm['children'].push(term); parentTerm['children'].unshift(term);
} }
} }
} }
@ -55,7 +60,7 @@ export const setChildTerms = (state, { terms, parent }) => {
if (state.terms != undefined) { if (state.terms != undefined) {
for (let term of terms) for (let term of terms)
state.terms.push(term); state.terms.unshift(term);
} else { } else {
state.terms = terms; state.terms = terms;
@ -63,6 +68,50 @@ export const setChildTerms = (state, { terms, parent }) => {
} }
}; };
export const updateChildTerm = (state, { term, parent }) => {
if (parent > 0 ) {
for (let aTerm of state.terms) {
let childTerm = t.find(aTerm, [], (node, par) => { return node.id == term; });
if (childTerm != undefined) {
childTerm = term;
}
}
} else {
if (state.terms != undefined) {
for (let i = 0; i < state.terms.length; i++) {
if (state.terms[i].id == term.id)
Vue.set(state.terms, i, term);
}
} else {
state.terms = []
state.terms.unshift(term);
}
}
};
export const deleteChildTerm = ( state, {termId, parent} ) => {
if (parent > 0 ) {
for (let aTerm of state.terms) {
let parentTerm = t.bfs(aTerm, [], (node, par) => { return node.id == parent; });
if (parentTerm != undefined) {
let index = parentTerm.children.findIndex(deletedTerm => deletedTerm.id == termId);
if (index >= 0) {
parentTerm.children.splice(index, 1);
}
}
}
} else {
if (state.terms != undefined) {
for (let i = 0; i < state.terms.length; i++) {
if (state.terms[i].id == termId)
state.terms.splice(i, 1);
}
}
}
};
export const deleteTerm = ( state, termId ) => { export const deleteTerm = ( state, termId ) => {
let index = state.terms.findIndex(deletedTerm => deletedTerm.id === termId); let index = state.terms.findIndex(deletedTerm => deletedTerm.id === termId);
if (index >= 0) { if (index >= 0) {