Solving small merge conflicts from develop.

This commit is contained in:
Mateus Machado Luna 2019-11-07 14:40:34 -03:00
commit 8fac7ae028
41 changed files with 1095 additions and 741 deletions

View File

@ -97,8 +97,6 @@
:maxtags="1"
:class="{'is-field-history': bulkEditionProcedures[criterion].isDone}"
:disabled="bulkEditionProcedures[criterion].isDone"
:id="getMetadataByID(bulkEditionProcedures[criterion].metadatumID).metadata_type_object.component +
'-' + getMetadataByID(bulkEditionProcedures[criterion].metadatumID).slug"
:is="getMetadataByID(bulkEditionProcedures[criterion].metadatumID).metadata_type_object.component"
:metadatum="{metadatum: getMetadataByID(bulkEditionProcedures[criterion].metadatumID)}"
class="tainacan-bulk-edition-field"
@ -152,8 +150,6 @@
:maxtags="1"
:class="{'is-field-history': bulkEditionProcedures[criterion].isDone}"
:disabled="bulkEditionProcedures[criterion].isDone || bulkEditionProcedures[criterion].isExecuting"
:id="getMetadataByID(bulkEditionProcedures[criterion].metadatumID).metadata_type_object.component +
'-' + getMetadataByID(bulkEditionProcedures[criterion].metadatumID).slug"
:is="getMetadataByID(bulkEditionProcedures[criterion].metadatumID).metadata_type_object.component"
:metadatum="{metadatum: getMetadataByID(bulkEditionProcedures[criterion].metadatumID)}"
class="tainacan-bulk-edition-field tainacan-bulk-edition-field-last"

View File

@ -132,8 +132,6 @@
:metadatum="{ metadatum: metadatum }"
:value="itemMetadata[index].value"
@input="clearErrorMessage(metadatum.id); bulkEdit($event, metadatum)"/>
<!-- :class="{'is-field-history': bulkEditionProcedures[criterion].isDone}"
:disabled="bulkEditionProcedures[criterion].isDone || bulkEditionProcedures[criterion].isExecuting" -->
</div>
</transition>
</b-field>

View File

@ -150,7 +150,7 @@
</b-field>
<b-field :addons="false">
<label class="label is-inline-block">{{ $i18n.get('label_options') }}</label>
<label class="label is-inline-block">{{ $i18n.get('label_insert_options') }}</label>
<b-field
:type="formErrors['required'] != undefined ? 'is-danger' : ''"
:message="formErrors['required'] != undefined ? formErrors['required'] : ''">

View File

@ -144,7 +144,7 @@
:message="$i18n.get('info_help_parent_term')"/>
</label>
<b-autocomplete
id="tainacan-text-cover-page"
id="tainacan-add-parent-field"
:placeholder="$i18n.get('instruction_parent_term')"
:data="parentTerms"
field="name"
@ -155,7 +155,18 @@
@focus="clearErrors('parent');"
:disabled="!hasParent">
<template slot-scope="props">
{{ props.option.name }}
<div class="media">
<div
v-if="props.option.header_image"
class="media-left">
<img
width="28"
:src="props.option.header_image">
</div>
<div class="media-content">
{{ props.option.name }}
</div>
</div>
</template>
<template slot="empty">{{ $i18n.get('info_no_parent_term_found') }}</template>
</b-autocomplete>

View File

