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

This commit is contained in:
weryques 2018-06-19 13:09:19 -03:00
commit b94a39689a
41 changed files with 1661 additions and 234 deletions

View File

@ -12,13 +12,6 @@
<b-field :addons="false">
<label class="section-label">{{ $i18n.get('label_header_image') }}</label>
<div class="header-field">
<a
class="button is-rounred is-secondary"
id="button-edit-header-image"
:aria-label="$i18n.get('label_button_edit_header_image')"
@click="headerImageMediaFrame.openFrame($event)">
<b-icon icon="pencil" />
</a>
<figure class="image">
<span
v-if="collection.header_image == undefined || collection.header_image == false"
@ -29,7 +22,15 @@
</figure>
<div class="header-buttons-row">
<a
id="button-delete"
class="button is-rounded is-secondary"
id="button-edit-header-image"
:aria-label="$i18n.get('label_button_edit_header_image')"
@click="headerImageMediaFrame.openFrame($event)">
<b-icon icon="pencil" />
</a>
<a
class="button is-rounded is-secondary"
id="button-delete-header-image"
:aria-label="$i18n.get('label_button_delete_thumb')"
@click="deleteHeaderImage()">
<b-icon icon="delete" />
@ -45,13 +46,7 @@
<b-field :addons="false">
<label class="section-label">{{ $i18n.get('label_thumbnail') }}</label>
<div class="thumbnail-field">
<a
class="button is-rounred is-secondary"
id="button-edit-thumbnail"
:aria-label="$i18n.get('label_button_edit_thumb')"
@click.prevent="thumbnailMediaFrame.openFrame($event)">
<b-icon icon="pencil" />
</a>
<figure class="image">
<span
v-if="collection.thumbnail.thumb == undefined || collection.thumbnail.thumb == false"
@ -63,7 +58,15 @@
</figure>
<div class="thumbnail-buttons-row">
<a
id="button-delete"
class="button is-rounded is-secondary"
id="button-edit-thumbnail"
:aria-label="$i18n.get('label_button_edit_thumb')"
@click.prevent="thumbnailMediaFrame.openFrame($event)">
<b-icon icon="pencil" />
</a>
<a
class="button is-rounded is-secondary"
id="button-delete-header-image"
:aria-label="$i18n.get('label_button_delete_thumb')"
@click="deleteThumbnail()">
<b-icon icon="delete" />
@ -753,13 +756,16 @@ export default {
line-height: 1.2em;
}
#button-edit-thumbnail, #button-edit-header-image {
#button-edit-thumbnail,
#button-edit-header-image,
#button-delete-thumbnail,
#button-delete-header-image {
border-radius: 100px !important;
height: 40px !important;
width: 40px !important;
bottom: -40px;
z-index: 99;
margin-left: 16px !important;
.icon {
display: inherit;
@ -772,6 +778,21 @@ export default {
img {
padding: 20px;
}
.image-placeholder {
position: relative;
left: 45%;
bottom: -100px;
font-size: 0.8rem;
font-weight: bold;
z-index: 99;
text-align: center;
color: gray;
}
.header-buttons-row {
text-align: right;
top: -42px;
position: relative;
}
}
.thumbnail-field {
max-height: 208px;
@ -790,31 +811,19 @@ export default {
padding: 20px;
}
.image-placeholder {
position: absolute;
margin-left: 10px;
margin-right: 10px;
bottom: 50%;
position: relative;
left: 40px;
bottom: -100px;
font-size: 0.8rem;
font-weight: bold;
z-index: 99;
text-align: center;
color: gray;
}
.thumbnail-buttons-row {
visibility: hidden;
display: inline-block;
position: relative;
top: -20px;
background-color: rgba(255, 255, 255, 0.9);
padding: 2px 8px;
border-radius: 0px 0px 0px 4px;
left: 88px;
}
&:hover {
.thumbnail-buttons-row {
visibility: visible;
}
left: 80px;
bottom: -136px;
}
}
.selected-cover-page {

View File

@ -0,0 +1,237 @@
<template>
<div
class="primary-page page-container">
<tainacan-title />
<form
class="tainacan-form"
label-width="120px"
v-if="importer != undefined && importer != null">
<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
: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>
<!-- 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')"/>
<b-select
id="tainacan-select-target-collection"
v-model="form.collectionId"
: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>
</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 class="columns">
<div class="column">
<ol v-if="importerSourceInfo != undefined">
<li
v-for="(source_metadatum, index) of importerSourceInfo.source_metadata"
:key="index">{{ source_metadatum }}</li>
</ol>
<div v-else>
Upload a source to load metadata.
</div>
</div>
<div class="column">
<div>Select collection to list metadada. (no implemented)</div>
</div>
</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 class="control">
<button
id="button-submit-collection-creation"
@click.prevent="runImporter"
class="button is-success">{{ $i18n.get('run') }}</button>
</div>
</div>
</form>
<b-loading
:active.sync="isLoading"
:can-cancel="false"/>
</div>
</template>
<script>
import { mapActions } from 'vuex';
export default {
name: 'ImporterEditionForm',
data(){
return {
importerId: Number,
importer: null,
isLoading: false,
isFetchingCollections: false,
form: {
collectionId: Number
},
importerTypes: [],
importerType: '',
importerFile: {},
importerSourceInfo: {},
collections: [],
}
},
methods: {
...mapActions('importer', [
'fetchImporterTypes',
'fetchImporter',
'sendImporter',
'updateImporter',
'updateImporterFile',
'fetchImporterSourceInfo',
'runImporter'
]),
...mapActions('collection', [
'fetchCollectionsForParent',
]),
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;
console.log(this.importerSourceInfo);
})
.catch((errors) => {
this.$console.log(errors);
});
})
.catch((errors) => {
this.$console.log(errors);
});
},
runImporter() {
this.runImporter({ sessionId: this.sessionId })
.then(backgroundProcess => {
this.$console.log(backgroundProcess);
})
.catch((errors) => {
this.$console.log(errors);
});
},
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;
});
}
},
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;
}
.drop-inner{
padding: 1rem 3rem;
}
</style>

View File

@ -235,7 +235,7 @@
<div class="section-box section-thumbnail">
<div class="thumbnail-field">
<a
class="button is-rounred is-secondary"
class="button is-rounded is-secondary"
id="button-edit-thumbnail"
:aria-label="$i18n.get('label_button_edit_thumb')"
@click.prevent="thumbnailMediaFrame.openFrame($event)">

View File

@ -12,7 +12,7 @@
:label="$i18n.get('label_header_image')">
<div class="thumbnail-field">
<a
class="button is-rounred is-secondary"
class="button is-rounded is-secondary"
id="button-edit-thumbnail"
:aria-label="$i18n.get('label_button_edit_header_image')"
@click="headerImageMediaFrame.openFrame($event)">

View File

