Merge branch 'develop' into field-mapping-interface

# Conflicts:
#	.travis.yml
#	src/admin/tainacan-admin-i18n.php
This commit is contained in:
Jacson Passold 2018-06-29 14:41:39 -03:00
commit c3e286b74e
139 changed files with 10850 additions and 1683 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@ -18,6 +18,7 @@ module.exports = {
'vue/require-default-prop': 'off', // https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/require-default-prop.md
},
globals: {
'tainacan_plugin': true
'tainacan_plugin': true,
'_': true
}
}

View File

@ -33,14 +33,14 @@ install:
true
- composer install
- sudo mkdir /tmp/wordpress/wordpress-test/wp-content/uploads
- sudo wget https://phar.phpunit.de/phpunit-6.5.7.phar -P /tmp
- sudo wget https://phar.phpunit.de/phpunit-6.5.7.phar -P /tmp
- sudo chmod +x /tmp/phpunit-6.5.7.phar
- sudo mv /tmp/phpunit-6.5.7.phar /usr/local/bin/phpunit-6
- sudo wget https://phar.phpunit.de/phpunit-5.phar -P /tmp
- sudo chmod +x /tmp/phpunit-5.phar
- sudo mv /tmp/phpunit-5.phar /usr/local/bin/phpunit-5
- echo '#!/bin/bash' |sudo tee /usr/local/bin/phpunit > /dev/null
- echo 'if ( php -v|grep -q --only-matching --perl-regexp "5\.\\d+\.\\d+" );then /usr/local/bin/phpunit-5 $@;else /usr/local/bin/phpunit-6 $@;fi' |sudo tee -a /usr/local/bin/phpunit > /dev/null
- echo 'if ( php -v|grep -q --only-matching --perl-regexp "5\.\\d+\.\\d+" );then /usr/local/bin/phpunit-5 $@;else /usr/local/bin/phpunit-6 $@;fi;exit $?' |sudo tee -a /usr/local/bin/phpunit > /dev/null
- sudo chmod +x /usr/local/bin/phpunit
script: /usr/local/bin/phpunit # phpunit
before_deploy:

View File

