Merge branch 'develop' of https://github.com/tainacan/tainacan into develop

This commit is contained in:
mateuswetah 2018-06-22 15:36:24 -03:00
commit 96d0058469
65 changed files with 2325 additions and 342 deletions

View File

@ -10,57 +10,103 @@
<b-field
class="columns"
grouped>
<!-- Metadata (Search criterias) -->
<b-field class="column">
<b-select
@input="addToAdvancedSearchQuery($event, 'key', searchCriteria)">
:disabled="advancedSearchQuery.taxquery[searchCriteria] ||
advancedSearchQuery.metaquery[searchCriteria] ? true : false"
@input="addToAdvancedSearchQuery($event, 'metadatum', searchCriteria)">
<option
v-for="metadata in metadataList"
v-if="metadata.enabled"
:value="metadata.id"
:key="metadata.id"
>{{ metadata.name }}</option>
v-for="metadatum in metadata"
:value="`${metadatum.id}-${metadatum.metadata_type_options.taxonomy}-${metadatum.metadata_type_object.primitive_type}`"
:key="metadatum.id"
>{{ metadatum.name }}</option>
</b-select>
</b-field>
<b-field class="column is-two-thirds">
<!-- Inputs -->
<b-field
class="column is-two-thirds">
<b-input
@input="addValueToAdvancedSearchQuery($event, 'value', searchCriteria)"/>
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)"
/>
<input
v-else-if="advancedSearchQuery.metaquery[searchCriteria] &&
advancedSearchQuery.metaquery[searchCriteria].ptype == 'date'"
class="input"
v-mask="dateMask"
@focus="addValueToAdvancedSearchQueryWithoutDelay($event, '', searchCriteria)"
@input="addValueToAdvancedSearchQueryWithoutDelay($event, 'value', searchCriteria)"
:placeholder="dateFormat"
type="text">
<b-taginput
v-else-if="advancedSearchQuery.taxquery[searchCriteria]"
:data="terms"
autocomplete
attached
ellipsis
:before-adding="hasTagIn($event, searchCriteria)"
@remove="removeValueOf($event, searchCriteria)"
@add="addValueToAdvancedSearchQuery($event, 'terms', searchCriteria)"
@typing="autoCompleteTerm($event, searchCriteria)"
/>
</b-field>
<b-field class="column">
<!-- Comparators -->
<b-field
class="column">
<b-select
@input="addToAdvancedSearchQuery($event, 'compare', searchCriteria)">
<option
v-for="(opt, key) in compare"
:value="key"
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 : '')">
<option
v-for="(comparator, key) in getComparators(searchCriteria)"
:key="key"
>{{ opt }}</option>
:value="key"
>{{ comparator }}</option>
</b-select>
</b-field>
<div class="field">
<button
@click="removeThis(searchCriteria)"
class="button is-white is-pulled-right">
<b-icon
size="is-small"
icon="close"/>
</button>
</div>
</b-field>
</div>
<!-- Add button -->
<div
:style="{'padding-left': '25px !important'}"
class="field column is-12">
<div class="is-inline">
<a
@click="addSearchCriteria"
class="is-secondary is-small">
<b-icon
icon="plus-circle"
size="is-small"
type="is-secondary"/>
<a
@click="addSearchCriteria"
class="is-secondary is-small">
{{ $i18n.get('add_more_one_search_criteria') }}</a>
</div>
{{ $i18n.get('add_another_search_criteria') }}</a>
</div>
<!-- Tags -->
<div
:class="{'tag-container-border': Object.keys(advancedSearchQuery).length > 1}"
class="field column is-12">
<b-field
:style="{'padding': '0.3rem 0 0 0'}"
grouped
group-multiline>
<div
@ -68,18 +114,31 @@
:key="searchCriteria"
class="control taginput-container">
<b-tag
v-if="advancedSearchQuery[searchCriteria] && advancedSearchQuery[searchCriteria].value"
v-if="(advancedSearchQuery.taxquery[searchCriteria] && advancedSearchQuery.taxquery[searchCriteria].terms)"
type="is-white"
class="is-rounded"
@close="removeThis(searchCriteria)"
attached
closable>
{{ Array.isArray(advancedSearchQuery[searchCriteria].value) ?
advancedSearchQuery[searchCriteria].value.toString() :
advancedSearchQuery[searchCriteria].value }}
</b-tag>
{{ Array.isArray(advancedSearchQuery.taxquery[searchCriteria].terms) ?
advancedSearchQuery.taxquery[searchCriteria].btags.toString() :
advancedSearchQuery.taxquery[searchCriteria].btags }}
</b-tag>
<b-tag
v-else-if="(advancedSearchQuery.metaquery[searchCriteria] && advancedSearchQuery.metaquery[searchCriteria].value)"
type="is-white"
class="is-rounded"
@close="removeThis(searchCriteria)"
attached
:loading="isFetching"
closable>
{{ advancedSearchQuery.metaquery[searchCriteria].value }}
</b-tag>
</div>
</b-field>
</div>
<!-- Clear and search button -->
<div class="column">
<div class="field is-grouped is-pulled-right">
<p class="control">
@ -95,42 +154,143 @@
</div>
</div>
</div>
<pre>{{ advancedSearchQuery }}</pre>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex';
import { dateInter } from '../../js/mixins.js';
import moment from 'moment';
export default {
name: "AdvancedSearch",
mixins: [ dateInter ],
props: {
metadataList: Array,
metadata: Array,
isRepositoryLevel: false,
},
created(){
let locale = navigator.language;
moment.locale(locale);
let localeData = moment.localeData();
this.dateFormat = localeData.longDateFormat('L');
},
data() {
return {
compare: {
metaqueryOperatorsForInterval: {
'=': this.$i18n.get('is_equal_to'),
'!=': this.$i18n.get('is_not_equal_to'),
'>': this.$i18n.get('greater_than'),
'<': this.$i18n.get('less_than'),
'>=': this.$i18n.get('greater_than_or_equal_to'),
'<=': this.$i18n.get('less_than_or_equal_to'),
},
metaqueryOperatorsRegular: {
'=': this.$i18n.get('is_equal_to'),
'!=': this.$i18n.get('is_not_equal_to'),
'LIKE': this.$i18n.get('contains'),
'NOT LIKE': this.$i18n.get('not_contains'),
},
taxqueryOperators: {
'IN': this.$i18n.get('contains'),
'NOT IN': this.$i18n.get('not_contains')
},
searchCriterias: [1],
advancedSearchQuery: {
advancedSearch: true,
metaquery: {},
taxquery: {},
},
termList: [],
terms: [],
isFetching: false,
dateMask: this.getDateLocaleMask(),
dateFormat: '',
}
},
methods: {
...mapActions('taxonomy', [
'fetchTerms'
]),
...mapGetters('taxonomy', [
'getTerms'
]),
autoCompleteTerm: _.debounce( function(value, searchCriteria){
this.termList = [];
this.terms = [];
this.isFetching = true;
this.fetchTerms({
taxonomyId: this.advancedSearchQuery.taxquery[searchCriteria].taxonomy_id,
fetchOnly: {
fetch_only: {
0: 'name',
1: 'id'
}
},
search: {
searchterm: value
}
}).then((res) => {
this.termList = res;
for(let term in this.termList){
this.terms.push(this.termList[term].name);
let i = this.terms.length - 1;
this.termList[term].i = i;
}
this.isFetching = false;
}).catch((error) => {
this.isFetching = false;
throw error;
});
}, 300),
getComparators(searchCriteria){
if(this.advancedSearchQuery.taxquery[searchCriteria]){
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'){
return this.metaqueryOperatorsForInterval;
} else{
return this.metaqueryOperatorsRegular;
}
}
},
removeThis(searchCriteria){
console.log(searchCriteria);
let criteriaIndex = this.searchCriterias.findIndex((element) => {
return element == searchCriteria;
});
this.searchCriterias.splice(criteriaIndex, 1);
delete this.advancedSearchQuery[searchCriteria];
console.log(this.advancedSearchQuery);
if(this.advancedSearchQuery.taxquery[searchCriteria]){
delete this.advancedSearchQuery.taxquery[searchCriteria];
} else if(this.advancedSearchQuery.metaquery[searchCriteria]){
delete this.advancedSearchQuery.metaquery[searchCriteria];
}
},
removeValueOf(value, searchCriteria){
if(this.advancedSearchQuery.taxquery[searchCriteria]){
let tagIndex = this.advancedSearchQuery.taxquery[searchCriteria].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', '');
}
},
hasTagIn(value, searchCriteria){
return !!this.advancedSearchQuery.taxquery[searchCriteria].btags.find((element) => {
return element == value;
});
},
addSearchCriteria(){
let aleatoryKey = Math.floor(Math.random() * 1000) + 2;
@ -149,74 +309,137 @@
this.searchCriterias = [1];
this.advancedSearchQuery = {
advancedSearch: true,
metaquery: {},
taxquery: {}
};
},
convertDateToMatchInDB(dateValue){
return moment(dateValue, this.dateFormat).toISOString().split('T')[0];
},
addValueToAdvancedSearchQueryWithoutDelay($event, type, searchCriteria){
if(type == ''){
this.$set($event.target, 'value', '');
this.addToAdvancedSearchQuery('', 'value', searchCriteria);
} else {
this.addToAdvancedSearchQuery($event.target.value, type, searchCriteria);
}
},
addValueToAdvancedSearchQuery: _.debounce(function(value, type, searchCriteria) {
let vm = this;
vm.addToAdvancedSearchQuery(value, type, searchCriteria);
this.addToAdvancedSearchQuery(value, type, searchCriteria);
}, 900),
searchAdvanced(){
if(Object.keys(this.advancedSearchQuery).length > 2){
searchAdvanced(){
if(Object.keys(this.advancedSearchQuery.taxquery).length > 0 &&
Object.keys(this.advancedSearchQuery.metaquery).length > 0){
this.advancedSearchQuery.relation = 'AND';
}
if(Object.keys(this.advancedSearchQuery.taxquery).length > 1){
this.$set(this.advancedSearchQuery.taxquery, 'relation', 'AND');
} else if(this.advancedSearchQuery.taxquery.hasOwnProperty('relation')){
delete this.advancedSearchQuery.taxquery.relation;
}
// Convert date values to a format (ISO_8601) that will match in database
if(Object.keys(this.advancedSearchQuery.metaquery).length > 0){
for(let metaquery in this.advancedSearchQuery.metaquery){
if(this.advancedSearchQuery.metaquery[metaquery].ptype == 'date'){
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));
}
}
}
}
if(Object.keys(this.advancedSearchQuery.metaquery).length > 1){
this.$set(this.advancedSearchQuery.metaquery, 'relation', 'AND');
} else if(this.advancedSearchQuery.metaquery.hasOwnProperty('relation')){
delete this.advancedSearchQuery.metaquery.relation;
}
if(this.advancedSearchQuery.hasOwnProperty('relation') && Object.keys(this.advancedSearchQuery).length <= 2){
if(this.advancedSearchQuery.hasOwnProperty('relation') && Object.keys(this.advancedSearchQuery).length <= 3){
delete this.advancedSearchQuery.relation;
}
this.$eventBusSearch.$emit('searchAdvanced', this.advancedSearchQuery);
if(Object.keys(this.advancedSearchQuery.metaquery).length > 0){
for(let metaquery in this.advancedSearchQuery.metaquery){
if(this.advancedSearchQuery.metaquery[metaquery].ptype == 'date'){
let value = this.advancedSearchQuery.metaquery[metaquery].value;
setTimeout(() => {
if(value.includes('-')){
this.$set(this.advancedSearchQuery.metaquery[metaquery], 'value', this.parseDateToNavigatorLanguage(value));
}
}, 110);
}
}
}
},
parseDateToNavigatorLanguage(date){
date = new Date(date.replace(/-/g, '/'));
return moment(date, moment.ISO_8601).format(this.dateFormat);
},
addToAdvancedSearchQuery(value, type, searchCriteria){
if(this.advancedSearchQuery.hasOwnProperty(searchCriteria)){
if(type == 'value' && (this.advancedSearchQuery[searchCriteria]['compare'] == 'IN' ||
this.advancedSearchQuery[searchCriteria]['compare'] == 'NOT IN')){
if(value.includes(';')){
this.advancedSearchQuery[searchCriteria].value = value.split(';');
if(type == 'metadatum'){
const criteriaKey = value.split('-');
if(criteriaKey[1] != 'undefined'){
// Was selected a taxonomy criteria
this.advancedSearchQuery.taxquery = Object.assign({}, this.advancedSearchQuery.taxquery, {
[`${searchCriteria}`]: {
taxonomy: criteriaKey[1],
terms: [],
btags: [],
field: 'term_id',
operator: 'IN',
taxonomy_id: Number(criteriaKey[1].match(/[\d]+/))
}
});
} else {
// Was selected a metadatum criteria
if(criteriaKey[2] != 'date' && criteriaKey[2] != 'int' && criteriaKey[2] != 'float'){
this.advancedSearchQuery.metaquery = Object.assign({}, this.advancedSearchQuery.metaquery, {
[`${searchCriteria}`]: {
key: Number(criteriaKey[0]),
compare: 'LIKE'
}
});
} else {
this.advancedSearchQuery[searchCriteria].value.pop();
if(!this.advancedSearchQuery[searchCriteria].value.includes(value)){
this.advancedSearchQuery[searchCriteria].value.push(value);
}
this.advancedSearchQuery.metaquery = Object.assign({}, this.advancedSearchQuery.metaquery, {
[`${searchCriteria}`]: {
key: Number(criteriaKey[0]),
compare: '='
}
});
}
} else {
if(type == 'compare' &&
this.advancedSearchQuery[searchCriteria].compare &&
!Array.isArray(this.advancedSearchQuery[searchCriteria].value) &&
(this.advancedSearchQuery.compare != 'IN' && value == 'IN' ||
this.advancedSearchQuery.compare != 'NOT IN' && value == 'NOT IN')){
let valueAsArray = this.advancedSearchQuery[searchCriteria].value.split(' ');
this.advancedSearchQuery[searchCriteria].value = valueAsArray;
} else if(type == 'compare' &&
this.advancedSearchQuery[searchCriteria].compare &&
(this.advancedSearchQuery.compare != '=' && value == '=' ||
this.advancedSearchQuery.compare != '!=' && value == '!=')){
let valueAsString = this.advancedSearchQuery[searchCriteria].value.toString().replace(/,/g, ' ');
this.advancedSearchQuery[searchCriteria].value = valueAsString;
}
this.$set(this.advancedSearchQuery[searchCriteria], `${type}`, value);
this.$set(this.advancedSearchQuery.metaquery[searchCriteria], 'ptype', criteriaKey[2]);
}
} else {
if(type == 'compare' && (value == 'IN' || value == 'NOT IN')){
} else if(type == 'terms'){
let termIndex = this.terms.findIndex((element, index) => {
if(element == value && index == this.termList[index].i){
return true;
}
});
this.advancedSearchQuery = Object.assign({}, this.advancedSearchQuery, {
[`${searchCriteria}`]: {
[`${type}`]: [value],
}
});
} else {
this.advancedSearchQuery = Object.assign({}, this.advancedSearchQuery, {
[`${searchCriteria}`]: {
[`${type}`]: value,
}
});
}
this.advancedSearchQuery.taxquery[searchCriteria].terms.push(this.termList[termIndex].id);
this.advancedSearchQuery.taxquery[searchCriteria].btags.push(value);
this.terms = [];
} else if(type == 'value'){
this.$set(this.advancedSearchQuery.metaquery[searchCriteria], '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);
}
}
console.log(this.advancedSearchQuery);
},
}
}
@ -232,9 +455,6 @@
padding-left: $page-side-padding;
padding-bottom: 47px;
.tag-container-border {
border: 1px solid $tainacan-input-background;
}
.column {
padding: 0 0.3rem 0.3rem !important;
}

View File

@ -221,17 +221,17 @@
<!-- Name -------------------------------- -->
<b-field
:addons="false"
:label="$i18n.get('label_name')"
:type="editFormErrors['name'] != undefined ? 'is-danger' : ''"
:message="editFormErrors['name'] != undefined ? editFormErrors['name'] : ''">
:addons="false"
:label="$i18n.get('label_name')"
:type="editFormErrors['name'] != undefined ? 'is-danger' : ''"
:message="editFormErrors['name'] != undefined ? editFormErrors['name'] : ''">
<help-button
:title="$i18n.getHelperTitle('collections', 'name')"
:message="$i18n.getHelperMessage('collections', 'name')"/>
:title="$i18n.getHelperTitle('collections', 'name')"
:message="$i18n.getHelperMessage('collections', 'name')"/>
<b-input
id="tainacan-text-name"
v-model="form.name"
@focus="clearErrors('name')"/>
id="tainacan-text-name"
v-model="form.name"
@focus="clearErrors('name')"/>
</b-field>
<!-- Description -------------------------------- -->
@ -420,7 +420,8 @@ export default {
thumbnailMediaFrame: undefined,
headerImageMediaFrame: undefined,
registeredViewModes: tainacan_plugin.registered_view_modes,
viewModesList: []
viewModesList: [],
fromImporter: ''
}
},
methods: {
@ -477,7 +478,10 @@ export default {
this.formErrorMessage = '';
this.editFormErrors = {};
this.$router.push(this.$routerHelper.getCollectionPath(this.collectionId));
if (this.fromImporter)
this.$router.go(-1);
else
this.$router.push(this.$routerHelper.getCollectionPath(this.collectionId));
})
.catch((errors) => {
for (let error of errors.errors) {
@ -538,7 +542,10 @@ export default {
this.editFormErrors[attribute] = undefined;
},
cancelBack(){
this.$router.push(this.$routerHelper.getCollectionsPath());
if (this.fromImporter)
this.$router.go(-1);
else
this.$router.push(this.$routerHelper.getCollectionsPath());
},
updateViewModeslist(viewMode) {
@ -656,15 +663,18 @@ export default {
},
created(){
if (this.$route.fullPath.split("/").pop() == "new") {
if (this.$route.query.fromImporter != undefined)
this.fromImporter = this.$route.query.fromImporter;
if (this.$route.path.split("/").pop() == "new") {
this.createNewCollection();
this.isNewCollection = true;
} else if (this.$route.fullPath.split("/").pop() == "settings") {
} else if (this.$route.path.split("/").pop() == "settings") {
this.isLoading = true;
// Obtains current Collection ID from URL
this.pathArray = this.$route.fullPath.split("/").reverse();
this.pathArray = this.$route.path.split("/").reverse();
this.collectionId = this.pathArray[1];
this.fetchCollection(this.collectionId).then(res => {
@ -730,7 +740,7 @@ export default {
},
mounted() {
if (this.$route.fullPath.split("/").pop() != "new") {
if (this.$route.path.split("/").pop() != "new") {
document.getElementById('collection-page-container').addEventListener('scroll', ($event) => {
this.$emit('onShrinkHeader', ($event.target.scrollTop > 53));
});
@ -779,14 +789,20 @@ export default {
padding: 20px;
}
.image-placeholder {
position: relative;
left: 45%;
bottom: -100px;
font-size: 0.8rem;
position: absolute;
left: 30%;
right: 30%;
top: 40%;
font-size: 2.0rem;
font-weight: bold;
z-index: 99;
text-align: center;
color: gray;
@media screen and (max-width: 769px) {
font-size: 1.2rem;
}
}
.header-buttons-row {
text-align: right;

View File

@ -0,0 +1,562 @@
<template>
<div
class="primary-page page-container">
<tainacan-title />
<form
class="tainacan-form"
label-width="120px"
v-if="importer != undefined && importer != null">
<!-- Target collection selection -------------------------------- -->
<b-field
v-if="importer.manual_collection"
:addons="false"
:label="$i18n.get('label_target_collection')">
<help-button
:title="$i18n.get('label_target_collection')"
:message="$i18n.get('info_target_collection_helper')"/>
<br>
<div class="is-inline">
<b-select
id="tainacan-select-target-collection"
:value="collectionId"
@input="onSelectCollection($event)"
:loading="isFetchingCollections"
:placeholder="$i18n.get('instruction_select_a_target_collection')">
<option
v-for="collection of collections"
:key="collection.id"
:value="collection.id">{{ collection.name }}
</option>
</b-select>
<router-link
tag="a"
class="is-inline add-link"
:to="{ path: $routerHelper.getNewCollectionPath(), query: { fromImporter: true }}">
<b-icon
icon="plus-circle"
size="is-small"
type="is-secondary"/>
{{ $i18n.get('new_blank_collection') }}</router-link>
</div>
</b-field>
<!-- File Source input -->
<b-field
v-if="importer.accepts.file"
:addons="false">
<label class="label">{{ $i18n.get('label_source_file') }}</label>
<help-button
:title="$i18n.get('label_source_file')"
:message="$i18n.get('info_source_file_upload')"/>
<br>
<b-upload
v-if="importer.tmp_file == undefined"
:value="importerFile"
@input="onUploadFile($event)"
drag-drop>
<section class="drop-inner">
<div class="content has-text-centered">
<p>
<b-icon
icon="upload"
size="is-large"/>
</p>
<p>{{ $i18n.get('instruction_drop_file_or_click_to_upload') }}</p>
</div>
</section>
</b-upload>
<div v-if="importer.tmp_file != undefined">{{ importer.tmp_file }}</div>
</b-field>
<!-- URL source input -------------------------------- -->
<b-field
v-if="importer.accepts.url"
:addons="false"
:label="$i18n.get('label_url_source_link')">
<help-button
:title="$i18n.get('label_url_source_link')"
:message="$i18n.get('info_url_source_link_helper')"/>
<b-input
id="tainacan-url-link-source"
:value="url"
@input="onInputURL($event)"/>
</b-field>
<!-- Metadata Mapping -->
<b-field
v-if="importer.manual_mapping"
:addons="false"
:label="$i18n.get('label_metadata_mapping')">
<help-button
:title="$i18n.get('label_metadata_mapping')"
:message="$i18n.get('info_metadata_mapping_helper')"/>
<div
v-if="importerSourceInfo != undefined &&
importerSourceInfo != null">
<p class="mapping-header-label is-inline">{{ $i18n.get('label_from_source_collection') }}</p>
<p class="mapping-header-label is-pulled-right">{{ $i18n.get('label_to_target_collection') }}</p>
<div
class="source-metadatum"
v-for="(source_metadatum, index) of importerSourceInfo.source_metadata"
:key="index"><p>{{ source_metadatum }}</p>
<b-select
v-if="collectionMetadata != undefined &&
collectionMetadata.length > 0 &&
!isFetchingCollectionMetadata"
@input="onSelectCollectionMetadata($event, source_metadatum)"
:placeholder="$i18n.get('label_select_metadatum')">
<option :value="undefined">
{{ $i18n.get('label_select_metadatum') }}
</option>
<option
v-for="(metadatum, index) of collectionMetadata"
:key="index"
:value="metadatum.id"
:disabled="checkIfMetadatumIsAvailable(metadatum.id)">
<span class="metadatum-name">
{{ metadatum.name }}
</span>
<span class="label-details">
({{ $i18n.get(metadatum.metadata_type_object.component) }}) <em>{{ (metadatum.collection_id != collectionId) ? $i18n.get('label_inherited') : '' }}</em>
</span>
</option>
</b-select>
<p v-if="collectionMetadata == undefined || collectionMetadata.length <= 0">{{ $i18n.get('info_select_collection_to_list_metadata') }}</p>
</div>
<b-modal
@close="onMetadatumEditionCanceled()"
:active.sync="isNewMetadatumModalActive">
<b-loading
:is-full-page="isFullPage"
:active.sync="isLoadingMetadatumTypes"/>
<div
v-if="selectedMetadatumType == undefined && !isEditingMetadatum"
class="tainacan-modal-content">
<div class="tainacan-modal-title">
<h2>{{ $i18n.get('instruction_select_metadatum_type') }}</h2>
<hr>
</div>
<b-select
:value="selectedMetadatumType"
@input="onSelectMetadatumType($event)"
:placeholder="$i18n.get('label_select_metadatum_type')">
<option
v-for="(metadatumType, index) of metadatumTypes"
:key="index"
:value="metadatumType">
{{ metadatumType.name }}
</option>
</b-select>
</div>
<div
v-if="isEditingMetadatum"
class="tainacan-modal-content">
<div class="tainacan-modal-title">
<h2>{{ $i18n.get('instruction_configure_new_metadatum') }}</h2>
<hr>
</div>
<metadatum-edition-form
:collection-id="collectionId"
:is-repository-level="false"
@onEditionFinished="onMetadatumEditionFinished()"
@onEditionCanceled="onMetadatumEditionCanceled()"
:index="0"
:original-metadatum="metadatum"
:edited-metadatum="editedMetadatum"
:is-on-modal="true"/>
</div>
</b-modal>
<a
v-if="collectionId != null && collectionId != undefined"
class="is-inline is-pulled-right add-link"
@click="createNewMetadatum()">
<b-icon
icon="plus-circle"
size="is-small"
type="is-secondary"/>
{{ $i18n.get('label_add_more_metadata') }}</a>
</div>
<div
v-if="importerSourceInfo == undefined ||
importerSourceInfo == null">
<p>{{ $i18n.get('info_upload_a_source_to_see_metadata') }}</p>
</div>
</b-field>
<!-- Form submit -------------------------------- -->
<div class="field is-grouped form-submit">
<div class="control">
<button
id="button-cancel-collection-creation"
class="button is-outlined"
type="button"
@click="cancelBack">{{ $i18n.get('cancel') }}</button>
</div>
<div
v-if="!hasRunImporter"
class="control">
<button
:disabled="sessionId == undefined || importer == undefined"
id="button-submit-collection-creation"
@click.prevent="onRunImporter"
class="button is-success">{{ $i18n.get('run') }}</button>
</div>
<div
v-if="hasRunImporter"
class="control">
<button
:disabled="sessionId == undefined || importer == undefined"
id="button-submit-collection-creation"
@click.prevent="onCheckBackgroundProcessStatus"
class="button is-success">Check Status</button>
</div>
</div>
</form>
<b-loading
:active.sync="isLoading"
:can-cancel="false"/>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex';
import MetadatumEditionForm from './../edition/metadatum-edition-form.vue';
import { tainacan as axios } from '../../../js/axios/axios.js';
export default {
name: 'ImporterEditionForm',
data(){
return {
importerId: Number,
importer: null,
isLoading: false,
isFetchingCollections: false,
form: {
},
mappedCollection: {
'id': Number,
'mapping': {},
'total_items': Number
},
importerTypes: [],
importerType: '',
importerFile: {},
importerSourceInfo: null,
collections: [],
collectionMetadata: [],
collectionId: undefined,
url: '',
isNewMetadatumModalActive: false,
isLoadingMetadatumTypes: false,
selectedMetadatumType: undefined,
isEditingMetadatum: false,
metadatum: {},
editedMetadatum: {},
hasRunImporter: false,
backgroundProcess: undefined
}
},
components: {
MetadatumEditionForm
},
computed: {
metadatumTypes() {
return this.getMetadatumTypes();
}
},
methods: {
...mapActions('importer', [
'fetchImporterTypes',
'fetchImporter',
'sendImporter',
'updateImporter',
'updateImporterFile',
'updateImporterURL',
'fetchImporterSourceInfo',
'updateImporterCollection',
'runImporter'
]),
...mapActions('collection', [
'fetchCollectionsForParent'
]),
...mapActions('metadata', [
'fetchMetadata',
'fetchMetadatumTypes',
'sendMetadatum'
]),
...mapGetters('metadata', [
'getMetadatumTypes'
]),
createImporter() {
// Puts loading on Draft Importer creation
this.isLoading = true;
// Creates draft Importer
this.sendImporter(this.importerType)
.then(res => {
this.sessionId = res.id;
this.importer = JSON.parse(JSON.stringify(res));
this.form = this.importer.options;
this.isLoading = false;
if (this.importer.manual_collection)
this.loadCollections();
})
.catch(error => this.$console.error(error));
},
cancelBack(){
this.$router.go(-1);
},
onUploadFile(file) {
this.updateImporterFile({ sessionId: this.sessionId, file: file[0] })
.then(updatedImporter => {
this.importer = updatedImporter;
this.importerFile = this.importer.tmp_file;
this.fetchImporterSourceInfo(this.sessionId)
.then(importerSourceInfo => {
this.importerSourceInfo = importerSourceInfo;
this.mappedCollection['total_items'] = this.importerSourceInfo.source_total_items;
})
.catch((errors) => {
this.$console.log(errors);
});
})
.catch((errors) => {
this.$console.log(errors);
});
},
checkIfMetadatumIsAvailable(metadatumId) {
return this.mappedCollection['mapping'][metadatumId] != undefined;
},
onInputURL(event) {
this.url = event;
this.updateImporterURL({ sessionId: this.sessionId, url: this.url })
.then(updatedImporter => {
this.importer = updatedImporter;
})
.catch((errors) => {
this.$console.log(errors);
});
},
onRunImporter() {
if (this.importer.manual_collection) {
this.updateImporterCollection({ sessionId: this.sessionId, collection: this.mappedCollection })
.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);
});
})
.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);
});
}
},
onCheckBackgroundProcessStatus() {
axios.get('/bg-processes/' + this.backgroundProcess.bg_process_id)
.then((backgroundProcess) => {
this.$console.log(JSON.stringify(backgroundProcess));
})
.catch((error) => {
this.$console.error(error);
});
},
loadCollections() {
// Generates options for target collection
this.isFetchingCollections = true;
this.fetchCollectionsForParent()
.then((collections) => {
this.collections = collections;
this.isFetchingCollections = false;
})
.catch((error) => {
this.$console.error(error);
this.isFetchingCollections = false;
});
},
onSelectCollection(collectionId) {
this.collectionId = collectionId;
this.mappedCollection['id'] = collectionId;
// Generates options for metadata listing
this.isFetchingCollectionMetadata = true;
this.fetchMetadata({collectionId: this.collectionId, isRepositoryLevel: false, isContextEdit: false })
.then((metadata) => {
this.collectionMetadata = JSON.parse(JSON.stringify(metadata));
this.isFetchingCollectionMetadata = false;
})
.catch((error) => {
this.$console.error(error);
this.isFetchingCollectionMetadata = false;
});
},
onSelectCollectionMetadata(selectedMetadatum, sourceMetadatum) {
if (selectedMetadatum)
this.mappedCollection['mapping'][selectedMetadatum] = sourceMetadatum;
else {
let removedKey = '';
for (let key in this.mappedCollection['mapping']) {
if(this.mappedCollection['mapping'][key] == sourceMetadatum)
removedKey = key;
}
if (removedKey != '')
delete this.mappedCollection['mapping'][removedKey];
}
// Necessary for causing reactivity to re-check if metadata remains available
this.collectionMetadata.push("");
this.collectionMetadata.pop();
},
onSelectMetadatumType(newMetadatum) {
this.sendMetadatum({
collectionId: this.collectionId,
name: newMetadatum.name, metadatumType:
newMetadatum.className,
status: 'auto-draft',
isRepositoryLevel: false,
newIndex: 0
})
.then((metadatum) => {
this.metadatum = metadatum;
this.editedMetadatum = JSON.parse(JSON.stringify(metadatum));
this.editedMetadatum.saved = false;
this.editedMetadatum.status = 'publish';
this.isEditingMetadatum = true;
})
.catch((error) => {
this.$console.error(error);
});
},
createNewMetadatum() {
this.fetchMetadatumTypes()
.then(() => {
this.isLoadingMetadatumTypes = false;
this.isNewMetadatumModalActive = true;
})
.catch(() => {
this.isLoadingMetadatumTypes = false;
});
},
onMetadatumEditionFinished() {
// Reset variables for metadatum creation
delete this.metadatum;
delete this.editedMetadatum;
this.isEditingMetadatum = false;
this.isNewMetadatumModalActive = false;
this.selectedMetadatumType = undefined;
// Generates options for metadata listing
this.isFetchingCollectionMetadata = true;
this.fetchMetadata({collectionId: this.collectionId, isRepositoryLevel: false, isContextEdit: false })
.then((metadata) => {
this.collectionMetadata = JSON.parse(JSON.stringify(metadata));
this.isFetchingCollectionMetadata = false;
})
.catch((error) => {
this.$console.error(error);
this.isFetchingCollectionMetadata = false;
});
},
onMetadatumEditionCanceled() {
// Reset variables for metadatum creation
if (this.metadatum)
delete this.metadatum;
if (this.editedMetadatum)
delete this.editedMetadatum;
this.isEditingMetadatum = false;
this.isNewMetadatumModalActive = false;
this.selectedMetadatumType = undefined;
}
},
created() {
this.importerType = this.$route.params.importerSlug;
this.createImporter();
}
}
</script>
<style lang="scss" scoped>
@import "../../scss/_variables.scss";
.field {
position: relative;
}
.section-label {
font-size: 16px !important;
font-weight: 500 !important;
color: $tertiary !important;
line-height: 1.2em;
}
.source-metadatum {
padding: 2px 0;
border-bottom: 1px solid $tainacan-input-background;
width: 100%;
margin-bottom: 6px;
display: flex;
justify-content: space-between;
align-items: center;
}
.is-inline .control{
display: inline;
}
.drop-inner{
padding: 1rem 3rem;
}
.mapping-header-label {
color: $gray-light;
margin: 12px 0 6px 0;
}
.modal .animation-content {
width: 100%;
z-index: 99999;
#metadatumEditForm {
background-color: white;
}
}
</style>

View File

@ -2,6 +2,7 @@
<form
id="metadatumEditForm"
class="tainacan-form"
:class="{ 'inCollapse': !isOnModal }"
@submit.prevent="saveEdition(editForm)">
<b-field
@ -229,7 +230,8 @@
editedMetadatum: Object,
originalMetadatum: Object,
isRepositoryLevel: false,
collectionId: ''
collectionId: '',
isOnModal: false
},
created() {
@ -334,7 +336,7 @@
@import "../../scss/_variables.scss";
form {
form.inCollapse {
padding: 1.0em 2.0em;
border-top: 1px solid $draggable-border-color;
border-bottom: 1px solid $draggable-border-color;

View File

@ -259,11 +259,11 @@
}
.image-placeholder {
position: absolute;
margin-left: 10px;
margin-right: 10px;
top: 24px;
margin-left: 15%;
margin-right: 15%;
top: 6px;
bottom: 50%;
font-size: 0.8rem;
font-size: 0.6rem;
font-weight: bold;
z-index: 99;
text-align: center;

View File

@ -26,7 +26,7 @@
<b-dropdown-item
@click="deleteSelectedItems()"
id="item-delete-selected-items">
{{ $i18n.get('label_delete_selected_items') }}
{{ isOnTrash ? $i18n.get('label_delete_permanently') : $i18n.get('label_send_to_trash') }}
</b-dropdown-item>
<b-dropdown-item disabled>{{ $i18n.get('label_edit_selected_items') + ' (Not ready)' }}
</b-dropdown-item>

View File

@ -292,6 +292,7 @@ export default {
} else {
this.openedMetadatumId = metadatum.id;
// First time opening
if (this.editForms[this.openedMetadatumId] == undefined) {
this.editForms[this.openedMetadatumId] = JSON.parse(JSON.stringify(metadatum));

View File

@ -314,7 +314,7 @@ export default {
},
loadTerms() {
this.isLoadingTerms = true;
this.fetchTerms(this.taxonomyId)
this.fetchTerms({ taxonomyId: this.taxonomyId, fetchOnly: '', search: ''})
.then(() => {
// Fill this.form data with current data.
this.isLoadingTerms = false;

View File

@ -104,6 +104,10 @@ export default {
max-width: $side-menu-width;
z-index: 99;
a:hover {
text-decoration: none;
}
.menu {
padding-top: 10px;
}

View File

@ -16,20 +16,24 @@
</div>
</div>
<div class="level-right">
<span class="search-area">
<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"
v-model="searchTerm">
<span class="icon is-right">
<i class="mdi mdi-magnify" />
</span>
:value="searchQuery"
@input="futureSearchQuery = $event.target.value"
@keyup.enter="updateSearch()">
<span
@click="updateSearch()"
class="icon is-right">
<i class="mdi mdi-magnify" />
</span>
</div>
<a @click="toItemsPage">{{ $i18n.get('advanced_search') }}</a>
</span>
</div>
<a
class="level-item"
:href="wordpressAdmin">
@ -47,7 +51,8 @@ export default {
return {
logoHeader: tainacan_plugin.base_url + '/admin/images/tainacan_logo_header.png',
wordpressAdmin: window.location.origin + window.location.pathname.replace('admin.php', ''),
searchTerm: ''
searchQuery: '',
futureSearchQuery: '',
}
},
methods: {
@ -55,10 +60,13 @@ export default {
this.$router.push({
path: '/items',
query: {
openAdvancedSearch: true
advancedSearch: true
}
});
}
},
updateSearch() {
this.$eventBusSearch.setSearchQuery(this.futureSearchQuery);
},
},
props: {
isMenuCompressed: false
@ -111,9 +119,6 @@ export default {
a{
color: white;
}
a:hover {
color: $tertiary;
}
.search-area {
display: flex;
align-items: center;
@ -133,7 +138,9 @@ export default {
width: 220px !important;
}
.icon {
pointer-events: all;
color: $tertiary;
cursor: pointer;
height: 27px;
font-size: 18px;
}

View File

@ -295,6 +295,7 @@ export default {
a:hover,
a.is-active {
background-color: #d1f1f2;
text-decoration: none;
}
a:focus{
box-shadow: none;

View File

@ -36,7 +36,6 @@ export default {
name: 'TainacanTitle',
data(){
return {
wordpressAdmin: window.location.origin + window.location.pathname.replace('admin.php', ''),
isRepositoryLevel: true,
pageTitle: '',
arrayRealPath: [],
@ -67,6 +66,9 @@ export default {
...mapActions('event', [
'fetchEventTitle'
]),
...mapActions('importer', [
'fetchAvailableImporters'
]),
generateViewPath() {
for (let i = 0; i < this.arrayRealPath.length; i++) {
@ -96,8 +98,15 @@ export default {
.then(eventName => this.arrayViewPath.splice(i, 1, eventName))
.catch((error) => this.$console.error(error));
break;
}
} else if (this.arrayRealPath[i-1] == 'importers' && i > 0){
this.fetchAvailableImporters()
.then(importers => {
this.arrayViewPath.splice(i, 1, importers[this.arrayRealPath[i]].name);
})
.catch((error) => this.$console.error(error));
} else {
this.arrayViewPath.splice(i, 1, this.$i18n.get(this.arrayRealPath[i]));
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 217 KiB

After

Width:  |  Height:  |  Size: 86 KiB

View File

@ -16,8 +16,10 @@ import EventPage from '../pages/singles/event-page.vue'
// Edition Form Components
import CollectionEditionForm from '../components/edition/collection-edition-form.vue'
import ImporterEditionForm from '../components/edition/importer-edition-form.vue'
import ItemEditionForm from '../components/edition/item-edition-form.vue'
import TaxonomyEditionForm from '../components/edition/taxonomy-edition-form.vue'
import AvailableImportersPage from '../pages/lists/available-importers-page.vue';
// Listing components
import FiltersList from '../components/lists/filters-list.vue'
@ -66,6 +68,9 @@ const routes = [
{ path: '/events', name: 'EventsPage', component: EventsPage, meta: {title: i18nGet('title_repository_events_page'), icon: 'flash'} },
{ path: '/events/:eventId', name: 'EventPage', component: EventPage, meta: {title: i18nGet('title_event_page'), icon: 'flash'} },
{ path: '/importers/', name: 'AvailableImportersPage', component: AvailableImportersPage, meta: {title: i18nGet('title_importers_page'), icon: 'file-multiple'} },
{ path: '/importers/:importerSlug', name: 'ImporterEditionForm', component: ImporterEditionForm, meta: {title: i18nGet('title_importer_page'), icon: 'file-multiple'} },
{ path: '*', redirect: '/'}
];

View File

@ -202,6 +202,9 @@ RouterHelperPlugin.install = function (Vue, options = {}) {
getEventsPath(query) {
return '/events/?' + qs.stringify(query);
},
getAvailableImportersPath() {
return '/importers/new';
},
// Singles
getCollectionPath(id) {
return '/collections/' + id;
@ -270,7 +273,10 @@ RouterHelperPlugin.install = function (Vue, options = {}) {
},
getEventEditPath(id) {
return '/events/' + id + '/edit';
}
},
getImporterEditionPath(importerType) {
return '/importers/' + importerType;
},
}
}

View File

@ -0,0 +1,78 @@
<template>
<div class="primary-page page-container">
<tainacan-title />
<h3>{{ $i18n.get('label_available_importers') }}</h3>
<p>{{ $i18n.get('info_available_importers_helper') }}</p>
<p>{{ $i18n.get('instruction_select_an_importer_type') }}</p>
<div class="importer-types-container">
<div
class="importer-type"
v-for="importerType in availableImporters"
:key="importerType.slug"
@click="onSelectImporter(importerType)">
<h4>{{ importerType.name }}</h4>
<p>{{ importerType.description }}</p>
</div>
</div>
<b-loading
:active.sync="isLoading"
:can-cancel="false"/>
</div>
</template>
<script>
import { mapActions } from 'vuex';
export default {
name: 'ImporterEditionForm',
data(){
return {
availableImporters: [],
isLoading: false
}
},
methods: {
...mapActions('importer', [
'fetchAvailableImporters'
]),
onSelectImporter(importerType) {
this.$router.push(this.$routerHelper.getImporterEditionPath(importerType.slug));
}
},
created() {
this.isLoading = true;
this.fetchAvailableImporters()
.then((res) => {
this.availableImporters = res;
this.isLoading = false;
}).catch((error) => {
this.$console.log(error);
this.isLoading = false;
});
}
}
</script>
<style lang="scss" scoped>
@import "../../scss/_variables.scss";
.importer-types-container {
display: flex;
flex: wrap;
.importer-type {
border: 1px solid $tainacan-input-background;
padding: 15px;
margin: 20px;
cursor: pointer;
}
}
</style>

View File

@ -7,6 +7,10 @@
}">
<tainacan-title />
<div :class="{ 'above-subheader': isRepositoryLevel }">
<b-loading
:active.sync="isLoading"
:can-cancel="false"/>
<events-list
:is-loading="isLoading"
:total-events="totalEvents"

View File

@ -15,8 +15,7 @@
<!-- Side bar with search and filters -->
<aside
v-show="!isFiltersMenuCompressed && !openAdvancedSearch"
class="filters-menu"
:class="{ 'tainacan-form': isOnTheme }">
class="filters-menu tainacan-form">
<b-loading
:is-full-page="false"
:active.sync="isLoadingFilters"/>
@ -290,20 +289,36 @@
<!-- ADVANCED SEARCH -->
<div
v-if="openAdvancedSearch">
<div 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>
</div>
</div>
<advanced-search
:is-repository-level="isRepositoryLevel"
:metadata-list="metadata" />
<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>
</div>
<advanced-search
:is-repository-level="isRepositoryLevel"
:metadata="metadata" />
</b-collapse>
</div>
<!-- --------------- -->
@ -365,18 +380,46 @@
:is-on-trash="status == 'trash'"
:view-mode="adminViewMode"/>
<!-- When advanced search -->
<!-- Theme View Modes -->
<div
v-if="isOnTheme &&
!isLoadingItems &&
openAdvancedSearch &&
advancedSearchResults &&
registeredViewModes[viewMode] != undefined &&
registeredViewModes[viewMode].type == 'template'"
v-html="itemsListTemplate"/>
<component
v-if="isOnTheme &&
!isLoadingItems &&
registeredViewModes[viewMode] != undefined &&
registeredViewModes[viewMode].type == 'component'"
registeredViewModes[viewMode].type == 'component' &&
openAdvancedSearch &&
advancedSearchResults"
:collection-id="collectionId"
:displayed-metadata="tableMetadata"
:items="items"
:is-loading="isLoadingItems"
:is="registeredViewModes[viewMode] != undefined ? registeredViewModes[viewMode].component : ''"/>
<!-- Regular -->
<!-- Theme View Modes -->
<div
v-if="isOnTheme &&
!isLoadingItems &&
!openAdvancedSearch &&
registeredViewModes[viewMode] != undefined &&
registeredViewModes[viewMode].type == 'template'"
v-html="itemsListTemplate"/>
<component
v-else-if="isOnTheme &&
!isLoadingItems &&
registeredViewModes[viewMode] != undefined &&
registeredViewModes[viewMode].type == 'component' &&
!openAdvancedSearch"
:collection-id="collectionId"
:displayed-metadata="tableMetadata"
:items="items"
@ -507,8 +550,8 @@
},
openAdvancedSearch(newValue){
if(newValue == false){
this.$router.push({query: {}});
location.reload();
this.$eventBusSearch.$emit('closeAdvancedSearch');
this.advancedSearchResults = false;
}
}
},
@ -725,15 +768,17 @@
}
});
if(this.$router.query && this.$router.query.metaquery && this.$router.query.metaquery.advancedSearch) {
this.openAdvancedSearch = this.$router.query.metaquery.advancedSearch;
this.$eventBusSearch.setViewMode(this.defaultViewMode);
if(this.$route.query && this.$route.query.advancedSearch) {
this.openAdvancedSearch = this.$route.query.advancedSearch;
}
},
mounted() {
if(this.$router.query && this.$router.query.metaquery && this.$router.query.metaquery.advancedSearch) {
this.openAdvancedSearch = this.$router.query.advancedSearch;
if(this.$route.query && this.$route.query.advancedSearch) {
this.openAdvancedSearch = this.$route.query.advancedSearch;
}
this.prepareMetadataAndFilters();
@ -807,7 +852,7 @@
max-width: $filter-menu-width;
min-height: 100%;
height: 100%;
background-color: $tainacan-input-background;
background-color: white;
padding: $page-small-side-padding;
float: left;
overflow-y: auto;

View File

@ -17,6 +17,9 @@
</div>
<div class="above-subheader">
<b-loading
:active.sync="isLoading"
:can-cancel="false"/>
<div class="tabs">
<ul>
<li

View File

@ -5,6 +5,7 @@
margin-bottom: -3px;
&:hover{
border-bottom-color: transparent;
text-decoration: none;
}
}
li.is-active a {

13
src/admin/scss/_tags.scss Normal file
View File

@ -0,0 +1,13 @@
.tags {
border: solid 1px $tainacan-input-background !important;
border-radius: 20px;
&:hover{
background-color: $tainacan-input-background;
}
.tag {
background: none !important;
margin-bottom: 0 !important;
}
}

View File

@ -6,6 +6,8 @@
justify-content: space-between !important;
padding: 12px 0px ;
margin-bottom: 0px;
width: 100%;
.button {
border-width: 1px;
padding: 2px 30px !important;
@ -68,14 +70,11 @@
select {
color: $tainacan-input-color;
background-color: white !important;
border: 1px solid $tainacan-input-background;
border: 1px solid $tainacan-input-background !important;
&:focus>option:checked, &:focus>option:hover {
background-color: $primary-lighter !important;
}
}
&.is-empty select{
//background-color: $tainacan-input-background !important;
}
}
}
.dropdown {
.button {
@ -84,4 +83,7 @@
padding: 2px 20px !important;
}
}
.upload-draggable {
border-radius: 0 !important;
}
}

View File

@ -20,6 +20,7 @@
@import "../scss/_tooltips.scss";
@import "../scss/_pagination.scss";
@import "../scss/_modals.scss";
@import "../scss/_tags.scss";
// Clears wordpress content
body.tainacan-admin-page #adminmenumain, body.tainacan-admin-page #wpfooter, body.tainacan-admin-page #wp-auth-check-wrap {
@ -46,6 +47,11 @@ html {
// Link (hover is the same color as secondary
a:hover {
color: $secondary;
text-decoration: underline;
}
.add-link {
display: inline;
font-size: 12px;
}
// Page settings
@ -63,10 +69,6 @@ a:hover {
height: 100%;
overflow-y: auto;
overflow-x: hidden;
@media screen and (max-width: 769px) {
padding: $page-mobile-top-padding $page-mobile-side-padding;
}
}
// Used for pages with collection subheader
.page-container-small {

View File

@ -6,3 +6,4 @@
@import "../../../node_modules/bulma/sass/elements/tag.sass"
@import "../../../node_modules/bulma/sass/components/tabs.sass"
@import "../../../node_modules/bulma/sass/elements/button.sass"
@import "../../../node_modules/bulma/sass/grid/columns.sass"

View File

@ -4,27 +4,32 @@ return apply_filters('tainacan-admin-i18n',[
// Advanced search comparators
'is_equal_to' => __( 'Equal', 'tainacan' ),
'is_not_equal_to' => __( 'Not Equal', 'tainacan'),
'is_not_equal_to' => __( 'Not equal', 'tainacan'),
'contains' => __( 'Contains', 'tainacan'),
'not_contains' => __( 'Not 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
'repository' => __( 'Repository', 'tainacan' ),
'collections' => __( 'Collections', 'tainacan' ),
'items' => __( 'Items', 'tainacan' ),
'metadata' => __( 'Metadata', 'tainacan' ),
'metadata' => __( 'Metadata', 'tainacan' ),
'filters' => __( 'Filters', 'tainacan' ),
'taxonomies' => __( 'Taxonomies', 'tainacan' ),
'events' => __( 'Events', 'tainacan' ),
'collection' => __( 'Collection', 'tainacan' ),
'item' => __( 'Item', 'tainacan' ),
'metadatum' => __( 'Metadata', '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' ),
// Actions
'edit' => __( 'Edit', 'tainacan' ),
@ -51,8 +56,11 @@ return apply_filters('tainacan-admin-i18n',[
'new_blank_collection' => __( 'New Blank Collection', 'tainacan' ),
'split' => __( 'Split', 'tainacan' ),
'unified' => __( 'Unified', 'tainacan' ),
'add_more_one_search_criteria' => __( 'Add more one search criteria', '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'),
// Wordpress Status
'publish' => __( 'Publish', 'tainacan' ),
@ -66,14 +74,14 @@ return apply_filters('tainacan-admin-i18n',[
// 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_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_metadatum_page' => __( 'Metadata', 'tainacan' ),
'title_collection_events' => __( 'Collection Events', 'tainacan' ),
'title_filter_page' => __( 'Filter', 'tainacan' ),
'title_taxonomy_page' => __( 'Taxonomy', 'tainacan' ),
@ -87,9 +95,11 @@ return apply_filters('tainacan-admin-i18n',[
'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_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' ),
// Labels (used mainly on Aria Labels and Inputs)
'label_clean' => __( 'Clear', 'tainacan' ),
@ -192,7 +202,8 @@ return apply_filters('tainacan-admin-i18n',[
'label_bulk_actions' => __( 'Bulk actions', 'tainacan' ),
'label_delete_selected_collections' => __( 'Delete selected collections', 'tainacan' ),
'label_edit_selected_collections' => __( 'Edit selected collections', 'tainacan' ),
'label_delete_selected_items' => __( 'Delete selected items', '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' ),
@ -214,6 +225,16 @@ return apply_filters('tainacan-admin-i18n',[
'label_table' => __( 'Table', 'tainacan' ),
'label_cards' => __( 'Cards', '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' ),
// Instructions. More complex sentences to guide user and placeholders
'instruction_delete_selected_collections' => __( 'Delete selected collections', 'tainacan' ),
@ -236,15 +257,20 @@ return apply_filters('tainacan-admin-i18n',[
'instruction_write_text' => __( 'Write Text', 'tainacan' ),
'instruction_search' => __( 'Search', 'tainacan' ),
'instruction_search_on_repository' => __( 'Search on repository', 'tainacan' ),
'instruction_select_a_target_collection' => __( 'Select a target collection', 'tainacan' ),
'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' ),
// Info. Other feedback to user.
'info_search_results' => __( 'Search Results', 'tainacan' ),
'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_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' ),
@ -260,17 +286,17 @@ return apply_filters('tainacan-admin-i18n',[
'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_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_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_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_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_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' ),
@ -282,7 +308,7 @@ return apply_filters('tainacan-admin-i18n',[
'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_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' ),
@ -291,7 +317,7 @@ return apply_filters('tainacan-admin-i18n',[
'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_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' ),
@ -303,7 +329,14 @@ return apply_filters('tainacan-admin-i18n',[
'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' ),
// Tainacan Metadatum Types
'tainacan-text' => __( 'Text', 'tainacan' ),
'tainacan-textarea' => __( 'Text area', 'tainacan' ),

View File

@ -288,7 +288,6 @@ export default {
.filters-menu {
height: auto;
min-width: $filter-menu-width-theme;
background-color: unset;
border-right: 0;
padding: 25px 12px 25px 4.1666667%;

View File

@ -64,6 +64,7 @@ class REST_Controller extends \WP_REST_Controller {
'authorid' => 'author_id',
'authorname' => 'author_name',
'search' => 's',
'searchterm' => 'search',
'status' => 'post_status',
'offset' => 'offset',
'metaquery' => 'meta_query',
@ -245,7 +246,7 @@ class REST_Controller extends \WP_REST_Controller {
foreach ( $request_meta_query as $index1 => $a ) {
// handle core metadatum
if( is_array($a) && array_key_exists("key", $a) ){
if( is_array($a) && array_key_exists("key", $a) && !$request['advancedSearch'] ){
$metadatum = new \Tainacan\Entities\Metadatum($a['key']);
if( strpos( $metadatum->get_metadata_type(), 'Core_Title') !== false ){
$args[ 'post_title_in' ] = [

View File

@ -0,0 +1,245 @@
<?php
namespace Tainacan\API\EndPoints;
use \Tainacan\API\REST_Controller;
use Tainacan\Repositories;
use Tainacan\Entities;
/**
* Represents the Background Processes REST Controller
*
* */
class REST_Background_Processes_Controller extends REST_Controller {
private $collections_repository;
private $collection;
/**
* REST_Background_Processes_Controller constructor.
* Define the namespace, rest base and instantiate your attributes.
*/
public function __construct(){
global $wpdb;
$this->rest_base = 'bg-processes';
$this->table = $wpdb->prefix . 'tnc_bg_process';
parent::__construct();
}
/**
* Register the BG Processes route and their endpoints
*/
public function register_routes(){
register_rest_route($this->namespace, '/' . $this->rest_base , array(
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array($this, 'get_items'),
'permission_callback' => array($this, 'bg_processes_permissions_check'),
'args' => [
'user_id' => [
'type' => 'integer',
'description' => __( 'The ID of the owner of the background processes. Defaults to current user', 'tainacan' ),
],
'all_users' => [
'type' => 'bool',
'description' => __( 'Whether to return processes from all users (if current user is admin). Default false.', 'tainacan' ),
],
'status' => [
'type' => 'string',
'description' => __( '"open" returns only processes currently running. "closed" returns only finished or aborted. "all" returns all. Default "all"', 'tainacan' ),
]
],
),
));
register_rest_route($this->namespace, '/' . $this->rest_base . '/(?P<id>[0-9]+)', array(
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array($this, 'get_item'),
'permission_callback' => array($this, 'bg_processes_permissions_check'),
),
));
register_rest_route($this->namespace, '/' . $this->rest_base . '/(?P<id>[0-9]+)', array(
array(
'methods' => \WP_REST_Server::EDITABLE,
'callback' => array($this, 'update_item'),
'permission_callback' => array($this, 'bg_processes_permissions_check'),
'args' => [
'status' => [
'type' => 'string',
'description' => __( '"open" or "closed" ', 'tainacan' ),
]
],
),
));
register_rest_route($this->namespace, '/' . $this->rest_base . '/(?P<id>[0-9]+)', array(
array(
'methods' => \WP_REST_Server::DELETABLE,
'callback' => array($this, 'delete_item'),
'permission_callback' => array($this, 'bg_processes_permissions_check'),
),
));
}
/**
*
* @param \WP_REST_Request $request
*
* @return bool|\WP_Error
* @throws \Exception
*/
public function bg_processes_permissions_check($request){
// TODO
return current_user_can('read');
}
public function get_items( $request ) {
global $wpdb;
$body = json_decode($request->get_body(), true);
$user_q = $wpdb->prepare("AND user_id = %d", get_current_user_id());
$status_q = "";
if (current_user_can('edit_users')) {
if (isset($body['user_id'])) {
$user_q = $wpdb->prepare("AND user_id = %d", $body['user_id']);
}
if ( isset($user_q['all_users']) && $user_q['all_users'] ) {
$user_q = "";
}
}
if ( isset($request['status']) && $request['status'] != 'all' ) {
if ( $request['status'] == 'open' ) {
$status_q = "AND done = 0";
}
if ( $request['status'] == 'closed' ) {
$status_q = "AND done = 1";
}
}
$query = "SELECT * FROM $this->table WHERE 1=1 $status_q $user_q ORDER BY priority DESC, queued_on DESC";
$result = $wpdb->get_results($query);
return new \WP_REST_Response( $result, 200 );
}
public function get_item( $request ) {
global $wpdb;
$id = $request['id'];
$user_q = $wpdb->prepare("AND user_id = %d", get_current_user_id());
$id_q = $wpdb->prepare("AND ID = %d", $id);
// do not allow users without permission to see others people process
if (current_user_can('edit_users')) {
if ( isset($user_q['all_users']) && $user_q['all_users'] ) {
$user_q = "";
}
}
$query = "SELECT * FROM $this->table WHERE 1=1 $id_q $user_q LIMIT 1";
$result = $wpdb->get_row($query);
$result->log = $this->get_log_url($id, $result->action);
$result->error_log = $this->get_log_url($id, $result->action, 'error');
return new \WP_REST_Response( $result, 200 );
}
public function update_item( $request ) {
global $wpdb;
$id = $request['id'];
$body = json_decode($request->get_body(), true);
if ( !isset($body['status']) || ($body['status'] != 'open' && $body['status'] != 'closed') ) {
return new \WP_REST_Response([
'error_message' => __('Status must be informed', 'tainacan' ),
'session_id' => $session_id
], 400);
}
if ( $body['status'] == 'open' ) {
$status_q = "done = 0";
}
if ( $body['status'] == 'closed' ) {
$status_q = "done = 1";
}
$id_q = $wpdb->prepare("AND ID = %d", $id);
$user_q = $wpdb->prepare("AND user_id = %d", get_current_user_id());
// do not allow users without permission to see others people process
if (current_user_can('edit_users')) {
if ( isset($user_q['all_users']) && $user_q['all_users'] ) {
$user_q = "";
}
}
$query = "UPDATE $this->table $status_q WHERE 1=1 $id_q $user_q";
$result = $wpdb->query($query);
return new \WP_REST_Response( $result, 200 );
}
public function delete_item( $request ) {
global $wpdb;
$id = $request['id'];
$user_q = $wpdb->prepare("AND user_id = %d", get_current_user_id());
$id_q = $wpdb->prepare("AND ID = %d", $id);
// do not allow users without permission to see others people process
if (current_user_can('edit_users')) {
if ( isset($user_q['all_users']) && $user_q['all_users'] ) {
$user_q = "";
}
}
$query = "DELETE FROM $this->table WHERE 1=1 $id_q $user_q LIMIT 1";
$result = $wpdb->query($query);
// TODO: delete log files
return new \WP_REST_Response( $result, 200 );
}
public function get_log_url($id, $action, $type = '') {
$suffix = $type ? '-' . $type : '';
$filename = 'bg-' . $action . '-' . $id . $suffix . '.log';
$upload_url = wp_upload_dir();
$upload_url = trailingslashit( $upload_url['url'] );
$logs_url = $upload_url . 'tainacan';
return $logs_url;
}
}
?>

View File

@ -188,7 +188,14 @@ class REST_Collections_Controller extends REST_Controller {
}
$item_arr['url'] = get_permalink( $item_arr['id'] );
}
}
$total_items = wp_count_posts( $item->get_db_identifier(), 'readable' );
$item_arr['total_items']['trash'] = $total_items->trash;
$item_arr['total_items']['publish'] = $total_items->publish;
$item_arr['total_items']['draft'] = $total_items->draft;
$item_arr['total_items']['private'] = $total_items->private;
return $item_arr;
}

View File

@ -20,23 +20,18 @@ class REST_Importers_Controller extends REST_Controller {
*/
public function __construct(){
$this->rest_base = 'importers';
if (session_status() == PHP_SESSION_NONE) {
@session_start(); // @ avoids Warnings when running phpunit tests
}
parent::__construct();
add_action('init', array(&$this, 'init_objects'), 11);
}
/**
* Initialize objects after post_type register
*/
public function init_objects() {
//$this->collections_repository = Repositories\Collections::get_instance();
//$this->collection = new Entities\Collection();
}
/**
* Register the collections route and their endpoints
*/
public function register_routes(){
register_rest_route($this->namespace, '/' . $this->rest_base, array(
register_rest_route($this->namespace, '/' . $this->rest_base . '/session', array(
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array($this, 'create_item'),
@ -49,7 +44,7 @@ class REST_Importers_Controller extends REST_Controller {
],
),
));
register_rest_route($this->namespace, '/' . $this->rest_base . '/(?P<session_id>[0-9a-f]+)', array(
register_rest_route($this->namespace, '/' . $this->rest_base . '/session/(?P<session_id>[0-9a-f]+)', array(
array(
'methods' => \WP_REST_Server::EDITABLE,
@ -61,7 +56,7 @@ class REST_Importers_Controller extends REST_Controller {
'description' => __( 'The URL to be used by the importer', 'tainacan' ),
],
'collection' => [
'type' => 'array',
'type' => 'array/object',
'description' => __( 'The array describing the destination collectino as expected by the importer', 'tainacan' ),
],
'options' => [
@ -73,7 +68,7 @@ class REST_Importers_Controller extends REST_Controller {
));
register_rest_route($this->namespace, '/' . $this->rest_base . '/(?P<session_id>[0-9a-f]+)/file', array(
register_rest_route($this->namespace, '/' . $this->rest_base . '/session/(?P<session_id>[0-9a-f]+)/file', array(
array(
'methods' => \WP_REST_Server::CREATABLE,
@ -83,7 +78,7 @@ class REST_Importers_Controller extends REST_Controller {
));
register_rest_route($this->namespace, '/' . $this->rest_base . '/(?P<session_id>[0-9a-f]+)/source_info', array(
register_rest_route($this->namespace, '/' . $this->rest_base . '/session/(?P<session_id>[0-9a-f]+)/source_info', array(
array(
'methods' => \WP_REST_Server::READABLE,
@ -93,7 +88,7 @@ class REST_Importers_Controller extends REST_Controller {
));
register_rest_route($this->namespace, '/' . $this->rest_base . '/(?P<session_id>[0-9a-f]+)/run', array(
register_rest_route($this->namespace, '/' . $this->rest_base . '/session/(?P<session_id>[0-9a-f]+)/run', array(
array(
'methods' => \WP_REST_Server::CREATABLE,
@ -102,6 +97,17 @@ class REST_Importers_Controller extends REST_Controller {
),
));
register_rest_route($this->namespace, '/' . $this->rest_base . '/available', array(
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array($this, 'get_registered_importers'),
'permission_callback' => array($this, 'import_permissions_check'),
),
));
}
@ -172,6 +178,19 @@ class REST_Importers_Controller extends REST_Controller {
if($importer) {
foreach ($body as $att => $value){
if ($att == 'collection') {
if (is_array($value) && isset($value['id'])) {
$importer->add_collection($value);
continue;
} else {
return new \WP_REST_Response([
'error_message' => __('Invalid collection', 'tainacan' ),
'session_id' => $session_id
], 400);
}
}
$method = 'set_' . $att;
if (method_exists($importer, $method)) {
$importer->$method($value);
@ -196,7 +215,7 @@ class REST_Importers_Controller extends REST_Controller {
}
public function source_info() {
public function source_info( $request ) {
$session_id = $request['session_id'];
$importer = $_SESSION['tainacan_importer'][$session_id];
@ -224,7 +243,7 @@ class REST_Importers_Controller extends REST_Controller {
}
public function add_file() {
public function add_file( $request ) {
$session_id = $request['session_id'];
$importer = $_SESSION['tainacan_importer'][$session_id];
@ -253,7 +272,7 @@ class REST_Importers_Controller extends REST_Controller {
}
public function run() {
public function run($request) {
$session_id = $request['session_id'];
$importer = $_SESSION['tainacan_importer'][$session_id];
@ -267,13 +286,27 @@ class REST_Importers_Controller extends REST_Controller {
global $Tainacan_Importer_Handler;
$process = $Tainacan_Importer_Handler->add_to_queue($importer);
if (false === $process) {
return new \WP_REST_Response([
'error_message' => __('Error starting importer', 'tainacan' ),
'session_id' => $session_id
], 400);
}
$response = [
'bg_process_id' => $process->get_id()
'bg_process_id' => $process->ID
];
return new \WP_REST_Response( $response, 200 );
}
public function get_registered_importers() {
global $Tainacan_Importer_Handler;
$importers = $Tainacan_Importer_Handler->get_registered_importers();
return new \WP_REST_Response( $importers, 200 );
}
}

View File

@ -217,7 +217,7 @@ class REST_Items_Controller extends REST_Controller {
}
$items = $this->items_repository->fetch($args, $collection_id, 'WP_Query');
$response = [];
$return_template = false;

View File

@ -298,6 +298,12 @@ class REST_Metadata_Controller extends REST_Controller {
$item_arr = $item->_toArray();
$item_arr['metadata_type_object'] = $item->get_metadata_type_object()->_toArray();
if(isset($item_arr['metadata_type_options']) && isset($item_arr['metadata_type_options']['taxonomy_id'])){
$taxonomy = new Entities\Taxonomy($item_arr['metadata_type_options']['taxonomy_id']);
$item_arr['metadata_type_options']['taxonomy'] = $taxonomy->get_db_identifier();
}
if($request['context'] === 'edit'){
$item_arr['current_user_can_edit'] = $item->can_edit();
@ -326,7 +332,7 @@ class REST_Metadata_Controller extends REST_Controller {
$args = $this->prepare_filters( $request );
if ($request['context'] === 'edit') {
if ($request['include_disabled'] === 'true') {
$args['include_disabled'] = true;
}

View File

@ -14,6 +14,7 @@ $rest_logs_controller = new \Tainacan\API\EndPoints\REST_Logs_Control
$rest_metadata_types_controller = new \Tainacan\API\EndPoints\REST_Metadata_Types_Controller();
$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();
new \Tainacan\API\EndPoints\REST_Export_Controller();
new \Tainacan\API\EndPoints\REST_Metadatum_Mappers_Controller();
// Add here other endpoints imports

View File

@ -36,7 +36,7 @@ abstract class Background_Process extends \WP_Background_Process {
* ID of the process in the database
* @var false|int
*/
protected $ID = false;
public $ID = false;
/**
* Prefix
@ -105,14 +105,17 @@ abstract class Background_Process extends \WP_Background_Process {
*
* @return $this
*/
public function update( $key, $data ) {
public function update( $key, $batch ) {
$data = $batch->data;
if ( ! empty( $data ) ) {
global $wpdb;
$wpdb->update(
$this->table,
[
'data' => maybe_serialize($data),
'processed_last' => date('Y-m-d H:i:s')
'processed_last' => date('Y-m-d H:i:s'),
'progress_label' => $batch->progress_label,
'progress_value' => $batch->progress_value
],
['ID' => $key]
);
@ -215,13 +218,22 @@ abstract class Background_Process extends \WP_Background_Process {
*/
protected function handle() {
$this->lock_process();
//error_log('new request');
// while we are debugging performance
$newRequest = true;
do {
$batch = $this->get_batch();
if ($newRequest) {
$this->write_log($batch->key, ['New Request']);
$newRequest = false;
}
// TODO: find a way to catch and log PHP errors as
try {
$task = $this->task( $batch->data, $batch->key );
$task = $this->task( $batch );
} catch (\Exception $e) {
// TODO: Add Stacktrace
$this->write_error_log($batch->key, ['Fatal Error: ' . $e->getMessage()]);

View File

@ -168,11 +168,11 @@
let index = this.query.metaquery.findIndex(newMetadatum => newMetadatum.key === this.metadatum );
if ( index >= 0){
let metadata = this.query.metaquery[ index ];
if( metadata.value.length > 0 && this.type === 'numeric'){
if( metadata.value && metadata.value.length > 0 && this.type === 'numeric'){
this.value_init = metadata.value[0];
this.value_end = metadata.value[1];
this.isValid = true;
} else if( metadata.value.length > 0 ){
} else if( metadata.value && metadata.value.length > 0 ){
this.date_init = new Date( metadata.value[0] );
this.date_end = new Date( metadata.value[1] );

View File

@ -165,7 +165,10 @@
.collapse-content {
margin-top: 12px;
}
.columns{
margin-left: 0px;
margin-right: 0px;
}
.column {
padding: 0.75rem 1px 0.75rem 0 !important;
}
@ -180,16 +183,10 @@
padding: 2px 25px 2px 15px !important;
margin-top: 0px !important;
margin-bottom: 0px !important;
background-color: white;
color: black;
&:focus > option:checked, &:focus > option:hover {
background-color: $primary-lighter !important;
}
}
&:not(.is-multiple)::after {
content: "\F35D" !important;
font: normal normal normal 24px/1 "Material Design Icons" !important;
border: none !important;
transform: none;
margin-top: -0.6em;
right: 0.95em;
@ -208,8 +205,6 @@
font-size: 14px;
border-radius: 1px !important;
background-color: white;
color: $tainacan-input-color;
box-shadow: none !important;
transition: background-color 0.1s;
height: 2.25em !important;

View File

@ -500,7 +500,7 @@ if ( ! class_exists( 'WP_Background_Process' ) ) {
*
* @return mixed
*/
abstract protected function task( $item, $key );
abstract protected function task( $item );
}
}

View File

@ -49,7 +49,7 @@
this.dateFormat = localeData.longDateFormat('L');
if( this.value ){
this.dateValue = this.parseDateToNavigatorLanguage(new Date(this.value.replace(/-/g, '/')));
this.dateValue = this.parseDateToNavigatorLanguage(this.value);
}
},
data() {
@ -83,6 +83,8 @@
this.$emit('blur');
},
parseDateToNavigatorLanguage(date){
date = new Date(date.replace(/-/g, '/'));
return moment(date, moment.ISO_8601).format(this.dateFormat);
}
}

View File

@ -6,7 +6,7 @@
:type="collectionType"
:message="collectionMessage">
<label class="label is-inline">
{{ $i18n.get('label_collection_related') }}<span :class="collectionType" >&nbsp;*&nbsp;</span>
{{ $i18n.get('label_related_collection') }}<span :class="collectionType" >&nbsp;*&nbsp;</span>
<help-button
:title="$i18n.getHelperTitle('tainacan-relationship', 'collection_id')"
:message="$i18n.getHelperMessage('tainacan-relationship', 'collection_id')"/>

View File

@ -23,7 +23,7 @@ class Relationship extends Metadata_Type {
public function get_form_labels(){
return [
'collection_id' => [
'title' => __( 'Collection Related', 'tainacan' ),
'title' => __( 'Related Collection', 'tainacan' ),
'description' => __( 'Select the collection to fetch items', 'tainacan' ),
],
'search' => [

View File

@ -32,7 +32,7 @@ class Taxonomy extends Metadata_Type {
public function get_form_labels(){
return [
'taxonomy_id' => [
'title' => __( 'Collection Related', 'tainacan' ),
'title' => __( 'Related Collection', 'tainacan' ),
'description' => __( 'Select the collection to fetch items', 'tainacan' ),
],
'input_type' => [

View File

@ -34,7 +34,10 @@ trait Entity_Collection_Relation {
$Tainacan_Collections = \Tainacan\Repositories\Collections::get_instance();
$this->collection = $Tainacan_Collections->fetch($this->get_collection_id());
return $this->collection;
if($this->collection instanceof Entities\Collection){
return $this->collection;
}
}
return null;

View File

@ -21,7 +21,11 @@ trait Entity_Collections_Relation {
$this->collections = [];
foreach ($this->get_collections_ids() as $col_id) {
$this->collections[] = $Tainacan_Collections->fetch($col_id);
$collection = $Tainacan_Collections->fetch($col_id);
if($collection instanceof \Tainacan\Entities\Collection){
$this->collections[] = $collection;
}
}
return $this->collections;

View File

@ -9,8 +9,11 @@ class Background_Importer extends Background_Process {
*/
protected $action = 'import';
function task($data, $key) {
function task($batch) {
$data = $batch->data;
$key = $batch->key;
$className = $data['class_name'];
if (class_exists($className)) {
$object = new $className($data);
@ -26,7 +29,13 @@ class Background_Importer extends Background_Process {
if (false === $runned) {
return false;
}
return $object->_to_Array();
$batch->progress_label = $object->get_progress_label();
$batch->progress_value = $object->get_progress_value();
$batch->data = $object->_to_Array(true);
return $batch;
}
return false;

View File

@ -17,18 +17,37 @@ class Importer_Handler {
public function init() {
$this->register_importer([
'name' => 'CSV',
'description' => __('Import items from a CSV file to a chosen collection', 'tainacan'),
'slug' => 'csv',
'class_name' => '\Tainacan\Importer\CSV'
]);
$this->register_importer([
'name' => 'Test Importer',
'description' => __('Create 2 test colletions with random items', 'tainacan'),
'slug' => 'test',
'class_name' => '\Tainacan\Importer\Test_Importer'
]);
$this->register_importer([
'name' => 'Tainacan Old',
'description' => __('Import structure from previously version of tainacan', 'tainacan'),
'slug' => 'tainacan_old',
'class_name' => '\Tainacan\Importer\Old_Tainacan'
]);
do_action('tainacan_register_importers');
}
function add_to_queue(\Tainacan\Importer\Importer $importer_object) {
$data = $importer_object->_to_Array();
$importer_object = $this->bg_importer->data($data)->save()->dispatch();
return $importer_object;
$data = $importer_object->_to_Array(true);
$bg_process = $this->bg_importer->data($data)->save();
if ( is_wp_error($bg_process->dispatch()) ) {
return false;
}
return $bg_process;
}
/**

View File

@ -61,7 +61,7 @@ abstract class Importer {
* Example of the structure of this propery for one collection:
* 0 => [
* 'id' => 12,
* 'map' => [
* 'mapping' => [
* 30 => 'column1'
* 31 => 'column2'
* ],
@ -89,7 +89,7 @@ abstract class Importer {
*/
protected $default_options = [];
private $accpets = [
private $accepts = [
'file' => true,
'url' => false,
];
@ -108,6 +108,7 @@ abstract class Importer {
protected $steps = [
[
'name' => 'Import Items',
'progress_label' => 'Importing Items',
'callback' => 'process_collections'
]
];
@ -179,13 +180,20 @@ abstract class Importer {
}
public function _to_Array() {
public function _to_Array($short = false) {
$return = ['id' => $this->get_id()];
foreach ($this->array_attributes as $attr) {
$method = 'get_' . $attr;
$return[$attr] = $this->$method();
}
$return['class_name'] = get_class($this);
if ($short === false) {
$return['manual_collection'] = $this->manual_collection;
$return['manual_mapping'] = $this->manual_mapping;
$return['accepts'] = $this->accepts;
}
return $return;
}
@ -341,7 +349,8 @@ abstract class Importer {
public function add_file( $file ){
$new_file = $this->upload_file( $file );
if ( is_numeric( $new_file ) ) {
$this->tmp_file = get_attached_file( $new_file );
$this->tmp_file = get_attached_file( $new_file );
return true;
} else {
return false;
}
@ -383,12 +392,19 @@ abstract class Importer {
* @param $path_file
* @return array $response
*/
private function upload_file( $path_file ){
$name = basename( $path_file );
$file_array['name'] = $name;
$file_array['tmp_name'] = $path_file;
$file_array['size'] = filesize( $path_file );
return media_handle_sideload( $file_array, 0 );
private function upload_file( $file_array ){
//$name = basename( $path_file );
//$file_array['name'] = $name;
//$file_array['tmp_name'] = $path_file;
//$file_array['size'] = filesize( $path_file );
if ( !function_exists('media_handle_upload') ) {
require_once(ABSPATH . "wp-admin" . '/includes/image.php');
require_once(ABSPATH . "wp-admin" . '/includes/file.php');
require_once(ABSPATH . "wp-admin" . '/includes/media.php');
}
//var_dump(media_handle_sideload( $file_array, 0 )); die;
return media_handle_sideload( $file_array, 0 );
}
/**
@ -429,8 +445,8 @@ abstract class Importer {
* @return bool true for success, false if method does not exist
*/
public function add_import_method($method) {
if ( array_key_exists($method, $this->accpets) ) {
$this->acceps[$method] = true;
if ( array_key_exists($method, $this->accepts) ) {
$this->accepts[$method] = true;
return true;
}
return false;
@ -445,8 +461,8 @@ abstract class Importer {
* @return bool true for success, false if method does not exist
*/
public function remove_import_method($method) {
if ( array_key_exists($method, $this->accpets) ) {
$this->acceps[$method] = false;
if ( array_key_exists($method, $this->accepts) ) {
$this->accepts[$method] = false;
return true;
}
return false;
@ -501,6 +517,131 @@ abstract class Importer {
return $this->abort;
}
/**
* Gets the current label to be displayed below the progress bar to give
* feedback to the user.
*
* It automatically gets the attribute progress_label from the current step running.
*
* Importers may change this label whenever they want
*
* @return string
*/
public function get_progress_label() {
$current_step = $this->get_current_step();
$steps = $this->get_steps();
$label = '';
if ( isset($steps[$current_step]) ) {
$step = $steps[$current_step];
if ( isset($step['progress_label']) ) {
$label = $step['progress_label'];
} elseif ( isset($step['name']) ) {
$label = $step['name'];
}
}
if ( sizeof($steps) > 1 ) {
$preLabel = sprintf( __('Step %d of %d', 'tainacan'), $current_step + 1, sizeof($steps) );
$label = $preLabel . ': ' . $label;
}
if ( empty($label) ) {
$label = __('Running Importer', 'tainacan');
}
return $label;
}
/**
* Gets the current value to build the progress bar and give feedback to the user
* on the background process that is running the importer.
*
* It does so by comparing the "size" attribute with the $in_step_count class attribute
* where size indicates the total size of iterations the step will take and $this->in_step_count
* is the current iteration.
*
* For the step with "process_items" as a callback, this method will look for the the $this->collections array
* and sum the value of all "total_items" attributes of each collection. Then it will look for
* $this->get_current_collection and $this->set_current_collection_item to calculate the progress.
*
* The value must be from 0 to 100
*
* If a negative value is passed, it is assumed that the progress is unknown
*/
public function get_progress_value() {
$current_step = $this->get_current_step();
$steps = $this->get_steps();
$value = -1;
if ( isset($steps[$current_step]) ) {
$step = $steps[$current_step];
if ($step['callback'] == 'process_collections') {
$totalItems = 0;
$currentItem = $this->get_current_collection_item();
$current_collection = $this->get_current_collection();
$collections = $this->get_collections();
foreach ($collections as $i => $col) {
if ( isset($col['total_items']) && is_integer($col['total_items']) ) {
$totalItems += $col['total_items'];
if ($i < $current_collection) {
$currentItem += $col['total_items'];
}
}
}
if ($totalItems > 0) {
$value = round( ($currentItem/$totalItems) * 100 );
}
} else {
if ( isset($step['total']) && is_integer($step['total']) && $step['total'] > 0 ) {
$current = $this->get_in_step_count();
$value = round( ($current/$step['total']) * 100 );
}
}
}
return $value;
}
/**
* Sets the total attribute for the current step
*
* The "total" attribute of a step indicates the number of iterations this step will take to complete.
*
* The iteration is counted using $this->in_step_count attribute, and comparing the two values gives us
* the current progress of the process.
*
*/
protected function set_current_step_total(int $value) {
$this->set_step_total($this->get_current_step(), $value);
}
/**
* Sets the total attribute for a given step
*
* The "total" attribute of a step indicates the number of iterations this step will take to complete.
*
* The iteration is counted using $this->in_step_count attribute, and comparing the two values gives us
* the current progress of the process.
*
*/
protected function set_step_total(int $step, int $value) {
$steps = $this->get_steps();
if (isset($steps[$step]) && is_array($steps[$step])) {
$steps[$step]['total'] = $value;
$this->set_steps($steps);
}
}
///////////////////////////////
// Abstract methods
@ -633,7 +774,7 @@ abstract class Importer {
$collections = $this->get_collections();
$collection_definition = isset($collections[$collection_index]) ? $collections[$collection_index] : false;
if ( !$collection_definition || !is_array($collection_definition) || !isset($collection_definition['id']) || !isset($collection_definition['map']) ) {
if ( !$collection_definition || !is_array($collection_definition) || !isset($collection_definition['id']) || !isset($collection_definition['mapping']) ) {
$this->add_error_log('Collection misconfigured');
return false;
}
@ -649,7 +790,7 @@ abstract class Importer {
if( is_array( $processed_item ) ){
foreach ( $processed_item as $metadatum_source => $values ){
$tainacan_metadatum_id = array_search( $metadatum_source, $collection_definition['map'] );
$tainacan_metadatum_id = array_search( $metadatum_source, $collection_definition['mapping'] );
$metadatum = $Tainacan_Metadata->fetch( $tainacan_metadatum_id );
if( $metadatum instanceof Entities\Metadatum ){

View File

@ -5,30 +5,36 @@ use \Tainacan\Entities;
class Old_Tainacan extends Importer{
protected $manual_mapping = true;
protected $manual_collection = true;
protected $manual_mapping = false;
protected $manual_collection = false;
protected $steps = [
[
'name' => 'Create Taxonomies',
'name' => 'Create Taxonomies',
'progress_label' => 'Creating taxonomies',
'callback' => 'create_taxonomies'
],
[
'name' => 'Create Repo Metadata',
'name' => 'Create Repo Metadata',
'progress_label' => 'Create Repo Metadata',
'callback' => 'create_repo_metadata'
],
[
'name' => 'Create Collections',
'name' => 'Create Collections',
'progress_label' => 'Create Collections',
'callback' => 'create_collections'
],
[
'name' => 'Import Items',
'name' => 'Import Items',
'progress_label' => 'Import Items',
'callback' => 'process_collections'
],
[
'name' => 'Finalize',
'callback' => 'finish_processing'
],
[
'name' => 'Link Relationships',
'progress_label' => 'Link Relationships',
'callback' => 'link_relationships',
'total' => 5
]
];
@ -38,15 +44,15 @@ class Old_Tainacan extends Importer{
/**
* tainacan old importer construct
*/
public function __construct(){
parent::__construct();
public function __construct($attributes = array()) {
parent::__construct($attributes);
$this->tax_repo = \Tainacan\Repositories\Taxonomies::get_instance();
$this->col_repo = \Tainacan\Repositories\Collections::get_instance();
$this->items_repo = \Tainacan\Repositories\Items::get_instance();
$this->metadata_repo = \Tainacan\Repositories\Metadata::get_instance();
$this->term_repo = \Tainacan\Repositories\Terms::get_instance();
$this->item_metadata_repo = \Tainacan\Repositories\Item_Metadata::get_instance();
$this->remove_import_method('file');
$this->add_import_method('url');
@ -122,14 +128,16 @@ class Old_Tainacan extends Importer{
$collection_id = $this->create_collection( $collection );
foreach( $this->get_collection_metadata( $collection->ID ) as $metadatum_old ) {
$metadatum_id = $this->create_metadata( $metadatum_old, $collection_id );
$map[$metadatum_id] = $metadatum_old->id;
if (isset($metadatum_old->slug) && strpos($metadatum_old->slug, 'socialdb_property_fixed') === false) {
$metadatum_id = $this->create_metadata( $metadatum_old, $collection_id );
$map[$metadatum_id] = $metadatum_old->id;
}
}
$this->add_collection([
'id' => $collection_id,
'map' => $map,
'mapping' => $map,
'total_items' => $this->get_total_items_from_source( $collection->ID ),
'source_id' => $collection->ID,
'items' => $this->get_all_items( $collection->ID )
@ -140,17 +148,49 @@ class Old_Tainacan extends Importer{
}
/**
* Method implemented by the child importer class to proccess each item
* Method responsible for links all relationships metadata
* @return int
*/
public function link_relationships(){
$args = [];
$collections = $this->col_repo->fetch([], 'OBJECT');
foreach( $this->metadata_repo->fetch($args, 'OBJECT' ) as $metadatum ){
//var_dump($metadatum->get_metadata_type());
}
if( $collections && is_array( $collections ) ){
// TODO: get all imported relationships and find the collection target
foreach( $collections as $collection ){ // loop collections
$map = $this->get_transient('collection_' . $collection->get_id() . '_relationships');
if(!$map){
return false;
}
foreach( $map as $metadatum_id => $items ){ // all relations in collection
$newMetadatum = new Entities\Metadatum($metadatum_id);
$first_index_id = key($items);
$collection_id = $this->get_transient('item_' . $items[$first_index_id] . '_collection');
$newMetadatum->set_metadata_type_options(['collection_id' => $collection_id ]);
if($newMetadatum->validate()){
$this->metadata_repo->update( $newMetadatum );
}
reset($items);
foreach( $items as $item_id => $value_old ){ // all values
$value_new = $this->get_transient('item_' . $value_old . '_id');
$item = new Entities\Item($item_id);
$item_metadata = new Entities\Item_Metadata_Entity( $item, $newMetadatum );
$item_metadata->set_value($value_new);
if( $item_metadata->validate() ){
$this->item_metadata_repo->insert( $item_metadata );
}
}
}
}
}
}
/**
@ -162,17 +202,116 @@ class Old_Tainacan extends Importer{
if( isset($collection_id['items'][$index]) ){
$item_Old = $collection_id['items'][$index]->item;
$collection = new Entities\Collection($collection_id['id']);
$item = new Entities\Item();
$item->set_name( $item_Old->post_title );
$item->set_description( $item_Old->post_content_filtered );
$item->set_title( $item_Old->post_title );
$item->set_description( (isset($item_Old->post_content)) ? $item_Old->post_content : '' );
$item->set_status('publish');
$item->set_collection( $collection );
if( $item->validate() ){
$insertedItem = $this->items_repo->insert( $item );
$this->add_transient('item_' . $item_Old->ID . '_id', $insertedItem->get_id()); // add reference for relations
$this->add_transient('item_' . $item_Old->ID . '_collection', $collection_id['id']); // add collection for relations
if( $insertedItem->get_id() && is_array($collection_id['items'][$index]->metadata) ){
$this->add_item_metadata( $insertedItem, $collection_id['items'][$index]->metadata, $collection_id );
//inserting files
$this->insert_files( $item_Old, $insertedItem );
}
} else {
$this->add_error_log( 'Error inserting item' );
$this->add_error_log( $item->get_errors() );
return false;
}
} else {
$this->add_error_log($result->get_error_message());
$this->add_error_log('proccessing an item empty');
$this->abort();
return false;
}
var_dump($collection_id['items'][$index]->item);
}
/**
* Method responsible to insert item metadata
*/
public function add_item_metadata( $item, $metadata_old, $collection_id ){
$relationships = [];
foreach( $metadata_old as $metadatum ){
if( isset($metadatum->id) && array_search($metadatum->id,$collection_id['mapping']) ){
$new_tainacanid = array_search($metadatum->id,$collection_id['mapping']);
$newMetadatum = new Entities\Metadatum($new_tainacanid);
$item_metadata = new Entities\Item_Metadata_Entity( $item, $newMetadatum );
// avoid blank metadatum
if( isset($metadatum->empty) ){
continue;
}
if( isset($metadatum->values) && empty($metadatum->values) ){
continue;
}
if( is_array($metadatum->values) && empty( array_filter($metadatum->values) ) ){
continue;
}
$unique = !$item_metadata->is_multiple();
$value = ( is_array($metadatum->values) && $unique ) ? $metadatum->values[0] : $metadatum->values;
if( in_array($metadatum->type,['text', 'textarea', 'numeric', 'date']) ){
$item_metadata->set_value($value);
} else if( $metadatum->type === 'item' ){ // RELATIONSHIPS
/**
* save the values to allow set the correct collection
* in metadata option in next step
*/
$relationships[$new_tainacanid][$item->get_id()] = $value;
} else {
if( is_array($value) ) {
$values = [];
foreach( is_array($value) as $cat){
$id = $this->get_transient('term_' . $cat . '_id');
if( $id )
$values[] = intval($id);
}
} else {
$id = $this->get_transient('term_' . $value . '_id');
if( $id )
$values = intval($id);
}
$item_metadata->set_value($values);
}
if( $item_metadata->validate() ){
$inserted = $this->item_metadata_repo->insert( $item_metadata );
} else {
$this->add_error_log( 'Error inserting metadatum' );
$this->add_error_log( $item_metadata->get_errors() );
return false;
}
}
}
$this->add_transient('collection_' . $collection_id['id'] . '_relationships', $relationships ); // add reference for relations
}
/**
@ -180,7 +319,12 @@ class Old_Tainacan extends Importer{
* @return int
*/
public function get_total_items_from_source( $collection_id ) {
$info = wp_remote_get( $this->get_url() . $this->tainacan_api_address . "/collections/".$collection_id."/items" );
$args = array(
'timeout' => 30,
'redirection' => 30,
);
$info = wp_remote_get( $this->get_url() . $this->tainacan_api_address . "/collections/".$collection_id."/items", $args );
if( !isset($info['body']) ){
$this->add_error_log($result->get_error_message());
@ -384,8 +528,9 @@ class Old_Tainacan extends Importer{
$newMetadatum->set_name($name);
$newMetadatum->set_metadata_type('Tainacan\Metadata_Types\\'.$type);
$newMetadatum->set_collection_id( (isset($collection_id)) ? $collection_id : 'default');
$newMetadatum->set_status('publish');
if(strcmp($type, "Category") === 0){
if(strcmp($type, "Taxonomy") === 0){
$taxonomy_id = $meta->metadata->taxonomy;
$related_taxonomy = $this->get_transient('tax_' . $taxonomy_id . '_id');
@ -432,9 +577,10 @@ class Old_Tainacan extends Importer{
if($newMetadatum->validate()){
$inserted_metadata = $this->metadata_repo->insert( $newMetadatum );
$this->add_transient('metadata_' . $inserted_metadata->get_id() . '_id', $inserted_metadata->get_id());
if(isset( $related_name) ){
$this->add_transient('relation_' . $inserted_metadata->get_id() . '_name', $related_name);
$this->add_transient('relation_' . $meta->id . '_name', $related_name);
}
return $inserted_metadata->get_id();
@ -501,4 +647,57 @@ class Old_Tainacan extends Importer{
return $type;
}
/**
* create attachments, document and thumb from old
*
* @param string $node_old
*
* @return string the class name
*/
private function insert_files( $node_old, $item ){
if( isset( $node_old->attachments ) && $node_old->attachments ){
$TainacanMedia = \Tainacan\Media::get_instance();
$types = ['audio','video','image'];
foreach( $types as $type){
if( isset( $node_old->attachments->$type ) ){
foreach( $node_old->attachments->$type as $attach){
$TainacanMedia->insert_attachment_from_url($attach->url, $item->get_id());
}
}
}
}
if( isset( $node_old->thumbnail ) && $node_old->thumbnail ){
$TainacanMedia = \Tainacan\Media::get_instance();
$id = $TainacanMedia->insert_attachment_from_url( $node_old->thumbnail, $item->get_id());
$item->set__thumbnail_id( $id );
}
if( isset( $node_old->content_tainacan ) && $node_old->content_tainacan ){
$TainacanMedia = \Tainacan\Media::get_instance();
if( isset($node_old->content_tainacan->guid) ){
$id = $TainacanMedia->insert_attachment_from_url( $node_old->content_tainacan->guid, $item->get_id());
if( $id ){
$item->set_document( $id );
$item->set_document_type( 'attachment' );
}
} else if(filter_var($node_old->content_tainacan, FILTER_VALIDATE_URL)){
$id = $TainacanMedia->insert_attachment_from_url( $node_old->content_tainacan, $item->get_id());
if( $id ){
$item->set_document( $id );
$item->set_document_type( 'attachment' );
}
}
}
if( $item->validate() )
$this->items_repo->update($item);
}
}

View File

@ -35,23 +35,29 @@ class Test_Importer extends Importer {
[
'name' => 'Create Taxonomies',
'progress_label' => 'Creating taxonomies',
'callback' => 'create_taxonomies'
],
[
'name' => 'Create Collections',
'progress_label' => 'Creating Collections',
'callback' => 'create_collections'
],
[
'name' => 'Import Items',
'progress_label' => 'Importing items',
'callback' => 'process_collections'
],
[
'name' => 'Post-configure taxonomies',
'progress_label' => 'post processing taxonomies',
'callback' => 'close_taxonomies'
],
[
'name' => 'Finalize',
'callback' => 'finish_processing'
'progress_label' => 'Finalizing',
'callback' => 'finish_processing',
'total' => 5
]
];
@ -196,7 +202,7 @@ class Test_Importer extends Importer {
$this->add_collection([
'id' => $col1->get_id(),
'map' => $col1_map,
'mapping' => $col1_map,
'total_items' => $this->get_col1_number_of_items(),
'source_id' => 'col1'
]);
@ -226,7 +232,7 @@ class Test_Importer extends Importer {
$this->add_collection([
'id' => $col2->get_id(),
'map' => $col2_map,
'mapping' => $col2_map,
'total_items' => $this->get_col2_number_of_items(),
'source_id' => 'col2'
]);

View File

@ -69,8 +69,7 @@ class ScriptTainacanOld {
$old_tainacan = new \Tainacan\Importer\Old_Tainacan();
$id = $old_tainacan->get_id();
$_SESSION['tainacan_importer'][$id]->set_url($url);
$_SESSION['tainacan_importer'][$id]->set_repository();
$_SESSION['tainacan_importer'][$id]->set_url($this->url);
while (!$_SESSION['tainacan_importer'][$id]->is_finished()){
$_SESSION['tainacan_importer'][$id]->run();

View File

@ -25,6 +25,12 @@ export default {
this.updateURLQueries();
});
this.$root.$on('closeAdvancedSearch', () => {
this.$store.dispatch('search/setPage', 1);
this.searchAdvanced({});
});
this.$root.$on('searchAdvanced', advancedSearchQuery => {
this.$store.dispatch('search/setPage', 1);
@ -79,23 +85,23 @@ export default {
let orderBy = this.$userPrefs.get(orderByKey);
if (orderBy) {
if (orderBy.slug == 'creation_date') {
this.$route.query.orderby = 'date';
} else if (orderBy.slug == 'author_name') {
this.$route.query.orderby = 'author_name';
} else if (orderBy.metadata_type_object.primitive_type == 'float' || orderBy.metadata_type_object.primitive_type == 'int') {
this.$route.query.orderby = 'meta_value_num';
this.$route.query.meta_key = orderBy.id;
} else if (orderBy.metadata_type_object.primitive_type == 'date') {
this.$route.query.orderby = 'meta_value';
this.$route.query.meta_key = orderBy.id;
this.$route.query.meta_type = 'DATETIME';
} else if (orderBy.metadata_type_object.core) {
this.$route.query.orderby = orderBy.metadata_type_object.related_mapped_prop;
} else {
this.$route.query.orderby = 'meta_value';
this.$route.query.meta_key = orderBy.id;
}
// if (orderBy.slug == 'creation_date') {
// this.$route.query.orderby = 'date';
// } else if (orderBy.slug == 'author_name') {
// this.$route.query.orderby = 'author_name';
// } else if (orderBy.metadata_type_object.primitive_type == 'float' || orderBy.metadata_type_object.primitive_type == 'int') {
// this.$route.query.orderby = 'meta_value_num';
// this.$route.query.meta_key = orderBy.id;
// } else if (orderBy.metadata_type_object.primitive_type == 'date') {
// this.$route.query.orderby = 'meta_value';
// this.$route.query.meta_key = orderBy.id;
// this.$route.query.meta_type = 'DATETIME';
// } else if (orderBy.metadata_type_object.core) {
// this.$route.query.orderby = orderBy.metadata_type_object.related_mapped_prop;
// } else {
// this.$route.query.orderby = 'meta_value';
// this.$route.query.meta_key = orderBy.id;
// }
} else {
this.$route.query.orderby = 'date';
@ -139,8 +145,8 @@ export default {
}
// Advanced Search
if (this.$route.query.metaquery && this.$route.query.metaquery.advancedSearch){
this.$store.dispatch('search/set_advanced_query', this.$route.query.metaquery);
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);
}
@ -152,7 +158,7 @@ export default {
methods: {
searchAdvanced(data) {
this.$store.dispatch('search/set_advanced_query', data);
this.updateURLQueries(true);
this.updateURLQueries();
},
add_metaquery( data ){
if ( data && data.collection_id ){
@ -265,10 +271,8 @@ export default {
this.$store.dispatch('search/setAdminViewMode', adminViewMode);
this.updateURLQueries();
},
updateURLQueries(isAdvancedSearch) {
updateURLQueries() {
this.$router.push({query: {}});
this.$route.meta['advancedSearch'] = isAdvancedSearch;
this.$router.push({query: this.$store.getters['search/getPostQuery']});
},
updateStoreFromURL() {
@ -293,6 +297,7 @@ export default {
this.$emit( 'hasFiltered', res.hasFiltered);
if(res.advancedSearchResults){
this.$router.push({query: this.$store.getters['search/getPostQuery'],});
this.$emit('advancedSearchResults', res.advancedSearchResults);
}
})

View File

@ -14,35 +14,35 @@ export const fetchItems = ({ rootGetters, dispatch, commit }, { collectionId, is
let hasFiltered = false;
let advancedSearchResults = false;
if (postQueries.metaquery != undefined &&
if ( (postQueries.metaquery != undefined &&
(Object.keys(postQueries.metaquery).length > 0 ||
postQueries.metaquery.length > 0)){
postQueries.metaquery.length > 0)) || (postQueries.taxquery != undefined &&
(Object.keys(postQueries.taxquery).length > 0 ||
postQueries.taxquery.length > 0)) ) {
hasFiltered = true;
if(postQueries.metaquery.advancedSearch){
advancedSearchResults = postQueries.metaquery.advancedSearch;
delete postQueries.metaquery.advancedSearch;
if(postQueries.advancedSearch){
advancedSearchResults = postQueries.advancedSearch;
}
query = qs.stringify(postQueries);
} else {
query = qs.stringify(postQueries);
}
query = qs.stringify(postQueries);
// Garanttees at least empty fetch_only are passed in case none is found
if (qs.stringify(postQueries.fetch_only) == '')
dispatch('search/add_fetchonly', {} , { root: true });
if (qs.stringify(postQueries.fetch_only) == ''){
dispatch('search/add_fetchonly', {}, { root: true });
}
if (qs.stringify(postQueries.fetch_only['meta']) == '')
dispatch('search/add_fetchonly_meta', 0 , { root: true });
if (qs.stringify(postQueries.fetch_only['meta']) == ''){
dispatch('search/add_fetchonly_meta', 0, { root: true });
}
// Differentiates between repository level and collection level queries
let endpoint = '/collection/'+collectionId+'/items?'
let endpoint = '/collection/'+ collectionId +'/items?';
if (collectionId == undefined){
endpoint = '/items?'
endpoint = '/items?';
}
if (!isOnTheme){
@ -54,6 +54,7 @@ export const fetchItems = ({ rootGetters, dispatch, commit }, { collectionId, is
if (postQueries.admin_view_mode != undefined)
postQueries.admin_view_mode = null;
}
axios.tainacan.get(endpoint+query)
.then(res => {
@ -78,8 +79,12 @@ export const fetchItems = ({ rootGetters, dispatch, commit }, { collectionId, is
export const deleteItem = ({ commit }, { itemId, isPermanently }) => {
return new Promise((resolve, reject) => {
let endpoint = '/items/' + itemId;
if (isPermanently)
endpoint = endpoint + '?permanently=1'
if (isPermanently){
endpoint = endpoint + '?permanently=1';
} else {
endpoint = endpoint + '?permanently=0';
}
axios.tainacan.delete(endpoint)
.then( res => {
@ -146,8 +151,11 @@ export const fetchCollectionName = ({ commit }, id) => {
export const deleteCollection = ({ commit }, { collectionId, isPermanently }) => {
return new Promise((resolve, reject) => {
let endpoint = '/collections/' + collectionId;
if (isPermanently)
endpoint = endpoint + '?permanently=true'
if (isPermanently){
endpoint = endpoint +'?permanently=1';
} else {
endpoint = endpoint +'?permanently=0';
}
axios.tainacan.delete(endpoint)
.then(res => {

View File

@ -0,0 +1,148 @@
import axios from '../../../axios/axios';
// IMPORTER ----------------------------------------------------
export const fetchAvailableImporters = ({ commit }) => {
return new Promise((resolve, reject) => {
axios.tainacan.get('importers/available')
.then((res) => {
let availableImporters = res.data;
commit('setAvailableImporters', availableImporters);
resolve (availableImporters);
})
.catch((error) => {
reject(error);
});
});
};
export const fetchImporter = ( { commit } , { importerId }) => {
return new Promise(( resolve, reject ) => {
axios.tainacan.post('importers/session/' + importerId)
.then( res => {
let importer = res.data;
commit('setImporter', importer);
resolve( importer );
})
.catch(error => {
reject( error );
});
});
};
export const sendImporter = ( { commit }, importerTypeSlug) => {
return new Promise(( resolve, reject ) => {
axios.tainacan.post('importers/session/', {
importer_slug: importerTypeSlug
})
.then( res => {
let importer = res.data;
commit('setImporter', importer);
resolve( importer );
})
.catch(error => {
reject( error );
});
});
};
export const updateImporter = ( { commit }, { sessionId, options }) => {
return new Promise(( resolve, reject ) => {
axios.tainacan.put('importers/session/' + sessionId, options)
.then( res => {
let importer = res.data;
commit('setImporter', importer);
resolve( importer );
})
.catch(error => {
reject(error);
});
});
};
export const updateImporterCollection = ( { commit }, { sessionId, collection }) => {
return new Promise(( resolve, reject ) => {
axios.tainacan.put('importers/session/' + sessionId, {
collection: collection
})
.then( res => {
let importer = res.data;
commit('setImporter', importer);
resolve( importer );
})
.catch(error => {
reject(error);
});
});
};
export const updateImporterURL = ( { commit }, { sessionId, url }) => {
return new Promise(( resolve, reject ) => {
axios.tainacan.put('importers/session/' + sessionId, {
url: url
})
.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 ) => {
let formData = new FormData();
formData.append('file', file)
axios.tainacan.post('importers/session/' + sessionId + '/file', formData, {
headers: {
'Content-Type': 'multipart/form-data;',
'Content-Disposition': 'form-data; filename=' + file.name + '; filesize=' + file.size},
})
.then( res => {
let updatedImporter = res.data;
commit('setImporter', updatedImporter);
resolve( updatedImporter );
})
.catch(error => {
reject(error);
});
});
};
export const fetchImporterSourceInfo = ({ commit }, sessionId ) => {
return new Promise((resolve, reject) => {
axios.tainacan.get('/importers/session/' + sessionId + '/source_info')
.then((res) => {
let importerSourceInfo = res.data;
commit('setImporterSourceInfo', importerSourceInfo);
resolve (importerSourceInfo);
})
.catch((error) => {
reject(error);
});
});
};
export const runImporter = ( { commit } , importerId ) => {
return new Promise(( resolve, reject ) => {
axios.tainacan.post('importers/session/' + importerId + '/run')
.then( res => {
let backgroundProcessId = res.data;
// probably send this a dedicated store to background process
//commit('background/addBackgroundProcess', backgroundProcessId);
resolve( backgroundProcessId );
})
.catch(error => {
reject( error );
});
});
};

View File

@ -0,0 +1,15 @@
export const getgetAvailableImporters = state => {
return state.available_importers;
}
export const getImporter = state => {
return state.importer
}
export const getImporterSourceInfo = state => {
return state.importer_source_info;
}
export const getImporterFile = state => {
return state.importer_file;
}

View File

@ -0,0 +1,18 @@
import * as actions from './actions';
import * as getters from './getters';
import * as mutations from './mutations';
const state = {
importer: {},
available_importers: [],
importer_file: {},
importer_source_info: {}
};
export default {
namespaced: true,
state,
mutations,
actions,
getters
}

View File

@ -0,0 +1,17 @@
import Vue from 'vue';
export const setAvailableImporters = (state, availableImporters) => {
state.available_importers = availableImporters;
}
export const setImporter = (state, importer) => {
state.importer = importer
}
export const setImporterFile = (state, importerFile) => {
state.importer_file = importerFile;
}
export const setImporterSourceInfo= (state, importerSourceInfo) => {
state.importer_source_info = importerSourceInfo;
}

View File

@ -135,7 +135,7 @@ export const sendAttachment = ( { commit }, { item_id, file }) => {
commit('cleanAttachment');
return new Promise(( resolve, reject ) => {
axios.wp.post('/media/?post=' + item_id, file, {
headers: { 'Content-Disposition': 'attachment; filename=' + file.name },
headers: { 'Content-Type': 'multipart/form-data;', 'Content-Disposition': 'attachment; filename=' + file.name },
})
.then( res => {
let attachment = res.data;

View File

@ -1,5 +1,4 @@
import axios from '../../../axios/axios';
import qs from 'qs';
export const fetchMetadata = ({commit}, {collectionId, isRepositoryLevel, isContextEdit}) => {
return new Promise((resolve, reject) => {

View File

@ -13,8 +13,9 @@ export const setPostQuery = ( state, postquery ) => {
};
export const setAdvancedSearchQuery = (state, advancedSearchQuery) => {
console.log(advancedSearchQuery);
state.postquery.metaquery = advancedSearchQuery;
state.postquery.advancedSearch = advancedSearchQuery.advancedSearch;
state.postquery.metaquery = advancedSearchQuery.metaquery;
state.postquery.taxquery = advancedSearchQuery.taxquery;
};
export const addMetaQuery = ( state, filter ) => {

View File

@ -1,4 +1,5 @@
import axios from '../../../axios/axios'
import qs from 'qs'
// TAXONOMIES
export const createTaxonomy = ({commit}, taxonomy) => {
@ -24,7 +25,7 @@ export const createTaxonomy = ({commit}, taxonomy) => {
export const deleteTaxonomy = ({ commit }, taxonomyId) => {
return new Promise(( resolve, reject ) => {
axios.tainacan.delete(`/taxonomies/${taxonomyId}?permanently=${true}`)
axios.tainacan.delete(`/taxonomies/${taxonomyId}?permanently=1`)
.then(res => {
commit('deleteTaxonomy', res.data);
@ -138,7 +139,7 @@ export const sendTerm = ({commit}, { taxonomyId, name, description, parent, head
export const deleteTerm = ({ commit }, { taxonomyId, termId }) => {
return new Promise(( resolve, reject ) => {
axios.tainacan.delete(`/taxonomy/${taxonomyId}/terms/${termId}?permanently=${true}`)
axios.tainacan.delete(`/taxonomy/${taxonomyId}/terms/${termId}?permanently=1`)
.then(res => {
let term = res.data;
commit('deleteTerm', termId);
@ -169,9 +170,18 @@ export const updateTerm = ({ commit }, { taxonomyId, termId, name, description,
});
};
export const fetchTerms = ({ commit }, taxonomyId ) => {
export const fetchTerms = ({ commit }, {taxonomyId, fetchOnly, search}) => {
let query = '';
if(fetchOnly && search){
query = `?order=asc&${qs.stringify(fetchOnly)}&${qs.stringify(search)}`;
} else {
query = '?hideempty=0&order=asc';
}
return new Promise((resolve, reject) => {
axios.tainacan.get(`/taxonomy/${taxonomyId}/terms/?hideempty=0&order=asc`)
axios.tainacan.get(`/taxonomy/${taxonomyId}/terms${query}`)
.then(res => {
let terms = res.data;
commit('setTerms', terms);

View File

@ -8,6 +8,7 @@ import filter from './modules/filter/';
import search from './modules/search/';
import taxonomy from './modules/taxonomy/';
import event from './modules/event';
import importer from './modules/importer';
Vue.use(Vuex);
@ -28,5 +29,6 @@ export default new Vuex.Store({
search,
taxonomy,
event,
importer
}
})

View File

@ -563,7 +563,7 @@ msgstr "Aprovado"
#: admin/tainacan-admin-i18n.php:130
#: classes/metadata-types/taxonomy/class-tainacan-taxonomy.php:35
#: classes/metadata-types/relationship/class-tainacan-relationship.php:26
msgid "Collection Related"
msgid "Related Collection"
msgstr "Coleção relacionada"
#: admin/tainacan-admin-i18n.php:131

View File

@ -168,4 +168,45 @@ function tainacan_migrate_post_type_field_to_metadatum(){
}
if (!get_option('tainacan_fix_core_indexes')) {
add_action('init', function() {
global $wpdb;
update_option('tainacan_fix_core_indexes', true);
$collections = \Tainacan\Repositories\Collections::get_instance()->fetch([], 'OBJECT');
foreach ($collections as $collection) {
// get title
$title_meta = $collection->get_core_title_metadatum();
// delete metadata if exists
$wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->postmeta WHERE meta_key = %s", $title_meta->get_id() ));
// create metadata
$wpdb->query( $wpdb->prepare("INSERT INTO $wpdb->postmeta
(post_id,meta_key,meta_value)
SELECT ID, %s, post_title FROM $wpdb->posts WHERE post_type = %s
", $title_meta->get_id(), $collection->get_db_identifier() ));
// get description
$description_meta = $collection->get_core_description_metadatum();
// delete metadata if exists
$wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->postmeta WHERE meta_key = %s", $description_meta->get_id() ));
// create metadata
$wpdb->query( $wpdb->prepare("INSERT INTO $wpdb->postmeta
(post_id,meta_key,meta_value)
SELECT ID, %s, post_content FROM $wpdb->posts WHERE post_type = %s
", $description_meta->get_id(), $collection->get_db_identifier() ));
}
});
}
?>

View File

@ -15,12 +15,25 @@ function tainacan_create_bd_process_db() {
data longtext NOT NULL,
action text NOT NULL,
done boolean not null default 0,
progress_label text,
progress_value int,
PRIMARY KEY (ID),
KEY user_id (user_id),
KEY action (action($max_index_length))
) $charset_collate;\n";
$wpdb->query($query);
$column_exists = $wpdb->get_results( "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = '{$wpdb->prefix}tnc_bg_process' AND column_name = 'progress_label'" );
if(empty($column_exists)) {
$wpdb->query("
ALTER TABLE {$wpdb->prefix}tnc_bg_process
ADD progress_label text,
ADD progress_value int
");
}
}

View File

@ -14,7 +14,7 @@ class TAINACAN_REST_Importers_Controller extends TAINACAN_UnitApiTestCase {
]);
$request = new \WP_REST_Request('POST', $this->namespace . '/importers');
$request = new \WP_REST_Request('POST', $this->namespace . '/importers/session');
$request->set_body($params);
$response = $this->server->dispatch($request);
@ -38,10 +38,18 @@ class TAINACAN_REST_Importers_Controller extends TAINACAN_UnitApiTestCase {
$params = json_encode([
'url' => 'http://test.com',
'options' => ['delimiter' => ';']
'options' => ['delimiter' => ';'],
'collection' => [
'id' => 231,
'map' => [
30 => 'column1',
31 => 'column2'
],
'total_items' => 1234
]
]);
$request = new \WP_REST_Request('PATCH', $this->namespace . '/importers/' . $session_id);
$request = new \WP_REST_Request('PATCH', $this->namespace . '/importers/session/' . $session_id);
$request->set_body($params);
$response = $this->server->dispatch($request);
@ -56,6 +64,8 @@ class TAINACAN_REST_Importers_Controller extends TAINACAN_UnitApiTestCase {
$this->assertEquals($__importer->get_url(), $data['url']);
$this->assertEquals(1234, $__importer->get_collections()[0]['total_items']);
}

View File

@ -207,7 +207,7 @@ class ImporterTests extends TAINACAN_UnitTestCase {
$map[$metadatum->get_id()] = $headers[$index];
}
$collection_definition['map'] = $map;
$collection_definition['mapping'] = $map;
// add the collection
$_SESSION['tainacan_importer'][$id]->add_collection( $collection_definition );