@ -361,7 +361,7 @@ export default {
.selection-control {
padding: 6px 0px 0px 13px;
padding: 6px 0px 0px 12px;
background: white;
height: 40px;

View File

@ -263,7 +263,7 @@
column.metadatum !== 'row_actions' &&
column.metadatum !== 'row_creation' &&
column.metadatum !== 'row_author'"
v-html="renderMetadata(item.metadata, column)"/>
v-html="item.metadata != undefined ? renderMetadata(item.metadata, column) : ''"/>
<span v-if="column.metadatum == 'row_thumbnail'">
<img
@ -472,7 +472,7 @@ export default {
.selection-control {
padding: 6px 0px 0px 13px;
padding: 6px 0px 0px 12px;
background: white;
height: 40px;

View File

@ -269,7 +269,7 @@
.selection-control {
padding: 6px 0px 0px 13px;
padding: 6px 0px 0px 12px;
background: white;
height: 40px;

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]));
}

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

@ -108,8 +108,16 @@ UserPrefsPlugin.install = function (Vue, options = {}) {
'events_per_page': 12,
'order': 'DESC',
'order_by': {
id: 'creation_date',
slug: 'creation_date',
name: 'Creation Date'
},
'view_mode': 'table',
'admin_view_mode': 'table',
'fetch_only': {
0: 'thumbnail',
1: 'creation_date',
2: 'author_name',
meta: []
}
},
init() {
@ -139,7 +147,7 @@ UserPrefsPlugin.install = function (Vue, options = {}) {
if (prefs[key]) {
resolve( prefs[key] );
} else {
reject('Key ' + key + 'does not exists in user preference.');
reject('Key ' + key + ' does not exists in user preference.');
}
})
.catch(error => {
@ -194,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;
@ -262,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

@ -134,11 +134,11 @@
{{ $i18n.get('add_items_external_source') + ' (Not ready)' }}
</b-dropdown-item>
</b-dropdown>
</div>
<!-- Displayed Metadata Dropdown -->
<div
v-if="!isOnTheme || registeredViewModes[viewMode].dynamic_metadata"
v-if="!isOnTheme || (registeredViewModes[viewMode] != undefined && registeredViewModes[viewMode].dynamic_metadata)"
class="search-control-item">
<b-dropdown
ref="displayedMetadataDropdown"
@ -182,6 +182,18 @@
@input="onChangeOrderBy($event)"
:placeholder="$i18n.get('label_sorting')">
<option
v-for="metadatum in tableMetadata"
v-if="
metadatum.slug === 'creation_date' || (
metadatum.metadata_type_object &&
metadatum.metadata_type_object.related_mapped_prop == 'title'
)"
:value="metadatum"
:key="metadatum.slug">
{{ metadatum.name }}
</option>
<!-- Once we have sorting by metadata we can use this -->
<!-- <option
v-for="metadatum in tableMetadata"
v-if="
metadatum.slug === 'creation_date' ||
@ -196,7 +208,7 @@
:value="metadatum"
:key="metadatum.slug">
{{ metadatum.name }}
</option>
</option> -->
</b-select>
<button
:disabled="totalItems <= 0"
@ -242,7 +254,7 @@
class="search-control-item">
<b-field>
<b-dropdown
v-model="adminViewMode"
@change="onChangeAdminViewMode($event)"
:mobile-modal="false"
position="is-bottom-left"
:aria-label="$i18n.get('label_view_mode')">
@ -275,7 +287,6 @@
</div>
</div>
<!-- ADVANCED SEARCH -->
<div
v-if="openAdvancedSearch">
@ -295,7 +306,6 @@
:metadata="metadata" />
</div>
<!-- --------------- -->
<!-- STATUS TABS, only on Admin -------- -->
@ -375,7 +385,7 @@
:displayed-metadata="tableMetadata"
:items="items"
:is-loading="isLoadingItems"
:is="registeredViewModes[viewMode].component"/>
:is="registeredViewModes[viewMode] != undefined ? registeredViewModes[viewMode].component : ''"/>
<!-- Regular -->
<component
@ -388,8 +398,7 @@
:displayed-metadata="tableMetadata"
:items="items"
:is-loading="isLoadingItems"
:is="registeredViewModes[viewMode].component"/>
:is="registeredViewModes[viewMode] != undefined ? registeredViewModes[viewMode].component : ''"/>
<!-- Empty Placeholder (only used in Admin) -->
<section
@ -417,17 +426,16 @@
</section>
<!-- Pagination -->
<!-- When advanced search -->
<pagination
v-if="totalItems > 0 &&
(!isOnTheme || registeredViewModes[viewMode].show_pagination) &&
(!isOnTheme || (registeredViewModes[viewMode] != undefined && registeredViewModes[viewMode].show_pagination)) &&
advancedSearchResults"/>
<!-- Regular -->
<pagination
v-else-if="totalItems > 0 &&
(!isOnTheme || registeredViewModes[viewMode].show_pagination) &&
(!isOnTheme || (registeredViewModes[viewMode] != undefined && registeredViewModes[viewMode].show_pagination)) &&
!openAdvancedSearch"/>
</div>
</div>
@ -460,7 +468,6 @@
isHeaderShrinked: false,
localTableMetadata: [],
registeredViewModes: tainacan_plugin.registered_view_modes,
adminViewMode: 'table',
openAdvancedSearch: false,
advancedSearchResults: false,
}
@ -495,6 +502,9 @@
viewMode() {
return this.getViewMode();
},
adminViewMode() {
return this.getAdminViewMode();
},
orderBy() {
return this.getOrderBy();
},
@ -542,7 +552,8 @@
'getOrderBy',
'getOrder',
'getViewMode',
'getTotalItems'
'getTotalItems',
'getAdminViewMode'
]),
updateSearch() {
this.$eventBusSearch.setSearchQuery(this.futureSearchQuery);
@ -559,6 +570,9 @@
onChangeViewMode(viewMode) {
this.$eventBusSearch.setViewMode(viewMode);
},
onChangeAdminViewMode(adminViewMode) {
this.$eventBusSearch.setAdminViewMode(adminViewMode);
},
onChangeDisplayedMetadata() {
let fetchOnlyMetadatumIds = [];
@ -575,16 +589,19 @@
let creationDateMetadatum = this.localTableMetadata.find(metadatum => metadatum.slug == 'creation_date');
let authorNameMetadatum = this.localTableMetadata.find(metadatum => metadatum.slug == 'author_name');
// Updates Search
this.$eventBusSearch.addFetchOnly({
'0': thumbnailMetadatum.display ? 'thumbnail' : null,
'meta': fetchOnlyMetadatumIds,
'1': creationDateMetadatum.display ? 'creation_date' : null,
'2': authorNameMetadatum.display ? 'author_name': null
});
// Closes dropdown
this.$refs.displayedMetadataDropdown.toggle();
},
prepareMetadataAndFilters() {
this.isLoadingFilters = true;
this.fetchFilters({
@ -597,22 +614,28 @@
.catch(() => this.isLoadingFilters = false);
this.isLoadingMetadata = true;
// Processing is done inside a local variable
let metadata = [];
this.fetchMetadata({
collectionId: this.collectionId,
isRepositoryLevel: this.isRepositoryLevel,
isContextEdit: !this.isOnTheme
isContextEdit: false
})
.then(() => {
// Loads user prefs object as we'll need to check if there's something configured by user
let prefsFetchOnly = !this.isRepositoryLevel ? 'fetch_only_' + this.collectionId : 'fetch_only';
let prefsFetchOnlyObject = this.$userPrefs.get(prefsFetchOnly);
let thumbnailMetadatumDisplay = prefsFetchOnlyObject != undefined ? (prefsFetchOnlyObject['0'] != null) : true;
metadata.push({
name: this.$i18n.get('label_thumbnail'),
metadatum: 'row_thumbnail',
metadata_type: undefined,
slug: 'thumbnail',
id: undefined,
display: true
display: thumbnailMetadatumDisplay
});
let fetchOnlyMetadatumIds = [];
@ -622,11 +645,22 @@
let display;
// Deciding display based on collection settings
if (metadatum.display == 'no')
display = false;
else if (metadatum.display == 'yes')
display = true;
// // Deciding display based on user prefs
// if (prefsFetchOnlyObject != undefined &&
// prefsFetchOnlyObject.meta != undefined) {
// let index = prefsFetchOnlyObject.meta.findIndex(metadatumId => metadatumId == metadatum.id);
// if (index >= 0)
// display = true;
// else
// display = false;
// }
metadata.push(
{
name: metadatum.name,
@ -643,13 +677,16 @@
}
}
let creationDateMetadatumDisplay = prefsFetchOnlyObject != undefined ? (prefsFetchOnlyObject['1'] != null) : true;
let authorNameMetadatumDisplay = prefsFetchOnlyObject != undefined ? (prefsFetchOnlyObject['2'] != null) : true;
metadata.push({
name: this.$i18n.get('label_creation_date'),
metadatum: 'row_creation',
metadata_type: undefined,
slug: 'creation_date',
id: undefined,
display: true
display: creationDateMetadatumDisplay
});
metadata.push({
name: this.$i18n.get('label_created_by'),
@ -657,22 +694,14 @@
metadata_type: undefined,
slug: 'author_name',
id: undefined,
display: true
display: authorNameMetadatumDisplay
});
// this.prefTableMetadata = this.tableMetadata;
// this.$userPrefs.get('table_columns_' + this.collectionId)
// .then((value) => {
// this.prefTableMetadata = value;
// })
// .catch((error) => {
// this.$userPrefs.set('table_columns_' + this.collectionId, this.prefTableMetadata, null);
// });
this.$eventBusSearch.addFetchOnly({
'0': 'thumbnail',
'0': (thumbnailMetadatumDisplay ? 'thumbnail' : null),
'meta': fetchOnlyMetadatumIds,
'1': 'creation_date',
'2': 'author_name'
'1': (creationDateMetadatumDisplay ? 'creation_date' : null),
'2': (authorNameMetadatumDisplay ? 'author_name' : null)
});
this.isLoadingMetadata = false;
this.tableMetadata = metadata;
@ -683,7 +712,7 @@
}
},
created() {
this.isOnTheme = (this.$route.name === null);
this.isRepositoryLevel = (this.collectionId === undefined);
@ -707,7 +736,8 @@
/* This condition is to prevent a incorrect fetch by filter or metadata when we come from items
* at collection level to items page at repository level
*/
if (this.collectionId === to.params.collectionId) {
if (this.isOnTheme || this.collectionId === to.params.collectionId) {
this.prepareMetadataAndFilters();
}
});
@ -717,6 +747,7 @@
if(this.$route.query && this.$route.query.advancedSearch) {
this.openAdvancedSearch = this.$route.query.advancedSearch;
}
},
mounted() {
@ -727,6 +758,22 @@
this.prepareMetadataAndFilters();
this.localTableMetadata = JSON.parse(JSON.stringify(this.tableMetadata));
// Setting initial view mode on Theme
if (this.isOnTheme) {
let prefsViewMode = !this.isRepositoryLevel ? 'view_mode_' + this.collectionId : 'view_mode';
if (this.$userPrefs.get(prefsViewMode) == undefined)
this.$eventBusSearch.setInitialViewMode(this.defaultViewMode);
else
this.$eventBusSearch.setInitialViewMode(this.$userPrefs.get(prefsViewMode));
} else {
let prefsAdminViewMode = !this.isRepositoryLevel ? 'admin_view_mode_' + this.collectionId : 'admin_view_mode';
if (this.$userPrefs.get(prefsAdminViewMode) == undefined)
this.$eventBusSearch.setInitialAdminViewMode('table');
else
this.$eventBusSearch.setInitialAdminViewMode(this.$userPrefs.get(prefsAdminViewMode));
}
// Watch Scroll for shrinking header, only on Admin at collection level
if (!this.isRepositoryLevel && !this.isOnTheme) {
document.getElementById('items-list-area').addEventListener('scroll', ($event) => {
@ -921,8 +968,8 @@
}
.table-container {
padding-left: 8.333333%;
padding-right: 8.333333%;
padding-left: 4.166666667%;
padding-right: 4.166666667%;
min-height: 200px;
//height: calc(100% - 82px);
}

View File

@ -33,7 +33,7 @@
<div>
<taxonomies-list
:is-loading="isLoading"
:total-taxonomies="total"
:total="total"
:page="page"
:taxonomies-per-page="taxonomiesPerPage"
:taxonomies="taxonomies"/>
@ -106,7 +106,7 @@
</template>
<script>
import List from "../../components/lists/taxonomies-list.vue";
import TaxonomiesList from "../../components/lists/taxonomies-list.vue";
import { mapActions, mapGetters } from 'vuex';
//import moment from 'moment'
@ -122,7 +122,7 @@
}
},
components: {
List
TaxonomiesList
},
methods: {
...mapActions('taxonomy', [
@ -184,7 +184,7 @@
this.$userPrefs.set('taxonomies_per_page', 12);
}
this.loadCategories();
this.load();
}
}
</script>

View File

@ -84,4 +84,7 @@
padding: 2px 20px !important;
}
}
.upload-draggable {
border-radius: 0 !important;
}
}

View File

@ -63,10 +63,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

@ -12,19 +12,20 @@ return apply_filters('tainacan-admin-i18n',[
'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' ),
@ -53,6 +54,7 @@ return apply_filters('tainacan-admin-i18n',[
'unified' => __( 'Unified', 'tainacan' ),
'add_another_search_criteria' => __( 'Add another search criteria', 'tainacan' ),
'clear_search' => __( 'Clear search', 'tainacan' ),
'run' => __( 'Run', 'tainacan' ),
// Wordpress Status
'publish' => __( 'Publish', 'tainacan' ),
@ -66,14 +68,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 +89,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' ),
@ -214,6 +218,10 @@ 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_metadata_mapping' => __( 'Metadata mapping', 'tainacan' ),
// Instructions. More complex sentences to guide user and placeholders
'instruction_delete_selected_collections' => __( 'Delete selected collections', 'tainacan' ),
@ -236,15 +244,18 @@ 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' ),
// 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 +271,22 @@ 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' ),
<<<<<<< HEAD
'info_warning_related_collection' => __( 'The metadata Collection related is required', 'tainacan' ),
'info_warning_no_metadata_found' => __( 'No metadata found in this collection', 'tainacan' ),
=======
'info_warning_collection_related' => __( 'The metadata Collection related is required', 'tainacan' ),
'info_warning_no_metadata_found' => __( 'No metadata found in this collection', 'tainacan' ),
>>>>>>> d461f05933bd727ee4c1ff0d8b2fc9dfd272bdaa
'info_showing_items' => __( 'Showing items ', 'tainacan' ),
'info_showing_collections' => __( 'Showing collections ', 'tainacan' ),
'info_showing_taxonomies' => __( 'Showing taxonomies ', 'tainacan' ),
@ -282,7 +298,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 +307,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 +319,10 @@ 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' ),
// Tainacan Metadatum Types
'tainacan-text' => __( 'Text', 'tainacan' ),
'tainacan-textarea' => __( 'Text area', 'tainacan' ),

View File

@ -9,6 +9,9 @@
<script>
export default {
name: "ThemeItemsList",
created() {
this.$userPrefs.init();
}
}
</script>
@ -298,11 +301,6 @@ export default {
border-bottom: 0;
}
.table-container {
padding-left: 4.166666667%;
padding-right: 4.166666667%;
}
#items-list-area {
width: 100%;
overflow-y: unset;

View File

@ -0,0 +1,306 @@
<?php
namespace Tainacan\API\EndPoints;
use \Tainacan\API\REST_Controller;
use Tainacan\Repositories;
use Tainacan\Entities;
/**
* Represents the Importers REST Controller
*
* */
class REST_Importers_Controller extends REST_Controller {
private $collections_repository;
private $collection;
/**
* REST_Importers_Controller constructor.
* Define the namespace, rest base and instantiate your attributes.
*/
public function __construct(){
$this->rest_base = 'importers';
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
parent::__construct();
}
/**
* Register the collections route and their endpoints
*/
public function register_routes(){
register_rest_route($this->namespace, '/' . $this->rest_base . '/session', array(
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array($this, 'create_item'),
'permission_callback' => array($this, 'import_permissions_check'),
'args' => [
'importer_slug' => [
'type' => 'string',
'description' => __( 'The slug of the importer to be initialized', 'tainacan' ),
]
],
),
));
register_rest_route($this->namespace, '/' . $this->rest_base . '/session/(?P<session_id>[0-9a-f]+)', array(
array(
'methods' => \WP_REST_Server::EDITABLE,
'callback' => array($this, 'update_item'),
'permission_callback' => array($this, 'import_permissions_check'),
'args' => [
'url' => [
'type' => 'string',
'description' => __( 'The URL to be used by the importer', 'tainacan' ),
],
'collection' => [
'type' => 'array',
'description' => __( 'The array describing the destination collectino as expected by the importer', 'tainacan' ),
],
'options' => [
'type' => 'array',
'description' => __( 'The importer options', 'tainacan' ),
]
],
),
));
register_rest_route($this->namespace, '/' . $this->rest_base . '/session/(?P<session_id>[0-9a-f]+)/file', array(
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array($this, 'add_file'),
'permission_callback' => array($this, 'import_permissions_check'),
),
));
register_rest_route($this->namespace, '/' . $this->rest_base . '/session/(?P<session_id>[0-9a-f]+)/source_info', array(
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array($this, 'source_info'),
'permission_callback' => array($this, 'import_permissions_check'),
),
));
register_rest_route($this->namespace, '/' . $this->rest_base . '/session/(?P<session_id>[0-9a-f]+)/run', array(
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array($this, 'run'),
'permission_callback' => array($this, 'import_permissions_check'),
),
));
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'),
),
));
}
/**
*
* @param \WP_REST_Request $request
*
* @return bool|\WP_Error
* @throws \Exception
*/
public function import_permissions_check($request){
// TODO
return true;
}
/**
* Creates a new instance of the desired importer and returns its ID
*
* @param \WP_REST_Request $request
*
* @return array|\WP_Error|\WP_REST_Response
*/
public function create_item( $request ) {
$body = json_decode($request->get_body(), true);
if(empty($body)){
return new \WP_REST_Response([
'error_message' => __('Body can not be empty.', 'tainacan'),
], 400);
}
$slug = $body['importer_slug'];
global $Tainacan_Importer_Handler;
if ($object = $Tainacan_Importer_Handler->initialize_importer($slug)) {
$response = $object->_to_Array();
return new \WP_REST_Response($response, 201);
} else {
return new \WP_REST_Response([
'error_message' => __('Importer not found', 'tainacan'),
], 400);
}
}
/**
* Update a collection
*
* @param \WP_REST_Request $request
*
* @return string|\WP_Error|\WP_REST_Response
*/
public function update_item( $request ) {
$session_id = $request['session_id'];
$body = json_decode($request->get_body(), true);
if(!empty($body)){
$attributes = [];
foreach ($body as $att => $value){
$attributes[$att] = $value;
}
$importer = $_SESSION['tainacan_importer'][$session_id];
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);
}
}
$response = $importer->_to_Array();
return new \WP_REST_Response( $response, 200 );
}
return new \WP_REST_Response([
'error_message' => __('Importer Session not found', 'tainacan' ),
'session_id' => $session_id
], 400);
}
return new \WP_REST_Response([
'error_message' => __('The body can not be empty', 'tainacan'),
'body' => $body
], 400);
}
public function source_info( $request ) {
$session_id = $request['session_id'];
$importer = $_SESSION['tainacan_importer'][$session_id];
if(!$importer) {
return new \WP_REST_Response([
'error_message' => __('Importer Session not found', 'tainacan' ),
'session_id' => $session_id
], 400);
}
$response = [
'source_metadata' => false,
'source_total_items' => false
];
if ( method_exists($importer, 'get_source_metadata') ) {
$response['source_metadata'] = $importer->get_source_metadata();
}
if ( method_exists($importer, 'get_source_number_of_items') ) {
$response['source_total_items'] = $importer->get_source_number_of_items();
}
return new \WP_REST_Response( $response, 200 );
}
public function add_file( $request ) {
$session_id = $request['session_id'];
$importer = $_SESSION['tainacan_importer'][$session_id];
if(!$importer) {
return new \WP_REST_Response([
'error_message' => __('Importer Session not found', 'tainacan' ),
'session_id' => $session_id
], 400);
}
$files = $request->get_file_params();
$headers = $request->get_headers();
if ( $importer->add_file($files['file']) ) {
$response = $importer->_to_Array();
return new \WP_REST_Response( $response, 200 );
} else {
return new \WP_REST_Response([
'error_message' => __('Failed to upload file', 'tainacan' ),
'session_id' => $session_id
], 400);
}
}
public function run() {
$session_id = $request['session_id'];
$importer = $_SESSION['tainacan_importer'][$session_id];
if(!$importer) {
return new \WP_REST_Response([
'error_message' => __('Importer Session not found', 'tainacan' ),
'session_id' => $session_id
], 400);
}
global $Tainacan_Importer_Handler;
$process = $Tainacan_Importer_Handler->add_to_queue($importer);
$response = [
'bg_process_id' => $process->get_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

@ -13,6 +13,7 @@ $rest_item_metadata_controller = new \Tainacan\API\EndPoints\REST_Item_Metadat
$rest_logs_controller = new \Tainacan\API\EndPoints\REST_Logs_Controller();
$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();
new \Tainacan\API\EndPoints\REST_Export_Controller();
new \Tainacan\API\EndPoints\REST_Metadatum_Mappers_Controller();
// Add here other endpoints imports

View File

@ -31,6 +31,12 @@ abstract class Background_Process extends \WP_Background_Process {
* @var string
*/
protected $table = '';
/**
* ID of the process in the database
* @var false|int
*/
protected $ID = false;
/**
* Prefix
@ -60,6 +66,10 @@ abstract class Background_Process extends \WP_Background_Process {
global $wpdb;
$this->table = $wpdb->prefix . 'tnc_bg_process';
}
public function get_id() {
return $this->ID;
}
/**
@ -81,6 +91,7 @@ abstract class Background_Process extends \WP_Background_Process {
'queued_on' => date('Y-m-d H:i:s')
]
);
$this->ID = $wpdb->insert_id;
}
return $this;

View File

@ -79,7 +79,8 @@ class Taxonomy extends Entity {
);
$tax_cpts = [];
$tax_cpts = [];
if (is_array($this->get_collections())){
foreach ($this->get_collections() as $tax_col){
$tax_cpts[] = $tax_col->get_db_identifier();

View File

@ -55,18 +55,20 @@ class CSV extends Importer {
$processedItem[ $header ] = $values[ $index ];
}
$this->set_progress_current($index+1);
return $processedItem;
}
/**
* @inheritdoc
*/
public function get_progress_total_from_source(){
$file = new \SplFileObject( $this->tmp_file, 'r' );
$file->seek(PHP_INT_MAX);
// -1 removing header
return $this->total_items = $file->key() - 1;
public function get_source_number_of_items(){
if (isset($this->tmp_file) && file_exists($this->tmp_file)) {
$file = new \SplFileObject( $this->tmp_file, 'r' );
$file->seek(PHP_INT_MAX);
// -1 removing header
return $this->total_items = $file->key() - 1;
}
return false;
}
}

View File

@ -4,17 +4,70 @@ namespace Tainacan;
class Importer_Handler {
private $registered_importers = [];
function __construct() {
$this->bg_importer = new Background_Importer();
add_action('init', array(&$this, 'init'));
}
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'
]);
do_action('tainacan_register_importers');
}
function add_to_queue($importer_object) {
$data = $importer_object->_to_Array();
$this->bg_importer->data($data)->save()->dispatch();
function add_to_queue(\Tainacan\Importer\Importer $importer_object) {
$data = $importer_object->_to_Array(true);
$importer_object = $this->bg_importer->data($data)->save()->dispatch();
return $importer_object;
}
/**
* Register Importer
*
* @param array $importer
* [
* 'slug' => 'example-importer',
* 'class_name' => '\Tainacan\Importer\Test_Importer'
* ]
*/
public function register_importer(array $importer) {
$this->registered_importers[$importer['slug']] = $importer;
}
public function unregister_importer($importer_slug) {
unset($this->registered_importers[$importer_slug]);
}
public function get_registered_importers() {
return $this->registered_importers;
}
public function get_importer($importer_slug) {
$importers = $this->get_registered_importers();
if (isset($importers[$importer_slug])) {
return $importers[$importer_slug];
}
return null;
}
public function initialize_importer($importer_slug) {
$importer = $this->get_importer($importer_slug);
if ( is_array($importer) && isset($importer['class_name']) && class_exists($importer['class_name']) ) {
return new $importer['class_name']();
}
return false;
}

View File

@ -47,17 +47,6 @@ abstract class Importer {
protected $manual_collection = true;
/**
* The total number of iterations to be imported.
*
* if not possible to calculate, inform 0 (zero) and no progress bar will be displayed.
*
* @var int
*/
protected $progress_total;
protected $progress_current;
/**
* This array holds the structure that the default step 'process_collections' will handle.
*
@ -100,7 +89,7 @@ abstract class Importer {
*/
protected $default_options = [];
private $accpets = [
private $accepts = [
'file' => true,
'url' => false,
];
@ -190,13 +179,20 @@ abstract class Importer {
}
public function _to_Array() {
$return = [];
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;
}
@ -279,14 +275,6 @@ abstract class Importer {
$this->tmp_file = $filepath;
}
public function get_progress_current() {
return $this->progress_current;
}
public function set_progress_current($value) {
$this->progress_current = $value;
}
public function get_collections() {
return $this->collections;
}
@ -332,22 +320,6 @@ abstract class Importer {
return $this->steps;
}
/**
* return the total progress number to calculate progress
*
* @return int Total of items
*/
public function get_progress_total() {
if ( !isset( $this->progress_total ) ) {
if ( method_exists($this, 'get_progress_total_from_source') ) {
$this->progress_total = $this->get_progress_total_from_source();
} else {
$this->progress_total = 0;
}
}
return $this->progress_total;
}
private function get_transients() {
return $this->transients;
@ -376,7 +348,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;
}
@ -418,12 +391,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 );
}
/**
@ -464,8 +444,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;
@ -480,8 +460,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;
@ -565,13 +545,13 @@ abstract class Importer {
/**
* Method implemented by the child importer class to return the total number of interations the importer must run
* Method implemented by the child importer class to return the total number of items that will be imported
*
* Used to build the progress bar
*
* @return int
*/
public function get_progress_total_from_source() {}
public function get_source_number_of_items() {}

View File

@ -22,13 +22,13 @@ class Old_Tainacan extends Importer{
'name' => 'Create Collections',
'callback' => 'create_collections'
],
[
'name' => 'Link relationship metadata',
'callback' => 'link_relationships'
],
[
'name' => 'Import Items',
'callback' => 'process_collections'
],
[
'name' => 'Link Relationships',
'callback' => 'link_relationships'
],
[
'name' => 'Finalize',
@ -51,6 +51,7 @@ class Old_Tainacan extends Importer{
$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');
@ -124,7 +125,7 @@ class Old_Tainacan extends Importer{
if ( isset($collection->post_title) && $collection->post_status === 'publish') {
$collection_id = $this->create_collection( $collection );
foreach( $this->get_collection_metadata( $collection_id ) as $metadatum_old ) {
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;
@ -134,8 +135,9 @@ class Old_Tainacan extends Importer{
$this->add_collection([
'id' => $collection_id,
'map' => $map,
'total_items' => $this->get_total_items_from_source( $collection_id ),
'source_id' => $collection->ID
'total_items' => $this->get_total_items_from_source( $collection->ID ),
'source_id' => $collection->ID,
'items' => $this->get_all_items( $collection->ID )
]);
}
@ -143,20 +145,19 @@ 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 = [];
$args['meta_query'] = [ 'relation' => 'OR' ];
$collections = $this->col_repo->fetch([], 'OBJECT');
$args['meta_query'][] = array(
'key' => 'metadata_type',
'value' => 'Tainacan\Metadata_Types\\Relationship',
'compare' => 'IN',
);
if( $collections && is_array( $collections ) ){
$this->metadata_repo->fetch($args, 'OBJECT' );
foreach( $collections as $collection ){
$map = $this->get_transient('collection_' . $collection->get_id() . '_relationships');
var_dump($map);
}
}
// TODO: get all imported relationships and find the collection target
}
@ -166,6 +167,119 @@ class Old_Tainacan extends Importer{
* @return int
*/
public function process_item( $index, $collection_id ){
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_title( $item_Old->post_title );
$item->set_description( $item_Old->post_content_filtered );
$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 );
}
} 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;
}
}
/**
* 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['map']) ){
$new_tainacanid = array_search($metadatum->id,$collection_id['map']);
$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 );
// TODO: verify why taxonomies is not saving
} else {
$this->add_error_log( 'Error inserting item' );
$this->add_error_log( $item->get_errors() );
return false;
}
}
}
$this->add_transient('collection_' . $collection_id['id'] . '_relationships', $relationships ); // add reference for relations
}
/**
@ -173,7 +287,20 @@ 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());
$this->add_error_log('Error in fetch remote total items');
$this->abort();
return false;
}
$info = json_decode($info['body']);
if( isset($info->found_items) ){
@ -185,19 +312,43 @@ class Old_Tainacan extends Importer{
}
/**
* Method implemented by the child importer class to return the number of items to be imported
* Method that retrieves all items
* @return int
*/
public function get_progress_total_from_source(){
public function get_all_items( $collection_id ) {
$page = 1;
$items = [];
$args = array(
'timeout' => 30,
'redirection' => 30,
);
$info = wp_remote_get( $this->get_url() . $this->tainacan_api_address . "/collections/".$collection_id."/items?includeMetadata=1&filter[page]=" . $page, $args );
if( !isset($info['body']) ){
$this->add_error_log($result->get_error_message());
$this->add_error_log('Error in fetch remote first page item');
$this->abort();
return false;
}
$info = json_decode($info['body']);
while( isset($info->items) && count( $info->items ) > 0 ){
foreach( $info->items as $item){
$items[] = $item;
}
$page++;
$info = wp_remote_get( $this->get_url() . $this->tainacan_api_address . "/collections/".$collection_id."/items?includeMetadata=1&filter[page]=" . $page, $args );
$info = json_decode($info['body']);
}
return $items;
}
/**
* Method implemented by the child importer class to return the number of items to be imported
* @return int
*/
public function get_source_metadata(){
}
// AUX functions
@ -276,8 +427,8 @@ class Old_Tainacan extends Importer{
if($collection_tabs){
foreach ($collection_tabs as $tab) {
if($tab->properties){
$metadata = array_merge($metadata, $tab->properties);
if($tab->{'tab-properties'}){
$metadata = array_merge($metadata, $tab->{'tab-properties'});
}
}
@ -344,9 +495,9 @@ class Old_Tainacan extends Importer{
$newMetadatum->set_name($name);
$newMetadatum->set_metadata_type('Tainacan\Metadata_Types\\'.$type);
$newMetadatum->set_parent( (isset($collection_id)) ? $collection_id : 'default');
$newMetadatum->set_collection_id( (isset($collection_id)) ? $collection_id : 'default');
if(strcmp($type, "Category") === 0){
if(strcmp($type, "Taxonomy") === 0){
$taxonomy_id = $meta->metadata->taxonomy;
$related_taxonomy = $this->get_transient('tax_' . $taxonomy_id . '_id');
@ -362,7 +513,6 @@ class Old_Tainacan extends Importer{
if(isset($related_taxonomy)){
$newMetadatum->set_metadata_type_options(['collection_id' => $related_taxonomy]);
}
} else if(strcmp($type, "Compound") === 0){
if( isset( $meta->metadata->children ) ){
@ -394,9 +544,11 @@ 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);
if(isset( $related_name) ){
$this->add_transient('relation_' . $meta->id . '_name', $related_name);
}
return $inserted_metadata->get_id();
} else{

View File

@ -36,10 +36,14 @@ export default {
watch: {
'$route' (to, from) {
this.collectionId = !this.$route.params.collectionId ? this.$route.params.collectionId : parseInt(this.$route.params.collectionId);
// Should set Collection ID from URL only when in admin.
if (this.$route.name == 'CollectionItemsPage' || this.$route.name == 'ItemsPage')
this.collectionId = !this.$route.params.collectionId ? this.$route.params.collectionId : parseInt(this.$route.params.collectionId);
// Fills the URL with apropriate default values in case a query is not passed
if (this.$route.name == null || this.$route.name == undefined || this.$route.name == 'CollectionItemsPage' || this.$route.name == 'ItemsPage') {
// Items Per Page
if (this.$route.query.perpage == undefined || to.params.collectionId != from.params.collectionId) {
let perPageKey = (this.collectionId != undefined ? 'items_per_page_' + this.collectionId : 'items_per_page');
let perPageValue = this.$userPrefs.get(perPageKey);
@ -51,10 +55,25 @@ export default {
this.$userPrefs.set(perPageKey, 12);
}
}
// Page
if (this.$route.query.paged == undefined || to.params.collectionId != from.params.collectionId)
this.$route.query.paged = 1;
if (this.$route.query.order == undefined || to.params.collectionId != from.params.collectionId)
this.$route.query.order = 'DESC';
// Order (ASC, DESC)
if (this.$route.query.order == undefined || to.params.collectionId != from.params.collectionId) {
let orderKey = (this.collectionId != undefined ? 'order_' + this.collectionId : 'order');
let orderValue = this.$userPrefs.get(orderKey);
if (orderValue)
this.$route.query.order = orderValue;
else {
this.$route.query.order = 'DESC';
this.$userPrefs.set(orderKey, 'DESC');
}
}
// Order By (required extra work to deal with custom metadata ordering)
if (this.$route.query.orderby == undefined || to.params.collectionId != from.params.collectionId) {
let orderByKey = (this.collectionId != undefined ? 'order_by_' + this.collectionId : 'order_by');
let orderBy = this.$userPrefs.get(orderByKey);
@ -81,13 +100,46 @@ export default {
} else {
this.$route.query.orderby = 'date';
this.$userPrefs.set(orderByKey, {
id: 'creation_date',
slug: 'creation_date',
name: this.$i18n.get('label_creation_date')
});
}).catch(() => { });
}
}
if(this.$route.query && this.$route.query.advancedSearch){
// Theme View Modes
if ((this.$route.name == null || this.$route.name == undefined ) &&
this.$route.name != 'CollectionItemsPage' && this.$route.name != 'ItemsPage' &&
(this.$route.query.view_mode == undefined || to.params.collectionId != from.params.collectionId)
) {
let viewModeKey = (this.collectionId != undefined ? 'view_mode_' + this.collectionId : 'view_mode');
let viewModeValue = this.$userPrefs.get(viewModeKey);
if (viewModeValue)
this.$route.query.view_mode = viewModeValue;
else {
this.$route.query.view_mode = 'table';
this.$userPrefs.set(viewModeKey, 'table');
}
}
// Admin View Modes
if (this.$route.name != null && this.$route.name != undefined &&
(this.$route.name == 'CollectionItemsPage' || this.$route.name == 'ItemsPage') &&
(this.$route.query.admin_view_mode == undefined || to.params.collectionId != from.params.collectionId)
) {
let adminViewModeKey = (this.collectionId != undefined ? 'admin_view_mode_' + this.collectionId : 'admin_view_mode');
let adminViewModeValue = this.$userPrefs.get(adminViewModeKey);
if (adminViewModeValue)
this.$route.query.admin_view_mode = adminViewModeValue;
else {
this.$route.query.admin_view_mode = 'table';
this.$userPrefs.set(adminViewModeKey, 'table');
}
}
// Advanced Search
if (this.$route.query && this.$route.query.advancedSearch){
this.$store.dispatch('search/set_advanced_query', this.$route.query);
} else {
this.$store.dispatch('search/set_postquery', this.$route.query);
@ -117,8 +169,14 @@ export default {
this.updateURLQueries();
},
addFetchOnly( metadatum ){
let prefsFetchOnly = this.collectionId != undefined ? 'fetch_only_' + this.collectionId : 'fetch_only';
if(this.$userPrefs.get(prefsFetchOnly) != metadatum) {
this.$userPrefs.set(prefsFetchOnly, metadatum)
.catch(() => {});
}
this.$store.dispatch('search/add_fetchonly', metadatum );
this.updateURLQueries();
this.updateURLQueries();
},
removeFetchOnlyMeta( metadatum ){
this.$store.dispatch('search/remove_fetchonly_meta', metadatum );
@ -144,22 +202,31 @@ export default {
},
setItemsPerPage(itemsPerPage) {
let prefsPerPage = this.collectionId != undefined ? 'items_per_page_' + this.collectionId : 'items_per_page';
this.$userPrefs.set(prefsPerPage, itemsPerPage)
.catch(() => { this.$console.log("Error settings user prefs for items per page.") });
if(this.$userPrefs.get(prefsPerPage) != itemsPerPage) {
this.$userPrefs.set(prefsPerPage, itemsPerPage)
.catch(() => {});
}
this.$store.dispatch('search/setItemsPerPage', itemsPerPage);
this.updateURLQueries();
},
setOrderBy(newOrderBy) {
setOrderBy(orderBy) {
let prefsOrderBy = this.collectionId != undefined ? 'order_by_' + this.collectionId : 'order_by';
this.$userPrefs.set(prefsOrderBy, newOrderBy)
.catch(() => { this.$console.log("Error settings user prefs for order by.") });
this.$store.dispatch('search/setOrderBy', newOrderBy);
if(this.$userPrefs.get(prefsOrderBy) != orderBy) {
this.$userPrefs.set(prefsOrderBy, orderBy)
.catch(() => {});
}
this.$store.dispatch('search/setOrderBy', orderBy);
this.updateURLQueries();
},
setOrder(newOrder) {
this.$store.dispatch('search/setOrder', newOrder);
setOrder(order) {
let prefsOrder = this.collectionId != undefined ? 'order_' + this.collectionId : 'order';
if(this.$userPrefs.get(prefsOrder) != order) {
this.$userPrefs.set(prefsOrder, order)
.catch(() => {});
}
this.$store.dispatch('search/setOrder', order);
this.updateURLQueries();
},
setStatus(status) {
@ -171,9 +238,33 @@ export default {
this.updateURLQueries();
},
setViewMode(viewMode) {
let prefsViewMode = this.collectionId != undefined ? 'view_mode_' + this.collectionId : 'view_mode';
if(this.$userPrefs.get(prefsViewMode) != viewMode) {
this.$userPrefs.set(prefsViewMode, viewMode)
.catch(() => {});
}
this.$store.dispatch('search/setViewMode', viewMode);
this.updateURLQueries();
},
setAdminViewMode(adminViewMode) {
let prefsAdminViewMode = this.collectionId != undefined ? 'admin_view_mode_' + this.collectionId : 'admin_view_mode';
if(this.$userPrefs.get(prefsAdminViewMode) != adminViewMode) {
this.$userPrefs.set(prefsAdminViewMode, adminViewMode)
.catch(() => { });
}
this.$store.dispatch('search/setAdminViewMode', adminViewMode);
this.updateURLQueries();
},
setInitialViewMode(viewMode) {
this.$store.dispatch('search/setViewMode', viewMode);
this.updateURLQueries();
},
setInitialAdminViewMode(adminViewMode) {
this.$store.dispatch('search/setAdminViewMode', adminViewMode);
this.updateURLQueries();
},
updateURLQueries() {
this.$router.push({query: {}});
this.$router.push({query: this.$store.getters['search/getPostQuery']});
@ -182,11 +273,12 @@ export default {
this.$store.dispatch('search/set_postquery', this.$route.query);
},
loadItems(to) {
// Forces fetch_only to be filled before any search happens
if (this.$store.getters['search/getFetchOnly'] == undefined) {
this.$emit( 'hasToPrepareMetadataAndFilters', to);
} else {
this.$emit( 'isLoadingItems', true);
this.$store.dispatch('collection/fetchItems', {
@ -194,6 +286,7 @@ export default {
'isOnTheme': (this.$route.name == null)
})
.then((res) => {
this.$emit( 'isLoadingItems', false);
this.$emit( 'hasFiltered', res.hasFiltered);

View File

@ -46,15 +46,21 @@ export const fetchItems = ({ rootGetters, dispatch, commit }, { collectionId, is
}
if (!isOnTheme){
endpoint = endpoint + 'context=edit&';
}
if (postQueries.view_mode != undefined)
postQueries.view_mode = null;
endpoint = endpoint + 'context=edit&'
} else {
if (postQueries.admin_view_mode != undefined)
postQueries.admin_view_mode = null;
}
axios.tainacan.get(endpoint+query)
.then(res => {
let items = res.data;
let viewModeObject = tainacan_plugin.registered_view_modes[postQueries.view_mode];
if (isOnTheme && viewModeObject != undefined && viewModeObject.type == 'template') {
commit('setItemsListTemplate', items);
resolve({'itemsListTemplate': items, 'total': res.headers['x-wp-total'], hasFiltered: hasFiltered, advancedSearchResults: advancedSearchResults});

View File

@ -0,0 +1,116 @@
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 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

@ -106,4 +106,9 @@ export const setSearchQuery = ({ commit }, searchQuery ) => {
// Set ViewMode (view_mode)
export const setViewMode = ({ commit }, viewMode ) => {
commit('setViewMode', viewMode );
};
// Set AdminViewMode (admin_view_mode)
export const setAdminViewMode = ({ commit }, adminViewMode ) => {
commit('setAdminViewMode', adminViewMode );
};

View File

@ -52,6 +52,9 @@ export const getViewMode = state => {
return state.postquery.view_mode;
};
export const getAdminViewMode = state => {
return state.postquery.admin_view_mode;
};
export const getFetchOnly = state => {
return state.postquery.fetch_only;
};

View File

@ -19,7 +19,8 @@ const state = {
'1': 'creation_date',
'2': 'author_name'
},
view_mode: 'table'
view_mode: 'table',
admin_view_mode: 'table'
},
totalItems: 0
};

View File

@ -128,4 +128,8 @@ export const setStatus = ( state, status ) => {
export const setViewMode = ( state, viewMode ) => {
state.postquery.view_mode = viewMode;
};
export const setAdminViewMode = ( state, adminViewMode ) => {
state.postquery.admin_view_mode = adminViewMode;
};

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

@ -36,8 +36,6 @@
v-for="(column, index) in displayedMetadata"
v-if="column.display"
:label="column.name"
:aria-label="(column.metadatum != 'row_thumbnail' && column.metadatum != 'row_creation' && column.metadatum != 'row_author')
? column.name + '' + (item.metadata ? item.metadata[column.slug].value_as_string : '') : ''"
class="column-default-width"
:class="{
'thumbnail-cell': column.metadatum == 'row_thumbnail',

View File

@ -0,0 +1,75 @@
<?php
namespace Tainacan\Tests;
/**
* @group api
*/
class TAINACAN_REST_Importers_Controller extends TAINACAN_UnitApiTestCase {
public function test_create(){
$params = json_encode([
'importer_slug' => 'csv'
]);
$request = new \WP_REST_Request('POST', $this->namespace . '/importers/session');
$request->set_body($params);
$response = $this->server->dispatch($request);
$this->assertEquals(201, $response->get_status());
$data = $response->get_data();
$this->assertTrue( isset($data['id']) );
$this->assertTrue( is_string($data['id']) );
}
public function test_update() {
$importer = new \Tainacan\Importer\CSV();
$session_id = $importer->get_id();
$params = json_encode([
'url' => 'http://test.com',
'options' => ['delimiter' => ';'],
'collection' => [
'id' => 231,
'map' => [
30 => 'column1',
31 => 'column2'
],
'total_items' => 1234
]
]);
$request = new \WP_REST_Request('PATCH', $this->namespace . '/importers/session/' . $session_id);
$request->set_body($params);
$response = $this->server->dispatch($request);
$data = $response->get_data();
$this->assertEquals(200, $response->get_status());
$__importer = $_SESSION['tainacan_importer'][$session_id];
$this->assertEquals('http://test.com', $__importer->get_url());
$this->assertEquals(';', $__importer->get_option('delimiter'));
$this->assertEquals($__importer->get_url(), $data['url']);
$this->assertEquals(1234, $__importer->get_collections()[0]['total_items']);
}
}
?>

View File

@ -178,6 +178,159 @@ class TAINACAN_REST_Items_Controller extends TAINACAN_UnitApiTestCase {
$this->assertNotEquals($item->get_title(), $data['title']);
$this->assertEquals('SCRUM e XP', $data['title']);
}
function test_fetch_only() {
$collection = $this->tainacan_entity_factory->create_entity(
'collection',
array(
'name' => 'Agile',
'description' => 'Agile methods',
'status' => 'publish'
),
true
);
$private_meta = $this->tainacan_entity_factory->create_entity(
'metadatum',
array(
'name' => 'private_meta',
'status' => 'publish',
'collection' => $collection,
'metadata_type' => 'Tainacan\Metadata_Types\Text',
'status' => 'private'
),
true
);
$public_meta = $this->tainacan_entity_factory->create_entity(
'metadatum',
array(
'name' => 'public_meta',
'status' => 'publish',
'collection' => $collection,
'metadata_type' => 'Tainacan\Metadata_Types\Text',
'status' => 'publish'
),
true
);
$discarded = $this->tainacan_entity_factory->create_entity(
'metadatum',
array(
'name' => 'discarded',
'status' => 'publish',
'collection' => $collection,
'metadata_type' => 'Tainacan\Metadata_Types\Text',
'status' => 'publish'
),
true
);
$item1 = $this->tainacan_entity_factory->create_entity(
'item',
array(
'title' => 'Lean Startup',
'description' => 'Um processo ágil de criação de novos negócios.',
'collection' => $collection,
'status' => 'publish'
),
true
);
$item2 = $this->tainacan_entity_factory->create_entity(
'item',
array(
'title' => 'SCRUM',
'description' => 'Um framework ágil para gerenciamento de tarefas.',
'collection' => $collection,
'status' => 'publish'
),
true
);
$itemMetaRepo = \Tainacan\Repositories\Item_Metadata::get_instance();
$newMeta = new \Tainacan\Entities\Item_Metadata_Entity($item1, $public_meta);
$newMeta->set_value('test');
$newMeta->validate();
$itemMetaRepo->insert($newMeta);
$newMeta = new \Tainacan\Entities\Item_Metadata_Entity($item1, $private_meta);
$newMeta->set_value('test');
$newMeta->validate();
$itemMetaRepo->insert($newMeta);
$newMeta = new \Tainacan\Entities\Item_Metadata_Entity($item1, $discarded);
$newMeta->set_value('test');
$newMeta->validate();
$itemMetaRepo->insert($newMeta);
$newMeta = new \Tainacan\Entities\Item_Metadata_Entity($item2, $public_meta);
$newMeta->set_value('test');
$newMeta->validate();
$itemMetaRepo->insert($newMeta);
$newMeta = new \Tainacan\Entities\Item_Metadata_Entity($item2, $private_meta);
$newMeta->set_value('test');
$newMeta->validate();
$itemMetaRepo->insert($newMeta);
$newMeta = new \Tainacan\Entities\Item_Metadata_Entity($item2, $discarded);
$newMeta->set_value('test');
$newMeta->validate();
$itemMetaRepo->insert($newMeta);
$attributes = [
'fetch_only' => [
'meta' => [
$public_meta->get_id(),
$private_meta->get_id()
]
],
];
// First without fetch only
$request = new \WP_REST_Request(
'GET', $this->namespace . '/items'
);
$response = $this->server->dispatch($request);
$data = $response->get_data();
$this->assertEquals( 2, sizeof($data) );
$this->assertEquals( 5, sizeof($data[0]['metadata']) );
// Fetch only as admin
$request = new \WP_REST_Request(
'GET', $this->namespace . '/items'
);
$request->set_query_params($attributes);
$response = $this->server->dispatch($request);
$data = $response->get_data();
$this->assertEquals( 2, sizeof($data) );
$this->assertEquals( 2, sizeof($data[0]['metadata']) );
////
$new_user = $this->factory()->user->create(array( 'role' => 'subscriber' ));
wp_set_current_user($new_user);
// Fetch only as subscriber
$request = new \WP_REST_Request(
'GET', $this->namespace . '/items'
);
$request->set_query_params($attributes);
$response = $this->server->dispatch($request);
$data = $response->get_data();
$this->assertEquals( 2, sizeof($data) );
$this->assertEquals( 1, sizeof($data[0]['metadata']) );
$this->assertEquals( 'public_meta', $data[0]['metadata']['public_meta']['name'] );
}
}
?>

View File

@ -56,7 +56,7 @@ class ImporterTests extends TAINACAN_UnitTestCase {
$Tainacan_Collections = \Tainacan\Repositories\Collections::get_instance();
$collections = $Tainacan_Collections->fetch([], 'OBJECT');
$this->assertEquals(3, $collections, 'total collection in this url does not match');
$this->assertEquals(3, count( $collections ), 'total collection in this url does not match');
$this->assertTrue(true);
}
@ -175,7 +175,7 @@ class ImporterTests extends TAINACAN_UnitTestCase {
$this->assertTrue( !empty( $_SESSION['tainacan_importer'][$id]->get_tmp_file() ) );
// count size of csv
$this->assertEquals( 5, $_SESSION['tainacan_importer'][$id]->get_progress_total_from_source() );
$this->assertEquals( 5, $_SESSION['tainacan_importer'][$id]->get_source_number_of_items() );
// get metadata to mapping
$headers = $_SESSION['tainacan_importer'][$id]->get_source_metadata();
@ -195,7 +195,7 @@ class ImporterTests extends TAINACAN_UnitTestCase {
$collection_definition = [
'id' => $collection->get_id(),
'total_items' => $_SESSION['tainacan_importer'][$id]->get_progress_total_from_source(),
'total_items' => $_SESSION['tainacan_importer'][$id]->get_source_number_of_items(),
];
// get collection metadata to map
@ -222,7 +222,7 @@ class ImporterTests extends TAINACAN_UnitTestCase {
$items = $Tainacan_Items->fetch( [], $collection, 'OBJECT' );
$this->assertEquals( $_SESSION['tainacan_importer'][$id]->get_progress_total_from_source(), count( $items ) );
$this->assertEquals( $_SESSION['tainacan_importer'][$id]->get_source_number_of_items(), count( $items ) );
}
/**