@ -363,35 +363,35 @@
let selected = this.selected instanceof Array ? this.selected : [this.selected];
if (this.taxonomy_id && selected.length) {
for (const term of selected) {
this.isSelectedTermsLoading = true;
this.isSelectedTermsLoading = true;
axios.get(`/taxonomy/${this.taxonomy_id}/terms/${term}`)
.then((res) => {
this.saveSelectedTagName(res.data.id, res.data.name);
this.isSelectedTermsLoading = false;
})
.catch((error) => {
this.$console.log(error);
this.isSelectedTermsLoading = false;
});
}
axios.get(`/taxonomy/${this.taxonomy_id}/terms/?${qs.stringify({ hideempty: 0, include: selected})}`)
.then((res) => {
for (const term of res.data)
this.saveSelectedTagName(term.id, term.name);
this.isSelectedTermsLoading = false;
})
.catch((error) => {
this.$console.log(error);
this.isSelectedTermsLoading = false;
});
} else if (this.metadatum_type === 'Tainacan\\Metadata_Types\\Relationship' && selected.length) {
this.isSelectedTermsLoading = true;
for (const item of selected) {
axios.get(`/items/?${qs.stringify({ fetch_only: 'title', postin: selected})}`)
.then((res) => {
for (const item of res.data)
this.saveSelectedTagName(item.id, item.title);
axios.get('/items/' + item + '?fetch_only=title')
.then((res) => {
this.saveSelectedTagName(res.data.id, res.data.title);
this.isSelectedTermsLoading = false;
})
.catch((error) => {
this.$console.log(error);
this.isSelectedTermsLoading = false;
});
}
this.isSelectedTermsLoading = false;
})
.catch((error) => {
this.$console.log(error);
this.isSelectedTermsLoading = false;
});
}
},
saveSelectedTagName(value, label){

View File

@ -22,6 +22,7 @@ import Taxonomy from '../../classes/metadata-types/taxonomy/Taxonomy.vue';
import FormRelationship from '../../classes/metadata-types/relationship/FormRelationship.vue';
import FormTaxonomy from '../../classes/metadata-types/taxonomy/FormTaxonomy.vue';
import FormSelectbox from '../../classes/metadata-types/selectbox/FormSelectbox.vue';
import FormNumeric from '../../classes/metadata-types/numeric/FormNumeric.vue';
import FilterNumeric from '../../classes/filter-types/numeric/Numeric.vue';
import FilterDate from '../../classes/filter-types/date/Date.vue';
@ -31,12 +32,13 @@ import FilterCheckbox from '../../classes/filter-types/checkbox/Checkbox.vue';
import FilterTaginput from '../../classes/filter-types/taginput/Taginput.vue';
import FilterNumericInterval from '../../classes/filter-types/numeric-interval/NumericInterval.vue';
import FilterDateInterval from '../../classes/filter-types/date-interval/DateInterval.vue';
import FilterNumericListInterval from '../../classes/filter-types/numeric-list-interval/NumericListInterval.vue';
import FilterTaxonomyCheckbox from '../../classes/filter-types/taxonomy/Checkbox.vue';
import FilterTaxonomyTaginput from '../../classes/filter-types/taxonomy/Taginput.vue';
import FormNumeric from '../../classes/filter-types/numeric/FormNumeric.vue';
import FormNumericInterval from '../../classes/filter-types/numeric-interval/FormNumericInterval.vue';
import FormFilterNumeric from '../../classes/filter-types/numeric/FormNumeric.vue';
import FormFilterNumericInterval from '../../classes/filter-types/numeric-interval/FormNumericInterval.vue';
import FormFilterNumericListInterval from '../../classes/filter-types/numeric-list-interval/FormNumericListInterval.vue';
// import FormDate from '../../classes/filter-types/date/FormDate.vue';
import TainacanFormItem from '../../classes/metadata-types/tainacan-form-item.vue';
@ -52,10 +54,6 @@ import eventBusSearch from '../../js/event-bus-search';
import termsListBus from './terms-list-bus.js';
import { I18NPlugin, UserPrefsPlugin, RouterHelperPlugin, ConsolePlugin, UserCapabilitiesPlugin, StatusHelperPlugin } from './utilities';
import FilterNumericListInterval from '../../classes/filter-types/numeric-list-interval/NumericListInterval.vue';
import FormNumericListInterval from '../../classes/filter-types/numeric-list-interval/FormNumericListInterval.vue';
// Configure and Register Plugins
Vue.use(Buefy, {
defaultTooltipAnimated: true
@ -78,10 +76,12 @@ Vue.component('tainacan-numeric', Numeric);
Vue.component('tainacan-date', Date);
Vue.component('tainacan-relationship', Relationship);
Vue.component('tainacan-taxonomy', Taxonomy);
/* Metadata Option forms */
Vue.component('tainacan-form-relationship', FormRelationship);
Vue.component('tainacan-form-taxonomy', FormTaxonomy);
Vue.component('tainacan-form-selectbox', FormSelectbox);
Vue.component('tainacan-form-numeric', FormNumeric);
Vue.component('tainacan-form-item', TainacanFormItem);
Vue.component('tainacan-filter-item', TainacanFiltersList);
@ -99,9 +99,9 @@ Vue.component('tainacan-filter-numeric-list-interval', FilterNumericListInterval
Vue.component('tainacan-filter-date-interval', FilterDateInterval);
/* Filter Metadata Option forms */
Vue.component('tainacan-filter-form-numeric', FormNumeric);
Vue.component('tainacan-filter-form-numeric-interval', FormNumericInterval);
Vue.component('tainacan-filter-form-numeric-list-interval', FormNumericListInterval);
Vue.component('tainacan-filter-form-numeric', FormFilterNumeric);
Vue.component('tainacan-filter-form-numeric-interval', FormFilterNumericInterval);
Vue.component('tainacan-filter-form-numeric-list-interval', FormFilterNumericListInterval);
// Vue.component('tainacan-filter-form-date', FormDate);
/* Others */

View File

@ -78,6 +78,39 @@
</p>
</b-field>
<b-field
style="margin-left: auto"
class="header-item">
<div class="control has-icons-right is-small is-clearfix">
<b-autocomplete
:data="users"
:placeholder="$i18n.get('instruction_type_search_users_filter')"
:keep-first="keepFirst"
:open-on-focus="openOnFocus"
@typing="fetchUsersForFiltering"
@select="filterActivitiesByUser"
:loading="isFetchingUsers"
field="name"
icon="account">
<template slot-scope="props">
<div class="media">
<div
v-if="props.option.avatar_urls && props.option.avatar_urls['24']"
class="media-left">
<img
width="24"
:src="props.option.avatar_urls['24']">
</div>
<div class="media-content">
{{ props.option.name }}
</div>
</div>
</template>
<template slot="empty">{{ $i18n.get('info_no_user_found') }}</template>
</b-autocomplete>
</div>
</b-field>
<b-field class="header-item">
<div class="control has-icons-right is-small is-clearfix">
<input
@ -237,7 +270,10 @@
tab: '',
isItemLevel: false,
searchQuery: '',
searchDates: []
searchDates: [],
users: [],
isFetchingUsers: false,
userIdForFiltering: null
}
},
components: {
@ -248,7 +284,8 @@
...mapActions('activity', [
'fetchActivities',
'fetchCollectionActivities',
'fetchItemActivities'
'fetchItemActivities',
'fetchUsers'
]),
...mapGetters('activity', [
'getActivities'
@ -315,10 +352,11 @@
if(this.isRepositoryLevel) {
this.fetchActivities({
'page': this.activitiesPage,
'activitiesPerPage': this.activitiesPerPage,
'search': this.searchQuery,
'searchDates': [dataInit, dataEnd]
page: this.activitiesPage,
activitiesPerPage: this.activitiesPerPage,
search: this.searchQuery,
searchDates: [dataInit, dataEnd],
authorId: this.userIdForFiltering
})
.then((res) => {
this.isLoading = false;
@ -329,11 +367,12 @@
});
} else if (!this.isRepositoryLevel && !this.isItemLevel) {
this.fetchCollectionActivities({
'page': this.activitiesPage,
'activitiesPerPage': this.activitiesPerPage,
'collectionId': this.$route.params.collectionId,
'search': this.searchQuery,
'searchDates': [dataInit, dataEnd]
page: this.activitiesPage,
activitiesPerPage: this.activitiesPerPage,
collectionId: this.$route.params.collectionId,
search: this.searchQuery,
searchDates: [dataInit, dataEnd],
authorId: this.userIdForFiltering
})
.then((res) => {
this.isLoading = false;
@ -344,11 +383,12 @@
});
} else {
this.fetchItemActivities({
'page': this.activitiesPage,
'activitiesPerPage': this.activitiesPerPage,
'itemId': this.$route.params.itemId,
'search': this.searchQuery,
'searchDates': [dataInit, dataEnd]
page: this.activitiesPage,
activitiesPerPage: this.activitiesPerPage,
itemId: this.$route.params.itemId,
search: this.searchQuery,
searchDates: [dataInit, dataEnd],
authorId: this.userIdForFiltering
})
.then((res) => {
this.isLoading = false;
@ -391,6 +431,10 @@
this.searchDates = null;
this.searchActivities();
},
filterActivitiesByUser(user) {
this.userIdForFiltering = user != null && user.id != undefined ? user.id : null;
this.loadActivities();
},
dateFormatter(dateObject) {
if (dateObject == null || dateObject.length == 0 || dateObject[0] == null || dateObject[1] == null)
return "";
@ -401,7 +445,20 @@
moment(dateString[0], this.dateFormat).toDate(),
moment(dateString[1], this.dateFormat).toDate()
];
}
},
fetchUsersForFiltering: _.debounce(function (search) {
this.isFetchingUsers = true;
this.fetchUsers({ search: search })
.then((users) => {
this.users = users;
this.isFetchingUsers = false;
})
.catch((error) => {
this.$console.error(error);
this.isFetchingPages = false;
});
}, 500)
},
computed: {
activities(){

View File

@ -26,6 +26,7 @@
border-radius: 0px;
min-width: 6rem;
border: none;
z-index: 99;
.dropdown-content {
padding: 0px;
@ -50,18 +51,22 @@
.is-small { color: $gray4; }
&.is-active { background-color: $turquoise2; }
.media-left {
margin-right: 0.5rem;
}
.media-content {
display: flex;
width: 80%;
.media {
align-items: center;
.media-left {
margin-right: 0.5rem;
}
.media-content {
display: flex;
width: 80%;
.ellipsed-text {
overflow-x: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-right: 3px;
.ellipsed-text {
overflow-x: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-right: 3px;
}
}
}
}

View File

@ -51,6 +51,7 @@
}
.b-numberinput {
height: 30px;
padding: 0 !important;
.control {
margin-right: 0 !important;
@ -62,6 +63,7 @@
button,
input {
height: 30px !important;
text-align: start;
}
button.is-primary,
button.is-primary:hover,

View File

@ -121,7 +121,7 @@ $subheader-height: 42px;
$side-menu-width: 160px;
$filter-menu-width: 16.666666667%;
$filter-menu-width-theme: 20.833333333%;
$page-height: calc(100% - 94px);
$page-height: calc(100vh - 94px);
// Overall Pages padding:
$page-side-padding: 4.166666667%;//82px;

View File

@ -98,6 +98,7 @@ a:hover {
.add-link {
display: inline;
font-size: 0.75rem;
margin: 3px 0 6px 0;
&.disabled {
pointer-events: none;
cursor: default;

View File

@ -200,7 +200,9 @@ return apply_filters( 'tainacan-admin-i18n', [
'label_select_taxonomy_input_type' => __( 'Input type', 'tainacan' ),
'label_taxonomy_allow_new_terms' => __( 'Allow new terms', 'tainacan' ),
'label_selectbox_init' => __( 'Select', 'tainacan' ),
'label_options' => __( 'Insert options', 'tainacan' ),
'label_insert_options' => __( 'Insert options', 'tainacan'),
'label_available_terms' => __( 'Available terms', 'tainacan' ),
'label_some_available_terms' => __( 'Some available terms', 'tainacan' ),
'label_attachments' => __( 'Attachments', 'tainacan' ),
'label_attachment' => __( 'Attachment', 'tainacan' ),
'label_enabled' => __( 'Enabled', 'tainacan' ),
@ -213,6 +215,7 @@ return apply_filters( 'tainacan-admin-i18n', [
'label_parent_term' => __( 'Parent Term', 'tainacan' ),
'label_children_terms' => __( 'children terms', 'tainacan' ),
'label_new_term' => __( 'Create New Term', 'tainacan' ),
'label_create_and_select' => __( 'Create and Select', 'tainacan' ),
'label_new_child' => __( 'New Child', 'tainacan' ),
'label_taxonomy_terms' => __( 'Taxonomy Terms', 'tainacan' ),
'label_no_parent_term' => __( 'No parent term', 'tainacan' ),
@ -348,6 +351,7 @@ return apply_filters( 'tainacan-admin-i18n', [
'label_show_metadata' => __( 'Show metadata', 'tainacan' ),
'label_all_terms' => __( 'All terms', 'tainacan' ),
'label_selected_terms' => __( 'Selected terms', 'tainacan' ),
'label_selected_term' => __( 'Selected term', 'tainacan' ),
'label_all_metadatum_values' => __( 'All metadatum values', 'tainacan' ),
'label_selected_metadatum_values' => __( 'Selected metadatum values', 'tainacan' ),
'label_editing_item_number' => __( 'Editing item n.', 'tainacan' ),
@ -450,10 +454,12 @@ return apply_filters( 'tainacan-admin-i18n', [
'instruction_image_upload_box' => __( 'Drop an image here or click to upload.', 'tainacan' ),
'instruction_select_a_status' => __( 'Select a status:', 'tainacan' ),
'instruction_select_a_status2' => __( 'Select a status', 'tainacan' ),
'instruction_click_to_select_a_filter_type' => __( 'Click to select a filter type:', 'tainacan' ),
'instruction_click_to_select_a_filter_type' => __( 'Click to select a filter type:', 'tainacan' ),
'instruction_select_a_parent_term' => __( 'Select a parent term:', 'tainacan' ),
'instruction_select_a_metadatum' => __( 'Select a metadatum', 'tainacan' ),
'instruction_cover_page' => __( 'Type to search a Page to choose.', 'tainacan' ),
'instruction_moderators' => __( 'Type to search a User to add.', 'tainacan' ),
'instruction_type_search_users_filter' => __( 'Type to search users to filter...', 'tainacan' ),
'instruction_select_a_parent_collection' => __( 'Select a parent collection.', 'tainacan' ),
'instruction_select_collection_thumbnail' => __( 'Select a thumbnail image for collection', 'tainacan' ),
'instruction_select_item_thumbnail' => __( 'Select a thumbnail image for item', 'tainacan' ),
@ -578,6 +584,7 @@ return apply_filters( 'tainacan-admin-i18n', [
'info_no_role_associated_capability' => __( 'No role associated to this capability', 'tainacan' ),
'info_associated_roles' => __( 'These are the roles that have this capability set. You may add or remove the capability to customize the role.', 'tainacan' ),
'info_inherited_roles' => __( 'These are the roles that have greater capabilities, which inherit this one. You can not edit this as it will not have precendece over the greater capability.', 'tainacan' ),
'info_showing_terms' => __( 'Showing terms ', 'tainacan' ),
'info_warning_remove_from_trash_first' => __( 'Remove this item from trash first' ),
'info_to' => __( ' to ', 'tainacan' ),
'info_of' => __( ' of ', 'tainacan' ),

View File

@ -81,9 +81,9 @@ class Elastic_Press {
if ($item instanceof Entities\Item) {
$ids_meta = array_keys ($post_args['meta']);
\array_filter(function($n) {
\array_filter($ids_meta, function($n) {
if (is_numeric($n)) return intval($n);
}, $ids_meta);
});
$Tainacan_Metadata = \Tainacan\Repositories\Metadata::get_instance();
$Tainacan_Item_Metadata = \Tainacan\Repositories\Item_Metadata::get_instance();

View File

@ -20,7 +20,7 @@
<img
:alt="$i18n.get('label_thumbnail')"
width="24"
:src="`${props.option.img}`">
:src="props.option.img">
</div>
<div class="media-content">
<span class="ellipsed-text">{{ props.option.label }}</span>
@ -148,15 +148,4 @@
}
}
}
</script>
<style scoped>
#profileImage {
width: 32px;
height: 32px;
font-size: 2.1875rem;
color: #fff;
text-align: center;
line-height: 9.375rem;
margin: 20px 0;
}
</style>
</script>

View File

@ -276,13 +276,14 @@ export const dynamicFilterTypeMixin = {
sResults.push({
label: item.label,
value: item.value,
img: item.thumbnail && item.thumbnail['tainacan-small'] && item.thumbnail['tainacan-small'][0] ? item.thumbnail['tainacan-small'][0] : (item.img ? item.img : ''),
total_items: item.total_items
});
} else if (indexToIgnore < 0) {
opts.push({
label: item.label,
value: item.value,
img: (item.img ? item.img : this.thumbPlaceholderPath),
img: item.thumbnail && item.thumbnail['tainacan-small'] && item.thumbnail['tainacan-small'][0] ? item.thumbnail['tainacan-small'][0] : (item.img ? item.img : ''),
total_items: item.total_items
});
}
@ -291,14 +292,14 @@ export const dynamicFilterTypeMixin = {
sResults.push({
label: item.label,
value: item.value,
img: (item.img ? item.img : this.thumbPlaceholderPath),
img: item.thumbnail && item.thumbnail['tainacan-small'] && item.thumbnail['tainacan-small'][0] ? item.thumbnail['tainacan-small'][0] : (item.img ? item.img : ''),
total_items: item.total_items
});
} else {
opts.push({
label: item.label,
value: item.value,
img: (item.img ? item.img : this.thumbPlaceholderPath),
img: item.thumbnail && item.thumbnail['tainacan-small'] && item.thumbnail['tainacan-small'][0] ? item.thumbnail['tainacan-small'][0] : (item.img ? item.img : ''),
total_items: item.total_items
});
}

View File

@ -74,9 +74,7 @@
export default {
props: {
filter: Object,
value: [String, Number, Array],
disabled: false,
value: [String, Number, Array]
},
data() {
return {

View File

@ -157,7 +157,8 @@
let params = {
'include': metadata.terms,
'order': 'asc'
'order': 'asc',
'fetchonly': 0
};
return axios.get('/taxonomy/' + this.taxonomyId + '/terms/?' + qs.stringify(params) )

View File

@ -1,41 +1,34 @@
<template>
<div>
<div
:class="{'has-content': dateValue !== undefined && dateValue !== ''}"
class="control is-inline">
<input
:disabled="disabled"
class="input"
:class="{'is-danger': isInvalidDate && dateValue}"
type="text"
v-mask="dateMask"
v-model="dateValue"
@blur="onBlur"
@input="onInput"
:placeholder="dateFormat.toLowerCase()">
<p
v-if="isInvalidDate && dateValue"
class="has-text-danger is-italic is-size-7">{{ $i18n.get('info_error_invalid_date') }}</p>
<!--<b-collapse-->
<!--position="is-bottom-right">-->
<!--<span class="icon"-->
<!--icon="calendar-today"-->
<!--size="is-small"-->
<!--slot="trigger" />-->
<b-input
:id="metadatum.metadatum.metadata_type_object.component + '-' + metadatum.metadatum.slug"
:disabled="disabled"
class="input"
:class="{'is-danger': isInvalidDate && dateValue}"
type="text"
v-mask="dateMask"
v-model="dateValue"
@input.native="onInput"
:placeholder="dateFormat.toLowerCase()" />
<p
v-if="isInvalidDate && dateValue"
class="has-text-danger is-italic is-size-7">{{ $i18n.get('info_error_invalid_date') }}</p>
<!--<b-collapse-->
<!--position="is-bottom-right">-->
<!--<span class="icon"-->
<!--icon="calendar-today"-->
<!--size="is-small"-->
<!--slot="trigger" />-->
<!--<div class="field">-->
<!--<b-datepicker-->
<!--:class="{'has-content': dateValue !== undefined && dateValue !== ''}"-->
<!--:id="id"-->
<!--v-model="dateValue"-->
<!--@blur="onBlur"-->
<!--:readonly="false"-->
<!--inline-->
<!--@input="onInput($event)"-->
<!--:placeholder="datePlaceHolder"/>-->
<!--</div>-->
<!--</b-collapse>-->
</div>
<!--<div class="field">-->
<!--<b-datepicker-->
<!--v-model="dateValue"-->
<!--:readonly="false"-->
<!--inline-->
<!--@input="onInput($event)"-->
<!--:placeholder="datePlaceHolder"/>-->
<!--</div>-->
<!--</b-collapse>-->
</div>
</template>
@ -56,17 +49,11 @@
}
},
props: {
id: '',
metadatum: {
type: Object
},
metadatum: Object,
value: [String, Number, Array],
disabled: false,
},
methods: {
onBlur() {
this.$emit('blur');
},
onInput: _.debounce(function ($event) {
// Emty dates don't need to be validated, they remove the metadata
if ($event.target.value != '') {
@ -89,8 +76,14 @@
} else {
this.$emit('input', [null]);
}
this.$emit('blur');
}, 300)
}
}
</script>
<style scoped lang="scss">
.control {
padding-left: 0 !important;
padding-right: 0 !important;
}
</style>

View File

@ -0,0 +1,99 @@
<template>
<section>
<b-field :addons="false">
<label class="label is-inline">
{{ $i18n.getHelperTitle('tainacan-numeric', 'step') }}<span>&nbsp;*&nbsp;</span>
<help-button
:title="$i18n.getHelperTitle('tainacan-numeric', 'step')"
:message="$i18n.getHelperMessage('tainacan-numeric', 'step')"/>
</label>
<div
v-if="!showEditStepOptions"
class="is-flex">
<b-select
name="step_options"
v-model="step"
@input="onUpdateStep">
<option value="0.001">0.001</option>
<option value="0.01">0.01</option>
<option value="0.1">0.1</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="5">5</option>
<option value="10">10</option>
<option value="100">100</option>
<option value="1000">1000</option>
<option
v-if="step && ![0.001,0.01,0.1,1,2,5,10,100,1000].find( (element) => element == step )"
:value="step">
{{ step }}</option>
</b-select>
<button
class="button is-white is-pulled-right"
:aria-label="$i18n.get('edit')"
@click.prevent="showEditStepOptions = true">
<span
v-tooltip="{
content: $i18n.get('edit'),
autoHide: true,
placement: 'bottom'
}"
class="icon">
<i class="tainacan-icon tainacan-icon-18px tainacan-icon-edit has-text-secondary"/>
</span>
</button>
</div>
<div
v-if="showEditStepOptions"
class="is-flex">
<b-input
name="max_options"
v-model="step"
@input="onUpdateStep"
type="number"
step="1" />
<button
@click.prevent="showEditStepOptions = false"
class="button is-white is-pulled-right">
<span
v-tooltip="{
content: $i18n.get('close'),
autoHide: true,
placement: 'bottom'
}"
class="icon">
<i class="tainacan-icon tainacan-icon-18px tainacan-icon-close has-text-secondary"/>
</span>
</button>
</div>
</b-field>
</section>
</template>
<script>
export default {
props: {
value: [ String, Object, Array ]
},
data() {
return {
step: [Number, String],
showEditStepOptions: false
}
},
methods: {
onUpdateStep(value) {
this.$emit('input', { step: value });
}
},
created() {
this.step = this.value && this.value.step ? this.value.step : 0.01;
}
}
</script>
<style scoped>
section{
margin-bottom: 10px;
}
</style>

View File

@ -1,44 +1,32 @@
<template>
<b-input
:disabled="disabled"
:class="{'has-content': inputValue !== undefined && inputValue !== ''}"
:id="id"
lang="en"
:id="metadatum.metadatum.metadata_type_object.component + '-' + metadatum.metadatum.slug"
:value="value"
@input="onInput($event)"
type="number"
:value="inputValue"
step="0.01"
@blur="onBlur"
@change="onBlur"
@input="onInput($event)"/>
lang="en"
:step="getStep"/>
</template>
<script>
export default {
created(){
if( this.value ){
this.inputValue = this.value
}
},
data() {
return {
inputValue: ''
}
},
props: {
id: '',
metadatum: {
type: Object
},
metadatum: Object,
value: [String, Number, Array],
disabled: false,
},
computed: {
getStep() {
if (this.metadatum && this.metadatum.metadatum.metadata_type_options && this.metadatum.metadatum.metadata_type_options.step)
return this.metadatum.metadatum.metadata_type_options.step;
else
return 0.01;
}
},
methods: {
onBlur() {
this.$emit('blur');
},
onInput($event) {
this.inputValue = $event;
this.$emit('input', this.inputValue);
onInput(value) {
this.$emit('input', value);
}
}
}

View File

@ -12,9 +12,10 @@ class Numeric extends Metadata_Type {
function __construct(){
// call metadatum type constructor
parent::__construct();
$this->set_name( __('Numeric', 'tainacan') );
$this->set_primitive_type('float');
$this->set_component('tainacan-numeric');
$this->set_name( __('Numeric', 'tainacan') );
$this->set_form_component('tainacan-form-numeric');
$this->set_description( __('A numeric value, integer or float', 'tainacan') );
$this->set_preview_template('
<div>
@ -25,6 +26,18 @@ class Numeric extends Metadata_Type {
');
}
/**
* @inheritdoc
*/
public function get_form_labels(){
return [
'step' => [
'title' => __( 'Step', 'tainacan' ),
'description' => __( 'The amount to be increased or decreased when clicking on filter control buttons.', 'tainacan' ),
]
];
}
/**
* @param $itemMetadata \Tainacan\Entities\Item_Metadata_Entity The instace of the entity itemMetadata
* @return string

View File

@ -3,17 +3,41 @@
<b-taginput
expanded
:disabled="disabled"
:id="id"
v-model="selected"
:id="metadatum.metadatum.metadata_type_object.component + '-' + metadatum.metadatum.slug"
:value="selected"
size="is-small"
icon="magnify"
@input="onInput"
:data="options"
:maxtags="maxtags != undefined ? maxtags : (metadatum.metadatum.multiple == 'yes' || allowNew === true ? 100 : 1)"
autocomplete
attached
:loading="loading"
:placeholder="$i18n.get('instruction_type_existing_term')"
:loading="isLoading"
:aria-close-label="$i18n.get('remove_value')"
:class="{'has-selected': selected != undefined && selected != []}"
field="label"
@typing="search"/>
@typing="(query) => { options = []; search(query); }">
<template slot-scope="props">
<div class="media">
<div
v-if="props.option.img"
class="media-left">
<img
width="28"
:src="props.option.img">
</div>
<div class="media-content">
{{ props.option.label }}
</div>
</div>
</template>
<template
v-if="!isLoading"
slot="empty">
{{ $i18n.get('info_no_item_found') }}
</template>
</b-taginput>
</div>
</template>
@ -22,17 +46,20 @@
import qs from 'qs';
export default {
created(){
let collectionId = ( this.metadatum && this.metadatum.metadatum.metadata_type_options.collection_id ) ? this.metadatum.metadatum.metadata_type_options.collection_id : this.collection_id;
if ( this.metadatum.value && (Array.isArray( this.metadatum.value ) ? this.metadatum.value.length > 0 : true )){
created() {
this.collectionId = ( this.metadatum && this.metadatum.metadatum.metadata_type_options && this.metadatum.metadatum.metadata_type_options.collection_id ) ? this.metadatum.metadatum.metadata_type_options.collection_id : '';
if (this.metadatum.value && (Array.isArray( this.metadatum.value ) ? this.metadatum.value.length > 0 : true )) {
let query = qs.stringify({ postin: ( Array.isArray( this.metadatum.value ) ) ? this.metadatum.value : [ this.metadatum.value ] });
query += this.metadatum.metadatum.metadata_type_options.search ? '&fetch_only_meta=' + this.metadatum.metadatum.metadata_type_options.search : '';
axios.get('/collection/'+collectionId+'/items?' + query + '&nopaging=1&fetch_only=title,thumbnail')
axios.get('/collection/' + this.collectionId + '/items?' + query + '&nopaging=1&fetch_only=title,thumbnail')
.then( res => {
if (res.data.items) {
for (let item of res.data.items) {
this.selected.push({ label: this.getItemLabel(item), value: item.id, img: item.thumbnail && item.thumbnail['tainacan-small'] && item.thumbnail['tainacan-small'][0] ? item.thumbnail['tainacan-small'][0] : '' });
}
for (let item of res.data.items)
this.selected.push({
label: this.getItemLabel(item),
value: item.id,
img: item.thumbnail && item.thumbnail['tainacan-small'] && item.thumbnail['tainacan-small'][0] ? item.thumbnail['tainacan-small'][0] : ''
});
}
})
.catch(error => {
@ -40,100 +67,78 @@
});
}
},
data(){
data() {
return {
results:'',
selected:[],
options: [],
loading: false,
collectionId: 0,
isLoading: false,
collectionId: '',
inputValue: null,
queryObject: {},
itemsFound: []
}
},
props: {
metadatum: {
type: Object
},
collection_id: {
type: Number
},
id: '',
metadatum: Object,
maxtags: undefined,
disabled: false,
allowNew: true,
},
watch: {
selected( value ){
this.selected = value;
let values = [];
if( this.selected.length > 0 ){
for(let val of this.selected){
values.push( val.value );
}
}
this.onInput( values );
}
},
methods: {
setResults(option){
if(!option)
return;
this.results = option.value;
},
onInput( $event ) {
this.$emit('input', $event);
this.$emit('blur');
onInput(newSelected) {
this.selected = newSelected;
this.$emit('input', newSelected.map((item) => item.value));
},
search: _.debounce(function(query) {
if ( this.selected.length > 0 && this.metadatum.metadatum.multiple === 'no')
return '';
if (query !== '') {
this.loading = true;
this.options = [];
let metaquery = this.mountQuery( query );
let collectionId = ( this.metadatum && this.metadatum.metadatum.metadata_type_options.collection_id ) ? this.metadatum.metadatum.metadata_type_options.collection_id : this.collection_id;
axios.get('/collection/'+collectionId+'/items?' + qs.stringify( metaquery ))
.then( res => {
this.loading = false;
this.options = [];
let result = res.data;
this.isLoading = true;
if (result.items) {
for (let item of result.items) {
this.options.push({ label: this.getItemLabel(item), value: item.id })
}
axios.get('/collection/' + this.collectionId + '/items?' + this.getQueryString(query))
.then( res => {
this.isLoading = false;
this.options = [];
if (res.data.items) {
for (let item of res.data.items)
this.options.push({
label: this.getItemLabel(item),
value: item.id,
img: item.thumbnail && item.thumbnail['tainacan-small'] && item.thumbnail['tainacan-small'][0] ? item.thumbnail['tainacan-small'][0] : ''
})
}
})
.catch(error => {
this.$console.log(error);
});
} else {
this.options = [];
}
}, 500),
getItemLabel(item) {
let label = '';
for (let m in item.metadata) {
if (item.metadata[m].id == this.metadatum.metadatum.metadata_type_options.search) {
if (item.metadata[m].id == this.metadatum.metadatum.metadata_type_options.search)
label = item.metadata[m].value_as_string;
}
}
if (label != '' && label != item.title && item.title != '') {
if (label != '' && label != item.title && item.title != '')
label += ' (' + item.title + ')';
} else if (label == '') {
else if (label == '')
label = item.title;
}
return label;
},
mountQuery( search ) {
getQueryString( search ) {
let query = [];
if ( this.metadatum.metadatum.metadata_type_options &&
if (this.metadatum.metadatum.metadata_type_options &&
this.metadatum.metadatum.metadata_type_options.search)
{
query['metaquery'] = [];
@ -150,7 +155,7 @@
query['fetch_only'] = 'title,thumbnail';
query['fetch_only_meta'] = this.metadatum.metadatum.metadata_type_options.search;
return query;
return qs.stringify(query);
}
}
}

View File

@ -1,44 +1,33 @@
<template>
<div>
<b-select
expanded
:disabled="disabled"
:id = "id"
:placeholder="$i18n.get('label_selectbox_init')"
:value="value"
:class="{'is-empty': value == undefined || value == ''}"
@blur="$emit('blur')"
@input="onChecked($event)">
<option
v-for="(option, index) in getOptions"
:key="index"
:label="option"
:value="option"
border>{{ option }}</option>
</b-select>
</div>
<b-select
expanded
:disabled="disabled"
:id="metadatum.metadatum.metadata_type_object.component + '-' + metadatum.metadatum.slug"
:placeholder="$i18n.get('label_selectbox_init')"
:value="value"
@input="onSelected($event)">
<option value="">{{ $i18n.get('label_selectbox_init') }}...</option>
<option
v-for="(option, index) in getOptions"
:key="index"
:label="option"
:value="option">
{{ option }}
</option>
</b-select>
</template>
<script>
export default {
props: {
metadatum: {
type: Object
},
options: {
type: String
},
metadatum: Object,
value: [String, Number, Array],
id: '',
disabled: false,
},
computed: {
getOptions(){
if ( this.options && this.options !== '' ){
return this.options.split("\n");
}
else if ( this.metadatum && this.metadatum.metadatum.metadata_type_options.options ) {
if (this.metadatum && this.metadatum.metadatum.metadata_type_options && this.metadatum.metadatum.metadata_type_options.options ) {
const metadata = this.metadatum.metadatum.metadata_type_options.options;
return ( metadata ) ? metadata.split("\n") : [];
}
@ -46,7 +35,7 @@
}
},
methods: {
onChecked(value) {
onSelected(value) {
this.$emit('input', value);
},
}

View File

@ -27,8 +27,12 @@
<span
v-if="metadatum.metadatum.required == 'yes'"
class="required-metadatum-asterisk"
:class="metadatumTypeMessage">*</span>
<span class="metadata-type">({{ metadatum.metadatum.metadata_type_object.name }})</span>
:class="metadatumTypeMessage">
*
</span>
<span class="metadata-type">
({{ metadatum.metadatum.metadata_type_object.name }})
</span>
<help-button
:title="metadatum.metadatum.name"
:message="metadatum.metadatum.description"/>
@ -38,43 +42,45 @@
v-show="isCollapsed || metadatumTypeMessage == 'is-danger'"
v-if="isTextInputComponent( metadatum.metadatum.metadata_type_object.component )">
<component
:id="metadatum.metadatum.metadata_type_object.component + '-' + metadatum.metadatum.slug"
:is="metadatum.metadatum.metadata_type_object.component"
v-model="inputs[0]"
:metadatum="metadatum"
@input="emitIsChangingValue()"/>
<div v-if="metadatum.metadatum.multiple == 'yes'">
<div
v-if="index > 0"
v-for="(input, index) in inputs"
:key="index"
@input="changeValue()"/>
<template v-if="metadatum.metadatum.multiple == 'yes'">
<transition-group
name="filter-item"
class="multiple-inputs">
<component
:id="metadatum.metadatum.metadata_type_object.component + '-' + metadatum.metadatum.slug"
:is="metadatum.metadatum.metadata_type_object.component"
v-model="inputs[index]"
:metadatum="metadatum"
@input="emitIsChangingValue()"/>
<a
v-if="index > 0"
@click="removeInput(index)"
class="is-inline add-link">
<b-icon
icon="minus-circle"
size="is-small"
type="is-secondary"/>
&nbsp;{{ $i18n.get('label_remove_value') }}</a>
</div>
<template
v-if="index > 0"
v-for="(input, index) in inputs">
<component
:key="index"
:is="metadatum.metadatum.metadata_type_object.component"
v-model="inputs[index]"
:metadatum="metadatum"
@input="changeValue()"/>
<a
v-if="index > 0"
@click="removeInput(index)"
class="is-inline add-link"
:key="index">
<b-icon
icon="minus-circle"
size="is-small"
type="is-secondary"/>
&nbsp;{{ $i18n.get('label_remove_value') }}
</a>
</template>
</transition-group>
<a
@click="addInput"
class="is-inline add-link">
class="is-block add-link">
<span class="icon is-small">
<i class="tainacan-icon has-text-secondary tainacan-icon-add"/>
</span>
&nbsp;{{ $i18n.get('label_add_value') }}
</a>
</div>
</template>
</div>
</transition>
<transition name="filter-item">
@ -82,11 +88,10 @@
v-show="isCollapsed"
v-if="!isTextInputComponent( metadatum.metadatum.metadata_type_object.component )">
<component
:id="metadatum.metadatum.metadata_type_object.component + '-' + metadatum.metadatum.slug"
:is="metadatum.metadatum.metadata_type_object.component"
v-model="inputs"
:metadatum="metadatum"
@input="emitIsChangingValue()"/>
@input="changeValue()"/>
</div>
</transition>
</b-field>
@ -103,8 +108,7 @@
},
data(){
return {
inputs: [],
metadatumTypeMessage: ''
inputs: []
}
},
computed: {
@ -113,79 +117,70 @@
let errors = eventBus.getErrors(this.metadatum.metadatum.id);
if (errors) {
this.setMetadatumTypeMessage('is-danger');
for (let error of errors) {
for (let index of Object.keys(error)) {
// this.$console.log(index);
for (let index of Object.keys(error))
errorMessage += error[index] + '\n';
}
}
} else {
this.setMetadatumTypeMessage('');
}
return errorMessage;
},
metadatumTypeMessage() {
return this.getErrorMessage ? 'is-danger' : ''
}
},
created(){
this.getValue();
this.createInputs();
},
methods: {
emitIsChangingValue() {
this.changeValue();
},
changeValue: _.debounce(function() {
if (this.metadatum.value != this.inputs) {
if (this.inputs.length > 0 && this.inputs[0].value) {
let terms = this.inputs.map(term => term.value)
if (this.metadatum.value instanceof Array){
let equal = [];
for (let meta of terms) {
let foundIndex = this.metadatum.value.findIndex(element => meta == element.id);
if (foundIndex >= 0)
equal.push(this.metadatum.value[foundIndex]);
}
if (equal.length == terms.length && this.metadatum.value.length <= equal.length)
return;
}
} else if (this.metadatum.value.constructor.name == 'Object') {
if (this.metadatum.value.id == this.inputs)
return;
} else if (this.metadatum.value instanceof Array) {
if (this.inputs.length > 0 && this.inputs[0] && this.inputs[0].value) {
let terms = this.inputs.map(term => term.value)
if (this.metadatum.value instanceof Array){
let equal = [];
for (let meta of this.inputs) {
for (let meta of terms) {
let foundIndex = this.metadatum.value.findIndex(element => meta == element.id);
if (foundIndex >= 0)
equal.push(this.metadatum.value[foundIndex]);
}
if (equal.length == this.inputs.length && this.metadatum.value.length <= equal.length)
if (equal.length == terms.length && this.metadatum.value.length <= equal.length)
return;
}
eventBus.$emit('input', { item_id: this.metadatum.item.id, metadatum_id: this.metadatum.metadatum.id, values: this.inputs } );
}
}, 1000),
getValue(){
if (this.metadatum.value instanceof Array) {
}
} else if (this.metadatum.value.constructor.name == 'Object') {
if (this.metadatum.value.id == this.inputs)
return;
} else if (this.metadatum.value instanceof Array) {
let equal = [];
for (let meta of this.inputs) {
let foundIndex = this.metadatum.value.findIndex(element => meta == element.id);
if (foundIndex >= 0)
equal.push(this.metadatum.value[foundIndex]);
}
if (equal.length == this.inputs.length && this.metadatum.value.length <= equal.length)
return;
}
eventBus.$emit('input', {
itemId: this.metadatum.item.id,
metadatumId: this.metadatum.metadatum.id,
values: this.inputs
} );
}, 900),
createInputs(){
if (this.metadatum.value instanceof Array)
this.inputs = this.metadatum.value.slice(0);
if (this.inputs.length === 0)
this.inputs.push('');
} else {
this.metadatum.value == null || this.metadatum.value == undefined ? this.inputs.push('') : this.inputs.push(this.metadatum.value);
}
else
this.metadatum.value == null || this.metadatum.value == undefined ? this.inputs = [] : this.inputs.push(this.metadatum.value);
},
addInput(){
this.inputs.push('');
@ -195,12 +190,9 @@
this.inputs.splice(index, 1);
this.changeValue();
},
isTextInputComponent(component){
let array = ['tainacan-relationship','tainacan-taxonomy'];
return !( array.indexOf( component ) >= 0 );
},
setMetadatumTypeMessage(message){
this.metadatumTypeMessage = message;
isTextInputComponent(component) {
const array = ['tainacan-relationship','tainacan-taxonomy'];
return !(array.indexOf(component) >= 0 );
}
}
}

View File

@ -1,5 +1,5 @@
<template>
<div>
<div class="add-new-term">
<span v-if="!showForm">
<a
@click="toggleForm()"
@ -10,10 +10,10 @@
&nbsp;{{ $i18n.get('label_new_term') }}
</a>
</span>
<transition name="appear">
<transition name="filter-item">
<section
v-if="showForm"
style="padding-left: 0px; margin-top: 12px; margin-bottom: -12px;">
class="add-new-term-form">
<b-field
:addons="false"
:type="((formErrors.name !== '' || formErrors.repeated !== '') && (formErrors.name !== undefined || formErrors.repeated !== undefined )) ? 'is-danger' : ''"
@ -25,26 +25,12 @@
:title="$i18n.get('label_name')"
:message="$i18n.get('info_help_term_name')"/>
</label>
<b-input
:class="{'has-content': name != undefined && name != ''}"
<b-input
:placeholder="$i18n.get('label_term_without_name')"
v-model="name"
@focus="clearErrors({ name: 'name', repeated: 'repeated' })"/>
</b-field>
<!-- <b-field :label="$i18n.get('label_parent_term')">
<b-select
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"
@ -62,7 +48,7 @@
:message="$i18n.get('info_help_parent_term')"/>
</label>
<b-autocomplete
id="tainacan-text-cover-page"
id="tainacan-add-parent-field"
:placeholder="$i18n.get('instruction_parent_term')"
:data="parentTerms"
field="name"
@ -85,22 +71,22 @@
</p>
</transition>
</b-field>
<button
:class="{ 'is-loading': isAddingNewTerm }"
class="button is-outlined"
@click="toggleForm()"
type="button">
{{ $i18n.get('cancel') }}
</button>
<button
:class="{ 'is-loading': isAddingNewTerm }"
class="button is-secondary"
@click="save"
type="button">
{{ $i18n.get('save') }}
</button>
<div class="field is-grouped form-submit">
<button
:class="{ 'is-loading': isAddingNewTerm }"
class="button is-outlined"
@click="toggleForm()"
type="button">
{{ $i18n.get('cancel') }}
</button>
<button
:class="{ 'is-loading': isAddingNewTerm }"
class="button is-secondary"
@click="save"
type="button">
{{ $i18n.get('label_create_and_select') }}
</button>
</div>
</section>
</transition>
@ -122,19 +108,15 @@
parentTermName: '',
isAddingNewTerm: false,
isFetchingParentTerms: false,
metadatum_id: this.metadatum.metadatum.id,
metadatumId: this.metadatum.metadatum.id,
itemId: this.metadatum.item.id,
formErrors: {}
}
},
props: {
id: String,
item_id: [Number,String],
metadatum: [Number,String],
taxonomy_id: [Number,String],
value:[ Array, Boolean, Number ],
options: {
type: Array
},
taxonomyId: [Number,String],
value: [ Array, Boolean, Number ],
componentType: ''
},
methods: {
@ -153,20 +135,11 @@
this.formErrors = {};
this.showForm = !this.showForm;
},
setSpaces( level ){
let result = '';
let space = '&nbsp;&nbsp;'
for(let i = 0;i < level; i++)
result += space;
return result;
},
fecthParentTerms(search) {
this.isFetchingParentTerms = true;
this.fetchPossibleParentTerms({
taxonomyId: this.taxonomy_id,
taxonomyId: this.taxonomyId,
termId: 'new',
search: search })
.then((parentTerms) => {
@ -187,16 +160,15 @@
this.parentTermName = selectedParentTerm.name;
},
clearErrors(attributes) {
if(attributes instanceof Object){
for(let attribute in attributes){
if (attributes instanceof Object) {
for(let attribute in attributes)
this.formErrors[attribute] = undefined;
}
} else {
this.formErrors[attributes] = undefined;
}
},
save(){
if( this.name.trim() === ''){
save() {
if ( this.name.trim() === '') {
this.$buefy.toast.open({
duration: 2000,
message: this.$i18n.get('info_name_is_required'),
@ -206,32 +178,32 @@
} else {
this.isAddingNewTerm = true;
axios.post(`/taxonomy/${this.taxonomy_id}/terms?hideempty=0&order=asc`, {
axios.post(`/taxonomy/${this.taxonomyId}/terms?hideempty=0&order=asc`, {
name: this.name,
parent: this.parent
})
.then( res => {
.then(res => {
this.isAddingNewTerm = false;
if( res.data && res.data.id || res.id ){
let id = ( res.id ) ? res.id : res.data.id;
if (res.data && res.data.id || res.id) {
let id = res.id ? res.id : res.data.id;
let val = this.value;
if( !Array.isArray( val ) && this.metadatum.metadatum.multiple === 'no' ){
axios.patch(`/item/${this.item_id}/metadata/${this.metadatum_id}`, {
if (!Array.isArray(val) && this.metadatum.metadatum.multiple === 'no') {
axios.patch(`/item/${this.itemId}/metadata/${this.metadatumId}`, {
values: id,
}).then(() => {
this.$emit('newTerm', { values: id, taxonomyId: this.taxonomy_id, metadatumId: this.metadatum_id });
this.$emit('newTerm', { values: id, taxonomyId: this.taxonomyId, metadatumId: this.metadatumId });
this.toggleForm();
})
} else {
val = ( val ) ? val : [];
val = val ? val : [];
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.itemId}/metadata/${this.metadatumId}`, {
values: val,
}).then(() => {
this.$emit('newTerm', { values: val, taxonomyId: this.taxonomy_id, metadatumId: this.metadatum_id });
this.$emit('newTerm', { values: val, taxonomyId: this.taxonomyId, metadatumId: this.metadatumId });
this.toggleForm();
})
}
@ -256,5 +228,17 @@
}
}
</script>
<style scoped>
.add-new-term {
margin-top: 15px;
margin-bottom: 25px;
font-size: 0.75rem;
}
.add-new-term-form {
padding: 14px 24px;
margin-top: 12px;
margin-bottom: -12px;
border: 1px solid #cbcbcb;
}
</style>

View File

@ -7,53 +7,33 @@
v-model="valueComponent"
:allow-select-to-create="allowSelectToCreate"
:allow-new="allowNew"
:terms="terms"
:taxonomy-id="taxonomy_id"
:options="getOptions(0)"/>
<a
class="add-new-term"
v-if="(getComponent == 'tainacan-taxonomy-checkbox' || getComponent == 'tainacan-taxonomy-radio') &&
terms.length < totalTerms"
@click="openCheckboxModal()">
{{ $i18n.get('label_view_all') }}
</a>
:taxonomy-id="taxonomyId"
:metadatum="metadatum.metadatum"/>
<add-new-term
class="add-new-term"
v-if="allowNew"
:component-type="getComponent"
:taxonomy_id="taxonomy_id"
:taxonomy-id="taxonomyId"
:metadatum="metadatum"
:item_id="metadatum.item.id"
:value="valueComponent"
:options="getOptions(0)"
@newTerm="reload"/>
</div>
</template>
<script>
import { tainacan as axios } from '../../../js/axios/axios'
import TainacanTaxonomyRadio from './TaxonomyRadio.vue'
import TainacanTaxonomyCheckbox from './TaxonomyCheckbox.vue'
import TainacanTaxonomyTagInput from './TaxonomyTaginput.vue'
import AddNewTerm from './AddNewTerm.vue'
import CheckboxRadioModal from '../../../admin/components/other/checkbox-radio-modal.vue'
export default {
created(){
let metadata_type_options = this.metadatum.metadatum.metadata_type_options;
this.component = ( metadata_type_options && metadata_type_options.input_type )
? this.metadatum.metadatum.metadata_type_options.input_type : this.componentAttribute;
const metadata_type_options = this.metadatum.metadatum.metadata_type_options;
this.collectionId = this.metadatum.metadatum.collection_id;
this.taxonomy_id = metadata_type_options.taxonomy_id;
this.taxonomyId = metadata_type_options.taxonomy_id;
this.taxonomy = metadata_type_options.taxonomy;
if (metadata_type_options && metadata_type_options.allow_new_terms && this.metadatum.item)
this.allowNew = metadata_type_options.allow_new_terms == 'yes';
// This condition is temporary, used by bulk edition modal
if (this.component != 'tainacan-taxonomy-tag-input' || this.forcedComponentType != 'tainacan-taxonomy-tag-input')
this.getTermsFromTaxonomy();
this.getTermsId();
},
components: {
@ -65,32 +45,20 @@
data(){
return {
valueComponent: null,
component: '',
collectionId: '',
taxonomy_id: '',
taxonomyId: '',
taxonomy: '',
terms:[], // object with names
totalTerms: 0,
allowNew: false,
offset: 0,
termsNumber: 12
terms:[],
allowNew: false
}
},
watch: {
valueComponent( val ){
this.$emit('input', val);
this.$emit('blur');
}
},
props: {
metadatum: {
type: Object
},
componentAttribute: {
type: String
},
metadatum: Object,
value: [ Number, String, Array, Object ],
id: '',
disabled: false,
forcedComponentType: '',
maxtags: '',
@ -98,123 +66,36 @@
},
computed: {
getComponent() {
if (this.forcedComponentType){
if (this.forcedComponentType)
return this.forcedComponentType;
} else if( this.metadatum.metadatum
&& this.metadatum.metadatum.metadata_type_options && this.metadatum.metadatum.metadata_type_options.input_type ){
else if(this.metadatum.metadatum &&
this.metadatum.metadatum.metadata_type_options &&
this.metadatum.metadatum.metadata_type_options.input_type
)
return this.metadatum.metadatum.metadata_type_options.input_type;
}
}
},
methods: {
openCheckboxModal(){
this.$buefy.modal.open({
parent: this,
component: CheckboxRadioModal,
props: {
isFilter: false,
parent: 0,
taxonomy_id: this.taxonomy_id,
selected: !this.valueComponent ? [] : this.valueComponent,
metadatumId: this.metadatum.metadatum.id,
taxonomy: this.taxonomy,
collectionId: this.collectionId,
isTaxonomy: true,
query: '',
metadatum: this.metadatum.metadatum,
isCheckbox: this.getComponent == 'tainacan-taxonomy-checkbox'
},
events: {
input: (selected) => {
this.valueComponent = selected;
}
},
width: 'calc(100% - 8.333333333%)',
trapFocus: true
});
},
getTermsFromTaxonomy(){
let endpoint = '/taxonomy/' + this.taxonomy_id + '/terms?hideempty=0&order=asc';
if (this.getComponent == 'tainacan-taxonomy-checkbox' || this.getComponent == 'tainacan-taxonomy-radio')
endpoint = endpoint + '&number=' + this.termsNumber + '&offset=' + this.offset;
axios.get(endpoint)
.then( res => {
if (this.getComponent == 'tainacan-taxonomy-checkbox' || this.getComponent == 'tainacan-taxonomy-radio') {
this.totalTerms = Number(res.headers['x-wp-total']);
this.offset += this.termsNumber;
}
for (let item of res.data) {
this.terms.push( item );
}
})
.catch(error => {
this.$console.log(error);
});
},
getOptions( parent, level = 0 ){ // retrieve only ids
let result = [];
if ( this.terms ){
for( let term of this.terms ){
if( term.parent == parent ){
term['level'] = level;
result.push( term );
const levelTerm = level + 1;
const children = this.getOptions( term.id, levelTerm);
result = result.concat( children );
}
}
}
return result;
},
getTermsId(){
let values = [];
if( this.value && this.value.length > 0){
for( let term of this.value ){
if( term && term.id)
values.push(term.id);
}
}
if( values.length > 0 && this.metadatum.metadatum && this.component != 'tainacan-taxonomy-tag-input'){
this.valueComponent = ( this.metadatum.metadatum && this.metadatum.metadatum.multiple === 'no' ) ? values[0] : values;
} else if(values.length > 0 && this.metadatum.metadatum && this.component == 'tainacan-taxonomy-tag-input') {
let values = [];
for(let term of this.value){
values.push({label: term.name, value: term.id});
}
getTermsId() {
let values = [];
if (this.value && this.metadatum.metadatum && this.getComponent != 'tainacan-taxonomy-tag-input') {
values = this.value.map(term => term.id)
this.valueComponent = (values.length >= 0 && this.metadatum.metadatum && this.metadatum.metadatum.multiple === 'no') ? values[0] : values;
} else if (this.value && this.metadatum.metadatum && this.getComponent == 'tainacan-taxonomy-tag-input') {
values = this.value.map((term) => { return { label: term.name, value: term.id } });
this.valueComponent = values;
}
}
},
onInput($event) {
this.inputValue = $event;
this.valueComponent = $event;
this.$emit('input', this.inputValue);
this.$emit('blur');
this.$emit('input', this.valueComponent);
},
reload( $event ) {
if ($event.taxonomyId == this.taxonomy_id && $event.metadatumId == this.metadatum.metadatum.id) {
reload($event) {
if ($event.taxonomyId == this.taxonomyId && $event.metadatumId == this.metadatum.metadatum.id) {
this.valueComponent = $event.values;
this.terms = [];
this.offset = 0;
this.getTermsFromTaxonomy();
this.getTermsId();
this.$emit('update-taxonomy-inputs', $event)
}
}
}
}
</script>
<style scoped>
.add-new-term{
margin-top: 15px;
margin-bottom: 30px;
font-size: 0.75rem;
}
</style>

View File

@ -3,7 +3,7 @@
<p
v-if="value instanceof Array ? value.length > 0 : (value != undefined && value != '')"
class="has-text-gray">
{{ $i18n.get('label_selected_terms') + ' :' }}
{{ $i18n.get('label_selected_terms') + ':' }}
</p>
<b-field
v-if="value instanceof Array ? value.length > 0 : (value != undefined && value != '')"
@ -24,97 +24,187 @@
v-if="isSelectedTermsLoading"
class="control has-icons-right is-loading is-clearfix" />
</b-field>
<div
v-for="(option, index) in options"
:key="index">
<b-checkbox
:disabled="disabled"
:id="id"
:style="{ paddingLeft: (option.level * 30) + 'px' }"
:key="index"
v-model="checked"
@input="onChecked(option)"
:native-value="option.id"
border>
{{ option.name }}
</b-checkbox>
<br>
<p
style="margin-top: 10px;"
class="has-text-gray">
{{ (isShowingAllTerms ? $i18n.get('label_available_terms') : $i18n.get('label_some_available_terms')) + ':' }}
</p>
<div
class="metadata-taxonomy-list"
:id="metadatum.metadata_type_object.component + '-' + metadatum.slug">
<template v-for="(option, index) in options">
<b-checkbox
:key="index"
:disabled="disabled"
:style="{ paddingLeft: (option.level * 30) + 'px' }"
v-model="checked"
@input="onChecked(option)"
:native-value="option.id"
border>
{{ option.name }}
</b-checkbox>
<br :key="index">
</template>
</div>
<div
v-if="!isShowingAllTerms"
class="view-all">
<span>
{{
$i18n.get('info_showing_terms') + 1 +
$i18n.get('info_to') + options.length +
$i18n.get('info_of') + totalTerms + '. '
}}
</span>
<a @click="openCheckboxModal()">
{{ $i18n.get('label_view_all') + ' ' + totalTerms + '.' }}
</a>
</div>
</div>
</template>
<script>
import { tainacan as axios } from '../../../js/axios/axios';
import qs from 'qs';
import CheckboxRadioModal from '../../../admin/components/other/checkbox-radio-modal.vue'
export default {
created(){
if( this.value && this.value.length > 0)
created() {
if (this.value && this.value.length > 0)
this.checked = this.value;
this.getTermsFromTaxonomy();
this.$parent.$on('update-taxonomy-inputs', ($event) => {
if ($event.taxonomyId == this.taxonomyId && $event.metadatumId == this.metadatum.metadatum.id) {
this.offset = 0;
this.getTermsFromTaxonomy();
}
});
},
data(){
data() {
return {
checked: [],
selectedTagsName: {},
isSelectedTermsLoading: false,
options: [],
terms: [],
termsNumber: 12,
offset: 0,
totalTerms: 0
}
},
watch: {
value( val ){
value(val){
this.checked = val;
this.fetchSelectedLabels();
}
},
computed: {
isShowingAllTerms() {
return this.terms.length >= this.totalTerms;
}
},
props: {
options: {
type: Array
},
value: [ Number, String, Array ],
disabled: false,
taxonomyId: Number
taxonomyId: Number,
metadatum: Object
},
methods: {
onChecked() {
this.$emit('blur');
this.onInput(this.checked);
},
onInput($event) {
this.inputValue = $event;
this.$emit('input', this.inputValue);
this.value = $event;
this.$emit('input', this.value);
},
fetchSelectedLabels() {
if (this.value != null && this.value != undefined) {
this.isSelectedTermsLoading = true;
let selected = this.value instanceof Array ? this.value : [this.value];
const selected = this.value instanceof Array ? this.value : [this.value];
if (this.taxonomyId && selected.length > 0) {
for (const term of selected) {
if (this.taxonomyId) {
this.isSelectedTermsLoading = true;
if(!this.isSelectedTermsLoading){
this.isSelectedTermsLoading = true;
}
axios.get(`/taxonomy/${this.taxonomyId}/terms/?${qs.stringify({ hideempty: 0, include: selected })}`)
.then((res) => {
let terms = res.data;
axios.get(`/taxonomy/${this.taxonomyId}/terms/${term}`)
.then((res) => {
this.saveSelectedTagName(res.data.id, res.data.name);
this.isSelectedTermsLoading = false;
})
.catch((error) => {
this.$console.log(error);
this.isSelectedTermsLoading = false;
});
}
} else {
this.isSelectedTermsLoading = false;
for (let term of terms) {
if (!this.selectedTagsName[term.id])
this.$set(this.selectedTagsName, term.id, term.name);
}
this.isSelectedTermsLoading = false;
})
.catch((error) => {
this.$console.log(error);
this.isSelectedTermsLoading = false;
});
}
}
},
saveSelectedTagName(value, label){
if(!this.selectedTagsName[value]) {
this.$set(this.selectedTagsName, `${value}`, label);
getTermsFromTaxonomy() {
this.terms = [];
const endpoint = '/taxonomy/' + this.taxonomyId + '/terms?hideempty=0&order=asc&number=' + this.termsNumber + '&offset=' + this.offset;
axios.get(endpoint)
.then( res => {
this.totalTerms = Number(res.headers['x-wp-total']);
this.offset += this.termsNumber;
for (let item of res.data)
this.terms.push( item );
this.options = this.getOptions(0);
})
.catch(error => {
this.$console.log(error);
});
},
getOptions(parent, level = 0) { // retrieve only ids
let result = [];
if (this.terms) {
for (let term of this.terms){
if (term.parent == parent){
term['level'] = level;
result.push(term);
const levelTerm = level + 1;
const children = this.getOptions( term.id, levelTerm);
result = result.concat(children);
}
}
}
return result;
},
openCheckboxModal() {
this.$buefy.modal.open({
parent: this,
component: CheckboxRadioModal,
props: {
isFilter: false,
parent: 0,
taxonomy_id: this.taxonomyId,
selected: !this.value ? [] : this.value,
metadatumId: this.metadatum.id,
taxonomy: this.taxonomy,
collectionId: this.metadatum.collection_id,
isTaxonomy: true,
query: '',
metadatum: this.metadatum,
isCheckbox: true
},
events: {
input: (selected) => {
this.value = selected;
this.$emit('input', this.value);
}
},
width: 'calc(100% - 8.333333333%)',
trapFocus: true
});
}
},
mounted() {
@ -123,7 +213,7 @@
}
</script>
<style>
<style scoped lang="scss">
.selected-tags {
margin-top: 0.75rem;
font-size: 0.75rem;
@ -138,4 +228,18 @@
border-right-color: #dbdbdb !important;
border-top-color: #dbdbdb !important;
}
.metadata-taxonomy-list {
column-count: 2;
margin: 10px;
label {
break-inside: avoid;
padding-right: 10px;
}
}
.view-all {
color: #898d8f;
margin-bottom: 20px;
font-size: 0.75rem;
}
</style>

View File

@ -3,7 +3,7 @@
<p
v-if="value instanceof Array ? value.length > 0 : (value != undefined && value != '')"
class="has-text-gray">
{{ $i18n.get('label_selected_terms') + ' :' }}
{{ $i18n.get('label_selected_term') + ':' }}
</p>
<b-field
v-if="value instanceof Array ? value.length > 0 : (value != undefined && value != '')"
@ -24,43 +24,79 @@
v-if="isSelectedTermsLoading"
class="control has-icons-right is-loading is-clearfix" />
</b-field>
<b-radio
:disabled="disabled"
:id="id"
v-model="checked"
@input="onChecked()"
:native-value="''"
border>
{{ $i18n.get('clear_radio') }}
</b-radio>
<div
v-for="(option, index) in options"
:key="index">
<p
style="margin-top: 10px;"
class="has-text-gray">
{{ (isShowingAllTerms ? $i18n.get('label_available_terms') : $i18n.get('label_some_available_terms')) + ':' }}
</p>
<div class="metadata-taxonomy-list">
<b-radio
:disabled="disabled"
:id="id"
:style="{ paddingLeft: (option.level * 30) + 'px' }"
:key="index"
:id="metadatum.metadata_type_object.component + '-' + metadatum.slug"
v-model="checked"
@input="onChecked(option)"
:native-value="option.id"
@input="onChecked()"
:native-value="''"
border>
{{ option.name }}
{{ $i18n.get('clear_radio') }}
</b-radio>
<br>
<template
:id="metadatum.metadata_type_object.component + '-' + metadatum.slug"
v-for="(option, index) in options">
<b-radio
:disabled="disabled"
:style="{ marginLeft: 0, paddingLeft: (option.level * 30) + 'px' }"
:key="index"
v-model="checked"
@input="onChecked(option)"
:native-value="option.id"
border>
{{ option.name }}
</b-radio>
<br :key="index">
</template>
</div>
<div
v-if="!isShowingAllTerms"
class="view-all">
<span>
{{
$i18n.get('info_showing_terms') + 1 +
$i18n.get('info_to') + options.length +
$i18n.get('info_of') + totalTerms + '. '
}}
</span>
<a @click="openCheckboxModal()">
{{ $i18n.get('label_view_all') + ' ' + totalTerms + '.' }}
</a>
</div>
</div>
</template>
<script>
import { tainacan as axios } from '../../../js/axios/axios';
import qs from 'qs';
import CheckboxRadioModal from '../../../admin/components/other/checkbox-radio-modal.vue'
export default {
data(){
created() {
this.getTermsFromTaxonomy();
this.$parent.$on('update-taxonomy-inputs', ($event) => {
if ($event.taxonomyId == this.taxonomyId && $event.metadatumId == this.metadatum.metadatum.id) {
this.offset = 0;
this.getTermsFromTaxonomy();
}
});
},
data() {
return {
checked: ( this.value ) ? this.value : '',
checked: this.value ? this.value : '',
selectedTagsName: {},
isSelectedTermsLoading: false,
options: [],
terms: [],
termsNumber: 12,
offset: 0,
totalTerms: 0
}
},
watch: {
@ -69,60 +105,147 @@
this.fetchSelectedLabels();
}
},
computed: {
isShowingAllTerms() {
return this.terms.length >= this.totalTerms;
}
},
props: {
options: {
type: Array
},
value: [ Number, String, Array ],
disabled: false,
taxonomyId: Number
taxonomyId: Number,
metadatum: Object
},
methods: {
onChecked() {
this.$emit('blur');
this.onInput(this.checked)
},
onInput($event) {
this.inputValue = $event;
this.$emit('input', this.inputValue);
this.value = $event;
this.$emit('input', this.value);
},
fetchSelectedLabels() {
if (this.value != null && this.value != undefined) {
this.isSelectedTermsLoading = true;
let selected = this.value instanceof Array ? this.value : [this.value];
const selected = this.value instanceof Array ? this.value : [this.value];
if (this.taxonomyId && selected.length > 0) {
for (const term of selected) {
this.isSelectedTermsLoading = true;
if(!this.isSelectedTermsLoading){
this.isSelectedTermsLoading = true;
}
axios.get(`/taxonomy/${this.taxonomyId}/terms/?${qs.stringify({ hideempty: 0, include: selected })}`)
.then((res) => {
let terms = res.data;
axios.get(`/taxonomy/${this.taxonomyId}/terms/${term}`)
.then((res) => {
this.saveSelectedTagName(res.data.id, res.data.name);
this.isSelectedTermsLoading = false;
})
.catch((error) => {
this.$console.log(error);
this.isSelectedTermsLoading = false;
});
}
} else {
this.isSelectedTermsLoading = false;
for (let term of terms) {
if (!this.selectedTagsName[term.id])
this.$set(this.selectedTagsName, term.id, term.name);
}
this.isSelectedTermsLoading = false;
})
.catch((error) => {
this.$console.log(error);
this.isSelectedTermsLoading = false;
});
}
}
},
saveSelectedTagName(value, label){
if(!this.selectedTagsName[value]) {
this.$set(this.selectedTagsName, `${value}`, label);
getTermsFromTaxonomy() {
this.terms = [];
const endpoint = '/taxonomy/' + this.taxonomyId + '/terms?hideempty=0&order=asc&number=' + this.termsNumber + '&offset=' + this.offset;
axios.get(endpoint)
.then( res => {
this.totalTerms = Number(res.headers['x-wp-total']);
this.offset += this.termsNumber;
for (let item of res.data)
this.terms.push( item );
this.options = this.getOptions(0);
})
.catch(error => {
this.$console.log(error);
});
},
getOptions(parent, level = 0) { // retrieve only ids
let result = [];
if (this.terms) {
for (let term of this.terms){
if (term.parent == parent){
term['level'] = level;
result.push(term);
const levelTerm = level + 1;
const children = this.getOptions( term.id, levelTerm);
result = result.concat(children);
}
}
}
return result;
},
openCheckboxModal() {
this.$buefy.modal.open({
parent: this,
component: CheckboxRadioModal,
props: {
isFilter: false,
parent: 0,
taxonomy_id: this.taxonomyId,
selected: !this.value ? [] : this.value,
metadatumId: this.metadatum.metadatum.id,
taxonomy: this.taxonomy,
collectionId: this.metadatum.collection_id,
isTaxonomy: true,
query: '',
metadatum: this.metadatum.metadatum,
isCheckbox: false
},
events: {
input: (selected) => {
this.value = selected;
this.$emit('input', this.value);
}
},
width: 'calc(100% - 8.333333333%)',
trapFocus: true
});
}
},
mounted() {
this.fetchSelectedLabels();
}
}
</script>
</script>
<style lang="scss" scoped>
.selected-tags {
margin-top: 0.75rem;
font-size: 0.75rem;
position: relative;
}
.selected-tags .is-loading {
margin-left: 2rem;
margin-top: -0.4rem;
}
.selected-tags .is-loading::after {
border: 2px solid #555758 !important;
border-right-color: #dbdbdb !important;
border-top-color: #dbdbdb !important;
}
.metadata-taxonomy-list {
column-count: 2;
margin: 10px;
label {
break-inside: avoid;
padding-right: 10px;
}
}
.view-all {
color: #898d8f;
margin-bottom: 20px;
font-size: 0.75rem;
}
</style>

View File

@ -1,6 +1,7 @@
<template>
<div class="block">
<b-taginput
:id="metadatumComponentId"
:disabled="disabled"
size="is-small"
icon="magnify"
@ -36,16 +37,14 @@
},
watch: {
selected(){
if(this.allowSelectToCreate && this.selected[0]){
if (this.allowSelectToCreate && this.selected[0]) {
this.selected[0].label.includes(`(${this.$i18n.get('select_to_create')})`);
this.selected[0].label = this.selected[0].label.split('(')[0];
}
}
},
props: {
options: {
type: Array
},
metadatumComponentId: '',
value: [ Number, String, Array ],
allowNew: true,
taxonomyId: Number,
@ -54,7 +53,7 @@
maxtags: '',
},
created(){
if(this.value && this.value.length > 0){
if (this.value && this.value.length > 0){
this.selected = this.value;
}
},
@ -85,13 +84,11 @@
}).then((res) => {
this.termList = res.terms;
for(let term of this.termList){
for (let term of this.termList)
this.labels.push({label: term.name, value: term.id});
}
if(this.termList.length <= 0 && this.allowSelectToCreate){
if (this.termList.length <= 0 && this.allowSelectToCreate)
this.labels.push({label: `${value} (${this.$i18n.get('select_to_create')})`, value: value})
}
this.isFetching = false;
}).catch((error) => {
@ -102,9 +99,8 @@
updateSelectedValues(){
let selected = [];
for( let term of this.value){
for( let term of this.value)
selected.push({label: term.label, value: term.value})
}
this.selected = selected;
},
@ -117,7 +113,6 @@
results.push( term.value );
this.$emit('input', results);
this.$emit('blur');
}
},
emitRemove(){
@ -128,7 +123,6 @@
results.push(term.value);
this.$emit('input', results);
this.$emit('blur');
}
}
}

View File

@ -184,6 +184,7 @@ class Taxonomy extends Metadata_Type {
// TODO term_exists is not fully reliable. Use $terms_repository->term_exists. see issue #159
if (!term_exists($term)) {
$valid = false;
$this->add_error(__('term not found.', 'tainacan'));
break;
}
}

View File

@ -1,21 +1,16 @@
<template>
<b-input
:disabled="disabled"
:class="{'has-content': value !== undefined && value !== ''}"
:id="id"
:id="metadatum.metadatum.metadata_type_object.component + '-' + metadatum.metadatum.slug"
:value="value"
@blur="$emit('blur')"
@input="onInput($event)"/>
</template>
<script>
export default {
props: {
metadatum: {
type: Object
},
metadatum: Object,
value: [String, Number, Array],
id: '',
disabled: false
},
methods: {

View File

@ -1,42 +1,22 @@
<template>
<b-input
:disabled="disabled"
:class="{'has-content': inputValue !== undefined && inputValue !== ''}"
:id="id"
size="is-small"
type="textarea"
:value="inputValue"
@blur="onBlur"
@input="onInput($event)"/>
:id="metadatum.metadatum.metadata_type_object.component + '-' + metadatum.metadatum.slug"
:value="value"
@input="onInput($event)"
type="textarea" />
</template>
<script>
export default {
created(){
if( this.value ){
this.inputValue = this.value
}
},
data() {
return {
inputValue: ''
}
},
props: {
id: '',
metadatum: {
type: Object
},
metadatum: Object,
value: [String, Number, Array],
disabled: false
},
methods: {
onBlur() {
this.$emit('blur');
},
onInput($event) {
this.inputValue = $event;
this.$emit('input', this.inputValue);
onInput(value) {
this.$emit('input', value);
}
}
}

View File

@ -283,7 +283,10 @@ class Terms extends Repository {
* @return bool|WP_Term return boolean indicating if term exists. If $return_term is true and term exists, return WP_Term object
*/
public function term_exists($searched_term, $taxonomy, $parent = null, $return_term = false) {
if ($searched_term == "") {
return false;
}
$Tainacan_Taxonomies = \Tainacan\Repositories\Taxonomies::get_instance();
if ( is_numeric( $taxonomy ) ) {

View File

@ -240,7 +240,7 @@ export default {
this.termsRequestSource = axios.CancelToken.source();
let endpoint = '/taxonomy/' + this.taxonomyId + '/terms/?'+ qs.stringify({ include: this.selectedTerms }) + '&fetch_only=id,name,url,header_image';
let endpoint = '/taxonomy/' + this.taxonomyId + '/terms/?'+ qs.stringify({ hideempty: 0, include: this.selectedTerms }) + '&fetch_only=id,name,url,header_image';
this.tainacanAxios.get(endpoint, { cancelToken: this.termsRequestSource.token })
.then(response => {

View File

@ -210,7 +210,7 @@ registerBlockType('tainacan/carousel-terms-list', {
terms = [];
let endpoint = '/taxonomy/' + taxonomyId + '/terms/?'+ qs.stringify({ include: selectedTerms }) + '&fetch_only=id,name,url,header_image';
let endpoint = '/taxonomy/' + taxonomyId + '/terms/?'+ qs.stringify({ hideempty: 0, include: selectedTerms }) + '&fetch_only=id,name,url,header_image';
tainacan.get(endpoint, { cancelToken: itemsRequestSource.token })
.then(response => {

View File

@ -15,51 +15,46 @@ export const eventBus = new Vue({
}
},
methods : {
updateValue(data){
updateValue({ itemId, metadatumId, values}){
this.$emit('isUpdatingValue', true);
if (data.item_id) {
if (itemId) {
if (data.values.length > 0 && data.values[0].value) {
let val = [];
for (let i of data.values)
val.push(i.value);
data.values = val;
}
let values = ( Array.isArray( data.values[0] ) ) ? data.values[0] : data.values ;
if (values.length > 0 && values[0].value) {
let onlyValues = values.map((aValueObject) => aValueObject.value);
values = onlyValues;
}
this.$store.dispatch('item/updateMetadata', {
item_id: data.item_id,
metadatum_id: data.metadatum_id,
values: values
item_id: itemId,
metadatum_id: metadatumId,
values: Array.isArray(values[0]) ? values[0] : values
})
.then(() => {
this.$emit('isUpdatingValue', false);
let index = this.errors.findIndex( errorItem => errorItem.metadatum_id == data.metadatum_id );
if ( index >= 0)
let index = this.errors.findIndex( errorItem => errorItem.metadatum_id == metadatumId );
if (index >= 0)
this.errors.splice( index, 1);
})
.catch((error) => {
this.$emit('isUpdatingValue', false);
let index = this.errors.findIndex( errorItem => errorItem.metadatum_id == data.metadatum_id );
let index = this.errors.findIndex( errorItem => errorItem.metadatum_id == metadatumId );
let messages = [];
for (let index in error)
messages.push(error[index]);
if ( index >= 0)
Vue.set( this.errors, index, { metadatum_id: data.metadatum_id, errors: messages });
Vue.set( this.errors, index, { metadatum_id: metadatumId, errors: messages });
else
this.errors.push( { metadatum_id: data.metadatum_id, errors: messages } );
this.errors.push( { metadatum_id: metadatumId, errors: messages } );
});
}
},
getErrors(metadatum_id) {
let error = this.errors.find( errorItem => errorItem.metadatum_id == metadatum_id );
return ( error ) ? error.errors : false
let error = this.errors.find(errorItem => errorItem.metadatum_id == metadatum_id);
return error ? error.errors : false
},
clearAllErrors() {
this.errors = [];

View File

@ -1,7 +1,7 @@
import axios from '../../../axios/axios';
import qs from 'qs';
export const fetchActivities = ({ commit }, { page, activitiesPerPage, search, searchDates} ) => {
export const fetchActivities = ({ commit }, { page, activitiesPerPage, search, searchDates, authorId} ) => {
let endpoint = `/logs?paged=${page}&perpage=${activitiesPerPage}&context=edit&orderby=id&order=desc`;
@ -21,6 +21,19 @@ export const fetchActivities = ({ commit }, { page, activitiesPerPage, search, s
endpoint += '&' + qs.stringify(dateQuery);
}
if (authorId != undefined && authorId != null) {
let metaQuery = {
metaquery: [
{
value: authorId,
key: 'user_id',
compare: '='
}
]
};
endpoint += '&' + qs.stringify(metaQuery);
}
return new Promise((resolve, reject) => {
axios.tainacan.get(endpoint)
.then(res => {
@ -37,7 +50,7 @@ export const fetchActivities = ({ commit }, { page, activitiesPerPage, search, s
});
};
export const fetchCollectionActivities = ({ commit }, { page, activitiesPerPage, collectionId, search, searchDates }) => {
export const fetchCollectionActivities = ({ commit }, { page, activitiesPerPage, collectionId, search, searchDates, authorId }) => {
let endpoint = `/collection/${collectionId}/logs?paged=${page}&perpage=${activitiesPerPage}&context=edit&orderby=id&order=desc`;
@ -57,6 +70,19 @@ export const fetchCollectionActivities = ({ commit }, { page, activitiesPerPage,
endpoint += '&' + qs.stringify(dateQuery);
}
if (authorId != undefined && authorId != null) {
let metaQuery = {
metaquery: [
{
value: authorId,
key: 'user_id',
compare: '='
}
]
};
endpoint += '&' + qs.stringify(metaQuery);
}
return new Promise((resolve, reject) => {
axios.tainacan.get(endpoint)
.then(res => {
@ -73,13 +99,26 @@ export const fetchCollectionActivities = ({ commit }, { page, activitiesPerPage,
});
};
export const fetchItemActivities = ({ commit }, { page, activitiesPerPage, itemId, search, searchDates }) => {
export const fetchItemActivities = ({ commit }, { page, activitiesPerPage, itemId, search, searchDates, authorId }) => {
let endpoint = `/item/${itemId}/logs?paged=${page}&perpage=${activitiesPerPage}&context=edit&orderby=id&order=desc`;
if (search != undefined && search != '')
endpoint += `&search=${search}`;
if (authorId != undefined && authorId != null) {
let metaQuery = {
metaquery: [
{
value: authorId,
key: 'user_id',
compare: '='
}
]
};
endpoint += '&' + qs.stringify(metaQuery);
}
if (searchDates && searchDates[0] != null && searchDates[1] != null) {
let dateQuery = {
datequery: [
@ -154,4 +193,17 @@ export const approve = ({commit}, activityId) => {
export const notApprove = ({commit}, activityId) => {
};
// Users for filtering
export const fetchUsers = ({ commit }, { search }) => {
return new Promise((resolve, reject) => {
axios.wp.get('/users?search=' + search)
.then(res => {
resolve(res.data);
})
.catch(error => {
reject(error);
});
});
};

View File

@ -296,7 +296,7 @@ export const clearTerms = ({ commit }) => {
// Used only on Term Edition form, for autocomplete searhc for parents
export const fetchPossibleParentTerms = ({ commit }, { taxonomyId, termId, search } ) => {
return new Promise((resolve, reject) => {
axios.tainacan.get('/taxonomy/' + taxonomyId + '/terms?searchterm=' + search + '&hierarchical=1&exclude_tree=' + termId + "&hideempty=0&offset=0&number=20")
axios.tainacan.get('/taxonomy/' + taxonomyId + '/terms?searchterm=' + search + '&hierarchical=1&exclude_tree=' + termId + "&hideempty=0&offset=0&number=20&order=asc")
.then(res => {
let parentTerms = res.data;
resolve( parentTerms );

View File

@ -8,11 +8,11 @@ Stable tag: 0.13
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-3.0.html
Tainacan is a powerful and flexible repository platform for WordPress. Manage and publish your digital collections just as easily as you post to your blog, having all the tools of a professional repository platform.
Tainacan is an open source, powerful and flexible repository platform for WordPress. Manage and publish your digital collections just as easily as you post to your blog, having all the tools of a professional repository platform.
== Description ==
Tainacan is a powerful and flexible repository platform for WordPress. Manage and publish your digital collections just as easily as you post to your blog, having all the tools of a professional repository platform.
[Tainacan](https://tainacan.org/) is an open source, powerful and flexible repository platform for WordPress. Manage and publish your digital collections just as easily as you post to your blog, having all the tools of a professional repository platform.
= Features =
@ -76,6 +76,11 @@ Upload the files to the plugins directory and activate it. You can also install
If you have Imagick installed in your server, Tainacan will be able to automatically generate a thumbnail from your PDF files. This is desired but not required.
== Find out more ==
* Visit our oficial website: [https://tainacan.org/](https://tainacan.org/)
* Check our documentation Wiki: [https://wiki.tainacan.org/](https://wiki.tainacan.org/)
== Screenshots ==
1. Manage your repository

View File

@ -2,7 +2,7 @@
/*
Plugin Name: Tainacan
Plugin URI: https://tainacan.org/
Description: powerfull and flexible repository platform for WordPress. Manage and publish you digital collections as easily as publishing a post to your blog, while having all the tools of a professional respository platform.
Description: Open source, powerfull and flexible repository platform for WordPress. Manage and publish you digital collections as easily as publishing a post to your blog, while having all the tools of a professional respository platform.
Author: Tainacan.org
Version: 0.13
Text Domain: tainacan

View File

@ -575,6 +575,98 @@ class TAINACAN_REST_Metadata_Controller extends TAINACAN_UnitApiTestCase {
}
public function test_update_taxonomy_metadata() {
$Tainacan_Item_Metadata = \Tainacan\Repositories\Item_Metadata::get_instance();
$collection = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'test_col',
'status' => 'publish'
),
true
);
$tax = $this->tainacan_entity_factory->create_entity(
'taxonomy',
array(
'name' => 'tax_test',
'collections' => [$collection],
'status' => 'publish'
),
true
);
$this->tainacan_entity_factory->create_entity(
'term',
array(
'taxonomy' => $tax->get_db_identifier(),
'name' => 'Rock',
'user' => 56
),
true
);
$this->tainacan_entity_factory->create_entity(
'term',
array(
'taxonomy' => $tax->get_db_identifier(),
'name' => 'Samba',
'user' => 56
),
true
);
$metadatum = $this->tainacan_entity_factory->create_entity(
'metadatum',
array(
'name' => 'tax',
'status' => 'publish',
'collection' => $collection,
'metadata_type' => 'Tainacan\Metadata_Types\Taxonomy',
'metadata_type_options' => [
'taxonomy_id' => $tax->get_id(),
]
),
true
);
$i1 = $this->tainacan_entity_factory->create_entity(
'item',
array(
'title' => 'item teste',
'description' => 'adasdasdsa',
'collection' => $collection
),
true
);
$itemMeta1 = new \Tainacan\Entities\Item_Metadata_Entity($i1, $metadatum);
$itemMeta1->set_value('Rock');
$itemMeta1->validate();
$Tainacan_Item_Metadata->insert($itemMeta1);
$request = new \WP_REST_Request(
'GET',
$this->namespace . '/item/' . $i1->get_id() . '/metadata/' . $metadatum->get_id()
);
$response = $this->server->dispatch($request);
$data = $response->get_data();
$this->assertEquals(false, empty($data['value']));
$request = new \WP_REST_Request(
'PATCH',
$this->namespace . '/item/' . $i1->get_id() . '/metadata/' . $metadatum->get_id()
);
$attributes = json_encode(['values' => '']);
$request->set_body($attributes);
$response = $this->server->dispatch($request);
$data = $response->get_data();
$this->assertEquals(true, empty($data['value']));
}
}
?>