Merge remote-tracking branch 'origin/develop' into field-mapping-interface

# Conflicts:
#	src/admin/tainacan-admin-i18n.php
This commit is contained in:
Jacson Passold 2018-07-09 21:21:32 -03:00
commit 831ec18fb9
59 changed files with 4890 additions and 3918 deletions

2
.gitignore vendored
View File

@ -28,3 +28,5 @@ report.txt
src/assets/css/tainacan-embeds.css
src/assets/css/tainacan-embeds.css.map
demosaved.csv
.DS_Store
src/.DS_Store

View File

@ -54,7 +54,7 @@ before_deploy:
- ssh-add -l
deploy:
- provider: script
script: ssh $ssh_user@$ssh_host $script_deploy_tainacan
script: sshpass -p '$ssh_password' ssh $ssh_user@$ssh_host sh /home/l3p/atualiza_git/atualiza_todos.sh #ssh $ssh_user@$ssh_host $script_deploy_tainacan
skip_cleanup: true
on:
branch: develop

View File

@ -1,4 +1,4 @@
[![Waffle.io - Columns and their card count](https://badge.waffle.io/tainacan/tainacan.svg?columns=In%20Progress)](https://waffle.io/tainacan/tainacan)
[![Build Status](https://travis-ci.org/tainacan/tainacan.svg?branch=develop)](https://travis-ci.org/tainacan/tainacan) [![Waffle.io - Columns and their card count](https://badge.waffle.io/tainacan/tainacan.svg?columns=In%20Progress)](https://waffle.io/tainacan/tainacan)
# Tainacan

View File

@ -2,4 +2,5 @@
* everything auto draft
* post_meta of deleted metadata
* post_meta of deleted instaces of a multiple compound Metadatum. post_meta of a metadatum that is child of a compound metadatum, but which the ID does not appear in any array of a compound metadatum meta_value
* orphan terms (with taxonomy that does not exist)
* orphan terms (with taxonomy that does not exist)
* tnc_bulk postmeta

3772
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -8,44 +8,44 @@
},
"dependencies": {
"axios": "^0.18.0",
"buefy": "^0.6.5",
"buefy": "^0.6.6",
"bulma": "^0.7.1",
"html-to-json": "^0.6.0",
"mdi": "^2.2.43",
"moment": "^2.22.1",
"moment": "^2.22.2",
"npm": "^6.1.0",
"qs": "^6.5.2",
"v-mask": "^1.3.2",
"v-tooltip": "^2.0.0-rc.32",
"v-tooltip": "^2.0.0-rc.33",
"vue": "^2.5.16",
"vue-router": "^3.0.1",
"vuedraggable": "^2.16.0",
"vuex": "^3.0.1"
},
"devDependencies": {
"autoprefixer": "^8.5.0",
"autoprefixer": "^8.6.4",
"babel-core": "^6.26.3",
"babel-loader": "^7.1.4",
"babel-preset-env": "^1.7.0",
"babel-preset-stage-3": "^6.24.1",
"cross-env": "^5.1.5",
"cross-env": "^5.2.0",
"css-loader": "^0.28.11",
"cypress": "^2.1.0",
"element-theme-chalk": "^2.3.9",
"eslint": "^4.19.1",
"cypress": "^3.0.2",
"element-theme-chalk": "^2.4.3",
"eslint": "^5.0.1",
"eslint-loader": "^2.0.0",
"eslint-plugin-vue": "^4.5.0",
"file-loader": "^1.1.11",
"node-sass": "^4.9.0",
"node-sass": "^4.9.1",
"postcss-loader": "^2.1.5",
"sass-loader": "^7.0.1",
"sass-loader": "^7.0.3",
"style-loader": "^0.21.0",
"uglifyjs-webpack-plugin": "^1.2.5",
"vue-custom-element": "^3.0.6",
"vue-loader": "^15.1.0",
"uglifyjs-webpack-plugin": "^1.2.7",
"vue-custom-element": "^3.2.1",
"vue-loader": "^15.2.4",
"vue-template-compiler": "^2.5.16",
"webpack": "^4.8.3",
"webpack-cli": "^2.1.3",
"webpack": "^4.15.1",
"webpack-cli": "^3.0.8",
"webpack-dev-server": "^3.1.4"
}
}

View File

@ -1,22 +1,29 @@
<template>
<div>
<div class="columns is-multiline tnc-advanced-search-container">
<div
:style="advancedSearchResults ? { 'padding-top': '0' } : { 'padding-top': '47px' }"
class="columns is-multiline tnc-advanced-search-container">
<div
v-for="searchCriteria in searchCriterias"
:key="searchCriteria"
v-show="!advancedSearchResults"
v-for="searchCriterion in searchCriteria"
:key="searchCriterion"
class="field column is-12 tainacan-form">
<b-field
class="columns"
grouped>
<!-- Metadata (Search criterias) -->
<!-- Metadata (Search criteria) -->
<b-field class="column">
<b-select
:disabled="advancedSearchQuery.taxquery[searchCriteria] ||
advancedSearchQuery.metaquery[searchCriteria] ? true : false"
@input="addToAdvancedSearchQuery($event, 'metadatum', searchCriteria)">
:placeholder="$i18n.get('instruction_select_a_metadatum')"
:disabled="advancedSearchQuery.taxquery[searchCriterion] ||
advancedSearchQuery.metaquery[searchCriterion] ? true : false"
:value="advancedSearchQuery.metaquery[searchCriterion] ?
advancedSearchQuery.metaquery[searchCriterion].originalMeta :
(advancedSearchQuery.taxquery[searchCriterion] ? advancedSearchQuery.taxquery[searchCriterion].originalMeta : undefined)"
@input="addToAdvancedSearchQuery($event, 'metadatum', searchCriterion)">
<option
v-for="metadatum in metadata"
:value="`${metadatum.id}-${metadatum.metadata_type_options.taxonomy}-${metadatum.metadata_type_object.primitive_type}`"
@ -29,32 +36,36 @@
<b-field
class="column is-two-thirds">
<b-input
v-if="advancedSearchQuery.metaquery[searchCriteria] &&
advancedSearchQuery.metaquery[searchCriteria].ptype != 'date'"
:type="advancedSearchQuery.metaquery[searchCriteria].ptype == 'int' ||
advancedSearchQuery.metaquery[searchCriteria].ptype == 'float' ? 'number' : 'text'"
@input="addValueToAdvancedSearchQuery($event, 'value', searchCriteria)"
/>
v-if="advancedSearchQuery.metaquery[searchCriterion] &&
advancedSearchQuery.metaquery[searchCriterion].ptype != 'date'"
:type="advancedSearchQuery.metaquery[searchCriterion].ptype == 'int' ||
advancedSearchQuery.metaquery[searchCriterion].ptype == 'float' ? 'number' : 'text'"
step="any"
@input="addValueToAdvancedSearchQuery($event, 'value', searchCriterion)"
:value="advancedSearchQuery.metaquery[searchCriterion].value"
/>
<input
v-else-if="advancedSearchQuery.metaquery[searchCriteria] &&
advancedSearchQuery.metaquery[searchCriteria].ptype == 'date'"
v-else-if="advancedSearchQuery.metaquery[searchCriterion] &&
advancedSearchQuery.metaquery[searchCriterion].ptype == 'date'"
class="input"
:value="parseDateToNavigatorLanguage(advancedSearchQuery.metaquery[searchCriterion].value)"
v-mask="dateMask"
@focus="addValueToAdvancedSearchQueryWithoutDelay($event, '', searchCriteria)"
@input="addValueToAdvancedSearchQueryWithoutDelay($event, 'value', searchCriteria)"
@focus="addValueToAdvancedSearchQueryWithoutDelay($event, '', searchCriterion)"
@input="addValueToAdvancedSearchQueryWithoutDelay($event, 'value', searchCriterion)"
:placeholder="dateFormat"
type="text">
<b-taginput
v-else-if="advancedSearchQuery.taxquery[searchCriteria]"
v-else-if="advancedSearchQuery.taxquery[searchCriterion]"
:data="terms"
:value="advancedSearchQuery.taxquery[searchCriterion].btags.length > 0 ?
Array.from(new Set(advancedSearchQuery.taxquery[searchCriterion].btags)) : []"
autocomplete
:loading="isFetching"
attached
ellipsis
:before-adding="hasTagIn($event, searchCriteria)"
@remove="removeValueOf($event, searchCriteria)"
@add="addValueToAdvancedSearchQuery($event, 'terms', searchCriteria)"
@typing="autoCompleteTerm($event, searchCriteria)"
@remove="removeValueOf($event, searchCriterion)"
@add="addValueToAdvancedSearchQuery($event, 'terms', searchCriterion)"
@typing="autoCompleteTerm($event, searchCriterion)"
/>
</b-field>
@ -62,15 +73,15 @@
<b-field
class="column">
<b-select
v-if="advancedSearchQuery.taxquery[searchCriteria] ||
advancedSearchQuery.metaquery[searchCriteria] ? true : false"
@input="addToAdvancedSearchQuery($event, 'comparator', searchCriteria)"
:value="advancedSearchQuery.taxquery[searchCriteria] ?
advancedSearchQuery.taxquery[searchCriteria].operator :
(advancedSearchQuery.metaquery[searchCriteria] ? advancedSearchQuery.metaquery[searchCriteria].compare : '')">
v-if="advancedSearchQuery.taxquery[searchCriterion] ||
advancedSearchQuery.metaquery[searchCriterion] ? true : false"
@input="addToAdvancedSearchQuery($event, 'comparator', searchCriterion)"
:value="advancedSearchQuery.taxquery[searchCriterion] ?
advancedSearchQuery.taxquery[searchCriterion].operator :
(advancedSearchQuery.metaquery[searchCriterion] ? advancedSearchQuery.metaquery[searchCriterion].compare : '')">
<option
v-for="(comparator, key) in getComparators(searchCriteria)"
v-for="(comparator, key) in getComparators(searchCriterion)"
:key="key"
:value="key"
>{{ comparator }}</option>
@ -79,10 +90,10 @@
<div class="field">
<button
@click="removeThis(searchCriteria)"
@click="removeThis(searchCriterion)"
class="button is-white is-pulled-right">
<b-icon
size="is-small"
type="is-secondary"
icon="close"/>
</button>
</div>
@ -92,55 +103,62 @@
<!-- Add button -->
<div
:style="{'padding-left': '25px !important'}"
v-show="!advancedSearchResults"
:style="{
'margin-top': '-15px !important',
'padding-left': '25px !important'
}"
class="field column is-12">
<a
@click="addSearchCriteria"
class="is-secondary is-small">
class="is-secondary is-small add-link">
<b-icon
icon="plus-circle"
size="is-small"
type="is-secondary"/>
{{ $i18n.get('add_another_search_criteria') }}</a>
{{ $i18n.get('add_another_search_criterion') }}</a>
</div>
<!-- Tags -->
<div
class="field column is-12">
<div
v-show="advancedSearchResults"
class="field column is-12">
<b-field
grouped
group-multiline>
<div
v-for="searchCriteria in searchCriterias"
:key="searchCriteria"
v-for="searchCriterion in searchCriteria"
:key="searchCriterion"
class="control taginput-container">
<b-tag
v-if="(advancedSearchQuery.taxquery[searchCriteria] && advancedSearchQuery.taxquery[searchCriteria].terms)"
<b-tag
v-if="advancedSearchQuery.taxquery[searchCriterion] && advancedSearchQuery.taxquery[searchCriterion].terms"
type="is-white"
class="is-rounded"
@close="removeThis(searchCriteria)"
@close="removeThis(searchCriterion)"
attached
closable>
{{ Array.isArray(advancedSearchQuery.taxquery[searchCriteria].terms) ?
advancedSearchQuery.taxquery[searchCriteria].btags.toString() :
advancedSearchQuery.taxquery[searchCriteria].btags }}
{{ Array.isArray(advancedSearchQuery.taxquery[searchCriterion].terms) ?
advancedSearchQuery.taxquery[searchCriterion].btags.toString() :
advancedSearchQuery.taxquery[searchCriterion].btags }}
</b-tag>
<b-tag
v-else-if="(advancedSearchQuery.metaquery[searchCriteria] && advancedSearchQuery.metaquery[searchCriteria].value)"
v-else-if="advancedSearchQuery.metaquery[searchCriterion] && advancedSearchQuery.metaquery[searchCriterion].value"
type="is-white"
class="is-rounded"
@close="removeThis(searchCriteria)"
@close="removeThis(searchCriterion)"
attached
:loading="isFetching"
closable>
{{ advancedSearchQuery.metaquery[searchCriteria].value }}
{{ advancedSearchQuery.metaquery[searchCriterion].value }}
</b-tag>
</div>
</b-field>
</div>
<!-- Clear and search button -->
<div class="column">
<div
v-show="!advancedSearchResults"
class="column">
<div class="field is-grouped is-pulled-right">
<p class="control">
<button
@ -170,6 +188,14 @@
props: {
metadata: Array,
isRepositoryLevel: false,
advancedSearchResults: false,
openFormAdvancedSearch: false,
isDoSearch: false,
},
watch: {
isDoSearch(){
this.searchAdvanced();
}
},
created(){
let locale = navigator.language;
@ -178,6 +204,57 @@
let localeData = moment.localeData();
this.dateFormat = localeData.longDateFormat('L');
if((this.$route.query.metaquery && Object.keys(this.$route.query.metaquery).length > 0) ||
(this.$route.query.taxquery && Object.keys(this.$route.query.taxquery).length > 0) ){
this.searchCriteria = [];
}
if(this.$route.query.metaquery && Object.keys(this.$route.query.metaquery).length > 0){
let metaquery = this.$route.query.metaquery;
for(let meta in metaquery){
this.$set(this.advancedSearchQuery.metaquery, `${meta}`, metaquery[meta]);
}
let keys = Object.keys(this.advancedSearchQuery.metaquery);
let relationIndex = keys.findIndex((element) => {
return element == 'relation';
});
if(relationIndex != -1) {
keys.splice(relationIndex, 1);
}
for(let k of keys){
this.searchCriteria.push(k);
}
}
if(this.$route.query.taxquery && Object.keys(this.$route.query.taxquery).length > 0){
let taxquery = this.$route.query.taxquery;
for(let tax in taxquery){
this.$set(this.advancedSearchQuery.taxquery, `${tax}`, taxquery[tax]);
}
let keys = Object.keys(this.advancedSearchQuery.taxquery);
let relationIndex = keys.findIndex((element) => {
return element == 'relation';
});
if(relationIndex != -1) {
keys.splice(relationIndex, 1);
}
for(let k of keys){
this.searchCriteria.push(k);
}
}
},
data() {
return {
@ -199,7 +276,7 @@
'IN': this.$i18n.get('contains'),
'NOT IN': this.$i18n.get('not_contains')
},
searchCriterias: [1],
searchCriteria: [1],
advancedSearchQuery: {
advancedSearch: true,
metaquery: {},
@ -219,13 +296,13 @@
...mapGetters('taxonomy', [
'getTerms'
]),
autoCompleteTerm: _.debounce( function(value, searchCriteria){
autoCompleteTerm: _.debounce( function(value, searchCriterion){
this.termList = [];
this.terms = [];
this.isFetching = true;
this.fetchTerms({
taxonomyId: this.advancedSearchQuery.taxquery[searchCriteria].taxonomy_id,
taxonomyId: this.advancedSearchQuery.taxquery[searchCriterion].taxonomy_id,
fetchOnly: {
fetch_only: {
0: 'name',
@ -251,64 +328,64 @@
throw error;
});
}, 300),
getComparators(searchCriteria){
if(this.advancedSearchQuery.taxquery[searchCriteria]){
getComparators(searchCriterion){
if(this.advancedSearchQuery.taxquery[searchCriterion]){
return this.taxqueryOperators;
} else if(this.advancedSearchQuery.metaquery[searchCriteria]){
if(this.advancedSearchQuery.metaquery[searchCriteria].ptype == 'int' ||
this.advancedSearchQuery.metaquery[searchCriteria].ptype == 'float' ||
this.advancedSearchQuery.metaquery[searchCriteria].ptype == 'date'){
} else if(this.advancedSearchQuery.metaquery[searchCriterion]){
if(this.advancedSearchQuery.metaquery[searchCriterion].ptype == 'int' ||
this.advancedSearchQuery.metaquery[searchCriterion].ptype == 'float' ||
this.advancedSearchQuery.metaquery[searchCriterion].ptype == 'date'){
return this.metaqueryOperatorsForInterval;
} else{
return this.metaqueryOperatorsRegular;
}
}
},
removeThis(searchCriteria){
let criteriaIndex = this.searchCriterias.findIndex((element) => {
return element == searchCriteria;
removeThis(searchCriterion){
let criteriaIndex = this.searchCriteria.findIndex((element) => {
return element == searchCriterion;
});
this.searchCriterias.splice(criteriaIndex, 1);
this.searchCriteria.splice(criteriaIndex, 1);
if(this.advancedSearchQuery.taxquery[searchCriteria]){
delete this.advancedSearchQuery.taxquery[searchCriteria];
} else if(this.advancedSearchQuery.metaquery[searchCriteria]){
delete this.advancedSearchQuery.metaquery[searchCriteria];
if(this.advancedSearchQuery.taxquery[searchCriterion]){
delete this.advancedSearchQuery.taxquery[searchCriterion];
} else if(this.advancedSearchQuery.metaquery[searchCriterion]){
delete this.advancedSearchQuery.metaquery[searchCriterion];
}
},
removeValueOf(value, searchCriteria){
if(this.advancedSearchQuery.taxquery[searchCriteria]){
let tagIndex = this.advancedSearchQuery.taxquery[searchCriteria].btags.findIndex((element) => {
removeValueOf(value, searchCriterion){
if(this.advancedSearchQuery.taxquery[searchCriterion]){
let tagIndex = this.advancedSearchQuery.taxquery[searchCriterion].btags.findIndex((element) => {
return element == value;
});
this.advancedSearchQuery.taxquery[searchCriteria].btags.splice(tagIndex, 1);
this.advancedSearchQuery.taxquery[searchCriteria].terms.splice(tagIndex, 1);
} else if(this.advancedSearchQuery.metaquery[searchCriteria]){
this.$set(this.advancedSearchQuery.metaquery[searchCriteria], 'value', '');
this.advancedSearchQuery.taxquery[searchCriterion].btags.splice(tagIndex, 1);
this.advancedSearchQuery.taxquery[searchCriterion].terms.splice(tagIndex, 1);
} else if(this.advancedSearchQuery.metaquery[searchCriterion]){
this.$set(this.advancedSearchQuery.metaquery[searchCriterion], 'value', '');
}
},
hasTagIn(value, searchCriteria){
return !!this.advancedSearchQuery.taxquery[searchCriteria].btags.find((element) => {
return element == value;
});
},
// hasTagIn(value, searchCriterion){
// return !!this.advancedSearchQuery.taxquery[searchCriterion].btags.find((element) => {
// return element == value;
// });
// },
addSearchCriteria(){
let aleatoryKey = Math.floor(Math.random() * 1000) + 2;
let aleatoryKey = Math.floor(Math.random() * (1000 - 2 + 1)) + 2;
let found = this.searchCriterias.find((element) => {
let found = this.searchCriteria.find((element) => {
return element == aleatoryKey;
});
if(found == undefined){
this.searchCriterias.push(aleatoryKey);
this.searchCriteria.push(aleatoryKey);
} else {
this.addSearchCriteria();
}
},
clearSearch(){
this.searchCriterias = [1];
this.searchCriteria = [1];
this.advancedSearchQuery = {
advancedSearch: true,
metaquery: {},
@ -318,16 +395,16 @@
convertDateToMatchInDB(dateValue){
return moment(dateValue, this.dateFormat).toISOString().split('T')[0];
},
addValueToAdvancedSearchQueryWithoutDelay($event, type, searchCriteria){
addValueToAdvancedSearchQueryWithoutDelay($event, type, searchCriterion){
if(type == ''){
this.$set($event.target, 'value', '');
this.addToAdvancedSearchQuery('', 'value', searchCriteria);
this.addToAdvancedSearchQuery('', 'value', searchCriterion);
} else {
this.addToAdvancedSearchQuery($event.target.value, type, searchCriteria);
this.addToAdvancedSearchQuery($event.target.value, type, searchCriterion);
}
},
addValueToAdvancedSearchQuery: _.debounce(function(value, type, searchCriteria) {
this.addToAdvancedSearchQuery(value, type, searchCriteria);
addValueToAdvancedSearchQuery: _.debounce(function(value, type, searchCriterion) {
this.addToAdvancedSearchQuery(value, type, searchCriterion);
}, 900),
searchAdvanced(){
if(Object.keys(this.advancedSearchQuery.taxquery).length > 0 &&
@ -348,8 +425,7 @@
let value = this.advancedSearchQuery.metaquery[metaquery].value;
if(value.includes('/')){
this.advancedSearchQuery.metaquery[metaquery].value = this.convertDateToMatchInDB(value);
//this.$set(this.advancedSearchQuery.metaquery[metaquery], 'value', this.convertDateToMatchInDB(value));
this.$set(this.advancedSearchQuery.metaquery[metaquery], 'value', this.convertDateToMatchInDB(value));
}
}
}
@ -376,17 +452,21 @@
if(value.includes('-')){
this.$set(this.advancedSearchQuery.metaquery[metaquery], 'value', this.parseDateToNavigatorLanguage(value));
}
}, 110);
}, 200);
}
}
}
},
parseDateToNavigatorLanguage(date){
date = new Date(date.replace(/-/g, '/'));
if(date && date.length === this.dateMask.length) {
date = new Date(date.replace(/-/g, '/'));
return moment(date, moment.ISO_8601).format(this.dateFormat);
return moment(date, moment.ISO_8601).format(this.dateFormat);
} else {
return date;
}
},
addToAdvancedSearchQuery(value, type, searchCriteria){
addToAdvancedSearchQuery(value, type, searchCriterion){
if(type == 'metadatum'){
const criteriaKey = value.split('-');
@ -394,12 +474,13 @@
if(criteriaKey[1] != 'undefined'){
// Was selected a taxonomy criteria
this.advancedSearchQuery.taxquery = Object.assign({}, this.advancedSearchQuery.taxquery, {
[`${searchCriteria}`]: {
[`${searchCriterion}`]: {
taxonomy: criteriaKey[1],
terms: [],
btags: [],
field: 'term_id',
operator: 'IN',
originalMeta: value,
taxonomy_id: Number(criteriaKey[1].match(/[\d]+/))
}
});
@ -407,21 +488,23 @@
// Was selected a metadatum criteria
if(criteriaKey[2] != 'date' && criteriaKey[2] != 'int' && criteriaKey[2] != 'float'){
this.advancedSearchQuery.metaquery = Object.assign({}, this.advancedSearchQuery.metaquery, {
[`${searchCriteria}`]: {
[`${searchCriterion}`]: {
key: Number(criteriaKey[0]),
compare: 'LIKE'
compare: 'LIKE',
originalMeta: value,
}
});
} else {
this.advancedSearchQuery.metaquery = Object.assign({}, this.advancedSearchQuery.metaquery, {
[`${searchCriteria}`]: {
[`${searchCriterion}`]: {
key: Number(criteriaKey[0]),
compare: '='
compare: '=',
originalMeta: value,
}
});
}
this.$set(this.advancedSearchQuery.metaquery[searchCriteria], 'ptype', criteriaKey[2]);
this.$set(this.advancedSearchQuery.metaquery[searchCriterion], 'ptype', criteriaKey[2]);
}
} else if(type == 'terms'){
let termIndex = this.terms.findIndex((element, index) => {
@ -430,16 +513,16 @@
}
});
this.advancedSearchQuery.taxquery[searchCriteria].terms.push(this.termList[termIndex].id);
this.advancedSearchQuery.taxquery[searchCriteria].btags.push(value);
this.advancedSearchQuery.taxquery[searchCriterion].terms.push(this.termList[termIndex].id);
this.advancedSearchQuery.taxquery[searchCriterion].btags.push(value);
this.terms = [];
} else if(type == 'value'){
this.$set(this.advancedSearchQuery.metaquery[searchCriteria], 'value', value);
this.$set(this.advancedSearchQuery.metaquery[searchCriterion], 'value', value);
} else if(type == 'comparator'){
if(this.advancedSearchQuery.taxquery[searchCriteria]){
this.$set(this.advancedSearchQuery.taxquery[searchCriteria], 'operator', value);
} else if(this.advancedSearchQuery.metaquery[searchCriteria]){
this.$set(this.advancedSearchQuery.metaquery[searchCriteria], 'compare', value);
if(this.advancedSearchQuery.taxquery[searchCriterion]){
this.$set(this.advancedSearchQuery.taxquery[searchCriterion], 'operator', value);
} else if(this.advancedSearchQuery.metaquery[searchCriterion]){
this.$set(this.advancedSearchQuery.metaquery[searchCriterion], 'compare', value);
}
}
},
@ -452,7 +535,6 @@
@import '../../scss/_variables.scss';
.tnc-advanced-search-container {
padding-top: 47px;
padding-right: $page-side-padding;
padding-left: $page-side-padding;
padding-bottom: 47px;

View File

@ -806,7 +806,7 @@ export default {
height: 30px !important;
width: 30px !important;
z-index: 99;
margin-left: 10px !important;
margin-left: 12px !important;
.icon {
display: inherit;
@ -839,7 +839,7 @@ export default {
.header-buttons-row {
text-align: right;
top: -35px;
right: 5px;
right: 20px;
position: relative;
}
}
@ -871,8 +871,8 @@ export default {
}
.thumbnail-buttons-row {
position: relative;
left: 100px;
bottom: -136px;
left: 60px;
bottom: -142px;
}
}
.selected-cover-page {

View File

@ -42,6 +42,13 @@
</div>
</b-field>
<!-- Importer custom options -->
<form
id="importerOptionsForm"
v-if="importer.options_form != undefined && importer.options_form != null && importer.options_form != ''">
<div v-html="importer.options_form"/>
</form>
<!-- File Source input -->
<b-field
v-if="importer.accepts.file"
@ -280,6 +287,7 @@ export default {
'updateImporter',
'updateImporterFile',
'updateImporterURL',
'updateImporterOptions',
'fetchImporterSourceInfo',
'updateImporterCollection',
'runImporter'
@ -370,30 +378,63 @@ export default {
.then(updatedImporter => {
this.importer = updatedImporter;
this.runImporter(this.sessionId)
.then(backgroundProcess => {
this.hasRunImporter = true;
this.backgroundProcess = backgroundProcess;
this.$console.log(backgroundProcess);
})
.catch((errors) => {
this.$console.log(errors);
});
if (this.importer.options_form != undefined && this.importer.options != null && this.importer.options_form != '') {
let formElement = document.getElementById('importerOptionsForm');
let formData = new FormData(formElement);
let formObj = {};
for (let [key, value] of formData.entries())
formObj[key] = value;
this.updateImporterOptions({ sessionId: this.sessionId, options: formObj })
.then(updatedImporter => {
this.importer = updatedImporter;
this.finishRunImporter();
})
.catch((errors) => {
this.$console.log(errors);
});
} else
this.finishRunImporter();
})
.catch((errors) => {
this.$console.log(errors);
});
} else {
this.runImporter(this.sessionId)
.then(backgroundProcess => {
this.hasRunImporter = true;
this.backgroundProcess = backgroundProcess;
})
.catch((errors) => {
this.$console.log(errors);
});
if (this.importer.options_form != undefined && this.importer.options != null && this.importer.options_form != '') {
let formElement = document.getElementById('importerOptionsForm');
let formData = new FormData(formElement);
let formObj = {};
for (let [key, value] of formData.entries())
formObj[key] = value;
this.updateImporterOptions({ sessionId: this.sessionId, optionsForm: formObj })
.then(updatedImporter => {
this.importer = updatedImporter;
this.finishRunImporter();
})
.catch((errors) => {
this.$console.log(errors);
});
} else
this.finishRunImporter();
}
},
finishRunImporter() {
this.runImporter(this.sessionId)
.then(backgroundProcess => {
this.hasRunImporter = true;
this.backgroundProcess = backgroundProcess;
})
.catch((errors) => {
this.$console.log(errors);
});
},
onCheckBackgroundProcessStatus() {
this.fetchProcess(this.backgroundProcess.bg_process_id)
.then((backgroundProcess) => {

View File

@ -1,5 +1,8 @@
<template>
<div>
<b-loading
:active.sync="isLoading"
:can-cancel="false"/>
<button
id="metadata-column-compress-button"
@click="isMetadataColumnCompressed = !isMetadataColumnCompressed">
@ -13,52 +16,6 @@
<div class="columns">
<div class="column is-5-5">
<!-- Status -------------------------------- -->
<div class="section-label">
<label>{{ $i18n.get('label_status') }}</label>
<span class="required-metadatum-asterisk">*</span>
<help-button
:title="$i18n.getHelperTitle('items', 'status')"
:message="$i18n.getHelperMessage('items', 'status')"/>
</div>
<!-- Last Updated Info -->
<p>{{ ($i18n.get('info_updated_at') + ' ' + lastUpdated) }}
<em>
<span v-if="isUpdatingValues && !isEditingValues">&nbsp;&nbsp;{{ $i18n.get('info_updating_metadata_values') }}</span>
<span v-if="isEditingValues">&nbsp;&nbsp;{{ $i18n.get('info_editing_metadata_values') }}</span>
</em>
</p>
<div class="section-status">
<div class="field has-addons">
<b-select
v-model="form.status"
:placeholder="$i18n.get('instruction_select_a_status')">
<option
:id="`status-option-${statusOption.value}`"
v-for="statusOption in statusOptions"
:key="statusOption.value"
:value="statusOption.value"
:disabled="statusOption.disabled">{{ statusOption.label }}
</option>
</b-select>
<div class="control">
<button
type="button"
id="button-submit-item-creation"
@click.prevent="onSubmit"
class="button is-success">
{{ $i18n.get('save') }}
</button>
</div>
</div>
<p
v-if="item.status == 'auto-draft'"
class="help is-danger">
{{ $i18n.get('info_item_not_saved') }}
</p>
<p class="help is-danger">{{ formErrorMessage }}</p>
</div>
<!-- Document -------------------------------- -->
<div class="section-label">
<label>{{ form.document != undefined && form.document != null && form.document != '' ? $i18n.get('label_document') : $i18n.get('label_document_empty') }}</label>
@ -66,61 +23,84 @@
:title="$i18n.getHelperTitle('items', 'document')"
:message="$i18n.getHelperMessage('items', 'document')"/>
</div>
<div class="section-box ">
<div class="section-box document-field">
<div
v-if="form.document != undefined && form.document != null &&
form.document_type != undefined && form.document_type != null &&
form.document != '' && form.document_type != 'empty'">
<div v-if="form.document_type == 'attachment'">
<div v-html="item.document_as_html" />
<button
type="button"
class="button is-primary"
size="is-small"
@click.prevent="setFileDocument($event)">
{{ $i18n.get('edit') }}
</button>
<button
type="button"
class="button is-primary"
size="is-small"
@click.prevent="removeDocument()">
{{ $i18n.get('remove') }}
</button>
<div class="document-buttons-row">
<a
class="button is-rounded is-secondary"
size="is-small"
id="button-edit-document"
:aria-label="$i18n.get('label_button_edit_document')"
@click.prevent="setFileDocument($event)">
<b-icon
size="is-small"
icon="pencil" />
</a>
<a
class="button is-rounded is-secondary"
size="is-small"
id="button-delete-document"
:aria-label="$i18n.get('label_button_delete_document')"
@click.prevent="removeDocument()">
<b-icon
size="is-small"
icon="delete" />
</a>
</div>
</div>
<div v-if="form.document_type == 'text'">
<div v-html="item.document_as_html" />
<button
type="button"
class="button is-primary"
size="is-small"
@click.prevent="setTextDocument()">
{{ $i18n.get('edit') }}
</button>
<button
type="button"
class="button is-primary"
size="is-small"
@click.prevent="removeDocument()">
{{ $i18n.get('remove') }}
</button>
<div class="document-buttons-row">
<a
class="button is-rounded is-secondary"
:aria-label="$i18n.get('label_button_edit_document')"
id="button-edit-document"
@click.prevent="setTextDocument()">
<b-icon
size="is-small"
icon="pencil" />
</a>
<a
class="button is-rounded is-secondary"
size="is-small"
:aria-label="$i18n.get('label_button_delete_document')"
id="button-delete-document"
@click.prevent="removeDocument()">
<b-icon
size="is-small"
icon="delete" />
</a>
</div>
</div>
<div v-if="form.document_type == 'url'">
<div v-html="item.document_as_html" />
<button
type="button"
class="button is-secondary"
size="is-small"
@click.prevent="setURLDocument()">
{{ $i18n.get('edit') }}
</button>
<button
type="button"
class="button is-secondary"
size="is-small"
@click.prevent="removeDocument()">
{{ $i18n.get('remove') }}
</button>
<div class="document-buttons-row">
<a
class="button is-rounded is-secondary"
size="is-small"
:aria-label="$i18n.get('label_button_edit_document')"
id="button-edit-document"
@click.prevent="setURLDocument()">
<b-icon
size="is-small"
icon="pencil" />
</a>
<a
class="button is-rounded is-secondary"
size="is-small"
:aria-label="$i18n.get('label_button_delete_document')"
id="button-delete-document"
@click.prevent="removeDocument()">
<b-icon
size="is-small"
icon="delete" />
</a>
</div>
</div>
</div>
<ul v-else>
@ -229,16 +209,10 @@
</div>
<div class="section-box section-thumbnail">
<div class="thumbnail-field">
<a
class="button is-rounded is-secondary"
id="button-edit-thumbnail"
:aria-label="$i18n.get('label_button_edit_thumb')"
@click.prevent="thumbnailMediaFrame.openFrame($event)">
<b-icon icon="pencil" />
</a>
<file-item
v-if="item.thumbnail.thumb != undefined && item.thumbnail.thumb != false"
:show-name="false"
:size="178"
:file="{
media_type: 'image',
guid: { rendered: item.thumbnail.thumb },
@ -254,13 +228,23 @@
</figure>
<div class="thumbnail-buttons-row">
<a
id="button-delete"
class="button is-rounded is-secondary"
id="button-edit-thumbnail"
:aria-label="$i18n.get('label_button_edit_thumb')"
@click.prevent="thumbnailMediaFrame.openFrame($event)">
<b-icon
size="is-small"
icon="pencil" />
</a>
<a
v-if="item.thumbnail.thumb != undefined && item.thumbnail.thumb != false"
id="button-delete-thumbnail"
class="button is-rounded is-secondary"
:aria-label="$i18n.get('label_button_delete_thumb')"
@click="deleteThumbnail()">
<b-icon
type="is-gray"
size="is-small"
icon="delete" />
<span class="text">{{ $i18n.get('remove') }} </span>
</a>
</div>
</div>
@ -294,6 +278,71 @@
<div
class="column is-4-5"
v-show="!isMetadataColumnCompressed">
<!-- Visibility (status public or private) -------------------------------- -->
<div class="section-label">
<label>{{ $i18n.get('label_visibility') }}</label>
<span class="required-metadatum-asterisk">*</span>
<help-button
:title="$i18n.get('label_visibility')"
:message="$i18n.get('info_visibility_helper')"/>
</div>
<div class="section-status">
<div class="field has-addons">
<b-radio
v-model="visibility"
value="publish"
native-value="publish">
<span class="icon">
<i class="mdi mdi-earth"/>
</span> {{ $i18n.get('publish_visibility') }}
</b-radio>
<b-radio
v-model="visibility"
value="private"
native-value="private">
<span class="icon">
<i class="mdi mdi-lock"/>
</span> {{ $i18n.get('private_visibility') }}
</b-radio>
</div>
</div>
<!-- Status -------------------------------- -->
<!--<div class="section-label">
<label>{{ $i18n.get('label_status') }}</label>
<span class="required-metadatum-asterisk">*</span>
<help-button
:title="$i18n.getHelperTitle('items', 'status')"
:message="$i18n.getHelperMessage('items', 'status')"/>
</div>
<div class="section-status">
<div class="field has-addons">
<b-select
v-model="form.status"
:placeholder="$i18n.get('instruction_select_a_status')">
<option
:id="`status-option-${statusOption.value}`"
v-for="statusOption in statusOptions"
:key="statusOption.value"
:value="statusOption.value"
:disabled="statusOption.disabled">{{ statusOption.label }}
</option>
</b-select>
<div class="control">
<button
type="button"
id="button-submit-item-creation"
@click.prevent="onSubmit"
class="button is-success">
{{ $i18n.get('save') }}
</button>
</div>
</div>
</div>-->
<label class="section-label">{{ $i18n.get('metadata') }}</label>
<br>
<a
@ -315,11 +364,74 @@
</div>
</div>
<div class="footer">
<!-- Last Updated Info -->
<div class="update-info-section">
<p>{{ ($i18n.get('info_updated_at') + ' ' + lastUpdated) }}
<em>
<span v-if="isUpdatingValues && !isEditingValues">&nbsp;&nbsp;{{ $i18n.get('info_updating_metadata_values') }}</span>
<span v-if="isEditingValues">&nbsp;&nbsp;{{ $i18n.get('info_editing_metadata_values') }}</span>
</em>
</p>
<p class="help is-danger">{{ errorList }}</p>
<p class="help is-danger">{{ formErrorMessage }}</p>
</div>
<div
class="form-submission-footer"
v-if="form.status == 'trash'">
<button
@click="onDeletePermanently()"
type="button"
class="button is-outlined">{{ $i18n.get('label_delete_permanently') }}</button>
<button
@click="onSubmit('draft')"
type="button"
class="button is-secondary">{{ $i18n.get('label_save_as_draft') }}</button>
<button
@click="onSubmit(visibility)"
type="button"
class="button is-success">{{ $i18n.get('label_publish') }}</button>
</div>
<div
class="form-submission-footer"
v-if="form.status == 'auto-draft' || form.status == 'draft' || form.status == undefined">
<button
v-if="form.status == 'draft'"
@click="onSubmit('trash')"
type="button"
class="button is-outlined">{{ $i18n.get('label_send_to_trash') }}</button>
<button
v-if="form.status == 'auto-draft'"
@click="onDiscart()"
type="button"
class="button is-outlined">{{ $i18n.get('label_discart') }}</button>
<button
@click="onSubmit('draft')"
type="button"
class="button is-secondary">{{ form.status == 'draft' ? $i18n.get('label_update_draft') : $i18n.get('label_save_as_draft') }}</button>
<button
@click="onSubmit(visibility)"
type="button"
class="button is-success">{{ $i18n.get('label_publish') }}</button>
</div>
<div
class="form-submission-footer"
v-if="form.status == 'publish' || form.status == 'private'">
<button
@click="onSubmit('trash')"
type="button"
class="button is-outlined">{{ $i18n.get('label_send_to_trash') }}</button>
<button
@click="onSubmit('draft')"
type="button"
class="button is-secondary">{{ $i18n.get('label_return_to_draft') }}</button>
<button
@click="onSubmit(visibility)"
type="button"
class="button is-success">{{ $i18n.get('label_update') }}</button>
</div>
</div>
</form>
<b-loading
:active.sync="isLoading"
:can-cancel="false"/>
</div>
</template>
@ -342,6 +454,7 @@ export default {
isMetadataColumnCompressed: false,
metadatumCollapses: [],
collapseAll: false,
visibility: 'publish',
form: {
collectionId: Number,
status: '',
@ -385,6 +498,9 @@ export default {
},
lastUpdated() {
return this.getLastUpdated();
},
errrorList() {
return eventBus.errors;
}
},
components: {
@ -402,17 +518,24 @@ export default {
'sendAttachments',
'updateThumbnail',
'fetchAttachments',
'cleanLastUpdated'
'cleanLastUpdated',
'setLastUpdated'
]),
...mapGetters('item',[
'getMetadata',
'getAttachments',
'getLastUpdated'
]),
onSubmit() {
...mapActions('collection', [
'deleteItem',
]),
onSubmit(status) {
// Puts loading on Item edition
this.isLoading = true;
let previousStatus = this.form.status;
this.form.status = status;
let data = {item_id: this.itemId, status: this.form.status};
this.updateItem(data).then(updatedItem => {
@ -426,19 +549,28 @@ export default {
this.isLoading = false;
this.$router.push(this.$routerHelper.getItemPath(this.form.collectionId, this.itemId));
if (this.form.status != 'trash')
this.$router.push(this.$routerHelper.getItemPath(this.form.collectionId, this.itemId));
else
this.$router.push(this.$routerHelper.getCollectionPath(this.form.collectionId));
})
.catch((errors) => {
for (let error of errors.errors) {
for (let metadatum of Object.keys(error)){
eventBus.errors.push({ metadatum_id: metadatum, errors: error[metadatum]});
}
}
this.formErrorMessage = errors.error_message;
this.form.status = previousStatus;
this.item.status = previousStatus;
this.isLoading = false;
});
},
onDiscart() {
this.$router.go(-1);
},
createNewItem() {
// Puts loading on Draft Item creation
this.isLoading = true;
@ -454,7 +586,8 @@ export default {
this.initializeMediaFrames();
// Pre-fill status with publish to incentivate it
this.form.status = 'publish';
this.visibility = 'publish';
this.form.status = 'auto-draft'
this.form.document = this.item.document;
this.form.document_type = this.item.document_type;
@ -628,6 +761,21 @@ export default {
},
onChangeCollapse(event, index) {
this.metadatumCollapses.splice(index, 1, event);
},
onDeletePermanently() {
this.$modal.open({
parent: this,
component: CustomDialog,
props: {
icon: 'alert',
title: this.$i18n.get('label_warning'),
message: this.isOnTrash ? this.$i18n.get('info_warning_item_delete') : this.$i18n.get('info_warning_item_trash'),
onConfirm: () => {
this.deleteItem({ itemId: this.itemId, isPermanently: true })
this.$router.push(this.$routerHelper.getCollectionPath(this.form.collectionId))
}
}
});
}
},
created(){
@ -661,7 +809,11 @@ export default {
if (this.form.document_type != undefined && this.form.document_type == 'text')
this.textContent = this.form.document;
if (this.item.status == 'publish' || this.item.status == 'private')
this.visibility = this.item.status;
this.loadMetadata();
this.setLastUpdated(this.item.modification_date);
});
// Fetch current existing attachments
@ -669,14 +821,15 @@ export default {
}
// Sets feedback variables
eventBus.$on('isChangingValue', () => {
this.isEditingValues = true;
setTimeout(()=> {
this.isEditingValues = false;
}, 1000)
});
eventBus.$on('isUpdatingValue', (status) => {
this.isUpdatingValues = status;
// if (this.isUpdatingValues) {
// this.$toast.open({
// duration: 2000,
// message: this.$i18n.get('info_updating_metadata_values'),
// position: 'is-bottom',
// })
// }
});
this.cleanLastUpdated();
},
@ -732,6 +885,10 @@ export default {
}
}
.page-container-shrinked {
height: calc(100% - 132px) !important; // Bigger than the others due footer's height
}
.page-container {
padding: 25px 0px;
@ -740,10 +897,6 @@ export default {
padding-right: $page-side-padding;
}
.column {
padding-top: 0px;
padding-bottom: 0px;
}
.column.is-5-5 {
width: 45.833333333%;
padding-left: $page-side-padding;
@ -764,6 +917,10 @@ export default {
padding: 10px 0px 10px 60px;
}
@media screen and (max-width: 769px) {
width: 100%;
}
}
}
@ -780,11 +937,13 @@ export default {
.collapse-all {
font-size: 12px;
.icon { vertical-align: bottom; }
.icon {
vertical-align: bottom;
}
}
.section-box {
border: 1px solid $draggable-border-color;
background-color: white;
padding: 26px;
margin-top: 16px;
@ -814,13 +973,16 @@ export default {
}
.section-status{
padding: 16px 0;
}
.section-thumbnail {
width: 174px;
padding-top: 0;
padding-bottom: 0;
.field .b-radio {
margin-right: 24px;
.icon {
font-size: 18px !important;
color: $gray;
}
}
}
.section-attachments {
border: 1px solid $draggable-border-color;
height: 250px;
max-width: 100%;
resize: vertical;
@ -836,61 +998,97 @@ export default {
margin-right: -15px;
}
.document-field {
.document-buttons-row {
text-align: right;
top: -21px;
position: relative;
}
}
#button-edit-thumbnail,
#button-edit-document,
#button-delete-thumbnail,
#button-delete-document {
border-radius: 100px !important;
height: 30px !important;
width: 30px !important;
z-index: 99;
margin-left: 10px !important;
.icon {
display: inherit;
padding: 0;
margin: 0;
margin-top: 1px;
font-size: 18px;
}
}
.thumbnail-field {
margin-top: -8px;
.content {
padding: 10px;
font-size: 0.8em;
}
img {
height: 112px;
width: 112px;
height: 178px;
width: 178px;
}
.image-placeholder {
position: absolute;
margin-left: 10px;
margin-right: 10px;
margin-left: 45px;
margin-right: 45px;
font-size: 0.8rem;
font-weight: bold;
z-index: 99;
text-align: center;
color: gray;
top: 38px;
top: 70px;
max-width: 90px;
}
#button-edit-thumbnail {
border-radius: 100px !important;
height: 40px !important;
width: 40px !important;
bottom: -20px;
left: -20px;
z-index: 99;
.icon {
display: inherit;
padding: 0;
margin: 0;
margin-top: 1px;
}
}
.thumbnail-buttons-row {
display: inline-block;
padding: 8px 0px;
border-radius: 0px 0px 0px 4px;
font-size: 14px;
a { color: $tainacan-input-color; }
.text {
top: -3px;
position: relative;
}
i.mdi-24px.mdi-set, i.mdi-24px.mdi::before {
font-size: 20px;
}
position: relative;
left: 90px;
bottom: 22px;
}
}
.footer {
padding: 24px $page-side-padding;
position: absolute;
bottom: 0;
z-index: 999999;
background-color: white;
border-top: 2px solid $secondary;
width: 100%;
.form-submission-footer {
width: 100%;
display: flex;
justify-content: end;
.button {
margin-left: 6px;
margin-right: 6px;
}
.button.is-outlined {
margin-left: 0px;
margin-right: auto;
}
}
.update-info-section {
text-align: center;
position: relative;
margin-top: -20px;
top: 28px;
color: $gray-light;
}
}
</style>

View File

@ -85,7 +85,7 @@
<a
id="button-edit"
:aria-label="$i18n.getFrom('items','edit_item')"
@click.prevent.stop="goToItemEditPage(item.id)">
@click.prevent.stop="goToItemEditPage(item)">
<b-icon
type="is-secondary"
icon="pencil"/>
@ -145,7 +145,7 @@
<a
id="button-edit"
:aria-label="$i18n.getFrom('items','edit_item')"
@click.prevent.stop="goToItemEditPage(item.id)">
@click.prevent.stop="goToItemEditPage(item)">
<b-icon
type="is-secondary"
icon="pencil"/>
@ -248,7 +248,7 @@
<a
id="button-edit"
:aria-label="$i18n.getFrom('items','edit_item')"
@click.prevent.stop="goToItemEditPage(item.id)">
@click.prevent.stop="goToItemEditPage(item)">
<b-icon
type="is-secondary"
icon="pencil"/>
@ -419,7 +419,7 @@
<a
id="button-edit"
:aria-label="$i18n.getFrom('items','edit_item')"
@click.prevent.stop="goToItemEditPage(item.id)">
@click.prevent.stop="goToItemEditPage(item)">
<b-icon
type="is-secondary"
icon="pencil"/>
@ -570,10 +570,10 @@ export default {
});
},
goToItemPage(item) {
this.$router.push(this.$routerHelper.getItemPath(this.collectionId, item.id));
this.$router.push(this.$routerHelper.getItemPath(item.collection_id, item.id));
},
goToItemEditPage(itemId) {
this.$router.push(this.$routerHelper.getItemEditPath(this.collectionId, itemId));
goToItemEditPage(item) {
this.$router.push(this.$routerHelper.getItemEditPath(item.collection_id, item.id));
},
renderMetadata(itemMetadata, column) {

View File

@ -1,16 +1,16 @@
<template>
<div
id="tainacan-header"
class="level"
id="tainacan-header"
class="level"
:class="{'menu-compressed': isMenuCompressed}">
<div class="level-left">
<div class="level-item">
<router-link
tag="a"
<router-link
tag="a"
to="/">
<img
class="tainacan-logo"
alt="Tainacan Logo"
<img
class="tainacan-logo"
alt="Tainacan Logo"
:src="logoHeader">
</router-link>
</div>
@ -18,24 +18,45 @@
<div class="level-right">
<div class="search-area">
<div class="control has-icons-right is-small is-clearfix">
<input
autocomplete="on"
:placeholder="$i18n.get('instruction_search_on_repository')"
class="input is-small"
type="search"
<input
autocomplete="on"
:placeholder="$i18n.get('instruction_search_in_repository')"
class="input is-small"
type="search"
:value="searchQuery"
@input="futureSearchQuery = $event.target.value"
@keyup.enter="updateSearch()">
<span
<span class="icon is-right">
<i
@click="updateSearch()"
class="icon is-right">
<i class="mdi mdi-magnify" />
</span>
class="mdi mdi-magnify"/>
</span>
<!--<b-dropdown-->
<!--position="is-bottom-left">-->
<!--<b-icon-->
<!--class="is-right"-->
<!--slot="trigger"-->
<!--size="is-small"-->
<!--icon="menu-down"/>-->
<!--<b-dropdown-item>-->
<!--<p class="is-left">{{ $i18n.get('advanced_search') }}</p>-->
<!--<b-icon-->
<!--icon="menu-up"-->
<!--class="is-right" />-->
<!--</b-dropdown-item>-->
<!--<b-dropdown-item-->
<!--:custom="true">-->
<!--<advanced-search />-->
<!--</b-dropdown-item>-->
<!--</b-dropdown>-->
</div>
<a @click="toItemsPage">{{ $i18n.get('advanced_search') }}</a>
<a
:style="{color: 'white'}"
@click="toItemsPage">{{ $i18n.get('advanced_search') }}</a>
</div>
<a
class="level-item"
<a
:style="{color: 'white'}"
class="level-item"
:href="wordpressAdmin">
<b-icon icon="wordpress"/>
</a>
@ -45,39 +66,56 @@
<script>
export default {
name: 'TainacanHeader',
data(){
return {
logoHeader: tainacan_plugin.base_url + '/admin/images/tainacan_logo_header.png',
wordpressAdmin: window.location.origin + window.location.pathname.replace('admin.php', ''),
searchQuery: '',
futureSearchQuery: '',
}
},
methods: {
toItemsPage(){
this.$router.push({
path: '/items',
query: {
advancedSearch: true
}
});
import AdvancedSearch from '../advanced-search/advanced-search.vue';
export default {
name: 'TainacanHeader',
data() {
return {
logoHeader: tainacan_plugin.base_url + '/admin/images/tainacan_logo_header.png',
wordpressAdmin: window.location.origin + window.location.pathname.replace('admin.php', ''),
searchQuery: '',
futureSearchQuery: '',
}
},
updateSearch() {
this.$eventBusSearch.setSearchQuery(this.futureSearchQuery);
},
},
props: {
isMenuCompressed: false
components: {
AdvancedSearch,
},
methods: {
toItemsPage() {
if(this.$route.path == '/items') {
this.$root.$emit('openAdvancedSearch', true);
}
if(this.$route.path != '/items') {
this.$router.push({
path: '/items',
query: {
advancedSearch: true
}
});
}
},
updateSearch() {
if (this.$route.path != '/items') {
this.$router.push({
path: '/items',
});
}
this.$eventBusSearch.setSearchQuery(this.futureSearchQuery);
},
},
props: {
isMenuCompressed: false
}
}
}
</script>
<style lang="scss" scoped>
<style lang="scss">
@import "../../scss/_variables.scss";
// Tainacan Header
#tainacan-header {
background-color: $secondary;
@ -85,7 +123,7 @@ export default {
max-height: $header-height;
width: 100%;
padding: 12px;
vertical-align: middle;
vertical-align: middle;
left: 0;
right: 0;
position: absolute;
@ -93,16 +131,16 @@ export default {
color: white;
.level-left {
margin-left: -12px;
margin-left: -12px;
.level-item{
.level-item {
height: $header-height;
width: 180px;
transition: width 0.15s, background-color 0.2s;
-webkit-transition: width 0.15s background-color 0.2s;
-webkit-transition: width 0.15s background-color 0.2s;
cursor: pointer;
background-color: #257787;
&:focus {
box-shadow: none;
}
@ -110,21 +148,18 @@ export default {
max-height: 22px;
padding: 0px 24px;
transition: padding 0.15s;
-webkit-transition: padding linear 0.15s;
-webkit-transition: padding linear 0.15s;
}
}
}
}
.level-right {
padding-right: 12px;
a{
color: white;
}
.search-area {
display: flex;
align-items: center;
margin-right: 36px;
.control {
.control:not(.tnc-advanced-search-container) {
input {
border-width: 0 !important;
height: 27px;
@ -143,9 +178,18 @@ export default {
cursor: pointer;
height: 27px;
font-size: 18px;
width: 30px !important;
}
}
/*.dropdown-content {*/
/*width: 800px !important;*/
/*}*/
/*.dropdown-item:hover {*/
/*background-color: white;*/
/*}*/
a {
margin: 0px 12px;
font-size: 12px;
@ -157,10 +201,10 @@ export default {
width: 220px;
background-color: $secondary;
.tainacan-logo {
padding: 0px 42px;
padding: 0px 42px;
}
}
}
@media screen and (max-width: 769px) {

View File

@ -0,0 +1,43 @@
<template>
<form action="">
<div
class="tainacan-modal-content"
style="width: auto">
<header class="tainacan-modal-title">
<h2>{{ this.$i18n.get('filter') }} <em>{{ title }}</em></h2>
<hr>
</header>
<section class="tainacan-form">
<footer class="field is-grouped form-submit">
<div class="control">
<button
class="button is-outlined"
type="button"
@click="$parent.close()">Close</button>
</div>
<div class="control">
<button class="button is-success">Login</button>
</div>
</footer>
</section>
</div>
</form>
</template>
<script>
export default {
name: 'CheckboxFilterModal',
props: {
title: ''
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -18,7 +18,7 @@
</section>
<footer class="modal-card-foot form-submit">
<button
class="button is-outline"
class="button is-outlined"
type="button"
@click="$parent.close()">
{{ $i18n.get('cancel') }}

View File

@ -3,7 +3,13 @@
<figure
class="file-item"
@click="isPreviewModalActive = true">
<div class="image-wrapper">
<figcaption
:style="{ 'max-width': size != undefined ? size + 'px' : '112px' }"
v-if="showName">{{ file.title.rendered }}</figcaption>
<div
:class="{ 'rounded': showName }"
:style="{ 'width': size != undefined ? size + 'px' : '112px', 'height': size != undefined ? size + 'px' : '112px' }"
class="image-wrapper">
<div
v-if="file.media_type == 'image'"
class="image"
@ -17,7 +23,6 @@
type="is-gray"/>
</div>
</div>
<figcaption v-if="showName">{{ file.title.rendered }}</figcaption>
</figure>
<!-- Preview Modal ----------------- -->
@ -54,6 +59,7 @@ export default {
name: 'FileItem',
props: {
file: Object,
size: 112,
showName: false,
isSelected: false,
isPreviewModalActive: false
@ -92,7 +98,8 @@ export default {
@import "../../scss/_variables.scss";
.file-item {
display: inline-block;
&:hover {
cursor: pointer;
.image, .file-placeholder {
@ -100,14 +107,16 @@ export default {
}
}
.image-wrapper {
height: 112px;
width: 112px;
border-radius: 2px;
overflow: hidden;
position: relative;
display: inline-block;
background-color: $tainacan-input-background;
&.rounded {
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
}
.image {
height: 100%;
width: 100%;
@ -136,12 +145,11 @@ export default {
figcaption {
background-color: $tainacan-input-background;
border-bottom-left-radius: 7px;
border-bottom-right-radius: 7px;
padding: 5px 15px;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
padding: 8px 15px;
font-size: 9px;
margin-top: -4px;
width: 112px;
width: 100%;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;

View File

@ -0,0 +1,88 @@
<template>
<div
class="is-inline-flex"
v-if="filterTags != undefined && filterTags.length > 0">
<b-tag
v-for="(filterTag, index) of filterTags"
:key="index"
attached
closable
@close="removeMetaQuery(filterTag.filterId, filterTag.value, filterTag.singleValue)">
{{ filterTag.singleValue != undefined ? filterTag.singleValue : filterTag.value }}
</b-tag>
<button
@click="clearAllFilters()"
id="button-clear-all"
class="button is-outlined">
{{ $i18n.get('label_clear_filters') }}
</button>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex';
export default {
name: 'FiltersTagsList',
props: {
filters: Array
},
computed: {
filterTags() {
let tags = this.getFilterTags();
let flattenTags = [];
for (let tag of tags) {
if (Array.isArray(tag.value)) {
for (let valueTag of tag.value)
flattenTags.push({filterId: tag.filterId, value: tag, singleValue: valueTag});
} else {
flattenTags.push(tag);
}
}
return flattenTags;
}
},
methods: {
...mapGetters('search',[
'getPostQuery',
'getFilterTags'
]),
...mapActions('metadata',[
'fetchMetadatum'
]),
removeMetaQuery(filterId, value, singleValue) {
if (singleValue != undefined)
this.$eventBusSearch.removeMetaFromFilterTag({ filterId: filterId, singleValue: singleValue });
else
this.$eventBusSearch.removeMetaFromFilterTag({ filterId: filterId, value: value });
},
clearAllFilters() {
// this.$eventBusSearch.clearAllFilters();
for (let tag of this.filterTags) {
this.removeMetaQuery(tag.filterId, tag.value, tag.singleValue);
}
}
}
}
</script>
<style lang="scss" scoped>
@import "../../scss/_variables.scss";
.filter-tags-list {
width: 100%;
padding: 1.5rem $page-side-padding 0px $page-side-padding;
font-size: 0.75rem;
margin-bottom: -0.375rem;
&.is-inline-flex {
flex-wrap: wrap;
justify-content: flex-start;
}
#button-clear-all {
margin-left: auto;
}
}
</style>

View File

@ -97,6 +97,12 @@
:is-full-page="false"
:active.sync="isLoadingItems"/>
<!-- FILTERS TAG LIST-->
<filters-tags-list
class="filter-tags-list"
:filters="filters"
v-if="hasFiltered">Teste</filters-tags-list>
<!-- SEARCH CONTROL ------------------------- -->
<div
v-if="!openAdvancedSearch"
@ -307,36 +313,46 @@
<!-- ADVANCED SEARCH -->
<div
v-if="openAdvancedSearch">
<b-collapse
class="show"
:open="advancedSearchResults ? false : true">
<div
slot="trigger"
slot-scope="props"
class="columns tnc-advanced-search-close">
<div class="column">
<button
@click="openAdvancedSearch = false"
class="button is-white is-pulled-right">
<b-icon
size="is-small"
icon="close"/>
</button>
<button
class="button is-white is-pulled-right">
<span>
{{ props.open ? $i18n.get('hide_advanced_search') : $i18n.get('show_advanced_search') }}
</span>
<b-icon
:style="'margin-left'"
:icon="props.open ? 'menu-down' : 'menu-up'" />
</button>
<div class="columns tnc-advanced-search-close">
<div class="column">
<div class="advanced-search-criteria-title">
<h1>{{ $i18n.get('info_search_criteria') }}</h1>
<div
:style="{'margin-bottom': 'auto'}"
class="field is-grouped is-pulled-right">
<p
v-if="advancedSearchResults"
class="control">
<button
@click="advancedSearchResults = !advancedSearchResults"
class="button is-small is-light">{{ $i18n.get('edit_search') }}</button>
</p>
<p
v-if="advancedSearchResults"
class="control">
<button
@click="isDoSearch = !isDoSearch"
class="button is-small is-secondary">{{ $i18n.get('search') }}</button>
</p>
<p class="control">
<a @click="openAdvancedSearch = false">
{{ $i18n.get('exit') }}
</a>
</p>
</div>
<hr>
</div>
<advanced-search
:is-repository-level="isRepositoryLevel"
:metadata="metadata" />
</b-collapse>
</div>
</div>
<advanced-search
:is-repository-level="isRepositoryLevel"
:advanced-search-results="advancedSearchResults"
:open-form-advanced-search="openFormAdvancedSearch"
:is-do-search="isDoSearch"
:metadata="metadata"/>
</div>
<!-- --------------- -->
@ -489,6 +505,7 @@
<script>
import ItemsList from '../../components/lists/items-list.vue';
import FiltersTagsList from '../../components/search/filters-tags-list.vue';
import FiltersItemsList from '../../components/search/filters-items-list.vue';
import Pagination from '../../components/search/pagination.vue'
import AdvancedSearch from '../../components/advanced-search/advanced-search.vue';
@ -513,7 +530,9 @@
localTableMetadata: [],
registeredViewModes: tainacan_plugin.registered_view_modes,
openAdvancedSearch: false,
openFormAdvancedSearch: false,
advancedSearchResults: false,
isDoSearch: false,
}
},
props: {
@ -558,6 +577,7 @@
},
components: {
ItemsList,
FiltersTagsList,
FiltersItemsList,
Pagination,
AdvancedSearch,
@ -740,7 +760,7 @@
id: undefined,
display: authorNameMetadatumDisplay
});
this.$eventBusSearch.addFetchOnly({
'0': (thumbnailMetadatumDisplay ? 'thumbnail' : null),
'meta': fetchOnlyMetadatumIds,
@ -792,13 +812,12 @@
this.openAdvancedSearch = this.$route.query.advancedSearch;
}
this.$root.$on('openAdvancedSearch', (openAdvancedSearch) => {
this.openAdvancedSearch = openAdvancedSearch;
});
},
mounted() {
if(this.$route.query && this.$route.query.advancedSearch) {
this.openAdvancedSearch = this.$route.query.advancedSearch;
}
this.prepareMetadataAndFilters();
this.localTableMetadata = JSON.parse(JSON.stringify(this.tableMetadata));
@ -811,7 +830,6 @@
this.$eventBusSearch.setInitialViewMode(this.$userPrefs.get(prefsViewMode));
} else {
let prefsAdminViewMode = !this.isRepositoryLevel ? 'admin_view_mode_' + this.collectionId : 'admin_view_mode';
if (this.$userPrefs.get(prefsAdminViewMode) == undefined)
this.$eventBusSearch.setInitialAdminViewMode('table');
else
@ -833,6 +851,23 @@
@import '../../scss/_variables.scss';
.advanced-search-criteria-title {
padding: 0;
h1 {
font-size: 20px;
font-weight: 500;
color: $tertiary;
display: inline-block;
}
hr {
margin: 3px 0px 4px 0px;
height: 1px;
background-color: $secondary;
}
}
.advanced-search-results-title {
padding: 0 $table-side-padding;
@ -843,7 +878,7 @@
display: inline-block;
}
hr{
hr {
margin: 3px 0px 4px 0px;
height: 1px;
background-color: $secondary;
@ -878,7 +913,6 @@
visibility: visible;
display: block;
transition: visibility ease 0.5s, display ease 0.5s;
margin-bottom: -0.1rem;
h3 {
font-size: 100%;

View File

@ -9,86 +9,103 @@
<b-icon :icon="isMetadataColumnCompressed ? 'menu-left' : 'menu-right'" />
</button>
<tainacan-title/>
<div class="columns">
<div class="tainacan-form columns">
<div class="column is-5-5">
<div class="column is-12">
<router-link
class="button is-secondary"
:to="{ path: $routerHelper.getItemEditPath(collectionId, itemId)}">
{{ $i18n.getFrom('items','edit_item') }}
</router-link>
<a
class="button is-success is-pulled-right"
:href="item.url">
{{ $i18n.getFrom('items', 'view_item') }}
</a>
<br>
<br>
<!-- Status -------------------------------- -->
<div class="section-label">
<label>{{ $i18n.get('label_status') }}</label>
</div>
<div>
<p>{{ item.status }}</p>
</div>
<br>
<!-- Document -------------------------------- -->
<div class="section-label">
<label>{{ item.document !== undefined && item.document !== null && item.document !== '' ?
$i18n.get('label_document') : $i18n.get('label_document_empty') }}</label>
</div>
<div class="section-box">
<div
v-if="item.document !== undefined && item.document !== null &&
item.document_type !== undefined && item.document_type !== null &&
item.document !== '' && item.document_type !== 'empty'">
<div class="column is-12">
<div v-if="item.document_type === 'attachment'">
<div v-html="item.document_as_html"/>
</div>
<!-- Document -------------------------------- -->
<div class="section-label">
<label>{{ item.document !== undefined && item.document !== null && item.document !== '' ?
$i18n.get('label_document') : $i18n.get('label_document_empty') }}</label>
</div>
<div class="section-box">
<div
v-if="item.document !== undefined && item.document !== null &&
item.document_type !== undefined && item.document_type !== null &&
item.document !== '' && item.document_type !== 'empty'">
<div v-else-if="item.document_type === 'text'">
<div v-html="item.document_as_html"/>
</div>
<div v-if="item.document_type === 'attachment'">
<div v-html="item.document_as_html"/>
</div>
<div v-else-if="item.document_type === 'text'">
<div v-html="item.document_as_html"/>
</div>
<div v-else-if="item.document_type === 'url'">
<div v-html="item.document_as_html"/>
</div>
<div v-else-if="item.document_type === 'url'">
<div v-html="item.document_as_html"/>
</div>
</div>
</div>
<div class="column is-12">
<!-- Attachments ------------------------------------------ -->
<div class="section-label">
<label>{{ $i18n.get('label_attachments') }}</label>
</div>
<div class="section-box section-attachments">
<div class="uploaded-files">
<file-item
:style="{ margin: 15 + 'px'}"
v-if="attachmentsList.length > 0"
v-for="(attachment, index) in attachmentsList"
:key="index"
:show-name="true"
:file="attachment"/>
<p v-if="attachmentsList.length <= 0"><br>{{ $i18n.get('info_no_attachments_on_item_yet') }}</p>
</div>
<!-- Thumbnail -------------------------------- -->
<div class="section-label">
<label>{{ $i18n.get('label_thumbnail') }}</label>
</div>
<div class="section-box section-thumbnail">
<div class="thumbnail-field">
<file-item
v-if="item.thumbnail != undefined && item.thumbnail.thumb != undefined && item.thumbnail.thumb != false"
:show-name="false"
:size="178"
:file="{
media_type: 'image',
guid: { rendered: item.thumbnail.thumb },
title: { rendered: $i18n.get('label_thumbnail')},
description: { rendered: `<img alt='Thumbnail' src='` + item.thumbnail.full + `'/>` }}"/>
<figure
v-if="item.thumbnail == undefined || item.thumbnail.thumb == undefined || item.thumbnail.thumb == false"
class="image">
<span class="image-placeholder">{{ $i18n.get('label_empty_thumbnail') }}</span>
<img
:alt="$i18n.get('label_thumbnail')"
:src="thumbPlaceholderPath">
</figure>
</div>
</div>
<!-- Attachments ------------------------------------------ -->
<div class="section-label">
<label>{{ $i18n.get('label_attachments') }}</label>
</div>
<div class="section-box section-attachments">
<div class="uploaded-files">
<file-item
:style="{ margin: 15 + 'px'}"
v-if="attachmentsList.length > 0"
v-for="(attachment, index) in attachmentsList"
:key="index"
:show-name="true"
:file="attachment"/>
<p v-if="attachmentsList.length <= 0"><br>{{ $i18n.get('info_no_attachments_on_item_yet') }}</p>
</div>
</div>
</div>
<div
v-show="!isMetadataColumnCompressed"
class="column is-4-5">
<!-- Visibility (status public or private) -------------------------------- -->
<div class="section-label">
<label>{{ $i18n.get('label_visibility') }}</label>
<span class="required-metadatum-asterisk">*</span>
</div>
<div class="section-status">
<div class="field has-addons">
<span v-if="item.status != 'private'">
<span class="icon">
<i class="mdi mdi-earth"/>
</span> {{ $i18n.get('publish_visibility') }}
</span>
<span v-if="item.status == 'private'">
<span class="icon">
<i class="mdi mdi-lock"/>
</span> {{ $i18n.get('private_visibility') }}
</span>
</div>
</div>
<!-- Metadata -------------------------------- -->
<label class="section-label">{{ $i18n.get('metadata') }}</label>
<br>
<a
@ -99,8 +116,6 @@
type="is-secondary"
:icon=" open ? 'menu-down' : 'menu-right'"/>
</a>
<!-- Metadata -------------------------------- -->
<div>
<div
v-for="(metadatum, index) of metadatumList"
@ -132,6 +147,20 @@
</div>
</div>
</div>
<div class="footer">
<div class="form-submission-footer">
<router-link
class="button is-secondary"
:to="{ path: $routerHelper.getItemEditPath(collectionId, itemId)}">
{{ $i18n.getFrom('items','edit_item') }}
</router-link>
<a
class="button is-success is-pulled-right"
:href="item.url">
{{ $i18n.getFrom('items', 'view_item') }}
</a>
</div>
</div>
</div>
</template>
@ -228,6 +257,10 @@
}
}
.page-container-shrinked {
height: calc(100% - 132px) !important; // Bigger than the others due footer's height
}
.page-container {
padding: 25px 0px;
@ -236,21 +269,33 @@
padding-right: $page-side-padding;
}
.column {
padding-top: 0px;
padding-bottom: 0px;
}
.column.is-5-5 {
width: 45.833333333%;
padding-left: $page-side-padding;
padding-right: $page-side-padding;
transition: width 0.6s;
@media screen and (max-width: 769px) {
width: 100%;
}
}
.column.is-4-5 {
width: 37.5%;
padding-left: $page-side-padding;
padding-right: $page-side-padding;
transition: all 0.6s;
.field {
padding: 10px 0px 10px 30px;
.collapse .collapse-content {
margin-left: 30px;
}
}
@media screen and (max-width: 769px) {
width: 100%;
}
}
}
@ -288,8 +333,9 @@
}
.section-box {
border: 1px solid $draggable-border-color;
padding: 30px;
background-color: white;
padding: 26px;
margin-top: 16px;
margin-bottom: 38px;
@ -318,19 +364,24 @@
}
}
.section-status{
width: 174px;
}
.section-thumbnail {
width: 174px;
padding-top: 0;
padding-bottom: 0;
padding-bottom: 16px;
font-size: 0.75rem;
.field {
border-bottom: none;
.icon {
font-size: 18px !important;
color: $gray;
}
}
}
.section-attachments {
border: 1px solid $draggable-border-color;
height: 250px;
max-width: 100%;
resize: vertical;
overflow: auto;
padding: 15px;
p { margin: 4px 15px }
}
@ -341,5 +392,55 @@
margin-left: -15px;
margin-right: -15px;
}
.thumbnail-field {
.content {
padding: 10px;
font-size: 0.8em;
}
img {
height: 178px;
width: 178px;
}
.image-placeholder {
position: absolute;
margin-left: 45px;
margin-right: 45px;
font-size: 0.8rem;
font-weight: bold;
z-index: 99;
text-align: center;
color: gray;
top: 70px;
max-width: 90px;
}
}
.footer {
padding: 24px $page-side-padding;
position: absolute;
bottom: 0;
z-index: 999999;
background-color: white;
border-top: 2px solid $secondary;
width: 100%;
.form-submission-footer {
width: 100%;
display: flex;
justify-content: end;
.button {
margin-left: 6px;
margin-right: 6px;
}
.button.is-outlined {
margin-left: 0px;
margin-right: auto;
}
}
}
</style>

View File

@ -28,7 +28,7 @@
}
&.is-outlined {
color: #150e38 !important;
background-color: white;
background-color: white !important;
border-color: $gray-light !important;
}
&:focus {

View File

@ -0,0 +1,18 @@
.notices .toast {
font-size: 0.75rem;
border-radius: 8px;
box-shadow: none;
&.is-dark {
background-color: $tainacan-input-background;
color: $gray-light;
}
&.is-warning {
background-color: #e7dede;
color: $danger;
}
&.is-success {
background-color: #d6feed;
color: $success;
}
}

View File

@ -1,16 +1,23 @@
.tags {
border: solid 1px $tainacan-input-background !important;
border-radius: 20px;
flex-wrap: nowrap;
margin-bottom: 0.375rem !important;
margin-right: 0.375rem;
max-width: 100%;
overflow: hidden;
&:hover{
background-color: $tainacan-input-background;
}
.tag {
background: none !important;
background-color: white;
margin-bottom: 0 !important;
}
&:last-child {
margin-bottom: 0;
max-width: calc(100% - 21px);
justify-content: flex-start;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}

View File

@ -21,6 +21,7 @@
@import "../scss/_pagination.scss";
@import "../scss/_modals.scss";
@import "../scss/_tags.scss";
@import "../scss/_notices.scss";
// Clears wordpress content
body.tainacan-admin-page #adminmenumain, body.tainacan-admin-page #wpfooter, body.tainacan-admin-page #wp-auth-check-wrap {

View File

@ -1,18 +1,19 @@
<?php
return apply_filters('tainacan-admin-i18n',[
return apply_filters( 'tainacan-admin-i18n', [
// Advanced search comparators
'is_equal_to' => __( 'Equal', 'tainacan' ),
'is_not_equal_to' => __( 'Not equal', 'tainacan'),
'contains' => __( 'Contains', 'tainacan'),
'not_contains' => __( 'Not contains', 'tainacan' ),
'greater_than' => __( 'Greater than', 'tainacan' ),
'less_than' => __( 'Less than', 'tainacan' ),
'greater_than_or_equal_to' => __( 'Greater than or equal to', 'tainacan' ),
'less_than_or_equal_to' => __( 'Less than or equal to', 'tainacan' ),
'is_equal_to' => __( 'Equal', 'tainacan' ),
'is_not_equal_to' => __( 'Not equal', 'tainacan' ),
'contains' => __( 'Contains', 'tainacan' ),
'not_contains' => __( 'Not contains', 'tainacan' ),
'greater_than' => __( 'Greater than', 'tainacan' ),
'less_than' => __( 'Less than', 'tainacan' ),
'greater_than_or_equal_to' => __( 'Greater than or equal to', 'tainacan' ),
'less_than_or_equal_to' => __( 'Less than or equal to', 'tainacan' ),
// Tainacan common terms
<<<<<<< HEAD
'repository' => __( 'Repository', 'tainacan' ),
'collections' => __( 'Collections', 'tainacan' ),
'items' => __( 'Items', 'tainacan' ),
@ -31,122 +32,145 @@ return apply_filters('tainacan-admin-i18n',[
'mapping' => __( 'Mapping', 'tainacan' ),
'metadata' => __( 'metadata', 'tainacan' ),
'importers' => __( 'Importers', 'tainacan' ),
=======
'repository' => __( 'Repository', 'tainacan' ),
'collections' => __( 'Collections', 'tainacan' ),
'items' => __( 'Items', 'tainacan' ),
'metadata' => __( 'Metadata', 'tainacan' ),
'filters' => __( 'Filters', 'tainacan' ),
'taxonomies' => __( 'Taxonomies', 'tainacan' ),
'events' => __( 'Events', 'tainacan' ),
'collection' => __( 'Collection', 'tainacan' ),
'item' => __( 'Item', 'tainacan' ),
'metadatum' => __( 'Metadata', 'tainacan' ),
'filter' => __( 'Filter', 'tainacan' ),
'taxonomy' => __( 'Taxonomia', 'tainacan' ),
'event' => __( 'Event', 'tainacan' ),
'term' => __( 'Term', 'tainacan' ),
'terms' => __( 'Terms', 'tainacan' ),
'mapping' => __( 'Mapping', 'tainacan' ),
'importers' => __( 'Importers', 'tainacan' ),
>>>>>>> origin/develop
// Actions
'edit' => __( 'Edit', 'tainacan' ),
'settings' => __( 'Settings', 'tainacan' ),
'new' => __( 'New', 'tainacan' ),
'add' => __( 'Add', 'tainacan' ),
'import' => __( 'Import', 'tainacan' ),
'export' => __( 'Export', 'tainacan' ),
'cancel' => __( 'Cancel', 'tainacan' ),
'remove' => __( 'Remove', 'tainacan' ),
'save' => __( 'Save', 'tainacan' ),
'next' => __( 'Next', 'tainacan' ),
'back' => __( 'Back', 'tainacan' ),
'see' => __( 'View', 'tainacan' ),
'search' => __( 'Search', 'tainacan' ),
'advanced_search' => __( 'Advanced Search', 'tainacan' ),
'continue' => __( 'Continue', 'tainacan' ),
'approve_item' => __( 'Approve', 'tainacan' ),
'not_approve_item' => __( 'Not approve', 'tainacan' ),
'add_one_item' => __( 'Add one item', 'tainacan' ),
'add_items_bulk' => __( 'Add items in bulk', 'tainacan' ),
'add_items_external_source' => __( 'Add items from an external source', 'tainacan' ),
'new_mapped_item' => __( 'New mapped collection', 'tainacan' ),
'new_blank_collection' => __( 'New Blank Collection', 'tainacan' ),
'split' => __( 'Split', 'tainacan' ),
'unified' => __( 'Unified', 'tainacan' ),
'add_another_search_criteria' => __( 'Add another search criteria', 'tainacan' ),
'clear_search' => __( 'Clear search', 'tainacan' ),
'run' => __( 'Run', 'tainacan' ),
'show_advanced_search' => __( 'Show advanced search', 'tainacan'),
'hide_advanced_search' => __( 'Hide advanced search', 'tainacan'),
'edit' => __( 'Edit', 'tainacan' ),
'settings' => __( 'Settings', 'tainacan' ),
'new' => __( 'New', 'tainacan' ),
'add' => __( 'Add', 'tainacan' ),
'import' => __( 'Import', 'tainacan' ),
'export' => __( 'Export', 'tainacan' ),
'cancel' => __( 'Cancel', 'tainacan' ),
'remove' => __( 'Remove', 'tainacan' ),
'save' => __( 'Save', 'tainacan' ),
'next' => __( 'Next', 'tainacan' ),
'back' => __( 'Back', 'tainacan' ),
'see' => __( 'View', 'tainacan' ),
'search' => __( 'Search', 'tainacan' ),
'advanced_search' => __( 'Advanced Search', 'tainacan' ),
'continue' => __( 'Continue', 'tainacan' ),
'approve_item' => __( 'Approve', 'tainacan' ),
'not_approve_item' => __( 'Not approve', 'tainacan' ),
'add_one_item' => __( 'Add one item', 'tainacan' ),
'add_items_bulk' => __( 'Add items in bulk', 'tainacan' ),
'add_items_external_source' => __( 'Add items from an external source', 'tainacan' ),
'new_mapped_item' => __( 'New mapped collection', 'tainacan' ),
'new_blank_collection' => __( 'New Blank Collection', 'tainacan' ),
'split' => __( 'Split', 'tainacan' ),
'unified' => __( 'Unified', 'tainacan' ),
'add_another_search_criterion' => __( 'Add another search criterion', 'tainacan' ),
'clear_search' => __( 'Clear search', 'tainacan' ),
'run' => __( 'Run', 'tainacan' ),
'edit_search' => __( 'Edit search', 'tainacan' ),
'exit' => __( 'Exit', 'tainacan' ),
// Wordpress Status
'publish' => __( 'Publish', 'tainacan' ),
'draft' => __( 'Draft', 'tainacan' ),
'private' => __( 'Private', 'tainacan' ),
'trash' => __( 'Trash', 'tainacan' ),
'auto-draft' => __( 'Automatic Draft', 'tainacan' ),
'publish_visibility' => __( 'Visible to everyone', 'tainacan' ),
'private_visibility' => __( 'Visible only for editors', 'tainacan' ),
'publish' => __( 'Publish', 'tainacan' ),
'draft' => __( 'Draft', 'tainacan' ),
'private' => __( 'Private', 'tainacan' ),
'trash' => __( 'Trash', 'tainacan' ),
'auto-draft' => __( 'Automatic Draft', 'tainacan' ),
'publish_visibility' => __( 'Visible to everyone', 'tainacan' ),
'private_visibility' => __( 'Visible only for editors', 'tainacan' ),
// Page Titles (used mainly on Router)
'title_repository_collections_page' => __( 'Repository Collections', 'tainacan' ),
'title_items_page' => __( 'Items', 'tainacan' ),
'title_repository_metadata_page' => __( 'Repository Metadata', 'tainacan' ),
'title_repository_filters_page' => __( 'Repository Filters', 'tainacan' ),
'title_taxonomies_page' => __( 'Taxonomies Page', 'tainacan' ),
'title_terms_page' => __( 'Terms', 'tainacan' ),
'title_repository_events_page' => __( 'Repository Events', 'tainacan' ),
'title_collection_page' => __( 'Collection', 'tainacan' ),
'title_item_page' => __( 'Item', 'tainacan' ),
'title_metadatum_page' => __( 'Metadata', 'tainacan' ),
'title_collection_events' => __( 'Collection Events', 'tainacan' ),
'title_filter_page' => __( 'Filter', 'tainacan' ),
'title_taxonomy_page' => __( 'Taxonomy', 'tainacan' ),
'title_term_edition' => __( 'Term edition', 'tainacan' ),
'title_event_page' => __( 'Event', 'tainacan' ),
'title_create_collection' => __( 'Collection Creation', 'tainacan' ),
'title_create_taxonomy_page' => __( 'Taxonomy Creation', 'tainacan' ),
'title_create_item_collection' => __( 'Create Item on Collection', 'tainacan' ),
'title_create_filter' => __( 'Filter Creation', 'tainacan' ),
'title_collection_settings' => __( 'Settings of Collection', 'tainacan' ),
'title_edit_item' => __( 'Edit Item', 'tainacan' ),
'title_taxonomy_edition_page' => __( 'Taxonomy Edition', 'tainacan' ),
'title_filter_edition' => __( 'Filter Edition', 'tainacan' ),
'title_metadatum_edition' => __( 'Metadata Edition', 'tainacan' ),
'title_collection_metadata_edition' => __( 'Edit Metadata of', 'tainacan' ),
'title_collection_filters_edition' => __( 'Edit Filters of', 'tainacan' ),
'title_importer_page' => __( 'Importer', 'tainacan' ),
'title_importers_page' => __( 'Importers', 'tainacan' ),
'title_export_collection_page' => __( 'Export Collection Page', 'tainacan' ),
'title_export_item_page' => __( 'Export Item Page', 'tainacan' ),
'title_export_page' => __( 'Export Page', 'tainacan' ),
'title_repository_collections_page' => __( 'Repository Collections', 'tainacan' ),
'title_items_page' => __( 'Items', 'tainacan' ),
'title_repository_metadata_page' => __( 'Repository Metadata', 'tainacan' ),
'title_repository_filters_page' => __( 'Repository Filters', 'tainacan' ),
'title_taxonomies_page' => __( 'Taxonomies Page', 'tainacan' ),
'title_terms_page' => __( 'Terms', 'tainacan' ),
'title_repository_events_page' => __( 'Repository Events', 'tainacan' ),
'title_collection_page' => __( 'Collection', 'tainacan' ),
'title_item_page' => __( 'Item', 'tainacan' ),
'title_metadatum_page' => __( 'Metadata', 'tainacan' ),
'title_collection_events' => __( 'Collection Events', 'tainacan' ),
'title_filter_page' => __( 'Filter', 'tainacan' ),
'title_taxonomy_page' => __( 'Taxonomy', 'tainacan' ),
'title_term_edition' => __( 'Term edition', 'tainacan' ),
'title_event_page' => __( 'Event', 'tainacan' ),
'title_create_collection' => __( 'Collection Creation', 'tainacan' ),
'title_create_taxonomy_page' => __( 'Taxonomy Creation', 'tainacan' ),
'title_create_item_collection' => __( 'Create Item on Collection', 'tainacan' ),
'title_create_filter' => __( 'Filter Creation', 'tainacan' ),
'title_collection_settings' => __( 'Settings of Collection', 'tainacan' ),
'title_edit_item' => __( 'Edit Item', 'tainacan' ),
'title_taxonomy_edition_page' => __( 'Taxonomy Edition', 'tainacan' ),
'title_filter_edition' => __( 'Filter Edition', 'tainacan' ),
'title_metadatum_edition' => __( 'Metadata Edition', 'tainacan' ),
'title_collection_metadata_edition' => __( 'Edit Metadata of', 'tainacan' ),
'title_collection_filters_edition' => __( 'Edit Filters of', 'tainacan' ),
'title_importer_page' => __( 'Importer', 'tainacan' ),
'title_importers_page' => __( 'Importers', 'tainacan' ),
'title_export_collection_page' => __( 'Export Collection Page', 'tainacan' ),
'title_export_item_page' => __( 'Export Item Page', 'tainacan' ),
'title_export_page' => __( 'Export Page', 'tainacan' ),
// Labels (used mainly on Aria Labels and Inputs)
'label_clean' => __( 'Clear', 'tainacan' ),
'label_selected' => __( 'Selected', 'tainacan' ),
'label_relationship_new_search' => __( 'New Search', 'tainacan' ),
'label_relationship_items_found' => __( 'Items found', 'tainacan' ),
'label_menu' => __( 'Menu', 'tainacan' ),
'label_main_menu' => __( 'Main Menu', 'tainacan' ),
'label_collection_menu' => __( 'Collection Menu', 'tainacan' ),
'label_title' => __( 'Title', 'tainacan' ),
'label_settings' => __( 'Settings', 'tainacan' ),
'label_actions' => __( 'Actions', 'tainacan' ),
'label_name' => __( 'Name', 'tainacan' ),
'label_description' => __( 'Description', 'tainacan' ),
'label_status' => __( 'Status', 'tainacan' ),
'label_slug' => __( 'Slug', 'tainacan' ),
'label_image' => __( 'Image', 'tainacan' ),
'label_thumbnail' => __( 'Thumbnail', 'tainacan' ),
'label_empty_thumbnail' => __( 'Empty Thumbnail', 'tainacan' ),
'label_moderators' => __( 'Moderators', 'tainacan' ),
'label_parent_collection' => __( 'Parent collection', 'tainacan' ),
'label_no_parent_collection' => __( 'No parent collection', 'tainacan' ),
'label_button_view' => __( 'Button View', 'tainacan' ),
'label_button_edit' => __( 'Button Edit', 'tainacan' ),
'label_button_delete' => __( 'Button Delete', 'tainacan' ),
'label_button_delete_header_image' => __( 'Button Delete Header Image', 'tainacan' ),
'label_button_edit_thumb' => __( 'Button Edit Thumbnail', 'tainacan' ),
'label_button_edit_header_image' => __( 'Button Edit Header Image', 'tainacan' ),
'label_choose_thumb' => __( 'Choose Thumbnail', 'tainacan' ),
'label_button_delete_thumb' => __( 'Button Delete Thumbnail', 'tainacan' ),
'label_collections_per_page' => __( 'Collections per Page:', 'tainacan' ),
'label_taxonomies_per_page' => __( 'Taxonomies per Page:', 'tainacan' ),
'label_events_per_page' => __( 'Events per Page:', 'tainacan' ),
'label_items_per_page' => __( 'Items per Page:', 'tainacan' ),
'label_clean' => __( 'Clear', 'tainacan' ),
'label_clear_filters' => __( 'Clear filters', 'tainacan' ),
'label_selected' => __( 'Selected', 'tainacan' ),
'label_relationship_new_search' => __( 'New Search', 'tainacan' ),
'label_relationship_items_found' => __( 'Items found', 'tainacan' ),
'label_menu' => __( 'Menu', 'tainacan' ),
'label_main_menu' => __( 'Main Menu', 'tainacan' ),
'label_collection_menu' => __( 'Collection Menu', 'tainacan' ),
'label_title' => __( 'Title', 'tainacan' ),
'label_settings' => __( 'Settings', 'tainacan' ),
'label_actions' => __( 'Actions', 'tainacan' ),
'label_name' => __( 'Name', 'tainacan' ),
'label_description' => __( 'Description', 'tainacan' ),
'label_status' => __( 'Status', 'tainacan' ),
'label_slug' => __( 'Slug', 'tainacan' ),
'label_image' => __( 'Image', 'tainacan' ),
'label_thumbnail' => __( 'Thumbnail', 'tainacan' ),
'label_empty_thumbnail' => __( 'Empty Thumbnail', 'tainacan' ),
'label_moderators' => __( 'Moderators', 'tainacan' ),
'label_parent_collection' => __( 'Parent collection', 'tainacan' ),
'label_no_parent_collection' => __( 'No parent collection', 'tainacan' ),
'label_button_view' => __( 'Button View', 'tainacan' ),
'label_button_edit' => __( 'Button Edit', 'tainacan' ),
'label_button_delete' => __( 'Button Delete', 'tainacan' ),
'label_button_delete_header_image' => __( 'Button Delete Header Image', 'tainacan' ),
'label_button_edit_thumb' => __( 'Button Edit Thumbnail', 'tainacan' ),
'label_button_edit_header_image' => __( 'Button Edit Header Image', 'tainacan' ),
'label_button_edit_document' => __( 'Button Edit Document', 'tainacan' ),
'label_button_delete_document' => __( 'Button Delete Document', 'tainacan' ),
'label_choose_thumb' => __( 'Choose Thumbnail', 'tainacan' ),
'label_button_delete_thumb' => __( 'Button Delete Thumbnail', 'tainacan' ),
'label_collections_per_page' => __( 'Collections per Page:', 'tainacan' ),
'label_taxonomies_per_page' => __( 'Taxonomies per Page:', 'tainacan' ),
'label_events_per_page' => __( 'Events per Page:', 'tainacan' ),
'label_items_per_page' => __( 'Items per Page:', 'tainacan' ),
'label_active_metadata' => __( 'Active Metadata', 'tainacan' ),
'label_available_metadata' => __( 'Available Metadata', 'tainacan' ),
'label_available_metadata_types' => __( 'Available Metadata Types', 'tainacan' ),
'label_active_filters' => __( 'Active Filters', 'tainacan' ),
'label_filter_type' => __( 'Filter Type', 'tainacan' ),
'label_available_filters' => __( 'Available Filters', 'tainacan' ),
'label_available_filter_types' => __( 'Available Filter Types', 'tainacan' ),
'label_per_page' => __( 'per Page', 'tainacan' ),
'label_available_metadata_types' => __( 'Available Metadata Types', 'tainacan' ),
'label_active_filters' => __( 'Active Filters', 'tainacan' ),
'label_filter_type' => __( 'Filter Type', 'tainacan' ),
'label_available_filters' => __( 'Available Filters', 'tainacan' ),
'label_available_filter_types' => __( 'Available Filter Types', 'tainacan' ),
'label_per_page' => __( 'per Page', 'tainacan' ),
'label_displayed_metadata' => __( 'Displayed metadata', 'tainacan' ),
<<<<<<< HEAD
'label_required' => __( 'Required', 'tainacan' ),
'label_allow_multiple' => __( 'Allow multiple values', 'tainacan' ),
'label_default_value' => __( 'Default value', 'tainacan' ),
@ -245,6 +269,115 @@ return apply_filters('tainacan-admin-i18n',[
'label_remove_value' => __( 'Remove value', 'tainacan' ),
'label_create_new_page' => __( 'Create new page', 'tainacan' ),
'label_total_items' => __( 'Total items', 'tainacan' ),
=======
'label_required' => __( 'Required', 'tainacan' ),
'label_allow_multiple' => __( 'Allow multiple values', 'tainacan' ),
'label_default_value' => __( 'Default value', 'tainacan' ),
'label_unique_value' => __( 'Unique value', 'tainacan' ),
'label_yes' => __( 'Yes', 'tainacan' ),
'label_no' => __( 'No', 'tainacan' ),
'label_approved' => __( 'Approved', 'tainacan' ),
'label_collection_related' => __( 'Collection Related', 'tainacan' ),
'label_metadata_for_search' => __( 'Metadata for search', 'tainacan' ),
'label_allow_repeated_items' => __( 'Allow repeated items', 'tainacan' ),
'label_select_taxonomy' => __( 'Select taxonomy', 'tainacan' ),
'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_attachments' => __( 'Attachments', 'tainacan' ),
'label_attachment' => __( 'Attachment', 'tainacan' ),
'label_enabled' => __( 'Enabled', 'tainacan' ),
'label_disabled' => __( 'Disabled', 'tainacan' ),
'label_creation' => __( 'Creation', 'tainacan' ),
'label_creation_date' => __( 'Creation date', 'tainacan' ),
'label_collection_items' => __( 'Collection Items', 'tainacan' ),
'label_collection_metadata' => __( 'Collection Metadata', 'tainacan' ),
'label_collection_filters' => __( 'Collection Filters', 'tainacan' ),
'label_parent_term' => __( 'Parent Term', 'tainacan' ),
'label_new_term' => __( 'New Term', 'tainacan' ),
'label_new_child' => __( 'New Child', 'tainacan' ),
'label_taxonomy_terms' => __( 'Taxonomy Terms', 'tainacan' ),
'label_no_parent_term' => __( 'No parent term', 'tainacan' ),
'label_term_without_name' => __( 'Term without name', 'tainacan' ),
'label_inherited' => __( 'Inherited', 'tainacan' ),
'label_sorting' => __( 'Sorting', 'tainacan' ),
'label_event_date' => __( 'Event date', 'tainacan' ),
'label_event_title' => __( 'Event', 'tainacan' ),
'label_header_image' => __( 'Header Image', 'tainacan' ),
'label_empty_header_image' => __( 'Empty Header Image', 'tainacan' ),
'label_enable_cover_page' => __( 'Enable Cover Page', 'tainacan' ),
'label_cover_page' => __( 'Cover Page', 'tainacan' ),
'label_default_displayed_metadata' => __( 'Default Displayed Metadata', 'tainacan' ),
'label_display' => __( 'Display on Listing', 'tainacan' ),
'label_display_default' => __( 'Display by default', 'tainacan' ),
'label_display_never' => __( 'Never displayed', 'tainacan' ),
'label_not_display' => __( 'Not display by default', 'tainacan' ),
'label_attach_to_item' => __( 'Attach to item', 'tainacan' ),
'label_document' => __( 'Document', 'tainacan' ),
'label_document_empty' => __( 'Empty document', 'tainacan' ),
'label_file' => __( 'File', 'tainacan' ),
'label_text' => __( 'Text', 'tainacan' ),
'label_url' => __( 'URL', 'tainacan' ),
'label_select_file' => __( 'Select File', 'tainacan' ),
'label_expand_all' => __( 'Expand all', 'tainacan' ),
'label_collapse_all' => __( 'Collapse all', 'tainacan' ),
'label_view_term' => __( 'View Term', 'tainacan' ),
'label_all_items' => __( 'All items', 'tainacan' ),
'label_draft_items' => __( 'Draft', 'tainacan' ),
'label_trash_items' => __( 'Trash', 'tainacan' ),
'label_bulk_actions' => __( 'Bulk actions', 'tainacan' ),
'label_delete_selected_collections' => __( 'Delete selected collections', 'tainacan' ),
'label_edit_selected_collections' => __( 'Edit selected collections', 'tainacan' ),
'label_delete_permanently' => __( 'Delete permanently', 'tainacan' ),
'label_send_to_trash' => __( 'Send to trash', 'tainacan' ),
'label_delete_selected_taxonomies' => __( 'Delete selected taxonomies', 'tainacan' ),
'label_edit_selected_items' => __( 'Edit selected items', 'tainacan' ),
'label_edit_selected_taxonomies' => __( 'Edit selected taxonomies', 'tainacan' ),
'label_select_all_collections_page' => __( 'Select all collections on page', 'tainacan' ),
'label_select_all_items_page' => __( 'Select all items on page', 'tainacan' ),
'label_select_all_taxonomies_page' => __( 'Select all taxonomies on page', 'tainacan' ),
'label_edit_attachments' => __( 'Edit attachments', 'tainacan' ),
'label_blank_collection' => __( 'Blank collection', 'tainacan' ),
'label_dublin_core' => __( 'Dublin Core', 'tainacan' ),
'label_created_by' => __( 'Created by', 'tainacan' ),
'label_apply_changes' => __( 'Apply changes', 'tainacan' ),
'label_view_mode' => __( 'View mode', 'tainacan' ),
'label_default_view_mode' => __( 'Default view mode', 'tainacan' ),
'label_enabled_view_modes' => __( 'Enabled view modes', 'tainacan' ),
'label_view_modes_available' => __( 'View modes available on theme', 'tainacan' ),
'label_warning' => __( 'Warning', 'tainacan' ),
'label_error' => __( 'Erro', 'tainacan' ),
'label_grid' => __( 'Grid', 'tainacan' ),
'label_table' => __( 'Table', 'tainacan' ),
'label_cards' => __( 'Cards', 'tainacan' ),
'label_records' => __( 'Records', 'tainacan' ),
'label_visualization' => __( 'Visualization', 'tainacan' ),
'label_available_importers' => __( 'Available Importers', 'tainacan' ),
'label_target_collection' => __( 'Target Collection', 'tainacan' ),
'label_source_file' => __( 'Source file', 'tainacan' ),
'label_url_source_link' => __( 'URL Source link', 'tainacan' ),
'label_metadata_mapping' => __( 'Metadata mapping', 'tainacan' ),
'label_select_metadatum' => __( 'Select metadatum', 'tainacan' ),
'label_select_metadatum_type' => __( 'Select a metadatum type', 'tainacan' ),
'label_add_more_metadata' => __( 'Add more metadata', 'tainacan' ),
'label_from_source_collection' => __( 'From source collection', 'tainacan' ),
'label_to_target_collection' => __( 'To target collection', 'tainacan' ),
'label_add_value' => __( 'Add value', 'tainacan' ),
'label_remove_value' => __( 'Remove value', 'tainacan' ),
'label_create_new_page' => __( 'Create new page', 'tainacan' ),
'label_total_items' => __( 'Total items', 'tainacan' ),
'label_see_more' => __( 'See more', 'tainacan' ),
'label_until' => __( 'until', 'tainacan' ),
'label_visibility' => __( 'Visibility', 'tainacan' ),
'label_discart' => __( 'Discart', 'tainacan' ),
'label_save_as_draft' => __( 'Save as draft', 'tainacan' ),
'label_update_draft' => __( 'Update draft', 'tainacan' ),
'label_return_to_draft' => __( 'Return to draft', 'tainacan' ),
'label_publish' => __( 'Publish', 'tainacan' ),
'label_send_to_trash' => __( 'Send to trash', 'tainacan' ),
'label_update' => __( 'Update', 'tainacan' ),
>>>>>>> origin/develop
// Instructions. More complex sentences to guide user and placeholders
'instruction_delete_selected_collections' => __( 'Delete selected collections', 'tainacan' ),
@ -254,15 +387,17 @@ return apply_filters('tainacan-admin-i18n',[
'instruction_select_a_status' => __( 'Select a status:', 'tainacan' ),
'instruction_select_a_filter_type' => __( 'Select a filter type:', 'tainacan' ),
'instruction_select_a_parent_term' => __( 'Select a parent term:', 'tainacan' ),
'instruction_cover_page' => __( 'Type to search a Page to choose.', 'tainacan'),
'instruction_moderators' => __( 'Type to search a User to add.', 'tainacan'),
'instruction_select_a_parent_collection' => __( 'Select a parent colection.', 'tainacan' ),
'instruction_select_collection_thumbnail' => __( 'Select a thumbnail image for collection', 'tainacan' ),
'instruction_select_item_thumbnail' => __( 'Select a thumbnail image for item', '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_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' ),
'instruction_select_collection_header_image' => __( 'Select a header image for collection', 'tainacan' ),
'instruction_select_term_header_image' => __( 'Select a header image for term', 'tainacan' ),
'instruction_select_term_header_image' => __( 'Select a header image for term', 'tainacan' ),
'instruction_select_files_to_attach_to_item' => __( 'Select files to attach to item', 'tainacan' ),
'instruction_select_document_file_for_item' => __( 'Select a document file for item', 'tainacan' ),
<<<<<<< HEAD
'instruction_insert_url' => __( 'Insert URL', 'tainacan' ),
'instruction_write_text' => __( 'Write Text', 'tainacan' ),
'instruction_search' => __( 'Search', 'tainacan' ),
@ -270,106 +405,120 @@ return apply_filters('tainacan-admin-i18n',[
'instruction_select_a_mapper' => __( 'Select a mapper', 'tainacan' ),
'instruction_search_on_repository' => __( 'Search on repository', 'tainacan' ),
'instruction_select_a_target_collection' => __( 'Select a target collection', 'tainacan' ),
=======
'instruction_insert_url' => __( 'Insert URL', 'tainacan' ),
'instruction_write_text' => __( 'Write Text', 'tainacan' ),
'instruction_search' => __( 'Search', 'tainacan' ),
'instruction_search_in_repository' => __( 'Search in repository', 'tainacan' ),
'instruction_select_a_target_collection' => __( 'Select a target collection', 'tainacan' ),
>>>>>>> origin/develop
'instruction_select_an_importer_type' => __( 'Select an importer type from the options above:', 'tainacan' ),
'instruction_drop_file_or_click_to_upload' => __( 'Drop your source file or click here to upload.', 'tainacan' ),
'instruction_select_metadatum_type' => __( 'Select a metadatum type.', 'tainacan' ),
'instruction_configure_new_metadatum' => __( 'Configure new metadatum.', 'tainacan' ),
'instruction_drop_file_or_click_to_upload' => __( 'Drop your source file or click here to upload.', 'tainacan' ),
'instruction_select_metadatum_type' => __( 'Select a metadatum type.', 'tainacan' ),
'instruction_configure_new_metadatum' => __( 'Configure new metadatum.', 'tainacan' ),
// Info. Other feedback to user.
'info_search_results' => __( 'Search Results', 'tainacan' ),
'info_name_is_required' => __( 'Name is required.', 'tainacan' ),
'info_no_collection_created' => __( 'No collection was created in this repository.', 'tainacan' ),
'info_no_collection_draft' => __( 'No draft collection found.', 'tainacan' ),
'info_no_collection_trash' => __( 'No collection on trash.', 'tainacan' ),
'info_no_taxonomy_draft' => __( 'No draft taxonomy found.', 'tainacan' ),
'info_no_taxonomy_trash' => __( 'No taxonomy on trash.', 'tainacan' ),
'info_no_taxonomy_created' => __( 'No taxonomy was created in this repository.', 'tainacan' ),
'info_no_item_created' => __( 'No item was created in this collection.', 'tainacan' ),
'info_no_item_draft' => __( 'No draft item found.', 'tainacan' ),
'info_no_item_trash' => __( 'No item on trash.', 'tainacan' ),
'info_no_page_found' => __( 'No page was found with this name.', 'tainacan' ),
'info_no_user_found' => __( 'No user was found with this name.', 'tainacan' ),
'info_no_item_found' => __( 'No item was found here with these filters.', 'tainacan' ),
'info_item_not_saved' => __( 'Warning: Item not saved.', 'tainacan' ),
'info_no_moderator_on_collection' => __( "This collection doesn't have any moderator yet.", 'tainacan' ),
'info_error_deleting_collection' => __( 'Error on deleting collection.', 'tainacan' ),
'info_error_deleting_taxonomy' => __( 'Error on deleting taxonomy', 'tainacan' ),
'info_collection_deleted' => __( 'Collection deleted.', 'tainacan' ),
'info_item_deleted' => __( 'Item deleted.', 'tainacan' ),
'info_taxonomy_deleted' => __( 'Taxonomy deleted', 'tainacan' ),
'info_warning_collection_delete' => __( 'Do you really want to permanently delete this collection?', 'tainacan' ),
'info_warning_collection_trash' => __( 'Do you really want to trash this collection?', 'tainacan' ),
'info_warning_item_delete' => __( 'Do you really want to permanently delete this item?', 'tainacan' ),
'info_warning_item_trash' => __( 'Do you really want to trash this item?', 'tainacan' ),
'info_warning_taxonomy_delete' => __( 'Do you really want to delete this taxonomy?', 'tainacan' ),
'info_warning_selected_collections_delete' => __( 'Do you really want to permanently delete the selected collections?', 'tainacan' ),
'info_warning_selected_collections_trash' => __( 'Do you really want to trash the selected collections?', 'tainacan' ),
'info_warning_selected_items_delete' => __( 'Do you really want to permanently delete the selected items?', 'tainacan' ),
'info_warning_selected_items_trash' => __( 'Do you really want to trash the selected items?', 'tainacan' ),
'info_warning_selected_taxonomies_delete' => __( 'Do you really want to delete the selected taxonomies?', 'tainacan' ),
'info_warning_collection_related' => __( 'The metadata Collection related is required', 'tainacan' ),
'info_warning_no_metadata_found' => __( 'No metadata found in this collection', 'tainacan' ),
'info_showing_items' => __( 'Showing items ', 'tainacan' ),
'info_showing_collections' => __( 'Showing collections ', 'tainacan' ),
'info_showing_taxonomies' => __( 'Showing taxonomies ', 'tainacan' ),
'info_showing_events' => __( 'Showing events ', 'tainacan' ),
'info_to' => __( ' to ', 'tainacan' ),
'info_of' => __( ' of ', 'tainacan' ),
'info_created_by' => __( 'Created by: ', 'tainacan' ),
'info_by' => __( 'By: ', 'tainacan' ),
'info_date' => __( 'Date: ', 'tainacan' ),
'info_not_saved' => __( 'Not saved ', 'tainacan' ),
'info_warning_item_not_saved' => __( 'Are you sure? The item is not saved, changes will be lost.', 'tainacan' ),
'info_warning_metadata_not_saved' => __( 'Are you sure? There are metadata not saved, changes will be lost.', 'tainacan' ),
'info_warning_filters_not_saved' => __( 'Are you sure? There are filters not saved, changes will be lost.', 'tainacan' ),
'info_no_description_provided' => __( 'No description provided.', 'tainacan' ),
'info_warning_taxonomy_not_saved' => __( 'Are you sure? The metadata is not saved, changes will be lost.', 'tainacan' ),
'info_warning_terms_not_saved' => __( 'Are you sure? There are terms not saved, changes will be lost.', 'tainacan' ),
'info_warning_orphan_terms' => __( 'Are you sure? This term is parent of other terms. These will be converted to root terms.', 'tainacan' ),
'info_no_events' => __( 'No events', 'tainacan' ),
'info_logs_before' => __( 'Before updating', 'tainacan' ),
'info_logs_after' => __( 'What was updated', 'tainacan' ),
'info_there_is_no_metadatum' => __( 'There is no metadata here yet.', 'tainacan' ),
'info_there_is_no_filter' => __( 'There is no filter here yet.', 'tainacan' ),
'info_changes' => __( 'Changes', 'tainacan' ),
'info_possible_external_sources' => __( 'Possible external sources: CSV, Instagram, Youtube, etc.', 'tainacan' ),
'info_help_term_name' => __( 'The term name', 'tainacan' ),
'info_help_term_description' => __( 'The description of the Term.', 'tainacan' ),
'info_no_attachments_on_item_yet' => __( 'The are no attachments on this item so far.', 'tainacan' ),
'info_repository_metadata_inheritance' => __( 'Repository Metadata will be inherited by all collections.', 'tainacan' ),
'info_repository_filters_inheritance' => __( 'Repository Filters will be inherited by all collections.', 'tainacan' ),
'info_create_filters' => __( 'Click or Drag and Drop Metadata here for creating a new Filter.', 'tainacan' ),
'info_create_metadata' => __( 'Click or Drag and Drop Metadata Types here for creating a new Metadata.', 'tainacan' ),
'info_choose_your_metadata' => __( 'Choose your metadata.', 'tainacan' ),
'info_available_importers_helper' => __( 'The available importer type will affect the file or link that will provide your data besides deciding wich options are available to the importer.', 'tainacan' ),
'info_target_collection_helper' => __( 'The collection to which imported data will be send.', 'tainacan' ),
'info_source_file_upload' => __( 'The file containing the data to be imported.', 'tainacan' ),
'info_metadata_mapping_helper' => __( 'Map each file metadata with the corresponding one in selected collection.', 'tainacan' ),
'info_upload_a_source_to_see_metadata' => __( 'Upload a source file to load metadata.', 'tainacan' ),
'info_select_collection_to_list_metadata' => __( 'Select a target collection to list metadata.', 'tainacan' ),
'info_url_source_link_helper' => __( 'Link to file containing the data to be imported.', 'tainacan' ),
'info_updated_at' => __( 'Updated at', 'tainacan' ),
'info_editing_metadata_values' => __( 'Editing metadata values...', 'tainacan' ),
'info_updating_metadata_values' => __( 'Updating metadata values...', 'tainacan' ),
'info_search_results' => __( 'Search Results', 'tainacan' ),
'info_search_criteria' => __( 'Search Criteria', 'tainacan' ),
'info_name_is_required' => __( 'Name is required.', 'tainacan' ),
'info_no_collection_created' => __( 'No collection was created in this repository.', 'tainacan' ),
'info_no_collection_draft' => __( 'No draft collection found.', 'tainacan' ),
'info_no_collection_trash' => __( 'No collection in trash.', 'tainacan' ),
'info_no_taxonomy_draft' => __( 'No draft taxonomy found.', 'tainacan' ),
'info_no_taxonomy_trash' => __( 'No taxonomy in trash.', 'tainacan' ),
'info_no_taxonomy_created' => __( 'No taxonomy was created in this repository.', 'tainacan' ),
'info_no_item_created' => __( 'No item was created in this collection.', 'tainacan' ),
'info_no_item_draft' => __( 'No draft item found.', 'tainacan' ),
'info_no_item_trash' => __( 'No item in trash.', 'tainacan' ),
'info_no_page_found' => __( 'No page was found with this name.', 'tainacan' ),
'info_no_user_found' => __( 'No user was found with this name.', 'tainacan' ),
'info_no_item_found' => __( 'No item was found here with these filters.', 'tainacan' ),
'info_item_not_saved' => __( 'Warning: Item not saved.', 'tainacan' ),
'info_no_moderator_on_collection' => __( "This collection doesn't have any moderator yet.", 'tainacan' ),
'info_error_deleting_collection' => __( 'Error on deleting collection.', 'tainacan' ),
'info_error_deleting_taxonomy' => __( 'Error on deleting taxonomy', 'tainacan' ),
'info_collection_deleted' => __( 'Collection deleted.', 'tainacan' ),
'info_item_deleted' => __( 'Item deleted.', 'tainacan' ),
'info_taxonomy_deleted' => __( 'Taxonomy deleted', 'tainacan' ),
'info_warning_collection_delete' => __( 'Do you really want to permanently delete this collection?', 'tainacan' ),
'info_warning_collection_trash' => __( 'Do you really want to trash this collection?', 'tainacan' ),
'info_warning_item_delete' => __( 'Do you really want to permanently delete this item?', 'tainacan' ),
'info_warning_item_trash' => __( 'Do you really want to trash this item?', 'tainacan' ),
'info_warning_taxonomy_delete' => __( 'Do you really want to delete this taxonomy?', 'tainacan' ),
'info_warning_selected_collections_delete' => __( 'Do you really want to permanently delete the selected collections?', 'tainacan' ),
'info_warning_selected_collections_trash' => __( 'Do you really want to trash the selected collections?', 'tainacan' ),
'info_warning_selected_items_delete' => __( 'Do you really want to permanently delete the selected items?', 'tainacan' ),
'info_warning_selected_items_trash' => __( 'Do you really want to trash the selected items?', 'tainacan' ),
'info_warning_selected_taxonomies_delete' => __( 'Do you really want to delete the selected taxonomies?', 'tainacan' ),
'info_warning_collection_related' => __( 'The metadata Collection related is required', 'tainacan' ),
'info_warning_no_metadata_found' => __( 'No metadata found in this collection', 'tainacan' ),
'info_showing_items' => __( 'Showing items ', 'tainacan' ),
'info_showing_collections' => __( 'Showing collections ', 'tainacan' ),
'info_showing_taxonomies' => __( 'Showing taxonomies ', 'tainacan' ),
'info_showing_events' => __( 'Showing events ', 'tainacan' ),
'info_to' => __( ' to ', 'tainacan' ),
'info_of' => __( ' of ', 'tainacan' ),
'info_created_by' => __( 'Created by: ', 'tainacan' ),
'info_by' => __( 'By: ', 'tainacan' ),
'info_date' => __( 'Date: ', 'tainacan' ),
'info_not_saved' => __( 'Not saved ', 'tainacan' ),
'info_warning_item_not_saved' => __( 'Are you sure? The item is not saved, changes will be lost.', 'tainacan' ),
'info_warning_metadata_not_saved' => __( 'Are you sure? There are metadata not saved, changes will be lost.', 'tainacan' ),
'info_warning_filters_not_saved' => __( 'Are you sure? There are filters not saved, changes will be lost.', 'tainacan' ),
'info_no_description_provided' => __( 'No description provided.', 'tainacan' ),
'info_warning_taxonomy_not_saved' => __( 'Are you sure? The metadata is not saved, changes will be lost.', 'tainacan' ),
'info_warning_terms_not_saved' => __( 'Are you sure? There are terms not saved, changes will be lost.', 'tainacan' ),
'info_warning_orphan_terms' => __( 'Are you sure? This term is parent of other terms. These will be converted to root terms.', 'tainacan' ),
'info_no_events' => __( 'No events', 'tainacan' ),
'info_logs_before' => __( 'Before updating', 'tainacan' ),
'info_logs_after' => __( 'What was updated', 'tainacan' ),
'info_there_is_no_metadatum' => __( 'There is no metadata here yet.', 'tainacan' ),
'info_there_is_no_filter' => __( 'There is no filter here yet.', 'tainacan' ),
'info_changes' => __( 'Changes', 'tainacan' ),
'info_possible_external_sources' => __( 'Possible external sources: CSV, Instagram, Youtube, etc.', 'tainacan' ),
'info_help_term_name' => __( 'The term name', 'tainacan' ),
'info_help_term_description' => __( 'The description of the Term.', 'tainacan' ),
'info_no_attachments_on_item_yet' => __( 'The are no attachments on this item so far.', 'tainacan' ),
'info_repository_metadata_inheritance' => __( 'Repository Metadata will be inherited by all collections.', 'tainacan' ),
'info_repository_filters_inheritance' => __( 'Repository Filters will be inherited by all collections.', 'tainacan' ),
'info_create_filters' => __( 'Click or Drag and Drop Metadata here for creating a new Filter.', 'tainacan' ),
'info_create_metadata' => __( 'Click or Drag and Drop Metadata Types here for creating a new Metadata.', 'tainacan' ),
'info_choose_your_metadata' => __( 'Choose your metadata.', 'tainacan' ),
'info_available_importers_helper' => __( 'The available importer type will affect the file or link that will provide your data besides deciding wich options are available to the importer.', 'tainacan' ),
'info_target_collection_helper' => __( 'The collection to which imported data will be send.', 'tainacan' ),
'info_source_file_upload' => __( 'The file containing the data to be imported.', 'tainacan' ),
'info_metadata_mapping_helper' => __( 'Map each file metadata with the corresponding one in selected collection.', 'tainacan' ),
'info_upload_a_source_to_see_metadata' => __( 'Upload a source file to load metadata.', 'tainacan' ),
'info_select_collection_to_list_metadata' => __( 'Select a target collection to list metadata.', 'tainacan' ),
'info_url_source_link_helper' => __( 'Link to file containing the data to be imported.', 'tainacan' ),
'info_updated_at' => __( 'Updated at', 'tainacan' ),
'info_editing_metadata_values' => __( 'Editing metadata values...', 'tainacan' ),
'info_updating_metadata_values' => __( 'Updating metadata values...', 'tainacan' ),
'info_type_to_add_items' => __( 'Add items...', 'tainacan' ),
'info_type_to_search_items' => __( 'Search items...', 'tainacan' ),
'info_type_to_add_terms' => __( 'Add terms...', 'tainacan' ),
'info_type_to_search_metadata' => __( 'Search metadata...', 'tainacan' ),
'info_type_to_add_metadata' => __( 'Add metadata...', 'tainacan' ),
'info_visibility_helper' => __( 'How the item will be available to visualization.', 'tainacan' ),
// Tainacan Metadatum Types
'tainacan-text' => __( 'Text', 'tainacan' ),
'tainacan-textarea' => __( 'Text area', 'tainacan' ),
'tainacan-date' => __( 'Date', 'tainacan' ),
'tainacan-numeric' => __( 'Numeric', 'tainacan' ),
'tainacan-selectbox' => __( 'Select box', 'tainacan' ),
'tainacan-relationship' => __( 'Relationship', 'tainacan' ),
'tainacan-taxonomy' => __( 'Taxonomy', 'tainacan' ),
'tainacan-compound' => __( 'Compound', 'tainacan' ),
'tainacan-text' => __( 'Text', 'tainacan' ),
'tainacan-textarea' => __( 'Text area', 'tainacan' ),
'tainacan-date' => __( 'Date', 'tainacan' ),
'tainacan-numeric' => __( 'Numeric', 'tainacan' ),
'tainacan-selectbox' => __( 'Select box', 'tainacan' ),
'tainacan-relationship' => __( 'Relationship', 'tainacan' ),
'tainacan-taxonomy' => __( 'Taxonomy', 'tainacan' ),
'tainacan-compound' => __( 'Compound', 'tainacan' ),
// Tainacan Filter Types
'tainacan-filter-custom-interval' => __( 'Custom Interval', 'tainacan' ),
'tainacan-filter-selectbox' => __( 'Select Box', 'tainacan' ),
'tainacan-filter-autocomplete' => __( 'Autocomplete', 'tainacan' ),
'tainacan-filter-taginput' => __( 'Tag Input', 'tainacan' ),
'tainacan-filter-checkbox' => __( 'Check Box', 'tainacan' ),
'tainacan-filter-taxonomy-taginput' => __( 'Taxonomy Tag Input', 'tainacan' ),
'tainacan-filter-taxonomy-checkbox' => __( 'Taxonomy Check Box', 'tainacan' ),
'tainacan-filter-taxonomy-selectbox' => __( 'Taxonomy Select Box', 'tainacan' )
]);
'tainacan-filter-custom-interval' => __( 'Custom Interval', 'tainacan' ),
'tainacan-filter-selectbox' => __( 'Select Box', 'tainacan' ),
'tainacan-filter-autocomplete' => __( 'Autocomplete', 'tainacan' ),
'tainacan-filter-taginput' => __( 'Tag Input', 'tainacan' ),
'tainacan-filter-checkbox' => __( 'Check Box', 'tainacan' ),
'tainacan-filter-taxonomy-taginput' => __( 'Taxonomy Tag Input', 'tainacan' ),
'tainacan-filter-taxonomy-checkbox' => __( 'Taxonomy Check Box', 'tainacan' ),
'tainacan-filter-taxonomy-selectbox' => __( 'Taxonomy Select Box', 'tainacan' )
] );
?>

View File

@ -0,0 +1,292 @@
<?php
namespace Tainacan\API\EndPoints;
use \Tainacan\API\REST_Controller;
use Tainacan\Entities;
use Tainacan\Repositories;
use Tainacan\Entities\Entity;
class REST_Bulkedit_Controller extends REST_Controller {
public function __construct() {
$this->rest_base = 'bulk-edit';
parent::__construct();
add_action('init', array(&$this, 'init_objects'), 11);
}
public function init_objects() {
$this->metadatum_repository = Repositories\Metadata::get_instance();
$this->collections_repository = Repositories\Collections::get_instance();
}
/**
*
*
* @throws \Exception
*/
public function register_routes() {
register_rest_route($this->namespace, '/collection/(?P<collection_id>[\d]+)/' . $this->rest_base,
array(
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array($this, 'create_item'),
'permission_callback' => array($this, 'bulk_edit_permissions_check'),
'args' => $this->get_create_params()
),
)
);
register_rest_route($this->namespace, '/collection/(?P<collection_id>[\d]+)/' . $this->rest_base . '/(?P<group_id>[0-9a-f]+)/add',
array(
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array($this, 'add_value'),
'permission_callback' => array($this, 'bulk_edit_permissions_check'),
'args' => [
'metadatum_id' => [
'type' => 'integer',
'description' => __( 'The metadatum ID', 'tainacan' ),
],
'value' => [
'type' => 'string',
'description' => __( 'The value to be added', 'tainacan' ),
],
],
),
)
);
register_rest_route($this->namespace, '/collection/(?P<collection_id>[\d]+)/' . $this->rest_base . '/(?P<group_id>[0-9a-f]+)/set',
array(
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array($this, 'set_value'),
'permission_callback' => array($this, 'bulk_edit_permissions_check'),
'args' => [
'metadatum_id' => [
'type' => 'integer',
'description' => __( 'The metadatum ID', 'tainacan' ),
],
'value' => [
'type' => 'string',
'description' => __( 'The value to be added', 'tainacan' ),
],
],
),
)
);
register_rest_route($this->namespace, '/collection/(?P<collection_id>[\d]+)/' . $this->rest_base . '/(?P<group_id>[0-9a-f]+)/remove',
array(
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array($this, 'remove_value'),
'permission_callback' => array($this, 'bulk_edit_permissions_check'),
'args' => [
'metadatum_id' => [
'type' => 'integer',
'description' => __( 'The metadatum ID', 'tainacan' ),
],
'value' => [
'type' => 'string',
'description' => __( 'The value to be added', 'tainacan' ),
],
],
),
)
);
register_rest_route($this->namespace, '/collection/(?P<collection_id>[\d]+)/' . $this->rest_base . '/(?P<group_id>[0-9a-f]+)/replace',
array(
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array($this, 'add_value'),
'permission_callback' => array($this, 'bulk_edit_permissions_check'),
'args' => [
'metadatum_id' => [
'type' => 'integer',
'description' => __( 'The metadatum ID', 'tainacan' ),
],
'old_value' => [
'type' => 'string',
'description' => __( 'The value to search for', 'tainacan' ),
],
'new_value' => [
'type' => 'string',
'description' => __( 'The value to be set', 'tainacan' ),
],
],
),
)
);
}
public function bulk_edit_permissions_check($request) {
$collection = $this->collections_repository->fetch($request['collection_id']);
if ($collection instanceof Entities\Collection) {
return current_user_can($collection->get_items_capabilities()->edit_others_posts);
}
return false;
}
public function create_item($request) {
$body = json_decode($request->get_body(), true);
$args = [];
if (isset($body['items_ids']) && is_array($body['items_ids']) && !empty($body['items_ids'])) {
$args['items_ids'] = $body['items_ids'];
} elseif ( isset($body['use_query']) && $body['use_query'] ) {
unset($request['paged']);
unset($request['offset']);
unset($request['perpage']);
$request['nopaging'] = 1;
$query_args = $this->prepare_filters($request);
$collection_id = $request['collection_id'];
$args = [
'query' => $query_args,
'collection_id' => $collection_id
];
} else {
return new \WP_REST_Response([
'error_message' => __('You mus specify items_ids OR use_query', 'tainacan'),
], 400);
}
$bulk = new \Tainacan\Bulk_Edit($args);
$response = [
'id' => $bulk->get_id()
];
$rest_response = new \WP_REST_Response($response, 200);
$rest_response->header('X-WP-Total', $bulk->count_posts());
return $rest_response;
}
public function add_value($request) {
return $this->generic_action('add_value', $request);
}
public function set_value($request) {
return $this->generic_action('set_value', $request);
}
public function remove_value($request) {
return $this->generic_action('remove_value', $request);
}
public function replace_value($request) {
return $this->generic_action('replace_value', $request, ['old_value', 'new_value']);
}
private function generic_action($method, $request, $keys = ['value']) {
$body = json_decode($request->get_body(), true);
if(empty($body)){
return new \WP_REST_Response([
'error_message' => __('Body can not be empty.', 'tainacan'),
], 400);
}
if(!isset($body['metadatum_id'])){
return new \WP_REST_Response([
'error_message' => __('You must specify a Metadatum ID.', 'tainacan'),
], 400);
}
foreach ($keys as $key) {
if(!isset($body[$key])){
return new \WP_REST_Response([
'error_message' => sprintf(__('%s must be provided', 'tainacan'), $key),
], 400);
}
}
$group_id = $request['group_id'];
var_dump($group_id);
$args = ['id' => $group_id];
$bulk = new \Tainacan\Bulk_Edit($args);
$metadatum = $this->metadatum_repository->fetch($body['metadatum_id']);
if ( $metadatum instanceof Entities\Metadatum ) {
$value = isset($body['new_value']) ? $body['new_value'] : $body['value'];
$old_value = isset($body['old_value']) ? $body['old_value'] : null;
$action = $bulk->$method($metadatum, $value, $old_value);
if ( is_wp_error($action) ) {
return new \WP_REST_Response([
'error_message' => $action->get_error_message(),
], 400);
} else {
return new \WP_REST_Response($action, 200);
}
} else {
return new \WP_REST_Response([
'error_message' => __('Metadatum not found.', 'tainacan'),
], 400);
}
}
/**
* @param null $object_name
*
* @return array|void
*/
public function get_create_params($object_name = null) {
$query_params['context']['default'] = 'view';
array_merge($query_params, parent::get_collection_params('item'));
$query_params['title'] = array(
'description' => __('Limits the result set to items with a specific title'),
'type' => 'string',
);
$query_params['items_ids'] = [
'type' => 'array',
'items' => [
'type' => 'integer'
],
'description' => __( 'Array of items IDs', 'tainacan' ),
];
$query_params['use_query'] = [
'type' => 'bool',
'description' => __( 'Whether to use the current query to select posts', 'tainacan' ),
];
$query_params = array_merge($query_params, parent::get_meta_queries_params());
return $query_params;
}
}
?>

View File

@ -159,11 +159,12 @@ class REST_Items_Controller extends REST_Controller {
$attributes_to_filter = $request['fetch_only'];
# Always returns id
# Always returns id and collection id
if(is_array($attributes_to_filter)) {
$attributes_to_filter[] = 'id';
$attributes_to_filter[] = 'collection_id';
} else {
$attributes_to_filter = array($attributes_to_filter, 'id');
$attributes_to_filter = array($attributes_to_filter, 'id', 'collection_id');
}
$item_arr = $this->filter_object_by_attributes($item, $attributes_to_filter);

View File

@ -297,7 +297,7 @@ class REST_Terms_Controller extends REST_Controller {
if(isset($args['number'], $args['offset'])){
unset( $args['number'], $args['offset'] );
$total_terms = wp_count_terms( $this->taxonomy->get_db_identifier(), $args );
$total_terms = wp_count_terms( $taxonomy->get_db_identifier(), $args );
if ( ! $total_terms ) {
$total_terms = 0;

View File

@ -15,6 +15,7 @@ $rest_metadata_types_controller = new \Tainacan\API\EndPoints\REST_Metadata_Type
$rest_filter_types_controller = new \Tainacan\API\EndPoints\REST_Filter_Types_Controller();
$rest_importers_controller = new \Tainacan\API\EndPoints\REST_Importers_Controller();
$rest_background_processes_controller = new \Tainacan\API\EndPoints\REST_Background_Processes_Controller();
$rest_bulkedit_controller = new \Tainacan\API\EndPoints\REST_Bulkedit_Controller();
new \Tainacan\API\EndPoints\REST_Export_Controller();
new \Tainacan\API\EndPoints\REST_Metadatum_Mappers_Controller();
// Add here other endpoints imports

View File

@ -8,7 +8,6 @@ namespace Tainacan;
* Uses https://github.com/A5hleyRich/wp-background-processing to handle DB
* updates in the background.
*
* @package WooCommerce/Classes
*/
defined( 'ABSPATH' ) || exit;

View File

@ -0,0 +1,428 @@
<?php
namespace Tainacan;
use Tainacan\Repositories;
use Tainacan\Entities;
defined( 'ABSPATH' ) || exit;
/**
* Bulk_Edit class handles bulk item edition
*/
class Bulk_Edit {
private $meta_key = '_tnc_bulk';
/**
* The ID of the current bulk edition group.
* @var string
*/
private $id;
/**
* Initializes a bulk edit object
*
* This object have an ID that identifies the group of selected items that are to be affected by the changes.
*
* When itialized it adds a postmeta to the posts of these groups so they can be easily fetched as a group in all operations.
*
* The object can be initialized in three different ways:
* 1. passing an array of Items IDs, using the items_ids params
* 2. passing a query array, that will be passed to the fetch method of items repository to create the group (in this case you also need to inform the collection id)
* 3. passing an group ID, generated by this class in a previous initialization using one of the methods above.
*
* When initializing using methods 1 or 2, controllers should then call the get_id() method and store it if they want to perform future requests that wil affect this same group of items
*
* Note: if the ID paramater is passed, other paramaters will be ignored.
*
* @param array $params {
*
* Initialization paramaters
*
* @type int $collection_id The items collection ID. Required if initializing using a query search
* @type array $query The query paramaters used to fetch items that will be part of this bulk edit group
* @type array $items_ids an array containing the IDs of items that will be part of this bulk edit group
* @type string $id The ID of the Bulk edit group.
*
* }
*/
public function __construct($params) {
if (isset($params['id']) && !empty($params['id'])) {
$this->id = $params['id'];
return;
}
global $wpdb;
$id = uniqid();
$this->id = $id;
if (isset($params['query']) && is_array($params['query'])) {
if (!isset($params['collection_id']) || !is_numeric($params['collection_id'])) {
throw new \Exception('Collection ID must be informed when creating a group via query');
}
/**
* Here we use the fetch method to parse the parameter and use WP_Query
*
* However, we add a filter so the query is not executed. We just want WP_Query to build it for us
* and then we can use it to INSERT the postmeta with the bulk group ID
*/
// this avoids wp_query to run the query. We just want to build the query
add_filter('posts_pre_query', '__return_empty_array');
// this adds the meta key and meta value to the SELECT query so it can be used directly in the INSERT below
add_filter('posts_fields_request', [&$this, 'add_fields_to_query'], 10, 2);
$itemsRepo = Repositories\Items::get_instance();
$params['query']['fields'] = 'ids';
$items_query = $itemsRepo->fetch($params['query'], $params['collection_id']);
remove_filter('posts_pre_query', '__return_empty_array');
remove_filter('posts_fields_request', [&$this, 'add_fields_to_query']);
$wpdb->query( "INSERT INTO $wpdb->postmeta (post_id, meta_key, meta_value) {$items_query->request}" );
return;
} elseif (isset($params['items_ids']) && is_array($params['items_ids'])) {
$items_ids = array_filter($params['items_ids'], 'is_integer');
$insert_q = '';
foreach ($items_ids as $item_id) {
$insert_q .= $wpdb->prepare( "(%d, %s, %s),", $item_id, $this->meta_key, $this->get_id() );
}
$insert_q = rtrim($insert_q, ',');
$wpdb->query( "INSERT INTO $wpdb->postmeta (post_id, meta_key, meta_value) VALUES $insert_q" );
return;
}
}
/**
* Internally used to filter WP_Query and build the INSERT statement.
* Must be public because it is registered as a filter callback
*/
public function add_fields_to_query($fields, $wp_query) {
global $wpdb;
if ( $wp_query->get('fields') == 'ids' ) { // just to make sure we are in the right query
$fields .= $wpdb->prepare( ", %s, %s", $this->meta_key, $this->get_id() );
}
return $fields;
}
/**
* Get the current group ID
* @return string the group ID
*/
public function get_id() {
return $this->id;
}
// return the number of items selected in the current bulk group
public function count_posts() {
global $wpdb;
$id = $this->get_id();
if (!empty($id)) {
return $wpdb->get_var( $wpdb->prepare("SELECT COUNT(post_id) FROM $wpdb->postmeta WHERE meta_key = %s AND meta_value = %s", $this->meta_key, $id) );
}
return 0;
}
private function _build_select($fields) {
global $wpdb;
return $wpdb->prepare( "SELECT $fields FROM $wpdb->postmeta WHERE meta_key = %s AND meta_value = %s", $this->meta_key, $this->get_id() );
}
/**
* Adds a value to a metadatum to all items in the current group
* Must be used with a multiple metadatum
*
*/
public function add_value(Entities\Metadatum $metadatum, $value) {
if (!$this->get_id()) {
return new \WP_Error( 'no_id', __( 'Bulk Edit group not initialized', 'tainacan' ) );
}
// Specific validation
if (!$metadatum->is_multiple()) {
return new \WP_Error( 'invalid_action', __( 'Unable to add a value to a metadata if it does not accept multiple values', 'tainacan' ) );
}
if ($metadatum->is_collection_key()) {
return new \WP_Error( 'invalid_action', __( 'Unable to add a value to a metadata set to be a collection key', 'tainacan' ) );
}
$dummyItem = new Entities\Item();
$checkItemMetadata = new Entities\Item_Metadata_Entity($dummyItem, $metadatum);
$checkItemMetadata->set_value([$value]);
if ($checkItemMetadata->validate()) {
return $this->_add_value($metadatum, $value);
} else {
return new \WP_Error( 'invalid_value', __( 'Invalid Value', 'tainacan' ) );
}
}
/**
* Sets a value to a metadatum to all items in the current group.
*
* If metadatum is multiple, it will delete all values item may have for this metadatum and then add
* this value
*/
public function set_value(Entities\Metadatum $metadatum, $value) {
if (!$this->get_id()) {
return new \WP_Error( 'no_id', __( 'Bulk Edit group not initialized', 'tainacan' ) );
}
// Specific validation
if ($metadatum->is_collection_key()) {
return new \WP_Error( 'invalid_action', __( 'Unable to set a value to a metadata set to be a collection key', 'tainacan' ) );
}
$dummyItem = new Entities\Item();
$checkItemMetadata = new Entities\Item_Metadata_Entity($dummyItem, $metadatum);
$checkItemMetadata->set_value( $metadatum->is_multiple() ? [$value] : $value );
if ($checkItemMetadata->validate()) {
$this->_remove_values($metadatum);
return $this->_add_value($metadatum, $value);
} else {
return new \WP_Error( 'invalid_value', __( 'Invalid Value', 'tainacan' ) );
}
}
/**
* Removes one value from a metadatum of all items in current group
*
* Must be used with multiple metadatum that are not set as required
*
*/
public function remove_value(Entities\Metadatum $metadatum, $value) {
if (!$this->get_id()) {
return new \WP_Error( 'no_id', __( 'Bulk Edit group not initialized', 'tainacan' ) );
}
// Specific validation
if ($metadatum->is_required()) {
return new \WP_Error( 'invalid_action', __( 'Unable to remove a value from a required metadatum', 'tainacan' ) );
}
if (!$metadatum->is_multiple()) {
return new \WP_Error( 'invalid_action', __( 'Unable to remove a value from a metadata if it does not accept multiple values', 'tainacan' ) );
}
return $this->_remove_value($metadatum, $value);
}
/**
* Relplaces a value from one metadata with another value in all items in current group
*/
public function replace_value(Entities\Metadatum $metadatum, $new_value, $old_value) {
if (!$this->get_id()) {
return new \WP_Error( 'no_id', __( 'Bulk Edit group not initialized', 'tainacan' ) );
}
// Specific validation
if ($metadatum->is_collection_key()) {
return new \WP_Error( 'invalid_action', __( 'Unable to set a value to a metadata set to be a collection key', 'tainacan' ) );
}
$dummyItem = new Entities\Item();
$checkItemMetadata = new Entities\Item_Metadata_Entity($dummyItem, $metadatum);
$checkItemMetadata->set_value( $metadatum->is_multiple() ? [$new_value] : $new_value );
if ($checkItemMetadata->validate()) {
$this->_remove_value($metadatum, $old_value);
return $this->_add_value($metadatum, $new_value);
} else {
return new \WP_Error( 'invalid_value', __( 'Invalid Value', 'tainacan' ) );
}
}
/**
* Adds a value to the current group of items
*
* This method adds value to the database directly, any check or validation must be done beforehand
*/
private function _add_value(Entities\Metadatum $metadatum, $value) {
global $wpdb;
$type = $metadatum->get_metadata_type_object();
if ($type->get_primitive_type() == 'term') {
$options = $metadatum->get_metadata_type_options();
$taxonomy_id = $options['taxonomy_id'];
$tax = Repositories\Taxonomies::get_instance()->fetch($taxonomy_id);
if ($tax instanceof Entities\Taxonomy) {
$term = term_exists($value, $tax->get_db_identifier());
if (!is_array($term)) {
$term = wp_insert_term($value, $tax->get_db_identifier());
}
if (is_WP_Error($term) || !isset($term['term_taxonomy_id'])) {
return new \WP_Error( 'error', __( 'Error adding term', 'tainacan' ) );
}
$insert_q = $this->_build_select( $wpdb->prepare("post_id, %d", $term['term_taxonomy_id']) );
$query = "INSERT INTO $wpdb->term_relationships (object_id, term_taxonomy_id) $insert_q";
return $wpdb->query($query);
//TODO update term count
}
} else {
global $wpdb;
$insert_q = $this->_build_select( $wpdb->prepare("post_id, %s, %s", $metadatum->get_id(), $value) );
$query = "INSERT INTO $wpdb->postmeta (post_id, meta_key, meta_value) $insert_q";
$affected = $wpdb->query($query);
if ($type->get_core()) {
$field = $type->get_related_mapped_prop();
$map_field = [
'title' => 'post_title',
'description' => 'post_content'
];
$column = $map_field[$field];
$update_q = $this->_build_select( "post_id" );
$core_query = $wpdb->prepare( "UPDATE $wpdb->posts SET $column = %s WHERE ID IN ($update_q)", $value );
$wpdb->query($core_query);
}
return $affected;
}
}
/**
* Removes a value from the current group of items
*
* This method removes value from the database directly, any check or validation must be done beforehand
*/
private function _remove_value(Entities\Metadatum $metadatum, $value) {
global $wpdb;
$type = $metadatum->get_metadata_type_object();
if ($type->get_primitive_type() == 'term') {
$options = $metadatum->get_metadata_type_options();
$taxonomy_id = $options['taxonomy_id'];
$tax = Repositories\Taxonomies::get_instance()->fetch($taxonomy_id);
if ($tax instanceof Entities\Taxonomy) {
$term = term_exists($value, $tax->get_db_identifier());
if (!$term) {
return 0;
}
if (is_WP_Error($term) || !isset($term['term_taxonomy_id'])) {
return new \WP_Error( 'error', __( 'Term not found', 'tainacan' ) );
}
$delete_q = $this->_build_select( "post_id" );
$query = $wpdb->prepare( "DELETE FROM $wpdb->term_relationships WHERE term_taxonomy_id = %d AND object_id IN ($delete_q)", $term['term_taxonomy_id'] );
return $wpdb->query($query);
//TODO update term count
}
} else {
global $wpdb;
$delete_q = $this->_build_select( "post_id" );
$query = $wpdb->prepare( "DELETE FROM $wpdb->postmeta WHERE meta_key = %s AND meta_value = %s AND post_id IN ( SELECT implicitTemp.post_id FROM ($delete_q) implicitTemp )", $metadatum->get_id(), $value );
return $wpdb->query($query);
}
}
/**
* Removes all values of a metadatum from the current group of items
*
* This method removes value from the database directly, any check or validation must be done beforehand
*/
private function _remove_values(Entities\Metadatum $metadatum) {
global $wpdb;
$type = $metadatum->get_metadata_type_object();
if ($type->get_primitive_type() == 'term') {
$options = $metadatum->get_metadata_type_options();
$taxonomy_id = $options['taxonomy_id'];
$tax = Repositories\Taxonomies::get_instance()->fetch($taxonomy_id);
if ($tax instanceof Entities\Taxonomy) {
$delete_q = $this->_build_select( "post_id" );
$delete_tax_q = $wpdb->prepare( "SELECT term_taxonomy_id FROM $wpdb->term_taxonomy WHERE taxonomy = %s" , $tax->get_db_identifier() );
$query = "DELETE FROM $wpdb->term_relationships WHERE term_taxonomy_id IN ($delete_tax_q) AND object_id IN ($delete_q)";
return $wpdb->query($query);
//TODO update term count
}
} else {
global $wpdb;
$delete_q = $this->_build_select( "post_id" );
$query = $wpdb->prepare( "DELETE FROM $wpdb->postmeta WHERE meta_key = %s AND post_id IN ( SELECT implicitTemp.post_id FROM ($delete_q) implicitTemp )", $metadatum->get_id() );
return $wpdb->query($query);
}
}
}

View File

@ -319,6 +319,9 @@ class Item_Metadata_Entity extends Entity {
if (empty($value) && $this->is_required()) {
$this->add_error('required', $metadatum->get_name() . ' is required');
return false;
} elseif (empty($value) && !$this->is_required()) {
$this->set_as_valid();
return true;
}
$classMetadatumType = $metadatum->get_metadata_type_object();

View File

@ -6,17 +6,18 @@
:id="id"
v-model="selected"
:data="options"
expanded
@input="search"
:loading="isLoading"
field="label"
@select="option => setResults(option) ">
@select="option => setResults(option) "
:placeholder="(type == 'Tainacan\\Metadata_Types\\Relationship') ? $i18n.get('info_type_to_search_items') : $i18n.get('info_type_to_search_metadata')">
<template slot-scope="props">
<div class="media">
<div
class="media-left"
v-if="props.option.img">
<img
width="32"
width="24"
:src="`${props.option.img}`">
</div>
<div class="media-content">
@ -25,25 +26,13 @@
</div>
</template>
</b-autocomplete>
<!-- <ul
class="selected-list-box"
v-if="selected !== '' && selected !== undefined">
<li>
<b-tag
attached
closable
@close="clearSearch()">
{{ label }}
</b-tag>
</li>
</ul> -->
</div>
</template>
<script>
import { tainacan as axios } from '../../../js/axios/axios'
import { filter_type_mixin } from '../filter-types-mixin'
import qs from 'qs';
// import qs from 'qs';
export default {
created(){
@ -69,16 +58,22 @@
.catch(error => {
this.$console.log(error);
});
this.$eventBusSearch.$on('removeFromFilterTag', (filterTag) => {
if (filterTag.filterId == this.filter.id)
this.cleanSearch();
})
},
data(){
return {
results:'',
selected:'',
options: [],
isLoading: false,
type: '',
collection: '',
metadatum: '',
metadatum_object: {},
label: ''
}
},
@ -101,25 +96,27 @@
collection_id: this.collection,
value: this.results
});
this.selectedValues();
},
search( query ){
let promise = null;
this.options = [];
if ( this.type === 'Tainacan\\Metadata_Types\\Relationship' ) {
let collectionTarget = ( this.metadatum_object && this.metadatum_object.metadata_type_options.collection_id ) ?
this.metadatum_object.metadata_type_options.collection_id : this.collection_id;
promise = this.getValuesRelationship( collectionTarget );
if (query != '') {
let promise = null;
this.options = [];
if ( this.type === 'Tainacan\\Metadata_Types\\Relationship' ) {
let collectionTarget = ( this.metadatum_object && this.metadatum_object.metadata_type_options.collection_id ) ?
this.metadatum_object.metadata_type_options.collection_id : this.collection_id;
promise = this.getValuesRelationship( collectionTarget, query );
} else {
promise = this.getValuesPlainText( this.metadatum, query, this.isRepositoryLevel );
}
promise.catch( error => {
this.$console.log('error select', error );
});
} else {
promise = this.getValuesPlainText( this.metadatum, query, this.isRepositoryLevel );
this.cleanSearch();
}
promise.then( () => {
this.isLoading = false;
}).catch( error => {
this.$console.log('error select', error );
this.isLoading = false;
});
},
selectedValues(){
const instance = this;
@ -129,33 +126,44 @@
let index = this.query.metaquery.findIndex(newMetadatum => newMetadatum.key === this.metadatum );
if ( index >= 0){
let metadata = this.query.metaquery[ index ];
let collectionTarget = ( this.metadatum_object && this.metadatum_object.metadata_type_options.collection_id ) ?
this.metadatum_object.metadata_type_options.collection_id : this.collection_id;
// let collectionTarget = ( this.metadatum_object && this.metadatum_object.metadata_type_options.collection_id ) ?
// this.metadatum_object.metadata_type_options.collection_id : this.collection_id;
if ( this.type === 'Tainacan\\Metadata_Types\\Relationship' ) {
let query = qs.stringify({ postin: metadata.value });
axios.get('/collection/' + collectionTarget + '/items?' + query)
// let query = qs.stringify({ postin: metadata.value });
axios.get('/items/' + metadata.value)
.then( res => {
for (let item of res.data) {
// instance.selected.push({ label: item.title, value: item.id, img: '' });
this.$console.log(item.title);
instance.results = item.title;
instance.label = item.title;
}
let item = res.data;
instance.results = item.title;
instance.label = item.title;
instance.selected = item.title;
this.$eventBusSearch.$emit( 'sendValuesToTags', {
filterId: instance.filter.id,
value: instance.label
});
})
.catch(error => {
this.$console.log(error);
});
} else {
instance.results = metadata.value;
instance.label = metadata.value;
instance.selected = metadata.value;
this.$eventBusSearch.$emit( 'sendValuesToTags', {
filterId: instance.filter.id,
value: metadata.value
});
}
} else {
return false;
}
},
clearSearch(){
cleanSearch(){
this.results = '';
this.label = '';
this.selected = '';

View File

@ -6,15 +6,22 @@
class="metadatum">
<b-checkbox
v-model="selected"
:native-value="option.value"
>{{ option.label }}</b-checkbox>
:native-value="option.value">
{{ option.label }}
</b-checkbox>
</div>
<!-- <a
@click="openCheckboxModal()"
class="add-link">
{{ $i18n.get('label_see_more') }}
</a> -->
</div>
</template>
<script>
import { tainacan as axios } from '../../../js/axios/axios';
import { filter_type_mixin } from '../filter-types-mixin'
// import CheckboxFilterModal from '../../../admin/components/other/checkbox-filter-modal.vue'
export default {
created(){
@ -40,6 +47,33 @@
.catch(error => {
this.$console.log(error);
});
this.$eventBusSearch.$on('removeFromFilterTag', (filterTag) => {
if (filterTag.filterId == this.filter.id) {
let selectedIndex = this.selected.findIndex(option => option == filterTag.singleValue);
if (selectedIndex >= 0) {
let newSelected = this.selected.slice();
newSelected.splice(selectedIndex, 1);
this.$emit('input', {
filter: 'checkbox',
compare: 'IN',
metadatum_id: this.metadatum,
collection_id: ( this.collection_id ) ? this.collection_id : this.filter.collection_id,
value: newSelected
});
this.$eventBusSearch.$emit( 'sendValuesToTags', {
filterId: this.filter.id,
value: newSelected
});
this.selectedValues();
}
}
});
},
props: {
isRepositoryLevel: Boolean,
@ -93,6 +127,11 @@
collection_id: ( this.collection_id ) ? this.collection_id : this.filter.collection_id,
value: this.selected
});
this.$eventBusSearch.$emit( 'sendValuesToTags', {
filterId: this.filter.id,
value: this.selected
});
},
selectedValues(){
if ( !this.query || !this.query.metaquery || !Array.isArray( this.query.metaquery ) )
@ -100,12 +139,22 @@
let index = this.query.metaquery.findIndex(newMetadatum => newMetadatum.key === this.metadatum );
if ( index >= 0){
let metadata = this.query.metaquery[ index ];
this.selected = metadata.value;
let query = this.query.metaquery.slice();
this.selected = query[ index ].value;
} else {
this.selected = [];
return false;
}
}
},
// openCheckboxModal() {
// this.$modal.open({
// parent: this,
// component: CheckboxFilterModal,
// props: {
// title: this.filter.name
// }
// });
// }
}
}
</script>

View File

@ -4,15 +4,14 @@
<div v-if="type === 'date'">
<b-datepicker
:placeholder="$i18n.get('label_selectbox_init')"
:class="{'has-content': date_init != undefined && date_init != ''}"
v-model="date_init"
size="is-small"
@focus="isTouched = true"
@input="validate_values()"
icon="calendar-today"/>
<p class="is-size-7 has-text-centered">{{ $i18n.get('label_until') }}</p>
<b-datepicker
:placeholder="$i18n.get('label_selectbox_init')"
:class="{'has-content': date_end != undefined && date_end != ''}"
v-model="date_end"
size="is-small"
@input="validate_values()"
@ -25,7 +24,6 @@
class="columns"
v-else>
<b-input
:class="{'has-content': value_init != undefined && value_init != ''}"
size="is-small"
type="number"
step="any"
@ -33,7 +31,6 @@
class="column"
v-model="value_init"/>
<b-input
:class="{'has-content': value_end != undefined && value_end != ''}"
size="is-small"
type="number"
step="any"
@ -42,16 +39,6 @@
class="column"
v-model="value_end"/>
</div>
<div
class="selected-list-box"
v-if="isValid && !clear">
<b-tag
attached
closable
@close="clearSearch()">
{{ showSearch() }}
</b-tag>
</div>
</div>
</template>
@ -84,6 +71,11 @@
.catch(error => {
this.$console.log(error);
});
this.$eventBusSearch.$on('removeFromFilterTag', (filterTag) => {
if (filterTag.filterId == this.filter.id)
this.clearSearch();
});
},
data(){
return {
@ -179,6 +171,13 @@
this.isValid = true;
}
if (metadata.value[0] != undefined && metadata.value[1] != undefined) {
this.$eventBusSearch.$emit( 'sendValuesToTags', {
filterId: this.filter.id,
value: metadata.value[0] + ' - ' + metadata.value[1]
});
}
} else {
return false;
}
@ -214,8 +213,8 @@
this.date_end = null;
this.isTouched = false;
} else {
// this.value_end = null;
// this.value_init = null;
this.value_end = null;
this.value_init = null;
this.isTouched = false;
}
},
@ -273,7 +272,6 @@
}
}
vm.$emit('input', {
filter: 'range',
type: type,
@ -282,6 +280,13 @@
collection_id: ( vm.collection_id ) ? vm.collection_id : vm.filter.collection_id,
value: values
});
if (values[0] != undefined && values[1] != undefined) {
vm.$eventBusSearch.$emit( 'sendValuesToTags', {
filterId: vm.filter.id,
value: values[0] + ' - ' + values[1]
});
}
}
}
}

View File

@ -1,6 +1,11 @@
import { tainacan as axios } from '../../js/axios/axios';
export const filter_type_mixin = {
data () {
return {
thumbPlaceholderPath: tainacan_plugin.base_url + '/admin/images/placeholder_square.png'
}
},
props: {
filter: {
type: Object // concentrate all attributes metadatum id and type
@ -12,7 +17,7 @@ export const filter_type_mixin = {
query: {}
},
methods: {
getValuesPlainText(metadatumId, search, isRepositoryLevel) {
getValuesPlainText(metadatumId, search, isRepositoryLevel, valuesToIgnore) {
let url = '/collection/' + this.collection + '/metadata/' + metadatumId + '?fetch=all_metadatum_values&nopaging=1';
@ -30,7 +35,13 @@ export const filter_type_mixin = {
for (let metadata of res.data[0]) {
let index = this.options.findIndex(itemMetadata => itemMetadata.value === metadata.mvalue);
if (index < 0 && metadata.mvalue !== '') {
this.options.push({label: metadata.mvalue, value: metadata.mvalue})
if (valuesToIgnore != undefined && valuesToIgnore.length > 0) {
let indexToIgnore = valuesToIgnore.findIndex(value => value == metadata.mvalue);
if (indexToIgnore < 0)
this.options.push({ label: metadata.mvalue, value: metadata.mvalue })
} else {
this.options.push({ label: metadata.mvalue, value: metadata.mvalue })
}
}
}
@ -40,18 +51,24 @@ export const filter_type_mixin = {
this.$console.error(error);
});
},
getValuesRelationship(collectionTarget, search) {
getValuesRelationship(collectionTarget, search, valuesToIgnore) {
let url = '/collection/' + collectionTarget + '/items?';
if( search ){
url += "search=" + search;
}
return axios.get( url + '&nopaging=1')
return axios.get(url + '&nopaging=1&fetch_only[0]=thumbnail&fetch_only[1]=title&fetch_only[2]=id')
.then(res => {
if (res.data.length > 0) {
for (let item of res.data) {
this.options.push({label: item.title, value: item.id, img: item.thumbnail.thumb });
if (valuesToIgnore != undefined && valuesToIgnore.length > 0) {
let indexToIgnore = valuesToIgnore.findIndex(value => value == item.id);
if (indexToIgnore < 0)
this.options.push({ label: item.title, value: item.id, img: (item.thumbnail.thumb ? item.thumbnail.thumb : this.thumbPlaceholderPath) });
} else {
this.options.push({ label: item.title, value: item.id, img: (item.thumbnail.thumb ? item.thumbnail.thumb : this.thumbPlaceholderPath) });
}
}
}
})

View File

@ -1,13 +1,12 @@
<template>
<div class="block">
<b-select
:id = "id"
:loading = "isLoading"
v-model = "selected"
@input = "onSelect($event)"
:id="id"
:loading="isLoading"
:value="selected"
@input="onSelect($event)"
:placeholder="$i18n.get('label_selectbox_init')"
expanded
:class="{'is-empty': selected == undefined || selected == ''}">
expanded>
<option value="">{{ $i18n.get('label_selectbox_init') }}...</option>
<option
v-for="(option, index) in options"
@ -46,6 +45,11 @@
.catch(error => {
this.$console.error(error);
});
this.$eventBusSearch.$on('removeFromFilterTag', (filterTag) => {
if (filterTag.filterId == this.filter.id)
this.onSelect();
});
},
props: {
isRepositoryLevel: Boolean,
@ -89,12 +93,20 @@
});
},
onSelect(value){
this.selected = value;
this.$emit('input', {
filter: 'selectbox',
metadatum_id: this.metadatum,
collection_id: ( this.collection_id ) ? this.collection_id : this.filter.collection_id,
value: ( value ) ? value : ''
});
if (value) {
this.$eventBusSearch.$emit( 'sendValuesToTags', {
filterId: this.filter.id,
value: value
});
}
},
selectedValues(){
if ( !this.query || !this.query.metaquery || !Array.isArray( this.query.metaquery ) )
@ -104,6 +116,7 @@
if ( index >= 0){
let metadata = this.query.metaquery[ index ];
this.selected = metadata.value;
} else {
return false;
}

View File

@ -1,15 +1,32 @@
<template>
<div class="block">
<b-taginput
icon="magnify"
size="is-small"
v-model="selected"
:data="options"
autocomplete
:loading="isLoading"
expanded
:remove-on-keys="[]"
field="label"
attached
:class="{'has-selected': selected != undefined && selected != []}"
@typing="search"/>
@typing="search"
:placeholder="(type == 'Tainacan\\Metadata_Types\\Relationship') ? $i18n.get('info_type_to_add_items') : $i18n.get('info_type_to_add_metadata')">
<template slot-scope="props">
<div class="media">
<div
class="media-left"
v-if="props.option.img">
<img
width="24"
:src="`${props.option.img}`">
</div>
<div class="media-content">
{{ props.option.label }}
</div>
</div>
</template>
</b-taginput>
</div>
</template>
@ -27,7 +44,7 @@
let in_route = '/collection/' + this.collection + '/metadata/' + this.metadatum;
if(this.isRepositoryLevel || this.collection == 'filter_in_repository'){
in_route = '/metadata?nopaging=1';
in_route = '/metadata/'+ this.metadatum + '?nopaging=1';
}
axios.get(in_route)
@ -42,13 +59,44 @@
.catch(error => {
this.$console.log(error);
});
this.$eventBusSearch.$on('removeFromFilterTag', (filterTag) => {
if (filterTag.filterId == this.filter.id) {
let selectedIndex = this.selected.findIndex(option => option.label == filterTag.singleValue);
if (selectedIndex >= 0) {
this.selected.splice(selectedIndex, 1);
let values = [];
let labels = [];
for(let val of this.selected){
values.push( val.value );
labels.push( val.label );
}
this.$emit('input', {
filter: 'taginput',
compare: 'IN',
metadatum_id: this.metadatum,
collection_id: ( this.collection_id ) ? this.collection_id : this.filter.collection_id,
value: values
});
this.$eventBusSearch.$emit( 'sendValuesToTags', {
filterId: this.filter.id,
value: labels
});
}
}
});
},
data(){
return {
results:'',
selected:[],
options: [],
isLoading: false,
type: '',
collection: '',
metadatum: '',
@ -62,39 +110,50 @@
watch: {
selected( value ){
this.selected = value;
let values = [];
let labels = [];
if( this.selected.length > 0 ){
for(let val of this.selected){
values.push( val.value );
labels.push( val.label );
}
}
this.$emit('input', {
filter: 'taginput',
compare: 'IN',
metadatum_id: this.metadatum,
collection_id: this.collection,
collection_id: ( this.collection_id ) ? this.collection_id : this.filter.collection_id,
value: values
});
this.$eventBusSearch.$emit( 'sendValuesToTags', {
filterId: this.filter.id,
value: labels
});
}
},
methods: {
search( query ){
let promise = null;
this.options = [];
let valuesToIgnore = [];
for(let val of this.selected)
valuesToIgnore.push( val.value );
if ( this.type === 'Tainacan\\Metadata_Types\\Relationship' ) {
let collectionTarget = ( this.metadatum_object && this.metadatum_object.metadata_type_options.collection_id ) ?
this.metadatum_object.metadata_type_options.collection_id : this.collection_id;
promise = this.getValuesRelationship( collectionTarget, query );
promise = this.getValuesRelationship( collectionTarget, query, valuesToIgnore );
} else {
promise = this.getValuesPlainText( this.metadatum, query, this.isRepositoryLevel );
promise = this.getValuesPlainText( this.metadatum, query, this.isRepositoryLevel, valuesToIgnore );
}
this.isLoading = true;
promise.then(() => {
this.isLoading = false;
}).catch( error => {
promise
.catch( error => {
this.$console.log('error select', error );
this.isLoading = false;
});
},
selectedValues(){
@ -102,7 +161,7 @@
if ( !this.query || !this.query.metaquery || !Array.isArray( this.query.metaquery ) )
return false;
let index = this.query.metaquery.findIndex(newMetadatum => newMetadatum.key === this.metadatum );
let index = this.query.metaquery.findIndex(newMetadatum => newMetadatum.key == this.metadatum );
if ( index >= 0){
let metadata = this.query.metaquery[ index ];
let collectionTarget = ( this.metadatum_object && this.metadatum_object.metadata_type_options.collection_id ) ?
@ -115,7 +174,7 @@
axios.get('/collection/' + collectionTarget + '/items?' + query)
.then( res => {
for (let item of res.data) {
instance.selected.push({ label: item.title, value: item.id, img: '' });
instance.selected.push({ label: item.title, value: item.id, img: item.thumbnail.thumb });
}
})
.catch(error => {

View File

@ -207,21 +207,28 @@
}
.input, .textarea, .taginput-container {
font-size: 14px;
border-radius: 1px !important;
box-shadow: none !important;
transition: background-color 0.1s;
height: 2.25em !important;
&:focus, &:active {
box-shadow: none !important;
border: none !important;
}
}
.taginput-container {
display: table-cell;
border: none !important;
&.is-focusable:active, &.is-focusable:focus {
border: none !important;
}
input, input:active, input:focus {
border: 1px solid $tainacan-input-background !important;
}
.control.has-icons-left .icon {
top: 5px;
}
.tags {
display: none !important;
}
}
.input {

View File

@ -23,6 +23,38 @@
this.metadatum = ( this.metadatum_id ) ? this.metadatum_id : this.filter.metadatum.metadatum_id ;
this.type = ( this.filter_type ) ? this.filter_type : this.filter.metadatum.metadata_type;
this.loadOptions();
this.$eventBusSearch.$on('removeFromFilterTag', (filterTag) => {
if (filterTag.filterId == this.filter.id) {
let selectedOption = this.options.find(option => option.name == filterTag.singleValue);
if(selectedOption) {
let selectedIndex = this.selected.findIndex(option => option == selectedOption.id);
if (selectedIndex >= 0) {
let newSelected = this.selected.slice();
newSelected.splice(selectedIndex, 1);
this.$emit('input', {
filter: 'checkbox',
compare: 'IN',
taxonomy: this.taxonomy,
metadatum_id: this.metadatum,
collection_id: ( this.collection_id ) ? this.collection_id : this.filter.collection_id,
terms: newSelected
});
this.$eventBusSearch.$emit( 'sendValuesToTags', {
filterId: this.filter.id,
value: newSelected
});
this.selectedValues();
}
}
}
});
},
data(){
return {
@ -76,7 +108,7 @@
promise.then( () => {
this.isLoading = false;
this.selectedValues()
this.selectedValues();
})
.catch( error => {
this.$console.log('error select', error );
@ -103,6 +135,7 @@
return result;
},
selectedValues(){
if ( !this.query || !this.query.taxquery || !Array.isArray( this.query.taxquery ) )
return false;
@ -116,13 +149,24 @@
},
onSelect(){
this.$emit('input', {
filter: 'selectbox',
filter: 'checkbox',
taxonomy: this.taxonomy,
compare: 'IN',
metadatum_id: this.metadatum,
collection_id: this.collection,
terms: this.selected
});
let onlyLabels = [];
for(let selected of this.selected) {
let valueIndex = this.options.findIndex(option => option.id == selected );
if (valueIndex >= 0)
onlyLabels.push(this.options[valueIndex].name)
}
this.$eventBusSearch.$emit("sendValuesToTags", {
filterId: this.filter.id,
value: onlyLabels
});
}
}
}

View File

@ -1,12 +1,13 @@
<template>
<div class="block">
<b-select
:id = "id"
:loading = "isLoading"
v-model = "selected"
@input = "onSelect()"
:id="id"
:loading="isLoading"
:value="selected"
@input="onSelect($event)"
size="is-small"
expanded>
expanded
:placeholder="$i18n.get('label_selectbox_init')">
<option value="">{{ $i18n.get('label_selectbox_init') }}...</option>
<option
v-for=" (option, index) in options"
@ -18,114 +19,144 @@
</template>
<script>
import { tainacan as axios } from '../../../js/axios/axios';
import { tainacan as axios } from "../../../js/axios/axios";
export default {
created(){
this.collection = ( this.collection_id ) ? this.collection_id : this.filter.collection_id;
this.metadatum = ( this.metadatum_id ) ? this.metadatum_id : this.filter.metadatum.metadatum_id ;
this.type = ( this.filter_type ) ? this.filter_type : this.filter.metadatum.metadata_type;
this.loadOptions();
},
data(){
return {
isLoading: false,
options: [],
collection: '',
metadatum: '',
selected: '',
taxonomy: ''
}
},
props: {
filter: {
type: Object // concentrate all attributes metadatum id and type
},
metadatum_id: [Number], // not required, but overrides the filter metadatum id if is set
collection_id: [Number], // not required, but overrides the filter metadatum id if is set
filter_type: [String], // not required, but overrides the filter metadatum type if is set
id: '',
query: {
type: Object // concentrate all attributes metadatum id and type
}
},
watch: {
selected: function(val){
this.selected = val;
this.onSelect();
}
},
methods: {
getValuesTaxonomy( taxonomy ){
return axios.get('/taxonomy/' + taxonomy + '/terms?hideempty=0' ).then( res => {
for (let item of res.data) {
this.taxonomy = item.taxonomy;
this.options.push(item);
}
})
.catch(error => {
this.$console.log(error);
});
},
loadOptions(){
let promise = null;
this.isLoading = true;
export default {
created() {
this.collection = this.collection_id
? this.collection_id
: this.filter.collection_id;
this.metadatum = this.metadatum_id
? this.metadatum_id
: this.filter.metadatum.metadatum_id;
this.type = this.filter_type
? this.filter_type
: this.filter.metadatum.metadata_type;
this.loadOptions();
axios.get('/collection/'+ this.collection +'/metadata/' + this.metadatum)
.then( res => {
let metadatum = res.data;
promise = this.getValuesTaxonomy( metadatum.metadata_type_options.taxonomy_id );
promise.then( () => {
this.isLoading = false;
this.selectedValues();
})
.catch( error => {
this.$console.log('error select', error );
this.isLoading = false;
});
})
.catch(error => {
this.$console.log(error);
});
},
getOptions( parent, level = 0 ){ // retrieve only ids
let result = [];
if ( this.options ){
for( let term of this.options ){
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;
},
selectedValues(){
if ( !this.query || !this.query.taxquery || !Array.isArray( this.query.taxquery ) )
return false;
let index = this.query.taxquery.findIndex(newMetadatum => newMetadatum.taxonomy === this.taxonomy );
if ( index >= 0){
let metadata = this.query.taxquery[ index ];
this.selected = metadata.terms;
} else {
return false;
}
},
onSelect(){
this.$emit('input', {
filter: 'selectbox',
compare: 'IN',
taxonomy: this.taxonomy,
metadatum_id: this.metadatum,
collection_id: this.collection,
terms: this.selected
});
}
this.$eventBusSearch.$on("removeFromFilterTag", filterTag => {
if (filterTag.filterId == this.filter.id) {
this.onSelect();
}
});
},
data() {
return {
isLoading: false,
options: [],
collection: "",
metadatum: "",
selected: "",
taxonomy: ""
};
},
props: {
filter: {
type: Object // concentrate all attributes metadatum id and type
},
metadatum_id: [Number], // not required, but overrides the filter metadatum id if is set
collection_id: [Number], // not required, but overrides the filter metadatum id if is set
filter_type: [String], // not required, but overrides the filter metadatum type if is set
id: "",
query: {
type: Object // concentrate all attributes metadatum id and type
}
},
methods: {
getValuesTaxonomy(taxonomy) {
return axios
.get("/taxonomy/" + taxonomy + "/terms?hideempty=0")
.then(res => {
for (let item of res.data) {
this.taxonomy = item.taxonomy;
this.options.push(item);
}
})
.catch(error => {
this.$console.log(error);
});
},
loadOptions() {
let promise = null;
this.isLoading = true;
axios
.get("/collection/" + this.collection + "/metadata/" + this.metadatum)
.then(res => {
let metadatum = res.data;
promise = this.getValuesTaxonomy(
metadatum.metadata_type_options.taxonomy_id
);
promise
.then(() => {
this.isLoading = false;
this.selectedValues();
})
.catch(error => {
this.$console.log("error select", error);
this.isLoading = false;
});
})
.catch(error => {
this.$console.log(error);
});
},
getOptions(parent, level = 0) {
// retrieve only ids
let result = [];
if (this.options) {
for (let term of this.options) {
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;
},
selectedValues() {
if (
!this.query ||
!this.query.taxquery ||
!Array.isArray(this.query.taxquery)
)
return false;
let index = this.query.taxquery.findIndex(
newMetadatum => newMetadatum.taxonomy === this.taxonomy
);
if (index >= 0) {
let metadata = this.query.taxquery[index];
this.selected = metadata.terms;
} else {
return false;
}
},
onSelect(value) {
this.selected = value;
this.$emit("input", {
filter: "selectbox",
compare: "IN",
taxonomy: this.taxonomy,
metadatum_id: this.metadatum,
collection_id: this.collection,
terms: this.selected
});
let valueIndex = this.options.findIndex(
option => option.id == this.selected
);
if (valueIndex >= 0) {
this.$eventBusSearch.$emit("sendValuesToTags", {
filterId: this.filter.id,
value: this.options[valueIndex].name
});
}
}
}
};
</script>

View File

@ -2,14 +2,17 @@
<div class="block">
<b-taginput
size="is-small"
icon="magnify"
v-model="selected"
:data="options"
:loading="isLoading"
autocomplete
expanded
:remove-on-keys="[]"
field="label"
attached
:class="{'has-selected': selected != undefined && selected != []}"
@typing="search" />
@typing="search"
:placeholder="$i18n.get('info_type_to_add_terms')" />
</div>
</template>
@ -33,6 +36,39 @@
let metadatum = res.data;
this.selectedValues( metadatum.metadata_type_options.taxonomy_id );
});
this.$eventBusSearch.$on('removeFromFilterTag', (filterTag) => {
if (filterTag.filterId == this.filter.id) {
let selectedIndex = this.selected.findIndex(option => option.label == filterTag.singleValue);
if (selectedIndex >= 0) {
this.selected.splice(selectedIndex, 1);
let values = [];
let labels = [];
for(let val of this.selected){
values.push( val.value );
labels.push( val.label );
}
this.$emit('input', {
filter: 'taginput',
compare: 'IN',
taxonomy: this.taxonomy,
metadatum_id: ( this.metadatum_id ) ? this.metadatum_id : this.filter.metadatum,
collection_id: ( this.collection_id ) ? this.collection_id : this.filter.collection_id,
terms: values
});
this.$eventBusSearch.$emit( 'sendValuesToTags', {
filterId: this.filter.id,
value: labels
});
}
}
});
},
data(){
return {
@ -62,10 +98,13 @@
watch: {
selected( value ){
this.selected = value;
let values = [];
let labels = [];
if( this.selected.length > 0 ){
for(let val of this.selected){
values.push( val.value );
labels.push( val.label );
}
}
this.$emit('input', {
@ -76,13 +115,19 @@
collection_id: ( this.collection_id ) ? this.collection_id : this.filter.collection_id,
terms: values
});
this.$eventBusSearch.$emit("sendValuesToTags", {
filterId: this.filter.id,
value: labels
});
}
},
methods: {
search( query ){
let promise = null;
this.options = [];
const q = query;
const q = query;
const endpoint = this.isRepositoryLevel ? '/metadata/' + this.metadatum : '/collection/'+ this.collection +'/metadata/' + this.metadatum;
axios.get(endpoint)
@ -103,12 +148,26 @@
});
},
getValuesTaxonomy( taxonomy, query ){
let valuesToIgnore = [];
for(let val of this.selected)
valuesToIgnore.push( val.value );
return axios.get('/taxonomy/' + taxonomy + '/terms?hideempty=0&order=asc' ).then( res => {
for (let term of res.data) {
if( term.name.toLowerCase().indexOf( query.toLowerCase() ) >= 0 ){
this.taxonomy = term.taxonomy;
this.options.push({label: term.name, value: term.id});
}
for (let term of res.data) {
if (valuesToIgnore != undefined && valuesToIgnore.length > 0) {
let indexToIgnore = valuesToIgnore.findIndex(value => value == term.id);
if (indexToIgnore < 0) {
if( term.name.toLowerCase().indexOf( query.toLowerCase() ) >= 0 ){
this.taxonomy = term.taxonomy;
this.options.push({label: term.name, value: term.id});
}
}
} else {
if( term.name.toLowerCase().indexOf( query.toLowerCase() ) >= 0 ){
this.taxonomy = term.taxonomy;
this.options.push({label: term.name, value: term.id});
}
}
}
})
.catch(error => {
@ -119,7 +178,7 @@
if ( !this.query || !this.query.taxquery || !Array.isArray( this.query.taxquery ) )
return false;
let index = this.query.taxquery.findIndex(newMetadatum => newMetadatum.taxonomy === this.taxonomy );
let index = this.query.taxquery.findIndex(newMetadatum => newMetadatum.taxonomy == 'tnc_tax_' + taxonomy );
if ( index >= 0){
let metadata = this.query.taxquery[ index ];
for ( let id of metadata.terms ){
@ -130,8 +189,9 @@
}
},
getTerm( taxonomy, id ){
return axios.get('/taxonomy/' + taxonomy + '/terms/' + id + '?order=asc&hideempty=0' ).then( res => {
this.$console.log(res);
return axios.get('/taxonomy/' + taxonomy + '/terms/' + id + '?order=asc&hideempty=0' )
.then( res => {
this.selected.push({ label: res.data.name, value: res.data.id })
})
.catch(error => {
this.$console.log(error);

View File

@ -1,5 +1,5 @@
<template>
<div>
<div :class="{ 'is-flex': metadatum.metadatum.multiple != 'yes' }">
<b-taginput
:id="id"
v-model="selected"
@ -147,4 +147,7 @@
.help.counter {
display: none;
}
div.is-flex {
justify-content: flex-start;
}
</style>

View File

@ -27,7 +27,6 @@
:is="metadatum.metadatum.metadata_type_object.component"
v-model="inputs[0]"
:metadatum="metadatum"
@blur="changeValue()"
@input="emitIsChangingValue()"/>
<div v-if="metadatum.metadatum.multiple == 'yes'">
<div
@ -40,7 +39,6 @@
:is="metadatum.metadatum.metadata_type_object.component"
v-model="inputs[index]"
:metadatum="metadatum"
@blur="changeValue()"
@input="emitIsChangingValue()"/>
<a
v-if="index > 0"
@ -72,7 +70,6 @@
:is="metadatum.metadatum.metadata_type_object.component"
v-model="inputs"
:metadatum="metadatum"
@blur="changeValue()"
@input="emitIsChangingValue()"/>
</div>
</b-field>
@ -124,14 +121,14 @@
},
methods: {
emitIsChangingValue() {
eventBus.isChangingValue(true);
this.changeValue();
},
changeValue(){
changeValue: _.debounce(function() {
if(this.metadatum.value != this.inputs){
if(this.inputs.length > 0 && this.inputs[0].value){
let terms = []
let terms = [];
for(let term of this.inputs){
terms.push(term.value);
@ -179,7 +176,7 @@
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) {
this.inputs = this.metadatum.value.slice(0);

View File

@ -13,11 +13,21 @@ class CSV extends Importer {
parent::__construct($attributes);
$this->set_default_options([
'delimiter' => ','
'delimiter' => ',',
'multivalued_delimiter' => '||',
'encode' => 'utf8',
'enclosure' => '"'
]);
}
/**
* alter the default options
*/
public function set_option($key,$value){
$this->default_options[$key] = $value;
}
/**
* @inheritdoc
*/
@ -42,19 +52,27 @@ class CSV extends Importer {
if( $index === 0 ){
$file->current();
$file->next();
$values = $file->fgetcsv( $this->get_option('delimiter') );
$values = $file->fgetcsv( $this->get_option('delimiter'), $this->get_option('enclosure') );
}else{
$values = $file->fgetcsv( $this->get_option('delimiter') );
$values = $file->fgetcsv( $this->get_option('delimiter'), $this->get_option('enclosure') );
}
if( count( $headers ) !== count( $values ) ){
return false;
}
$cont = 0;
foreach ( $collection_definition['mapping'] as $metadatum_id => $header) {
$metadatum = new \Tainacan\Entities\Metadatum($metadatum_id);
foreach ($headers as $index => $header) {
$processedItem[ $header ] = $values[ $index ];
$column = $this->handle_encoding( $values[ $cont ] );
$processedItem[ $header ] = ( $metadatum->get_multiple() ) ?
explode( $this->get_option('multivalued_delimiter'), $column) : $column;
$cont++;
}
return $processedItem;
}
@ -71,4 +89,52 @@ class CSV extends Importer {
return false;
}
public function options_form() {
$form = '<label class="label">' . __('Delimiter', 'tainacan') . '</label>';
$form .= '<input type="text" class="input" name="delimiter" value="' . $this->get_option('delimiter') . '" />';
$form .= '<label class="label">' . __('Multivalued metadata delimiter', 'tainacan') . '</label>';
$form .= '<input type="text" class="input" name="multivalued_delimiter" value="' . $this->get_option('multivalued_delimiter') . '" />';
$form .= '<div class="control">';
$form = '<label class="label">' . __('Encoding', 'tainacan') . '</label>';
$form .= '<label class="radio">';
$form .= '<input type="radio" name="encode" value="utf8" '
. ( !$this->get_option('encode') || $this->get_option('encode') === 'utf8' ) ? 'checked' : '' . ' />';
$form .= __('UTF8', 'tainacan') . '</label>';
$form .= '<label class="radio">';
$form .= '<input type="radio" name="encode" value="iso88591" '
. ( !$this->get_option('encode') || $this->get_option('encode') === 'iso88591' ) ? 'checked' : '' . ' />';
$form .= __('ISO 8859-1', 'tainacan') . '</label>';
$form .= '</div>';
$form .= '<label class="label">' . __('Enclosure character', 'tainacan') . '</label>';
$form .= '<input type="text" class="input" size="1" name="enclosure" value="' . $this->get_option('enclosure') . '" />';
return $form;
}
/**
* get the encode option and return as expected
*/
private function handle_encoding($string){
switch( $this->get_option('encode') ){
case 'utf8':
return $string;
case 'iso88591':
return utf8_encode($string);
default:
return $string;
}
}
}

View File

@ -192,6 +192,7 @@ abstract class Importer {
$return['manual_collection'] = $this->manual_collection;
$return['manual_mapping'] = $this->manual_mapping;
$return['accepts'] = $this->accepts;
$return['options_form'] = $this->options_form();
}
return $return;
@ -678,6 +679,12 @@ abstract class Importer {
* @return int
*/
public function get_source_number_of_items() {}
/**
* Method implemented by child importer to return the HTML of the Options Form to be rendered in the Importer page
*/
public function options_form() {}

View File

@ -118,6 +118,9 @@ class Old_Tainacan extends Importer{
}
}
$this->add_log('FInished repository metadata');
return false;
}
/**
@ -130,6 +133,7 @@ class Old_Tainacan extends Importer{
foreach ($this->fetch_collections() as $collection) {
$map = [];
$this->add_log(memory_get_usage());
if ( isset($collection->post_title) && $collection->post_status === 'publish') {
@ -156,6 +160,8 @@ class Old_Tainacan extends Importer{
}
}
return false;
}
/**
@ -204,6 +210,8 @@ class Old_Tainacan extends Importer{
}
}
}
return false;
}
/**
@ -220,7 +228,7 @@ class Old_Tainacan extends Importer{
$this->add_log('Proccess item index' . $index . ' in collection OLD ' . $collection_id['source_id'] );
$info = wp_remote_get( $this->get_url() . $this->tainacan_api_address . "/collections/".$collection_id['source_id']."/items?includeMetadata=1&filter[items_per_page]=1&filter[page]=" . $page, $args );
$info = $this->requester( $this->get_url() . $this->tainacan_api_address . "/collections/".$collection_id['source_id']."/items?includeMetadata=1&filter[items_per_page]=1&filter[page]=" . $page, $args );
$info = json_decode($info['body']);
if( !isset( $info->items ) ){
@ -391,7 +399,7 @@ class Old_Tainacan extends Importer{
'redirection' => 30,
);
$info = wp_remote_get( $this->get_url() . $this->tainacan_api_address . "/collections/".$collection_id."/items", $args );
$info = $this->requester( $this->get_url() . $this->tainacan_api_address . "/collections/".$collection_id."/items", $args );
if( !isset($info['body']) ){
$this->add_error_log($result->get_error_message());
@ -547,12 +555,55 @@ class Old_Tainacan extends Importer{
* executes the request
*/
protected function requester( $link ){
$has_response = false;
$requests = 0;
$args = array(
'timeout' => 30,
'timeout' => 60,
'redirection' => 30,
);
return wp_remote_get($link, $args);
$this->add_log('fetching init ' . $link );
$result = wp_remote_get($link, $args);
while( !$has_response ){
if (is_wp_error($result)) {
$this->add_log($result->get_error_message());
$this->add_log('Error in fetch remote' . $url);
$this->add_log('request number ' . $requests);
} else if (isset($result['body'])){
$this->add_log('fetch OK ');
return $result;
}
if( $requests > 10 ){
break;
}
if( $requests > 3 ){
$this->add_log('taking a moment to breathe, waiting for ' . ( $requests * 10 ) . ' seconds ' );
sleep( $requests * 10 );
}
$args = array(
'timeout' => 60,
'redirection' => 30,
);
$result = wp_remote_get($link, $args);
$requests++;
$this->add_log('going to ' . $requests );
}
$this->add_error_log('Error in fetch remote, expired the 10 requests limit ' . $url);
$this->abort();
return false;
}
/**
@ -687,9 +738,8 @@ class Old_Tainacan extends Importer{
return $inserted_metadata->get_id();
} else{
$this->add_error_log('Error creating metadata ' . $name );
$this->add_error_log($newMetadatum->get_errors());
$this->abort();
$this->add_log('Error creating metadata ' . $name . ' in collection ' . $collection_id);
$this->add_log($newMetadatum->get_errors());
return false;
}
}

View File

@ -25,6 +25,10 @@ export default {
this.updateURLQueries();
});
this.$on('sendValuesToTags', data => {
this.$store.dispatch('search/addFilterTag', data);
});
this.$root.$on('closeAdvancedSearch', () => {
this.$store.dispatch('search/setPage', 1);
@ -46,9 +50,9 @@ export default {
if (this.$route.name == 'CollectionItemsPage' || this.$route.name == 'ItemsPage')
this.collectionId = !this.$route.params.collectionId ? this.$route.params.collectionId : parseInt(this.$route.params.collectionId);
// Fills the URL with apropriate default values in case a query is not passed
// Fills the URL with appropriate default values in case a query is not passed
if (this.$route.name == null || this.$route.name == undefined || this.$route.name == 'CollectionItemsPage' || this.$route.name == 'ItemsPage') {
// Items Per Page
if (this.$route.query.perpage == undefined || to.params.collectionId != from.params.collectionId) {
let perPageKey = (this.collectionId != undefined ? 'items_per_page_' + this.collectionId : 'items_per_page');
@ -143,16 +147,17 @@ export default {
this.$userPrefs.set(adminViewModeKey, 'table');
}
}
// Advanced Search
if (this.$route.query && this.$route.query.advancedSearch){
this.$store.dispatch('search/set_advanced_query', this.$route.query);
} else {
this.$store.dispatch('search/set_postquery', this.$route.query);
}
this.loadItems(to);
}
}
},
methods: {
@ -165,6 +170,15 @@ export default {
this.$store.dispatch('search/add_metaquery', data );
}
},
removeMetaQuery(query) {
this.$store.dispatch('search/remove_metaquery', query );
this.updateURLQueries();
},
removeMetaFromFilterTag(filterTag) {
this.$emit('removeFromFilterTag', filterTag);
if (filterTag.singleValue == undefined)
this.$store.dispatch('search/removeFilterTag', filterTag);
},
add_taxquery( data ){
if ( data && data.collection_id ){
this.$store.dispatch('search/add_taxquery', data );
@ -176,6 +190,7 @@ export default {
},
addFetchOnly( metadatum ){
let prefsFetchOnly = this.collectionId != undefined ? 'fetch_only_' + this.collectionId : 'fetch_only';
if(this.$userPrefs.get(prefsFetchOnly) != metadatum) {
this.$userPrefs.set(prefsFetchOnly, metadatum)
.catch(() => {});
@ -281,7 +296,7 @@ export default {
loadItems(to) {
// Forces fetch_only to be filled before any search happens
if (this.$store.getters['search/getFetchOnly'] == undefined) {
if (this.$store.getters['search/getPostQuery']['fetch_only'] == undefined) {
this.$emit( 'hasToPrepareMetadataAndFilters', to);
} else {
@ -308,6 +323,12 @@ export default {
},
setCollectionId(collectionId) {
this.collectionId = collectionId;
},
clearAllFilters() {
this.$store.dispatch('search/cleanFilterTags');
this.$store.dispatch('search/cleanMetaQueries');
this.$store.dispatch('search/cleanTaxQueries');
this.updateURLQueries();
},
/* Dev interfaces methods */

View File

@ -33,13 +33,11 @@ export const eventBus = new Vue({
}
});
}
},
isChangingValue() {
this.$emit('isChangingValue', true);
},
},
updateValue(data){
this.$emit('isUpdatingValue', true);
if ( data.item_id ){
if(data.values.length > 0 && data.values[0].value){
@ -55,7 +53,7 @@ export const eventBus = new Vue({
const promisse = this.$store.dispatch('item/updateMetadata',
{ item_id: data.item_id, metadatum_id: data.metadatum_id, values: values });
promisse.then( () => {
promisse.then( () => {
this.$emit('isUpdatingValue', false);
let index = this.errors.findIndex( errorItem => errorItem.metadatum_id == data.metadatum_id );
if ( index >= 0){

View File

@ -8,8 +8,7 @@ export const fetchItems = ({ rootGetters, dispatch, commit }, { collectionId, is
// Adds queries for filtering
let postQueries = rootGetters['search/getPostQuery'];
let query = '';
// Sets a flag to inform components that an empty sate is or not due to filtering
let hasFiltered = false;
let advancedSearchResults = false;
@ -27,9 +26,9 @@ export const fetchItems = ({ rootGetters, dispatch, commit }, { collectionId, is
}
}
query = qs.stringify(postQueries);
let query = qs.stringify(postQueries);
// Garanttees at least empty fetch_only are passed in case none is found
// Guarantees at least empty fetch_only are passed in case none is found
if (qs.stringify(postQueries.fetch_only) == ''){
dispatch('search/add_fetchonly', {}, { root: true });
}

View File

@ -95,6 +95,22 @@ export const updateImporterURL = ( { commit }, { sessionId, url }) => {
});
};
export const updateImporterOptions = ( { commit }, { sessionId, options }) => {
return new Promise(( resolve, reject ) => {
axios.tainacan.put('importers/session/' + sessionId, {
options: options
})
.then( res => {
let importer = res.data;
commit('setImporter', importer);
resolve( importer );
})
.catch(error => {
reject(error);
});
});
};
export const updateImporterFile = ( { commit }, { sessionId, file }) => {
return new Promise(( resolve, reject ) => {

View File

@ -53,10 +53,14 @@ export const cleanMetadata = ({ commit }) => {
commit('cleanMetadata');
};
export const cleanLastUpdated = ({commit}) => {
export const cleanLastUpdated = ({ commit }) => {
commit('cleanLastUpdated');
};
export const setLastUpdated = ({ commit}, value) => {
commit('setLastUpdated', value);
};
// Actions directly related to Item
export const fetchItem = ({ commit }, item_id) => {
commit('cleanItem')
@ -172,7 +176,6 @@ export const fetchAttachments = ({ commit }, item_id) => {
});
};
export const updateThumbnail = ({ commit }, { itemId, thumbnailId }) => {
return new Promise((resolve, reject) => {
axios.tainacan.patch('/items/' + itemId, {

View File

@ -9,7 +9,7 @@ export const cleanItem = ( state ) => {
}
export const cleanLastUpdated = ( state ) => {
state.cleanLastUpdated = '';
state.lastUpdated = '';
}
export const setSingleAttachment = ( state, attachment ) => {
@ -60,8 +60,12 @@ export const setSingleMetadatum = ( state, metadatum) => {
}
}
export const setLastUpdated = (state) => {
let now = new Date();
state.lastUpdated = now.toLocaleString();
export const setLastUpdated = (state, value) => {
if (value != undefined)
state.lastUpdated = value;
else {
let now = new Date();
state.lastUpdated = now.toLocaleString();
}
}

View File

@ -76,6 +76,26 @@ export const updateMetadatum = ({commit}, {collectionId, metadatumId, isReposito
});
};
export const fetchMetadatum = ({commit}, {collectionId, metadatumId}) => {
return new Promise((resolve, reject) => {
let endpoint = '';
if (collectionId && collectionId != "default")
endpoint = '/collection/' + collectionId + '/metadata/' + metadatumId;
else
endpoint = '/metadata/' + metadatumId;
axios.tainacan.get(endpoint)
.then((res) => {
let metadata = res.data;
resolve(metadata);
})
.catch((error) => {
console.log(error);
reject(error);
});
});
};
export const updateMetadata = ({commit}, metadata) => {
commit('setMetadata', metadata);
};

View File

@ -13,7 +13,7 @@ export const set_advanced_query = ({commit}, advancedSearchQuery) => {
// Meta Queries from filters
export const add_metaquery = ( { commit }, filter ) => {
if( filter && filter.value.length === 0 ){
if (filter && (filter.value == undefined || filter.value == null || filter.value.length === 0 || filter.value == '')) {
commit('removeMetaQuery', filter );
} else {
commit('addMetaQuery', filter );
@ -22,7 +22,7 @@ export const add_metaquery = ( { commit }, filter ) => {
// Fetch Only for item attributes limiting on results
export const add_fetchonly = ( { commit }, metadatum ) => {
commit('addFetchOnly', metadatum );
commit('addFetchOnly', metadatum );
};
export const remove_fetchonly = ( { commit }, metadatum ) => {
commit('removeFetchOnly', metadatum );
@ -38,7 +38,7 @@ export const remove_fetchonly_meta = ( { commit }, metadatum ) => {
// Tax Queries from filters
export const add_taxquery = ( { commit }, filter ) => {
if( filter && filter.terms.length === 0 ){
if (filter && (filter.terms == undefined || filter.terms == null || filter.terms == '' || filter.terms.length == 0 )) {
commit('removeTaxQuery', filter );
} else {
commit('addTaxQuery', filter );
@ -111,4 +111,27 @@ export const setViewMode = ({ commit }, viewMode ) => {
// Set AdminViewMode (admin_view_mode)
export const setAdminViewMode = ({ commit }, adminViewMode ) => {
commit('setAdminViewMode', adminViewMode );
};
};
// Remove filter tag
export const addFilterTag = ( { commit }, filterTag ) => {
commit('addFilterTag', filterTag );
};
// Remove filter tag
export const removeFilterTag = ( { commit }, filterTag ) => {
commit('removeFilterTag', filterTag );
};
// Remove filter tag
export const cleanFilterTags = ( { commit } ) => {
commit('cleanFilterTags');
};
export const cleanMetaQueries = ( { commit } ) => {
commit('cleanMetaQueries');
};
export const cleanTaxQueries = ({ commit }) => {
commit('cleanTaxQueries');
};

View File

@ -61,4 +61,8 @@ export const getFetchOnly = state => {
export const getFetchOnlyMeta = state => {
return ( ! state.postquery.fetch_only['meta'] ) ? [] : state.postquery.fetch_only['meta'];
};
};
export const getFilterTags = state => {
return state.filter_tags;
};

View File

@ -22,6 +22,7 @@ const state = {
view_mode: 'table',
admin_view_mode: 'table'
},
filter_tags: [],
totalItems: 0
};

View File

@ -14,12 +14,12 @@ export const setPostQuery = ( state, postquery ) => {
export const setAdvancedSearchQuery = (state, advancedSearchQuery) => {
state.postquery.advancedSearch = advancedSearchQuery.advancedSearch;
state.postquery.metaquery = advancedSearchQuery.metaquery;
state.postquery.taxquery = advancedSearchQuery.taxquery;
state.postquery.metaquery = Object.assign({}, advancedSearchQuery.metaquery);
state.postquery.taxquery = Object.assign({}, advancedSearchQuery.taxquery);
};
export const addMetaQuery = ( state, filter ) => {
state.postquery.metaquery = ( ! state.postquery.metaquery ) ? [] : state.postquery.metaquery;
state.postquery.metaquery = ( ! state.postquery.metaquery || state.postquery.metaquery.length == undefined ) ? [] : state.postquery.metaquery;
let index = state.postquery.metaquery.findIndex( item => item.key === filter.metadatum_id);
@ -41,7 +41,7 @@ export const addMetaQuery = ( state, filter ) => {
};
export const addTaxQuery = ( state, filter ) => {
state.postquery.taxquery = ( ! state.postquery.taxquery ) ? [] : state.postquery.taxquery;
state.postquery.taxquery = ( ! state.postquery.taxquery || state.postquery.taxquery.length == undefined ) ? [] : state.postquery.taxquery;
let index = state.postquery.taxquery.findIndex( item => item.taxonomy === filter.taxonomy);
if ( index >= 0 ){
Vue.set( state.postquery.taxquery, index, {
@ -62,8 +62,9 @@ export const addFetchOnly = ( state, metadatum ) => {
state.postquery.fetch_only = ( ! state.postquery.fetch_only ) ? { '0': 'thumbnail', 'meta': [], '1': 'creation_date', '2': 'author_name' } : state.postquery.fetch_only;
for (let key in metadatum) {
state.postquery.fetch_only[key] = metadatum[key];
Vue.set(state.postquery.fetch_only, `${key}`, metadatum[key]);
}
};
export const addFetchOnlyMeta = ( state, metadatum ) => {
state.postquery.fetch_only = ( ! state.postquery.fetch_only ) ? { '0': 'thumbnail', 'meta': [], '1': 'creation_date', '2': 'author_name' } : state.postquery.fetch_only;
@ -97,14 +98,14 @@ export const removeFetchOnlyMeta = ( state, metadatum ) => {
export const removeMetaQuery = ( state, filter ) => {
state.postquery.metaquery = ( ! state.postquery.metaquery ) ? [] : state.postquery.metaquery;
let index = state.postquery.metaquery.findIndex( item => item.key === filter.metadatum_id);
let index = state.postquery.metaquery.findIndex( item => item.key == filter.metadatum_id);
if (index >= 0) {
state.postquery.metaquery.splice(index, 1);
}
};
export const removeTaxQuery = ( state, filter ) => {
let index = state.postquery.taxquery.findIndex( item => item.taxonomy === filter.taxonomy);
let index = state.postquery.taxquery.findIndex( item => item.taxonomy == filter.taxonomy);
if (index >= 0) {
state.postquery.taxquery.splice(index, 1);
}
@ -132,4 +133,33 @@ export const setViewMode = ( state, viewMode ) => {
export const setAdminViewMode = ( state, adminViewMode ) => {
state.postquery.admin_view_mode = adminViewMode;
};
export const addFilterTag = ( state, filterTag ) => {
state.filter_tags = ( ! state.filter_tags) ? [] : state.filter_tags;
let index = state.filter_tags.findIndex( tag => tag.filterId == filterTag.filterId);
if ( index >= 0 )
Vue.set( state.filter_tags, index, filterTag );
else
state.filter_tags.push(filterTag);
};
export const removeFilterTag = ( state, filterTag ) => {
state.filter_tags = ( ! state.filter_tags ) ? [] : state.filter_tags;
let index = state.filter_tags.findIndex( tag => tag.filterId == filterTag.filterId);
if (index >= 0) {
state.filter_tags.splice(index, 1);
}
};
export const cleanFilterTags = ( state ) => {
state.filter_tags = [];
};
export const cleanMetaQueries = (state) => {
state.postquery.metaquery = [];
};
export const cleanTaxQueries = (state) => {
state.postquery.taxquery = [];
};

View File

@ -53,8 +53,8 @@ function tainacan_get_the_metadata($args = array()) {
}
function tainacan_the_metadata($metadatum = null, $args = array()) {
echo tainacan_get_the_metadata($metadatum, $args);
function tainacan_the_metadata($args = array()) {
echo tainacan_get_the_metadata($args);
}
/**

847
tests/test-bulkedit.php Normal file
View File

@ -0,0 +1,847 @@
<?php
namespace Tainacan\Tests;
/**
* Class TestCollections
*
* @package Test_Tainacan
*/
use Tainacan\Entities;
/**
* Sample test case.
*/
class BulkEdit extends TAINACAN_UnitApiTestCase {
public $items_ids = [];
function setUp() {
parent::setUp();
$collection = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'test_col',
'status' => 'publish'
),
true
);
$this->collection = $collection;
$metadatum = $this->tainacan_entity_factory->create_entity(
'metadatum',
array(
'name' => 'metadado',
'status' => 'publish',
'collection' => $collection,
'metadata_type' => 'Tainacan\Metadata_Types\Text',
),
true
);
$this->metadatum = $metadatum;
$multiple_meta = $this->tainacan_entity_factory->create_entity(
'metadatum',
array(
'name' => 'multimetadado',
'status' => 'publish',
'collection' => $collection,
'metadata_type' => 'Tainacan\Metadata_Types\Text',
'multiple' => 'yes',
'required' => 'no'
),
true
);
$this->multiple_meta = $multiple_meta;
$taxonomy = $this->tainacan_entity_factory->create_entity(
'taxonomy',
array(
'name' => 'genero',
'description' => 'tipos de musica',
'allow_insert' => 'yes'
),
true
);
$this->taxonomy = $taxonomy;
$category = $this->tainacan_entity_factory->create_entity(
'metadatum',
array(
'name' => 'category',
'status' => 'publish',
'collection' => $collection,
'metadata_type' => 'Tainacan\Metadata_Types\Taxonomy',
'metadata_type_options' => [
'allow_new_terms' => true,
'taxonomy_id' => $taxonomy->get_id()
],
'multiple' => 'yes'
),
true
);
$this->category = $category;
for ($i = 1; $i<=40; $i++) {
$item = $this->tainacan_entity_factory->create_entity(
'item',
array(
'title' => 'testeItem ' . $i,
'collection' => $collection,
'status' => 'publish'
),
true
);
$this->items_ids[] = $item->get_id();
$this->tainacan_item_metadata_factory->create_item_metadata($item, $metadatum, $i % 2 == 0 ? 'even' : 'odd');
$this->tainacan_item_metadata_factory->create_item_metadata($item, $category, ['good', 'bad']);
}
$this->api_baseroute = $this->namespace . '/collection/' . $collection->get_id() . '/bulk-edit';
}
function test_setup() {
$this->assertEquals(40, sizeof($this->items_ids));
}
function test_init_by_query() {
$query = [
'meta_query' => [
[
'key' => $this->metadatum->get_id(),
'value' => 'even'
]
],
'posts_per_page' => -1
];
$bulk = new \Tainacan\Bulk_Edit([
'query' => $query,
'collection_id' => $this->collection->get_id()
]);
$this->assertEquals(20, $bulk->count_posts());
}
function test_init_by_ids() {
$ids = array_slice($this->items_ids, 2, 7);
$bulk = new \Tainacan\Bulk_Edit([
'items_ids' => $ids,
]);
$this->assertEquals(7, $bulk->count_posts());
}
function test_init_by_bulk_id() {
$ids = array_slice($this->items_ids, 4, 11);
$bulk = new \Tainacan\Bulk_Edit([
'items_ids' => $ids,
]);
$id = $bulk->get_id();
$newBulk = new \Tainacan\Bulk_Edit([
'id' => $id,
]);
$this->assertEquals(11, $newBulk->count_posts());
}
function test_add() {
$Tainacan_Items = \Tainacan\Repositories\Items::get_instance();
$query = [
'meta_query' => [
[
'key' => $this->metadatum->get_id(),
'value' => 'even'
]
],
'posts_per_page' => -1
];
$bulk = new \Tainacan\Bulk_Edit([
'query' => $query,
'collection_id' => $this->collection->get_id()
]);
$bulk->add_value($this->category, 'test');
$items = $Tainacan_Items->fetch([
'tax_query' => [
[
'taxonomy' => $this->taxonomy->get_db_identifier(),
'field' => 'name',
'terms' => 'test'
]
],
'posts_per_page' => -1
]);
$this->assertEquals(20, $items->found_posts);
$items = $Tainacan_Items->fetch([
'meta_query' => [
[
'key' => $this->metadatum->get_id(),
'value' => 'odd'
]
],
'tax_query' => [
[
'taxonomy' => $this->taxonomy->get_db_identifier(),
'field' => 'name',
'terms' => 'test'
]
],
'posts_per_page' => -1
]);
$this->assertEquals(0, $items->found_posts);
$bulk->add_value($this->multiple_meta, 'super');
$items = $Tainacan_Items->fetch([
'meta_query' => [
[
'key' => $this->metadatum->get_id(),
'value' => 'even'
],
[
'key' => $this->multiple_meta->get_id(),
'value' => 'super'
]
],
'tax_query' => [
[
'taxonomy' => $this->taxonomy->get_db_identifier(),
'field' => 'name',
'terms' => 'test'
]
],
'posts_per_page' => -1
]);
$this->assertEquals(20, $items->found_posts);
$items = $Tainacan_Items->fetch([
'meta_query' => [
[
'key' => $this->metadatum->get_id(),
'value' => 'odd'
],
[
'key' => $this->multiple_meta->get_id(),
'value' => 'super'
]
],
'posts_per_page' => -1
]);
$this->assertEquals(0, $items->found_posts);
}
function test_remove_value_from_taxonomy_metadatum() {
$Tainacan_Items = \Tainacan\Repositories\Items::get_instance();
$query = [
'meta_query' => [
[
'key' => $this->metadatum->get_id(),
'value' => 'even'
]
],
'posts_per_page' => -1
];
$bulk = new \Tainacan\Bulk_Edit([
'query' => $query,
'collection_id' => $this->collection->get_id()
]);
$bulk->remove_value($this->category, 'good');
$items = $Tainacan_Items->fetch([
'tax_query' => [
[
'taxonomy' => $this->taxonomy->get_db_identifier(),
'field' => 'name',
'terms' => 'good'
]
],
'posts_per_page' => -1
]);
$this->assertEquals(20, $items->found_posts);
$items = $Tainacan_Items->fetch([
'tax_query' => [
[
'taxonomy' => $this->taxonomy->get_db_identifier(),
'field' => 'name',
'terms' => 'bad'
]
],
'posts_per_page' => -1
]);
$this->assertEquals(40, $items->found_posts);
}
function test_remove_value_from_regular_metadatum() {
$Tainacan_Items = \Tainacan\Repositories\Items::get_instance();
$bulk = new \Tainacan\Bulk_Edit([
'items_ids' => $this->items_ids,
]);
$bulk->add_value($this->multiple_meta, 'test'); // for everyone
$query = [
'meta_query' => [
[
'key' => $this->metadatum->get_id(),
'value' => 'even'
]
],
'posts_per_page' => -1
];
$bulk = new \Tainacan\Bulk_Edit([
'query' => $query,
'collection_id' => $this->collection->get_id()
]);
$bulk->remove_value($this->multiple_meta, 'test');
$items = $Tainacan_Items->fetch([
'meta_query' => [
[
'key' => $this->multiple_meta->get_id(),
'value' => 'test'
]
],
'posts_per_page' => -1
]);
$this->assertEquals(20, $items->found_posts);
}
function test_replace_value_in_tax_metadata() {
$Tainacan_Items = \Tainacan\Repositories\Items::get_instance();
$query = [
'meta_query' => [
[
'key' => $this->metadatum->get_id(),
'value' => 'even'
]
],
'posts_per_page' => -1
];
$bulk = new \Tainacan\Bulk_Edit([
'query' => $query,
'collection_id' => $this->collection->get_id()
]);
$bulk->replace_value($this->category, 'awesome', 'good');
$items = $Tainacan_Items->fetch([
'tax_query' => [
[
'taxonomy' => $this->taxonomy->get_db_identifier(),
'field' => 'name',
'terms' => 'good'
]
],
'posts_per_page' => -1
]);
$this->assertEquals(20, $items->found_posts);
$items = $Tainacan_Items->fetch([
'tax_query' => [
[
'taxonomy' => $this->taxonomy->get_db_identifier(),
'field' => 'name',
'terms' => 'awesome'
]
],
'posts_per_page' => -1
]);
$this->assertEquals(20, $items->found_posts);
$items = $Tainacan_Items->fetch([
'tax_query' => [
[
'taxonomy' => $this->taxonomy->get_db_identifier(),
'field' => 'name',
'terms' => 'bad'
]
],
'posts_per_page' => -1
]);
$this->assertEquals(40, $items->found_posts);
}
function test_replace_regular_metadata() {
$Tainacan_Items = \Tainacan\Repositories\Items::get_instance();
$query = [
'meta_query' => [
[
'key' => $this->metadatum->get_id(),
'value' => 'even'
]
],
'posts_per_page' => 5
];
$bulk = new \Tainacan\Bulk_Edit([
'query' => $query,
'collection_id' => $this->collection->get_id()
]);
$bulk->replace_value($this->metadatum, 'super', 'even');
$items = $Tainacan_Items->fetch([
'meta_query' => [
[
'key' => $this->metadatum->get_id(),
'value' => 'super'
]
],
'posts_per_page' => -1
]);
$this->assertEquals(5, $items->found_posts);
$items = $Tainacan_Items->fetch([
'meta_query' => [
[
'key' => $this->metadatum->get_id(),
'value' => 'even'
]
],
'posts_per_page' => -1
]);
$this->assertEquals(15, $items->found_posts);
}
function test_set_tax_meta() {
$Tainacan_Items = \Tainacan\Repositories\Items::get_instance();
$query = [
'meta_query' => [
[
'key' => $this->metadatum->get_id(),
'value' => 'even'
]
],
'posts_per_page' => 5
];
$bulk = new \Tainacan\Bulk_Edit([
'query' => $query,
'collection_id' => $this->collection->get_id()
]);
$bulk->set_value($this->category, 'super');
$items = $Tainacan_Items->fetch([
'tax_query' => [
[
'taxonomy' => $this->taxonomy->get_db_identifier(),
'field' => 'name',
'terms' => 'bad'
]
],
'posts_per_page' => -1
]);
$this->assertEquals(35, $items->found_posts);
$items = $Tainacan_Items->fetch([
'tax_query' => [
[
'taxonomy' => $this->taxonomy->get_db_identifier(),
'field' => 'name',
'terms' => 'good'
]
],
'posts_per_page' => -1
]);
$this->assertEquals(35, $items->found_posts);
$items = $Tainacan_Items->fetch([
'tax_query' => [
[
'taxonomy' => $this->taxonomy->get_db_identifier(),
'field' => 'name',
'terms' => 'super'
]
],
'posts_per_page' => -1
]);
$this->assertEquals(5, $items->found_posts);
}
function test_set_regular_meta() {
$Tainacan_Items = \Tainacan\Repositories\Items::get_instance();
$query = [
'meta_query' => [
[
'key' => $this->metadatum->get_id(),
'value' => 'even'
]
],
'posts_per_page' => 5
];
$bulk = new \Tainacan\Bulk_Edit([
'query' => $query,
'collection_id' => $this->collection->get_id()
]);
$bulk->set_value($this->metadatum, 'super');
$items = $Tainacan_Items->fetch([
'meta_query' => [
[
'key' => $this->metadatum->get_id(),
'value' => 'super'
]
],
'posts_per_page' => -1
]);
$this->assertEquals(5, $items->found_posts);
$items = $Tainacan_Items->fetch([
'meta_query' => [
[
'key' => $this->metadatum->get_id(),
'value' => 'even'
]
],
'posts_per_page' => -1
]);
$this->assertEquals(15, $items->found_posts);
$items = $Tainacan_Items->fetch([
'meta_query' => [
[
'key' => $this->metadatum->get_id(),
'value' => 'odd'
]
],
'posts_per_page' => -1
]);
$this->assertEquals(20, $items->found_posts);
}
function test_set_regular_multi_meta() {
$Tainacan_Items = \Tainacan\Repositories\Items::get_instance();
$bulk = new \Tainacan\Bulk_Edit([
'items_ids' => $this->items_ids,
]);
$bulk->add_value($this->multiple_meta, 'test'); // for everyone
$bulk->add_value($this->multiple_meta, 'super'); // for everyone
$ids = array_slice($this->items_ids, 2, 7);
$bulk = new \Tainacan\Bulk_Edit([
'items_ids' => $ids,
]);
$bulk->set_value($this->multiple_meta, 'ultra');
$items = $Tainacan_Items->fetch([
'meta_query' => [
[
'key' => $this->multiple_meta->get_id(),
'value' => 'test'
]
],
'posts_per_page' => -1
]);
$this->assertEquals(33, $items->found_posts);
$items = $Tainacan_Items->fetch([
'meta_query' => [
[
'key' => $this->multiple_meta->get_id(),
'value' => 'super'
]
],
'posts_per_page' => -1
]);
$this->assertEquals(33, $items->found_posts);
$items = $Tainacan_Items->fetch([
'meta_query' => [
[
'key' => $this->multiple_meta->get_id(),
'value' => 'ultra'
]
],
'posts_per_page' => -1
]);
$this->assertEquals(7, $items->found_posts);
}
function test_set_core_metadata() {
$Tainacan_Items = \Tainacan\Repositories\Items::get_instance();
$core_title = $this->collection->get_core_title_metadatum();
$core_description = $this->collection->get_core_description_metadatum();
$ids = array_slice($this->items_ids, 2, 7);
$bulk = new \Tainacan\Bulk_Edit([
'items_ids' => $ids,
]);
$bulk->set_value($core_title, 'test_title');
$bulk->set_value($core_description, 'test_description');
$items = $Tainacan_Items->fetch([
'meta_query' => [
[
'key' => $core_title->get_id(),
'value' => 'test_title'
]
],
'posts_per_page' => -1
]);
$this->assertEquals(7, $items->found_posts);
$items = $Tainacan_Items->fetch([
'title' => 'test_title',
'posts_per_page' => -1
]);
$this->assertEquals(7, $items->found_posts);
$items = $Tainacan_Items->fetch([
'meta_query' => [
[
'key' => $core_description->get_id(),
'value' => 'test_description'
]
],
'posts_per_page' => -1
]);
$this->assertEquals(7, $items->found_posts);
global $wpdb;
$count = $wpdb->get_var( "SELECT COUNT(ID) FROM $wpdb->posts WHERE post_content = 'test_description'" );
$this->assertEquals(7, $count);
}
/**
* @group api
*/
function test_api_create_by_items_ids() {
$ids = array_slice($this->items_ids, 2, 17);
$request = new \WP_REST_Request(
'POST', $this->api_baseroute
);
$request->set_body( json_encode(['items_ids' => $ids]) );
$response = $this->server->dispatch($request);
$this->assertEquals(200, $response->get_status());
$data = $response->get_data();
$this->assertTrue(is_string($data['id']));
$this->assertEquals(17, $response->headers['X-WP-Total']);
}
/**
* @group api
*/
function test_api_create_by_query() {
$query = [
'metaquery' => [
[
'key' => $this->metadatum->get_id(),
'value' => 'odd'
]
],
'taxquery' => [
[
'taxonomy' => $this->taxonomy->get_db_identifier(),
'field' => 'name',
'terms' => 'good'
]
],
'perpage' => 4,
'paged' => 2
];
$request = new \WP_REST_Request(
'POST', $this->api_baseroute
);
$request->set_query_params($query);
$request->set_body( json_encode(['use_query' => 1]) );
$response = $this->server->dispatch($request);
$this->assertEquals(200, $response->get_status());
$data = $response->get_data();
$this->assertTrue(is_string($data['id']));
$this->assertEquals(20, $response->headers['X-WP-Total']);
}
/**
* @group api
*/
public function test_api_add_action() {
$Tainacan_Items = \Tainacan\Repositories\Items::get_instance();
$ids = array_slice($this->items_ids, 2, 14);
$bulk = new \Tainacan\Bulk_Edit([
'items_ids' => $ids,
]);
$body = json_encode([
'metadatum_id' => $this->multiple_meta->get_id(),
'value' => 'superduper'
]);
$request = new \WP_REST_Request(
'POST', $this->api_baseroute . '/' . $bulk->get_id() . '/add'
);
$request->set_body( $body );
$response = $this->server->dispatch($request);
$items = $Tainacan_Items->fetch([
'meta_query' => [
[
'key' => $this->multiple_meta->get_id(),
'value' => 'superduper'
]
],
'posts_per_page' => -1
]);
$this->assertEquals(14, $items->found_posts);
}
}

View File

@ -241,5 +241,122 @@ class ImporterTests extends TAINACAN_UnitTestCase {
$this->assertTrue( isset( $_SESSION['tainacan_importer'][$id]->tmp_file ) );
}
*/
*/
/**
* @group importer
*/
public function test_file_csv_multiple () {
$Tainacan_Items = \Tainacan\Repositories\Items::get_instance();
$Tainacan_Metadata = \Tainacan\Repositories\Metadata::get_instance();
$file_name = 'demosaved.csv';
$csv_importer = new Importer\CSV();
$id = $csv_importer->get_id();
// open the file "demosaved.csv" for writing
$file = fopen($file_name, 'w');
// save the column headers
fputcsv($file, array('Column 1', 'Column 2', 'Column 3', 'Column 4', 'Column 5'));
// Sample data
$data = array(
array('Data 11', 'Data 12', 'Data 13||TESTE', 'Data 14', 'Data 15'),
array('Data 21', 'Data 22', 'Data 23', 'Data 24', 'Data 25'),
array('Data 31', 'Data 32', utf8_decode( 'Data 33||Rééço' ), 'Data 34', 'Data 35'),
array('Data 41', 'Data 42', 'Data 43||limbbo', 'Data 44', 'Data 45'),
array('Data 51', 'Data 52', 'Data 53', 'Data 54', 'Data 55')
);
// save each row of the data
foreach ($data as $row){
fputcsv($file, $row);
}
// Close the file
fclose($file);
$_SESSION['tainacan_importer'][$id]->set_tmp_file( $file_name );
// file isset on importer
$this->assertTrue( !empty( $_SESSION['tainacan_importer'][$id]->get_tmp_file() ) );
// count size of csv
$this->assertEquals( 5, $_SESSION['tainacan_importer'][$id]->get_source_number_of_items() );
// get metadata to mapping
$headers = $_SESSION['tainacan_importer'][$id]->get_source_metadata();
$this->assertEquals( $headers[4], 'Column 5' );
// inserting the collection
$collection = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'Other',
'description' => 'adasdasdsa',
'default_order' => 'DESC',
'status' => 'publish'
),
true
);
$metadatum = $this->tainacan_entity_factory->create_entity(
'metadatum',
array(
'name' => 'Data multiplo',
'description' => 'Descreve o dado do campo data.',
'collection' => $collection,
'status' => 'publish',
'metadata_type' => 'Tainacan\Metadata_Types\Text',
'multiple' => 'yes'
),
true
);
$metadatum = $this->tainacan_entity_factory->create_entity(
'metadatum',
array(
'name' => 'Texto simples',
'description' => 'Descreve o dado do campo data.',
'collection' => $collection,
'status' => 'publish',
'metadata_type' => 'Tainacan\Metadata_Types\Text',
'multiple' => 'no'
),
true
);
$collection_definition = [
'id' => $collection->get_id(),
'total_items' => $_SESSION['tainacan_importer'][$id]->get_source_number_of_items(),
];
// get collection metadata to map
$metadata = $Tainacan_Metadata->fetch_by_collection( $collection, [], 'OBJECT' ) ;
//create a random mapping
$map = [];
foreach ( $metadata as $index => $metadatum ){
$map[$metadatum->get_id()] = $headers[$index];
}
$collection_definition['mapping'] = $map;
// add the collection
$_SESSION['tainacan_importer'][$id]->add_collection( $collection_definition );
$_SESSION['tainacan_importer'][$id]->set_option('encode','iso88591');
//$_SESSION['tainacan_importer'][$id]->set_option('encode','utf8');
//execute the process
$this->assertEquals(1, $_SESSION['tainacan_importer'][$id]->run(), 'first step should import 1 item');
$this->assertEquals(2, $_SESSION['tainacan_importer'][$id]->run(), 'second step should import 2 items');
$this->assertEquals(3, $_SESSION['tainacan_importer'][$id]->run(), 'third step should import 3 items');
$this->assertEquals(4, $_SESSION['tainacan_importer'][$id]->run(), 'third step should import 4 items');
$this->assertEquals(false, $_SESSION['tainacan_importer'][$id]->run(), '5 items and return false because its finished');
$this->assertEquals(false, $_SESSION['tainacan_importer'][$id]->run(), 'if call run again after finish, do nothing');
$items = $Tainacan_Items->fetch( [], $collection, 'OBJECT' );
$this->assertEquals( $_SESSION['tainacan_importer'][$id]->get_source_number_of_items(), count( $items ) );
}
}