@ -1,4 +1,4 @@
describe('Category test', function () {
describe('Taxonomy test', function () {
beforeEach(() => {
cy.loginByUI()
})
@ -8,100 +8,100 @@ describe('Category test', function () {
})
context('CRUD Taxonomies', function(){
it('canceled create category', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/categories')
cy.location('hash').should('eq', '#/categories')
//cy.get('#button-category-creation').click()
it('canceled create taxonomy', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/taxonomies')
cy.location('hash').should('eq', '#/taxonomies')
//cy.get('#button-taxonomy-creation').click()
cy.get('.button').click()
cy.location('hash').should('eq', '#/categories/new')
cy.get('#tainacan-text-name').type('Category canceled')
cy.get('#tainacan-text-description').type('description category canceled')
cy.location('hash').should('eq', '#/taxonomies/new')
cy.get('#tainacan-text-name').type('Taxonomy canceled')
cy.get('#tainacan-text-description').type('description taxonomy canceled')
cy.get('#tainacan-select-status').select('Publish').should('have.value', 'publish')
cy.get('#button-cancel-category-creation').click()
cy.location('hash').should('eq', '#/categories/')
cy.get('#button-cancel-taxonomy-creation').click()
cy.location('hash').should('eq', '#/taxonomies/')
cy.get('td').should('not.contain', 'Book canceled')
})
it('create category with status publish', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/categories')
cy.location('hash').should('eq', '#/categories')
//cy.get('#button-category-creation').click()
it('create taxonomy with status publish', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/taxonomies')
cy.location('hash').should('eq', '#/taxonomies')
//cy.get('#button-taxonomy-creation').click()
cy.get('.button').click()
cy.location('hash').should('eq', '#/categories/new')
cy.get('#tainacan-text-name').type('Category publish')
cy.get('#tainacan-text-description').type('description category publish')
cy.location('hash').should('eq', '#/taxonomies/new')
cy.get('#tainacan-text-name').type('Taxonomy publish')
cy.get('#tainacan-text-description').type('description taxonomy publish')
cy.get('#tainacan-select-status').select('Publish').should('have.value', 'publish')
cy.get('#button-submit-category-creation').click()
cy.location('hash').should('eq', '#/categories/')
cy.get('td').should('contain', 'Category publish')
cy.get('#button-submit-taxonomy-creation').click()
cy.location('hash').should('eq', '#/taxonomies/')
cy.get('td').should('contain', 'Taxonomy publish')
})
it('create category with status private', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/categories')
cy.location('hash').should('eq', '#/categories')
//cy.get('#button-category-creation').click()
it('create taxonomy with status private', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/taxonomies')
cy.location('hash').should('eq', '#/taxonomies')
//cy.get('#button-taxonomy-creation').click()
cy.get('.button').click()
cy.location('hash').should('eq', '#/categories/new')
cy.get('#tainacan-text-name').type('Category private')
cy.get('#tainacan-text-description').type('description category private')
cy.location('hash').should('eq', '#/taxonomies/new')
cy.get('#tainacan-text-name').type('Taxonomy private')
cy.get('#tainacan-text-description').type('description taxonomy private')
cy.get('#tainacan-select-status').select('Private').should('have.value', 'private')
cy.get('#button-submit-category-creation').click()
cy.location('hash').should('eq', '#/categories/')
cy.get('td').should('contain', 'Category private')
cy.get('#button-submit-taxonomy-creation').click()
cy.location('hash').should('eq', '#/taxonomies/')
cy.get('td').should('contain', 'Taxonomy private')
})
it('create category with status draft', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/categories')
cy.location('hash').should('eq', '#/categories')
//cy.get('#button-category-creation').click()
it('create taxonomy with status draft', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/taxonomies')
cy.location('hash').should('eq', '#/taxonomies')
//cy.get('#button-taxonomy-creation').click()
cy.get('.button').click()
cy.location('hash').should('eq', '#/categories/new')
cy.get('#tainacan-text-name').type('Category draft')
cy.get('#tainacan-text-description').type('description category draft')
cy.location('hash').should('eq', '#/taxonomies/new')
cy.get('#tainacan-text-name').type('Taxonomy draft')
cy.get('#tainacan-text-description').type('description taxonomy draft')
cy.get('#tainacan-select-status').select('Draft').should('have.value', 'draft')
cy.get('#button-submit-category-creation').click()
cy.location('hash').should('eq', '#/categories/')
cy.get('td').should('not.contain', 'Category draft')
cy.get('#button-submit-taxonomy-creation').click()
cy.location('hash').should('eq', '#/taxonomies/')
cy.get('td').should('not.contain', 'Taxonomy draft')
})
it('create category with status draft', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/categories')
cy.location('hash').should('eq', '#/categories')
//cy.get('#button-category-creation').click()
it('create taxonomy with status draft', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/taxonomies')
cy.location('hash').should('eq', '#/taxonomies')
//cy.get('#button-taxonomy-creation').click()
cy.get('.button').click()
cy.location('hash').should('eq', '#/categories/new')
cy.get('#tainacan-text-name').type('Category trash')
cy.get('#tainacan-text-description').type('description category trash')
cy.location('hash').should('eq', '#/taxonomies/new')
cy.get('#tainacan-text-name').type('Taxonomy trash')
cy.get('#tainacan-text-description').type('description taxonomy trash')
cy.get('#tainacan-select-status').select('Trash').should('have.value', 'trash')
cy.get('#button-submit-category-creation').click()
cy.location('hash').should('eq', '#/categories/')
cy.get('td').should('not.contain', 'Category trash')
cy.get('#button-submit-taxonomy-creation').click()
cy.location('hash').should('eq', '#/taxonomies/')
cy.get('td').should('not.contain', 'Taxonomy trash')
})
it('create category color', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/categories')
cy.location('hash').should('eq', '#/categories')
//cy.get('#button-category-creation').click()
it('create taxonomy color', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/taxonomies')
cy.location('hash').should('eq', '#/taxonomies')
//cy.get('#button-taxonomy-creation').click()
cy.get('.button').click()
cy.location('hash').should('eq', '#/categories/new')
cy.get('#tainacan-text-name').type('Category color')
cy.get('#tainacan-text-description').type('description category color')
cy.location('hash').should('eq', '#/taxonomies/new')
cy.get('#tainacan-text-name').type('Taxonomy color')
cy.get('#tainacan-text-description').type('description taxonomy color')
cy.get('#tainacan-select-status').select('Publish').should('have.value', 'publish')
cy.get('#button-submit-category-creation').click()
cy.location('hash').should('eq', '#/categories/')
cy.get('td').should('contain', 'Category color')
cy.get('#button-submit-taxonomy-creation').click()
cy.location('hash').should('eq', '#/taxonomies/')
cy.get('td').should('contain', 'Taxonomy color')
})
it('delete category color', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/categories')
cy.location('hash').should('eq', '#/categories')
it('delete taxonomy color', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/taxonomies')
cy.location('hash').should('eq', '#/taxonomies')
cy.get('.breadcrumbs > :nth-child(3) > .router-link-active').click()
cy.get('.b-table').should('contain', 'Category trash')
cy.get('.b-table').should('contain', 'Taxonomy trash')
cy.get(':nth-child(1) > [data-label="Actions"] > :nth-child(1) > #button-delete > .icon > .mdi').click()
cy.get('.modal-card').should('have.class', 'animation-content')
cy.get('.is-primary').click()
cy.get('.breadcrumbs > :nth-child(3) > .router-link-active').click()
cy.get('.b-table').should('not.contain', 'Category trash')
cy.get('.b-table').should('not.contain', 'Taxonomy trash')
})
})
})

View File

@ -1,4 +1,4 @@
context('Category field test', function(){
context('Taxonomy field test', function(){
beforeEach(() => {
cy.loginByUI()
})
@ -27,40 +27,40 @@ context('Category field test', function(){
cy.get('#tainacan-text-name').type('Cat 1')
cy.get('#tainacan-text-description').type('description cat 1')
cy.get('#tainacan-select-status').select('Publish').should('have.value', 'publish')
cy.get('#button-submit-category-creation').click()
cy.get('#button-submit-taxonomy-creation').click()
cy.get('.page-container').should('contain', 'Cat 1')
cy.get('.button').click()
cy.get('#tainacan-text-name').type('Cat 2')
cy.get('#tainacan-text-description').type('description cat 2')
cy.get('#tainacan-select-status').select('Publish').should('have.value', 'publish')
cy.get('#button-submit-category-creation').click()
cy.get('#button-submit-taxonomy-creation').click()
cy.get('.page-container').should('contain', 'Cat 2')
cy.get('.button').click()
cy.get('#tainacan-text-name').type('Cat 3')
cy.get('#tainacan-text-description').type('description cat 3')
cy.get('#tainacan-select-status').select('Publish').should('have.value', 'publish')
cy.get('#button-submit-category-creation').click()
cy.get('#button-submit-taxonomy-creation').click()
cy.get('.page-container').should('contain', 'Cat 3')
cy.get('.button').click()
cy.get('#tainacan-text-name').type('Cat 4')
cy.get('#tainacan-text-description').type('description cat 4')
cy.get('#tainacan-select-status').select('Publish').should('have.value', 'publish')
cy.get('#button-submit-category-creation').click()
cy.get('#button-submit-taxonomy-creation').click()
cy.get('.page-container').should('contain', 'Cat 4')
cy.get('.button').click()
cy.get('#tainacan-text-name').type('Cat 5')
cy.get('#tainacan-text-description').type('description cat 5')
cy.get('#tainacan-select-status').select('Publish').should('have.value', 'publish')
cy.get('#button-submit-category-creation').click()
cy.get('#button-submit-taxonomy-creation').click()
cy.get('.page-container').should('contain', 'Cat 5')
cy.get('#tainacan-text-name').type('Cat 6')
cy.get('#tainacan-text-description').type('description cat 6')
cy.get('#tainacan-select-status').select('Publish').should('have.value', 'publish')
cy.get('#button-submit-category-creation').click()
cy.get('#button-submit-taxonomy-creation').click()
cy.get('.page-container').should('contain', 'Cat 6')
})
it('canceled create category-type field public', function(){
it('canceled create taxonomy-type field public', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.location('hash').should('eq', '#/collections')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
@ -69,14 +69,14 @@ context('Category field test', function(){
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(7)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('category name canceled')
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('taxonomy name canceled')
cy.get('.textarea').type('name book canceled description')
cy.get('#tainacan-select-status-publish > .check').click()
cy.get(':nth-child(1) > .button').click()
cy.get('.active-fields-area >').should('not.contain', 'category name canceled')
cy.get('.active-fields-area >').should('not.contain', 'taxonomy name canceled')
})
it('create category-type field public - input type = radio', function(){
it('create taxonomy-type field public - input type = radio', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.location('hash').should('eq', '#/collections')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
@ -85,16 +85,16 @@ context('Category field test', function(){
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(7)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('category name public')
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('taxonomy name public')
cy.get('.textarea').type('name book description')
cy.get('#tainacan-select-status-publish > .check').click()
cy.get(':nth-child(1) > .control > .select > select').select('Cat 1')
cy.get(':nth-child(2) > .control > .select > select').select('Radio').should('have.value', 'tainacan-category-radio')
cy.get(':nth-child(2) > .control > .select > select').select('Radio').should('have.value', 'tainacan-taxonomy-radio')
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'category name public')
cy.get('.active-fields-area >').should('contain', 'taxonomy name public')
})
it('create category-type field public - input type = selectbox', function(){
it('create taxonomy-type field public - input type = selectbox', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.location('hash').should('eq', '#/collections')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
@ -103,16 +103,16 @@ context('Category field test', function(){
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(7)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('category name public')
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('taxonomy name public')
cy.get('.textarea').type('name book description')
cy.get('#tainacan-select-status-publish > .check').click()
cy.get(':nth-child(1) > .control > .select > select').select('Cat 1')
cy.get(':nth-child(2) > .control > .select > select').select('Selectbox').should('have.value', 'tainacan-category-selectbox')
cy.get(':nth-child(2) > .control > .select > select').select('Selectbox').should('have.value', 'tainacan-taxonomy-selectbox')
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'category name public')
cy.get('.active-fields-area >').should('contain', 'taxonomy name public')
})
it('create category-type field private', function(){
it('create taxonomy-type field private', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.location('hash').should('eq', '#/collections')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
@ -121,16 +121,16 @@ context('Category field test', function(){
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(7)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('category name private')
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('taxonomy name private')
cy.get('.textarea').type('name book description')
cy.get('#tainacan-select-status-private > .check').click()
cy.get(':nth-child(1) > .control > .select > select').select('Cat 2')
cy.get(':nth-child(2) > .control > .select > select').select('Radio').should('have.value', 'tainacan-category-radio')
cy.get(':nth-child(2) > .control > .select > select').select('Radio').should('have.value', 'tainacan-taxonomy-radio')
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'category name private')
cy.get('.active-fields-area >').should('contain', 'taxonomy name private')
})
it('create category-type field public required', function(){
it('create taxonomy-type field public required', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.location('hash').should('eq', '#/collections')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
@ -139,16 +139,16 @@ context('Category field test', function(){
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(7)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('category name public required')
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('taxonomy name public required')
cy.get('.textarea').type('name book description required')
cy.get('#tainacan-select-status-publish > .check').click()
cy.get(':nth-child(1) > .control > .select > select').select('Cat 3')
cy.get(':nth-child(2) > .control > .select > select').select('Radio').should('have.value', 'tainacan-category-radio')
cy.get(':nth-child(2) > .control > .select > select').select('Radio').should('have.value', 'tainacan-taxonomy-radio')
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'category name public required')
cy.get('.active-fields-area >').should('contain', 'taxonomy name public required')
})
it('create category-type field public multiple values', function(){
it('create taxonomy-type field public multiple values', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.location('hash').should('eq', '#/collections')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
@ -157,16 +157,16 @@ context('Category field test', function(){
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(7)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('category name public multiple values')
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('taxonomy name public multiple values')
cy.get('.textarea').type('name book description multiple values')
cy.get('#tainacan-select-status-publish > .check').click()
cy.get(':nth-child(1) > .control > .select > select').select('Cat 4')
cy.get(':nth-child(2) > .control > .select > select').select('Radio').should('have.value', 'tainacan-category-radio')
cy.get(':nth-child(2) > .control > .select > select').select('Radio').should('have.value', 'tainacan-taxonomy-radio')
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'category name public multiple values')
cy.get('.active-fields-area >').should('contain', 'taxonomy name public multiple values')
})
it('create category-type field public unique values', function(){
it('create taxonomy-type field public unique values', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.location('hash').should('eq', '#/collections')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
@ -175,13 +175,13 @@ context('Category field test', function(){
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(7)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('category name public unique values')
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('taxonomy name public unique values')
cy.get('.textarea').type('name book description multiple values')
cy.get('#tainacan-select-status-publish > .check').click()
cy.get(':nth-child(1) > .control > .select > select').select('Cat 5')
cy.get(':nth-child(2) > .control > .select > select').select('Radio').should('have.value', 'tainacan-category-radio')
cy.get(':nth-child(2) > .control > .select > select').select('Radio').should('have.value', 'tainacan-taxonomy-radio')
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'category name public unique values')
cy.get('.active-fields-area >').should('contain', 'taxonomy name public unique values')
})
it('check if fields are updated to page', function(){
@ -191,11 +191,11 @@ context('Category field test', function(){
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(7) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.active-fields-area >').should('not.contain', 'category name canceled')
cy.get('.active-fields-area >').should('contain', 'category name public')
cy.get('.active-fields-area >').should('contain', 'category name private')
cy.get('.active-fields-area >').should('contain', 'category name public required')
cy.get('.active-fields-area >').should('contain', 'category name public multiple values')
cy.get('.active-fields-area >').should('contain', 'category name public unique values')
cy.get('.active-fields-area >').should('not.contain', 'taxonomy name canceled')
cy.get('.active-fields-area >').should('contain', 'taxonomy name public')
cy.get('.active-fields-area >').should('contain', 'taxonomy name private')
cy.get('.active-fields-area >').should('contain', 'taxonomy name public required')
cy.get('.active-fields-area >').should('contain', 'taxonomy name public multiple values')
cy.get('.active-fields-area >').should('contain', 'taxonomy name public unique values')
})
})

View File

@ -175,18 +175,18 @@ Fetch all values of a metadatum from a collection in all it collection items
**Returns:** array|null|object
### `private function pre_update_category_field($metadatum)`
### `private function pre_update_taxonomy_field($metadatum)`
Stores the value of the taxonomy_id option to use on update_category_field method.
Stores the value of the taxonomy_id option to use on update_taxonomy_field method.
### `private function update_category_field($metadatum)`
### `private function update_taxonomy_field($metadatum)`
Triggers hooks when saving a Category Metadatum, indicating wich taxonomy was added or removed from a collection.
Triggers hooks when saving a Taxonomy Metadatum, indicating wich taxonomy was added or removed from a collection.
This is used by Taxonomies repository to update the collections_ids property of the taxonomy as a metadatum type category is inserted or removed
This is used by Taxonomies repository to update the collections_ids property of the taxonomy as a metadatum type taxonomy is inserted or removed
**Parameters:**

View File

@ -11,7 +11,7 @@ The typical workflow when you create a Digital Repository with Tainacan is:
A collection is a group of items, that share the same set of metadata. Every item uploaded to your digital repository will be part of a collection - and only one collection. For instance, you could have a "paintings" collections, with metadata such as Title, Author, Country, Tecnique, etc and another collection for "films", with Title, Director, Country and Genre.
For each collection you can set a different set of metadata and they can share common categories, which means you could browse for items in a specific Country, and get both paintings and films in your results.
For each collection you can set a different set of metadata and they can share common taxonomies, which means you could browse for items in a specific Country, and get both paintings and films in your results.
Collections can also have child collections, which will inherit parent's collection metadata and can add their own set of additional information.
@ -69,7 +69,7 @@ Taxonomies can be created and used to classify items. Typical Taxonomies are Gen
In WordPress language, they are Custom Taxonomies, and they can be shared among many collections.
Each Category has a set of terms. For example, the category Genre may have terms like "drama" and "comedy".
Each Taxonomy has a set of terms. For example, the taxonomy Genre may have terms like "drama" and "comedy".
Terms can have hierarchy, which means that when you browse for items that have a parente term (for instance, "Rock"), the results will include items that have any of the child terms (for instance, "Progressive Rock" and "Classic Rock").

View File

@ -207,7 +207,7 @@ Who's got it: Administrators, Editors and Tainacan Editors
Allows to view Items marked as private and its items.
### Categories
### Taxonomies
### Metadata

5124
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -13,6 +13,7 @@
"html-to-json": "^0.6.0",
"mdi": "^2.2.43",
"moment": "^2.22.1",
"npm": "^6.1.0",
"qs": "^6.5.2",
"v-mask": "^1.3.2",
"v-tooltip": "^2.0.0-rc.32",

BIN
src/.DS_Store vendored

Binary file not shown.

View File

@ -10,54 +10,102 @@
<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
:loading="isFetching"
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
grouped
@ -67,18 +115,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">
@ -98,37 +159,140 @@
</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
},
all: false
}).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;
@ -147,55 +311,137 @@
this.searchCriterias = [1];
this.advancedSearchQuery = {
advancedSearch: true,
metaquery: {},
taxquery: {}
};
},
addValueToAdvancedSearchQuery: _.debounce(function(value, type, relation) {
let vm = this;
vm.addToAdvancedSearchQuery(value, type, relation);
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) {
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);
},
addToAdvancedSearchQuery(value, type, relation){
if(this.advancedSearchQuery.hasOwnProperty(relation)){
//if(this.advancedSearchQuery[relation].compare === 'IN'){
//this.advancedSearchQuery[relation][type] = value.split(' ');
//} else {
if(type == 'compare' && (this.advancedSearchQuery[relation]['compare'] == 'IN' ||
this.advancedSearchQuery[relation]['compare'] == 'NOT IN')){
this.advancedSearchQuery[relation].value.push(value);
} else {
this.advancedSearchQuery[relation][type] = value;
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);
}
}
//}
} else {
if(type == 'compare' && (value == 'IN' || value == 'NOT IN')){
}
},
parseDateToNavigatorLanguage(date){
date = new Date(date.replace(/-/g, '/'));
this.advancedSearchQuery = Object.assign({}, this.advancedSearchQuery, {
[`${relation}`]: {
[`${type}`]: [value],
return moment(date, moment.ISO_8601).format(this.dateFormat);
},
addToAdvancedSearchQuery(value, type, searchCriteria){
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 {
this.advancedSearchQuery = Object.assign({}, this.advancedSearchQuery, {
[`${relation}`]: {
[`${type}`]: value,
}
});
}
}
// 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.metaquery = Object.assign({}, this.advancedSearchQuery.metaquery, {
[`${searchCriteria}`]: {
key: Number(criteriaKey[0]),
compare: '='
}
});
}
console.log(this.advancedSearchQuery);
this.$set(this.advancedSearchQuery.metaquery[searchCriteria], 'ptype', criteriaKey[2]);
}
} else if(type == 'terms'){
let termIndex = this.terms.findIndex((element, index) => {
if(element == value && index == this.termList[index].i){
return true;
}
});
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);
}
}
},
}
}
@ -211,9 +457,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

@ -10,15 +10,8 @@
<!-- Header Page -------------------------------- -->
<b-field :addons="false">
<label class="section-label">{{ $i18n.get('label_header_image') }}</label>
<label class="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,29 +22,35 @@
</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
size="is-small"
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" />
<b-icon
size="is-small"
icon="delete" />
</a>
</div>
</div>
</b-field>
<div class="columns">
<div class="column">
<div class="column is-4">
<!-- Thumbnail -------------------------------- -->
<b-field :addons="false">
<label class="section-label">{{ $i18n.get('label_thumbnail') }}</label>
<label class="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,37 +62,39 @@
</figure>
<div class="thumbnail-buttons-row">
<a
id="button-delete"
class="button is-rounded is-secondary"
id="button-edit-thumbnail"
:aria-label="$i18n.get('label_button_edit_thumb')"
@click.prevent="thumbnailMediaFrame.openFrame($event)">
<b-icon
size="is-small"
icon="pencil" />
</a>
<a
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" />
<b-icon
size="is-small"
icon="delete" />
</a>
</div>
</div>
</b-field>
<!-- Enable Cover Page -------------------------------- -->
<div class="field">
<b-checkbox
id="tainacan-checkbox-cover-page"
size="is-small"
true-value="yes"
false-value="no"
v-model="form.enable_cover_page">
{{ $i18n.get('label_enable_cover_page') }}
</b-checkbox>
<help-button
:title="$i18n.getHelperTitle('collections', 'enable_cover_page')"
:message="$i18n.getHelperMessage('collections', 'enable_cover_page')"/>
</div>
<!-- Cover Page -------------------------------- -->
<b-field
v-show="form.enable_cover_page == 'yes'"
:addons="false"
:label="$i18n.get('label_cover_page')"
:type="editFormErrors['cover_page_id'] != undefined ? 'is-danger' : ''"
:message="editFormErrors['cover_page_id'] != undefined ? editFormErrors['cover_page_id'] : ''">
<b-switch
id="tainacan-checkbox-cover-page"
size="is-small"
true-value="yes"
false-value="no"
v-model="form.enable_cover_page" />
<help-button
:title="$i18n.getHelperTitle('collections', 'cover_page_id')"
:message="$i18n.getHelperMessage('collections', 'cover_page_id')"/>
@ -106,7 +107,8 @@
:loading="isFetchingPages"
@input="fecthCoverPages($event)"
@focus="clearErrors('cover_page_id')"
v-if="coverPage == undefined || coverPage.title == undefined">
v-if="coverPage == undefined || coverPage.title == undefined"
:disabled="form.enable_cover_page != 'yes'">
<template slot-scope="props">
{{ props.option.title.rendered }}
</template>
@ -119,18 +121,44 @@
<span v-html="coverPage.title.rendered" />
<span class="selected-cover-page-control">
<a
target="blank"
:href="coverPageEditPath">{{ $i18n.get('edit') }}</a>
&nbsp;&nbsp;
<a
target="_blank"
:href="coverPage.link">{{ $i18n.get('see') }}</a>
&nbsp;&nbsp;
<button
class="button is-secondary is-small"
@click.prevent="removeCoverPage()">{{ $i18n.get('remove') }}</button>
target="_blank"
@click.prevent="removeCoverPage()">
<b-icon
size="is-small"
icon="close"/>
</a>
</span>
</div>
<span
:class="{'disabled': form.enable_cover_page != 'yes' || coverPage == undefined || coverPage.title == undefined}"
class="selected-cover-page-buttons">
<a
target="_blank"
:href="coverPage.link">
<b-icon
size="is-small"
icon="eye"/>
</a>
&nbsp;&nbsp;
<a
target="blank"
:href="coverPageEditPath">
<b-icon
size="is-small"
icon="pencil"/>
</a>
</span>
<br>
<a
class="is-inline add-link"
:class="{'disabled': form.enable_cover_page != 'yes'}"
target="_blank"
:href="newPagePath">
<b-icon
icon="plus-circle"
size="is-small"
type="is-secondary"/>
{{ $i18n.get('label_create_new_page') }}</a>
</b-field>
<!-- Enabled View Modes ------------------------------- -->
@ -141,6 +169,7 @@
:message="$i18n.getHelperMessage('collections', 'enabled_view_modes')"/>
<div class="control">
<b-dropdown
class="two-columns-dropdown"
ref="enabledViewModesDropdown"
:mobile-modal="false"
:disabled="Object.keys(registeredViewModes).length < 0">
@ -179,6 +208,7 @@
:title="$i18n.getHelperTitle('collections', 'default_view_mode')"
:message="$i18n.getHelperMessage('collections', 'default_view_mode')"/>
<b-select
expanded
id="tainacan-select-default_view_mode"
v-model="form.default_view_mode"
@focus="clearErrors('default_view_mode')">
@ -192,6 +222,7 @@
</b-field>
</div>
<div class="column is-1" />
<div class="column">
<!-- Status -------------------------------- -->
<b-field
@ -203,6 +234,7 @@
:title="$i18n.getHelperTitle('collections', 'status')"
:message="$i18n.getHelperMessage('collections', 'status')"/>
<b-select
expanded
id="tainacan-select-status"
v-model="form.status"
@focus="clearErrors('status')"
@ -218,17 +250,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 -------------------------------- -->
@ -247,6 +279,32 @@
@focus="clearErrors('description')"/>
</b-field>
<!-- Parent Collection -------------------------------- -->
<b-field
:addons="false"
:label="$i18n.get('label_parent_collection')"
:type="editFormErrors['parent'] != undefined ? 'is-danger' : ''"
:message="editFormErrors['parent'] != undefined ? editFormErrors['parent'] : ''">
<help-button
:title="$i18n.getHelperTitle('collections', 'parent')"
:message="$i18n.getHelperMessage('collections', 'parent')"/>
<b-select
expanded
id="tainacan-select-parent"
v-model="form.parent"
@focus="clearErrors('parent')"
:loading="isFetchingCollections"
:placeholder="$i18n.get('instruction_select_a_parent_collection')">
<option value="0">{{ $i18n.get('label_no_parent_collection') }}</option>
<option
v-if="collection.id != anotherCollection.id"
v-for="anotherCollection of collections"
:key="anotherCollection.id"
:value="anotherCollection.id">{{ anotherCollection.name }}
</option>
</b-select>
</b-field>
<!-- Moderators List -------------------------------- -->
<b-field
:addons="false"
@ -304,31 +362,6 @@
v-model="form.slug"
@focus="clearErrors('slug')"/>
</b-field>
<!-- Parent Collection -------------------------------- -->
<b-field
:addons="false"
:label="$i18n.get('label_parent_collection')"
:type="editFormErrors['parent'] != undefined ? 'is-danger' : ''"
:message="editFormErrors['parent'] != undefined ? editFormErrors['parent'] : ''">
<help-button
:title="$i18n.getHelperTitle('collections', 'parent')"
:message="$i18n.getHelperMessage('collections', 'parent')"/>
<b-select
id="tainacan-select-parent"
v-model="form.parent"
@focus="clearErrors('parent')"
:loading="isFetchingCollections"
:placeholder="$i18n.get('instruction_select_a_parent_collection')">
<option value="0">{{ $i18n.get('label_no_parent_collection') }}</option>
<option
v-if="collection.id != anotherCollection.id"
v-for="anotherCollection of collections"
:key="anotherCollection.id"
:value="anotherCollection.id">{{ anotherCollection.name }}
</option>
</b-select>
</b-field>
</div>
</div>
@ -417,7 +450,9 @@ export default {
thumbnailMediaFrame: undefined,
headerImageMediaFrame: undefined,
registeredViewModes: tainacan_plugin.registered_view_modes,
viewModesList: []
viewModesList: [],
fromImporter: '',
newPagePath: tainacan_plugin.admin_url + 'post-new.php?post_type=page'
}
},
methods: {
@ -474,7 +509,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) {
@ -535,7 +573,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) {
@ -565,7 +606,7 @@ export default {
this.form.cover_page_id = selectedPage.id;
this.coverPage = selectedPage;
this.coverPageTitle = this.coverPage.title.rendered;
this.coverPageEditPath = tainacan_plugin.admin_url + '/post.php?post=' + selectedPage.id + '&action=edit';
this.coverPageEditPath = tainacan_plugin.admin_url + 'post.php?post=' + selectedPage.id + '&action=edit';
},
fecthModerators(search) {
this.isFetchingModerators = true;
@ -653,15 +694,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 => {
@ -727,7 +771,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));
});
@ -753,25 +797,51 @@ 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;
height: 30px !important;
width: 30px !important;
z-index: 99;
margin-left: 10px !important;
.icon {
display: inherit;
padding: 0;
margin: 0;
margin-top: 1px;
font-size: 18px;
}
}
.header-field {
img {
padding: 20px;
}
.image-placeholder {
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;
top: -35px;
right: 5px;
position: relative;
}
}
.thumbnail-field {
max-height: 208px;
@ -790,43 +860,38 @@ 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: 100px;
bottom: -136px;
}
}
.selected-cover-page {
background-color: $tainacan-input-background;
border: 1px solid $tainacan-input-background;
padding: 8px;
font-size: .85rem;
font-size: .75rem;
.span { vertical-align: middle;}
.selected-cover-page-control {
float: right;
}
}
.selected-cover-page-buttons {
float: right;
padding: 4px 6px;
.icon { font-size: 20px; }
&.disabled {
.icon { color: $tainacan-input-background; }
}
}
.moderators-empty-list {
color: gray;

View File

@ -0,0 +1,574 @@
<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"
:value="checkCurrentSelectedCollectionMetadatum(source_metadatum)"
@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';
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('bgprocess', [
'fetchProcess'
]),
...mapActions('metadata', [
'fetchMetadata',
'fetchMetadatumTypes',
'sendMetadatum'
]),
...mapGetters('metadata', [
'getMetadatumTypes'
]),
...mapGetters('bgprocess', [
'getProcess'
]),
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;
},
checkCurrentSelectedCollectionMetadatum(sourceMetadatum) {
for (let key in this.mappedCollection['mapping']) {
if(this.mappedCollection['mapping'][key] == sourceMetadatum)
return key;
}
return 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() {
this.fetchProcess(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

@ -21,18 +21,15 @@
:title="$i18n.getHelperTitle('items', 'status')"
:message="$i18n.getHelperMessage('items', 'status')"/>
</div>
<!-- Last Updated Info -->
<p>{{ ($i18n.get('info_updated_at') + ' ' + lastUpdated) }}
<em>
<span v-if="isUpdatingValues && !isEditingValues">&nbsp;&nbsp;{{ $i18n.get('info_updating_metadata_values') }}</span>
<span v-if="isEditingValues">&nbsp;&nbsp;{{ $i18n.get('info_editing_metadata_values') }}</span>
</em>
</p>
<div class="section-status">
<div class="field">
<!-- <div class="block">
<b-radio
:id="`status-option-${statusOption.value}`"
v-for="statusOption in statusOptions"
:key="statusOption.value"
:value="statusOption.value"
:disabled="statusOption.disabled">
{{ statusOption.label }}
</b-radio>
</div> -->
<div class="field has-addons">
<b-select
v-model="form.status"
:placeholder="$i18n.get('instruction_select_a_status')">
@ -44,13 +41,6 @@
:disabled="statusOption.disabled">{{ statusOption.label }}
</option>
</b-select>
<p
v-if="item.status == 'auto-draft'"
class="help is-danger">
{{ $i18n.get('info_item_not_saved') }}
</p>
</div>
<div class="field is-grouped">
<div class="control">
<button
type="button"
@ -61,6 +51,11 @@
</button>
</div>
</div>
<p
v-if="item.status == 'auto-draft'"
class="help is-danger">
{{ $i18n.get('info_item_not_saved') }}
</p>
<p class="help is-danger">{{ formErrorMessage }}</p>
</div>
@ -235,7 +230,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)">
@ -376,7 +371,9 @@ export default {
isURLModalActive: false,
urlLink: '',
isTextModalActive: false,
textLink: ''
textLink: '',
isEditingValues: false,
isUpdatingValues: false
}
},
computed: {
@ -385,6 +382,9 @@ export default {
},
attachmentsList(){
return this.getAttachments();
},
lastUpdated() {
return this.getLastUpdated();
}
},
components: {
@ -401,11 +401,13 @@ export default {
'cleanMetadata',
'sendAttachments',
'updateThumbnail',
'fetchAttachments'
'fetchAttachments',
'cleanLastUpdated'
]),
...mapGetters('item',[
'getMetadata',
'getAttachments'
'getAttachments',
'getLastUpdated'
]),
onSubmit() {
// Puts loading on Item edition
@ -665,6 +667,18 @@ export default {
// Fetch current existing attachments
this.fetchAttachments(this.itemId);
}
// Sets feedback variables
eventBus.$on('isChangingValue', () => {
this.isEditingValues = true;
setTimeout(()=> {
this.isEditingValues = false;
}, 1000)
});
eventBus.$on('isUpdatingValue', (status) => {
this.isUpdatingValues = status;
});
this.cleanLastUpdated();
},
mounted() {
document.getElementById('collection-page-container').addEventListener('scroll', ($event) => {
@ -735,6 +749,10 @@ export default {
padding-left: $page-side-padding;
padding-right: $page-side-padding;
transition: width 0.6s;
@media screen and (max-width: 769px) {
width: 100%;
}
}
.column.is-4-5 {
width: 37.5%;
@ -742,8 +760,8 @@ export default {
padding-right: $page-side-padding;
transition: all 0.6s;
.metadatum {
padding: 10px 0px 10px 25px;
.field {
padding: 10px 0px 10px 60px;
}
}

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

@ -5,7 +5,7 @@
<b-tabs v-model="activeTab">
<b-tab-item :label="$i18n.get('taxonomy')">
<form
v-if="category != null && category != undefined"
v-if="taxonomy != null && taxonomy != undefined"
class="tainacan-form"
label-width="120px">
@ -16,8 +16,8 @@
:type="editFormErrors['name'] != undefined ? 'is-danger' : ''"
:message="editFormErrors['name'] != undefined ? editFormErrors['name'] : ''">
<help-button
:title="$i18n.getHelperTitle('categories', 'name')"
:message="$i18n.getHelperMessage('categories', 'name')"/>
:title="$i18n.getHelperTitle('taxonomies', 'name')"
:message="$i18n.getHelperMessage('taxonomies', 'name')"/>
<b-input
id="tainacan-text-name"
v-model="form.name"
@ -32,8 +32,8 @@
:type="editFormErrors['description'] != undefined ? 'is-danger' : ''"
:message="editFormErrors['description'] != undefined ? editFormErrors['description'] : ''">
<help-button
:title="$i18n.getHelperTitle('categories', 'description')"
:message="$i18n.getHelperMessage('categories', 'description')"/>
:title="$i18n.getHelperTitle('taxonomies', 'description')"
:message="$i18n.getHelperMessage('taxonomies', 'description')"/>
<b-input
id="tainacan-text-description"
type="textarea"
@ -48,8 +48,8 @@
:type="editFormErrors['status'] != undefined ? 'is-danger' : ''"
:message="editFormErrors['status'] != undefined ? editFormErrors['status'] : ''">
<help-button
:title="$i18n.getHelperTitle('categories', 'status')"
:message="$i18n.getHelperMessage('categories', 'status')"/>
:title="$i18n.getHelperTitle('taxonomies', 'status')"
:message="$i18n.getHelperMessage('taxonomies', 'status')"/>
<b-select
id="tainacan-select-status"
v-model="form.status"
@ -71,8 +71,8 @@
:type="editFormErrors['slug'] != undefined ? 'is-danger' : ''"
:message="editFormErrors['slug'] != undefined ? editFormErrors['slug'] : ''">
<help-button
:title="$i18n.getHelperTitle('categories', 'slug')"
:message="$i18n.getHelperMessage('categories', 'slug')"/>
:title="$i18n.getHelperTitle('taxonomies', 'slug')"
:message="$i18n.getHelperMessage('taxonomies', 'slug')"/>
<b-icon :class="{'is-loading': isUpdatingSlug}"/>
<b-input
@input="updateSlug()"
@ -85,10 +85,10 @@
<!-- Allow Insert -->
<b-field
:addons="false"
:label="$i18n.get('label_category_allow_new_terms')">
:label="$i18n.get('label_taxonomy_allow_new_terms')">
<help-button
:title="$i18n.getHelperTitle('categories', 'allow_insert')"
:message="$i18n.getHelperMessage('categories', 'allow_insert')"/>
:title="$i18n.getHelperTitle('taxonomies', 'allow_insert')"
:message="$i18n.getHelperMessage('taxonomies', 'allow_insert')"/>
<div class="block" >
<b-checkbox
v-model="form.allowInsert"
@ -103,14 +103,14 @@
<div class="field is-grouped form-submit">
<div class="control">
<button
id="button-cancel-category-creation"
id="button-cancel-taxonomy-creation"
class="button is-outlined"
type="button"
@click="cancelBack">{{ $i18n.get('cancel') }}</button>
</div>
<div class="control">
<button
id="button-submit-category-creation"
id="button-submit-taxonomy-creation"
@click.prevent="onSubmit"
class="button is-success">{{ $i18n.get('save') }}</button>
</div>
@ -121,11 +121,11 @@
<b-tab-item :label="$i18n.get('terms')">
<!-- Terms List -->
<terms-list :category-id="categoryId"/>
<terms-list :taxonomy-id="taxonomyId"/>
</b-tab-item>
<b-loading
:active.sync="isLoadingCategory"
:active.sync="isLoadingTaxonomy"
:can-cancel="false"/>
</b-tabs>
</div>
@ -140,14 +140,14 @@
import CustomDialog from '../other/custom-dialog.vue';
export default {
name: 'CategoryEditionForm',
name: 'TaxonomyEditionForm',
mixins: [ wpAjax ],
data(){
return {
categoryId: String,
taxonomyId: String,
activeTab: 0,
category: null,
isLoadingCategory: false,
taxonomy: null,
isLoadingTaxonomy: false,
isUpdatingSlug: false,
form: {
name: String,
@ -180,15 +180,15 @@
beforeRouteLeave( to, from, next ) {
let formNotSaved = false;
if (this.category.name != this.form.name)
if (this.taxonomy.name != this.form.name)
formNotSaved = true;
if (this.category.description != this.form.description)
if (this.taxonomy.description != this.form.description)
formNotSaved = true;
if (this.category.slug != this.form.slug)
if (this.taxonomy.slug != this.form.slug)
formNotSaved = true;
if (this.category.allow_insert != this.form.allowInsert)
if (this.taxonomy.allow_insert != this.form.allowInsert)
formNotSaved = true;
if (this.category.status != this.form.status)
if (this.taxonomy.status != this.form.status)
formNotSaved = true;
if (formNotSaved) {
@ -198,7 +198,7 @@
props: {
icon: 'alert',
title: this.$i18n.get('label_warning'),
message: this.$i18n.get('info_warning_category_not_saved'),
message: this.$i18n.get('info_warning_taxonomy_not_saved'),
onConfirm: () => {
next();
}
@ -209,21 +209,21 @@
}
},
methods: {
...mapActions('category', [
'createCategory',
'updateCategory',
'fetchCategory',
...mapActions('taxonomy', [
'createTaxonomy',
'updateTaxonomy',
'fetchTaxonomy',
'fetchOnlySlug'
]),
...mapGetters('category',[
'getCategory',
...mapGetters('taxonomy',[
'getTaxonomy',
]),
onSubmit() {
this.isLoadingCategory = true;
this.isLoadingTaxonomy = true;
let data = {
categoryId: this.categoryId,
taxonomyId: this.taxonomyId,
name: this.form.name,
description: this.form.description,
slug: this.form.slug,
@ -231,23 +231,23 @@
allowInsert: this.form.allowInsert
};
this.updateCategory(data)
.then(updatedCategory => {
this.updateTaxonomy(data)
.then(updatedTaxonomy => {
this.category = updatedCategory;
this.taxonomy = updatedTaxonomy;
// Fill this.form data with current data.
this.form.name = this.category.name;
this.form.slug = this.category.slug;
this.form.description = this.category.description;
this.form.status = this.category.status;
this.form.allowInsert = this.category.allow_insert;
this.form.name = this.taxonomy.name;
this.form.slug = this.taxonomy.slug;
this.form.description = this.taxonomy.description;
this.form.status = this.taxonomy.status;
this.form.allowInsert = this.taxonomy.allow_insert;
this.isLoadingCategory = false;
this.isLoadingTaxonomy = false;
this.formErrorMessage = '';
this.editFormErrors = {};
this.$router.push(this.$routerHelper.getCategoriesPath());
this.$router.push(this.$routerHelper.getPath());
})
.catch((errors) => {
for (let error of errors.errors) {
@ -257,7 +257,7 @@
}
this.formErrorMessage = errors.error_message;
this.isLoadingCategory = false;
this.isLoadingTaxonomy = false;
});
},
updateSlug(){
@ -267,7 +267,7 @@
this.isUpdatingSlug = true;
this.getSamplePermalink(this.categoryId, this.form.name, this.form.slug)
this.getSamplePermalink(this.taxonomyId, this.form.name, this.form.slug)
.then(samplePermalink => {
let promise = htmlToJSON.parse(samplePermalink, {
@ -292,11 +292,11 @@
});
},
createNewCategory() {
// Puts loading on Draft Category creation
this.isLoadingCategory = true;
createNewTaxonomy() {
// Puts loading on Draft Taxonomy creation
this.isLoadingTaxonomy = true;
// Creates draft Category
// Creates draft Taxonomy
let data = {
name: '',
description: '',
@ -305,22 +305,22 @@
allowInsert: '',
};
this.createCategory(data)
this.createTaxonomy(data)
.then(res => {
this.categoryId = res.id;
this.category = res;
this.taxonomyId = res.id;
this.taxonomy = res;
// Fill this.form data with current data.
this.form.name = this.category.name;
this.form.description = this.category.description;
this.form.slug = this.category.slug;
this.form.allowInsert = this.category.allow_insert;
this.form.name = this.taxonomy.name;
this.form.description = this.taxonomy.description;
this.form.slug = this.taxonomy.slug;
this.form.allowInsert = this.taxonomy.allow_insert;
// Pre-fill status with publish to incentivate it
this.form.status = 'publish';
this.isLoadingCategory = false;
this.isLoadingTaxonomy = false;
})
.catch(error => this.$console.error(error));
@ -329,7 +329,7 @@
this.editFormErrors[attribute] = undefined;
},
cancelBack(){
this.$router.push(this.$routerHelper.getCategoriesPath());
this.$router.push(this.$routerHelper.getPath());
},
labelNewTerms(){
return ( this.form.allowInsert === 'yes' ) ? this.$i18n.get('label_yes') : this.$i18n.get('label_no');
@ -338,26 +338,26 @@
created(){
if (this.$route.fullPath.split("/").pop() === "new") {
this.createNewCategory();
this.createNewTaxonomy();
} else if (this.$route.fullPath.split("/").pop() === "edit" || this.$route.fullPath.split("/").pop() === "terms") {
this.isLoadingCategory = true;
this.isLoadingTaxonomy = true;
// Obtains current category ID from URL
// Obtains current taxonomy ID from URL
this.pathArray = this.$route.fullPath.split("/").reverse();
this.categoryId = this.pathArray[1];
this.taxonomyId = this.pathArray[1];
this.fetchCategory(this.categoryId).then(res => {
this.category = res.category;
this.fetchTaxonomy(this.taxonomyId).then(res => {
this.taxonomy = res.taxonomy;
// Fill this.form data with current data.
this.form.name = this.category.name;
this.form.description = this.category.description;
this.form.slug = this.category.slug;
this.form.status = this.category.status;
this.form.allowInsert = this.category.allow_insert;
this.form.name = this.taxonomy.name;
this.form.description = this.taxonomy.description;
this.form.slug = this.taxonomy.slug;
this.form.status = this.taxonomy.status;
this.form.allowInsert = this.taxonomy.allow_insert;
this.isLoadingCategory = false;
this.isLoadingTaxonomy = false;
});
if (this.$route.fullPath.split("/").pop() === "terms")

View File

@ -3,88 +3,84 @@
id="termEditForm"
class="tainacan-form"
@submit.prevent="saveEdition(editForm)">
<div class="columns">
<div class="column is-narrow">
<!-- Header Image -------------------------------- -->
<b-field
:addons="false"
:label="$i18n.get('label_header_image')">
<div class="thumbnail-field">
<a
class="button is-rounred is-secondary"
id="button-edit-thumbnail"
:aria-label="$i18n.get('label_button_edit_header_image')"
@click="headerImageMediaFrame.openFrame($event)">
<b-icon icon="pencil"/>
</a>
<figure class="image">
<span
v-if="editForm.header_image === undefined || editForm.header_image === false"
class="image-placeholder">{{ $i18n.get('label_empty_header_image') }}</span>
<img
:alt="$i18n.get('label_header_image')"
:src="(editForm.header_image === undefined || editForm.header_image === false) ? headerPlaceholderPath : editForm.header_image">
</figure>
<div class="thumbnail-buttons-row">
<a
id="button-delete"
:aria-label="$i18n.get('label_button_delete_thumb')"
@click="deleteThumbnail()">
<b-icon
type="is-gray"
icon="delete" />
<span class="text">{{ $i18n.get('remove') }} </span>
</a>
</div>
<br>
</div>
<a
v-if="editForm.url != undefined && editForm.url!= ''"
class="button is-secondary"
:href="editForm.url">
{{ $i18n.get('see') + ' ' + $i18n.get('term') }}
</a>
</b-field>
</div>
<div class="column">
<b-field
:addons="false"
:type="((formErrors.name !== '' || formErrors.repeated !== '') && (formErrors.name !== undefined || formErrors.repeated !== undefined )) ? 'is-danger' : ''"
:message="formErrors.name ? formErrors : formErrors.repeated">
<label class="label is-inline">
{{ $i18n.get('label_name') }}
<span class="required-term-asterisk">*</span>
<help-button
:title="$i18n.get('label_name')"
:message="$i18n.get('info_help_term_name')"/>
</label>
<b-input
v-model="editForm.name"
name="name"
@focus="clearErrors({ name: 'name', repeated: 'repeated' })"/>
</b-field>
<b-field
:addons="false"
:type="formErrors['description'] !== '' && formErrors['description'] !== undefined ? 'is-danger' : ''"
:message="formErrors['description']">
<label class="label">
{{ $i18n.get('label_description') }}
<help-button
:title="$i18n.get('label_description')"
:message="$i18n.get('info_help_term_description')"/>
</label>
<b-input
type="textarea"
name="description"
v-model="editForm.description"
@focus="clearErrors('description')"/>
</b-field>
</div>
<div class="tainacan-page-title">
<h2>{{ $i18n.get("title_term_edition") }}</h2>
<hr>
</div>
<!-- Header Image -------------------------------- -->
<b-field
:addons="false"
:label="$i18n.get('label_header_image')">
<div class="thumbnail-field">
<figure class="image">
<span
v-if="editForm.header_image === undefined || editForm.header_image === false"
class="image-placeholder">{{ $i18n.get('label_empty_header_image') }}</span>
<img
:alt="$i18n.get('label_header_image')"
:src="(editForm.header_image === undefined || editForm.header_image === false) ? headerPlaceholderPath : editForm.header_image">
</figure>
<div class="thumbnail-buttons-row">
<a
class="button is-rounded is-secondary"
id="button-edit-header"
:aria-label="$i18n.get('label_button_edit_header_image')"
@click="headerImageMediaFrame.openFrame($event)">
<b-icon
size="is-small"
icon="pencil"/>
</a>
<a
class="button is-rounded is-secondary"
id="button-delete-header"
:aria-label="$i18n.get('label_button_delete_thumb')"
@click="deleteThumbnail()">
<b-icon
size="is-small"
icon="delete" />
</a>
</div>
<br>
</div>
</b-field>
<b-field
:addons="false"
:type="((formErrors.name !== '' || formErrors.repeated !== '') && (formErrors.name !== undefined || formErrors.repeated !== undefined )) ? 'is-danger' : ''"
:message="formErrors.name ? formErrors : formErrors.repeated">
<label class="label is-inline">
{{ $i18n.get('label_name') }}
<span class="required-term-asterisk">*</span>
<help-button
:title="$i18n.get('label_name')"
:message="$i18n.get('info_help_term_name')"/>
</label>
<b-input
v-model="editForm.name"
name="name"
@focus="clearErrors({ name: 'name', repeated: 'repeated' })"/>
</b-field>
<b-field
:addons="false"
:type="formErrors['description'] !== '' && formErrors['description'] !== undefined ? 'is-danger' : ''"
:message="formErrors['description']">
<label class="label">
{{ $i18n.get('label_description') }}
<help-button
:title="$i18n.get('label_description')"
:message="$i18n.get('info_help_term_description')"/>
</label>
<b-input
type="textarea"
name="description"
v-model="editForm.description"
@focus="clearErrors('description')"/>
</b-field>
<div class="field is-grouped form-submit">
<div class="control">
<button
@ -95,6 +91,15 @@
{{ $i18n.get('cancel') }}
</button>
</div>
<div class="control">
<button
type="button"
v-if="editForm.url != undefined && editForm.url!= ''"
class="button is-secondary"
:href="editForm.url">
{{ $i18n.get('see') + ' ' + $i18n.get('term') }}
</button>
</div>
<div class="control">
<button
class="button is-success"
@ -121,21 +126,21 @@
},
props: {
editForm: Object,
categoryId: ''
taxonomyId: ''
},
methods: {
...mapActions('category', [
...mapActions('taxonomy', [
'sendTerm',
'updateTerm',
]),
...mapGetters('category', [
...mapGetters('taxonomy', [
'getTerms'
]),
saveEdition(term) {
if (term.id === 'new') {
this.sendTerm({
categoryId: this.categoryId,
taxonomyId: this.taxonomyId,
name: this.editForm.name,
description: this.editForm.description,
parent: this.editForm.parent,
@ -157,7 +162,7 @@
} else {
this.updateTerm({
categoryId: this.categoryId,
taxonomyId: this.taxonomyId,
termId: this.editForm.id,
name: this.editForm.name,
description: this.editForm.description,
@ -239,15 +244,27 @@
}
form {
padding: 2.0rem 2rem 1rem 2rem;
border-top: 1px solid $draggable-border-color;
border-bottom: 1px solid $draggable-border-color;
padding: 2.0rem 0rem 1rem 3rem;
border-left: 1px solid $draggable-border-color;
margin-top: 1.0em;
.tainacan-page-title {
margin-bottom: 40px;
h2 {
font-size: 20px;
font-weight: 500;
color: $tertiary;
display: inline-block;
}
hr{
margin: 3px 0px 4px 0px;
height: 1px;
background-color: $secondary;
}
}
.thumbnail-field {
max-height: 128px;
margin-bottom: 66px;
margin-top: -20px;
.content {
padding: 10px;
@ -255,49 +272,41 @@
}
img {
position: relative;
width: 128px;
}
.image-placeholder {
position: absolute;
margin-left: 10px;
margin-right: 10px;
top: 24px;
bottom: 50%;
font-size: 0.8rem;
margin-left: auto;
margin-right: auto;
width: 100%;
top: 35%;
font-size: 1.2rem;
font-weight: bold;
z-index: 99;
text-align: center;
color: gray;
}
#button-edit-thumbnail, #button-edit-header-image {
#button-delete-header,
#button-edit-header {
border-radius: 100px !important;
height: 40px !important;
width: 40px !important;
bottom: -20px;
left: -20px;
height: 30px !important;
width: 30px !important;
z-index: 99;
margin-left: 10px !important;
.icon {
display: inherit;
padding: 0;
margin: 0;
margin-top: 1px;
font-size: 18px;
}
}
.thumbnail-buttons-row {
display: inline-block;
padding: 8px 0px;
border-radius: 0px 0px 0px 4px;
font-size: 14px;
a { color: $tainacan-input-color; }
.text {
top: -3px;
position: relative;
}
i.mdi-24px.mdi-set, i.mdi-24px.mdi::before {
font-size: 20px;
}
text-align: right;
top: -15px;
position: relative;
}
}
}

View File

@ -62,6 +62,10 @@
<th>
<div class="th-wrap">{{ $i18n.get('label_created_by') }}</div>
</th>
<!-- Total Items -->
<th v-if="!isOnTrash">
<div class="th-wrap">{{ $i18n.get('label_total_items') }}</div>
</th>
<th class="actions-header">
&nbsp;
<!-- nothing to show on header for actions cell-->
@ -149,6 +153,21 @@
}"
v-html="collection.author_name" />
</td>
<!-- Total items -->
<td
@click="goToCollectionPage(collection.id)"
class="column-small-width column-align-right"
:label="$i18n.get('label_total_items')"
v-if="collection.total_items != undefined"
:aria-label="$i18n.get('label_total_items') + ': ' + getTotalItems(collection.total_items)">
<p
v-tooltip="{
content: getTotalItems(collection.total_items),
autoHide: false,
placement: 'auto-start'
}"
v-html="getTotalItems(collection.total_items)" />
</td>
<!-- Actions -->
<td
@click="goToCollectionPage(collection.id)"
@ -229,6 +248,9 @@ export default {
for (let i = 0; i < this.selectedCollections.length; i++)
this.selectedCollections.splice(i, 1, !this.allCollectionsOnPageSelected);
},
getTotalItems(total_items) {
return Number(total_items['publish']) + Number(total_items['private']);
},
deleteOneCollection(collectionId) {
this.$modal.open({
parent: this,
@ -361,7 +383,7 @@ export default {
.selection-control {
padding: 6px 0px 0px 13px;
padding: 6px 0px 0px 12px;
background: white;
height: 40px;

View File

@ -66,7 +66,7 @@
v-if="filter.filter_type != undefined">
<b-switch
size="is-small"
v-model="filter.enabled"
:value="filter.enabled"
@input="onChangeEnable($event, index)"/>
<a
:style="{ visibility: filter.collection_id != collectionId && !isRepositoryLevel? 'hidden' : 'visible' }"
@ -294,11 +294,11 @@ export default {
this.availableMetadatumList = availableMetadata;
},
onChangeEnable($event, index) {
this.activeFilterList[index].enabled = $event;
let filtersOrder = [];
for (let filter of this.activeFilterList) {
filtersOrder.push({'id': filter.id, 'enabled': filter.enabled});
}
filtersOrder[index].enabled = $event;
this.updateCollectionFiltersOrder({ collectionId: this.collectionId, filtersOrder: filtersOrder });
},
addMetadatumViaButton(metadatumType, metadatumIndex) {
@ -319,7 +319,7 @@ export default {
for (let filter of this.filterTypes) {
for (let supportedType of filter['supported_types']) {
if (choosenMetadatum.metadatum_type_object.primitive_type == supportedType)
if (choosenMetadatum.metadata_type_object.primitive_type == supportedType)
this.allowedFilterTypes.push(filter);
}
}
@ -442,7 +442,7 @@ export default {
this.isLoadingFilterTypes = false;
});
this.fetchFilters({collectionId: this.collectionId, isRepositoryLevel: this.isRepositoryLevel, isContextEdit: true, includeDisabled: 'yes' })
this.fetchFilters({collectionId: this.collectionId, isRepositoryLevel: this.isRepositoryLevel, isContextEdit: true, includeDisabled: true })
.then(() => {
this.isLoadingFilters = false;
// Needs to be done after activeFilterList exists to compare and remove chosen metadata.

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>
@ -56,14 +56,20 @@
</div>
<!-- Title -->
<p
v-for="(column, index) in tableMetadata"
:key="index"
v-if="column.display && column.metadata_type_object != undefined && (column.metadata_type_object.related_mapped_prop == 'title')"
class="metadata-title"
@click="goToItemPage(item)"
v-html="item.metadata != undefined ? renderMetadata(item.metadata, column) : ''"/>
<div class="metadata-title">
<p
v-tooltip="{
content: item.metadata != undefined ? renderMetadata(item.metadata, column) : '',
html: true,
autoHide: false,
placement: 'auto-start'
}"
v-for="(column, index) in tableMetadata"
:key="index"
v-if="column.display && column.metadata_type_object != undefined && (column.metadata_type_object.related_mapped_prop == 'title')"
@click="goToItemPage(item)"
v-html="item.metadata != undefined ? renderMetadata(item.metadata, column) : ''"/>
</div>
<!-- Thumbnail -->
<a
v-if="item.thumbnail != undefined"
@ -117,14 +123,20 @@
</div>
<!-- Title -->
<p
v-for="(column, index) in tableMetadata"
:key="index"
v-if="column.display && column.metadata_type_object != undefined && (column.metadata_type_object.related_mapped_prop == 'title')"
class="metadata-title"
@click="goToItemPage(item)"
v-html="item.metadata != undefined ? renderMetadata(item.metadata, column) : ''" />
<div class="metadata-title">
<p
v-tooltip="{
content: item.metadata != undefined ? renderMetadata(item.metadata, column) : '',
html: true,
autoHide: false,
placement: 'auto-start'
}"
v-for="(column, index) in tableMetadata"
:key="index"
v-if="column.display && column.metadata_type_object != undefined && (column.metadata_type_object.related_mapped_prop == 'title')"
@click="goToItemPage(item)"
v-html="item.metadata != undefined ? renderMetadata(item.metadata, column) : ''" />
</div>
<!-- Actions -->
<div
v-if="item.current_user_can_edit"
@ -152,19 +164,134 @@
<div
class="media"
@click="goToItemPage(item)">
<a
<img
v-if="item.thumbnail != undefined"
@click="goToItemPage(item)">
<img :src="item['thumbnail'].medium_large ? item['thumbnail'].medium_large : thumbPlaceholderPath">
</a>
:src="item['thumbnail'].medium_large ? item['thumbnail'].medium_large : thumbPlaceholderPath">
<div class="list-metadata media-body">
<!-- Description -->
<p
v-tooltip="{
content: item.metadata != undefined ? renderMetadata(item.metadata, column) : '',
html: true,
autoHide: false,
placement: 'auto-start'
}"
v-if="
column.metadata_type_object != undefined &&
(column.metadata_type_object.related_mapped_prop == 'description')"
v-for="(column, index) in tableMetadata"
:key="index"
class="metadata-description"
v-html="(item.metadata != undefined && item.metadata[column.slug] != undefined) ? getLimitedDescription(item.metadata[column.slug].value_as_string) : ''" />
<br>
<!-- Author and Creation Date-->
<p
v-tooltip="{
content: column.metadatum == 'row_author' || column.metadatum == 'row_creation',
html: false,
autoHide: false,
placement: 'auto-start'
}"
v-for="(column, index) in tableMetadata"
:key="index"
v-if="column.metadatum == 'row_author' || column.metadatum == 'row_creation'"
class="metadata-author-creation">
{{ column.metadatum == 'row_author' ? $i18n.get('info_created_by') + ' ' + item[column.slug] : $i18n.get('info_date') + ' ' + item[column.slug] }}
</p>
</div>
</div>
</div>
</div>
<!-- RECORDS VIEW MODE -->
<div
class="tainacan-records-container"
v-if="viewMode == 'records'">
<div
:key="index"
v-for="(item, index) of items"
:class="{ 'selected-record': selectedItems[index] }"
class="tainacan-record">
<!-- Checkbox -->
<div
:class="{ 'is-selecting': isSelectingItems }"
class="record-checkbox">
<b-checkbox
size="is-small"
v-model="selectedItems[index]"/>
</div>
<!-- Title -->
<div class="metadata-title">
<p
v-tooltip="{
content: item.metadata != undefined ? renderMetadata(item.metadata, column) : '',
html: true,
autoHide: false,
placement: 'auto-start'
}"
v-for="(column, index) in tableMetadata"
:key="index"
v-if="column.display && column.metadata_type_object != undefined && (column.metadata_type_object.related_mapped_prop == 'title')"
@click="goToItemPage(item)"
v-html="item.metadata != undefined ? renderMetadata(item.metadata, column) : ''" />
</div>
<!-- Actions -->
<div
v-if="item.current_user_can_edit"
class="actions-area"
:label="$i18n.get('label_actions')">
<a
id="button-edit"
:aria-label="$i18n.getFrom('items','edit_item')"
@click.prevent.stop="goToItemEditPage(item.id)">
<b-icon
type="is-secondary"
icon="pencil"/>
</a>
<a
id="button-delete"
:aria-label="$i18n.get('label_button_delete')"
@click.prevent.stop="deleteOneItem(item.id)">
<b-icon
type="is-secondary"
:icon="!isOnTrash ? 'delete' : 'delete-forever'"/>
</a>
</div>
<!-- Remaining metadata -->
<div
class="media"
@click="goToItemPage(item)">
<img
v-if="item.thumbnail != undefined"
:src="item['thumbnail'].medium_large ? item['thumbnail'].medium_large : thumbPlaceholderPath">
<div class="list-metadata media-body">
<span
v-for="(column, index) in tableMetadata"
:key="index"
v-if="column.display && column.slug != 'thumbnail' && column.metadata_type_object != undefined && (column.metadata_type_object.related_mapped_prop != 'title')">
<h3 class="metadata-label">{{ column.name }}</h3>
<h3
v-tooltip="{
content: column.name,
html: false,
autoHide: false,
placement: 'auto-start'
}"
class="metadata-label">{{ column.name }}</h3>
<p
v-tooltip="{
content: item.metadata != undefined ? renderMetadata(item.metadata, column) : '',
html: true,
autoHide: false,
placement: 'auto-start'
}"
v-html="item.metadata != undefined ? renderMetadata(item.metadata, column) : ''"
class="metadata-value"/>
</span>
@ -263,7 +390,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
@ -459,6 +586,9 @@ export default {
} else {
return metadata.value_as_html;
}
},
getLimitedDescription(description) {
return description.length > 120 ? description.substring(0, 117) + '...' : description;
}
}
}
@ -469,10 +599,11 @@ export default {
@import "../../scss/_variables.scss";
@import "../../scss/_view-mode-grid.scss";
@import "../../scss/_view-mode-cards.scss";
@import "../../scss/_view-mode-records.scss";
.selection-control {
padding: 6px 0px 0px 13px;
padding: 6px 0px 0px 12px;
background: white;
height: 40px;

View File

@ -70,7 +70,7 @@
v-if="metadatum.id !== undefined">
<b-switch
size="is-small"
v-model="metadatum.enabled"
:value="metadatum.enabled"
@input="onChangeEnable($event, index)"/>
<a
:style="{ visibility:
@ -358,11 +358,11 @@ export default {
this.updateCollectionMetadataOrder({ collectionId: this.collectionId, metadataOrder: metadataOrder });
},
onChangeEnable($event, index) {
this.activeMetadatumList[index].enabled = $event;
let metadataOrder = [];
for (let metadatum of this.activeMetadatumList) {
metadataOrder.push({'id': metadatum.id, 'enabled': metadatum.enabled});
}
metadataOrder[index].enabled = $event;
this.updateCollectionMetadataOrder({ collectionId: this.collectionId, metadataOrder: metadataOrder });
},
addMetadatumViaButton(metadatumType) {
@ -405,6 +405,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));
@ -515,7 +516,7 @@ export default {
this.collectionId = this.$route.params.collectionId;
this.fetchMetadata({collectionId: this.collectionId, isRepositoryLevel: this.isRepositoryLevel, isContextEdit: true})
this.fetchMetadata({collectionId: this.collectionId, isRepositoryLevel: this.isRepositoryLevel, isContextEdit: true, includeDisabled: true})
.then(() => {
this.isLoadingMetadata = false;
})

View File

@ -1,21 +1,21 @@
<template>
<div
v-if="totalCategories > 0 && !isLoading"
v-if="total > 0 && !isLoading"
class="table-container">
<div class="selection-control">
<div class="field select-all is-pulled-left">
<span>
<b-checkbox
@click.native="selectAllCategoriesOnPage()"
:value="allCategoriesOnPageSelected">{{ $i18n.get('label_select_all_categories_page') }}</b-checkbox>
@click.native="selectAllOnPage()"
:value="allOnPageSelected">{{ $i18n.get('label_select_all_taxonomies_page') }}</b-checkbox>
</span>
</div>
<div class="field is-pulled-right">
<b-dropdown
position="is-bottom-left"
v-if="categories[0].current_user_can_edit"
:disabled="!isSelectingCategories"
v-if="taxonomies[0].current_user_can_edit"
:disabled="!isSelecting"
id="bulk-actions-dropdown">
<button
class="button is-white"
@ -26,10 +26,10 @@
<b-dropdown-item
id="item-delete-selected-items"
@click="deleteSelectedCategories()">
{{ $i18n.get('label_delete_selected_categories') }}
@click="deleteSelected()">
{{ $i18n.get('label_delete_selected_taxonomies') }}
</b-dropdown-item>
<b-dropdown-item disabled>{{ $i18n.get('label_edit_selected_categories') + ' (Not ready)' }}
<b-dropdown-item disabled>{{ $i18n.get('label_edit_selected_taxonomies') + ' (Not ready)' }}
</b-dropdown-item>
</b-dropdown>
</div>
@ -61,55 +61,55 @@
</thead>
<tbody>
<tr
:class="{ 'selected-row': selectedCategories[index] }"
:class="{ 'selected-row': selected[index] }"
:key="index"
v-for="(category, index) of categories">
v-for="(taxonomy, index) of taxonomies">
<!-- Checking list -->
<td
:class="{ 'is-selecting': isSelectingCategories }"
:class="{ 'is-selecting': isSelecting }"
class="checkbox-cell">
<b-checkbox
size="is-small"
v-model="selectedCategories[index]"/>
v-model="selected[index]"/>
</td>
<!-- Name -->
<td
class="column-default-width column-main-content"
@click="goToCategoryEditPage(category.id)"
@click="goToTaxonomyEditPage(taxonomy.id)"
:label="$i18n.get('label_name')"
:aria-label="$i18n.get('label_name') + ': ' + category.name">
:aria-label="$i18n.get('label_name') + ': ' + taxonomy.name">
<p
v-tooltip="{
content: category.name,
content: taxonomy.name,
autoHide: false,
placement: 'auto-start'
}">
{{ category.name }}</p>
{{ taxonomy.name }}</p>
</td>
<!-- Description -->
<td
class="column-large-width"
@click="goToCategoryEditPage(category.id)"
@click="goToTaxonomyEditPage(taxonomy.id)"
:label="$i18n.get('label_description')"
:aria-label="$i18n.get('label_description') + ': ' + category.description">
:aria-label="$i18n.get('label_description') + ': ' + taxonomy.description">
<p
v-tooltip="{
content: category.description,
content: taxonomy.description,
autoHide: false,
placement: 'auto-start'
}">
{{ category.description }}</p>
{{ taxonomy.description }}</p>
</td>
<!-- Actions -->
<td
@click="goToCategoryEditPage(category.id)"
@click="goToTaxonomyEditPage(taxonomy.id)"
class="actions-cell column-default-width"
:label="$i18n.get('label_actions')">
<div class="actions-container">
<a
id="button-edit"
:aria-label="$i18n.getFrom('categories','edit_item')"
@click="goToCategoryEditPage(category.id)">
:aria-label="$i18n.getFrom('taxonomies','edit_item')"
@click="goToTaxonomyEditPage(taxonomy.id)">
<b-icon
type="is-secondary"
icon="pencil"/>
@ -117,7 +117,7 @@
<a
id="button-delete"
:aria-label="$i18n.get('label_button_delete')"
@click.prevent.stop="deleteOneCategory(category.id)">
@click.prevent.stop="deleteOneTaxonomy(taxonomy.id)">
<b-icon
type="is-secondary"
icon="delete"/>
@ -136,76 +136,76 @@
import CustomDialog from '../other/custom-dialog.vue';
export default {
name: 'CategoriesList',
name: 'List',
data() {
return {
selectedCategories: [],
allCategoriesOnPageSelected: false,
isSelectingCategories: false
selected: [],
allOnPageSelected: false,
isSelecting: false
}
},
props: {
isLoading: false,
totalCategories: 0,
total: 0,
page: 1,
categoriesPerPage: 12,
categories: Array
taxonomiesPerPage: 12,
taxonomies: Array
},
watch: {
categories() {
this.selectedCategories = [];
for (let i = 0; i < this.categories.length; i++)
this.selectedCategories.push(false);
taxonomies() {
this.selected = [];
for (let i = 0; i < this.taxonomies.length; i++)
this.selected.push(false);
},
selectedCategories() {
selected() {
let allSelected = true;
let isSelecting = false;
for (let i = 0; i < this.selectedCategories.length; i++) {
if (this.selectedCategories[i] == false) {
for (let i = 0; i < this.selected.length; i++) {
if (this.selected[i] == false) {
allSelected = false;
} else {
isSelecting = true;
}
}
this.allCategoriesOnPageSelected = allSelected;
this.isSelectingCategories = isSelecting;
this.allOnPageSelected = allSelected;
this.isSelecting = isSelecting;
}
},
methods: {
...mapActions('category', [
'deleteCategory'
...mapActions('taxonomy', [
'deleteTaxonomy'
]),
selectAllCategoriesOnPage() {
for (let i = 0; i < this.selectedCategories.length; i++)
this.selectedCategories.splice(i, 1, !this.allCategoriesOnPageSelected);
selectAllOnPage() {
for (let i = 0; i < this.selected.length; i++)
this.selected.splice(i, 1, !this.allOnPageSelected);
},
deleteOneCategory(categoryId) {
deleteOneTaxonomy(taxonomyId) {
this.$modal.open({
parent: this,
component: CustomDialog,
props: {
icon: 'alert',
title: this.$i18n.get('label_warning'),
message: this.$i18n.get('info_warning_category_delete'),
message: this.$i18n.get('info_warning_taxonomy_delete'),
onConfirm: () => {
this.deleteCategory(categoryId)
this.deleteTaxonomy(taxonomyId)
.then(() => {
// this.$toast.open({
// duration: 3000,
// message: this.$i18n.get('info_category_deleted'),
// message: this.$i18n.get('info_taxonomy_deleted'),
// position: 'is-bottom',
// type: 'is-secondary',
// queue: true
// });
for (let i = 0; i < this.selectedCategories.length; i++) {
if (this.selectedCategories[i].id === this.categoryId)
this.selectedCategories.splice(i, 1);
for (let i = 0; i < this.selected.length; i++) {
if (this.selected[i].id === this.taxonomyId)
this.selected.splice(i, 1);
}
})
.catch(() => {
// this.$toast.open({
// duration: 3000,
// message: this.$i18n.get('info_error_deleting_category'),
// message: this.$i18n.get('info_error_deleting_taxonomy'),
// position: 'is-bottom',
// type: 'is-danger',
// queue: true
@ -215,24 +215,24 @@
}
});
},
deleteSelectedCategories() {
deleteSelected() {
this.$modal.open({
parent: this,
component: CustomDialog,
props: {
icon: 'alert',
title: this.$i18n.get('label_warning'),
message: this.$i18n.get('info_warning_selected_categories_delete'),
message: this.$i18n.get('info_warning_selected_taxonomies_delete'),
onConfirm: () => {
for (let i = 0; i < this.categories.length; i++) {
if (this.selectedCategories[i]) {
this.deleteCategory(this.categories[i].id)
for (let i = 0; i < this.taxonomies.length; i++) {
if (this.selected[i]) {
this.deleteTaxonomy(this.taxonomies[i].id)
.then(() => {
// this.loadCategories();
// this.load();
// this.$toast.open({
// duration: 3000,
// message: this.$i18n.get('info_category_deleted'),
// message: this.$i18n.get('info_taxonomy_deleted'),
// position: 'is-bottom',
// type: 'is-secondary',
// queue: false
@ -240,7 +240,7 @@
}).catch(() => {
// this.$toast.open({
// duration: 3000,
// message: this.$i18n.get('info_error_deleting_category'),
// message: this.$i18n.get('info_error_deleting_taxonomy'),
// position: 'is-bottom',
// type: 'is-danger',
// queue: false
@ -248,16 +248,16 @@
});
}
}
this.allCategoriesOnPageSelected = false;
this.allOnPageSelected = false;
}
}
});
},
goToCategoryPage(categoryId) {
this.$router.push(this.$routerHelper.getCategoryPath(categoryId));
goToTaxonomyPage(taxonomyId) {
this.$router.push(this.$routerHelper.getTaxonomyPath(taxonomyId));
},
goToCategoryEditPage(categoryId) {
this.$router.push(this.$routerHelper.getCategoryEditPath(categoryId));
goToTaxonomyEditPage(taxonomyId) {
this.$router.push(this.$routerHelper.getTaxonomyEditPath(taxonomyId));
}
}
}
@ -269,7 +269,7 @@
.selection-control {
padding: 6px 0px 0px 13px;
padding: 6px 0px 0px 12px;
background: white;
height: 40px;

View File

@ -1,81 +1,93 @@
<template>
<div>
<b-field
:addons="false"
:label="$i18n.get('label_category_terms')">
<div class="columns">
<div class="column">
<button
class="button is-secondary is-pulled-right"
class="button is-secondary"
type="button"
@click="addNewTerm()">
{{ $i18n.get('label_new_term') }}
</button>
</b-field>
<br>
<br>
<div
class="term-item"
:class="{
'not-sortable-item': term.opened || !term.saved,
'not-focusable-item': term.opened
}"
:style="{'margin-left': (term.depth * 20) + 'px'}"
v-for="(term, index) in orderedTermsList"
:key="term.id">
<span
class="term-name"
:class="{'is-danger': formWithErrors == term.id }">
{{ term.saved && !term.opened ? term.name : getUnsavedTermName(term) }}
</span>
<span
v-if="term.id != undefined"
class="label-details">
<span
class="not-saved"
v-if="!term.saved">
{{ $i18n.get('info_not_saved') }}
</span>
</span>
<span class="controls" >
<!--
<b-field class="order-area">
<button
class="button is-success is-small"
type="button"
:href="categoryPath + '/' + term.slug">
{{ $i18n.get('label_view_term') }}
:disabled="orderedTermsList.length <= 0 || isLoadingTerms || isEditingTerm"
class="button is-white is-small"
@click="onChangeOrder()">
<b-icon
class="gray-icon"
:icon="order === 'ASC' ? 'sort-ascending' : 'sort-descending'"/>
</button>
-->
</b-field>
<br>
<br>
<div
class="term-item"
:class="{
'not-sortable-item': term.opened || !term.saved,
'not-focusable-item': term.opened
}"
:style="{'margin-left': (term.depth * 40) + 'px'}"
v-for="(term, index) in orderedTermsList"
:key="term.id">
<a
class="is-small"
class="is-medium"
type="button"
@click="addNewChildTerm(term, index)">
<b-icon
size="is-small"
icon="plus-circle"/>
{{ $i18n.get('label_new_child') }}
<b-icon icon="plus-circle"/>
</a>
<span
class="term-name"
:class="{'is-danger': formWithErrors == term.id }">
{{ term.saved && !term.opened ? term.name : getUnsavedTermName(term) }}
</span>
<span
v-if="term.id != undefined"
class="label-details">
<span
class="not-saved"
v-if="!term.saved">
{{ $i18n.get('info_not_saved') }}
</span>
</span>
<span class="controls" >
<!--
<button
class="button is-success is-small"
type="button"
:href="taxonomyPath + '/' + term.slug">
{{ $i18n.get('label_view_term') }}
</button>
-->
<a @click.prevent="editTerm(term, index)">
<b-icon
type="is-gray"
icon="pencil"/>
</a>
<a
@click.prevent="tryToRemoveTerm(term)">
<b-icon
type="is-gray"
icon="delete"/>
</a>
</span>
<div v-show="term.opened">
<term-edition-form
:category-id="categoryId"
@onEditionFinished="onTermEditionFinished()"
@onEditionCanceled="onTermEditionCanceled(term)"
@onErrorFound="formWithErrors = term.id"
:edit-form="term"/>
<a @click.prevent="editTerm(term, index)">
<b-icon
type="is-secondary"
icon="pencil"/>
</a>
<a
@click.prevent="tryToRemoveTerm(term)">
<b-icon
type="is-secondary"
icon="delete"/>
</a>
</span>
</div>
</div>
<div
class="column"
:key="index"
v-for="(term, index) in orderedTermsList"
v-show="term.opened">
<term-edition-form
:taxonomy-id="taxonomyId"
@onEditionFinished="onTermEditionFinished()"
@onEditionCanceled="onTermEditionCanceled(term)"
@onErrorFound="formWithErrors = term.id"
:edit-form="term"/>
</div>
<b-loading
:active.sync="isLoadingTerms"
@ -93,13 +105,14 @@ export default {
data(){
return {
isLoadingTerms: false,
isEditingTerm: false,
formWithErrors: '',
orderedTermsList: []
orderedTermsList: [],
order: 'asc'
}
},
props: {
categoryId: String,
//categoryPath: ''
taxonomyId: String,
},
computed: {
termsList() {
@ -110,7 +123,7 @@ export default {
termsList() {
this.generateOrderedTerms();
},
categoryId() {
taxonomyId() {
this.loadTerms();
}
},
@ -118,17 +131,21 @@ export default {
TermEditionForm
},
methods: {
...mapActions('category', [
...mapActions('taxonomy', [
'updateTerm',
'deleteTerm',
'fetchTerms'
]),
...mapGetters('category',[
...mapGetters('taxonomy',[
'getTerms'
]),
onChangeOrder() {
this.order == 'asc' ? this.order = 'desc' : this.order = 'asc';
this.loadTerms();
},
addNewTerm() {
let newTerm = {
categoryId: this.categoryId,
taxonomyId: this.taxonomyId,
name: this.$i18n.get('label_term_without_name'),
description: '',
parent: 0,
@ -141,7 +158,7 @@ export default {
},
addNewChildTerm(parent, parentIndex) {
let newTerm = {
categoryId: this.categoryId,
taxonomyId: this.taxonomyId,
name: this.$i18n.get('label_term_without_name'),
description: '',
parent: parent.id,
@ -153,7 +170,7 @@ export default {
this.editTerm(newTerm, parentIndex + 1);
},
editTerm(term, index) {
this.isEditingTerm = true;
if (!term.opened) {
for (let i = 0; i < this.orderedTermsList.length; i++) {
@ -238,7 +255,7 @@ export default {
}
} else {
this.deleteTerm({categoryId: this.categoryId, termId: term.id})
this.deleteTerm({taxonomyId: this.taxonomyId, termId: term.id})
.then(() => {
})
@ -250,7 +267,7 @@ export default {
for (let orphanTerm of this.termsList) {
if (orphanTerm.parent == term.id) {
this.updateTerm({
categoryId: this.categoryId,
taxonomyId: this.taxonomyId,
termId: orphanTerm.id,
name: orphanTerm.name,
description: orphanTerm.description,
@ -264,7 +281,7 @@ export default {
}
},
onTermEditionFinished() {
this.isEditingTerm = false;
},
onTermEditionCanceled(term) {
@ -277,6 +294,7 @@ export default {
if (term.id == 'new')
this.removeTerm(term);
}
this.isEditingTerm = false;
},
buildOrderedTermsList(parentId, termDepth) {
@ -314,7 +332,7 @@ export default {
},
loadTerms() {
this.isLoadingTerms = true;
this.fetchTerms(this.categoryId)
this.fetchTerms({ taxonomyId: this.taxonomyId, fetchOnly: '', search: '', all: '', order: this.order})
.then(() => {
// Fill this.form data with current data.
this.isLoadingTerms = false;
@ -326,7 +344,7 @@ export default {
}
},
created() {
if (this.categoryId !== String) {
if (this.taxonomyId !== String) {
this.loadTerms();
}
}
@ -338,24 +356,30 @@ export default {
@import "../../scss/_variables.scss";
.order-area {
display: inline-block;
padding: 4px;
margin-left: 30px;
.gray-icon, .gray-icon .icon {
color: $tainacan-placeholder-color !important;
}
.gray-icon .icon i::before, .gray-icon i::before {
font-size: 21px !important;
}
}
.term-item {
font-size: 14px;
border-left: 1px solid #eee;
padding: 0.7em 0.9em;
margin: 4px;
min-height: 40px;
display: block;
position: relative;
//cursor: grab;
.handle {
padding-right: 6em;
}
.grip-icon {
fill: $gray;
top: 2px;
position: relative;
}
.term-name {
text-overflow: ellipsis;
overflow-x: hidden;
@ -402,9 +426,6 @@ export default {
cursor: default;
background-color: white !important;
.handle .label-details, .handle .icon {
color: $gray !important;
}
}
&.not-focusable-item, &.not-focusable-item:hover {
cursor: default;
@ -412,9 +433,6 @@ export default {
.term-name {
color: $primary;
}
.handle .label-details, .handle .icon {
color: $gray !important;
}
}
}

View File

@ -57,11 +57,11 @@
<router-link
tag="a"
to="/taxonomies"
:class="activeRoute == 'CategoriesPage' ? 'is-active':''">
:class="activeRoute == 'Page' ? 'is-active':''">
<b-icon
size="is-small"
icon="shape"/>
<span class="menu-text">{{ $i18n.getFrom('categories', 'name') }}</span>
<span class="menu-text">{{ $i18n.getFrom('taxonomies', 'name') }}</span>
</router-link>
</li>
<li>
@ -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

@ -141,11 +141,11 @@ export default {
...mapGetters('item', [
'getItemTitle'
]),
...mapActions('category', [
'fetchCategoryName'
...mapActions('taxonomy', [
'fetchTaxonomyName'
]),
...mapGetters('category', [
'getCategoryName'
...mapGetters('taxonomy', [
'getTaxonomyName'
]),
...mapActions('event', [
'fetchEventTitle'
@ -171,8 +171,8 @@ export default {
.catch((error) => this.$console.error(error));
break;
case 'taxonomies':
this.fetchCategoryName(this.arrayRealPath[i])
.then(categoryName => this.arrayViewPath.splice(i, 1, categoryName))
this.fetchTaxonomyName(this.arrayRealPath[i])
.then(taxonomyName => this.arrayViewPath.splice(i, 1, taxonomyName))
.catch((error) => this.$console.error(error));
break;
case 'events':
@ -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: [],
@ -58,15 +57,18 @@ export default {
...mapGetters('item', [
'getItemTitle'
]),
...mapActions('category', [
'fetchCategoryName'
...mapActions('taxonomy', [
'fetchTaxonomyName'
]),
...mapGetters('category', [
'getCategoryName'
...mapGetters('taxonomy', [
'getTaxonomyName'
]),
...mapActions('event', [
'fetchEventTitle'
]),
...mapActions('importer', [
'fetchAvailableImporters'
]),
generateViewPath() {
for (let i = 0; i < this.arrayRealPath.length; i++) {
@ -87,8 +89,8 @@ export default {
.catch((error) => this.$console.error(error));
break;
case 'taxonomies':
this.fetchCategoryName(this.arrayRealPath[i])
.then(categoryName => this.arrayViewPath.splice(i, 1, categoryName))
this.fetchTaxonomyName(this.arrayRealPath[i])
.then(taxonomyName => this.arrayViewPath.splice(i, 1, taxonomyName))
.catch((error) => this.$console.error(error));
break;
case 'events':
@ -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

@ -14,10 +14,10 @@ import Selectbox from '../../classes/metadata-types/selectbox/Selectbox.vue';
import Numeric from '../../classes/metadata-types/numeric/Numeric.vue';
import Date from '../../classes/metadata-types/date/Date.vue';
import Relationship from '../../classes/metadata-types/relationship/Relationship.vue';
import Category from '../../classes/metadata-types/category/Category.vue';
import Taxonomy from '../../classes/metadata-types/taxonomy/Taxonomy.vue';
import FormRelationship from '../../classes/metadata-types/relationship/FormRelationship.vue';
import FormCategory from '../../classes/metadata-types/category/FormCategory.vue';
import FormTaxonomy from '../../classes/metadata-types/taxonomy/FormTaxonomy.vue';
import FormSelectbox from '../../classes/metadata-types/selectbox/FormSelectbox.vue';
import FilterCustomInterval from '../../classes/filter-types/custom-interval/CustomInterval.vue';
@ -26,9 +26,9 @@ import FilterAutocomplete from '../../classes/filter-types/autocomplete/Autocomp
import FilterCheckbox from '../../classes/filter-types/checkbox/Checkbox.vue';
import FilterTaginput from '../../classes/filter-types/taginput/Taginput.vue';
import FilterCategoryCheckbox from '../../classes/filter-types/category/Checkbox.vue';
import FilterCategoryTaginput from '../../classes/filter-types/category/Taginput.vue';
import FilterCategorySelectbox from '../../classes/filter-types/category/Selectbox.vue';
import FilterTaxonomyCheckbox from '../../classes/filter-types/taxonomy/Checkbox.vue';
import FilterTaxonomyTaginput from '../../classes/filter-types/taxonomy/Taginput.vue';
import FilterTaxonomySelectbox from '../../classes/filter-types/taxonomy/Selectbox.vue';
import TainacanFormItem from '../../classes/metadata-types/tainacan-form-item.vue';
import TainacanFiltersList from '../../classes/filter-types/tainacan-filter-item.vue';
@ -61,10 +61,10 @@ Vue.component('tainacan-selectbox', Selectbox);
Vue.component('tainacan-numeric', Numeric);
Vue.component('tainacan-date', Date);
Vue.component('tainacan-relationship', Relationship);
Vue.component('tainacan-category', Category);
Vue.component('tainacan-taxonomy', Taxonomy);
Vue.component('tainacan-form-relationship', FormRelationship);
Vue.component('tainacan-form-category', FormCategory);
Vue.component('tainacan-form-taxonomy', FormTaxonomy);
Vue.component('tainacan-form-selectbox', FormSelectbox);
Vue.component('tainacan-form-item', TainacanFormItem);
Vue.component('tainacan-filter-item', TainacanFiltersList);
@ -75,9 +75,9 @@ Vue.component('tainacan-filter-selectbox', FilterSelectbox);
Vue.component('tainacan-filter-autocomplete', FilterAutocomplete);
Vue.component('tainacan-filter-checkbox', FilterCheckbox);
Vue.component('tainacan-filter-taginput', FilterTaginput);
Vue.component('tainacan-filter-category-checkbox', FilterCategoryCheckbox);
Vue.component('tainacan-filter-category-taginput', FilterCategoryTaginput);
Vue.component('tainacan-filter-category-selectbox', FilterCategorySelectbox);
Vue.component('tainacan-filter-taxonomy-checkbox', FilterTaxonomyCheckbox);
Vue.component('tainacan-filter-taxonomy-taginput', FilterTaxonomyTaginput);
Vue.component('tainacan-filter-taxonomy-selectbox', FilterTaxonomySelectbox);
/* Others */
Vue.component('help-button', HelpButton);

View File

@ -9,15 +9,17 @@ import ItemsPage from '../pages/lists/items-page.vue'
import ItemPage from '../pages/singles/item-page.vue'
import MetadataPage from '../pages/lists/metadata-page.vue'
import FiltersPage from '../pages/lists/filters-page.vue'
import CategoriesPage from '../pages/lists/categories-page.vue'
import CategoryPage from '../pages/singles/category-page.vue'
import Page from '../pages/lists/taxonomies-page.vue'
import TaxonomyPage from '../pages/singles/taxonomy-page.vue'
import EventsPage from '../pages/lists/events-page.vue'
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 CategoryEditionForm from '../components/edition/category-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'
@ -58,14 +60,17 @@ const routes = [
{ path: '/metadata', name: 'MetadataPage', component: MetadataPage, meta: {title: i18nGet('title_repository_metadata_page'), icon: 'format-list-checks'} },
{ path: '/taxonomies', name: 'CategoriesPage', component: CategoriesPage, meta: {title: i18nGet('title_categories_page'), icon: 'shape'} },
{ path: '/taxonomies/new', name: 'CategoryCreationForm', component: CategoryEditionForm, meta: {title: i18nGet('title_create_category_page'), icon: 'shape'} },
{ path: '/taxonomies/:categoryId/edit', name: 'CategoryEditionForm', component: CategoryEditionForm, meta: {title: i18nGet('title_category_edition_page'), icon: 'shape'} },
{ path: '/taxonomies/:categoryId', name: 'CategoryPage', component: CategoryPage, meta: {title: i18nGet('title_category_page'), icon: 'shape'} },
{ path: '/taxonomies', name: 'Page', component: Page, meta: {title: i18nGet('title_taxonomies_page'), icon: 'shape'} },
{ path: '/taxonomies/new', name: 'TaxonomyCreationForm', component: TaxonomyEditionForm, meta: {title: i18nGet('title_create_taxonomy_page'), icon: 'shape'} },
{ path: '/taxonomies/:taxonomyId/edit', name: 'TaxonomyEditionForm', component: TaxonomyEditionForm, meta: {title: i18nGet('title_taxonomy_edition_page'), icon: 'shape'} },
{ path: '/taxonomies/:taxonomyId', name: 'TaxonomyPage', component: TaxonomyPage, meta: {title: i18nGet('title_taxonomy_page'), icon: 'shape'} },
{ 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

@ -10,10 +10,10 @@ import Selectbox from '../../classes/metadata-types/selectbox/Selectbox.vue';
import Numeric from '../../classes/metadata-types/numeric/Numeric.vue';
import Date from '../../classes/metadata-types/date/Date.vue';
import Relationship from '../../classes/metadata-types/relationship/Relationship.vue';
import Category from '../../classes/metadata-types/category/Category.vue';
import Taxonomy from '../../classes/metadata-types/taxonomy/Taxonomy.vue';
import FormRelationship from '../../classes/metadata-types/relationship/FormRelationship.vue';
import FormCategory from '../../classes/metadata-types/category/FormCategory.vue';
import FormTaxonomy from '../../classes/metadata-types/taxonomy/FormTaxonomy.vue';
import FormSelectbox from '../../classes/metadata-types/selectbox/FormSelectbox.vue';
import FilterCustomInterval from '../../classes/filter-types/custom-interval/CustomInterval.vue';
@ -22,15 +22,16 @@ import FilterAutocomplete from '../../classes/filter-types/autocomplete/Autocomp
import FilterCheckbox from '../../classes/filter-types/checkbox/Checkbox.vue';
import FilterTaginput from '../../classes/filter-types/taginput/Taginput.vue';
import FilterCategoryCheckbox from '../../classes/filter-types/category/Checkbox.vue';
import FilterCategoryTaginput from '../../classes/filter-types/category/Taginput.vue';
import FilterCategorySelectbox from '../../classes/filter-types/category/Selectbox.vue';
import FilterTaxonomyCheckbox from '../../classes/filter-types/taxonomy/Checkbox.vue';
import FilterTaxonomyTaginput from '../../classes/filter-types/taxonomy/Taginput.vue';
import FilterTaxonomySelectbox from '../../classes/filter-types/taxonomy/Selectbox.vue';
import TaincanFormItem from '../../classes/metadata-types/tainacan-form-item.vue';
import TaincanFiltersList from '../../classes/filter-types/tainacan-filter-item.vue';
import ItemsPage from '../pages/lists/items-page.vue';
import ViewModeTable from '../../theme-helper/view-mode-table.vue';
import ViewModeCards from '../../theme-helper/view-mode-cards.vue';
import ViewModeRecords from '../../theme-helper/view-mode-records.vue';
// Remaining imports
import HelpButton from '../components/other/help-button.vue';
@ -55,10 +56,10 @@ Vue.component('tainacan-selectbox', Selectbox);
Vue.component('tainacan-numeric', Numeric);
Vue.component('tainacan-date', Date);
Vue.component('tainacan-relationship', Relationship);
Vue.component('tainacan-category', Category);
Vue.component('tainacan-taxonomy', Taxonomy);
Vue.component('tainacan-form-relationship', FormRelationship);
Vue.component('tainacan-form-category', FormCategory);
Vue.component('tainacan-form-taxonomy', FormTaxonomy);
Vue.component('tainacan-form-selectbox', FormSelectbox);
Vue.component('tainacan-form-item', TaincanFormItem);
Vue.component('tainacan-filter-item', TaincanFiltersList);
@ -69,9 +70,9 @@ Vue.component('tainacan-filter-selectbox', FilterSelectbox);
Vue.component('tainacan-filter-autocomplete', FilterAutocomplete);
Vue.component('tainacan-filter-checkbox', FilterCheckbox);
Vue.component('tainacan-filter-taginput', FilterTaginput);
Vue.component('tainacan-filter-category-checkbox', FilterCategoryCheckbox);
Vue.component('tainacan-filter-category-taginput', FilterCategoryTaginput);
Vue.component('tainacan-filter-category-selectbox', FilterCategorySelectbox);
Vue.component('tainacan-filter-taxonomy-checkbox', FilterTaxonomyCheckbox);
Vue.component('tainacan-filter-taxonomy-taginput', FilterTaxonomyTaginput);
Vue.component('tainacan-filter-taxonomy-selectbox', FilterTaxonomySelectbox);
/* Others */
Vue.component('help-button', HelpButton);
@ -81,6 +82,7 @@ Vue.component('items-page', ItemsPage);
// Oficial view modes
Vue.component('view-mode-table', ViewModeTable);
Vue.component('view-mode-cards', ViewModeCards);
Vue.component('view-mode-records', ViewModeRecords);
Vue.use(eventBusSearch, { store: store, router: routerTheme});

View File

@ -64,7 +64,7 @@ I18NPlugin.install = function (Vue, options = {}) {
return (string != undefined && string != null && string != '' ) ? string : "Invalid i18n key: " + tainacan_plugin.i18n[key];
},
getFrom(entity, key) {
if (entity == 'categories') // Temporary hack, while we decide this terminology...
if (entity == 'taxonomies') // Temporary hack, while we decide this terminology...
entity = 'taxonomies'
if (tainacan_plugin.i18n['entities_labels'][entity] == undefined)
return 'Invalid i18n entity: ' + entity;
@ -72,7 +72,7 @@ I18NPlugin.install = function (Vue, options = {}) {
return (string != undefined && string != null && string != '' ) ? string : "Invalid i18n key: " + key;
},
getHelperTitle(entity, key) {
if (entity == 'categories') // Temporary hack, while we decide this terminology...
if (entity == 'taxonomies') // Temporary hack, while we decide this terminology...
entity = 'taxonomies'
if (tainacan_plugin.i18n['helpers_label'][entity] == undefined)
return 'Invalid i18n entity: ' + entity;
@ -82,7 +82,7 @@ I18NPlugin.install = function (Vue, options = {}) {
return (string != undefined && string != null && string != '' ) ? string : "Invalid i18n helper object.";
},
getHelperMessage(entity, key) {
if (entity == 'categories') // Temporary hack, while we decide this terminology...
if (entity == 'taxonomies') // Temporary hack, while we decide this terminology...
entity = 'taxonomies'
if (tainacan_plugin.i18n['helpers_label'][entity] == undefined)
return 'Invalid i18n entity: ' + entity;
@ -105,40 +105,33 @@ UserPrefsPlugin.install = function (Vue, options = {}) {
'items_per_page': 12,
'collections_per_page': 12,
'taxonomies_per_page': 12,
'events_per_page': 12
'events_per_page': 12,
'order': 'DESC',
'order_by': {
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() {
wpApi.get('/users/me/')
.then( res => {
if (res.data.meta['tainacan_prefs'] == undefined || res.data.meta['tainacan_prefs'] == '') {
let data = {'meta': {'tainacan_prefs': JSON.stringify(this.tainacanPrefs)} };
wpApi.post('/users/me/', qs.stringify(data))
.then( updatedRes => {
let prefs = JSON.parse(updatedRes.data.meta['tainacan_prefs']);
this.tainacanPrefs = prefs;
});
} else {
let prefs = JSON.parse(res.data.meta['tainacan_prefs']);
this.tainacanPrefs = prefs;
}
if (tainacan_plugin.user_prefs == undefined || tainacan_plugin.user_prefs == '') {
let data = {'meta': {'tainacan_prefs': JSON.stringify(this.tainacanPrefs)} };
wpApi.post('/users/me/', qs.stringify(data))
.then( updatedRes => {
let prefs = JSON.parse(updatedRes.data.meta['tainacan_prefs']);
this.tainacanPrefs = prefs;
});
},
fetch(key) {
return new Promise(( resolve, reject ) => {
wpApi.get('/users/me/')
.then( res => {
let prefs = JSON.parse(res.data.meta['tainacan_prefs']);
this.tainacanPrefs[key] = prefs[key];
if (prefs[key]) {
resolve( prefs[key] );
} else {
reject('Key ' + key + 'does not exists in user preference.');
}
})
.catch(error => {
reject( { message: error, value: false});
});
});
} else {
let prefs = JSON.parse(tainacan_plugin.user_prefs);
this.tainacanPrefs = prefs;
}
},
get(key) {
return this.tainacanPrefs[key];
@ -154,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 => {
@ -162,7 +155,7 @@ UserPrefsPlugin.install = function (Vue, options = {}) {
});
});
},
clear() {
clean() {
let data = {'meta': {'tainacan_prefs': ''} };
wpApi.post('/users/me/', qs.stringify(data))
}
@ -194,11 +187,11 @@ RouterHelperPlugin.install = function (Vue, options = {}) {
getItemsPath(query) {
return '/items/?' + qs.stringify(query);
},
getCategoriesPath(query) {
getPath(query) {
return '/taxonomies/?' + qs.stringify(query);
},
getCategoryTermsPath(categoryId, query) {
return '/categoryId/' + categoryId + '/terms/?' + qs.stringify(query);
getTaxonomyTermsPath(taxonomyId, query) {
return '/taxonomyId/' + taxonomyId + '/terms/?' + qs.stringify(query);
},
getFiltersPath(query) {
return '/filters/?' + qs.stringify(query);
@ -209,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;
@ -219,11 +215,11 @@ RouterHelperPlugin.install = function (Vue, options = {}) {
getFilterPath(id) {
return '/filters/' + id;
},
getCategoryPath(id) {
getTaxonomyPath(id) {
return '/taxonomies/' + id;
},
getTermPath(categoryId, termId) {
return '/taxonomies/' + categoryId + '/terms/' + termId;
getTermPath(taxonomyId, termId) {
return '/taxonomies/' + taxonomyId + '/terms/' + termId;
},
getEventPath(id) {
return '/events/' + id;
@ -250,11 +246,11 @@ RouterHelperPlugin.install = function (Vue, options = {}) {
getNewFilterPath() {
return '/filters/new';
},
getNewCategoryPath() {
getNewTaxonomyPath() {
return '/taxonomies/new';
},
getNewTermPath(categoryId) {
return '/taxonomies/' + categoryId + '/terms/new';
getNewTermPath(taxonomyId) {
return '/taxonomies/' + taxonomyId + '/terms/new';
},
getNewEventPath() {
return '/events/new';
@ -269,15 +265,18 @@ RouterHelperPlugin.install = function (Vue, options = {}) {
getFilterEditPath(id) {
return '/filters/' + id + '/edit';
},
getCategoryEditPath(id) {
getTaxonomyEditPath(id) {
return '/taxonomies/' + id + '/edit';
},
getTermEditPath(categoryId, termId) {
return '/taxonomies/' + categoryId + '/terms/' + termId + '/edit';
getTermEditPath(taxonomyId, termId) {
return '/taxonomies/' + taxonomyId + '/terms/' + termId + '/edit';
},
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

@ -218,16 +218,14 @@ export default {
});
},
mounted(){
this.$userPrefs.fetch('collections_per_page')
.then((value) => {
if (this.collectionsPerPage != value) {
this.collectionsPerPage = value;
this.loadCollections;
}
})
.catch(() => {
if (this.collectionsPerPage != this.$userPrefs.get('collections_per_page'))
this.collectionsPerPage = this.$userPrefs.get('collections_per_page');
if (!this.collectionsPerPage) {
this.collectionsPerPage = 12;
this.$userPrefs.set('collections_per_page', 12);
});
}
this.loadCollections();
}
}

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"
@ -143,16 +147,13 @@
this.isRepositoryLevel = (this.$route.params.collectionId === undefined);
},
mounted(){
this.$userPrefs.fetch('events_per_page')
.then((value) => {
if (this.eventsPerPage != value) {
this.eventsPerPage = value;
this.loadEvents;
}
})
.catch(() => {
if (this.eventsPerPage != this.$userPrefs.get('events_per_page'))
this.eventsPerPage = this.$userPrefs.get('events_per_page');
if (!this.eventsPerPage) {
this.eventsPerPage = 12;
this.$userPrefs.set('events_per_page', 12);
});
}
this.loadEvents();
if (!this.isRepositoryLevel) {

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"/>
@ -134,16 +133,16 @@
{{ $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"
:mobile-modal="false"
:disabled="totalItems <= 0 || adminViewMode == 'grid'"
:disabled="totalItems <= 0 || adminViewMode == 'grid'|| adminViewMode == 'cards'"
class="show">
<button
class="button is-white"
@ -184,8 +183,20 @@
<option
v-for="metadatum in tableMetadata"
v-if="
metadatum.id === 'creation_date' ||
metadatum.id === 'author_name' || (
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' ||
metadatum.slug === 'author_name' || (
metadatum.id !== undefined &&
metadatum.metadata_type_object &&
metadatum.metadata_type_object.related_mapped_prop !== 'description' &&
@ -194,15 +205,17 @@
metadatum.metadata_type_object.primitive_type !== 'compound'
)"
:value="metadatum"
:key="metadatum.id">
:key="metadatum.slug">
{{ metadatum.name }}
</option>
</option> -->
</b-select>
<button
:disabled="totalItems <= 0"
class="button is-white is-small"
@click="onChangeOrder()">
<b-icon :icon="order === 'ASC' ? 'sort-ascending' : 'sort-descending'"/>
<b-icon
class="gray-icon"
:icon="order === 'ASC' ? 'sort-ascending' : 'sort-descending'"/>
</button>
</b-field>
</div>
@ -221,6 +234,7 @@
class="button is-white"
slot="trigger">
<span
class="gray-icon view-mode-icon"
v-if="registeredViewModes[viewMode] != undefined"
v-html="registeredViewModes[viewMode].icon"/>
&nbsp;&nbsp;&nbsp;{{ $i18n.get('label_visualization') }}
@ -231,7 +245,9 @@
:key="index"
:value="viewModeOption"
v-if="registeredViewModes[viewModeOption] != undefined">
<span v-html="registeredViewModes[viewModeOption].icon"/>
<span
class="gray-icon"
v-html="registeredViewModes[viewModeOption].icon"/>
{{ registeredViewModes[viewModeOption].label }}
</b-dropdown-item>
</b-dropdown>
@ -242,7 +258,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')">
@ -251,6 +267,7 @@
slot="trigger">
<span>
<b-icon
class="gray-icon view-mode-icon"
:icon="(adminViewMode == 'table' || adminViewMode == undefined) ?
'table' : (adminViewMode == 'cards' ?
'view-list' : 'view-grid')"/>
@ -259,15 +276,27 @@
<b-icon icon="menu-down" />
</button>
<b-dropdown-item :value="'table'">
<b-icon icon="table"/>
<b-icon
class="gray-icon"
icon="table"/>
{{ $i18n.get('label_table') }}
</b-dropdown-item>
<b-dropdown-item :value="'cards'">
<b-icon icon="view-list"/>
<b-icon
class="gray-icon"
icon="view-list"/>
{{ $i18n.get('label_cards') }}
</b-dropdown-item>
<b-dropdown-item :value="'records'">
<b-icon
class="gray-icon"
icon="view-module"/>
{{ $i18n.get('label_records') }}
</b-dropdown-item>
<b-dropdown-item :value="'grid'">
<b-icon icon="view-grid"/>
<b-icon
class="gray-icon"
icon="view-grid"/>
{{ $i18n.get('label_grid') }}
</b-dropdown-item>
</b-dropdown>
@ -275,27 +304,41 @@
</div>
</div>
<!-- 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>
<!-- --------------- -->
<!-- STATUS TABS, only on Admin -------- -->
@ -355,23 +398,51 @@
: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].component"/>
: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"
:is-loading="isLoadingItems"
:is="registeredViewModes[viewMode] != undefined ? registeredViewModes[viewMode].component : ''"/>
<!-- Empty Placeholder (only used in Admin) -->
<section
@ -399,17 +470,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>
@ -442,7 +512,6 @@
isHeaderShrinked: false,
localTableMetadata: [],
registeredViewModes: tainacan_plugin.registered_view_modes,
adminViewMode: 'table',
openAdvancedSearch: false,
advancedSearchResults: false,
}
@ -477,6 +546,9 @@
viewMode() {
return this.getViewMode();
},
adminViewMode() {
return this.getAdminViewMode();
},
orderBy() {
return this.getOrderBy();
},
@ -496,8 +568,8 @@
},
openAdvancedSearch(newValue){
if(newValue == false){
this.$router.push({query: {}});
location.reload();
this.$eventBusSearch.$emit('closeAdvancedSearch');
this.advancedSearchResults = false;
}
}
},
@ -524,7 +596,8 @@
'getOrderBy',
'getOrder',
'getViewMode',
'getTotalItems'
'getTotalItems',
'getAdminViewMode'
]),
updateSearch() {
this.$eventBusSearch.setSearchQuery(this.futureSearchQuery);
@ -541,6 +614,9 @@
onChangeViewMode(viewMode) {
this.$eventBusSearch.setViewMode(viewMode);
},
onChangeAdminViewMode(adminViewMode) {
this.$eventBusSearch.setAdminViewMode(adminViewMode);
},
onChangeDisplayedMetadata() {
let fetchOnlyMetadatumIds = [];
@ -557,16 +633,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({
@ -579,22 +658,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 = [];
@ -604,11 +689,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,
@ -625,13 +721,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'),
@ -639,22 +738,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;
@ -665,7 +756,7 @@
}
},
created() {
this.isOnTheme = (this.$route.name === null);
this.isRepositoryLevel = (this.collectionId === undefined);
@ -689,26 +780,44 @@
/* 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();
}
});
this.$eventBusSearch.setViewMode(this.defaultViewMode);
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;
}
},
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();
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) => {
@ -758,10 +867,10 @@
.filters-menu {
position: relative;
width: $filter-menu-width;
max-width: $filter-menu-width;
min-width: 180px;
min-height: 100%;
height: 100%;
background-color: $tainacan-input-background;
background-color: white;
padding: $page-small-side-padding;
float: left;
overflow-y: auto;
@ -841,7 +950,6 @@
padding-top: $page-small-top-padding;
padding-left: $page-side-padding;
padding-right: $page-side-padding;
border-bottom: 0.5px solid #ddd;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
@ -849,25 +957,41 @@
.search-control-item {
display: inline-block;
.button {
align-items: flex-start;
}
.field {
align-items: center;
}
#item-creation-options-dropdown {
margin-right: 80px;
.gray-icon, .gray-icon .icon {
color: $tainacan-placeholder-color !important;
}
.gray-icon .icon i::before, .gray-icon i::before {
font-size: 21px !important;
}
.view-mode-icon {
margin-right: 4px !important;
margin-top: 1px;
}
.dropdown-menu {
display: block;
div.dropdown-content {
padding: 0;
.metadata-options-container {
max-height: 240px;
overflow: auto;
}
.dropdown-item span{
vertical-align: sub;
}
.dropdown-item-apply {
width: 100%;
border-top: 1px solid #efefef;
@ -903,8 +1027,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

@ -7,16 +7,19 @@
v-if="$userCaps.hasCapability('edit_tainacan-taxonomies')">
<div class="header-item">
<router-link
id="button-create-category"
id="button-create-taxonomy"
tag="button"
class="button is-secondary"
:to="{ path: $routerHelper.getNewCategoryPath() }">
:to="{ path: $routerHelper.getNewTaxonomyPath() }">
{{ $i18n.getFrom('taxonomies', 'new_item') }}
</router-link>
</div>
</div>
<div class="above-subheader">
<b-loading
:active.sync="isLoading"
:can-cancel="false"/>
<div class="tabs">
<ul>
<li
@ -31,15 +34,15 @@
</ul>
</div>
<div>
<categories-list
<taxonomies-list
:is-loading="isLoading"
:total-categories="totalCategories"
:total="total"
:page="page"
:categories-per-page="taxonomiesPerPage"
:categories="categories"/>
:taxonomies-per-page="taxonomiesPerPage"
:taxonomies="taxonomies"/>
<!-- Empty state image -->
<div v-if="totalCategories <= 0 && !isLoading">
<div v-if="total <= 0 && !isLoading">
<section class="section">
<div class="content has-text-grey has-text-centered">
<p>
@ -47,16 +50,16 @@
icon="inbox"
size="is-large"/>
</p>
<p v-if="status == undefined || status == ''">{{ $i18n.get('info_no_category_created') }}</p>
<p v-if="status == 'draft'">{{ $i18n.get('info_no_category_draft') }}</p>
<p v-if="status == 'trash'">{{ $i18n.get('info_no_category_trash') }}</p>
<p v-if="status == undefined || status == ''">{{ $i18n.get('info_no_taxonomy_created') }}</p>
<p v-if="status == 'draft'">{{ $i18n.get('info_no_taxonomy_draft') }}</p>
<p v-if="status == 'trash'">{{ $i18n.get('info_no_taxonomy_trash') }}</p>
<router-link
v-if="status == undefined || status == ''"
id="button-create-category"
id="button-create-taxonomy"
tag="button"
class="button is-primary"
:to="{ path: $routerHelper.getNewCategoryPath() }">
{{ $i18n.getFrom('categories', 'new_item') }}
:to="{ path: $routerHelper.getNewTaxonomyPath() }">
{{ $i18n.getFrom('taxonomies', 'new_item') }}
</router-link>
</div>
</section>
@ -64,24 +67,24 @@
<!-- Footer -->
<div
class="pagination-area"
v-if="totalCategories > 0">
v-if="total > 0">
<div class="shown-items">
{{
$i18n.get('info_showing_categories') +
$i18n.get('info_showing_taxonomies') +
(taxonomiesPerPage * (page - 1) + 1) +
$i18n.get('info_to') +
getLastCategoryNumber() +
$i18n.get('info_of') + totalCategories + '.'
getLastTaxonomyNumber() +
$i18n.get('info_of') + total + '.'
}}
</div>
<div class="items-per-page">
<b-field
horizontal
:label="$i18n.get('label_categories_per_page')">
:label="$i18n.get('label_taxonomies_per_page')">
<b-select
:value="taxonomiesPerPage"
@input="onChangeCategoriesPerPage"
:disabled="categories.length <= 0">
@input="onChangePerPage"
:disabled="taxonomies.length <= 0">
<option value="12">12</option>
<option value="24">24</option>
<option value="48">48</option>
@ -92,7 +95,7 @@
<div class="pagination">
<b-pagination
@change="onPageChange"
:total="totalCategories"
:total="total"
:current.sync="page"
order="is-centered"
size="is-small"
@ -106,36 +109,36 @@
</template>
<script>
import CategoriesList from "../../components/lists/categories-list.vue";
import TaxonomiesList from "../../components/lists/taxonomies-list.vue";
import { mapActions, mapGetters } from 'vuex';
//import moment from 'moment'
export default {
name: 'CategoriesPage',
name: 'Page',
data(){
return {
isLoading: false,
totalCategories: 0,
total: 0,
page: 1,
taxonomiesPerPage: 12,
status: ''
}
},
components: {
CategoriesList
TaxonomiesList
},
methods: {
...mapActions('category', [
'fetchCategories',
...mapActions('taxonomy', [
'fetch',
]),
...mapGetters('category', [
'getCategories'
...mapGetters('taxonomy', [
'get'
]),
onChangeTab(status) {
this.status = status;
this.loadCategories();
this.load();
},
onChangeCategoriesPerPage(value) {
onChangePerPage(value) {
this.taxonomiesPerPage = value;
this.$userPrefs.set('taxonomies_per_page', value)
.then((newValue) => {
@ -144,49 +147,47 @@
.catch(() => {
this.$console.log("Error settings user prefs for taxonomies per page")
});
this.loadCategories();
this.load();
},
onPageChange(page) {
this.page = page;
this.loadCategories();
this.load();
},
loadCategories() {
load() {
this.isLoading = true;
this.fetchCategories({ 'page': this.page, 'taxonomiesPerPage': this.taxonomiesPerPage, 'status': this.status })
this.fetch({ 'page': this.page, 'taxonomiesPerPage': this.taxonomiesPerPage, 'status': this.status })
.then((res) => {
this.isLoading = false;
this.totalCategories = res.total;
this.total = res.total;
})
.catch(() => {
this.isLoading = false;
});
},
getLastCategoryNumber() {
getLastTaxonomyNumber() {
let last = (Number(this.taxonomiesPerPage * (this.page - 1)) + Number(this.taxonomiesPerPage));
return last > this.totalCategories ? this.totalCategories : last;
return last > this.total ? this.total : last;
}
},
computed: {
categories(){
return this.getCategories();
taxonomies(){
return this.get();
}
},
created() {
this.taxonomiesPerPage = this.$userPrefs.get('taxonomies_per_page');
},
mounted(){
this.$userPrefs.fetch('taxonomies_per_page')
.then((value) => {
if (this.taxonomiesPerPage != value) {
this.taxonomiesPerPage = value;
this.loadCategories;
}
})
.catch(() => {
if (this.taxonomiesPerPage != this.$userPrefs.get('taxonomies_per_page'))
this.taxonomiesPerPage = this.$userPrefs.get('taxonomies_per_page');
if (!this.taxonomiesPerPage) {
this.taxonomiesPerPage = 12;
this.$userPrefs.set('taxonomies_per_page', 12);
});
this.loadCategories();
}
this.load();
}
}
</script>

View File

@ -4,16 +4,16 @@
<div class="card">
<div class="card-content">
<p class="title">
{{ category.name }}
{{ taxonomy.name }}
</p>
<p class="subtitle">
{{ category.description }}
{{ taxonomy.description }}
</p>
</div>
<footer class="card-footer">
<router-link
class="card-footer-item"
:to="{ path: $routerHelper.getCategoryEditPath(categoryId)}">
:to="{ path: $routerHelper.getTaxonomyEditPath(taxonomyId)}">
{{ $i18n.getFrom('taxonomies','edit_item') }}
</router-link>
<a class="card-footer-item">
@ -29,29 +29,29 @@
import { mapActions, mapGetters } from 'vuex';
export default {
name: 'CategoryPage',
name: 'TaxonomyPage',
data(){
return {
categoryId: Number,
taxonomyId: Number,
}
},
methods: {
...mapActions('category', [
'fetchCategory'
...mapActions('taxonomy', [
'fetchTaxonomy'
]),
...mapGetters('category', [
'getCategory'
...mapGetters('taxonomy', [
'getTaxonomy'
])
},
computed: {
category(){
return this.getCategory();
taxonomy(){
return this.getTaxonomy();
}
},
created(){
this.categoryId = parseInt(this.$route.params.categoryId);
this.taxonomyId = parseInt(this.$route.params.taxonomyId);
this.fetchCategory(this.categoryId);
this.fetchTaxonomy(this.taxonomyId);
}
}

View File

@ -21,6 +21,7 @@
padding: 0;
border-radius: 0px !important;
.dropdown-item {
text-decoration: none;
padding: 0.375rem 1rem;
font-size: 13px;
color: $tainacan-input-color !important;

View File

@ -9,4 +9,8 @@
background-color: white;
border: 1px solid $tainacan-input-background !important;
}
&[disabled] {
color: $tainacan-placeholder-color;
background-color: $tainacan-input-background;
}
}

View File

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

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

@ -0,0 +1,16 @@
.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;
}
&:last-child {
margin-bottom: 0;
}
}

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,20 +70,34 @@
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 {
width: 100%;
.dropdown-trigger { width: 100% }
.button {
justify-content: space-between;
width: 100%;
border: 1px solid $tainacan-input-background !important;
border-radius: 0 !important;
padding: 2px 20px !important;
padding: 2px 14px 2px 18px !important
}
}
.two-columns-dropdown {
&>.dropdown-menu>.dropdown-content {
display: flex;
flex-wrap: wrap;
.dropdown-item {
width: 50%;
}
}
}
.upload-draggable {
border-radius: 0 !important;
}
}

View File

@ -64,7 +64,7 @@ $size-small: 0.85em; // 0.75em on Bulma.
$header-height: 53px;
$subheader-height: 82px;
$side-menu-width: 180px;
$filter-menu-width: 200px;
$filter-menu-width: 16.666666667%;
$filter-menu-width-theme: 20.833333333%;
$page-height: calc(100% - 53px);

View File

@ -20,6 +20,7 @@
margin: 0.75rem;
max-width: 410px;
min-width: 410px;
min-height: 218px;
cursor: pointer;
&:hover {
@ -57,55 +58,53 @@
visibility: hidden;
}
img {
width: 170px;
width: 172px;
height: auto;
border-radius: 2px;
}
&:hover img {
border-radius: 0;
}
.metadata-title {
flex-shrink: 0;
font-size: 0.875rem;
padding: 0.75rem 2.75rem;
padding: 0.75rem 4.75rem 0.75rem 2.75rem;
margin-bottom: -27px;
min-height: 42px;
font-size: 0.875rem !important;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
margin-bottom: -27px;
p {
font-size: 0.875rem !important;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
}
&:hover .metadata-title {
background-color: $gray-hover !important;
}
.media {
margin-bottom: -6px;
width: 100%;
.list-metadata {
padding: 0.75rem 1.5rem;
padding: 0.75rem 1.375rem;
flex: 1;
font-size: 0.6875rem;
color: gray;
overflow: hidden;
width: 100%;
.metadata-label {
font-size: 0.75rem;
line-height: 1.0;
margin-bottom: 0.2rem;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
font-weight: 500;
color: $gray-light;
.metadata-description {
margin-bottom: 1.5rem;
}
.metadata-value {
.metadata-author-creation {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
margin-bottom: 1rem;
margin-bottom: 0;
}
}

View File

@ -63,19 +63,23 @@
margin-bottom: -5px;
}
p.metadata-title {
.metadata-title {
flex-shrink: 0;
font-size: 0.875rem;
margin-bottom: 6px;
margin-top: 6px;
margin-right: 6px;
margin-left: 24px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
text-align: left;
padding: 6px 1rem;
min-height: 30px;
cursor: pointer;
p{
font-size: 0.875rem;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
text-align: left;
}
}
}

View File

@ -0,0 +1,123 @@
.tainacan-records-container {
min-height: 200px;
padding: 0;
display: flex;
flex-wrap: wrap;
flex-grow: 1;
flex-shrink: 1;
justify-content: center;
.selected-record {
background-color: $primary-lighter;
.metadata-title {
background-color: $primary-lighter-hover;
}
}
.tainacan-record {
padding: 0px;
flex-basis: 0;
margin: 0.75rem;
max-width: 410px;
min-width: 410px;
min-height: 218px;
cursor: pointer;
&:hover {
background-color: $tainacan-input-background !important;
}
.record-checkbox {
position: absolute;
margin-left: 1.0rem;
margin-top: 9px;
}
.actions-area {
position: relative;
float: right;
top: -7px;
padding-right: 12px;
width: 80px;
display: flex;
justify-content: space-between;
visibility: hidden;
opacity: 0;
transition: visibility 0.2s, opacity 0.2s;
}
&:hover .actions-area {
visibility: visible;
opacity: 1.0;
}
.record-line {
height: 1px;
background-color: $tainacan-input-background;
margin-left: -44px;
margin-right: -44px;
opacity: 0;
visibility: hidden;
}
img {
width: 172px;
height: auto;
border-radius: 2px;
}
&:hover img {
border-radius: 0;
}
.metadata-title {
flex-shrink: 0;
padding: 0.75rem 4.75rem 0.75rem 2.75rem;
margin-bottom: -27px;
min-height: 42px;
font-size: 0.875rem !important;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
p {
font-size: 0.875rem !important;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
}
&:hover .metadata-title {
background-color: $gray-hover !important;
}
.media {
width: 100%;
.list-metadata {
padding: 0.75rem 1.375rem;
flex: 1;
font-size: 0.6875rem;
color: gray;
overflow: hidden;
width: 100%;
.metadata-label {
font-size: 0.75rem;
margin-bottom: 0.2rem;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
font-weight: 500;
color: $gray-light;
}
.metadata-value {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
margin-bottom: 1rem;
}
}
}
}
}

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,20 @@ html {
// Link (hover is the same color as secondary
a:hover {
color: $secondary;
text-decoration: underline;
}
.add-link {
display: inline;
font-size: 12px;
&.disabled {
pointer-events: none;
cursor: default;
color: $tainacan-input-background;
.icon {
color: $tainacan-input-background !important;
}
}
}
// Page settings
@ -63,10 +78,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,28 +4,33 @@ 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' ),
'metadata' => __( 'metadata', 'tainacan' ),
'metadata' => __( 'metadata', 'tainacan' ),
'importers' => __( 'Importers', 'tainacan' ),
// Actions
'edit' => __( 'Edit', 'tainacan' ),
@ -52,8 +57,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' ),
@ -67,30 +75,32 @@ 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_categories_page' => __( 'Categories Page', '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_category_page' => __( 'Taxonomy', 'tainacan' ),
'title_term_page' => __( 'Term', 'tainacan' ),
'title_taxonomy_page' => __( 'Taxonomy', 'tainacan' ),
'title_term_edition' => __( 'Term edition', 'tainacan' ),
'title_event_page' => __( 'Event', 'tainacan' ),
'title_create_collection' => __( 'Collection Creation', 'tainacan' ),
'title_create_category_page' => __( 'Taxonomy Creation', 'tainacan' ),
'title_create_taxonomy_page' => __( 'Taxonomy Creation', 'tainacan' ),
'title_create_item_collection' => __( 'Create Item on Collection', 'tainacan' ),
'title_create_filter' => __( 'Filter Creation', 'tainacan' ),
'title_collection_settings' => __( 'Settings of Collection', 'tainacan' ),
'title_edit_item' => __( 'Edit Item', 'tainacan' ),
'title_category_edition_page' => __( 'Taxonomy Edition', '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' ),
@ -122,7 +132,7 @@ return apply_filters('tainacan-admin-i18n',[
'label_choose_thumb' => __( 'Choose Thumbnail', 'tainacan' ),
'label_button_delete_thumb' => __( 'Button Delete Thumbnail', 'tainacan' ),
'label_collections_per_page' => __( 'Collections per Page:', 'tainacan' ),
'label_categories_per_page' => __( 'Categories per Page:', 'tainacan' ),
'label_taxonomies_per_page' => __( 'Taxonomies per Page:', 'tainacan' ),
'label_events_per_page' => __( 'Events per Page:', 'tainacan' ),
'label_items_per_page' => __( 'Items per Page:', 'tainacan' ),
'label_active_metadata' => __( 'Active Metadata', 'tainacan' ),
@ -140,28 +150,28 @@ return apply_filters('tainacan-admin-i18n',[
'label_unique_value' => __( 'Unique value', 'tainacan' ),
'label_yes' => __( 'Yes', 'tainacan' ),
'label_no' => __( 'No', 'tainacan' ),
'label_approved' => __( 'Approved', 'tainacan' ),
'label_approved' => __( 'Approved', 'tainacan' ),
'label_collection_related' => __( 'Collection Related', 'tainacan' ),
'label_metadata_for_search' => __( 'Metadata for search', 'tainacan' ),
'label_metadata_for_search' => __( 'Metadata for search', 'tainacan' ),
'label_allow_repeated_items' => __( 'Allow repeated items', 'tainacan' ),
'label_select_category' => __( 'Select taxonomy', 'tainacan' ),
'label_select_category_input_type' => __( 'Input type', 'tainacan' ),
'label_category_allow_new_terms' => __( 'Allow new terms', 'tainacan' ),
'label_select_taxonomy' => __( 'Select taxonomy', 'tainacan' ),
'label_select_taxonomy_input_type' => __( 'Input type', 'tainacan' ),
'label_taxonomy_allow_new_terms' => __( 'Allow new terms', 'tainacan' ),
'label_selectbox_init' => __( 'Select', 'tainacan' ),
'label_options' => __( 'Insert options', 'tainacan' ),
'label_attachments' => __( 'Attachments', 'tainacan' ),
'label_attachment' => __( 'Attachment', 'tainacan' ),
'label_enabled' => __( 'Enabled', 'tainacan' ),
'label_disabled' => __( 'Disabled', 'tainacan' ),
'label_creation' => __( 'Creation', 'tainacan' ),
'label_creation' => __( 'Creation', 'tainacan' ),
'label_creation_date' => __( 'Creation date', 'tainacan' ),
'label_collection_items' => __( 'Collection Items', 'tainacan' ),
'label_collection_metadata' => __( 'Collection Metadata', 'tainacan' ),
'label_collection_metadata' => __( 'Collection Metadata', 'tainacan' ),
'label_collection_filters' => __( 'Collection Filters', 'tainacan' ),
'label_parent_term' => __( 'Parent Term', 'tainacan' ),
'label_new_term' => __( 'New Term', 'tainacan' ),
'label_new_child' => __( 'New Child', 'tainacan' ),
'label_category_terms' => __( 'Taxonomy Terms', 'tainacan' ),
'label_taxonomy_terms' => __( 'Taxonomy Terms', 'tainacan' ),
'label_no_parent_term' => __( 'No parent term', 'tainacan' ),
'label_term_without_name' => __( 'Term without name', 'tainacan' ),
'label_inherited' => __( 'Inherited', 'tainacan' ),
@ -172,7 +182,7 @@ return apply_filters('tainacan-admin-i18n',[
'label_empty_header_image' => __( 'Empty Header Image', 'tainacan' ),
'label_enable_cover_page' => __( 'Enable Cover Page', 'tainacan' ),
'label_cover_page' => __( 'Cover Page', 'tainacan' ),
'label_default_displayed_metadata' => __( 'Default Displayed Metadata', 'tainacan' ),
'label_default_displayed_metadata' => __( 'Default Displayed Metadata', 'tainacan' ),
'label_display' => __( 'Display on Listing', 'tainacan' ),
'label_display_default' => __( 'Display by default', 'tainacan' ),
'label_display_never' => __( 'Never displayed', 'tainacan' ),
@ -193,13 +203,14 @@ 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_selected_categories' => __( 'Delete selected categories', '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_categories' => __( 'Edit selected categories', 'tainacan' ),
'label_edit_selected_taxonomies' => __( 'Edit selected taxonomies', 'tainacan' ),
'label_select_all_collections_page' => __( 'Select all collections on page', 'tainacan' ),
'label_select_all_items_page' => __( 'Select all items on page', 'tainacan' ),
'label_select_all_categories_page' => __( 'Select all categories on page', 'tainacan' ),
'label_select_all_taxonomies_page' => __( 'Select all taxonomies on page', 'tainacan' ),
'label_edit_attachments' => __( 'Edit attachments', 'tainacan' ),
'label_blank_collection' => __( 'Blank collection', 'tainacan' ),
'label_dublin_core' => __( 'Dublin Core', 'tainacan' ),
@ -215,12 +226,27 @@ return apply_filters('tainacan-admin-i18n',[
'label_grid' => __( 'Grid', 'tainacan' ),
'label_table' => __( 'Table', 'tainacan' ),
'label_cards' => __( 'Cards', 'tainacan' ),
'label_records' => __( 'Records', 'tainacan' ),
'label_visualization' => __( 'Visualization', 'tainacan' ),
'label_available_importers' => __( 'Available Importers', 'tainacan' ),
'label_target_collection' => __( 'Target Collection', 'tainacan' ),
'label_source_file' => __( 'Source file', 'tainacan' ),
'label_url_source_link' => __( 'URL Source link', 'tainacan' ),
'label_metadata_mapping' => __( 'Metadata mapping', 'tainacan' ),
'label_select_metadatum' => __( 'Select metadatum', 'tainacan' ),
'label_select_metadatum_type' => __( 'Select a metadatum type', 'tainacan' ),
'label_add_more_metadata' => __( 'Add more metadata', 'tainacan' ),
'label_from_source_collection' => __( 'From source collection', 'tainacan' ),
'label_to_target_collection' => __( 'To target collection', 'tainacan' ),
'label_add_value' => __( 'Add value', 'tainacan' ),
'label_remove_value' => __( 'Remove value', 'tainacan' ),
'label_create_new_page' => __( 'Create new page', 'tainacan' ),
'label_total_items' => __( 'Total items', 'tainacan' ),
// Instructions. More complex sentences to guide user and placeholders
'instruction_delete_selected_collections' => __( 'Delete selected collections', 'tainacan' ),
'instruction_delete_selected_items' => __( 'Delete selected items', 'tainacan' ),
'instruction_delete_selected_categories' => __( 'Delete selected categories', 'tainacan' ),
'instruction_delete_selected_taxonomies' => __( 'Delete selected taxonomies', 'tainacan' ),
'instruction_image_upload_box' => __( 'Drop an image here or click to upload.', 'tainacan' ),
'instruction_select_a_status' => __( 'Select a status:', 'tainacan' ),
'instruction_select_a_filter_type' => __( 'Select a filter type:', 'tainacan' ),
@ -240,16 +266,21 @@ return apply_filters('tainacan-admin-i18n',[
'instruction_select_a_metadatum' => __( 'Select a metadatum', 'tainacan' ),
'instruction_select_a_mapper' => __( 'Select a mapper', 'tainacan' ),
'instruction_search_on_repository' => __( 'Search on repository', 'tainacan' ),
'instruction_select_a_target_collection' => __( 'Select a target collection', 'tainacan' ),
'instruction_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_category_draft' => __( 'No draft category found.', 'tainacan' ),
'info_no_category_trash' => __( 'No category on trash.', 'tainacan' ),
'info_no_category_created' => __( 'No taxonomy was created in this repository.', 'tainacan' ),
'info_no_taxonomy_draft' => __( 'No draft taxonomy found.', 'tainacan' ),
'info_no_taxonomy_trash' => __( 'No taxonomy on trash.', 'tainacan' ),
'info_no_taxonomy_created' => __( 'No taxonomy was created in this repository.', 'tainacan' ),
'info_no_item_created' => __( 'No item was created in this collection.', 'tainacan' ),
'info_no_item_draft' => __( 'No draft item found.', 'tainacan' ),
'info_no_item_trash' => __( 'No item on trash.', 'tainacan' ),
@ -259,25 +290,25 @@ return apply_filters('tainacan-admin-i18n',[
'info_item_not_saved' => __( 'Warning: Item not saved.', 'tainacan' ),
'info_no_moderator_on_collection' => __( "This collection doesn't have any moderator yet.", 'tainacan' ),
'info_error_deleting_collection' => __( 'Error on deleting collection.', 'tainacan' ),
'info_error_deleting_category' => __( 'Error on deleting taxonomy', 'tainacan' ),
'info_error_deleting_taxonomy' => __( 'Error on deleting taxonomy', 'tainacan' ),
'info_collection_deleted' => __( 'Collection deleted.', 'tainacan' ),
'info_item_deleted' => __( 'Item deleted.', 'tainacan' ),
'info_category_deleted' => __( 'Taxonomy 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_category_delete' => __( 'Do you really want to delete this taxonomy?', '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_categories_delete' => __( 'Do you really want to delete the selected categories?', '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_categories' => __( 'Showing categories ', 'tainacan' ),
'info_showing_taxonomies' => __( 'Showing taxonomies ', 'tainacan' ),
'info_showing_events' => __( 'Showing events ', 'tainacan' ),
'info_to' => __( ' to ', 'tainacan' ),
'info_of' => __( ' of ', 'tainacan' ),
@ -286,16 +317,16 @@ 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_category_not_saved' => __( 'Are you sure? The metadata is not saved, changes will be lost.', 'tainacan' ),
'info_warning_taxonomy_not_saved' => __( 'Are you sure? The metadata is not saved, changes will be lost.', 'tainacan' ),
'info_warning_terms_not_saved' => __( 'Are you sure? There are terms not saved, changes will be lost.', 'tainacan' ),
'info_warning_orphan_terms' => __( 'Are you sure? This term is parent of other terms. These will be converted to root terms.', 'tainacan' ),
'info_no_events' => __( 'No events', 'tainacan' ),
'info_logs_before' => __( 'Before updating', 'tainacan' ),
'info_logs_after' => __( 'What was updated', 'tainacan' ),
'info_there_is_no_metadatum' => __( 'There is no metadata here yet.', 'tainacan' ),
'info_there_is_no_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' ),
@ -307,7 +338,17 @@ 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' ),
'info_updated_at' => __( 'Updated at', 'tainacan' ),
'info_editing_metadata_values' => __( 'Editing metadata values...', 'tainacan' ),
'info_updating_metadata_values' => __( 'Updating metadata values...', 'tainacan' ),
// Tainacan Metadatum Types
'tainacan-text' => __( 'Text', 'tainacan' ),
'tainacan-textarea' => __( 'Text area', 'tainacan' ),
@ -315,7 +356,8 @@ return apply_filters('tainacan-admin-i18n',[
'tainacan-numeric' => __( 'Numeric', 'tainacan' ),
'tainacan-selectbox' => __( 'Select box', 'tainacan' ),
'tainacan-relationship' => __( 'Relationship', 'tainacan' ),
'tainacan-category' => __( 'Taxonomy', 'tainacan' ),
'tainacan-taxonomy' => __( 'Taxonomy', 'tainacan' ),
'tainacan-compound' => __( 'Compound', 'tainacan' ),
// Tainacan Filter Types
'tainacan-filter-custom-interval' => __( 'Custom Interval', 'tainacan' ),
@ -323,8 +365,8 @@ return apply_filters('tainacan-admin-i18n',[
'tainacan-filter-autocomplete' => __( 'Autocomplete', 'tainacan' ),
'tainacan-filter-taginput' => __( 'Tag Input', 'tainacan' ),
'tainacan-filter-checkbox' => __( 'Check Box', 'tainacan' ),
'tainacan-filter-category-taginput' => __( 'Taxonomy Tag Input', 'tainacan' ),
'tainacan-filter-category-checkbox' => __( 'Taxonomy Check Box', 'tainacan' ),
'tainacan-filter-category-selectbox' => __( 'Taxonomy Select Box', 'tainacan' )
'tainacan-filter-taxonomy-taginput' => __( 'Taxonomy Tag Input', 'tainacan' ),
'tainacan-filter-taxonomy-checkbox' => __( 'Taxonomy Check Box', 'tainacan' ),
'tainacan-filter-taxonomy-selectbox' => __( 'Taxonomy Select Box', 'tainacan' )
]);
?>

View File

@ -9,6 +9,9 @@
<script>
export default {
name: "ThemeItemsList",
created() {
this.$userPrefs.init();
}
}
</script>
@ -31,6 +34,7 @@ export default {
// Tainacan imports
@import "../admin/scss/_tables.scss";
@import "../admin/scss/_tags.scss";
@import "../admin/scss/_selects.scss";
@import "../admin/scss/_dropdown-and-autocomplete.scss";
@import "../admin/scss/_tooltips.scss";
@ -285,7 +289,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%;
@ -295,12 +298,17 @@ export default {
}
.search-control {
border-bottom: 0;
}
.table-container {
padding-left: 4.166666667%;
padding-right: 4.166666667%;
.gray-icon, .gray-icon .icon {
color: $tainacan-placeholder-color !important;
i::before {
font-size: 21px;
}
}
.view-mode-icon {
margin-right: 8px !important;
margin-top: 2px;
}
}
#items-list-area {

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',
@ -77,6 +78,7 @@ class REST_Controller extends \WP_REST_Controller {
'metacompare' => 'meta_compare',
'hideempty' => 'hide_empty',
'perpage' => 'posts_per_page',
'number' => 'number',
'paged' => 'paged',
'postin' => 'post__in',
'relation' => 'relation',
@ -245,7 +247,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,20 @@ 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' );
if (isset($total_items->publish) ||
isset($total_items->private) ||
isset($total_items->trash) ||
isset($total_items->draft)) {
$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

@ -344,7 +344,7 @@ class REST_Filters_Controller extends REST_Controller {
public function get_items( $request ) {
$args = $this->prepare_filters( $request );
if ($request['include_disabled'] === 'yes') {
if ($request['include_disabled'] === 'true') {
$args['include_disabled'] = true;
}

View File

@ -0,0 +1,314 @@
<?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(); // @ avoids Warnings when running phpunit tests
}
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/object',
'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($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);
}
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->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;
}
@ -362,7 +368,7 @@ class REST_Metadata_Controller extends REST_Controller {
* @throws \Exception
*/
public function get_items_permissions_check( $request ) {
if ( 'edit' === $request['context'] && ! current_user_can('edit_tainacan-metadata') ) {
if ( 'edit' === $request['context'] && ! $this->metadatum_repository->can_edit(new Entities\Metadatum()) ) {
return false;
}

View File

@ -284,6 +284,7 @@ class REST_Terms_Controller extends REST_Controller {
$taxonomy = $this->taxonomy_repository->fetch($taxonomy_id);
$args = $this->prepare_filters($request);
$prepared_args = $args;
$terms = $this->terms_repository->fetch($args, $taxonomy);
@ -292,7 +293,27 @@ class REST_Terms_Controller extends REST_Controller {
array_push($response, $this->prepare_item_for_response( $term, $request ));
}
return new \WP_REST_Response($response, 200);
$response = new \WP_REST_Response($response, 200);
if(isset($args['number'], $args['offset'])){
unset( $args['number'], $args['offset'] );
$total_terms = wp_count_terms( $this->taxonomy->get_db_identifier(), $args );
if ( ! $total_terms ) {
$total_terms = 0;
}
$per_page = (int) $prepared_args['number'];
$page = ceil( ( ( (int) $prepared_args['offset'] ) / $per_page ) + 1 );
$response->header( 'X-WP-Total', (int) $total_terms );
$max_pages = ceil( $total_terms / $per_page );
$response->header( 'X-WP-TotalPages', (int) $max_pages );
}
return $response;
}
/**

View File

@ -13,6 +13,8 @@ $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();
$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

@ -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
*/
public $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;
@ -94,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]
);
@ -204,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

@ -421,15 +421,15 @@ class Metadatum extends Entity {
if (false === $is_valid)
return false;
// You cant have a multiple metadatum inside a compound metadatum (except category)
// You cant have a multiple metadatum inside a compound metadatum (except taxonomy)
if ($this->get_parent() > 0) {
if ( $this->is_multiple() && $this->get_metadata_type_object()->get_primitive_type() != 'term') {
$this->add_error($this->get_id(), __('Compound metadata do not support metadata with multiple values (except categories)', 'tainacan'));
$this->add_error($this->get_id(), __('Compound metadata do not support metadata with multiple values (except taxonomies)', 'tainacan'));
return false;
}
}
// You cant have a category metadatum inside a multiple compound metadatum
// You cant have a taxonomy metadatum inside a multiple compound metadatum
if ( $this->get_parent() > 0 && $this->get_metadata_type_object()->get_primitive_type() == 'term' ) {
$parent_metadatum = new \Tainacan\Entities\Metadatum($this->get_parent());
if ( $parent_metadatum->is_multiple() ) {
@ -442,7 +442,7 @@ class Metadatum extends Entity {
$children = $Tainacan_Metadata->fetch(
[
'parent' => $this->get_id(),
'metadata_type' => 'Tainacan\Metadata_Types\Category',
'metadata_type' => 'Tainacan\Metadata_Types\Taxonomy',
'post_status' => 'any'
]
, 'OBJECT');

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

@ -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

@ -7,6 +7,12 @@
class="show"
:open="open">
<label
v-tooltip="{
content: filter.name,
html: false,
autoHide: false,
placement: 'top-start'
}"
class="label"
slot="trigger"
slot-scope="props">
@ -165,7 +171,10 @@
.collapse-content {
margin-top: 12px;
}
.columns{
margin-left: 0px;
margin-right: 0px;
}
.column {
padding: 0.75rem 1px 0.75rem 0 !important;
}
@ -180,16 +189,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;
@ -198,9 +201,8 @@
}
.label {
font-weight: normal;
font-weight: normal !important;
font-size: 14px;
display: inline-flex;
width: 100%;
}
@ -208,8 +210,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

@ -54,7 +54,7 @@
}
},
methods: {
getValuesCategory( taxonomy ){
getValuesTaxonomy( taxonomy ){
return axios.get('/taxonomy/' + taxonomy + '/terms?hideempty=0&order=asc' ).then( res => {
for (let item of res.data) {
this.taxonomy = item.taxonomy;
@ -72,7 +72,7 @@
axios.get('/collection/'+ this.collection +'/metadata/' + this.metadatum)
.then( res => {
let metadatum = res.data;
promise = this.getValuesCategory( metadatum.metadata_type_options.taxonomy_id );
promise = this.getValuesTaxonomy( metadatum.metadata_type_options.taxonomy_id );
promise.then( () => {
this.isLoading = false;

View File

@ -56,7 +56,7 @@
}
},
methods: {
getValuesCategory( taxonomy ){
getValuesTaxonomy( taxonomy ){
return axios.get('/taxonomy/' + taxonomy + '/terms?hideempty=0' ).then( res => {
for (let item of res.data) {
this.taxonomy = item.taxonomy;
@ -74,7 +74,7 @@
axios.get('/collection/'+ this.collection +'/metadata/' + this.metadatum)
.then( res => {
let metadatum = res.data;
promise = this.getValuesCategory( metadatum.metadata_type_options.taxonomy_id );
promise = this.getValuesTaxonomy( metadatum.metadata_type_options.taxonomy_id );
promise.then( () => {
this.isLoading = false;

View File

@ -88,7 +88,7 @@
axios.get(endpoint)
.then( res => {
let metadatum = res.data;
promise = this.getValuesCategory( metadatum.metadata_type_options.taxonomy_id, q );
promise = this.getValuesTaxonomy( metadatum.metadata_type_options.taxonomy_id, q );
this.isLoading = true;
promise.then( () => {
this.isLoading = false;
@ -102,7 +102,7 @@
this.$console.log(error);
});
},
getValuesCategory( taxonomy, query ){
getValuesTaxonomy( taxonomy, query ){
return axios.get('/taxonomy/' + taxonomy + '/terms?hideempty=0&order=asc' ).then( res => {
for (let term of res.data) {
if( term.name.toLowerCase().indexOf( query.toLowerCase() ) >= 0 ){

View File

@ -6,11 +6,11 @@ defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
/**
* Class TainacanMetadatumType
*/
class CategoryCheckbox extends Filter_Type {
class TaxonomyCheckbox extends Filter_Type {
function __construct(){
$this->set_supported_types(['term']);
$this->set_component('tainacan-filter-category-checkbox');
$this->set_component('tainacan-filter-taxonomy-checkbox');
}
/**
@ -19,7 +19,7 @@ class CategoryCheckbox extends Filter_Type {
*/
public function render( $filter ){
return '<tainacan-filter-category-checkbox name="'.$filter->get_name().'"
return '<tainacan-filter-taxonomy-checkbox name="'.$filter->get_name().'"
filter_type="'.$filter->get_metadatum()->get_metadata_type().'"
collection_id="'.$filter->get_collection_id().'"
metadatum_id="'.$filter->get_metadatum()->get_id().'"></tainacan-filter-checkbox>';

View File

@ -6,11 +6,11 @@ defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
/**
* Class TainacanMetadatumType
*/
class CategorySelectbox extends Filter_Type {
class TaxonomySelectbox extends Filter_Type {
function __construct(){
$this->set_supported_types(['term']);
$this->set_component('tainacan-filter-category-selectbox');
$this->set_component('tainacan-filter-taxonomy-selectbox');
}
/**
@ -19,7 +19,7 @@ class CategorySelectbox extends Filter_Type {
*/
public function render( $filter ){
return '<tainacan-filter-category-selectbox name="'.$filter->get_name().'"
return '<tainacan-filter-taxonomy-selectbox name="'.$filter->get_name().'"
filter_type="'.$filter->get_metadatum()->get_metadata_type().'"
collection_id="'.$filter->get_collection_id().'"
metadatum_id="'.$filter->get_metadatum()->get_id().'"></tainacan-filter-selectbox>';

View File

@ -6,11 +6,11 @@ defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
/**
* Class Taginput
*/
class CategoryTaginput extends Filter_Type {
class TaxonomyTaginput extends Filter_Type {
function __construct(){
$this->set_supported_types(['term']);
$this->set_component('tainacan-filter-category-taginput');
$this->set_component('tainacan-filter-taxonomy-taginput');
}
/**
@ -19,7 +19,7 @@ class CategoryTaginput extends Filter_Type {
*/
public function render( $filter ){
return '<tainacan-filter-category-taginput name="'.$filter->get_name().'"
return '<tainacan-filter-taxonomy-taginput name="'.$filter->get_name().'"
filter_type="'.$filter->get_metadatum()->get_metadata_type().'"
collection_id="'.$filter->get_collection_id().'"
metadatum_id="'.$filter->get_metadatum()->get_id().'"></tainacan-filter-taginput>';

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

@ -1,83 +0,0 @@
<template>
<div class="block">
<b-taginput
size="is-small"
icon="magnify"
:allow-new="allowNew"
@input="emitChange"
v-model="selected"
:data="labels"
field="label"
attached
:class="{'has-selected': selected != undefined && selected != []}"
autocomplete
@typing="search"/>
</div>
</template>
<script>
export default {
data(){
return {
selected: [],
labels: []
}
},
watch: {
terms(){
this.selectedValues();
}
},
props: {
terms: [ Number, String, Array ],
options: {
type: Array
},
value: [ Number, String, Array ],
allowNew: [ Boolean ]
},
methods: {
search( query ){
if( this.terms && this.terms.length > 0 ){
let result = this.terms.filter( ( item ) => {
let name = item.name.toLowerCase();
let q = query.toLowerCase();
return ( name.indexOf(q) >= 0 )
});
this.labels = [];
for( let term of result){
this.labels.push({label: term.name, value: term.id})
}
}
},
selectedValues(){
if( this.value && this.value.length > 0 && this.selected.length === 0){
let result = this.terms.filter( ( item ) => {
let id = item.id;
return ( this.value.indexOf( id ) >= 0 )
});
let selected = [];
for( let term of result){
selected.push({label: term.name, value: term.id})
}
this.selected = selected;
}
},
emitChange(){
let val = this.selected;
let results = [];
for( let term of val ){
if( term.value ){
results.push( term.value );
} else {
results.push( term );
}
}
this.$emit('input', results);
this.$emit('blur');
}
}
}
</script>

View File

@ -7,7 +7,7 @@
class="input"
type="text"
v-mask="dateMask"
v-model="dateValue"
:value="dateValue"
@blur="onBlur"
@input="onInput"
:placeholder="dateFormat">
@ -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

@ -3,9 +3,10 @@
<b-select
:id = "id"
:placeholder="$i18n.get('label_selectbox_init')"
v-model="selected"
:class="{'is-empty': selected == undefined || selected == ''}"
@input="onChecked()">
:value="value"
:class="{'is-empty': value == undefined || value == ''}"
@blur="$emit('blur')"
@input="onChecked($event)">
<option
v-for="(option, index) in getOptions"
:key="index"
@ -19,16 +20,6 @@
<script>
export default {
created(){
if( this.value && this.value ){
this.selected = this.value
}
},
data(){
return {
selected: undefined
}
},
props: {
metadatum: {
type: Object
@ -52,14 +43,9 @@
}
},
methods: {
onChecked() {
this.$emit('blur');
if (this.selected != undefined)
this.onInput(this.selected)
onChecked(value) {
this.$emit('input', value);
},
onInput($event) {
this.$emit('input', $event);
}
}
}
</script>

View File

@ -27,7 +27,8 @@
:is="metadatum.metadatum.metadata_type_object.component"
v-model="inputs[0]"
:metadatum="metadatum"
@blur="changeValue()"/>
@blur="changeValue()"
@input="emitIsChangingValue()"/>
<div v-if="metadatum.metadatum.multiple == 'yes'">
<div
v-if="index > 0"
@ -39,14 +40,28 @@
:is="metadatum.metadatum.metadata_type_object.component"
v-model="inputs[index]"
:metadatum="metadatum"
@blur="changeValue()"/><a
class="button"
v-if="index > 0"
@click="removeInput(index)">-</a>
@blur="changeValue()"
@input="emitIsChangingValue()"/>
<a
v-if="index > 0"
@click="removeInput(index)"
class="is-inline add-link">
<b-icon
icon="minus-circle"
size="is-small"
type="is-secondary"/>
{{ $i18n.get('label_remove_value') }}</a>
</div>
<a
class="button"
@click="addInput">+</a>
@click="addInput"
class="is-inline add-link">
<b-icon
icon="plus-circle"
size="is-small"
type="is-secondary"/>
{{ $i18n.get('label_add_value') }}</a>
</div>
</div>
<div
@ -57,7 +72,8 @@
:is="metadatum.metadatum.metadata_type_object.component"
v-model="inputs"
:metadatum="metadatum"
@blur="changeValue()"/>
@blur="changeValue()"
@input="emitIsChangingValue()"/>
</div>
</b-field>
</template>
@ -107,14 +123,70 @@
this.getValue();
},
methods: {
changeValue(){
eventBus.$emit('input', { item_id: this.metadatum.item.id, metadatum_id: this.metadatum.metadatum.id, values: this.inputs } );
emitIsChangingValue() {
eventBus.isChangingValue(true);
},
getValue(){
changeValue(){
if(this.metadatum.value != this.inputs){
if(this.inputs.length > 0 && this.inputs[0].value){
let terms = []
for(let term of this.inputs){
terms.push(term.value);
}
if(this.metadatum.value instanceof Array){
let eq = [];
for(let meta of terms){
let found = this.metadatum.value.find((element) => {
return meta == element.id;
});
if(found){
eq.push(found);
}
}
if(eq.length == terms.length && this.metadatum.value.length <= eq.length){
return;
}
}
} else if(this.metadatum.value.constructor.name == 'Object'){
if(this.metadatum.value.id == this.inputs){
return;
}
} else if(this.metadatum.value instanceof Array){
let eq = [];
for(let meta of this.inputs){
let found = this.metadatum.value.find((element) => {
return meta == element.id;
});
if(found){
eq.push(found);
}
}
if(eq.length == this.inputs.length && this.metadatum.value.length <= eq.length){
return;
}
}
eventBus.$emit('input', { item_id: this.metadatum.item.id, metadatum_id: this.metadatum.metadatum.id, values: this.inputs } );
}
},
getValue(){
if (this.metadatum.value instanceof Array) {
this.inputs = this.metadatum.value;
if (this.inputs.length === 0)
this.inputs = this.metadatum.value.slice(0);
if (this.inputs.length === 0){
this.inputs.push('');
}
} else {
this.metadatum.value == null || this.metadatum.value == undefined ? this.inputs.push('') : this.inputs.push(this.metadatum.value);
}
@ -128,7 +200,7 @@
this.changeValue();
},
isTextInputComponent( component ){
let array = ['tainacan-relationship','tainacan-category'];
let array = ['tainacan-relationship','tainacan-taxonomy'];
return !( array.indexOf( component ) >= 0 );
},
setMetadatumTypeMessage( message ){
@ -144,6 +216,8 @@
.multiple-inputs {
display: flex;
align-items: center;
justify-content: space-between;
}
.field {
@ -153,7 +227,7 @@
.label {
font-size: 14px;
font-weight: 500;
margin-left: 18px;
margin-left: 15px;
margin-bottom: 0.5em;
}
.metadata-type {
@ -169,6 +243,7 @@
.collapse-handle {
cursor: pointer;
position: relative;
margin-left: -42px;
}
}
</style>

View File

@ -1,18 +1,21 @@
<template>
<div>
<span>
<a
class="button"
@click="showForm = !showForm"><b-icon
size="is-small"
icon="plus"/>&nbsp;{{ $i18n.get('label_new_term') }}</a>
<a
@click="showForm = !showForm"
class="is-inline add-link">
<b-icon
icon="plus-circle"
size="is-small"
type="is-secondary"/>
&nbsp;{{ $i18n.get('label_new_term') }}</a>
</span>
<div class="columns">
<div>
<transition name="fade">
<section
v-if="showForm"
class="column is-one-third"
style="padding-left: 0px;">
<b-field :label="$i18n.get('label_name')">
@ -36,7 +39,7 @@
</b-field>
<a
class="button is-primary"
class="button is-secondary"
@click="save">{{ $i18n.get('save') }}</a>
</section>
@ -124,9 +127,4 @@
}
</script>
<style scoped>
button{
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
}
</style>

View File

@ -7,10 +7,10 @@
:type="taxonomyType"
:message="taxonomyMessage">
<label class="label is-inline">
{{ $i18n.get('label_select_category') }}<span :class="taxonomyType" >&nbsp;*&nbsp;</span>
{{ $i18n.get('label_select_taxonomy') }}<span :class="taxonomyType" >&nbsp;*&nbsp;</span>
<help-button
:title="$i18n.getHelperTitle('tainacan-category', 'taxonomy_id')"
:message="$i18n.getHelperMessage('tainacan-category', 'taxonomy_id')"/>
:title="$i18n.getHelperTitle('tainacan-taxonomy', 'taxonomy_id')"
:message="$i18n.getHelperMessage('tainacan-taxonomy', 'taxonomy_id')"/>
</label>
<b-select
name="field_type_options[taxonomy_id]"
@ -31,15 +31,15 @@
<b-field :addons="false">
<label class="label">
{{ $i18n.get('label_select_category_input_type') }}
{{ $i18n.get('label_select_taxonomy_input_type') }}
<help-button
:title="$i18n.getHelperTitle('tainacan-category', 'input_type')"
:message="$i18n.getHelperMessage('tainacan-category', 'input_type')"/>
:title="$i18n.getHelperTitle('tainacan-taxonomy', 'input_type')"
:message="$i18n.getHelperMessage('tainacan-taxonomy', 'input_type')"/>
</label>
<b-select
v-if="listInputType"
name="metadata_type_options[component_type]"
placeholder="Select the input type for the category metadatum"
placeholder="Select the input type for the taxonomy metadatum"
@input="emitValues()"
v-model="input_type">
<option
@ -52,7 +52,7 @@
<b-select
name="metadata_type_options[input_type]"
placeholder="Select the input type for the category metadatum"
placeholder="Select the input type for the taxonomy metadatum"
v-model="input_type"
@input="emitValues()"
v-else>
@ -69,10 +69,10 @@
<b-field :addons="false">
<label class="label">
{{ $i18n.get('label_category_allow_new_terms') }}
{{ $i18n.get('label_taxonomy_allow_new_terms') }}
<help-button
:title="$i18n.getHelperTitle('tainacan-category', 'allow_new_terms')"
:message="$i18n.getHelperMessage('tainacan-category', 'allow_new_terms')"/>
:title="$i18n.getHelperTitle('tainacan-taxonomy', 'allow_new_terms')"
:message="$i18n.getHelperMessage('tainacan-taxonomy', 'allow_new_terms')"/>
</label>
<div class="block">
<b-checkbox
@ -110,10 +110,10 @@
this.allow_new_terms = ( this.value.allow_new_terms ) ? this.value.allow_new_terms : 'no';
}
this.single_types['tainacan-category-radio'] = 'Radio';
this.single_types['tainacan-category-selectbox'] = 'Selectbox';
this.multiple_types['tainacan-category-tag-input'] = 'Tag Input';
this.multiple_types['tainacan-category-checkbox'] = 'Checkbox';
this.single_types['tainacan-taxonomy-radio'] = 'Radio';
this.single_types['tainacan-taxonomy-selectbox'] = 'Selectbox';
this.multiple_types['tainacan-taxonomy-tag-input'] = 'Tag Input';
this.multiple_types['tainacan-taxonomy-checkbox'] = 'Checkbox';
this.isReady = true;
},
@ -122,12 +122,12 @@
if( this.metadatum && this.metadatum.multiple === 'no' ){
let types = Object.keys( this.single_types );
let hasValue = this.value && this.value.input_type && types.indexOf( this.value.input_type ) >= 0;
this.setInputType( ( hasValue ) ? this.value.input_type : 'tainacan-category-radio' );
this.setInputType( ( hasValue ) ? this.value.input_type : 'tainacan-taxonomy-radio' );
return true;
} else {
let types = Object.keys( this.multiple_types );
let hasValue = this.value && this.value.input_type && types.indexOf( this.value.input_type ) >= 0;
this.setInputType( ( hasValue ) ? this.value.input_type : 'tainacan-category-checkbox' );
this.setInputType( ( hasValue ) ? this.value.input_type : 'tainacan-taxonomy-checkbox' );
return false;
}
},
@ -147,7 +147,7 @@
taxonomy_id: '',
loading: true,
allow_new_terms: 'yes',
input_type: 'tainacan-category-radio',
input_type: 'tainacan-taxonomy-radio',
multiple_types: {},
single_types: {},
taxonomyType:'',

View File

@ -5,10 +5,11 @@
v-model="valueComponent"
:allow-new="allowNew"
:terms="terms"
:taxonomy-id="taxonomy"
:options="getOptions(0)"/>
<add-new-term
class="add-new-term"
v-if="getComponent() !== 'tainacan-category-tag-input' && allowNew"
v-if="getComponent() !== 'tainacan-taxonomy-tag-input' && allowNew"
:taxonomy_id="taxonomy"
:metadatum="metadatum"
:item_id="metadatum.item.id"
@ -19,10 +20,10 @@
</template>
<script>
import { tainacan as axios } from '../../../js/axios/axios'
import TainacanCategoryRadio from './CategoryRadio.vue'
import TainacanCategoryCheckbox from './CategoryCheckbox.vue'
import TainacanCategoryTagInput from './CategoryTaginput.vue'
import TainacanCategorySelectbox from './CategorySelectbox.vue'
import TainacanTaxonomyRadio from './TaxonomyRadio.vue'
import TainacanTaxonomyCheckbox from './TaxonomyCheckbox.vue'
import TainacanTaxonomyTagInput from './TaxonomyTaginput.vue'
import TainacanTaxonomySelectbox from './TaxonomySelectbox.vue'
import AddNewTerm from './AddNewTerm.vue'
export default {
@ -37,14 +38,19 @@
if( metadata_type_options && metadata_type_options.allow_new_terms ){
this.allowNew = metadata_type_options.allow_new_terms === 'yes'
}
this.getTermsFromTaxonomy();
// This condition is temporary
if(this.component != 'tainacan-taxonomy-tag-input'){
this.getTermsFromTaxonomy();
}
this.getTermsId();
},
components: {
TainacanCategoryRadio,
TainacanCategoryCheckbox,
TainacanCategoryTagInput,
TainacanCategorySelectbox,
TainacanTaxonomyRadio,
TainacanTaxonomyCheckbox,
TainacanTaxonomyTagInput,
TainacanTaxonomySelectbox,
AddNewTerm
},
data(){
@ -108,6 +114,7 @@
},
getTermsId(){
let values = [];
if( this.value && this.value.length > 0){
for( let term of this.value ){
if( term && term.id)
@ -115,8 +122,16 @@
}
}
if( values.length > 0 && this.metadatum.metadatum){
this.valueComponent = ( this.metadatum.metadatum && this.metadatum.metadatum.multiple === 'no' ) ? values[0] : values
if( values.length > 0 && this.metadatum.metadatum && this.component != 'tainacan-taxonomy-tag-input'){
this.valueComponent = ( this.metadatum.metadatum && this.metadatum.metadatum.multiple === 'no' ) ? values[0] : values;
} else if(values.length > 0 && this.metadatum.metadatum && this.component == 'tainacan-taxonomy-tag-input') {
let values = [];
for(let term of this.value){
values.push({label: term.name, value: term.id});
}
this.valueComponent = values;
}
},

View File

@ -5,7 +5,7 @@
:id="id"
v-model="selected"
@input="emitChange()"
:placeholder="$i18n.get('label_select_category')"
:placeholder="$i18n.get('label_select_taxonomy')"
expanded>
<option
v-for="(option, index) in options"

View File

@ -0,0 +1,117 @@
<template>
<div class="block">
<b-taginput
size="is-small"
icon="magnify"
:allow-new="allowNew"
@add="emitAdd"
@remove="emitRemove"
v-model="selected"
:data="labels"
field="label"
attached
ellipsis
:loading="isFetching"
:class="{'has-selected': selected != undefined && selected != []}"
autocomplete
@typing="autoCompleteTerm"/>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex';
export default {
data(){
return {
selected: [],
labels: [],
termList: [],
isFetching: false,
}
},
props: {
options: {
type: Array
},
value: [ Number, String, Array ],
allowNew: [ Boolean ],
taxonomyId: Number,
},
created(){
if(this.value && this.value.length > 0){
this.selected = this.value;
}
},
methods: {
...mapActions('taxonomy', [
'fetchTerms'
]),
...mapGetters('taxonomy', [
'getTerms'
]),
autoCompleteTerm: _.debounce( function(value){
this.termList = [];
this.labels = [];
this.isFetching = true;
this.fetchTerms({
taxonomyId: this.taxonomyId,
fetchOnly: {
fetch_only: {
0: 'name',
1: 'id'
}
},
search: {
searchterm: value
},
all: true
}).then((res) => {
this.termList = res;
for(let term of this.termList){
this.labels.push({label: term.name, value: term.id});
}
this.isFetching = false;
}).catch((error) => {
this.isFetching = false;
throw error;
});
}, 300),
selectedValues(){
let selected = [];
for( let term of this.value){
selected.push({label: term.label, value: term.value})
}
this.selected = selected;
},
emitAdd(){
let val = this.selected;
let results = [];
if(val.length > 0){
for( let term of val ){
results.push( term.value );
}
this.$emit('input', results);
this.$emit('blur');
}
},
emitRemove(){
let val = this.selected;
let results = [];
for( let term of val ){
results.push( term.value );
}
this.$emit('input', results);
this.$emit('blur');
}
}
}
</script>

View File

@ -11,7 +11,7 @@ defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
/**
* Class TainacanMetadatumType
*/
class Category extends Metadata_Type {
class Taxonomy extends Metadata_Type {
function __construct(){
// call metadatum type constructor
@ -22,8 +22,8 @@ class Category extends Metadata_Type {
'allow_new_terms' => false
]);
$this->set_form_component('tainacan-form-category');
$this->set_component('tainacan-category');
$this->set_form_component('tainacan-form-taxonomy');
$this->set_component('tainacan-taxonomy');
}
/**
@ -32,7 +32,7 @@ class Category 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' => [
@ -71,20 +71,20 @@ class Category extends Metadata_Type {
$Tainacan_Metadata = Metadata::get_instance();
$category_metadata = $Tainacan_Metadata->fetch([
$taxonomy_metadata = $Tainacan_Metadata->fetch([
'collection_id' => $metadatum->get_collection_id(),
'metadata_type' => 'Tainacan\\Metadata_Types\\Category'
'metadata_type' => 'Tainacan\\Metadata_Types\\Taxonomy'
], 'OBJECT');
$category_metadata = array_map(function ($metadatum_map) {
$taxonomy_metadata = array_map(function ($metadatum_map) {
$fto = $metadatum_map->get_metadata_type_object();
return [ $metadatum_map->get_id() => $fto->get_option('taxonomy_id') ];
}, $category_metadata);
}, $taxonomy_metadata);
if( is_array( $category_metadata ) ){
foreach ($category_metadata as $metadatum_id => $category_metadatum) {
if ( is_array( $category_metadatum ) && key($category_metadatum) != $metadatum->get_id()
&& in_array($this->get_option('taxonomy_id'), $category_metadatum)) {
if( is_array( $taxonomy_metadata ) ){
foreach ($taxonomy_metadata as $metadatum_id => $taxonomy_metadatum) {
if ( is_array( $taxonomy_metadatum ) && key($taxonomy_metadatum) != $metadatum->get_id()
&& in_array($this->get_option('taxonomy_id'), $taxonomy_metadatum)) {
return ['taxonomy_id' => __('You can not have 2 taxonomy metadata using the same taxonomy in a collection.', 'tainacan')];
}
}
@ -95,7 +95,7 @@ class Category extends Metadata_Type {
}
/**
* Validate item based on metadatum type categories options
* Validate item based on metadatum type taxonomies options
*
* @param Item_Metadata_Entity $item_metadata
*

View File

@ -1,24 +1,14 @@
<template>
<b-input
:class="{'has-content': inputValue !== undefined && inputValue !== ''}"
:class="{'has-content': value !== undefined && value !== ''}"
:id="id"
:value="inputValue"
@blur="onBlur"
:value="value"
@blur="$emit('blur')"
@input="onInput($event)"/>
</template>
<script>
export default {
created(){
if( this.value ){
this.inputValue = this.value
}
},
data() {
return {
inputValue: '',
}
},
props: {
metadatum: {
type: Object
@ -27,12 +17,8 @@
id: ''
},
methods: {
onBlur() {
this.$emit('blur');
},
onInput($event) {
this.inputValue = $event;
this.$emit('input', this.inputValue);
onInput(value) {
this.$emit('input', value);
}
}
}

View File

@ -168,7 +168,7 @@ class Collections extends Repository {
'map' => 'meta',
'title' => __( 'Cover Page ID', 'tainacan' ),
'type' => 'string',
'description' => __( 'The page to be used as cover for this collection', 'tainacan' ),
'description' => __( 'If enabled, this custom page will be used as cover for this collection, instead of default items list.', 'tainacan' ),
'on_error' => __( 'Invalid page', 'tainacan' ),
//'validation' => v::numeric(),
'default' => ''

View File

@ -440,10 +440,10 @@ class Metadata extends Repository {
* @see \Tainacan\Repositories\Repository::insert()
*/
public function insert($metadatum){
$this->pre_update_category_metadatum($metadatum);
$this->pre_update_taxonomy_metadatum($metadatum);
$new_metadatum = parent::insert($metadatum);
$this->update_category_metadatum($new_metadatum);
$this->update_taxonomy_metadatum($new_metadatum);
return $new_metadatum;
}
@ -459,7 +459,7 @@ class Metadata extends Repository {
}
public function delete($metadatum_id){
$this->delete_category_metadatum($metadatum_id);
$this->delete_taxonomy_metadatum($metadatum_id);
$deleted = new Entities\Metadatum( wp_trash_post( $metadatum_id ) );
@ -815,10 +815,10 @@ class Metadata extends Repository {
}
/**
* Stores the value of the taxonomy_id option to use on update_category_metadatum method.
* Stores the value of the taxonomy_id option to use on update_taxonomy_metadatum method.
*
*/
private function pre_update_category_metadatum($metadatum) {
private function pre_update_taxonomy_metadatum($metadatum) {
$metadata_type = $metadatum->get_metadata_type_object();
$current_tax = '';
if ($metadata_type->get_primitive_type() == 'term') {
@ -831,16 +831,16 @@ class Metadata extends Repository {
}
/**
* Triggers hooks when saving a Category Metadatum, indicating wich taxonomy was added or removed from a collection.
* Triggers hooks when saving a Taxonomy Metadatum, indicating wich taxonomy was added or removed from a collection.
*
* This is used by Taxonomies repository to update the collections_ids property of the taxonomy as
* a metadatum type category is inserted or removed
* a metadatum type taxonomy is inserted or removed
*
* @param [type] $metadatum [description]
*
* @return void [type] [description]
*/
private function update_category_metadatum($metadatum) {
private function update_taxonomy_metadatum($metadatum) {
$metadata_type = $metadatum->get_metadata_type_object();
$new_tax = '';
@ -862,7 +862,7 @@ class Metadata extends Repository {
}
}
private function delete_category_metadatum($metadatum_id) {
private function delete_taxonomy_metadatum($metadatum_id) {
$metadatum = $this->fetch($metadatum_id);
$metadata_type = $metadatum->get_metadata_type_object();

View File

@ -72,9 +72,9 @@ function tainacan_autoload($class_name){
}
if( in_array('Metadata_Types', $class_path) || in_array('Filter_Types', $class_path) ){
$exceptions = ['categorytaginput','categorycheckbox','categoryselectbox'];
$exceptions = ['taxonomytaginput','taxonomycheckbox','taxonomyselectbox'];
if( in_array( strtolower( $class_name ), $exceptions) ){
$dir.= 'category/';
$dir.= 'taxonomy/';
}else{
$dir.= strtolower(str_replace('_', '-' , $class_name)).'/';
}
@ -101,7 +101,7 @@ $Tainacan_Metadata->register_metadata_type('Tainacan\Metadata_Types\Date');
$Tainacan_Metadata->register_metadata_type('Tainacan\Metadata_Types\Numeric');
$Tainacan_Metadata->register_metadata_type('Tainacan\Metadata_Types\Selectbox');
$Tainacan_Metadata->register_metadata_type('Tainacan\Metadata_Types\Relationship');
$Tainacan_Metadata->register_metadata_type('Tainacan\Metadata_Types\Category');
$Tainacan_Metadata->register_metadata_type('Tainacan\Metadata_Types\Taxonomy');
$Tainacan_Metadata->register_metadata_type('Tainacan\Metadata_Types\Compound');
$Tainacan_Filters = \Tainacan\Repositories\Filters::get_instance();
@ -112,9 +112,9 @@ $Tainacan_Filters->register_filter_type('Tainacan\Filter_Types\Selectbox');
$Tainacan_Filters->register_filter_type('Tainacan\Filter_Types\Autocomplete');
$Tainacan_Filters->register_filter_type('Tainacan\Filter_Types\Taginput');
$Tainacan_Filters->register_filter_type('Tainacan\Filter_Types\Checkbox');
$Tainacan_Filters->register_filter_type('Tainacan\Filter_Types\CategoryTaginput');
$Tainacan_Filters->register_filter_type('Tainacan\Filter_Types\CategoryCheckbox');
$Tainacan_Filters->register_filter_type('Tainacan\Filter_Types\CategorySelectbox');
$Tainacan_Filters->register_filter_type('Tainacan\Filter_Types\TaxonomyTaginput');
$Tainacan_Filters->register_filter_type('Tainacan\Filter_Types\TaxonomyCheckbox');
$Tainacan_Filters->register_filter_type('Tainacan\Filter_Types\TaxonomySelectbox');
$Tainacan_Taxonomies = \Tainacan\Repositories\Taxonomies::get_instance();

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

@ -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,87 @@ 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'
]);
$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($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);
$bg_process = $this->bg_importer->data($data)->save();
if ( is_wp_error($bg_process->dispatch()) ) {
return false;
}
return $bg_process;
}
/**
* 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.
*
@ -72,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'
* ],
@ -100,7 +89,7 @@ abstract class Importer {
*/
protected $default_options = [];
private $accpets = [
private $accepts = [
'file' => true,
'url' => false,
];
@ -119,6 +108,7 @@ abstract class Importer {
protected $steps = [
[
'name' => 'Import Items',
'progress_label' => 'Importing Items',
'callback' => 'process_collections'
]
];
@ -190,13 +180,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 +276,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 +321,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 +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;
}
@ -418,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 );
}
/**
@ -464,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;
@ -480,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;
@ -536,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
@ -565,13 +671,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() {}
@ -668,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;
}
@ -684,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,34 +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' => 'Link relationship metadata',
'callback' => 'close_taxonomies'
],
[
'name' => 'Finalize',
'callback' => 'finish_processing'
],
[
'name' => 'Link Relationships',
'progress_label' => 'Link Relationships',
'callback' => 'link_relationships',
'total' => 5
]
];
@ -42,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');
@ -60,32 +62,36 @@ class Old_Tainacan extends Importer{
}
/**
* create taxonomies ( categories in tainacan old in first level )
* create taxonomies ( taxonomies in tainacan old in first level )
* next create the terms
*
*/
public function create_taxonomies() {
foreach ($this->get_taxonomies() as $taxonomy) {
$this->add_log('Creating taxonomies');
foreach ($this->get_taxonomies() as $taxonomy) {
$tax = new Entities\Taxonomy();
$tax->set_name( $category->name );
$tax->set_description( $category->description );
$tax->set_name( $taxonomy->name );
$tax->set_description( $taxonomy->description );
$tax->set_allow_insert('yes');
$tax->set_status('publish');
if ($tax->validate()) {
$tax = $this->tax_repo->insert($tax);
$this->add_log('Taxonomy ' . $tax->get_name() . ' created, id from Old'. $taxonomy->term_id );
$this->add_transient('tax_' . $term->term_id . '_id', $tax->get_id());
$this->add_transient('tax_' . $term->term_id . '_name', $tax->get_name());
$this->add_transient('tax_' . $taxonomy->term_id . '_id', $tax->get_id());
$this->add_transient('tax_' . $taxonomy->term_id . '_name', $tax->get_name());
if (isset($category->children) && $tax) {
$this->add_all_terms($tax, $category->children);
if (isset($taxonomy->children) && $tax) {
$this->add_all_terms($tax, $taxonomy->children);
}
} else {
$this->add_error_log('Error creating taxonomy ' . $category->name );
$this->add_error_log('Error creating taxonomy ' . $taxonomy->name );
$this->add_error_log($tax->get_errors());
$this->abort();
return false;
@ -103,7 +109,9 @@ class Old_Tainacan extends Importer{
*/
public function create_repo_metadata(){
foreach ($this->get_repo_metadata() as $metadata) {
$this->add_log('Creating repository metadata');
foreach ($this->get_repo_metadata() as $metadata) {
if (isset($metadata->slug) && strpos($metadata->slug, 'socialdb_property_fixed') === false) {
$metadatum_id = $this->create_metadata( $metadata );
@ -112,27 +120,341 @@ class Old_Tainacan extends Importer{
}
}
/**
* create all collections and its metadata
*
*/
public function create_collections(){
$this->add_log('Creating collections');
foreach ($this->fetch_collections() as $collection) {
$map = [];
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 ) {
if (isset($metadatum_old->slug) && strpos($metadatum_old->slug, 'socialdb_property_fixed') === false) {
$metadatum_id = $this->create_metadata( $metadatum_old, $collection_id );
if( $metadatum_id ){
$map[$metadatum_id] = $metadatum_old->id;
}
}
}
$this->add_collection([
'id' => $collection_id,
'mapping' => $map,
'total_items' => intval( $this->get_total_items_from_source( $collection->ID ) ),
'source_id' => $collection->ID
]);
}
}
}
/**
* Method responsible for links all relationships metadata
* @return int
*/
public function link_relationships(){
$collections = $this->col_repo->fetch([], 'OBJECT');
$this->add_log('Linking relationships');
if( $collections && is_array( $collections ) ){
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 );
$this->add_log('Relationship ' . $newMetadatum->get_name() . ' updated');
}
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 );
}
}
}
}
}
}
/**
* Method implemented by the child importer class to proccess each item
* @return int
*/
public function process_item( $index, $collection_id ){
$args = array(
'timeout' => 30,
'redirection' => 30,
);
$page = intval( $index ) + 1;
$this->add_log('Proccess item index' . $index . ' in collection OLD ' . $collection_id['source_id'] );
$info = wp_remote_get( $this->get_url() . $this->tainacan_api_address . "/collections/".$collection_id['source_id']."/items?includeMetadata=1&filter[items_per_page]=1&filter[page]=" . $page, $args );
$info = json_decode($info['body']);
if( !isset( $info->items ) ){
$this->add_error_log('Error in fetch remote (' . $this->get_url() . $this->tainacan_api_address . "/collections/".$collection_id['source_id']."/items?includeMetadata=1&filter[items_per_page]=1&filter[page]=" . $page);
$this->abort();
return false;
}
$the_item = null;
foreach( $info->items as $item ){
$the_item = $item;
}
if( isset($the_item) && isset($the_item->item) && !empty($the_item->item) ){
$item_Old = $the_item;
$this->add_log('item found ', $the_item->item->ID );
return [ 'item' => $item_Old, 'collection_definition' => $collection_id ];
} else {
$this->add_error_log('fetching remote (' . $this->get_url() . $this->tainacan_api_address . "/collections/".$collection_id['source_id']."/items?includeMetadata=1&filter[items_per_page]=1&filter[page]=" . $page);
$this->add_error_log('proccessing an item empty');
$this->abort();
return false;
}
}
/**
* insert processed item from source to Tainacan
*
* @param array $processed_item Associative array with metadatum source's as index with
* its value or values
* @param integet $collection_index The index in the $this->collections array of the collection the item is beeing inserted into
*
* @return Tainacan\Entities\Item Item inserted
*/
public function insert( $processed_item, $collection_index ) {
$collection_id = $processed_item['collection_definition'];
$item_Old = $processed_item['item']->item;
$collection = new Entities\Collection($collection_id['id']);
$item = new Entities\Item();
// get the id if exists
$id = $this->get_transient('item_' . $item_Old->ID . '_id');
if( $id && is_numeric( $id ) ) {
$this->add_log('Updating item ' . $item_Old->post_title . ' in collection ');
$item = new Entities\Item( $id );
}
$item->set_title( $item_Old->post_title );
$this->add_log('Begin insert ' . $item_Old->post_title . ' in collection ' . $collection_id['id'] );
$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($processed_item['item']->metadata) ){
$this->add_log('Item ' . $insertedItem->get_title() . ' inserted');
$this->add_item_metadata( $insertedItem, $processed_item['item']->metadata, $collection_id );
//inserting files
$this->insert_files( $item_Old, $insertedItem );
}
return $insertedItem;
} else {
$this->add_error_log( 'Error inserting item' );
$this->add_error_log( $item->get_errors() );
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['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 );
$this->add_log('Item Metadata inserted for item ' .$item->get_title() . ' and metadata ' . $newMetadatum->get_name() );
} 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
}
/**
* Method implemented by the child importer class to return the number of items to be imported
* @return int
*/
public function get_progress_total_from_source(){
public function get_total_items_from_source( $collection_id ) {
$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) ){
return $info->found_items;
} else {
return 0;
}
}
/**
* 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_source_metadata(){
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']);
if( !isset($info['body']) ){
$this->add_error_log($result->get_error_message());
$this->add_error_log('Error in fetch remote ' . $page . ' page item');
$this->abort();
return false;
}
}
return $items;
}
// AUX functions
@ -140,11 +462,11 @@ class Old_Tainacan extends Importer{
* decode request from wp_remote
* @return array/bool
*/
protected function decode_request($result){
protected function decode_request($result, $url){
if (is_wp_error($result)) {
$this->add_error_log($result->get_error_message());
$this->add_error_log('Error in fetch remote');
$this->add_error_log('Error in fetch remote' . $url);
$this->abort();
return false;
@ -157,17 +479,30 @@ class Old_Tainacan extends Importer{
return false;
}
/**
* return all taxonomies from tainacan old
* @return array
*/
protected function fetch_collections(){
$collections_link = $this->get_url() . $this->tainacan_api_address . "/collections";
$collections = $this->requester($collections_link);
$collections_array = $this->decode_request($collections, $collections_link);
return ($collections_array) ? $collections_array : [];
}
/**
* return all taxonomies from tainacan old
* @return array
*/
protected function get_taxonomies(){
$categories_link = $this->get_url() . $this->tainacan_api_address . "/categories";
$categories = wp_remote_get($categories_link);
$categories_array = $this->decode_request($categories);
$taxonomies_link = $this->get_url() . $this->tainacan_api_address . "/categories";
$taxonomies = $this->requester($taxonomies_link);
$taxonomies_array = $this->decode_request($taxonomies, $taxonomies_link);
return ($categories_array) ? $categories_array : [];
return ($taxonomies_array) ? $taxonomies_array : [];
}
/**
@ -177,24 +512,63 @@ class Old_Tainacan extends Importer{
protected function get_repo_metadata(){
$repository_meta_link = $this->get_url() . $this->tainacan_api_address . "/repository/metadata?includeMetadata=1";
$repo_meta = wp_remote_get($repository_meta_link);
$repo_meta_array = $this->decode_request($repo_meta);
$repo_meta = $this->requester($repository_meta_link);
$repo_meta_array = $this->decode_request($repo_meta, $repository_meta_link);
return ($repo_meta_array) ? $repo_meta_array : [];
}
/**
* return all metadata from collection
* @param $collection_id
* @return array
*/
protected function get_collection_metadata( $collection_id ){
$metadata = [];
$metadata_link = $this->get_url() . $this->tainacan_api_address . "/collections/".$collection_id."/metadata?includeMetadata=1";
$collection = $this->requester($metadata_link);
$collection_tabs = $this->decode_request($collection, $metadata_link);
if($collection_tabs){
foreach ($collection_tabs as $tab) {
if($tab->{'tab-properties'}){
$metadata = array_merge($metadata, $tab->{'tab-properties'});
}
}
}
return ($metadata) ? $metadata : [];
}
/**
* executes the request
*/
protected function requester( $link ){
$args = array(
'timeout' => 30,
'redirection' => 30,
);
return wp_remote_get($link, $args);
}
/**
* create recursively the terms from tainacan OLD
*
* @param Entities\Taxonomy $taxonomy_father
* @param array $children Array of categories from tainacan old
* @param array $children Array of taxonomies from tainacan old
* @param (optional) int $term_father the ID of father
*
* @return array
*/
protected function add_all_terms($taxonomy_father, $children, $term_father = null){
foreach ($children as $term) {
$this->add_log('adding terms');
foreach ($children as $term) {
$new_term = new Entities\Term();
$new_term->set_taxonomy($taxonomy_father->get_db_identifier());
@ -207,6 +581,17 @@ class Old_Tainacan extends Importer{
$inserted_term = $this->term_repo->insert($new_term);
if (is_wp_error($inserted_term)) {
$this->add_error_log($inserted_term->get_error_message());
$this->abort();
return false;
} else {
$this->add_log('Added term: ' . $inserted_term->get_name() . ' in tax: ' . $taxonomy_father->get_name());
$this->add_log('Added term before id ' . $term->term_id );
}
/*Insert old tainacan id*/
$this->add_transient('term_' . $term->term_id . '_id', $inserted_term->get_id());
$this->add_transient('term_' . $term->term_id . '_name', $inserted_term->get_name());
@ -225,7 +610,118 @@ class Old_Tainacan extends Importer{
* @return int $metadatum_id
*/
protected function create_metadata( $node_metadata_old, $collection_id = null){
//TODO: create process to insert different types of metadata
$newMetadatum = new Entities\Metadatum();
$meta = $node_metadata_old;
$name = $meta->name;
$type = $this->define_type($meta->type);
$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, "Taxonomy") === 0){
$taxonomy_id = $meta->metadata->taxonomy;
$related_taxonomy = $this->get_transient('tax_' . $taxonomy_id . '_id');
if ($related_taxonomy) {
$newMetadatum->set_metadata_type_options(['taxonomy_id' => $related_taxonomy]);
} else {
$this->add_log('Taxonomy ID not found: ' . $taxonomy_id);
$this->add_log('Skipping creating metadata ' . $name . ' taxonomy ID is required ' );
return false;
}
} else if(strcmp($type, "Relationship") === 0){
$relation_id = $meta->metadata->object_category_id;
$related_taxonomy = $this->get_transient('tax_' . $relation_id . '_id');
$related_name = $this->get_transient('tax_' . $relation_id . '_name');
if(isset($related_taxonomy)){
$newMetadatum->set_metadata_type_options(['collection_id' => $related_taxonomy]);
} else {
$this->add_log('Related Collection ID not found: ' . $relation_id);
$this->add_log('Skipping creating metadata ' . $name . ' Related Collection ID is required ' );
return false;
}
} else if(strcmp($type, "Compound") === 0){
if( isset( $meta->metadata->children ) ){
foreach( $meta->metadata->children as $child ){
$this->create_metadata( $node_metadata_old, $collection_id);
}
}
}
/*Properties of metadatum*/
if(isset($meta->metadata)){
if($meta->metadata->required == 1){
$newMetadatum->set_required(true);
}
if(!empty($meta->metadata->default_value)){
$newMetadatum->set_default_value($meta->metadata->default_value);
}
if(!empty($meta->metadata->cardinality)){
if($meta->metadata->cardinality > 1){
$newMetadatum->set_multiple('yes');
}
}
}
if($newMetadatum->validate()){
$inserted_metadata = $this->metadata_repo->insert( $newMetadatum );
$this->add_log('Metadata created: ' . $inserted_metadata->get_name());
$this->add_transient('metadata_' . $inserted_metadata->get_id() . '_id', $inserted_metadata->get_id());
if(isset( $related_name) ){
$this->add_transient('relation_' . $meta->id . '_name', $related_name);
}
return $inserted_metadata->get_id();
} else{
$this->add_error_log('Error creating metadata ' . $name );
$this->add_error_log($newMetadatum->get_errors());
$this->abort();
return false;
}
}
/**
* create the collection in tainacan
*
* @return int $metadatum_id
*/
protected function create_collection( $node_collection ){
$new_collection = new Entities\Collection();
$new_collection->set_name($node_collection->post_title);
$new_collection->set_status('publish');
$new_collection->validate();
if($new_collection->validate()){
$new_collection =$this->col_repo->insert($new_collection);
$this->add_log('Collection created: ' . $new_collection->get_name());
if( $new_collection )
$this->add_transient('collection_' . $node_collection->ID . '_name', $new_collection->get_id());
return $new_collection->get_id();
} else{
$this->add_error_log('Error creating collection ' . $node_collection->post_title );
$this->add_error_log($new_collection->get_errors());
$this->abort();
return false;
}
}
/**
@ -246,7 +742,7 @@ class Old_Tainacan extends Importer{
} else if(strcmp($type, 'item') === 0) {
$type = "Relationship";
} else if(strcmp($type, 'tree') === 0) {
$type = "Category";
$type = "Taxonomy";
} else if(strcmp($type, 'compound') === 0) {
$type = "Compound";
} else {
@ -255,4 +751,55 @@ 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' );
$this->add_log('Document imported from ' . $node_old->content_tainacan->guid);
}
} else if(filter_var($node_old->content_tainacan, FILTER_VALIDATE_URL)){
$item->set_document( $node_old->content_tainacan );
$item->set_document_type( 'url' );
$this->add_log('URL imported from ' . $node_old->content_tainacan);
}
}
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
]
];
@ -156,7 +162,7 @@ class Test_Importer extends Importer {
$metadatum = new Entities\Metadatum();
$metadatum->set_name('Colora');
$metadatum->set_collection($col1);
$metadatum->set_metadata_type('Tainacan\Metadata_Types\Category');
$metadatum->set_metadata_type('Tainacan\Metadata_Types\Taxonomy');
$metadatum->set_metadata_type_options([
'taxonomy_id' => $this->get_transient('tax_1_id'),
'allow_new_terms' => true
@ -177,7 +183,7 @@ class Test_Importer extends Importer {
$metadatum = new Entities\Metadatum();
$metadatum->set_name('Qualitya');
$metadatum->set_collection($col1);
$metadatum->set_metadata_type('Tainacan\Metadata_Types\Category');
$metadatum->set_metadata_type('Tainacan\Metadata_Types\Taxonomy');
$metadatum->set_metadata_type_options([
'taxonomy_id' => $this->get_transient('tax_2_id'),
'allow_new_terms' => true
@ -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();

Some files were not shown because too many files have changed in this diff Show More