Merge branch 'develop' into exposers

This commit is contained in:
Jacson Passold 2018-03-22 21:39:45 -03:00
commit e744fc4635
173 changed files with 9362 additions and 4091 deletions

View File

@ -0,0 +1,7 @@
<?php
return [
'tests_dir' => '/tmp/wordpress-tests-lib',
];
?>

View File

@ -1,11 +1,19 @@
#!/bin/sh
#!/bin/bash
## Run the build script whenever there is a change in src folder
echo 'Watching changes on src/'
while inotifywait -qqr src -e create,move,modify,delete; do
current_OS=`uname`
# For macOS (Darwin) is needed fsevents-tools installed (you can use homebrew install fsevents-tools)
if [ $current_OS == "Darwin" ]; then
echo
echo 'Change detected, running build'
./build.sh
done
notifyloop src ./build.sh
else
while inotifywait -qqr src -e create,move,modify,delete; do
echo
echo 'Change detected, running build'
./build.sh
done
fi

View File

@ -1,4 +1,6 @@
{
"projectId": "tubzok",
"videoRecording": false
"videoRecording": false,
"viewportWidth": 1280,
"viewportHeight": 720
}

View File

@ -0,0 +1,791 @@
describe('Fields text test', function () {
beforeEach(() => {
cy.loginByUI()
})
it('clear DB', function(){
cy.clearDB()
})
it('create collection for create fields', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.contains('New Collection').click()
cy.get('#tainacan-text-name').type('Book Fields')
cy.get('#tainacan-text-description').type('Descrição book Fields')
cy.get('#tainacan-select-status').select('Publish').should('have.value', 'publish')
cy.get('#button-submit-collection-creation').click()
cy.get('#primary-menu > .menu > .menu-header > .menu-list > li > .router-link-active > .icon > .mdi').click()
cy.get('.b-table').should('contain', 'Book Fields')
})
context('create text-type fields', function(){
it('canceled create text field public', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(1)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('Text 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', 'Text name canceled')
})
it('create text field public', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(1)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('Text name public')
cy.get('.textarea').type('name book description')
cy.get('#tainacan-select-status-publish > .check').click()
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'Text name public')
})
it('create text field private', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(1)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('Text name private')
cy.get('.textarea').type('name book description')
cy.get('#tainacan-select-status-private > .check').click()
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'Text name private')
})
it('create text field public required', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(1)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('Text name public required')
cy.get('.textarea').type('name book description required')
cy.get('#tainacan-select-status-publish > .check').click()
cy.get(':nth-child(2) > .b-checkbox > .check').click()
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'Text name public required')
})
it('create text field public multiple values', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(1)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('Text 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(3) > .b-checkbox > .check').click()
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'Text name public multiple values')
})
it('create text field public unique values', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(1)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('Text 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(4) > .b-checkbox > .check').click()
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'Text name public unique values')
})
it('check if fields are updated to page', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.active-fields-area >').should('not.contain', 'Text name canceled')
cy.get('.active-fields-area >').should('contain', 'Text name public')
cy.get('.active-fields-area >').should('contain', 'Text name private')
cy.get('.active-fields-area >').should('contain', 'Text name public required')
cy.get('.active-fields-area >').should('contain', 'Text name public multiple values')
cy.get('.active-fields-area >').should('contain', 'Text name public unique values')
})
})
context('delete text-type fields', function(){
it('delete fields created texts', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get(':nth-child(3) > .handle > .controls > :nth-child(3) > .icon > .mdi').click()
cy.get(':nth-child(4) > .handle > .controls > :nth-child(3) > .icon > .mdi').click()
cy.get(':nth-child(5) > .handle > .controls > :nth-child(3) > .icon > .mdi').click()
cy.get(':nth-child(6) > .handle > .controls > :nth-child(3) > .icon > .mdi').click()
cy.get(':nth-child(7) > .handle > .controls > :nth-child(3) > .icon > .mdi').click()
})
})
context('create textArea-type fields', function(){
it('canceled create textArea field public', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(2)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('TextArea 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', 'TextArea name canceled')
})
it('create textArea field public', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(2)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('TextArea name public')
cy.get('.textarea').type('name book description')
cy.get('#tainacan-select-status-publish > .check').click()
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'TextArea name public')
})
it('create textArea field private', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(2)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('TextArea name private')
cy.get('.textarea').type('name book description')
cy.get('#tainacan-select-status-private > .check').click()
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'TextArea name private')
})
it('create textArea field public required', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(2)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('TextArea name public required')
cy.get('.textarea').type('name book description required')
cy.get('#tainacan-select-status-publish > .check').click()
cy.get(':nth-child(2) > .b-checkbox > .check').click()
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'TextArea name public required')
})
it('create textArea field public multiple values', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(2)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('TextArea 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(3) > .b-checkbox > .check').click()
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'TextArea name public multiple values')
})
it('create textArea field public unique values', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(2)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('TextArea 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(4) > .b-checkbox > .check').click()
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'TextArea name public unique values')
})
it('check if fields are updated to page', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.active-fields-area >').should('not.contain', 'Text name canceled')
cy.get('.active-fields-area >').should('contain', 'TextArea name public')
cy.get('.active-fields-area >').should('contain', 'TextArea name private')
cy.get('.active-fields-area >').should('contain', 'TextArea name public required')
cy.get('.active-fields-area >').should('contain', 'TextArea name public multiple values')
cy.get('.active-fields-area >').should('contain', 'TextArea name public unique values')
})
})
context('delete textArea-type fields', function(){
it('delete fields created texts', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get(':nth-child(3) > .handle > .controls > :nth-child(3) > .icon > .mdi').click()
cy.get(':nth-child(4) > .handle > .controls > :nth-child(3) > .icon > .mdi').click()
cy.get(':nth-child(5) > .handle > .controls > :nth-child(3) > .icon > .mdi').click()
cy.get(':nth-child(6) > .handle > .controls > :nth-child(3) > .icon > .mdi').click()
cy.get(':nth-child(7) > .handle > .controls > :nth-child(3) > .icon > .mdi').click()
})
})
context('create date-type fields', function(){
it('canceled create date field public', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(3)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('date 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', 'date name canceled')
})
it('create date field public', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(3)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('date name public')
cy.get('.textarea').type('name book description')
cy.get('#tainacan-select-status-publish > .check').click()
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'date name public')
})
it('create date field private', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(3)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('date name private')
cy.get('.textarea').type('name book description')
cy.get('#tainacan-select-status-private > .check').click()
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'date name private')
})
it('create date field public required', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(3)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('date name public required')
cy.get('.textarea').type('name book description required')
cy.get('#tainacan-select-status-publish > .check').click()
cy.get(':nth-child(2) > .b-checkbox > .check').click()
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'date name public required')
})
it('create date field public multiple values', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(3)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('date 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(3) > .b-checkbox > .check').click()
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'date name public multiple values')
})
it('create date field public unique values', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(3)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('date 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(4) > .b-checkbox > .check').click()
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'date name public unique values')
})
it('check if fields are updated to page', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.active-fields-area >').should('not.contain', 'Text name canceled')
cy.get('.active-fields-area >').should('contain', 'date name public')
cy.get('.active-fields-area >').should('contain', 'date name private')
cy.get('.active-fields-area >').should('contain', 'date name public required')
cy.get('.active-fields-area >').should('contain', 'date name public multiple values')
cy.get('.active-fields-area >').should('contain', 'date name public unique values')
})
})
context('create numeric-type fields', function(){
it('canceled create date field public', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(4)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('numeric 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', 'numeric name canceled')
})
it('create numeric field public', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(4)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('numeric name public')
cy.get('.textarea').type('name book description')
cy.get('#tainacan-select-status-publish > .check').click()
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'numeric name public')
})
it('create numeric field private', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(4)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('numeric name private')
cy.get('.textarea').type('name book description')
cy.get('#tainacan-select-status-private > .check').click()
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'numeric name private')
})
it('create numeric field public required', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(4)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('numeric name public required')
cy.get('.textarea').type('name book description required')
cy.get('#tainacan-select-status-publish > .check').click()
cy.get(':nth-child(2) > .b-checkbox > .check').click()
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'numeric name public required')
})
it('create numeric field public multiple values', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(4)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('numeric 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(3) > .b-checkbox > .check').click()
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'numeric name public multiple values')
})
it('create numeric field public unique values', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(4)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('numeric 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(4) > .b-checkbox > .check').click()
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'numeric name public unique values')
})
it('check if fields are updated to page', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.active-fields-area >').should('not.contain', 'Text name canceled')
cy.get('.active-fields-area >').should('contain', 'numeric name public')
cy.get('.active-fields-area >').should('contain', 'numeric name private')
cy.get('.active-fields-area >').should('contain', 'numeric name public required')
cy.get('.active-fields-area >').should('contain', 'numeric name public multiple values')
cy.get('.active-fields-area >').should('contain', 'numeric name public unique values')
})
})
context('create select-type fields', function(){
it('canceled create select field public', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(5)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('select 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', 'select name canceled')
})
it('create select field public', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(5)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('select name public')
cy.get('.textarea').type('name book description')
cy.get('#tainacan-select-status-publish > .check').click()
cy.get('.autocomplete > .control > .input').type('select1{enter}')
cy.get('.autocomplete > .control > .input').type('select2{enter}')
cy.get('.autocomplete > .control > .input').type('select3{enter}')
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'select name public')
})
it('create select field private', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(5)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('select name private')
cy.get('.textarea').type('name book description')
cy.get('#tainacan-select-status-private > .check').click()
cy.get('.autocomplete > .control > .input').type('select1{enter}')
cy.get('.autocomplete > .control > .input').type('select2{enter}')
cy.get('.autocomplete > .control > .input').type('select3{enter}')
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'select name private')
})
it('create select field public required', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(5)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('select name public required')
cy.get('.textarea').type('name book description required')
cy.get('#tainacan-select-status-publish > .check').click()
cy.get(':nth-child(2) > .b-checkbox > .check').click()
cy.get('.autocomplete > .control > .input').type('select1{enter}')
cy.get('.autocomplete > .control > .input').type('select2{enter}')
cy.get('.autocomplete > .control > .input').type('select3{enter}')
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'select name public required')
})
it('create select field public multiple values', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(5)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('select 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(3) > .b-checkbox > .check').click()
cy.get('.autocomplete > .control > .input').type('select1{enter}')
cy.get('.autocomplete > .control > .input').type('select2{enter}')
cy.get('.autocomplete > .control > .input').type('select3{enter}')
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'select name public multiple values')
})
it('create select field public unique values', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(5)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('select 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(4) > .b-checkbox > .check').click()
cy.get('.autocomplete > .control > .input').type('select1{enter}')
cy.get('.autocomplete > .control > .input').type('select2{enter}')
cy.get('.autocomplete > .control > .input').type('select3{enter}')
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'select name public unique values')
})
it('check if fields are updated to page', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('[data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.active-fields-area >').should('not.contain', 'Text name canceled')
cy.get('.active-fields-area >').should('contain', 'select name public')
cy.get('.active-fields-area >').should('contain', 'select name private')
cy.get('.active-fields-area >').should('contain', 'select name public required')
cy.get('.active-fields-area >').should('contain', 'select name public multiple values')
cy.get('.active-fields-area >').should('contain', 'select name public unique values')
})
})
context('create relationship-type fields', function(){
it('create collection for create relationship', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.contains('New Collection').click()
cy.get('#tainacan-text-name').type('Book relationship')
cy.get('#tainacan-text-description').type('Descrição book relationship')
cy.get('#tainacan-select-status').select('Publish').should('have.value', 'publish')
cy.get('#button-submit-collection-creation').click()
cy.get('#primary-menu > .menu > .menu-header > .menu-list > li > .router-link-active > .icon > .mdi').click()
cy.get('.b-table').should('contain', 'Book relationship')
})
it('canceled create select field public', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get(':nth-child(2) > [data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(6)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('relationship 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', 'relationship name canceled')
})
it('create relationship field public', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get(':nth-child(2) > [data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(6)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('relationship name public')
cy.get('.textarea').type('name book description')
cy.get('#tainacan-select-status-publish > .check').click()
cy.get('select').select('Book relationship')
cy.get(':nth-child(1) > .b-checkbox > .check').click()
cy.get('.block > :nth-child(2) > .b-checkbox > .check').click()
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'relationship name public')
})
it('create relationship field private', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get(':nth-child(2) > [data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(6)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('relationship name private')
cy.get('.textarea').type('name book description')
cy.get('#tainacan-select-status-private > .check').click()
cy.get('select').select('Book relationship')
cy.get(':nth-child(1) > .b-checkbox > .check').click()
cy.get('.block > :nth-child(2) > .b-checkbox > .check').click()
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'relationship name private')
})
it('create relationship field public required', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get(':nth-child(2) > [data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(6)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('relationship name public required')
cy.get('.textarea').type('name book description required')
cy.get('#tainacan-select-status-publish > .check').click()
cy.get(':nth-child(2) > .b-checkbox > .check').click()
cy.get('select').select('Book relationship')
cy.get(':nth-child(1) > .b-checkbox > .check').click()
cy.get('.block > :nth-child(2) > .b-checkbox > .check').click()
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'relationship name public required')
})
it('create relationship field public multiple values', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get(':nth-child(2) > [data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(6)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('relationship 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(3) > .b-checkbox > .check').click()
cy.get('select').select('Book relationship')
cy.get(':nth-child(1) > .b-checkbox > .check').click()
cy.get('.block > :nth-child(2) > .b-checkbox > .check').click()
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'relationship name public multiple values')
})
it('create relationship field public unique values', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get(':nth-child(2) > [data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.field > :nth-child(2) > :nth-child(6)').click()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').clear()
cy.get('#fieldEditForm > :nth-child(1) > .control > .input').type('relationship 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(4) > .b-checkbox > .check').click()
cy.get('select').select('Book relationship')
cy.get(':nth-child(1) > .b-checkbox > .check').click()
cy.get('.block > :nth-child(2) > .b-checkbox > .check').click()
cy.get(':nth-child(2) > .button').click()
cy.get('.active-fields-area >').should('contain', 'relationship name public unique values')
})
it('check if fields are updated to page', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get(':nth-child(2) > [data-label="Name"] > :nth-child(1) > .clickable-row').click()
cy.get(':nth-child(4) > .router-link-active').should('contain', 'Items')
cy.get('.menu > :nth-child(2) > :nth-child(5) > a').click()
cy.get('h1').should('contain', 'Collection Fields Edition Page')
cy.get('.active-fields-area >').should('not.contain', 'Text name canceled')
cy.get('.active-fields-area >').should('contain', 'relationship name public')
cy.get('.active-fields-area >').should('contain', 'relationship name private')
cy.get('.active-fields-area >').should('contain', 'relationship name public required')
cy.get('.active-fields-area >').should('contain', 'relationship name public multiple values')
cy.get('.active-fields-area >').should('contain', 'relationship name public unique values')
})
})
})

View File

@ -0,0 +1,114 @@
describe('Tainacan Plugin Test', function () {
beforeEach(() => {
cy.loginByUI()
})
context('Collections', function(){
it('clear DB', function(){
cy.clearDB()
})
it('canceled collection', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.contains('New Collection').click()
cy.get('#tainacan-text-name').type('Book cancelado')
cy.get('#tainacan-text-description').type('Descrição book cancelado')
cy.get('#button-cancel-collection-creation').click()
cy.url().should('contain', '/wp-admin/admin.php?page=tainacan_admin#/collections/')
cy.get('h1').should('contain', 'Collections Page')
cy.get('td').should('not.contain', 'Book cancelado')
})
it('create collection', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.contains('New Collection').click()
cy.get('#tainacan-text-name').type('Book 1')
cy.get('#tainacan-text-description').type('Descrição book 1')
cy.get('#tainacan-select-status').select('Publish').should('have.value', 'publish')
cy.get('#button-submit-collection-creation').click()
cy.get('#primary-menu > .menu > .menu-header > .menu-list > li > .router-link-active > .icon > .mdi').click()
cy.get('.b-table').should('contain', 'Book 1')
})
it('delete collection', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.contains('New Collection').click()
cy.get('#tainacan-text-name').type('Book deletado')
cy.get('#tainacan-text-description').type('Descrição book deletado')
cy.get('#tainacan-select-status').select('Publish').should('have.value', 'publish')
cy.get('#button-submit-collection-creation').click()
cy.get('#primary-menu > .menu > .menu-header > .menu-list > li > .router-link-active > .icon > .mdi').click()
cy.get('.b-table').should('contain', 'Book deletado')
cy.get(':nth-child(1) > [data-label="Actions"] > :nth-child(1) > #button-delete > .icon > .mdi').click()
cy.get('.modal-card-body').should('contain', 'Do you really want to delete this collection?')
cy.get('.is-primary').click()
cy.get('.b-table').should('not.contain', 'Book deletado')
})
})
context('Items', function(){
it('canceled create item', function(){
cy.clearDB()
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.contains('New Collection').click()
cy.get('#tainacan-text-name').type('Book com items')
cy.get('#tainacan-text-description').type('Descrição book com items')
cy.get('#tainacan-select-status').select('Publish').should('have.value', 'publish')
cy.get('#button-submit-collection-creation').click()
cy.get('.b-table').should('contain', 'New Item')
cy.contains('New Item').click()
cy.get('#tainacan-text-title').type('Item cancelado')
cy.get('#tainacan-textarea-description').type('Item cancelado descrição')
cy.get('#status-select').select('Publish').should('have.value', 'publish')
cy.get('#button-cancel-item-creation').click()
cy.get('.b-table').should('not.contain', 'Item cancelado')
})
it('create item', function(){
cy.clearDB()
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.contains('New Collection').click()
cy.get('#tainacan-text-name').type('Book com items')
cy.get('#tainacan-text-description').type('Descrição book com items')
cy.get('#tainacan-select-status').select('Publish').should('have.value', 'publish')
cy.get('#button-submit-collection-creation').click()
cy.get('.b-table').should('contain', 'New Item')
cy.contains('New Item').click()
cy.get('#tainacan-text-title').type('Item 1')
cy.get('#tainacan-textarea-description').type('Item 1 descrição')
cy.get('#status-select').select('Publish').should('have.value', 'publish')
cy.get('#button-submit-item-creation').click()
cy.get('h1').should('contain', 'Item Page')
cy.get('.page-container').should('contain', 'Item 1')
})
it('delete item', function(){
cy.clearDB()
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.contains('New Collection').click()
cy.get('#tainacan-text-name').type('Book 2')
cy.get('#tainacan-text-description').type('Descrição book 2')
cy.get('#tainacan-select-status').select('Publish').should('have.value', 'publish')
cy.get('#button-submit-collection-creation').click()
cy.get('.b-table').should('contain', 'New Item')
cy.contains('New Item').click()
cy.get('#tainacan-text-title').type('Item 1')
cy.get('#tainacan-textarea-description').type('Item 1 descrição')
cy.get('#status-select').select('Publish').should('have.value', 'publish')
cy.get('#button-submit-item-creation').click()
cy.get('h1').should('contain', 'Item Page')
cy.get('#secondary-menu > .menu > :nth-child(2) > :nth-child(3) > .router-link-active').click()
cy.get('.b-table').should('contain', 'Item 1')
cy.get(':nth-child(1) > [data-label="Actions"] > :nth-child(1) > #button-delete > .icon > .mdi').click()
cy.get('.modal-card-body').should('contain', 'Do you really want to delete this item?')
cy.get('.is-primary').click()
cy.get('.b-table').should('not.contain', 'Item 1')
})
})
})

View File

@ -0,0 +1,23 @@
describe('Configuration Plugin Test', function () {
beforeEach(() => {
cy.loginByUI()
})
context ('Configuration', function(){
it('plugins active', function () {
cy.visit('wp-admin/plugins.php')
cy.get('.subsubsub > .active > a').click()
cy.get('.wp-list-table').should('contain', 'Tainacan').and('contain', 'WP Cypress DB Cleaner')
})
it('WPress configuration', function(){
cy.contains('WPress').click()
cy.get('#default-api-namespace').clear()
cy.get('#default-api-namespace').type('tainacan/v2')
cy.get('#default-db-prefix').clear()
cy.get('#default-db-prefix').type('wptests_')
cy.get('#submit').click()
})
})
})

View File

@ -1,46 +0,0 @@
describe('Tainacan Plugin Test', function () {
beforeEach(() => {
cy.loginByUI()
})
context('Collections', function(){
it('canceled collection', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.contains('New Collection').click()
cy.get('[id=tainacan-text-name]').type('Book cancelado')
cy.get('[id=button-cancel-collection-creation]').click()
cy.url().should('contain', '/wp-admin/admin.php?page=tainacan_admin#/collections/')
cy.get('h1').should('contain', 'Collections Page')
cy.get('td').should('not.contain', 'Book cancelado')
})
it('status field blank collection', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.contains('New Collection').click()
cy.get('[id=tainacan-text-name]').type('Ebook status em branco')
cy.get('[id=tainacan-text-description]').type('Importante a organização dos livros para estimular a leitura pelos usuários da biblioteca')
cy.get('[id=button-submit-collection-creation]').click()
cy.get('td').should('contain', 'New Item')
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.get('td').should('not.contain', 'Book cancelado')
})
it('create collection', function(){
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('h1').should('contain', 'Collections Page')
cy.contains('New Collection').click()
cy.get('[id=tainacan-text-name]').type('Ebook 1')
cy.get('[id=tainacan-text-description]').type('Importante a organização dos livros para estimular a leitura pelos usuários da biblioteca')
cy.get('[id=tainacan-select-status]').select('Publish').should('have.value', 'publish')
cy.get('[id=button-submit-collection-creation]').click()
cy.get('td').should('contain', 'New Item')
cy.visit('/wp-admin/admin.php?page=tainacan_admin#/collections')
cy.get('td').should('contain', 'Ebook 1')
})
})
})

View File

@ -1,18 +0,0 @@
describe('Configuration Plugin Test', function () {
beforeEach(() => {
cy.loginByUI()
})
context ('Configuration', function(){
it('plugins page', function(){
cy.visit('wp-admin/plugins.php')
cy.get('h1').should('contain', 'Plugins')
})
it('plugin active', function () {
cy.contains('Tainacan').click()
cy.get('h1').should('contain', 'Collections Page')
})
})
})

View File

@ -80,3 +80,7 @@ Cypress.Commands.add('loginByUI', () => {
cy.url().should('include', '/wp-admin')
cy.get('h1').should('contain', 'Dashboard')
})
Cypress.Commands.add('clearDB', () => {
cy.request('POST', '/wp-json/tainacan/v2/database')
})

View File

@ -0,0 +1,39 @@
# Exporting and Exposing your Repository
When you buid a digital repository with Tainacan, you gain the ability to show it to the world in many different ways thanks to the power and flexibility of WordPress.
But sometimes you dont want just to have your collections browsable via web, you want to download a spreadsheet to work with or you want to make it availabe via APIs so it can be consumed by other applications or harvested by an aggregator. This page describe how Tainacan handle with these situations.
## Mapping
With Tainacan you have the possibility to map your collection structure to one or more known standards you may want to be compatible with. So even if you use a custom set of fields to describe your collection, you may be compatible and interoperate with other repositories.
You do it by informing, for each field you create, what is it relative in each format you want to map your collection to. You may sau for example, that you "Name" Field is the equivalent to the dc:Title attribute in Dublin Core and some another attribute in other format you choose.
Tainacan is shipped with some Mapping standards that implement popular metadata standards. And it will be easy to create new standards. See more [details about mapping standards](mapping-standards.md).
Note: When you use a preset to build your collection, chances are that the mapping is already done. This is a good reason to consider using presets ;)
Note 2: If the mapping standard you mapped your collection to supports it, you will be able to expose your collection en JSON-LD format!
## Exporting
Exporting allows you to download the content of your repository to a file - or to multiple files. The format of the package you will download depends on the exporter you will use. Tainacan ships with a simple CSV exporter and a Tainacan-Package exporter, that allows you to export all the content of your collections, including the attachments, to import in another Tainacan instance.
Whatever exporter you choose to you use, you will be able to choose wether you want to download the collection as it is, which means, with the fields the way the were created in Tainacan, or wether you want to download it in a mapped version. For example, if you mapped your collection to Dublin Core, you can download a CSV file either in Dublin Core format or in the original format.
Tainacan makes it very easy to developers to create new exporters and publish them as plugins anyone can use.
## Exposing
Tainacan is powered with an API that allows other applications to search and consume the content of your repository. By default, this API serves the content in JSON format, preserving the fields in the collections the way you created them.
In the same way you can choose the format of the file when you export your collection, one can choose the format he/she want to consume yout content in. This is what exposers are for.
Each exposer implements a different way of presenting your data in the API response, and may support one or many mappings. See more [details about exposers](exposers.md).
For example, the default JSON exposer supports any mapping and can serve your content exposing any metadata standard you mapped your content to. The decision is in the hands of the application that makes the request to your API.
On the other hand, OAI-PMH exposer only supports Dublin Core mapping and will allways serve content this way.
Exposers are also really easy to develop and can be added to your Tainacan instance via plugins.

25
docs/exposers.md Normal file
View File

@ -0,0 +1,25 @@
# Exposers
Exposers are declarations and methods that expose the items of your repository in a certain way.
## Structure
### Name
The name of the Exposer.
### Slug
A URL friendly version of the Exposer name, to be used as a parameter to the API request informing you want to get the data using this exposer.
### Supported Mapping Standard
A list of mapping standards that is exposer supports. This means that whenever someone makes a request to receive that via this exposer, he/she will also be able to choose in which mapping standar they want the content to be served.
### Methods
Every exposer have to implement PHP methods that will build the API response.
Optionally, an exposer can also implement a method to print data in the `HEAD` section of the HTML when visiting an item page. For example, JSON-LD exposer can add a JSON-LD object to the head of the page of every item in your collection.

View File

@ -3,10 +3,9 @@
The typical workflow when you create a Digital Repository with Tainacan is:
* Create a collection
* Configure which fields the item in this collections will have
* Configure the collection
* Configure which filters will be used when browsing the collection
* Upload items to the collection or import them from an external source
* Choose which fields the item in this collections will have
* Choose which filters will be used when browsing the collection
* Insert items to the collection or import them from an external source
## Collections
@ -30,7 +29,7 @@ Each field has a set of settings. Is it required? Is it supposed to be unique (a
You may have repository-level fields, that will be inherited by all collections of your repository. In the same way, collections inherit fields from their parent collection.
(Note: you can import/export presets of field)
(Note: you can use and import/export presets of fields)
## Field Types
@ -58,4 +57,34 @@ Filter Types can be created via plugins and extend the default set of types ship
Categories (or Taxonomies) can be created and used to classify items. Typical Taxonomies are Genre, Country, etc.
They are the same WordPress Taxonomies you already know, and they can be shared among many collections.
In WordPress language, they are 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".
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").
Terms also have a description, may have an icon or image that represents it and may also be linked to a existing concept of an ontology. They can have their own URL in your site, with a page listing all items that are related to them, despite their collection. In that way, they behave as if they were a collection themselves.
## Item types
Item types gives you the abiity to specialize the desription of an item based on its nature. So, inside the same collection you may have items that vary in its nature and, therefore, have a different set of metadata.
For each item type you can choose a group of Fields, in the same way you do for a collection. When you create an item inside a collection, it will have all the fields chosen for that collection plus the fields related to its type.
AN item type can be anything. For example, LPs, Books and paintings are õbvious distinct item types that may have specific fields. But it could also more abstract concepts, such as "financial transactions".
## Under discussion
### Desktop
Desktop holds items that are not part of any collections yet. You might want to use it when you want to upload a bunch of items and organize them afterwards, instead of having to thinh an prepare all the collections beforehand.
Items in Desktop are not publicly visible and have only the fields configured in repository level.
### Thematic Collections
Thematic Collections is another way to organize the items in your repository. In essecen, they are a Category, that can hold items from any collections, and an item can be part of many Thematic Collections.
They work in exactly the same way as categories, the only difference is that you have another way to manage it,..
Another idea here is, intead of having a "fixed category" called thematic collections, we could just have a menu item "Categories" or "Organize by categories" that lets you browse the items by category, instead of by collections, and manipulate them.

79
docs/mapping-standards.md Normal file
View File

@ -0,0 +1,79 @@
# Mapping Standards
Mapping Standards are declarations of standards of metadata. Once they are available and activated in your repository, you can map the fields of your collections to them.
## Structure
A Mapping Standard has the following attributes.
### Name
The name of the Mapping Standard.
### Fields
A list of fields, terms or attributes that this mapping have. These are the element you will be able to map your Collection's Fields.
Each field has the following attributes:
* Name - The field name, that refers to the name of the attribute in the origin vocabulary or ontology (e.g. title)
* Label - The human readable name
* URI - The URI of this term/attribute in the origin Ontoloy/Vocabulary
### Allow additional custom fields
Boolen indicating wether this mapping allows additional custom fields to be added.
### Context URL / Vocab URL
The URL of the Ontology or vocabulary. For example `http://schema.org` or `http://dublincore.org/documents/dcmi-terms/`
### Type
The Class of the ontology that this mapping refers to. For example `CreativeWork`, which is a class of Schema.org.
## Examples
```
{
'name': 'Dublin Core',
'fields': {
{
'name': 'title',
'label': 'Title',
'URI': 'http://purl.org/dc/terms/title'
},
{
'name': 'publisher',
'label': 'Publisher',
'URI': 'http://purl.org/dc/terms/publisher'
},
... And so on...
},
'allow_extra_fields': true,
'context_url': 'http://dublincore.org/documents/dcmi-terms/'
}
```
```
{
'name': 'Schema.org Creative Works',
'fields': {
{
'name': 'name',
'label': 'Name',
'URI': 'http://schema.org/name'
},
{
'name': 'alternativeHeadline',
'label': 'Alternative Headline',
'URI': 'http://schema.org/alternativeHeadline'
},
... And so on...
},
'allow_extra_fields': false,
'context_url': 'http://schema.org',
'type': 'CreativeWork'
}
```

View File

@ -11,7 +11,9 @@ source build-config.cfg
./build.sh
plugin_name=`basename $wp_plugin_dir`
plugin_tainacan=`basename $wp_plugin_dir`
plugin_wpclear='wpress-db-cleaner'
test_db_prefix='wptests_'
cy_record_key='a15e6599-d240-4d98-b582-dea93a3008c0'
@ -26,7 +28,7 @@ echo "Installing WordPress..."
wp core install --url=$wp_url --title=Test --admin_user=admin --admin_password=admin --admin_email=admin@admin.com
# Activate Tainacan
wp plugin activate $plugin_name
wp plugin activate $plugin_tainacan $plugin_wpclear
# back to tainacan dev directory
cd -

View File

@ -3,126 +3,188 @@
namespace Tainacan;
class Admin {
private $menu_slug = 'tainacan_admin';
public function __construct() {
private $menu_slug = 'tainacan_admin';
private static $instance = null;
add_action( 'admin_menu', array(&$this, 'add_admin_menu') );
add_filter( 'admin_body_class', array(&$this, 'admin_body_class') );
add_action( 'init', array(&$this, 'register_user_meta') );
public static function getInstance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
}
return self::$instance;
}
function add_admin_menu() {
$page_suffix = add_menu_page(
__('Tainacan', 'tainacan'),
__('Tainacan', 'tainacan'),
'edit_posts',
$this->menu_slug,
array(&$this, 'admin_page'),
plugin_dir_url(__FILE__) . 'images/tainacan_logo_symbol.svg'
);
private function __construct() {
add_action( 'load-' . $page_suffix, array(&$this, 'load_admin_page'));
}
function load_admin_page() {
add_action( 'admin_enqueue_scripts', array(&$this, 'add_admin_css'), 90 );
}
function login_styles_reset( $style ) {
if ( strpos( $style, 'wp-admin-css') !== FALSE ) {
$style = NULL;
}
return $style;
}
add_action( 'admin_menu', array( &$this, 'add_admin_menu' ) );
add_filter( 'admin_body_class', array( &$this, 'admin_body_class' ) );
function add_admin_css() {
global $TAINACAN_BASE_URL;
add_action( 'init', array( &$this, 'register_user_meta' ) );
wp_enqueue_style('tainacan-admin-page', $TAINACAN_BASE_URL . '/assets/css/tainacan-admin.css' );
}
$undesired_wp_styles = [ 'admin-menu', 'admin-bar', 'code-editor', 'color-picker',
'customize-controls', 'customize-nav-menus', 'customize-widgets', 'dashboard',
'dashicons', 'deprecated-media', 'edit', 'wp-pointer', 'farbtastic', 'forms', 'common',
'install', 'wp-auth-check', 'site-icon', 'buttons', 'l10n', 'list-tables','login',
'media', 'nav-menus', 'revisions', 'themes', 'widgets', 'wp-admin'];
wp_dequeue_style($undesired_wp_styles);
wp_deregister_style($undesired_wp_styles);
}
function admin_body_class($classes) {
global $pagenow;
if ($pagenow == 'admin.php' && isset($_GET['page']) && $_GET['page'] == $this->menu_slug) {
$classes .= ' tainacan-admin-page';
}
return $classes;
}
function admin_page() {
global $TAINACAN_BASE_URL, $Tainacan_Collections, $Tainacan_Fields, $Tainacan_Filters, $Tainacan_Items, $Tainacan_Taxonomies;
function add_admin_menu() {
$page_suffix = add_menu_page(
__( 'Tainacan', 'tainacan' ),
__( 'Tainacan', 'tainacan' ),
'edit_posts',
$this->menu_slug,
array( &$this, 'admin_page' ),
plugin_dir_url( __FILE__ ) . 'images/tainacan_logo_symbol.svg'
);
add_action( 'load-' . $page_suffix, array( &$this, 'load_admin_page' ) );
}
function load_admin_page() {
add_action( 'admin_enqueue_scripts', array( &$this, 'add_admin_css' ), 90 );
}
function login_styles_reset( $style ) {
if ( strpos( $style, 'wp-admin-css' ) !== false ) {
$style = null;
}
return $style;
}
function add_admin_css() {
global $TAINACAN_BASE_URL;
wp_enqueue_style( 'tainacan-admin-page', $TAINACAN_BASE_URL . '/assets/css/tainacan-admin.css' );
$undesired_wp_styles = [
'admin-menu',
'admin-bar',
'code-editor',
'color-picker',
'customize-controls',
'customize-nav-menus',
'customize-widgets',
'dashboard',
'dashicons',
'deprecated-media',
'edit',
'wp-pointer',
'farbtastic',
'forms',
'common',
'install',
'wp-auth-check',
'site-icon',
'buttons',
'l10n',
'list-tables',
'login',
'media',
'nav-menus',
'revisions',
'themes',
'widgets',
'wp-admin'
];
wp_dequeue_style( $undesired_wp_styles );
wp_deregister_style( $undesired_wp_styles );
}
function admin_body_class( $classes ) {
global $pagenow;
if ( $pagenow == 'admin.php' && isset( $_GET['page'] ) && $_GET['page'] == $this->menu_slug ) {
$classes .= ' tainacan-admin-page';
}
return $classes;
}
function admin_page() {
global $TAINACAN_BASE_URL;
$Tainacan_Collections = \Tainacan\Repositories\Collections::getInstance();
$Tainacan_Fields = \Tainacan\Repositories\Fields::getInstance();
$Tainacan_Filters = \Tainacan\Repositories\Filters::getInstance();
$Tainacan_Items = \Tainacan\Repositories\Items::getInstance();
$Tainacan_Taxonomies = \Tainacan\Repositories\Taxonomies::getInstance();
// TODO move it to a separate file and start the Vue project
echo "<div id='tainacan-admin-app'></div>";
//wp_enqueue_script( 'tainacan-dev-admin', $TAINACAN_BASE_URL . '/assets/dev_admin-components.js', [] , null, true);
wp_enqueue_script( 'tainacan-user-admin', $TAINACAN_BASE_URL . '/assets/user_admin-components.js', [], null, true );
$tainacan_admin_i18n = require( 'tainacan-admin-i18n.php' );
// TODO move it to a separate file and start the Vue project
echo "<div id='tainacan-admin-app'></div>";
//wp_enqueue_script( 'tainacan-dev-admin', $TAINACAN_BASE_URL . '/assets/dev_admin-components.js', [] , null, true);
wp_enqueue_script( 'tainacan-user-admin', $TAINACAN_BASE_URL . '/assets/user_admin-components.js', [] , null, true);
$tainacan_admin_i18n = require('tainacan-admin-i18n.php');
$entities_labels = [
'collections' => $Tainacan_Collections->get_cpt_labels(),
'fields' => $Tainacan_Fields->get_cpt_labels(),
'filters' => $Tainacan_Filters->get_cpt_labels(),
'items' => $Tainacan_Items->get_cpt_labels(),
'taxonomies' => $Tainacan_Taxonomies->get_cpt_labels(),
'fields' => $Tainacan_Fields->get_cpt_labels(),
'filters' => $Tainacan_Filters->get_cpt_labels(),
'items' => $Tainacan_Items->get_cpt_labels(),
'taxonomies' => $Tainacan_Taxonomies->get_cpt_labels(),
];
$tainacan_admin_i18n['entities_labels'] = $entities_labels;
$components = ( has_filter( 'tainacan_register_web_components' ) ) ? apply_filters('tainacan_register_web_components') : [];
$cur_user = wp_get_current_user();
$user_caps = array();
$prefs = array();
if ($cur_user instanceof \WP_User) {
if (is_array($cur_user->allcaps)) {
foreach ($cur_user->allcaps as $cap => $bool)
if ($bool === true)
$user_caps[] = $cap;
}
$prefs = get_user_meta($cur_user->ID, 'tainacan_prefs', true);
}
$settings = [
'root' => esc_url_raw( rest_url() ).'tainacan/v2',
'root_wp_api' => esc_url_raw( rest_url() ).'wp/v2/',
'nonce' => wp_create_nonce( 'wp_rest' ),
'components' => $components,
'i18n' => $tainacan_admin_i18n,
'user_caps' => $user_caps,
'user_prefs' => $prefs,
'base_url' => $TAINACAN_BASE_URL
$components = ( has_filter( 'tainacan_register_web_components' ) ) ? apply_filters( 'tainacan_register_web_components' ) : [];
$cur_user = wp_get_current_user();
$user_caps = array();
$prefs = array();
if ( $cur_user instanceof \WP_User ) {
if ( is_array( $cur_user->allcaps ) ) {
foreach ( $cur_user->allcaps as $cap => $bool ) {
if ( $bool === true ) {
$user_caps[] = $cap;
}
}
}
$prefs = get_user_meta( $cur_user->ID, 'tainacan_prefs', true );
}
$settings = [
'root' => esc_url_raw( rest_url() ) . 'tainacan/v2',
'root_wp_api' => esc_url_raw( rest_url() ) . 'wp/v2/',
'nonce' => wp_create_nonce( 'wp_rest' ),
'components' => $components,
'i18n' => $tainacan_admin_i18n,
'user_caps' => $user_caps,
'user_prefs' => $prefs,
'base_url' => $TAINACAN_BASE_URL
];
wp_localize_script( 'tainacan-user-admin', 'tainacan_plugin', $settings );
}
$maps = [
'collections' => $Tainacan_Collections->get_map(),
'fields' => $Tainacan_Fields->get_map(),
'filters' => $Tainacan_Filters->get_map(),
'items' => $Tainacan_Items->get_map(),
'taxonomies' => $Tainacan_Taxonomies->get_map(),
];
$field_types = $Tainacan_Fields->fetch_field_types();
foreach( $maps as $type => $map ){
foreach ( $map as $field => $details){
$settings['i18n']['helpers_label'][$type][$field] = [ 'title' => $details['title'], 'description' => $details['description'] ];
}
}
foreach ( $field_types as $index => $field_type){
$class = new $field_type;
$settings['i18n']['helpers_label'][$class->get_component()] = $class->get_form_labels();
}
wp_localize_script( 'tainacan-user-admin', 'tainacan_plugin', $settings );
}
function register_user_meta() {
$args = array(
//'sanitize_callback' => 'sanitize_my_meta_key',
//'auth_callback' => 'authorize_my_meta_key',
'type' => 'array',
'description' => 'Tainacan admin user preferences',
'single' => true,
'type' => 'array',
'description' => 'Tainacan admin user preferences',
'single' => true,
'show_in_rest' => true,
);
register_meta( 'user', 'tainacan_prefs', $args );

View File

@ -1,20 +1,380 @@
<template>
<div class="page-container">
<h1>Category Edition Form</h1>
<div>
<div class="page-container primary-page">
<b-tag v-if="category != null && category != undefined" :type="'is-' + getStatusColor(category.status)" v-text="category.status"></b-tag>
<form v-if="category != null && category != undefined" class="tainacan-form" label-width="120px">
<!-- Name -------------------------------- -->
<b-field
:addons="false"
:label="$i18n.get('label_name')"
:type="editFormErrors['name'] != undefined ? 'is-danger' : ''"
:message="editFormErrors['name'] != undefined ? editFormErrors['name'] : ''">
<help-button
:title="$i18n.getHelperTitle('categories', 'name')"
:message="$i18n.getHelperMessage('categories', 'name')">
</help-button>
<b-input
id="tainacan-text-name"
v-model="form.name"
@focus="clearErrors('name')"
@blur="updateSlug()">
</b-input>
</b-field>
<!-- Description -------------------------------- -->
<b-field
:addons="false"
:label="$i18n.get('label_description')"
:type="editFormErrors['description'] != undefined ? 'is-danger' : ''"
:message="editFormErrors['description'] != undefined ? editFormErrors['description'] : ''">
<help-button
:title="$i18n.getHelperTitle('categories', 'description')"
:message="$i18n.getHelperMessage('categories', 'description')">
</help-button>
<b-input
id="tainacan-text-description"
type="textarea"
v-model="form.description"
@focus="clearErrors('description')">
</b-input>
</b-field>
<!-- Status -------------------------------- -->
<b-field
:addons="false"
:label="$i18n.get('label_status')"
:type="editFormErrors['status'] != undefined ? 'is-danger' : ''"
:message="editFormErrors['status'] != undefined ? editFormErrors['status'] : ''">
<help-button
:title="$i18n.getHelperTitle('categories', 'status')"
:message="$i18n.getHelperMessage('categories', 'status')">
</help-button>
<b-select
id="tainacan-select-status"
v-model="form.status"
@focus="clearErrors('status')"
:placeholder="$i18n.get('instruction_select_a_status')">
<option
v-for="statusOption in statusOptions"
:key="statusOption.value"
:value="statusOption.value"
:disabled="statusOption.disabled">{{ statusOption.label }}
</option>
</b-select>
</b-field>
<!-- Slug -------------------------------- -->
<b-field
:addons="false"
:label="$i18n.get('label_slug')"
:type="editFormErrors['slug'] != undefined ? 'is-danger' : ''"
:message="editFormErrors['slug'] != undefined ? editFormErrors['slug'] : ''">
<help-button
:title="$i18n.getHelperTitle('categories', 'slug')"
:message="$i18n.getHelperMessage('categories', 'slug')">
</help-button>
<b-input
id="tainacan-text-slug"
v-model="form.slug"
@focus="clearErrors('slug')"
:disabled="isUpdatingSlug">
</b-input>
</b-field>
<!-- Allow Insert -->
<b-field
:addons="false"
:label="$i18n.get('label_category_allow_new_terms')">
<help-button
:title="$i18n.getHelperTitle('categories', 'allow_insert')"
:message="$i18n.getHelperMessage('categories', 'allow_insert')">
</help-button>
<div class="block" >
<b-checkbox
v-model="form.allowInsert"
true-value="yes"
false-value="no">
{{ labelNewTerms() }}
</b-checkbox>
</div>
</b-field>
<div class="field is-grouped form-submit">
<div class="control">
<button
id="button-cancel-category-creation"
class="button is-outlined"
type="button"
@click="cancelBack">{{ $i18n.get('cancel') }}</button>
</div>
<div class="control">
<button
id="button-submit-category-creation"
@click.prevent="onSubmit"
class="button is-success">{{ $i18n.get('save') }}</button>
</div>
</div>
<p class="help is-danger">{{formErrorMessage}}</p>
</form>
<b-loading :active.sync="isLoading" :canCancel="false"></b-loading>
</div>
</div>
</template>
<script>
export default {
name: 'CategoryEditionForm',
data(){
return {
import { mapActions, mapGetters } from 'vuex'
export default {
name: 'CategoryEditionForm',
data(){
return {
categoryId: Number,
category: null,
isLoading: false,
isUpdatingSlug: false,
form: {
name: String,
status: String,
description: String,
slug: String,
allowInsert: String,
},
statusOptions: [{
value: 'publish',
label: this.$i18n.get('publish')
}, {
value: 'draft',
label: this.$i18n.get('draft')
}, {
value: 'private',
label: this.$i18n.get('private')
}, {
value: 'trash',
label: this.$i18n.get('trash')
}],
editFormErrors: {},
formErrorMessage: '',
}
},
methods: {
...mapActions('category', [
'createCategory',
'updateCategory',
'fetchCategory',
'fetchOnlySlug',
]),
...mapGetters('category',[
'getCategory'
]),
onSubmit() {
this.isLoading = true;
let data = {
categoryId: this.categoryId,
name: this.form.name,
description: this.form.description,
slug: this.form.slug,
status: this.form.status,
allowInsert: this.form.allowInsert
};
this.updateCategory(data)
.then(updatedCategory => {
this.category = updatedCategory;
// 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.allowInsert = this.category.allow_insert;
this.isLoading = false;
this.formErrorMessage = '';
this.editFormErrors = {};
this.$router.push(this.$routerHelper.getCategoryPath(this.categoryId));
})
.catch((errors) => {
for (let error of errors.errors) {
for (let attribute of Object.keys(error)) {
this.editFormErrors[attribute] = error[attribute];
}
}
this.formErrorMessage = errors.error_message;
this.isLoading = false;
});
},
updateSlug(){
if(!this.form.name || this.form.name.length <= 0){
return;
}
this.isUpdatingSlug = true;
let data = {
categoryId: this.categoryId,
name: this.form.name,
description: this.form.description,
//slug: '',
status: 'private',
allowInsert: this.form.allowInsert
};
console.log(data);
this.updateCategory(data)
.then(updatedCategory => {
this.category = updatedCategory;
console.info(this.category);
// 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.allowInsert = this.category.allow_insert;
this.isUpdatingSlug = false;
this.formErrorMessage = '';
this.editFormErrors = {};
})
.catch(errors => {
for (let error of errors.errors) {
for (let attribute of Object.keys(error)) {
this.editFormErrors[attribute] = error[attribute];
}
}
this.formErrorMessage = errors.error_message;
this.isLoading = false;
});
},
getStatusColor(status) {
switch(status) {
case 'publish':
return 'success';
case 'draft':
return 'info';
case 'private':
return 'warning';
case 'trash':
return 'danger';
default:
return 'info';
}
},
createNewCategory() {
// Puts loading on Draft Category creation
this.isLoading = true;
// Creates draft Category
let data = {
name: '',
description: '',
status: 'auto-draft',
slug: '',
allowInsert: '',
};
this.createCategory(data)
.then(res => {
this.categoryId = res.id;
this.category = 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;
// Pre-fill status with publish to incentivate it
this.form.status = 'publish';
this.isLoading = false;
}
)
.catch(error => console.log(error));
},
clearErrors(attribute) {
this.editFormErrors[attribute] = undefined;
},
cancelBack(){
this.$router.push(this.$routerHelper.getCategoriesPath());
},
labelNewTerms(){
return ( this.form.allowInsert === 'yes' ) ? this.$i18n.get('label_yes') : this.$i18n.get('label_no');
},
},
created(){
if (this.$route.fullPath.split("/").pop() === "new") {
this.createNewCategory();
} else if (this.$route.fullPath.split("/").pop() === "edit") {
this.isLoading = true;
// Obtains current category ID from URL
this.pathArray = this.$route.fullPath.split("/").reverse();
this.categoryId = this.pathArray[1];
this.fetchCategory(this.categoryId).then(res => {
this.category = res.category;
// 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.isLoading = false;
});
}
}
}
}
</script>
<style scoped>
<style lang="scss" scoped>
.thumbnail-field {
width: 128px;
height: 128px;
max-width: 128px;
max-height: 128px;
.content {
padding: 10px;
font-size: 0.8em;
}
img {
bottom: 0;
position: absolute;
}
.thumbnail-buttons-row {
display: none;
}
&:hover {
.thumbnail-buttons-row {
display: inline-block;
position: relative;
bottom: 31px;
background-color: rgba(255,255,255,0.8);
padding: 2px 8px;
border-radius: 0px 4px 0px 0px;
}
}
}
</style>

View File

@ -1,21 +1,70 @@
<template>
<div class="page-container">
<div class="page-container" :class="{'primary-page' : isNewCollection }">
<b-tag v-if="collection != null && collection != undefined" :type="'is-' + getStatusColor(collection.status)" v-text="collection.status"></b-tag>
<form class="tainacan-form" label-width="120px">
<form v-if="collection != null && collection != undefined" class="tainacan-form" label-width="120px">
<!-- Name -------------------------------- -->
<b-field
: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')">
</help-button>
<b-input
id="tainacan-text-name"
v-model="form.name"
@focus="clearErrors('name')">
</b-input>
</b-input>
</b-field>
<!-- Thumbnail -------------------------------- -->
<b-field
:label="$i18n.get('label_description')"
:type="editFormErrors['description'] != undefined ? 'is-danger' : ''"
:message="editFormErrors['description'] != undefined ? editFormErrors['description'] : ''">
:addons="false"
:label="$i18n.get('label_image')">
<div class="thumbnail-field">
<b-upload
v-if="collection.featured_image == undefined || collection.featured_image == false"
v-model="thumbnail"
drag-drop
@input="uploadThumbnail($event)">
<div class="content has-text-centered">
<p>
<b-icon
icon="upload">
</b-icon>
</p>
<p>{{ $i18n.get('instruction_image_upload_box') }}</p>
</div>
</b-upload>
<div v-else>
<figure class="image is-128x128">
<img :alt="$i18n.get('label_thumbnail')" :src="collection.featured_image"/>
</figure>
<div class="thumbnail-buttons-row">
<b-upload
model="thumbnail"
@input="uploadThumbnail($event)">
<a id="button-edit" :aria-label="$i18n.get('label_button_edit_thumb')"><b-icon icon="pencil"></b-icon></a>
</b-upload>
<a id="button-delete" :aria-label="$i18n.get('label_button_delete_thumb')" @click="deleteThumbnail()"><b-icon icon="delete"></b-icon></a>
</div>
</div>
</div>
</b-field>
<!-- Description -------------------------------- -->
<b-field
:addons="false"
:label="$i18n.get('label_description')"
:type="editFormErrors['description'] != undefined ? 'is-danger' : ''"
:message="editFormErrors['description'] != undefined ? editFormErrors['description'] : ''">
<help-button
:title="$i18n.getHelperTitle('collections', 'description')"
:message="$i18n.getHelperMessage('collections', 'description')">
</help-button>
<b-input
id="tainacan-text-description"
type="textarea"
@ -23,10 +72,17 @@
@focus="clearErrors('description')">
</b-input>
</b-field>
<b-field
<!-- Status -------------------------------- -->
<b-field
:addons="false"
:label="$i18n.get('label_status')"
:type="editFormErrors['status'] != undefined ? 'is-danger' : ''"
:message="editFormErrors['status'] != undefined ? editFormErrors['status'] : ''">
<help-button
:title="$i18n.getHelperTitle('collections', 'status')"
:message="$i18n.getHelperMessage('collections', 'status')">
</help-button>
<b-select
id="tainacan-select-status"
v-model="form.status"
@ -40,40 +96,42 @@
</option>
</b-select>
</b-field>
<!-- Slug -------------------------------- -->
<b-field
:type="editFormErrors['image'] != undefined ? 'is-danger' : ''"
:message="editFormErrors['image'] != undefined ? editFormErrors['image'] : ''"
:label="$i18n.get('label_image')">
<b-upload v-model="form.files"
multiple
drag-drop
@focus="clearErrors('image')">
<section class="section">
<div class="content has-text-centered">
<p>
<b-icon
icon="upload"
size="is-large">
</b-icon>
</p>
<p>{{ $i18n.get('instruction_image_upload_box') }}</p>
</div>
</section>
</b-upload>
:addons="false"
:label="$i18n.get('label_slug')"
:type="editFormErrors['slug'] != undefined ? 'is-danger' : ''"
:message="editFormErrors['slug'] != undefined ? editFormErrors['slug'] : ''">
<help-button
:title="$i18n.getHelperTitle('collections', 'slug')"
:message="$i18n.getHelperMessage('collections', 'slug')">
</help-button>
<b-input
id="tainacan-text-slug"
v-model="form.slug"
@focus="clearErrors('slug')">
</b-input>
</b-field>
<button
id="button-cancel-collection-creation"
class="button"
type="button"
@click="cancelBack">{{ $i18n.get('cancel') }}</button>
<button
id="button-submit-collection-creation"
@click.prevent="onSubmit"
class="button is-primary">{{ $i18n.get('save') }}</button>
<div class="field is-grouped form-submit">
<div class="control">
<button
id="button-cancel-collection-creation"
class="button is-outlined"
type="button"
@click="cancelBack">{{ $i18n.get('cancel') }}</button>
</div>
<div class="control">
<button
id="button-submit-collection-creation"
@click.prevent="onSubmit"
class="button is-success">{{ $i18n.get('save') }}</button>
</div>
</div>
<p class="help is-danger">{{formErrorMessage}}</p>
</form>
<b-loading :active.sync="isLoading" :canCancel="false">
<b-loading :active.sync="isLoading" :canCancel="false"></b-loading>
</div>
</template>
@ -91,8 +149,11 @@ export default {
name: '',
status: '',
description: '',
slug: '',
featured_image: '',
files:[]
},
thumbnail: {},
// Can be obtained from api later
statusOptions: [{
value: 'publish',
@ -109,13 +170,16 @@ export default {
}],
editFormErrors: {},
formErrorMessage: '',
isNewCollection: false
}
},
methods: {
...mapActions('collection', [
'sendCollection',
'updateCollection',
'fetchCollection'
'fetchCollection',
'sendAttachment',
'updateThumbnail'
]),
...mapGetters('collection',[
'getCollection'
@ -124,13 +188,14 @@ export default {
// Puts loading on Draft Collection creation
this.isLoading = true;
let data = {collection_id: this.collectionId, name: this.form.name, description: this.form.description, status: this.form.status};
let data = {collection_id: this.collectionId, name: this.form.name, description: this.form.description, slug: this.form.slug, status: this.form.status};
this.updateCollection(data).then(updatedCollection => {
this.collection = updatedCollection;
// Fill this.form data with current data.
this.form.name = this.collection.name;
this.form.slug = this.collection.slug;
this.form.description = this.collection.description;
this.form.status = this.collection.status;
@ -178,6 +243,7 @@ export default {
// Fill this.form data with current data.
this.form.name = this.collection.name;
this.form.description = this.collection.description;
this.form.slug = this.collection.slug;
// Pre-fill status with publish to incentivate it
this.form.status = 'publish';
@ -192,12 +258,41 @@ export default {
},
cancelBack(){
this.$router.push(this.$routerHelper.getCollectionsPath());
},
uploadThumbnail($event) {
this.sendAttachment({ collection_id: this.collectionId, file: $event[0] })
.then((res) => {
this.updateThumbnail({collectionId: this.collectionId, thumbnailId: res.id})
.then((res) => {
this.collection.featured_image = res.featured_image;
})
.catch((error) => {
console.log(error);
});
})
.catch((error) => {
console.log(error);
});
},
deleteThumbnail() {
this.updateThumbnail({collectionId: this.collectionId, thumbnailId: 0})
.then((res) => {
this.collection.featured_image = false;
})
.catch((error) => {
console.log(error);
});
}
},
created(){
if (this.$route.fullPath.split("/").pop() == "new") {
this.createNewCollection();
this.isNewCollection = true;
} else if (this.$route.fullPath.split("/").pop() == "edit") {
this.isLoading = true;
@ -212,6 +307,7 @@ export default {
// Fill this.form data with current data.
this.form.name = this.collection.name;
this.form.description = this.collection.description;
this.form.slug = this.collection.slug;
this.form.status = this.collection.status;
this.isLoading = false;
@ -222,7 +318,37 @@ export default {
}
</script>
<style scoped>
<style lang="scss" scoped>
.thumbnail-field {
width: 128px;
height: 128px;
max-width: 128px;
max-height: 128px;
.content {
padding: 10px;
font-size: 0.8em;
}
img {
bottom: 0;
position: absolute;
}
.thumbnail-buttons-row {
display: none;
}
&:hover {
.thumbnail-buttons-row {
display: inline-block;
position: relative;
bottom: 31px;
background-color: rgba(255,255,255,0.8);
padding: 2px 8px;
border-radius: 0px 4px 0px 0px;
}
}
}
</style>

View File

@ -2,88 +2,136 @@
<form id="fieldEditForm" class="tainacan-form" v-on:submit.prevent="saveEdition(editForm)">
<b-field
:label="$i18n.get('label_name')"
:addons="false"
:type="formErrors['name'] != undefined ? 'is-danger' : ''"
:message="formErrors['name'] != undefined ? formErrors['name'] : ''">
:message="formErrors['name'] != undefined ? formErrors['name'] : ''">
<label class="label">
{{$i18n.get('label_name')}}
<span class="required-field-asterisk" :class="formErrors['name'] != undefined ? 'is-danger' : ''">*</span>
<help-button
:title="$i18n.getHelperTitle('fields', 'name')"
:message="$i18n.getHelperMessage('fields', 'name')">
</help-button>
</label>
<b-input v-model="editForm.name" name="name" @focus="clearErrors('name')"></b-input>
</b-field>
<b-field
:label="$i18n.get('label_description')"
:addons="false"
:type="formErrors['description'] != undefined ? 'is-danger' : ''"
:message="formErrors['description'] != undefined ? formErrors['description'] : ''">
<label class="label">
{{$i18n.get('label_description')}}
<help-button
:title="$i18n.getHelperTitle('fields', 'description')"
:message="$i18n.getHelperMessage('fields', 'description')">
</help-button>
</label>
<b-input type="textarea" name="description" v-model="editForm.description" @focus="clearErrors('description')" ></b-input>
</b-field>
<b-field
:type="formErrors['required'] != undefined ? 'is-danger' : ''"
:message="formErrors['required'] != undefined ? formErrors['required'] : ''">
<b-switch
@input="clearErrors('required')"
v-model="editForm.required"
true-value="yes"
false-value="no"
name="required">
{{ $i18n.get('label_required') }}
</b-switch>
</b-field>
<b-field
:type="formErrors['multiple'] != undefined ? 'is-danger' : ''"
:message="formErrors['multiple'] != undefined ? formErrors['multiple'] : ''">
<b-switch
@input="clearErrors('multiple')"
v-model="editForm.multiple"
true-value="yes"
false-value="no"
name="multiple">
{{ $i18n.get('label_allow_multiple') }}
</b-switch>
</b-field>
<b-field
:type="formErrors['unique'] != undefined ? 'is-danger' : ''"
:message="formErrors['unique'] != undefined ? formErrors['unique'] : ''">
<b-switch
@input="clearErrors('unique')"
v-model="editForm.unique"
true-value="yes"
false-value="no"
name="collecion_key">
{{ $i18n.get('label_unique_value') }}
</b-switch>
</b-field>
<b-field
:label="$i18n.get('label_status')"
:addons="false"
:type="formErrors['status'] != undefined ? 'is-danger' : ''"
:message="formErrors['status'] != undefined ? formErrors['status'] : ''">
<b-select
<label class="label">
{{$i18n.get('label_status')}}
<help-button
:title="$i18n.getHelperTitle('fields', 'status')"
:message="$i18n.getHelperMessage('fields', 'status')">
</help-button>
</label>
<div class="inline-block">
<b-radio
@focus="clearErrors('label_status')"
id="tainacan-select-status"
name="status"
id="tainacan-select-status-publish"
name="status"
v-model="editForm.status"
:placeholder="$i18n.get('instruction_select_a_status')">
<option value="publish" selected>{{ $i18n.get('publish')}}</option>
<option value="private">{{ $i18n.get('private')}}</option>
</b-select>
native-value="publish">
{{ $i18n.get('publish_visibility') }}
</b-radio>
<br>
<b-radio
@focus="clearErrors('label_status')"
id="tainacan-select-status-private"
name="status"
v-model="editForm.status"
native-value="private">
{{ $i18n.get('private_visibility') }}
</b-radio>
</div>
</b-field>
<br>
<b-field
:addons="false"
:label="$i18n.get('label_options')">
<b-field
:type="formErrors['required'] != undefined ? 'is-danger' : ''"
:message="formErrors['required'] != undefined ? formErrors['required'] : ''">
<b-checkbox
@input="clearErrors('required')"
v-model="editForm.required"
true-value="yes"
false-value="no"
name="required">
{{ $i18n.get('label_required') }}
</b-checkbox>
<help-button
:title="$i18n.getHelperTitle('fields', 'required')"
:message="$i18n.getHelperMessage('fields', 'required')">
</help-button>
</b-field>
<b-field
:type="formErrors['multiple'] != undefined ? 'is-danger' : ''"
:message="formErrors['multiple'] != undefined ? formErrors['multiple'] : ''">
<b-checkbox
@input="clearErrors('multiple')"
v-model="editForm.multiple"
true-value="yes"
false-value="no"
name="multiple">
{{ $i18n.get('label_allow_multiple') }}
</b-checkbox>
<help-button
:title="$i18n.getHelperTitle('fields', 'multiple')"
:message="$i18n.getHelperMessage('fields', 'multiple')">
</help-button>
</b-field>
<b-field
:type="formErrors['unique'] != undefined ? 'is-danger' : ''"
:message="formErrors['unique'] != undefined ? formErrors['unique'] : ''">
<b-checkbox
@input="clearErrors('unique')"
v-model="editForm.unique"
true-value="yes"
false-value="no"
name="collecion_key">
{{ $i18n.get('label_unique_value') }}
</b-checkbox>
<help-button
:title="$i18n.getHelperTitle('fields', 'unique')"
:message="$i18n.getHelperMessage('fields', 'unique')">
</help-button>
</b-field>
</b-field>
<component
:errors="formErrors['field_type_options']"
v-if="(editForm.field_type_object && field.field_type_object.form_component) || field.edit_form == ''"
:is="editForm.field_type_object.form_component"
:field="editForm"
v-model="editForm.field_type_options">
:errors="formErrors['field_type_options']"
v-if="(editForm.field_type_object && editForm.field_type_object.form_component) || editForm.edit_form == ''"
:is="editForm.field_type_object.form_component"
:field="editForm"
v-model="editForm.field_type_options">
</component>
<div v-html="editForm.edit_form" v-else></div>
<div class="field is-grouped is-grouped-centered">
<div class="field is-grouped form-submit">
<div class="control">
<button class="button is-secondary" type="submit">Submit</button>
<button class="button is-outlined" @click.prevent="cancelEdition()" slot="trigger">{{ $i18n.get('cancel')}}</button>
</div>
<div class="control">
<button class="button is-text" @click.prevent="cancelEdition()" slot="trigger">Cancel</button>
<button class="button is-success" type="submit">{{ $i18n.get('save')}}</button>
</div>
</div>
<p class="help is-danger">{{formErrorMessage}}</p>
@ -98,36 +146,53 @@ export default {
data(){
return {
editForm: {},
oldForm: {},
formErrors: {},
formErrorMessage: ''
formErrorMessage: '',
closedByForm: false
}
},
props: {
field: {},
index: '',
editedField: {},
originalField: '',
isRepositoryLevel: false,
collectionId: ''
},
created() {
this.editForm = this.field;
this.editForm = this.editedField;
this.formErrors = this.editForm.formErrors != undefined ? this.editForm.formErrors : {};
this.formErrorMessage = this.editForm.formErrors != undefined ? this.editForm.formErrorMessage : '';
this.oldForm = JSON.parse(JSON.stringify(this.originalField));
},
beforeDestroy() {
if (this.closedByForm) {
this.editedField.saved = true;
} else {
this.oldForm.saved = this.editForm.saved;
if (JSON.stringify(this.editForm) != JSON.stringify(this.oldForm))
this.editedField.saved = false;
else
this.editedField.saved = true;
}
},
methods: {
...mapActions('fields', [
'fetchFields',
'updateField',
'updateField'
]),
saveEdition(field) {
this.openedFieldId = field.id;
this.formErrors = {};
this.formErrorMessage = '';
if ((field.field_type_object && field.field_type_object.form_component) || field.edit_form == '') {
this.updateField({collectionId: this.collectionId, fieldId: field.id, isRepositoryLevel: this.isRepositoryLevel, options: this.editForm})
this.updateField({collectionId: this.collectionId, fieldId: field.id, isRepositoryLevel: this.isRepositoryLevel, index: this.index, options: this.editForm})
.then((field) => {
this.editForm = {};
this.formErrors = {};
this.formErrorMessage = '';
this.closedByForm = true;
this.$emit('onEditionFinished');
})
.catch((errors) => {
@ -136,6 +201,10 @@ export default {
this.formErrors[attribute] = error[attribute];
}
this.formErrorMessage = errors.error_message;
this.$emit('onErrorFound');
this.editForm.formErrors = this.formErrors;
this.editForm.formErrorMessage = this.formErrorMessage;
});
} else {
let formElement = document.getElementById('fieldEditForm');
@ -145,12 +214,12 @@ export default {
for (let [key, value] of formData.entries())
formObj[key] = value;
this.updateField({collectionId: this.collectionId, fieldId: field.id, isRepositoryLevel: this.isRepositoryLevel, options: formObj})
this.updateField({collectionId: this.collectionId, fieldId: field.id, isRepositoryLevel: this.isRepositoryLevel, index: this.index, options: formObj})
.then((field) => {
this.editForm = {};
this.openedFieldId = '';
this.formErrors = {};
this.formErrorMessage = '';
this.closedByForm = true;
this.$emit('onEditionFinished');
})
.catch((errors) => {
@ -159,6 +228,10 @@ export default {
this.formErrors[attribute] = error[attribute];
}
this.formErrorMessage = errors.error_message;
this.$emit('onErrorFound');
this.editForm.formErrors = this.formErrors;
this.editForm.formErrorMessage = this.formErrorMessage;
});
}
},
@ -166,20 +239,22 @@ export default {
this.formErrors[attribute] = undefined;
},
cancelEdition() {
this.editForm = {};
this.formErrors = {};
this.formErrors = {};
this.formErrorMessage = '';
this.closedByForm = true;
this.$emit('onEditionCanceled');
},
}
}
</script>
<style scoped>
<style lang="scss" scoped>
@import "../../scss/_variables.scss";
form {
padding: 5px;
padding: 1.0em 2.0em;
border-top: 1px solid $draggable-border-color;
border-bottom: 1px solid $draggable-border-color;
margin-top: 1.0em;
}
</style>

View File

@ -1,20 +1,203 @@
<template>
<div class="page-container">
<h1>Filter Edition Form</h1>
</div>
<form id="filterEditForm" class="tainacan-form" v-on:submit.prevent="saveEdition(editForm)">
<b-field
:addons="false"
:type="formErrors['name'] != undefined ? 'is-danger' : ''"
:message="formErrors['name'] != undefined ? formErrors['name'] : ''">
<label class="label">
{{$i18n.get('label_name')}}
<span class="required-field-asterisk" :class="formErrors['name'] != undefined ? 'is-danger' : ''">*</span>
<help-button
:title="$i18n.getHelperTitle('filters', 'name')"
:message="$i18n.getHelperMessage('filters', 'name')">
</help-button>
</label>
<b-input v-model="editForm.name" name="name" @focus="clearErrors('name')"></b-input>
</b-field>
<b-field
:addons="false"
:type="formErrors['description'] != undefined ? 'is-danger' : ''"
:message="formErrors['description'] != undefined ? formErrors['description'] : ''">
<label class="label">
{{$i18n.get('label_description')}}
<help-button
:title="$i18n.getHelperTitle('filters', 'description')"
:message="$i18n.getHelperMessage('filters', 'description')">
</help-button>
</label>
<b-input type="textarea" name="description" v-model="editForm.description" @focus="clearErrors('description')" ></b-input>
</b-field>
<b-field
:addons="false"
:type="formErrors['status'] != undefined ? 'is-danger' : ''"
:message="formErrors['status'] != undefined ? formErrors['status'] : ''">
<label class="label">
{{$i18n.get('label_status')}}
<help-button
:title="$i18n.getHelperTitle('filters', 'status')"
:message="$i18n.getHelperMessage('filters', 'status')">
</help-button>
</label>
<div class="inline-block">
<b-radio
@focus="clearErrors('label_status')"
id="tainacan-select-status-publish"
name="status"
v-model="editForm.status"
native-value="publish">
{{ $i18n.get('publish_visibility') }}
</b-radio>
<br>
<b-radio
@focus="clearErrors('label_status')"
id="tainacan-select-status-private"
name="status"
v-model="editForm.status"
native-value="private">
{{ $i18n.get('private_visibility') }}
</b-radio>
</div>
</b-field>
<component
:errors="formErrors['filter_type_options']"
v-if="(editForm.filter_type_object && editForm.filter_type_object.form_component) || editForm.edit_form == ''"
:is="editForm.filter_type_object.form_component"
:filter="editForm"
v-model="editForm.filter_type_options">
</component>
<div v-html="editForm.edit_form" v-else></div>
<div class="field is-grouped form-submit">
<div class="control">
<button class="button is-outlined" @click.prevent="cancelEdition()" slot="trigger">{{ $i18n.get('cancel')}}</button>
</div>
<div class="control">
<button class="button is-success" type="submit">{{ $i18n.get('save')}}</button>
</div>
</div>
<p class="help is-danger">{{formErrorMessage}}</p>
</form>
</template>
<script>
import { mapActions } from 'vuex';
export default {
name: 'FilterEditionForm',
data(){
return {
editForm: {},
oldForm: {},
formErrors: {},
formErrorMessage: '',
closedByForm: false
}
},
props: {
index: '',
editedFilter: {},
originalFilter: {},
},
created() {
this.editForm = this.editedFilter;
this.formErrors = this.editForm.formErrors != undefined ? this.editForm.formErrors : {};
this.formErrorMessage = this.editForm.formErrors != undefined ? this.editForm.formErrorMessage : '';
this.oldForm = JSON.parse(JSON.stringify(this.originalFilter));
},
beforeDestroy() {
if (this.closedByForm) {
this.editedFilter.saved = true;
} else {
this.oldForm.saved = this.editForm.saved;
if (JSON.stringify(this.editForm) != JSON.stringify(this.oldForm))
this.editedFilter.saved = false;
else
this.editedFilter.saved = true;
}
},
methods: {
...mapActions('filter', [
'updateFilter'
]),
saveEdition(filter) {
if ((filter.filter_type_object && filter.filter_type_object.form_component) || filter.edit_form == '') {
this.updateFilter({ filterId: filter.id, index: this.index, options: this.editForm})
.then((filter) => {
this.editForm = {};
this.formErrors = {};
this.formErrorMessage = '';
this.closedByForm = true;
this.$emit('onEditionFinished');
})
.catch((errors) => {
for (let error of errors.errors) {
for (let attribute of Object.keys(error))
this.formErrors[attribute] = error[attribute];
}
this.formErrorMessage = errors.error_message;
this.$emit('onErrorFound');
this.editForm.formErrors = this.formErrors;
this.editForm.formErrorMessage = this.formErrorMessage;
});
} else {
let formElement = document.getElementById('filterEditForm');
let formData = new FormData(formElement);
let formObj = {}
for (let [key, value] of formData.entries())
formObj[key] = value;
this.updateFilter({ filterId: filter.id, index: this.index, options: formObj})
.then((filter) => {
this.editForm = {};
this.formErrors = {};
this.formErrorMessage = '';
this.closedByForm = true;
this.$emit('onEditionFinished');
})
.catch((errors) => {
for (let error of errors.errors) {
for (let attribute of Object.keys(error))
this.formErrors[attribute] = error[attribute];
}
this.formErrorMessage = errors.error_message;
this.$emit('onErrorFound');
this.editForm.formErrors = this.formErrors;
this.editForm.formErrorMessage = this.formErrorMessage;
});
}
},
clearErrors(attribute) {
this.formErrors[attribute] = undefined;
},
cancelEdition() {
this.closedByForm = true;
this.$emit('onEditionCanceled');
},
}
}
</script>
<style scoped>
<style lang="scss" scoped>
@import "../../scss/_variables.scss";
form {
padding: 1.0em 2.0em;
border-top: 1px solid $draggable-border-color;
border-bottom: 1px solid $draggable-border-color;
margin-top: 1.0em;
}
</style>

View File

@ -1,8 +1,14 @@
<template>
<div class="page-container">
<b-tag v-if="item != null && item != undefined" :type="'is-' + getStatusColor(item.status)" v-text="item.status"></b-tag>
<form class="tainacan-form" label-width="120px">
<b-field :label="$i18n.get('label_status')">
<b-tag v-if="!isLoading" :type="'is-' + getStatusColor(item.status)" v-text="item.status"></b-tag>
<form v-if="!isLoading" class="tainacan-form" label-width="120px">
<b-field
:addons="false"
:label="$i18n.get('label_status')">
<help-button
:title="$i18n.getHelperTitle('items', 'status')"
:message="$i18n.getHelperMessage('items', 'status')">
</help-button>
<b-select
id="status-select"
v-model="form.status"
@ -16,54 +22,106 @@
</option>
</b-select>
</b-field>
<b-field
:label="$i18n.get('label_image')">
<b-upload v-model="form.files"
multiple
drag-drop
@input="uploadAttachment($event)">
<section class="section">
<!-- Thumbnail -------------------------------- -->
<b-field :label="$i18n.get('label_image')">
<div class="thumbnail-field">
<b-upload
v-if="item.featured_image == undefined || item.featured_image == false"
v-model="thumbnail"
drag-drop
@input="uploadThumbnail($event)">
<div class="content has-text-centered">
<p>
<b-icon
icon="upload"
size="is-large">
</b-icon>
<b-icon
icon="upload">
</b-icon>
</p>
<p>{{ $i18n.get('instruction_image_upload_box') }}</p>
</div>
</section>
</b-upload>
</b-field>
<div class="uploaded-files">
<div v-for="(file, index) in form.files"
:key="index">
<span class="tag is-primary">
{{ file.name }}
<button class="delete is-small"
type="button"
@click="deleteFile(index)">
</button>
</span>
<!-- <progress class="progress is-secondary" value="15" max="100">30%</progress> -->
</b-upload>
<div v-else>
<figure class="image is-128x128">
<img :alt="$i18n.get('label_thumbnail')" :src="item.featured_image"/>
</figure>
<div class="thumbnail-buttons-row">
<b-upload
model="thumbnail"
@input="uploadThumbnail($event)">
<a id="button-edit" :aria-label="$i18n.get('label_button_edit_thumb')"><b-icon icon="pencil"></a>
</b-upload>
<a id="button-delete" :aria-label="$i18n.get('label_button_delete_thumb')" @click="deleteThumbnail()"><b-icon icon="delete"></a>
</div>
</div>
</div>
</div>
</b-field>
<!-- Fields from Collection-------------------------------- -->
<tainacan-form-item
v-for="(field, index) in fieldList"
v-bind:key="index"
:field="field"></tainacan-form-item>
<div>
<p v-for="(attachment, index) of attachmentsList" :key="index">{{attachment}}</p>
</div>
<button
id="button-cancel-item-creation"
class="button"
type="button"
@click="cancelBack">{{ $i18n.get('cancel') }}</button>
<button
id="button-submit-item-creation"
@click.prevent="onSubmit"
class="button is-primary" :disabled="formHasErrors">{{ $i18n.get('save') }}</button>
:field="field"></tainacan-form-item>
<!-- Attachments ------------------------------------------ -->
<div class="columns is-multiline">
<div class="column is-4">
<b-field :label="$i18n.get('label_image')">
<b-upload v-model="form.files"
multiple
drag-drop
@input="uploadAttachment($event)">
<section class="section">
<div class="content has-text-centered">
<p>
<b-icon
icon="upload"
size="is-large">
</b-icon>
</p>
<p>{{ $i18n.get('instruction_image_upload_box') }}</p>
</div>
</section>
</b-upload>
</b-field>
<div class="uploaded-files">
<div v-for="(file, index) in form.files"
:key="index">
<span class="tag is-primary">
{{ file.name }}
<button class="delete is-small"
type="button"
@click="deleteFile(index)">
</button>
</span>
<!-- <progress class="progress is-secondary" value="15" max="100">30%</progress> -->
</div>
</div>
</div>
<div class="column is-narrow"
v-for="(attachment, index) of item.attachments"
:key="index">
<figure class="image is-128x128">
<img
:alt="attachment.title"
:src="attachment.url"/>
</figure>
</div>
</div>
<div class="field is-grouped form-submit">
<div class="control">
<button
id="button-cancel-item-creation"
class="button is-outlined"
type="button"
@click="cancelBack">{{ $i18n.get('cancel') }}</button>
</div>
<div class="control">
<button
id="button-submit-item-creation"
@click.prevent="onSubmit"
class="button is-success" :disabled="formHasErrors">{{ $i18n.get('save') }}</button>
</div>
</div>
</form>
<b-loading :active.sync="isLoading" :canCancel="false">
@ -86,8 +144,9 @@ export default {
form: {
collectionId: Number,
status: '',
files:[]
files:[],
},
thumbnail: {},
// Can be obtained from api later
statusOptions: [{
value: 'publish',
@ -112,13 +171,12 @@ export default {
'sendField',
'fetchItem',
'cleanFields',
'fetchAttachments',
'sendAttachment'
'sendAttachment',
'updateThumbnail'
]),
...mapGetters('item',[
'getFields',
'getItem',
'getAttachments'
]),
onSubmit() {
// Puts loading on Item edition
@ -195,6 +253,33 @@ export default {
});
}
},
uploadThumbnail($event) {
this.sendAttachment({ item_id: this.itemId, file: $event[0] })
.then((res) => {
this.updateThumbnail({itemId: this.itemId, thumbnailId: res.id})
.then((res) => {
this.item.featured_image = res.featured_image;
})
.catch((error) => {
console.log(error);
});
})
.catch((error) => {
console.log(error);
});
},
deleteThumbnail() {
this.updateThumbnail({itemId: this.itemId, thumbnailId: 0})
.then((res) => {
this.item.featured_image = false;
})
.catch((error) => {
console.log(error);
});
},
deleteFile(index) {
}
@ -205,10 +290,7 @@ export default {
},
formHasErrors(){
return eventBus.errors.length > 0;
},
attachmentsList(){
return this.getAttachments();
}
}
},
created(){
@ -241,7 +323,38 @@ export default {
}
</script>
<style scoped>
<style lang="scss" scoped>
.thumbnail-field {
width: 128px;
height: 128px;
max-width: 128px;
max-height: 128px;
.content {
padding: 10px;
font-size: 0.8em;
}
img {
bottom: 0;
position: absolute;
}
.thumbnail-buttons-row {
display: none;
}
&:hover {
.thumbnail-buttons-row {
display: inline-block;
position: relative;
bottom: 31px;
background-color: rgba(255,255,255,0.8);
padding: 2px 8px;
border-radius: 0px 4px 0px 0px;
}
}
}
</style>

View File

@ -1,20 +1,206 @@
<template>
<div>
<h1>Categories List</h1>
<b-field grouped group-multiline>
<button
v-if="selectedCategories.length > 0"
class="button field is-danger"
@click="deleteSelectedCategories()">
<span>{{ $i18n.get('instruction_delete_selected_categories') }} </span>
<b-icon icon="delete"></b-icon>
</button>
</b-field>
<b-table
v-if="totalCategories > 0"
ref="categoryTable"
:data="categories"
@selection-change="handleSelectionChange"
:checked-rows.sync="selectedCategories"
checkable
:loading="isLoading"
hoverable
striped
selectable
backend-sorting>
<template slot-scope="props">
<b-table-column
tabindex="0"
:label="$i18n.get('label_name')"
:aria-label="$i18n.get('label_name')"
field="props.row.name">
<router-link
class="clickable-row"
tag="span"
:to="{path: $routerHelper.getCategoryPath(props.row.id)}">
{{ props.row.name }}
</router-link>
</b-table-column>
<b-table-column
tabindex="0"
:aria-label="$i18n.get('label_description')"
:label="$i18n.get('label_description')"
property="description"
show-overflow-tooltip
field="props.row.description">
<router-link class="clickable-row" tag="span" :to="{path: $routerHelper.getCategoryPath(props.row.id)}">
{{ props.row.description }}
</router-link>
</b-table-column>
<b-table-column
tabindex="0"
:label="$i18n.get('label_actions')"
width="78"
:aria-label="$i18n.get('label_actions')">
<!-- <a id="button-view" :aria-label="$i18n.get('label_button_view')" @click.prevent.stop="goToCollectionPage(props.row.id)"><b-icon icon="eye"></a> -->
<a
id="button-edit"
:aria-label="$i18n.getFrom('categories','edit_item')"
@click.prevent.stop="goToCategoryEditPage(props.row.id)">
<b-icon type="is-gray" icon="pencil" ></b-icon>
</a>
<a
id="button-delete"
:aria-label="$i18n.get('label_button_delete')"
@click.prevent.stop="deleteOneCategory(props.row.id)">
<b-icon type="is-gray" icon="delete" ></b-icon>
</a>
</b-table-column>
</template>
</b-table>
<div v-if="!totalCategories || totalCategories <= 0">
<section class="section">
<div class="content has-text-grey has-text-centered">
<p>
<b-icon
icon="inbox"
size="is-large">
</b-icon>
</p>
<p>{{ $i18n.get('info_no_category_created') }}</p>
<router-link tag="button" class="button is-secondary"
:to="{ path: $routerHelper.getNewCategoryPath() }">
{{ $i18n.get('new') + ' ' + $i18n.get('category') }}
</router-link>
</div>
</section>
</div>
</div>
</template>
<script>
export default {
name: 'CategoriesList',
data(){
return {
import { mapActions } from 'vuex'
export default {
name: 'CategoriesList',
props: {
isLoading: false,
totalCategories: 0,
page: 1,
categoriesPerPage: 12,
categories: []
},
data() {
return {
selectedCategories: []
}
},
methods: {
...mapActions('category', [
'deleteCategory'
]),
deleteOneCategory(categoryId) {
this.$dialog.confirm({
message: this.$i18n.get('info_warning_category_delete'),
onConfirm: () => {
this.deleteCategory(categoryId).then(() => {
this.loadCategories();
this.$toast.open({
duration: 3000,
message: this.$i18n.get('info_category_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);
}
}).catch(() =>
this.$toast.open({
duration: 3000,
message: this.$i18n.get('info_error_deleting_category'),
position: 'is-bottom',
type: 'is-danger',
queue: true
})
);
}
});
},
deleteSelectedCategories() {
this.$dialog.confirm({
message: this.$i18n.get('info_selected_categories_delete'),
onConfirm: () => {
for (let category of this.selectedCategories) {
this.deleteCategory(category.id)
.then((res) => {
this.loadCategories();
this.$toast.open({
duration: 3000,
message: this.$i18n.get('info_category_deleted'),
position: 'is-bottom',
type: 'is-secondary',
queue: false
})
}).catch((err) => {
this.$toast.open({
duration: 3000,
message: this.$i18n.get('info_error_deleting_category'),
position: 'is-bottom',
type: 'is-danger',
queue: false
});
});
}
this.selectedCategories = [];
}
});
},
handleSelectionChange(value) {
},
goToCategoryPage(categoryId) {
this.$router.push(this.$routerHelper.getCategoryPath(categoryId));
},
goToCategoryEditPage(categoryId) {
this.$router.push(this.$routerHelper.getCategoryEditPath(categoryId));
}
}
}
}
</script>
<style scoped>
<style lang="scss" scoped>
@import "../../scss/_variables.scss";
.table-thumb {
max-height: 38px !important;
vertical-align: middle !important;
}
.row-creation span {
color: $gray-light;
font-size: 0.75em;
line-height: 1.5
}
.clickable-row{ cursor: pointer !important; }
</style>

View File

@ -16,12 +16,10 @@
backend-sorting>
<template slot-scope="props">
<b-table-column tabindex="0" label="Imagem" :aria-label="$i18n.get('label_image')" field="featured_image" width="55">
<router-link class="clickable-row" tag="span" :to="{path: $routerHelper.getCollectionPath(props.row.id)}">
<b-table-column tabindex="0" :label="$i18n.get('label_thumbnail')" :aria-label="$i18n.get('label_thumbnail')" field="featured_image" width="55">
<template v-if="props.row.featured_image" slot-scope="scope">
<img class="table-thumb" :src="`${props.row.featured_image}`"/>
<router-link tag="img" :to="{path: $routerHelper.getCollectionPath(props.row.id)}" class="table-thumb clickable-row" :src="`${props.row.featured_image}`"></router-link>
</template>
</router-link>
</b-table-column>
<b-table-column tabindex="0" :label="$i18n.get('label_name')" :aria-label="$i18n.get('label_name')" field="props.row.name">
@ -43,8 +41,8 @@
<b-table-column tabindex="0" :label="$i18n.get('label_actions')" width="78" :aria-label="$i18n.get('label_actions')">
<!-- <a id="button-view" :aria-label="$i18n.get('label_button_view')" @click.prevent.stop="goToCollectionPage(props.row.id)"><b-icon icon="eye"></a> -->
<a id="button-edit" :aria-label="$i18n.getFrom('collections','edit_item')" @click.prevent.stop="goToCollectionEditPage(props.row.id)"><b-icon icon="pencil"></a>
<a id="button-delete" :aria-label="$i18n.get('label_button_delete')" @click.prevent.stop="deleteOneCollection(props.row.id)"><b-icon icon="delete"></a>
<a id="button-edit" :aria-label="$i18n.getFrom('collections','edit_item')" @click.prevent.stop="goToCollectionEditPage(props.row.id)"><b-icon type="is-gray" icon="pencil"></a>
<a id="button-delete" :aria-label="$i18n.get('label_button_delete')" @click.prevent.stop="deleteOneCollection(props.row.id)"><b-icon type="is-gray" icon="delete"></a>
</b-table-column>
</template>
@ -172,7 +170,7 @@ export default {
vertical-align: middle !important;
}
.row-creation {
.row-creation span {
color: $gray-light;
font-size: 0.75em;
line-height: 1.5

View File

@ -1,67 +1,112 @@
<template>
<div>
<b-loading :active.sync="isLoadingFieldTypes"></b-loading>
<div class="page-title">
<h2>{{ isRepositoryLevel ? $i18n.get('instruction_dragndrop_fields_repository') : $i18n.get('instruction_dragndrop_fields_collection')}}</h2>
</div>
<div class="columns">
<div class="column">
<b-field :label="$i18n.get('label_active_fields')" is-grouped>
<draggable
class="box active-fields-area"
@change="handleChange"
:class="{'fields-area-receive': isDraggingFromAvailable}"
:list="activeFieldList"
:options="{group: { name:'fields', pull: false, put: true }, 'handle': '.handle', chosenClass: 'sortable-chosen', filter: '.not-sortable-item'}">
<div
class="active-field-item"
:class="{'not-sortable-item': field.id == undefined, 'not-focusable-item': openedFieldId == field.id, 'inherited-field': field.collection_id != collectionId}"
v-for="(field, index) in activeFieldList" :key="index">
<div class="handle">
<b-icon type="is-gray" class="is-pulled-left" icon="drag"></b-icon>
<span class="field-name">{{ field.name }}</span>
<span v-if="field.id !== undefined" class="label-details">{{ $i18n.get(field.field_type_object.component)}}</span><span class="loading-spinner" v-if="field.id == undefined"></span>
<span class="controls" v-if="field.id !== undefined">
<b-switch size="is-small" v-model="field.disabled" @input="onChangeEnable($event, index)">{{ field.disabled ? $i18n.get('label_disabled') : $i18n.get('label_enabled') }}</b-switch>
<a @click.prevent="removeField(field)">
<b-icon icon="delete"></b-icon>
</a>
<a @click.prevent="editField(field)">
<b-icon icon="pencil"></b-icon>
</a>
</span>
</div>
<b-field v-if="openedFieldId == field.id">
<field-edition-form
:collectionId="collectionId"
:isRepositoryLevel="isRepositoryLevel"
@onEditionFinished="onEditionFinished()"
@onEditionCanceled="onEditionCanceled()"
:field="editForm"></field-edition-form>
</b-field>
<div class="column">
<draggable
class="active-fields-area"
@change="handleChange"
:class="{'fields-area-receive': isDraggingFromAvailable}"
:list="activeFieldList"
:options="{
group: { name:'fields', pull: false, put: true },
sort: openedFieldId == '' || openedFieldId == undefined,
disabled: openedFieldId != '' && openedFieldId != undefined,
handle: '.handle',
ghostClass: 'sortable-ghost',
filter: 'not-sortable-item',
animation: '250'}">
<div
class="active-field-item"
:class="{
'not-sortable-item': field.id == undefined || openedFieldId != '' ,
'not-focusable-item': openedFieldId == field.id,
'disabled-field': field.enabled == false}"
v-for="(field, index) in activeFieldList" :key="index">
<div class="handle">
<grip-icon></grip-icon>
<span
class="field-name"
:class="{'is-danger': formWithErrors == field.id }">
{{ field.name }}
</span>
<span
v-if="field.id != undefined"
class="label-details">
({{ $i18n.get(field.field_type_object.component) }})
<span class="not-saved" v-if="(editForms[field.id] != undefined && editForms[field.id].saved != true) || field.status == 'auto-draft'">
{{ $i18n.get('info_not_saved') }}
</span>
</span>
<span class="loading-spinner" v-if="field.id == undefined"></span>
<span class="controls" v-if="field.id !== undefined">
<b-switch size="is-small" v-model="field.enabled" @input="onChangeEnable($event, index)"></b-switch>
<a :style="{ visibility:
field.collection_id != collectionId
? 'hidden' : 'visible'
}"
@click.prevent="editField(field)">
<b-icon type="is-gray" icon="pencil"></b-icon>
</a>
<a :style="{ visibility:
field.collection_id != collectionId ||
field.field_type == 'Tainacan\\Field_Types\\Core_Title' ||
field.field_type == 'Tainacan\\Field_Types\\Core_Description'
? 'hidden' : 'visible'
}"
@click.prevent="removeField(field)">
<b-icon type="is-gray" icon="delete"></b-icon>
</a>
</span>
</div>
</draggable>
</b-field>
</div>
<div class="column">
<b-field :label="$i18n.get('label_available_field_types')">
<div class="columns box available-fields-area" >
<draggable class="column" :list="availableFieldList" :options="{ sort: false, group: { name:'fields', pull: 'clone', put: false, revertClone: true }}">
<div class="available-field-item" v-if="index % 2 == 0" v-for="(field, index) in availableFieldList" :key="index">
{{ field.name }} <b-icon type="is-gray" class="is-pulled-left" icon="drag"></b-icon>
</div>
</draggable>
<draggable class="column" :list="availableFieldList" :options="{ sort: false, group: { name:'fields', pull: 'clone', put: false, revertClone: true }}">
<div class="available-field-item" v-if="index % 2 != 0" v-for="(field, index) in availableFieldList" :key="index">
{{ field.name }} <b-icon type="is-gray" class="is-pulled-left" icon="drag"></b-icon>
</div>
</draggable>
</div>
</b-field>
<div v-if="openedFieldId == field.id">
<field-edition-form
:collectionId="collectionId"
:isRepositoryLevel="isRepositoryLevel"
@onEditionFinished="onEditionFinished()"
@onEditionCanceled="onEditionCanceled()"
@onErrorFound="formWithErrors = field.id"
:index="index"
:originalField="field"
:editedField="editForms[field.id]"></field-edition-form>
</div>
</div>
</draggable>
</div>
<div class="column available-fields-area" >
<div class="field">
<h3 class="label">{{ $i18n.get('label_available_field_types')}}</h3>
<draggable
:list="availableFieldList"
:options="{
sort: false,
group: { name:'fields', pull: 'clone', put: false, revertClone: true },
dragClass: 'sortable-drag'
}">
<div
@click.prevent="addFieldViaButton(field)"
class="available-field-item"
:class="{ 'hightlighted-field' : hightlightedField == field.name }"
v-for="(field, index) in availableFieldList"
:key="index">
<grip-icon></grip-icon>
<span class="field-name">{{ field.name }}</span>
<span class="loading-spinner" v-if="hightlightedField == field.name"></span>
</div>
</draggable>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex';
import GripIcon from '../other/grip-icon.vue';
import FieldEditionForm from './../edition/field-edition-form.vue';
export default {
@ -75,11 +120,35 @@ export default {
isLoadingFields: false,
isLoadingField: false,
openedFieldId: '',
editForm: {}
formWithErrors: '',
hightlightedField: '',
editForms: {}
}
},
components: {
FieldEditionForm
FieldEditionForm,
GripIcon
},
beforeRouteLeave ( to, from, next ) {
let hasUnsavedForms = false;
for (let editForm in this.editForms) {
if (!this.editForms[editForm].saved)
hasUnsavedForms = true;
}
if ((this.openedFieldId != '' && this.openedFieldId != undefined) || hasUnsavedForms ) {
this.$dialog.confirm({
message: this.$i18n.get('info_warning_fields_not_saved'),
onConfirm: () => {
this.onEditionCanceled();
next();
},
cancelText: this.$i18n.get('cancel'),
confirmText: this.$i18n.get('continue'),
type: 'is-secondary'
});
} else {
next()
}
},
methods: {
...mapActions('fields', [
@ -106,34 +175,36 @@ export default {
updateFieldsOrder() {
let fieldsOrder = [];
for (let field of this.activeFieldList) {
fieldsOrder.push({'id': field.id, 'enabled': !field.disabled});
fieldsOrder.push({'id': field.id, 'enabled': field.enabled});
}
this.updateCollectionFieldsOrder({ collectionId: this.collectionId, fieldsOrder: fieldsOrder });
},
onChangeEnable($event, index) {
this.activeFieldList[index].disabled = $event;
this.activeFieldList[index].enabled = $event;
let fieldsOrder = [];
for (let field of this.activeFieldList) {
fieldsOrder.push({'id': field.id, 'enabled': !field.disabled});
fieldsOrder.push({'id': field.id, 'enabled': field.enabled});
}
this.updateCollectionFieldsOrder({ collectionId: this.collectionId, fieldsOrder: fieldsOrder });
},
addFieldViaButton(fieldType) {
let lastIndex = this.activeFieldList.length;
this.activeFieldList.push(fieldType);
this.addNewField(fieldType, lastIndex);
// Higlights the clicker field
this.hightlightedField = fieldType.name;
},
addNewField(newField, newIndex) {
this.sendField({collectionId: this.collectionId, name: newField.name, fieldType: newField.className, status: 'auto-draft', isRepositoryLevel: this.isRepositoryLevel})
this.sendField({collectionId: this.collectionId, name: newField.name, fieldType: newField.className, status: 'auto-draft', isRepositoryLevel: this.isRepositoryLevel, newIndex: newIndex})
.then((field) => {
if (newIndex < 0) {
this.activeFieldList.pop();
this.activeFieldList.push(field);
} else {
this.activeFieldList.splice(newIndex, 1, field);
}
if (!this.isRepositoryLevel)
this.updateFieldsOrder();
this.editField(field);
this.hightlightedField = '';
})
.catch((error) => {
console.log(error);
@ -153,20 +224,35 @@ export default {
});
},
editField(field) {
if (this.openedFieldId == field.id) {
// Closing collapse
if (this.openedFieldId == field.id) {
this.openedFieldId = '';
this.editForm = {};
// Opening collapse
} else {
this.openedFieldId = field.id;
this.editForm = JSON.parse(JSON.stringify(field));
this.editForm.status = 'publish';
}
// First time opening
if (this.editForms[this.openedFieldId] == undefined) {
this.editForms[this.openedFieldId] = JSON.parse(JSON.stringify(field));
this.editForms[this.openedFieldId].saved = true;
// Field inserted now
if (this.editForms[this.openedFieldId].status == 'auto-draft') {
this.editForms[this.openedFieldId].status = 'publish';
this.editForms[this.openedFieldId].saved = false;
}
}
}
},
onEditionFinished() {
this.formWithErrors = '';
delete this.editForms[this.openedFieldId];
this.openedFieldId = '';
this.fetchFields({collectionId: this.collectionId, isRepositoryLevel: this.isRepositoryLevel});
},
onEditionCanceled() {
this.formWithErrors = '';
delete this.editForms[this.openedFieldId];
this.openedFieldId = '';
}
@ -209,16 +295,48 @@ export default {
}
</script>
<style lang="scss" scoped>
<style lang="scss">
@import "../../scss/_variables.scss";
.page-title {
border-bottom: 1px solid $secondary;
h2 {
color: $tertiary;
font-weight: 500;
}
margin: 1em 0em 2.0em 0em;
}
.loading-spinner {
animation: spinAround 500ms infinite linear;
border: 2px solid #dbdbdb;
border-radius: 290486px;
border-right-color: transparent;
border-top-color: transparent;
content: "";
display: inline-block;
height: 1em;
width: 1em;
}
.active-fields-area {
min-height: 40px;
padding: 10px;
font-size: 14px;
margin-right: 0.8em;
margin-left: -0.8em;
padding-right: 6em;
min-height: 330px;
@media screen and (max-width: 769px) {
min-height: 45px;
margin: 0;
padding-right: 0em;
}
@media screen and (max-width: 1216px) {
padding-right: 1em;
}
&.fields-area-receive {
background-color: whitesmoke;
border: 1px dashed gray;
}
@ -228,87 +346,298 @@ export default {
.active-field-item {
background-color: white;
padding: 0.4em;
margin: 10px;
border-radius: 5px;
border: 1px solid gainsboro;
padding: 0.7em 0.9em;
margin: 4px;
min-height: 40px;
display: block;
transition: top 0.2s ease;
position: relative;
cursor: grab;
.handle {
padding-right: 6em;
}
.grip-icon {
fill: $gray;
top: 2px;
position: relative;
}
.field-name {
text-overflow: ellipsis;
overflow-x: hidden;
white-space: nowrap;
font-weight: bold;
margin-left: 0.4em;
margin-right: 0.4em;
&.is-danger {
color: $danger !important;
}
}
.label-details {
font-weight: normal;
color: $gray;
}
.not-saved {
font-style: italic;
color: gray;
font-weight: bold;
color: $danger;
}
.controls { float: right }
.loading-spinner {
animation: spinAround 500ms infinite linear;
border: 2px solid #dbdbdb;
border-radius: 290486px;
border-right-color: transparent;
border-top-color: transparent;
content: "";
display: inline-block;
height: 1em;
width: 1em;
.controls {
position: absolute;
right: 5px;
top: 10px;
.switch {
position: relative;
bottom: 3px;
}
.icon {
bottom: 1px;
position: relative;
i, i:before { font-size: 20px; }
}
}
&.not-sortable-item, &.not-sortable-item:hover, &.not-focusable-item, &.not-focusable-item:hover {
box-shadow: none !important;
top: 0px !important;
&.not-sortable-item, &.not-sortable-item:hover {
cursor: default;
}
&.inherited-field {
color: gray;
}
}
.active-field-item:hover {
box-shadow: 0 3px 4px rgba(0,0,0,0.25);
position: relative;
top: -2px;
}
background-color: white !important;
.sortable-chosen {
background-color: $primary-lighter;
margin: 10px;
border-radius: 5px;
border: 1px dashed $primary-light;
display: block;
.handle .label-details, .handle .icon {
color: $gray !important;
}
}
&.not-focusable-item, &.not-focusable-item:hover {
cursor: default;
.field-name {
color: $primary;
}
.handle .label-details, .handle .icon {
color: $gray !important;
}
}
&.disabled-field {
color: $gray;
}
}
.active-field-item:hover:not(.not-sortable-item) {
background-color: $secondary;
border-color: $secondary;
color: white !important;
.label-details, .icon, .not-saved {
color: white !important;
}
.grip-icon {
fill: white;
}
.switch.is-small {
input[type="checkbox"] + .check {
border: 1.5px solid white !important;
&::before { background-color: white !important; }
}
input[type="checkbox"]:checked + .check {
border: 1.5px solid white !important;
&::before { background-color: white !important; }
}
&:hover input[type="checkbox"] + .check {
border: 1.5px solid white !important;
background-color: $secondary !important;
}
}
}
.sortable-ghost {
border: 1px dashed $draggable-border-color;
display: block;
padding: 0.7em 0.9em;
margin: 4px;
height: 40px;
position: relative;
.grip-icon {
fill: white;
}
}
}
.available-fields-area {
padding: 0 10px;
padding: 10px 0px 10px 10px;
margin: 0;
background-color: whitesmoke;
max-width: 280px;
font-size: 14px;
@media screen and (max-width: 769px) {
max-width: 100%;
padding: 10px;
h3 {
margin: 1em 0em 1em 0em !important;
}
.available-field-item::before,
.available-field-item::after {
display: none !important;
}
}
h3 {
color: $secondary;
margin: 0.2em 0em 1em -1.2em;
font-weight: 500;
}
.available-field-item {
padding: 0.4em;
margin: 10px 10% 10px 0px;
border-radius: 5px;
padding: 0.7em;
margin: 4px;
background-color: white;
border: 1px solid gainsboro;
width: 100%;
cursor: grab;
top: 0;
transition: top 0.2s ease;
cursor: pointer;
left: 0;
line-height: 1.3em;
height: 40px;
position: relative;
border: 1px solid $draggable-border-color;
border-radius: 1px;
transition: left 0.2s ease;
.grip-icon {
fill: $gray;
top: -3px;
position: relative;
display: inline-block;
}
.icon {
position: relative;
bottom: 1px;
}
.field-name {
text-overflow: ellipsis;
overflow-x: hidden;
white-space: nowrap;
font-weight: bold;
margin-left: 0.4em;
display: inline-block;
max-width: 200px;
}
&:after,
&:before {
content: '';
display: block;
position: absolute;
right: 100%;
width: 0;
height: 0;
border-style: solid;
}
&:after {
top: -1px;
border-color: transparent white transparent transparent;
border-right-width: 16px;
border-top-width: 20px;
border-bottom-width: 20px;
left: -19px;
}
&:before {
top: -1px;
border-color: transparent $draggable-border-color transparent transparent;
border-right-width: 16px;
border-top-width: 20px;
border-bottom-width: 20px;
left: -20px;
}
}
.sortable-drag {
opacity: 1 !important;
}
@keyframes hightlighten {
0% {
color: #222;
background-color: white;
border-color: white;
}
25% {
color: white;
background-color: #2cb4c1;
border-color: #2cb4c1;
}
75% {
color: white;
background-color: #2cb4c1;
border-color: #2cb4c1;
}
100% {
color: #222;
background-color: white;
border-color: white;
}
}
@keyframes hightlighten-icon {
0% { fill: #b1b1b1; }
25% { fill: white; }
75% { fill: white; }
100% { fill: #b1b1b1; }
}
@keyframes hightlighten-arrow {
0% {
border-color: transparent white transparent transparent;
border-color: transparent white transparent transparent;
}
25% {
border-color: transparent #2cb4c1 transparent transparent;
border-color: transparent #2cb4c1 transparent transparent;
}
75% {
border-color: transparent #2cb4c1 transparent transparent;
border-color: transparent #2cb4c1 transparent transparent;
}
100% {
border-color: transparent white transparent transparent;
border-color: transparent white transparent transparent;
}
}
.hightlighted-field {
background-color: white;
position: relative;
left: 0px;
animation-name: hightlighten;
animation-duration: 1.0s;
animation-iteration-count: 2;
.grip-icon{
animation-name: hightlighten-icon;
animation-duration: 1.0s;
animation-iteration-count: 2;
}
&::before,
&::after {
animation-name: hightlighten-arrow;
animation-duration: 1.0s;
animation-iteration-count: 2;
}
}
.available-field-item:hover {
border: 1px solid lightgrey;
box-shadow: 2px 3px 4px rgba(0,0,0,.25);
background-color: $secondary;
border-color: $secondary;
color: white;
position: relative;
top: -2px;
left: -2px;
left: -4px;
&:after {
border-color: transparent $secondary transparent transparent;
}
&:before {
border-color: transparent $secondary transparent transparent;
}
.icon {
color: white !important;
}
.grip-icon {
fill: white;
}
}
}
</style>
</style>

View File

@ -1,13 +1,15 @@
<template>
<div>
<tainacan-filters-list
:query="getPostQuery()"
v-for="(filter, index) in filters"
v-bind:key="index"
:filter="filter"></tainacan-filters-list>
</div>
</template>
<script>
import { mapActions } from 'vuex';
import { mapActions, mapGetters } from 'vuex';
import { eventFilterBus } from '../../../js/event-bus-filters'
export default {
data(){
@ -28,6 +30,9 @@
methods: {
...mapActions('filter',[
'fetchFilters'
]),
...mapGetters('search',[
'getPostQuery'
])
}
}

View File

@ -1,88 +1,124 @@
<template>
<div>
<b-loading :active.sync="isLoadingFieldTypes"></b-loading>
<div class="page-title">
<h2>{{ isRepositoryLevel ? $i18n.get('instruction_dragndrop_filters_collection') : $i18n.get('instruction_dragndrop_filters_collection') }}</h2>
</div>
<div class="columns">
<div class="column">
<b-filter :label="$i18n.get('label_active_filters')" is-grouped>
<draggable
class="box active-filters-area"
@change="handleChange"
:class="{'filters-area-receive': isDraggingFromAvailable}"
:list="activeFilterList"
:options="{group: { name:'filters', pull: false, put: true }, 'handle': '.handle', chosenClass: 'sortable-chosen', filter: '.not-sortable-item'}">
<div
class="active-filter-item"
:class="{'not-sortable-item': filter.id == undefined, 'not-focusable-item': openedFilterId == filter.id, 'inherited-filter': filter.collection_id != collectionId}"
v-for="(filter, index) in activeFilterList" :key="index">
<div class="handle">
<b-icon type="is-gray" class="is-pulled-left" icon="drag"></b-icon>
<span class="filter-name">{{ filter.name }}</span>
<span v-if="filter.id !== undefined" class="label-details">{{ $i18n.get(filter.filter_type_object.component)}}</span><span class="loading-spinner" v-if="filter.id == undefined"></span>
<span class="controls" v-if="filter.id != undefined">
<b-switch size="is-small" v-model="filter.disabled" @input="onChangeEnable($event, index)">{{ filter.disabled ? $i18n.get('label_disabled') : $i18n.get('label_enabled') }}</b-switch>
<a @click.prevent="removeFilter(filter)">
<b-icon icon="delete"></b-icon>
</a>
<a @click.prevent="editFilter(filter)">
<b-icon icon="pencil"></b-icon>
</a>
</span>
<b-modal :active.sync="isModalOpened" :width="320" scroll="keep">
<div class="filter-selection-modal">
<b-field :label="$i18n.get('label_filter_type')">
<b-select
:placeholder="$i18n.get('instruction_select_a_filter_type')">
<option value="publish" selected>{{ $i18n.get('publish')}}</option>
<option value="private">{{ $i18n.get('private')}}</option>
</b-select>
</b-field>
<div class="field is-grouped is-grouped-centered">
<div class="control">
<button
class="button is-secondary"
type="submit"
@click.prevent="confirmSelectedFilterType()">Submit</button>
</div>
<div class="control">
<button
class="button is-text"
@click.prevent="cancelFilterTypeSelection()"
slot="trigger">Cancel</button>
</div>
</div>
<div class="column">
<draggable
class="active-filters-area"
@change="handleChange"
:class="{'filters-area-receive': isDraggingFromAvailable}"
:list="activeFilterList"
:options="{
group: { name:'filters', pull: false, put: true },
sort: openedFilterId == '' || openedFilterId == undefined,
disabled: openedFilterId != '' && openedFilterId != undefined,
handle: '.handle',
ghostClass: 'sortable-ghost',
filter: 'not-sortable-item',
animation: '250'}">
<div
class="active-filter-item"
:class="{
'not-sortable-item': filter.id == undefined || openedFilterId != '' || choosenField.name == filter.name,
'not-focusable-item': openedFilterId == filter.id,
'disabled-filter': filter.enabled == false
}"
v-for="(filter, index) in activeFilterList" :key="index">
<div class="handle">
<grip-icon></grip-icon>
<span
class="filter-name"
:class="{'is-danger': formWithErrors == filter.id }">
{{ filter.name }}
</span>
<span
v-if="filter.filter_type_object != undefined"
class="label-details">
({{ $i18n.get(filter.filter_type_object.component) }})
<span class="not-saved" v-if="(editForms[filter.id] != undefined && editForms[filter.id].saved != true) ||filter.status == 'auto-draft'">
{{ $i18n.get('info_not_saved') }}
</span>
</span>
<span class="loading-spinner" v-if="filter.id == undefined"></span>
<span class="controls" v-if="filter.filter_type != undefined">
<b-switch size="is-small" v-model="filter.enabled" @input="onChangeEnable($event, index)"></b-switch>
<a :style="{ visibility: filter.collection_id != collectionId ? 'hidden' : 'visible' }"
@click.prevent="editFilter(filter)">
<b-icon type="is-gray" icon="pencil"></b-icon>
</a>
<a :style="{ visibility: filter.collection_id != collectionId ? 'hidden' : 'visible' }"
@click.prevent="removeFilter(filter)">
<b-icon type="is-gray" icon="delete"></b-icon>
</a>
</span>
</div>
<div v-if="choosenField.name == filter.name && openedFilterId == ''">
<form class="tainacan-form">
<b-field :label="$i18n.get('label_filter_type')">
<b-select
v-model="selectedFilterType"
:placeholder="$i18n.get('instruction_select_a_filter_type')">
<option
v-for="(filterType, index) in allowedFilterTypes"
:key="index"
:selected="index == 0"
:value="filterType">
{{ filterType.name }}</option>
</b-select>
</b-field>
<div class="field is-grouped form-submit">
<div class="control">
<button
class="button is-outlined"
@click.prevent="cancelFilterTypeSelection()"
slot="trigger">{{ $i18n.get('cancel')}}</button>
</div>
</b-modal>
</div>
<b-filter v-if="openedFilterId == filter.id">
<!-- <filter-edition-form
:collectionId="collectionId"
:isRepositoryLevel="isRepositoryLevel"
@onEditionFinished="onEditionFinished()"
@onEditionCanceled="onEditionCanceled()"
:filter="editForm"></filter-edition-form> -->
</b-filter>
<div class="control">
<button
class="button is-success"
type="submit"
:disabled="Object.keys(selectedFilterType).length == 0"
@click.prevent="confirmSelectedFilterType()">{{ $i18n.get('next')}}</button>
</div>
</div>
</form>
</div>
<!-- <div class="not-sortable-item" slot="footer">{{ $i18n.get('instruction_dragndrop_filters_collection') }}</div> -->
</draggable>
</b-filter>
<b-field v-if="openedFilterId == filter.id">
<filter-edition-form
@onEditionFinished="onEditionFinished()"
@onEditionCanceled="onEditionCanceled()"
@onErrorFound="formWithErrors = filter.id"
:index="index"
:originalFilter="filter"
:editedFilter="editForms[openedFilterId]"></filter-edition-form>
</b-field>
</div>
</draggable>
</div>
<div class="column">
<b-filter :label="$i18n.get('label_available_field_types')">
<div class="columns box available-fields-area" >
<draggable class="column" :list="availableFieldList" :options="{ sort: false, group: { name:'filters', pull: 'clone', put: false, revertClone: true }}">
<div class="available-field-item" v-if="index % 2 == 0" v-for="(field, index) in availableFieldList" :key="index">
{{ field.name }} <b-icon type="is-gray" class="is-pulled-left" icon="drag"></b-icon>
</div>
</draggable>
<draggable class="column" :list="availableFieldList" :options="{ sort: false, group: { name:'filters', pull: 'clone', put: false, revertClone: true }}">
<div class="available-field-item" v-if="index % 2 != 0" v-for="(field, index) in availableFieldList" :key="index">
{{ field.name }} <b-iiltercon type="is-gray" class="is-pulled-left" icon="drag"></b-iiltercon>
</div>
</draggable>
</div>
</b-filter>
<div class="column available-fields-area">
<div class="field">
<h3 class="label"> {{ $i18n.get('label_available_field_types') }}</h3>
<draggable
:list="availableFieldList"
:options="{
sort: false,
group: { name:'filters', pull: true, put: false, revertClone: true },
dragClass: 'sortable-drag'
}">
<div
class="available-field-item"
v-for="(field, index) in availableFieldList"
:key="index"
@click.prevent="addFieldViaButton(field, index)">
<grip-icon></grip-icon>
<span class="field-name">{{ field.name }}</span>
</div>
</draggable>
</div>
</div>
</div>
</div>
@ -90,6 +126,7 @@
<script>
import { mapActions, mapGetters } from 'vuex';
import GripIcon from '../other/grip-icon.vue';
import FilterEditionForm from './../edition/filter-edition-form.vue';
export default {
@ -104,12 +141,38 @@ export default {
isLoadingFilterTypes: false,
isLoadingFilter: false,
openedFilterId: '',
isModalOpened: false,
editForm: {}
formWithErrors: '',
editForms: {},
allowedFilterTypes: [],
selectedFilterType: {},
choosenField: {},
newIndex: 0
}
},
components: {
//FilterEditionForm
FilterEditionForm,
GripIcon
},
beforeRouteLeave ( to, from, next ) {
let hasUnsavedForms = false;
for (let editForm in this.editForms) {
if (!this.editForms[editForm].saved)
hasUnsavedForms = true;
}
if ((this.openedFilterId != '' && this.openedFilterId != undefined) || hasUnsavedForms ) {
this.$dialog.confirm({
message: this.$i18n.get('info_warning_filters_not_saved'),
onConfirm: () => {
this.onEditionCanceled();
next();
},
cancelText: this.$i18n.get('cancel'),
confirmText: this.$i18n.get('continue'),
type: 'is-secondary'
});
} else {
next()
}
},
methods: {
...mapActions('filter', [
@ -124,10 +187,10 @@ export default {
'getFilterTypes'
]),
...mapActions('fields', [
'fetchFieldTypes'
'fetchFields'
]),
...mapGetters('fields',[
'getFieldTypes'
'getFields'
]),
handleChange($event) {
if ($event.added) {
@ -142,48 +205,87 @@ export default {
updateFiltersOrder() {
let filtersOrder = [];
for (let filter of this.activeFilterList) {
filtersOrder.push({'id': filter.id, 'enabled': !filter.disabled});
filtersOrder.push({'id': filter.id, 'enabled': filter.enabled});
}
this.updateCollectionFiltersOrder({ collectionId: this.collectionId, filtersOrder: filtersOrder });
},
onChangeEnable($event, index) {
this.activeFilterList[index].disabled = $event;
this.activeFilterList[index].enabled = $event;
let filtersOrder = [];
for (let filter of this.activeFilterList) {
filtersOrder.push({'id': filter.id, 'enabled': !filter.disabled});
filtersOrder.push({'id': filter.id, 'enabled': filter.enabled});
}
this.updateCollectionFiltersOrder({ collectionId: this.collectionId, filtersOrder: filtersOrder });
},
addNewFilter(newFilter, newIndex) {
this.isModalOpened = true;
},
createChoosenFilter(field, newFilter, newIndex) {
this.sendFilter({collectionId: this.collectionId, fieldId: field.id, name: newFilter.name, filterType: newFilter.className, status: 'auto-draft', isRepositoryLevel: this.isRepositoryLevel})
.then((filter) => {
addFieldViaButton(fieldType, fieldIndex) {
this.availableFieldList.splice(fieldIndex, 1);
if (newIndex < 0) {
this.activeFilterList.pop();
this.activeFilterList.push(filter);
} else {
this.activeFilterList.splice(newIndex, 1, filter);
let lastIndex = this.activeFilterList.length;
this.activeFilterList.push(fieldType);
this.addNewFilter(fieldType, lastIndex);
},
addNewFilter(choosenField, newIndex) {
console.log(choosenField);
this.choosenField = choosenField;
this.newIndex = newIndex;
this.openedFilterId = '';
this.allowedFilterTypes = [];
this.selectedFilterType = {};
for (let filter of this.filterTypes) {
for (let supportedType of filter['supported_types']) {
if (choosenField.field_type_object.primitive_type == supportedType)
this.allowedFilterTypes.push(filter);
}
}
},
createChoosenFilter() {
this.sendFilter({
collectionId: this.collectionId,
fieldId: this.choosenField.id,
name: this.choosenField.name,
filterType: this.selectedFilterType.name,
status: 'auto-draft',
isRepositoryLevel: this.isRepositoryLevel,
newIndex: this.newIndex
})
.then((filter) => {
if (!this.isRepositoryLevel)
this.updateFiltersOrder();
this.newIndex = 0;
this.choosenField = {};
this.selectedFilterType = {}
this.allowedFilterTypes = [];
this.editFilter(filter);
})
.catch((error) => {
console.log(error);
this.newIndex = 0;
this.choosenField = {};
this.selectedFilterType = {}
this.allowedFilterTypes = [];
});
},
removeFilter(removedFilter) {
this.deleteFilter({ collectionId: this.collectionId, filterId: removedFilter.id, isRepositoryLevel: this.isRepositoryLevel})
this.deleteFilter(removedFilter.id)
.then((filter) => {
let index = this.activeFilterList.findIndex(deletedFilter => deletedFilter.id === filter.id);
if (index >= 0)
this.activeFilterList.splice(index, 1);
this.isLoadingFieldTypes = true;
this.fetchFields({collectionId: this.collectionId, isRepositoryLevel: this.isRepositoryLevel})
.then((res) => {
this.isLoadingFieldTypes = false;
})
.catch((error) => {
this.isLoadingFieldTypes = false;
});
if (!this.isRepositoryLevel)
this.updateFiltersOrder();
@ -192,74 +294,109 @@ export default {
});
},
confirmSelectedFilterType() {
// this.createChoosenFilter();
this.createChoosenFilter();
},
cancelFilterTypeSelection() {
// this.createChoosenFilter();
this.$modal.close();
this.availableFieldList.push(this.choosenField);
this.choosenField = {};
this.allowedFilterTypes = [];
this.selectedFilterType = {};
this.activeFilterList.splice(this.newIndex, 1);
this.newIndex = 0;
},
editFilter(filter) {
if (this.openedFilterId == filter.id) {
// Closing collapse
if (this.openedFilterId == filter.id) {
this.openedFilterId = '';
this.editForm = {};
// Opening collapse
} else {
console.log(this.choosenField);
if (this.openedFilterId == '' && this.choosenField.id != undefined) {
this.availableFieldList.push(this.choosenField);
this.choosenField = {};
this.allowedFilterTypes = [];
this.selectedFilterType = {};
this.activeFilterList.splice(this.newIndex, 1);
this.newIndex = 0;
}
this.openedFilterId = filter.id;
this.editForm = JSON.parse(JSON.stringify(filter));
this.editForm.status = 'publish';
}
// First time opening
if (this.editForms[this.openedFilterId] == undefined) {
this.editForms[this.openedFilterId] = JSON.parse(JSON.stringify(filter));
this.editForms[this.openedFilterId].saved = true;
// Filter inserted now
if (this.editForms[this.openedFilterId].status == 'auto-draft') {
this.editForms[this.openedFilterId].status = 'publish';
this.editForms[this.openedFilterId].saved = false;
}
}
}
},
onEditionFinished() {
this.formWithErrors = '';
delete this.editForms[this.openedFilterId];
this.openedFilterId = '';
this.fetchFilters({collectionId: this.collectionId, isRepositoryLevel: this.isRepositoryLevel});
},
onEditionCanceled() {
this.formWithErrors = '';
delete this.editForms[this.openedFilterId];
this.openedFilterId = '';
}
},
computed: {
availableFieldList() {
return this.getFieldTypes();
let availableFields = this.getFields();
for (let activeFilter of this.activeFilterList) {
for (let i = availableFields.length - 1; i >= 0 ; i--) {
if (activeFilter.field != undefined) {
if (activeFilter.field.field_id == availableFields[i].id)
availableFields.splice(i, 1);
}
}
}
return availableFields;
},
activeFilterList() {
return this.getFilters();
},
filterTypes() {
filterTypes() {
return this.getFilterTypes();
}
},
created() {
this.isLoadingFieldTypes = true;
this.isLoadingFilters = true;
this.isLoadingFilterTypes = true;
this.fetchFieldTypes()
.then((res) => {
this.isLoadingFieldTypes = false;
})
.catch((error) => {
this.isLoadingFieldTypes = false;
});
this.fetchFilterTypes()
.then((res) => {
console.log(res);
this.isLoadingFilterTypes = false;
})
.catch((error) => {
this.isLoadingFilterTypes = false;
});
this.isRepositoryLevel = this.$route.name == 'FiltersPage' ? true : false;
if (this.isRepositoryLevel)
this.collectionId = 'default';
else
this.collectionId = this.$route.params.collectionId;
this.isLoadingFieldTypes = true;
this.isLoadingFilters = true;
this.isLoadingFilterTypes = true;
this.fetchFilterTypes()
.then((res) => {
this.isLoadingFilterTypes = false;
})
.catch((error) => {
this.isLoadingFilterTypes = false;
});
this.fetchFilters({collectionId: this.collectionId, isRepositoryLevel: this.isRepositoryLevel})
.then((res) => {
this.isLoadingFilters = false;
// Needs to be done after activeFilterList exists to compare and remove chosen fields.
this.fetchFields({collectionId: this.collectionId, isRepositoryLevel: this.isRepositoryLevel})
.then((res) => {
this.isLoadingFieldTypes = false;
})
.catch((error) => {
this.isLoadingFieldTypes = false;
});
})
.catch((error) => {
this.isLoadingFilters = false;
@ -268,16 +405,48 @@ export default {
}
</script>
<style lang="scss" scoped>
<style lang="scss">
@import "../../scss/_variables.scss";
.page-title {
border-bottom: 1px solid $secondary;
h2 {
color: $tertiary;
font-weight: 500;
}
margin: 1em 0em 2.0em 0em;
}
.loading-spinner {
animation: spinAround 500ms infinite linear;
border: 2px solid #dbdbdb;
border-radius: 290486px;
border-right-color: transparent;
border-top-color: transparent;
content: "";
display: inline-block;
height: 1em;
width: 1em;
}
.active-filters-area {
min-height: 40px;
padding: 10px;
font-size: 14px;
margin-right: 0.8em;
margin-left: -0.8em;
padding-right: 6em;
min-height: 330px;
@media screen and (max-width: 769px) {
min-height: 45px;
margin: 0;
padding-right: 0em;
}
@media screen and (max-width: 1216px) {
padding-right: 1em;
}
&.filters-area-receive {
background-color: whitesmoke;
border: 1px dashed gray;
}
@ -285,91 +454,234 @@ export default {
display: initial;
}
.filter-selection-modal{
padding: 20px;
background-color: white;
border-radius: 3px;
}
.active-filter-item {
background-color: white;
padding: 0.4em;
margin: 10px;
border-radius: 5px;
border: 1px solid gainsboro;
padding: 0.7em 0.9em;
margin: 4px;
min-height: 40px;
position: relative;
display: block;
transition: top 0.2s ease;
transition: top 0.1s ease;
cursor: grab;
.handle {
padding-right: 6em;
}
.grip-icon {
fill: $gray;
top: 2px;
position: relative;
}
.filter-name {
text-overflow: ellipsis;
overflow-x: hidden;
white-space: nowrap;
font-weight: bold;
margin-left: 0.4em;
margin-right: 0.4em;
&.is-danger {
color: $danger !important;
}
}
.label-details {
font-weight: normal;
color: $gray;
}
.not-saved {
font-style: italic;
color: gray;
font-weight: bold;
color: $danger;
}
.controls { float: right }
.loading-spinner {
animation: spinAround 500ms infinite linear;
border: 2px solid #dbdbdb;
border-radius: 290486px;
border-right-color: transparent;
border-top-color: transparent;
content: "";
display: inline-block;
height: 1em;
width: 1em;
.controls {
position: absolute;
right: 5px;
top: 10px;
.switch {
position: relative;
bottom: 3px;
}
.icon {
bottom: 1px;
position: relative;
i, i:before { font-size: 20px; }
}
}
&.not-sortable-item, &.not-sortable-item:hover, &.not-focusable-item, &.not-focusable-item:hover {
box-shadow: none !important;
top: 0px !important;
color: gray;
cursor: default;
}
&.inherited-filter {
color: gray;
}
}
.active-filter-item:hover {
box-shadow: 0 3px 4px rgba(0,0,0,0.25);
position: relative;
top: -2px;
}
.sortable-chosen {
background-color: $primary-lighter;
margin: 10px;
border-radius: 5px;
border: 1px dashed $primary-light;
display: block;
form {
padding: 1.0em 2.0em;
border-top: 1px solid $draggable-border-color;
border-bottom: 1px solid $draggable-border-color;
margin-top: 1.0em;
}
&.not-sortable-item, &.not-sortable-item:hover {
cursor: default;
background-color: white !important;
.handle .label-details, .handle .icon {
color: $gray !important;
}
}
&.not-focusable-item, &.not-focusable-item:hover {
cursor: default;
.field-name {
color: $primary;
}
.handle .label-details, .handle .icon {
color: $gray !important;
}
}
&.disabled-field {
color: $gray;
}
}
.active-filter-item:hover:not(.not-sortable-item) {
background-color: $secondary;
border-color: $secondary;
color: white !important;
.grip-icon {
fill: $white;
}
.label-details, .icon {
color: white !important;
}
.switch.is-small {
input[type="checkbox"] + .check {
border: 1.5px solid white !important;
&::before { background-color: white !important; }
}
input[type="checkbox"]:checked + .check {
border: 1.5px solid white !important;
&::before { background-color: white !important; }
}
&:hover input[type="checkbox"] + .check {
border: 1.5px solid white !important;
background-color: $secondary !important;
}
}
}
.sortable-ghost {
border: 1px dashed $draggable-border-color;
display: block;
padding: 0.7em 0.9em;
margin: 4px;
height: 40px;
position: relative;
.grip-icon {
fill: $gray;
top: 2px;
position: relative;
}
}
}
.available-fields-area {
padding: 0 10px;
padding: 10px 0px 10px 10px;
margin: 0;
background-color: whitesmoke;
max-width: 280px;
font-size: 14px;
@media screen and (max-width: 769px) {
max-width: 100%;
padding: 10px;
h3 {
margin: 1em 0em 1em 0em !important;
}
.available-field-item::before,
.available-field-item::after {
display: none !important;
}
}
h3 {
color: $secondary;
margin: 0.2em 0em 1em -1.2em;
font-weight: 500;
}
.available-field-item {
padding: 0.4em;
margin: 10px 10% 10px 0px;
border-radius: 5px;
padding: 0.7em;
margin: 4px;
background-color: white;
border: 1px solid gainsboro;
width: 100%;
cursor: grab;
top: 0;
transition: top 0.2s ease;
cursor: pointer;
left: 0;
line-height: 1.3em;
height: 40px;
position: relative;
border: 1px solid $draggable-border-color;
border-radius: 1px;
transition: left 0.2s ease;
.grip-icon {
fill: $gray;
top: -3px;
position: relative;
display: inline-block;
}
.icon {
position: relative;
bottom: 3px;
}
.field-name {
text-overflow: ellipsis;
overflow-x: hidden;
white-space: nowrap;
font-weight: bold;
margin-left: 0.4em;
display: inline-block;
max-width: 200px;
}
&:after,
&:before {
content: '';
display: block;
position: absolute;
right: 100%;
width: 0;
height: 0;
border-style: solid;
}
&:after {
top: -1px;
border-color: transparent white transparent transparent;
border-right-width: 16px;
border-top-width: 20px;
border-bottom-width: 20px;
left: -19px;
}
&:before {
top: -1px;
border-color: transparent $draggable-border-color transparent transparent;
border-right-width: 16px;
border-top-width: 20px;
border-bottom-width: 20px;
left: -20px;
}
}
.sortable-drag {
opacity: 1 !important;
}
.available-field-item:hover {
border: 1px solid lightgrey;
box-shadow: 2px 3px 4px rgba(0,0,0,.25);
background-color: $secondary;
border-color: $secondary;
color: white;
position: relative;
top: -2px;
left: -2px;
left: -4px;
&:after {
border-color: transparent $secondary transparent transparent;
}
&:before {
border-color: transparent $secondary transparent transparent;
}
.grip-icon {
fill: white !important;
}
}
}

View File

@ -24,20 +24,18 @@
<router-link tag="span" class="clickable-row" :to="{path: $routerHelper.getItemPath(collectionId, props.row.id)}">
<template v-if="column.field != 'featured_image' && column.field != 'row_actions'">
{{ props.row.metadata[column.slug].multiple == 'yes' ? props.row.metadata[column.slug].value.join(', ') : props.row.metadata[column.slug].value}}
</template>
</router-link>
<router-link tag="span" class="clickable-row" :to="{path: $routerHelper.getItemPath(collectionId, props.row.id)}">
<template v-if="column.field == 'featured_image'">
<img class="table-thumb" :src="`${ props.row[column.slug] }`"/>
{{ showValue( props.row.metadata[column.slug] ) }}
</template>
</router-link>
<template v-if="column.field == 'featured_image'">
<router-link tag="img" class="table-thumb clickable-row" :to="{path: $routerHelper.getItemPath(collectionId, props.row.id)}" :src="props.row[column.slug]"></router-link>
</template>
<template v-if="column.field == 'row_actions'">
<!-- <a id="button-view" @click.prevent.stop="goToItemPage(props.row.id)"><b-icon icon="eye"></a> -->
<a id="button-edit" :aria-label="$i18n.getFrom('items','edit_item')" @click="goToItemEditPage(props.row.id)"><b-icon icon="pencil"></a>
<a id="button-delete" :aria-label="$i18n.get('label_button_delete')" @click="deleteOneItem(props.row.id)"><b-icon icon="delete"></a>
<a id="button-edit" :aria-label="$i18n.getFrom('items','edit_item')" @click="goToItemEditPage(props.row.id)"><b-icon type="is-gray" icon="pencil"></a>
<a id="button-delete" :aria-label="$i18n.get('label_button_delete')" @click="deleteOneItem(props.row.id)"><b-icon type="is-gray" icon="delete"></a>
</template>
</b-table-column>
@ -160,6 +158,20 @@ export default {
goToItemEditPage(itemId) {
this.$router.push(this.$routerHelper.getItemEditPath(this.collectionId, itemId));
},
showValue( metadata ){
if( ! metadata || metadata.value === false )
return '';
if( Array.isArray( metadata.value ) ){
let result = [];
for( let val of metadata.value ){
result.push( ( val.name ) ? val.name : val )
}
return result.join(', ');
} else {
return metadata.value.name ? metadata.value.name : metadata.value
}
}
}
}
</script>

View File

@ -40,7 +40,7 @@
<b-icon size="is-small" icon="shape"></b-icon> <span class="menu-text">{{ $i18n.getFrom('categories', 'name') }}</span>
</router-link></li>
<li><router-link tag="a" to="/events" :class="activeRoute == 'EventsPage' ? 'is-active':''">
<b-icon size="is-small" icon="bell"></b-icon> <span class="menu-text">{{ $i18n.getFrom('events', 'name') }}</span>
<b-icon size="is-small" icon="bell"></b-icon> <span class="menu-text">{{ $i18n.get('events') }}</span>
</router-link></li>
</ul>
</aside>
@ -175,7 +175,36 @@ export default {
@media screen and (max-width: 769px) {
width: 100% !important;
max-width: 100% !important;
max-width: 100% !important;
.menu-header {
height: 60px;
}
ul {
flex-flow: wrap;
display: flex;
align-items: stretch;
justify-content: space-evenly;
.separator { display: none; }
.search-area {
flex-basis: 100%;
padding-top: 1.0em !important;
.field {
padding: 0 0.8em !important;
margin-bottom: 0px;
}
}
a{
padding: 0.8em !important;
text-align: center;
}
li + li {
.menu-text{
display: none !important;
}
}
}
&.is-compressed {
@ -190,20 +219,9 @@ export default {
}
}
}
.separator {
width: 2px;
height: auto;
margin: 0;
}
a{ padding: 1em 0.8em !important;}
.menu-text {
display: none !important;
}
ul {
display: flex;
align-items: stretch;
justify-content: space-evenly;
.search-area {
display: none;
}
}
}
}

View File

@ -155,19 +155,27 @@ export default {
@media screen and (max-width: 769px) {
width: 100% !important;
max-width: 100% !important;
a{ padding: 1em 0.8em !important; }
.menu-header { display: none;
}
.menu-text {
padding-left: 0.3em !important;
}
.separator, .menu-header { display: none; }
ul {
flex-flow: wrap;
display: flex;
align-items: stretch;
justify-content: space-evenly;
.separator, li.search-area {
display: none;
a {
padding: 0.5em 0.7em !important;
text-align: center;
}
.menu-text {
padding-left: 0.3em !important;
}
.search-area {
flex-basis: 100%;
padding-top: 1.0em !important;
.field {
padding: 0 0.8em !important;
margin-bottom: 0px;
}
}
}
}

View File

@ -1,7 +1,7 @@
<template>
<div id="tainacan-header" class="level">
<div id="tainacan-header" class="level" :class="{'secondary-page': onSecondaryPage}">
<div class="level-left">
<div class="level-item" :class="{'secondary-page': onSecondaryPage}">
<div class="level-item">
<h1 class="has-text-weight-bold is-uppercase has-text-primary"><b-icon size="is-small" :icon="currentIcon"></b-icon>{{pageTitle}}</h1>
<nav class="breadcrumbs">
<router-link tag="a" :to="$routerHelper.getCollectionsPath()">{{ $i18n.get('repository') }}</router-link> >
@ -53,6 +53,12 @@ export default {
...mapGetters('item', [
'getItemTitle'
]),
...mapActions('category', [
'fetchCategoryName'
]),
...mapGetters('category', [
'getCategoryName'
]),
generateViewPath() {
for (let i = 0; i < this.arrayRealPath.length; i++) {
@ -66,12 +72,17 @@ export default {
this.fetchCollectionName(this.arrayRealPath[i])
.then(collectionName => this.arrayViewPath.splice(i, 1, collectionName))
.catch((error) => console.log(error));
break;
break;
case 'items':
this.fetchItemTitle(this.arrayRealPath[i])
.then(itemTitle => this.arrayViewPath.splice(i, 1,itemTitle))
.then(itemTitle => this.arrayViewPath.splice(i, 1, itemTitle))
.catch((error) => console.log(error));
break;
break;
case 'categories':
this.fetchCategoryName(this.arrayRealPath[i])
.then(categoryName => this.arrayViewPath.splice(i, 1, categoryName))
.catch((error) => console.log(error));
break;
}
} else {
@ -111,7 +122,7 @@ export default {
@import "../../scss/_variables.scss";
// Tainacan Header
#tainacan-header{
#tainacan-header {
background-color: $header-color;
height: $header-height;
max-height: $header-height;
@ -137,24 +148,29 @@ export default {
.level-item {
display: inline-block;
margin-left: 268px;
}
.secondary-page {
}
}
&.secondary-page {
.level-item {
margin-left: 310px;
}
}
@media screen and (max-width: 769px) {
.level-left {
margin-left: 0px !important;
.level-item {
margin-left: 0px;
margin-left: 30px;
}
}
.level-right {
display: none;
}
position: relative !important;
top: 206px;
&.secondary-page {
top: 237px !important;
}
margin-bottom: 0px !important;
}

View File

@ -0,0 +1,11 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 12.8 12.8" class="grip-icon"><circle cx="1.5" cy="1.5" r="1.5" class="undefined"/><circle cx="6.4" cy="1.5" r="1.5" class="undefined"/><circle cx="11.3" cy="1.5" r="1.5" class="undefined"/><circle cx="1.5" cy="6.4" r="1.5" class="undefined"/><circle cx="6.4" cy="6.4" r="1.5" class="undefined"/><circle cx="11.3" cy="6.4" r="1.5" class="undefined"/><circle cx="1.5" cy="11.3" r="1.5" class="undefined"/><circle cx="6.4" cy="11.3" r="1.5" class="undefined"/><circle cx="11.3" cy="11.3" r="1.5" class="undefined"/></svg>
</template>
<script>
export default {
name: 'GripIcon'
}
</script>

View File

@ -0,0 +1,118 @@
<template>
<span class="help-wrapper">
<a class="help-button" @click="isOpened = !isOpened"><b-icon size="is-small" icon="help-circle-outline"></b-icon></a>
<div class="help-tooltip" :class="{ 'opened': isOpened }">
<div class="help-tooltip-header">
<h5>{{ title }}</h5><a @click="isOpened = false"><b-icon icon="close"></b-icon></a>
</div>
<div class="help-tooltip-body">
<p>{{ (message != '' && message != undefined) ? message : $i18n.get('info_no_description_provided') }}</p>
</div>
</div>
</span>
</template>
<script>
export default {
name: 'HelpButton',
data() {
return {
isOpened: false
}
},
props: {
title: '',
message: ''
}
}
</script>
<style lang="scss">
@import "../../scss/_variables.scss";
.help-wrapper {
position: relative;
}
a.help-button .icon {
i, i::before { font-size: 0.9em !important; }
color: $gray;
&:hover {
color: $primary !important;
}
}
.help-tooltip.opened {
visibility: visible;
opacity: 1;
margin-bottom: 14px;
}
.help-tooltip {
color: #000;
background-color: #e8f9f5;
border: 1px solid #338591;
border-radius: 10px;
margin: 0px 0px 0px -37px;
position: absolute;
z-index: 99999999999999;
bottom: 100%;
left: 0%;
min-width: 250px;
display: block;
visibility: hidden;
opacity: 0;
transition: opacity 0.4s ease, margin-bottom 0.3s ease;
.help-tooltip-header {
padding: 0.8em 0.8em 0.6em 0.8em;
border-bottom: 1px solid #909293;
font-size: 18px;
font-weight: bold;
h5 {
margin-right: 25px;
}
.icon {
color: #909293 !important;
right: 14px;
top: 14px;
position: absolute;
&:hover {
color: black !important;
}
}
}
.help-tooltip-body {
padding: 1.2em;
font-size: 11px;
}
&:after,
&:before {
content: "";
display: block;
position: absolute;
left: 24px;
width: 0;
height: 0;
border-style: solid;
}
&:after {
border-color: #e8f9f5 transparent transparent transparent;
border-right-width: 20px;
border-top-width: 16px;
border-left-width: 20px;
}
&:before {
border-color: #338591 transparent transparent transparent;
border-right-width: 20px;
border-top-width: 16px;
border-left-width: 20px;
bottom: -20px;
}
}
</style>

View File

@ -6,21 +6,27 @@ import Buefy from 'buefy'
import Text from '../../classes/field-types/text/Text.vue';
import Textarea from '../../classes/field-types/textarea/Textarea.vue';
import Selectbox from '../../classes/field-types/selectbox/Selectbox.vue';
import Checkbox from '../../classes/field-types/checkbox/Checkbox.vue';
import Radio from '../../classes/field-types/radio/Radio.vue';
import Numeric from '../../classes/field-types/numeric/Numeric.vue';
import Date from '../../classes/field-types/date/Date.vue';
import Relationship from '../../classes/field-types/relationship/Relationship.vue';
import Category from '../../classes/field-types/category/Category.vue';
import FormRelationship from '../../classes/field-types/relationship/FormRelationship.vue';
import FormCategory from '../../classes/field-types/category/FormCategory.vue';
import FormSelectbox from '../../classes/field-types/selectbox/FormSelectbox.vue';
import FilterCustomInterval from '../../classes/filter-types/custom-interval/CustomInterval.vue';
import FilterSelectbox from '../../classes/filter-types/selectbox/Selectbox.vue';
import FilterAutocomplete from '../../classes/filter-types/autocomplete/Autocomplete.vue';
import FilterCheckbox from '../../classes/filter-types/checkbox/Checkbox.vue';
import FilterTaginput from '../../classes/filter-types/taginput/Taginput.vue';
import TaincanFormItem from '../../classes/field-types/tainacan-form-item.vue';
import TaincanFiltersList from '../../classes/filter-types/tainacan-filters-list.vue';
// Remaining imports
import AdminPage from '../admin.vue'
import HelpButton from '../components/other/help-button.vue';
import draggable from 'vuedraggable'
import store from '../../js/store/store'
import router from './router'
@ -40,11 +46,10 @@ Vue.use(Buefy);
Vue.component('tainacan-text', Text);
Vue.component('tainacan-textarea', Textarea);
Vue.component('tainacan-selectbox', Selectbox);
Vue.component('tainacan-checkbox', Checkbox);
Vue.component('tainacan-radio', Radio);
Vue.component('tainacan-numeric', Numeric);
Vue.component('tainacan-date', Date);
Vue.component('tainacan-relationship', Relationship);
Vue.component('tainacan-category', Category);
Vue.component('tainacan-form-relationship', FormRelationship);
Vue.component('tainacan-form-category', FormCategory);
@ -52,8 +57,18 @@ Vue.component('tainacan-form-selectbox', FormSelectbox);
Vue.component('tainacan-form-item', TaincanFormItem);
Vue.component('tainacan-filters-list', TaincanFiltersList);
Vue.component('help-button', HelpButton);
Vue.component('draggable', draggable);
/* Filters */
Vue.component('tainacan-filter-custom-interval', FilterCustomInterval);
Vue.component('tainacan-filter-selectbox', FilterSelectbox);
Vue.component('tainacan-filter-autocomplete', FilterAutocomplete);
Vue.component('tainacan-filter-checkbox', FilterCheckbox);
Vue.component('tainacan-filter-taginput', FilterTaginput);
new Vue({
el: '#tainacan-admin-app',
store,

View File

@ -1,5 +1,6 @@
import Vue from 'vue';
import VueRouter from 'vue-router'
import qs from 'qs';
// Main Pages
import AdminPage from '../admin.vue'
@ -10,6 +11,7 @@ import ItemPage from '../pages/singles/item-page.vue'
import FieldsPage from '../pages/lists/fields-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 EventsPage from '../pages/lists/events-page.vue'
// Edition Form Components
@ -61,6 +63,7 @@ const routes = [
{ path: '/categories', name: 'CategoriesPage', component: CategoriesPage, meta: {title: i18nGet('title_categories_page'), icon: 'shape'} },
{ path: '/categories/new', name: 'CategoryEditionForm', component: CategoryEditionForm, meta: {title: i18nGet('title_create_category_page'), icon: 'shape'} },
{ path: '/categories/:categoryId/edit', name: 'CategoryEditionForm', component: CategoryEditionForm, meta: {title: i18nGet('title_category_edition_page'), icon: 'shape'} },
{ path: '/categories/:categoryId', name: 'CategoryPage', component: CategoryPage, meta: {title: i18nGet('title_category_page'), icon: 'shape'} },
{ path: '/events', name: 'EventsPage', component: EventsPage, meta: {title: i18nGet('title_events_page'), icon: 'bell'} },
@ -68,5 +71,14 @@ const routes = [
]
export default new VueRouter ({
routes
routes,
// set custom query resolver
parseQuery(query) {
return qs.parse(query);
},
stringifyQuery(query) {
var result = qs.stringify(query);
return result ? ('?' + result) : '';
}
})

View File

@ -22,8 +22,28 @@ I18NPlugin.install = function (Vue, options = {}) {
if (tainacan_plugin.i18n['entities_labels'][entity] == undefined)
return 'Invalid i18n entity: ' + entity;
let string = tainacan_plugin.i18n['entities_labels'][entity][key];
return (string != undefined && string != null && string != '' ) ? string : "Invalid i18n key: " + tainacan_plugin.i18n[key];
}
return (string != undefined && string != null && string != '' ) ? string : "Invalid i18n key: " + key;
},
getHelperTitle(entity, key) {
if (entity == 'categories') // Temporary hack, while we decide this terminology...
entity = 'taxonomies'
if (tainacan_plugin.i18n['helpers_label'][entity] == undefined)
return 'Invalid i18n entity: ' + entity;
if (tainacan_plugin.i18n['helpers_label'][entity][key] == undefined)
return 'Invalid i18n key: ' + key;
let string = tainacan_plugin.i18n['helpers_label'][entity][key].title;
return (string != undefined && string != null && string != '' ) ? string : "Invalid i18n helper object.";
},
getHelperMessage(entity, key) {
if (entity == 'categories') // Temporary hack, while we decide this terminology...
entity = 'taxonomies'
if (tainacan_plugin.i18n['helpers_label'][entity] == undefined)
return 'Invalid i18n entity: ' + entity;
if (tainacan_plugin.i18n['helpers_label'][entity][key] == undefined)
return 'Invalid i18n key: ' + key;
let string = tainacan_plugin.i18n['helpers_label'][entity][key].description;
return (string != undefined && string != null && string != '' ) ? string : "Invalid i18n helper object. ";
},
}
}
@ -105,7 +125,7 @@ RouterHelperPlugin.install = function (Vue, options = {}) {
return '/items/?' + qs.stringify(query);
},
getCategoriesPath(query) {
return '/items/?' + qs.stringify(query);
return '/categories/?' + qs.stringify(query);
},
getCategoryTermsPath(categoryId, query) {
return '/categoryId/' + categoryId + 'terms/?' + qs.stringify(query);

View File

@ -1,27 +1,200 @@
<template>
<div>
<div class="primary-page page-container">
<h1>Category Page</h1>
<router-link tag="button" class="button is-secondary"
:to="{ path: $routerHelper.getNewCategoryPath() }">
{{ $i18n.get('new') + ' ' + $i18n.get('category') }}
</router-link>
<div class="primary-page page-container-small">
<div class="sub-header" v-if="totalCategories > 0">
<div class="header-item">
<router-link tag="button" class="button is-secondary"
:to="{ path: $routerHelper.getNewCategoryPath() }">
{{ $i18n.get('new') + ' ' + $i18n.get('category') }}
</router-link>
</div>
</div>
<div class="columns above-subheader">
<div class="column table-container">
<categories-list
:isLoading="isLoading"
:totalCategories="totalCategories"
:page="page"
:categoriesPerPage="categoriesPerPage"
:categories="categories">
</categories-list>
<!-- Footer -->
<div class="table-footer" v-if="totalCategories > 0">
<div class="shown-items">
{{
$i18n.get('info_showing_categories') +
(categoriesPerPage * (page - 1) + 1) +
$i18n.get('info_to') +
getLastCategoryNumber() +
$i18n.get('info_of') + totalCategories + '.'
}}
</div>
<div class="items-per-page">
<b-field horizontal :label="$i18n.get('label_categories_per_page')">
<b-select
:value="categoriesPerPage"
@input="onChangeCategoriesPerPage"
:disabled="categories.length <= 0">
<option value="12">12</option>
<option value="24">24</option>
<option value="48">48</option>
<option value="96">96</option>
</b-select>
</b-field>
</div>
<div class="pagination">
<b-pagination
@change="onPageChange"
:total="totalCategories"
:current.sync="page"
order="is-centered"
size="is-small"
:per-page="categoriesPerPage">
</b-pagination>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'CategoriesPage',
data(){
return {
import CategoriesList from "../../components/lists/categories-list.vue";
import { mapActions, mapGetters } from 'vuex';
//import moment from 'moment'
export default {
name: 'CategoriesPage',
data(){
return {
isLoading: false,
totalCategories: 0,
page: 1,
categoriesPerPage: 12
}
},
components: {
CategoriesList
},
methods: {
...mapActions('category', [
'fetchCategories',
]),
...mapGetters('category', [
'getCategories'
]),
onChangeCategoriesPerPage(value) {
let prevValue = this.categoriesPerPage;
this.categoriesPerPage = value;
this.$userPrefs.set('categories_per_page', value, prevValue);
this.loadCategories();
},
onPageChange(page) {
this.page = page;
this.loadCategories();
},
loadCategories() {
this.isLoading = true;
this.fetchCategories({ 'page': this.page, 'categoriesPerPage': this.categoriesPerPage })
.then((res) => {
this.isLoading = false;
this.totalCategories = res.total;
})
.catch((error) => {
this.isLoading = false;
});
},
getLastCategoryNumber() {
let last = (Number(this.categoriesPerPage * (this.page - 1)) + Number(this.categoriesPerPage));
return last > this.totalCategories ? this.totalCategories : last;
}
},
computed: {
categories(){
return this.getCategories();
// for (let category of categories)
// category['creation'] = this.$i18n.get('info_created_by') +
// category['author_name'] + '<br>' + this.$i18n.get('info_date') +
// moment(category['creation_date'], 'YYYY-MM-DD').format('DD/MM/YYYY');
}
},
created() {
this.$userPrefs.get('categories_per_page')
.then((value) => {
this.categoriesPerPage = value;
})
.catch((error) => {
this.$userPrefs.set('categories_per_page', 12, null);
});
},
mounted(){
this.loadCategories();
}
}
}
</script>
<style scoped>
<style lang="scss" scoped>
@import '../../scss/_variables.scss';
.sub-header {
max-height: $header-height;
height: $header-height;
margin-left: -$page-small-side-padding;
margin-right: -$page-small-side-padding;
margin-top: -$page-small-top-padding;
padding-top: $page-small-top-padding;
padding-left: $page-small-side-padding;
padding-right: $page-small-side-padding;
border-bottom: 0.5px solid #ddd;
.header-item {
display: inline-block;
padding-right: 8em;
}
@media screen and (max-width: 769px) {
height: 60px;
margin-top: -0.5em;
padding-top: 0.9em;
.header-item {
padding-right: 0.5em;
}
}
}
.above-subheader {
margin-bottom: 0;
margin-top: 0;
min-height: 100%;
height: auto;
.filters-menu {
min-width: $side-menu-width;
max-width: $side-menu-width;
background-color: $primary-lighter;
margin-left: -$page-small-side-padding;
padding-left: $page-small-side-padding
}
.table-container {
margin-right: -$page-small-side-padding;
padding: 3em 2.5em;
}
@media screen and (max-width: 769px) {
.filters-menu {
display: none;
}
.table-container {
margin-right: 0;
padding: .85em 0em;
}
}
}
</style>

View File

@ -155,6 +155,16 @@ export default {
display: inline-block;
padding-right: 8em;
}
@media screen and (max-width: 769px) {
height: 60px;
margin-top: -0.5em;
padding-top: 0.9em;
.header-item {
padding-right: 0.5em;
}
}
}
.above-subheader {
@ -175,6 +185,17 @@ export default {
margin-right: -$page-small-side-padding;
padding: 3em 2.5em;
}
@media screen and (max-width: 769px) {
.filters-menu {
display: none;
}
.table-container {
margin-right: 0;
padding: .85em 0em;
}
}
}
</style>

View File

@ -1,9 +1,5 @@
<template>
<div class="primary-page page-container">
<router-link tag="button" class="button is-secondary"
:to="{ path: $routerHelper.getNewFieldPath() }">
{{ $i18n.get('new') + ' ' + $i18n.get('field') }}
</router-link>
<fields-list></fields-list>
</div>
</template>

View File

@ -1,19 +1,20 @@
<template>
<div class="primary-page page-container">
<h1>Filters Page</h1>
<router-link tag="button" class="button is-secondary"
:to="{ path: $routerHelper.getNewFilterPath() }">
{{ $i18n.get('new') + ' ' + $i18n.get('filter') }}
</router-link>
<filters-list></filters-list>
</div>
</template>
<script>
import FiltersList from '../../components/lists/filters-list.vue';
export default {
name: 'FiltersPage',
data(){
return {
}
},
components: {
FiltersList
}
}
</script>

View File

@ -44,10 +44,10 @@
</items-list>
<!-- Footer -->
<div class="table-footer">
<div class="shown-items">
<div class="shown-items">
{{
$i18n.get('info_showing_items') +
(itemsPerPage*(page - 1) + 1) +
$i18n.get('info_showing_items') +
getFirstItem() +
$i18n.get('info_to') +
getLastItemNumber() +
$i18n.get('info_of') + totalItems + '.'
@ -95,12 +95,14 @@ export default {
isRepositoryLevel: false,
tableFields: [],
prefTableFields: [],
totalItems: 0,
page: 1,
itemsPerPage: 12,
isLoading: false
}
},
watch: {
page( value ){
this.page = ( value > 0 ) ? value : 1;
}
},
components: {
ItemsList,
FiltersItemsList
@ -114,18 +116,28 @@ export default {
'getItems',
'getFields'
]),
...mapGetters('search', [
'getPostQuery',
'getTotalItems',
'getPage',
'getItemsPerPage'
]),
...mapActions('fields', [
'fetchFields'
]),
...mapGetters('fields', [
'getFields'
]),
...mapActions('search', [
'set_postquery',
'setPage',
'setItemsPerPage',
'search_by_collection'
]),
onChangeTableFields(field) {
let prevValue = this.prefTableFields;
let index = this.prefTableFields.findIndex(alteredField => alteredField.slug === field.slug);
if (index >= 0) {
console.log(prevValue[index].visible);
console.log(this.prefTableFields[index].visible);
//prevValue[index].visible = this.prefTableFields[index].visible ? false : true;
}
@ -141,21 +153,43 @@ export default {
//this.$userPrefs.set('table_columns_' + this.collectionId, this.prefTableFields, prevValue);
},
onChangeItemsPerPage(value) {
if( this.itemsPerPage == value){
return false;
}
let prevValue = this.itemsPerPage;
this.itemsPerPage = value;
this.setItemsPerPage( value );
this.$userPrefs.set('items_per_page', value, prevValue);
this.alterQueryString();
this.loadItems();
},
onPageChange(page) {
this.page = page;
if(page == 0)
return;
this.setPage( page );
this.alterQueryString();
this.loadItems();
},
loadItems() {
this.isLoading = true;
this.fetchItems({ 'collectionId': this.collectionId, 'page': this.page, 'itemsPerPage': this.itemsPerPage })
.then((res) => {
let promisse = null;
if( Object.keys( this.$route.query ).length > 0 ) {
this.set_postquery(this.$route.query);
if (this.$route.params && this.$route.params.collectionId) {
promisse = this.search_by_collection(this.$route.params.collectionId);
}
}
if(!promisse){
promisse = this.fetchItems({ 'collectionId': this.collectionId, 'page': this.page, 'itemsPerPage': this.itemsPerPage });
this.alterQueryString();
}
promisse.then((res) => {
this.isLoading = false;
this.totalItems = res.total;
})
.catch((error) => {
this.isLoading = false;
@ -165,11 +199,30 @@ export default {
let last = (Number(this.itemsPerPage*(this.page - 1)) + Number(this.itemsPerPage));
return last > this.totalItems ? this.totalItems : last;
},
getFirstItem(){
if( this.totalItems == 0 )
return 0;
return ( this.itemsPerPage * ( this.page - 1 ) + 1)
},
alterQueryString(){
this.$router.push({ query: {} });
this.$router.push({ query: this.getPostQuery() });
}
},
computed: {
items(){
return this.getItems();
},
totalItems(){
return this.getTotalItems();
},
page(){
return this.getPage();
},
itemsPerPage(){
return this.getItemsPerPage();
}
},
created() {
@ -188,13 +241,14 @@ export default {
this.loadItems();
this.fetchFields({ collectionId: this.collectionId, isRepositoryLevel: false }).then((res) => {
let rawFields = res;
this.tableFields.push({ label: this.$i18n.get('label_thumbnail'), field: 'featured_image', slug: 'featured_image', visible: true });
for (let field of rawFields) {
this.tableFields.push(
{ label: field.name, field: field.description, slug: field.slug, visible: true }
);
}
this.tableFields.push({ label: this.$i18n.get('label_actions'), field: 'row_actions', slug: 'actions', visible: true });
this.prefTableFields = this.tableFields;
// this.$userPrefs.get('table_columns_' + this.collectionId)
// .then((value) => {
@ -229,6 +283,16 @@ export default {
display: inline-block;
padding-right: 8em;
}
@media screen and (max-width: 769px) {
height: 60px;
margin-top: -0.5em;
padding-top: 0.90em;
.header-item {
padding-right: 0.5em;
}
}
}
.above-subheader {
@ -242,13 +306,28 @@ export default {
max-width: $side-menu-width;
background-color: $primary-lighter;
margin-left: -$page-small-side-padding;
padding-left: $page-small-side-padding
padding: $page-small-side-padding;
.label {
font-weight: normal;
font-size: 0.85em;
}
}
.table-container {
margin-right: -$page-small-side-padding;
padding: 3em 2.5em;
}
@media screen and (max-width: 769px) {
.filters-menu {
display: none;
}
.table-container {
margin-right: 0;
padding: .85em 0em;
}
}
}

View File

@ -0,0 +1,59 @@
<template>
<div class="columns is-fullheight">
<div class="page-container primary-page">
<div class="card">
<div class="card-content">
<p class="title">
{{ category.name }}
</p>
<p class="subtitle">
{{ category.description }}
</p>
</div>
<footer class="card-footer">
<router-link
class="card-footer-item"
:to="{ path: $routerHelper.getCategoryEditPath(categoryId)}">
{{ $i18n.get('edit') + ' ' + $i18n.get('category') }}
</router-link>
</footer>
</div>
</div>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex';
export default {
name: 'CategoryPage',
data(){
return {
categoryId: Number,
}
},
methods: {
...mapActions('category', [
'fetchCategory'
]),
...mapGetters('category', [
'getCategory'
])
},
computed: {
category(){
return this.getCategory();
}
},
created(){
this.categoryId = parseInt(this.$route.params.categoryId);
this.fetchCategory(this.categoryId);
}
}
</script>
<style scoped>
</style>

View File

@ -15,11 +15,15 @@ $primary-lighter: lighten($primary-light, 15%);
$primary-dark: #55A0AF;
$primary-darker: darken($primary-dark, 5%);
$success: #25a189;
$success-invert: findColorInvert($success);
$separator-color: #2a6e77;
$header-color: #ececec;
$tainacan-input-color: #f0f0f0;
$draggable-border-color: #d8d8d8;
$gray: #898d8f;
$gray: #b1b1b1;
$gray-invert: findColorInvert($gray);
$gray-light: #898d8f;
$gray-light-invert: findColorInvert($gray-light);

View File

@ -54,6 +54,7 @@ html {
padding: $page-top-padding $page-side-padding;
height: 100%;
overflow-y: auto;
overflow-x: hidden;
@media screen and (max-width: 769px) {
padding: $page-mobile-top-padding $page-mobile-side-padding;
@ -76,16 +77,56 @@ html {
// Input components used in forms are gray in Tainacan
.tainacan-form {
color: black;
.form-submit {
justify-content: space-between !important;
padding: 1em 1.2em 0.4em 1.2em;
margin-bottom: 0px;
.button {
padding: 2px 30px !important;
}
.button.is-outlined {
color: $tertiary;
}
}
.label {
font-weight: normal;
font-size: 14px;
display: inline-block;
}
.required-field-asterisk {
color: $gray;
&.is-danger {
color: $danger;
}
}
.input, .textarea {
font-size: 14px;
border: none;
border-radius: 1px !important;
background-color: $tainacan-input-color;
color: black;
box-shadow: none;
&.is-danger {
background-color: #ece0e0;
}
}
.radio {
margin-bottom: 0.2em;
}
.checkbox {
margin-bottom: 0.2em;
}
.control-label { // The value part in checkbox, radio and switches
color: black;
padding-left: 0.8em;
font-size: 12px;
}
.select {
padding-top: 0px !important;
select {
font-size: 14px;
border: none;
border-radius: 1px !important;
font-weight: normal;
@ -163,6 +204,62 @@ html {
}
}
}
.switch {
input[type="checkbox"] + .check {
background-color: transparent;
border: 1.6px solid $gray;
&::before {
background-color: $gray;
box-shadow: none;
}
}
&:hover input[type="checkbox"]:checked + .check {
background-color: $primary-light;
}
input[type="checkbox"]:checked + .check {
border: 1.6px solid $secondary;
background-color: transparent;
&::before {
background-color: $secondary;
transform: translate3d(83%, 0, 0);
}
}
&:hover input[type="checkbox"] + .check {
background-color: $tainacan-input-color;
}
&:focus input[type="checkbox"] + .check,
&:focus input[type="checkbox"]:checked + .check {
box-shadow: none;
}
&.is-small {
font-size: 9px;
input[type="checkbox"] + .check {
border: 1.5px solid $gray;
&::before {
width: 1.05em;
height: 1.05em;
}
}
input[type="checkbox"]:checked + .check {
border: 1.5px solid $secondary;
&::before {
transform: translate3d(93%, 0, 0);
}
}
}
}
// Tables
.table {
tbody {
td { border-bottom: 0px solid $gray-light !important; }

View File

@ -1,146 +1,179 @@
<?php
<?php
return [
// Tainacan common terms
'repository' => __('Repository', 'tainacan'),
'collections' => __('Collections', 'tainacan'),
'items' => __('Items', 'tainacan'),
'fields' => __('Fields', 'tainacan'),
'filters' => __('Filters', 'tainacan'),
'categories' => __('Categories', 'tainacan'),
'events' => __('Events', 'tainacan'),
'collection' => __('Collection', 'tainacan'),
'item' => __('Item', 'tainacan'),
'field' => __('Field', 'tainacan'),
'filter' => __('Filter', 'tainacan'),
'category' => __('Category', 'tainacan'),
'event' => __('Event', 'tainacan'),
// Actions
'edit' => __('Edit', 'tainacan'),
'new' => __('New', 'tainacan'),
'import' => __('Import', 'tainacan'),
'export' => __('Export', 'tainacan'),
'cancel' => __('Cancel', 'tainacan'),
'save' => __('Save', 'tainacan'),
'see' => __('See', 'tainacan'),
'search' => __('Search', 'tainacan'),
'advanced_search' => __('Advanced Search', 'tainacan'),
// Tainacan common terms
'repository' => __( 'Repository', 'tainacan' ),
'collections' => __( 'Collections', 'tainacan' ),
'items' => __( 'Items', 'tainacan' ),
'fields' => __( 'Fields', 'tainacan' ),
'filters' => __( 'Filters', 'tainacan' ),
'categories' => __( 'Categories', 'tainacan' ),
'events' => __( 'Events', 'tainacan' ),
'collection' => __( 'Collection', 'tainacan' ),
'item' => __( 'Item', 'tainacan' ),
'field' => __( 'Field', 'tainacan' ),
'filter' => __( 'Filter', 'tainacan' ),
'category' => __( 'Category', 'tainacan' ),
'event' => __( 'Event', 'tainacan' ),
// Wordpress Status
'publish' => __('Publish', 'tainacan'),
'draft' => __('Draft', 'tainacan'),
'private' => __('Private', 'tainacan'),
'trash' => __('Trash', 'tainacan'),
'auto-draft' => __('Automatic Draft', 'tainacan'),
// Actions
'edit' => __( 'Edit', 'tainacan' ),
'new' => __( 'New', 'tainacan' ),
'import' => __( 'Import', 'tainacan' ),
'export' => __( 'Export', 'tainacan' ),
'cancel' => __( 'Cancel', 'tainacan' ),
'save' => __( 'Save', 'tainacan' ),
'next' => __( 'Next', 'tainacan' ),
'see' => __( 'See', 'tainacan' ),
'search' => __( 'Search', 'tainacan' ),
'advanced_search' => __( 'Advanced Search', 'tainacan' ),
'continue' => __('Continue', 'tainacan'),
// Wordpress Status
'publish' => __( 'Publish', 'tainacan' ),
'draft' => __( 'Draft', 'tainacan' ),
'private' => __( 'Private', 'tainacan' ),
'trash' => __( 'Trash', 'tainacan' ),
'auto-draft' => __( 'Automatic Draft', 'tainacan' ),
'publish_visibility' => __( 'Visible to everyone', 'tainacan' ),
'private_visibility' => __( 'Visible only for editors', 'tainacan' ),
// Page Titles (used mainly on Router)
'title_collections_page' => __( 'Collections Page', 'tainacan' ),
'title_items_page' => __( 'Items Page', 'tainacan' ),
'title_fields_page' => __( 'Fields Page', 'tainacan' ),
'title_filters_page' => __( 'Filters Page', 'tainacan' ),
'title_categories_page' => __( 'Categories Page', 'tainacan' ),
'title_terms_page' => __( 'Terms Page', 'tainacan' ),
'title_events_page' => __( 'Events Page', 'tainacan' ),
'title_collection_page' => __( 'Collection Page', 'tainacan' ),
'title_item_page' => __( 'Item Page', 'tainacan' ),
'title_field_page' => __( 'Field Page', 'tainacan' ),
// Page Titles (used mainly on Router)
'title_collections_page' => __('Collections Page', 'tainacan'),
'title_items_page' => __('Items Page', 'tainacan'),
'title_fields_page' => __('Fields Page', 'tainacan'),
'title_filters_page' => __('Filters Page', 'tainacan'),
'title_categories_page' => __('Categories Page', 'tainacan'),
'title_terms_page' => __('Terms Page', 'tainacan'),
'title_events_page' => __('Events Page', 'tainacan'),
'title_collection_page' => __('Collection Page', 'tainacan'),
'title_item_page' => __('Item Page', 'tainacan'),
'title_field_page' => __('Field Page', 'tainacan'),
/* translators: alkdjklasdj laksjd klsadj */
'title_filter_page' => __('Filter Page', 'tainacan'),
'title_category_page' => __('Category Page', 'tainacan'),
'title_term_page' => __('Term Page', 'tainacan'),
'title_event_page' => __('Event Page', 'tainacan'),
'title_create_collection' => __('Collection Creation Page', 'tainacan'),
'title_create_category' => __('Category Creation Page', 'tainacan'),
'title_create_item' => __('Item Creation Page', 'tainacan'),
'title_create_filter' => __('Filter Creation Page', 'tainacan'),
'title_collection_edition' => __('Collection Edition Page', 'tainacan'),
'title_item_edition' => __('Item Edition Page', 'tainacan'),
'title_category_edition' => __('Category Edition Page', 'tainacan'),
'title_filter_edition' => __('Filter Edition Page', 'tainacan'),
'title_collection_fields_edition' => __('Collection Fields Edition Page', 'tainacan'),
'title_collection_page' => __( 'Collection Page', 'tainacan' ),
'title_filter_page' => __( 'Filter Page', 'tainacan' ),
'title_category_page' => __( 'Category Page', 'tainacan' ),
'title_term_page' => __( 'Term Page', 'tainacan' ),
'title_event_page' => __( 'Event Page', 'tainacan' ),
'title_create_collection' => __( 'Collection Creation Page', 'tainacan' ),
'title_create_category_page' => __( 'Category Creation Page', 'tainacan' ),
'title_create_item' => __( 'Item Creation Page', 'tainacan' ),
'title_create_filter' => __( 'Filter Creation Page', 'tainacan' ),
'title_collection_edition' => __( 'Collection Edition Page', 'tainacan' ),
'title_item_edition' => __( 'Item Edition Page', 'tainacan' ),
'title_category_edition_page' => __( 'Category Edition Page', 'tainacan' ),
'title_filter_edition' => __( 'Filter Edition Page', 'tainacan' ),
'title_collection_fields_edition' => __( 'Collection Fields Edition Page', 'tainacan' ),
// Labels (used mainly on Aria Labels and Inputs)
'label_menu' => __('Menu', 'tainacan'),
'label_main_menu' => __('Main Menu', 'tainacan'),
'label_collection_menu' => __('Collection Menu', 'tainacan'),
'label_title' => __('Title', 'tainacan'),
'label_actions' => __('Actions', 'tainacan'),
'label_name' => __('Name', 'tainacan'),
'label_description' => __('Description', 'tainacan'),
'label_status' => __('Status', 'tainacan'),
'label_image' => __('Image', 'tainacan'),
'label_button_view' => __('Button View', 'tainacan'),
'label_button_edit' => __('Button Edit', 'tainacan'),
'label_button_delete' => __('Button Delete', 'tainacan'),
'label_collections_per_page' => __('Collections per Page:', 'tainacan'),
'label_items_per_page' => __('Items per Page:', 'tainacan'),
'label_active_fields' => __('Active Fields', 'tainacan'),
'label_available_fields' => __('Available Fields', 'tainacan'),
'label_available_field_types' => __('Available Field Types', 'tainacan'),
'label_active_filters' => __('Active Filters', 'tainacan'),
'label_filter_type' => __('Filter Type', 'tainacan'),
'label_available_filters' => __('Available Filters', 'tainacan'),
'label_available_filter_types' => __('Available Filter Types', 'tainacan'),
'label_per_page' => __('per Page', 'tainacan'),
'label_table_fields' => __('Fields on table', 'tainacan'),
'label_required' => __('Required', 'tainacan'),
'label_allow_multiple' => __('Allow multiple values', 'tainacan'),
'label_default_value' => __('Default value', 'tainacan'),
'label_unique_value' => __('Unique value', 'tainacan'),
'label_yes' => __('Yes', 'tainacan'),
'label_no' => __('No', 'tainacan'),
'label_collection_related' => __('Collection Related', 'tainacan'),
'label_fields_for_search' => __('Fields for search', 'tainacan'),
'label_allow_repeated_items' => __('Allow repeated items', 'tainacan'),
'label_select_category' => __('Select category', 'tainacan'),
'label_select_category_input_type' => __('Input type', 'tainacan'),
'label_category_allow_new_terms' => __('Allow new terms', 'tainacan'),
'label_selectbox_init' => __('Select', 'tainacan'),
'label_options' => __('Insert options', 'tainacan'),
'label_attachments' => __('Attachments', 'tainacan'),
'label_enabled' => __('Enabled', 'tainacan'),
'label_disabled' => __('Disabled', 'tainacan'),
'label_creation' => __('Creation', 'tainacan'),
'label_collection_items' => __('Collection Items', 'tainacan'),
'label_collection_fields' => __('Collection Fields', 'tainacan'),
'label_collection_filters' => __('Collection Filters', 'tainacan'),
// Labels (used mainly on Aria Labels and Inputs)
'label_menu' => __( 'Menu', 'tainacan' ),
'label_main_menu' => __( 'Main Menu', 'tainacan' ),
'label_collection_menu' => __( 'Collection Menu', 'tainacan' ),
'label_title' => __( 'Title', 'tainacan' ),
'label_actions' => __( 'Actions', 'tainacan' ),
'label_name' => __( 'Name', 'tainacan' ),
'label_description' => __( 'Description', 'tainacan' ),
'label_status' => __( 'Status', 'tainacan' ),
'label_slug' => __( 'Slug', 'tainacan' ),
'label_image' => __( 'Image', 'tainacan' ),
'label_thumbnail' => __( 'Thumbnail', 'tainacan' ),
'label_button_view' => __( 'Button View', 'tainacan' ),
'label_button_edit' => __( 'Button Edit', 'tainacan' ),
'label_button_delete' => __( 'Button Delete', 'tainacan' ),
'label_button_edit_thumb' => __( 'Button Edit 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_items_per_page' => __( 'Items per Page:', 'tainacan' ),
'label_active_fields' => __( 'Active Fields', 'tainacan' ),
'label_available_fields' => __( 'Available Fields', 'tainacan' ),
'label_available_field_types' => __( 'Available Field Types', 'tainacan' ),
'label_active_filters' => __( 'Active Filters', 'tainacan' ),
'label_filter_type' => __( 'Filter Type', 'tainacan' ),
'label_available_filters' => __( 'Available Filters', 'tainacan' ),
'label_available_filter_types' => __( 'Available Filter Types', 'tainacan' ),
'label_per_page' => __( 'per Page', 'tainacan' ),
'label_table_fields' => __( 'Fields on table', 'tainacan' ),
'label_required' => __( 'Required', 'tainacan' ),
'label_allow_multiple' => __( 'Allow multiple values', 'tainacan' ),
'label_default_value' => __( 'Default value', 'tainacan' ),
'label_unique_value' => __( 'Unique value', 'tainacan' ),
'label_yes' => __( 'Yes', 'tainacan' ),
'label_no' => __( 'No', 'tainacan' ),
'label_collection_related' => __( 'Collection Related', 'tainacan' ),
'label_fields_for_search' => __( 'Fields for search', 'tainacan' ),
'label_allow_repeated_items' => __( 'Allow repeated items', 'tainacan' ),
'label_select_category' => __( 'Select category', 'tainacan' ),
'label_select_category_input_type' => __( 'Input type', 'tainacan' ),
'label_category_allow_new_terms' => __( 'Allow new terms', 'tainacan' ),
'label_selectbox_init' => __( 'Select', 'tainacan' ),
'label_options' => __( 'Insert options', 'tainacan' ),
'label_attachments' => __( 'Attachments', 'tainacan' ),
'label_enabled' => __( 'Enabled', 'tainacan' ),
'label_disabled' => __( 'Disabled', 'tainacan' ),
'label_creation' => __( 'Creation', 'tainacan' ),
'label_collection_items' => __( 'Collection Items', 'tainacan' ),
'label_collection_fields' => __( 'Collection Fields', 'tainacan' ),
'label_collection_filters' => __( 'Collection Filters', 'tainacan' ),
'label_parent_term' => __( 'Parent Term', 'tainacan' ),
'label_add_new_term' => __( 'Add New Term', 'tainacan' ),
// Instructions. More complex sentences to guide user and placeholders
'instruction_dragndrop_fields_collection' => __('Drag and drop Fields here to add them to Collection.', 'tainacan'),
'instruction_delete_selected_collections' => __('Delete selected collections', 'tainacan'),
'instruction_delete_selected_items' => __('Delete selected items', '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'),
// Instructions. More complex sentences to guide user and placeholders
'instruction_dragndrop_fields_collection' => __( 'Drag and drop Fields here to Collection.', 'tainacan' ),
'instruction_dragndrop_filters_collection' => __( 'Drag and drop Fields to create Filters on Collection.', 'tainacan' ),
'instruction_dragndrop_fields_repository' => __( 'Drag and drop Fields here to Repository.', 'tainacan' ),
'instruction_dragndrop_filters_repository' => __( 'Drag and drop Fields to create Filters on Repository.', 'tainacan' ),
'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_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' ),
// Info. Other feedback to user.
'info_no_collection_created' => __('No collection was created in this repository.', 'tainacan'),
'info_no_item_created' => __('No item was created in this collection.', 'tainacan'),
'info_error_deleting_collection' => __('Error on deleting collection.', 'tainacan'),
'info_collection_deleted' => __('Collection deleted.', 'tainacan'),
'info_item_deleted' => __('Item deleted.', 'tainacan'),
'info_warning_collection_delete' => __('Do you really want to delete this collection?', 'tainacan'),
'info_warning_item_delete' => __('Do you really want to delete this item?', 'tainacan'),
'info_warning_selected_collections_delete' => __('Do you really want to delete the selected collections?', 'tainacan'),
'info_warning_selected_items_delete' => __('Do you really want to delete the selected items?', 'tainacan'),
'info_warning_collection_related' => __('The field Collection related is required', 'tainacan'),
'info_warning_no_fields_found' => __('No fields found in this collection', 'tainacan'),
'info_showing_items' => __('Showing items ', 'tainacan'),
'info_showing_collections' => __('Showing collections ', 'tainacan'),
'info_to' => __(' to ', 'tainacan'),
'info_of' => __(' of ', 'tainacan'),
'info_created_by' => __('Created by: ', 'tainacan'),
'info_date' => __('Date: ', 'tainacan'),
// Info. Other feedback to user.
'info_name_is_required' => __( 'Name is required.', 'tainacan' ),
'info_no_collection_created' => __( 'No collection was created in this repository.', 'tainacan' ),
'info_no_category_created' => __( 'No category was created in this repository.', 'tainacan' ),
'info_no_item_created' => __( 'No item was created in this collection.', 'tainacan' ),
'info_error_deleting_collection' => __( 'Error on deleting collection.', 'tainacan' ),
'info_collection_deleted' => __( 'Collection deleted.', 'tainacan' ),
'info_item_deleted' => __( 'Item deleted.', 'tainacan' ),
'info_warning_collection_delete' => __( 'Do you really want to delete this collection?', 'tainacan' ),
'info_warning_item_delete' => __( 'Do you really want to delete this item?', 'tainacan' ),
'info_warning_selected_collections_delete' => __( 'Do you really want to delete the selected collections?', 'tainacan' ),
'info_warning_selected_items_delete' => __( 'Do you really want to delete the selected items?', 'tainacan' ),
'info_warning_collection_related' => __( 'The field Collection related is required', 'tainacan' ),
'info_warning_no_fields_found' => __( 'No fields found in this collection', 'tainacan' ),
'info_showing_items' => __( 'Showing items ', 'tainacan' ),
'info_showing_collections' => __( 'Showing collections ', 'tainacan' ),
'info_showing_categories' => __( 'Showing categories ', 'tainacan' ),
'info_to' => __( ' to ', 'tainacan' ),
'info_of' => __( ' of ', 'tainacan' ),
'info_created_by' => __( 'Created by: ', 'tainacan' ),
'info_date' => __( 'Date: ', 'tainacan' ),
'info_not_saved' => __( 'Not saved ', 'tainacan' ),
'info_warning_fields_not_saved' => __('Are you sure? There are fields 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'),
// Tainacan Field Types
'tainacan-text' => __('Text', 'tainacan'),
'tainacan-textarea' => __('Text area', 'tainacan'),
'tainacan-date' => __('Date', 'tainacan'),
'tainacan-numeric' => __('Numeric', 'tainacan'),
'tainacan-selectbox' => __('Select box', 'tainacan'),
'tainacan-relationship' => __('Relationship', 'tainacan'),
'tainacan-category' => __('Category', 'tainacan'),
// Tainacan Field Types
'tainacan-text' => __( 'Text', 'tainacan' ),
'tainacan-textarea' => __( 'Text area', 'tainacan' ),
'tainacan-date' => __( 'Date', 'tainacan' ),
'tainacan-numeric' => __( 'Numeric', 'tainacan' ),
'tainacan-selectbox' => __( 'Select box', 'tainacan' ),
'tainacan-relationship' => __( 'Relationship', 'tainacan' ),
'tainacan-category' => __( 'Category', 'tainacan' ),
// Tainacan Filter Types
'tainacan-filter-custom-interval' => __( 'Custom Interval', 'tainacan' ),
'tainacan-filter-selectbox' => __( 'Select Box', 'tainacan' ),
'tainacan-filter-autocomplete' => __( 'Autocomplete', 'tainacan' ),
'tainacan-filter-taginput' => __( 'Tag Input', 'tainacan' ),
'tainacan-filter-checkbox' => __( 'Check Box', 'tainacan' ),
'tainacan-filter-category-taginput' => __( 'Category Tag Input', 'tainacan' ),
'tainacan-filter-category-checkbox' => __( 'Category Check Box', 'tainacan' ),
'tainacan-filter-category-selectbox' => __( 'Category Select Box', 'tainacan' )
]
?>
?>

View File

@ -189,7 +189,7 @@ class TAINACAN_REST_Controller extends WP_REST_Controller {
}
$user_id = $user->ID;
$metas = $field_name === 'meta' ? $meta : '';
$metas = $field_name === 'meta' ? $meta : [];
$map = [
'metakey',

View File

@ -28,7 +28,7 @@ class TAINACAN_REST_Collections_Controller extends TAINACAN_REST_Controller {
* Initialize objects after post_type register
*/
public function init_objects() {
$this->collections_repository = new Repositories\Collections();
$this->collections_repository = Repositories\Collections::getInstance();
$this->collection = new Entities\Collection();
}
@ -410,17 +410,6 @@ class TAINACAN_REST_Collections_Controller extends TAINACAN_REST_Controller {
return $endpoint_args;
}
/**
* @return array|mixed|void
*/
public function get_item_schema() {
$schema['collection']['type'] = 'array/object';
$schema['collection']['description'] = __('Passed in body.');
$schema['collection']['properties'] = $this->collections_repository->get_map();
return $schema;
}
/**
*
* Return the queries supported when getting a collection of objects

View File

@ -18,7 +18,41 @@ class TAINACAN_REST_Field_Types_Controller extends TAINACAN_REST_Controller {
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'get_items'),
'permission_callback' => array($this, 'get_items_permissions_check')
'permission_callback' => array($this, 'get_items_permissions_check'),
'args' => [
'field-type' => [
'description' => __('The structure of objects returned.'),
'items' => [
'errors' => [
'type' => 'string'
],
'component' => [
'type' => 'string'
],
'primitive_type' => [
'type' => 'array/string',
'items' => [
'type' => 'string'
]
],
'related_mapped_prop' => [
'type' => 'boolean'
],
'options' => [
'type' => 'array'
],
'className' => [
'type' => 'string'
],
'core' => [
'type' => 'boolean'
],
'form_component' => [
'type' => 'boolean'
]
]
]
]
)
)
);
@ -46,7 +80,7 @@ class TAINACAN_REST_Field_Types_Controller extends TAINACAN_REST_Controller {
* @return WP_Error|WP_REST_Response
*/
public function get_items( $request ) {
global $Tainacan_Fields;
$Tainacan_Fields = \Tainacan\Repositories\Fields::getInstance();
$field_types = $Tainacan_Fields->fetch_field_types('NAME');

View File

@ -23,10 +23,10 @@ class TAINACAN_REST_Fields_Controller extends TAINACAN_REST_Controller {
* @throws Exception
*/
public function init_objects() {
$this->field_repository = new Repositories\Fields();
$this->item_metadata_repository = new Repositories\Item_Metadata();
$this->item_repository = new Repositories\Items();
$this->collection_repository = new Repositories\Collections();
$this->field_repository = Repositories\Fields::getInstance();
$this->item_metadata_repository = Repositories\Item_Metadata::getInstance();
$this->item_repository = Repositories\Items::getInstance();
$this->collection_repository = Repositories\Collections::getInstance();
}
/**
@ -37,6 +37,8 @@ class TAINACAN_REST_Fields_Controller extends TAINACAN_REST_Controller {
* id body of requisition
*
* Both of GETs return the field of matched objects
*
* @throws Exception
*/
public function register_routes() {
register_rest_route($this->namespace, '/collection/(?P<collection_id>[\d]+)/' . $this->rest_base . '/(?P<field_id>[\d]+)',
@ -44,18 +46,20 @@ class TAINACAN_REST_Fields_Controller extends TAINACAN_REST_Controller {
array(
'methods' => WP_REST_Server::EDITABLE,
'callback' => array($this, 'update_item'),
'permission_callback' => array($this, 'update_item_permissions_check')
'permission_callback' => array($this, 'update_item_permissions_check'),
'args' => $this->get_endpoint_args_for_item_schema(WP_REST_Server::EDITABLE)
),
// ENDPOINT X. THIS ENDPOINT DO THE SAME THING OF ENDPOINT Z. I hope in a brief future it function changes.
array(
'methods' => WP_REST_Server::DELETABLE,
'callback' => array($this, 'delete_item'),
'permission_callback' => array($this, 'delete_item_permissions_check')
'permission_callback' => array($this, 'delete_item_permissions_check'),
),
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'get_item'),
'permission_callback' => array($this, 'get_item_permissions_check')
'permission_callback' => array($this, 'get_item_permissions_check'),
'args' => $this->get_endpoint_args_for_item_schema(WP_REST_Server::READABLE),
),
)
);
@ -65,12 +69,13 @@ class TAINACAN_REST_Fields_Controller extends TAINACAN_REST_Controller {
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'get_items'),
'permission_callback' => array($this, 'get_items_permissions_check'),
//'args' => $this->get_collection_params(),
'args' => $this->get_collection_params(),
),
array(
'methods' => WP_REST_Server::CREATABLE,
'callback' => array($this, 'create_item'),
'permission_callback' => array($this, 'create_item_permissions_check')
'permission_callback' => array($this, 'create_item_permissions_check'),
'args' => $this->get_endpoint_args_for_item_schema(WP_REST_Server::CREATABLE),
),
)
);
@ -79,12 +84,14 @@ class TAINACAN_REST_Fields_Controller extends TAINACAN_REST_Controller {
array(
'methods' => WP_REST_Server::CREATABLE,
'callback' => array($this, 'create_item'),
'permission_callback' => array($this, 'create_item_permissions_check')
'permission_callback' => array($this, 'create_item_permissions_check'),
'args' => $this->get_endpoint_args_for_item_schema(WP_REST_Server::CREATABLE),
),
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'get_items'),
'permission_callback' => array($this, 'get_items_permissions_check')
'permission_callback' => array($this, 'get_items_permissions_check'),
'args' => $this->get_collection_params(),
)
)
);
@ -99,7 +106,8 @@ class TAINACAN_REST_Fields_Controller extends TAINACAN_REST_Controller {
array(
'methods' => WP_REST_Server::EDITABLE,
'callback' => array($this, 'update_item'),
'permission_callback' => array($this, 'update_item_permissions_check')
'permission_callback' => array($this, 'update_item_permissions_check'),
'args' => $this->get_endpoint_args_for_item_schema(WP_REST_Server::EDITABLE)
),
)
);
@ -191,28 +199,9 @@ class TAINACAN_REST_Fields_Controller extends TAINACAN_REST_Controller {
if($prepared->validate()) {
$field = $this->field_repository->insert( $prepared);
$items = $this->item_repository->fetch([], $collection_id, 'WP_Query');
$response = $this->prepare_item_for_response($field, $request);
$field_added = '';
if($items->have_posts()){
while ($items->have_posts()){
$items->the_post();
$item = new Entities\Item($items->post);
$item_meta = new Entities\Item_Metadata_Entity($item, $field);
$field_added = $this->item_metadata_repository->insert($item_meta);
}
$response = $this->prepare_item_for_response($field_added->get_field(), $request);
return new WP_REST_Response($response, 201);
}
else {
$response = $this->prepare_item_for_response($prepared, $request);
return new WP_REST_Response($response, 201);
}
return new WP_REST_Response($response, 201);
} else {
return new WP_REST_Response([
'error_message' => __('One or more values are invalid.', 'tainacan'),
@ -236,8 +225,8 @@ class TAINACAN_REST_Fields_Controller extends TAINACAN_REST_Controller {
} else {
return new WP_REST_Response([
'error_message' => __('One or more values are invalid.', 'tainacan'),
'errors' => $this->field->get_errors(),
'field' => $this->prepare_item_for_response($this->field, $request),
'errors' => $prepared->get_errors(),
'field' => $this->prepare_item_for_response($prepared, $request),
], 400);
}
@ -280,8 +269,8 @@ class TAINACAN_REST_Fields_Controller extends TAINACAN_REST_Controller {
$item->get_field_type_object()->form();
$form = ob_get_clean();
$item_arr['edit_form'] = $form;
$item_arr['field_type_object'] = $item->get_field_type_object();
$item_arr['disabled'] = $item->get_disabled_for_collection();
$item_arr['field_type_object'] = $item->get_field_type_object()->__toArray();
$item_arr['enabled'] = $item->get_enabled_for_collection();
}
return $item_arr;
@ -350,13 +339,13 @@ class TAINACAN_REST_Fields_Controller extends TAINACAN_REST_Controller {
* @return WP_Error|WP_REST_Response
*/
public function delete_item( $request ) {
$field_id = $request['field_id'];
$field_id = $request['field_id'];
$field_trashed = $this->field_repository->delete($field_id);
$field_trashed = $this->field_repository->delete($field_id);
$prepared = $this->prepare_item_for_response($field_trashed, $request);
$prepared = $this->prepare_item_for_response($field_trashed, $request);
return new WP_REST_Response($prepared, 200);
return new WP_REST_Response($prepared, 200);
}
/**
@ -383,7 +372,7 @@ class TAINACAN_REST_Fields_Controller extends TAINACAN_REST_Controller {
* @return WP_Error|WP_REST_Response
*/
public function update_item( $request ) {
$collection_id = $request['collection_id'];
$collection_id = is_numeric($request['collection_id']) ? $request['collection_id'] : null;
$body = json_decode($request->get_body(), true);
if(!empty($body)){
@ -465,6 +454,63 @@ class TAINACAN_REST_Fields_Controller extends TAINACAN_REST_Controller {
return $this->field_repository->can_edit(new Entities\Field());
}
/**
* @param null $object_name
*
* @return array|void
*/
public function get_collection_params( $object_name = null ) {
$query_params['context']['default'] = 'view';
$query_params = array_merge($query_params, parent::get_collection_params('field'));
$query_params['name'] = array(
'description' => __('Limit result set to field with specific name.'),
'type' => 'string',
);
$query_params = array_merge($query_params, parent::get_meta_queries_params());
return $query_params;
}
/**
* @param null $method
*
* @return array
* @throws Exception
*/
public function get_endpoint_args_for_item_schema( $method = null ) {
$endpoint_args = [];
if($method === WP_REST_Server::READABLE) {
$endpoint_args['fetch'] = [
'type' => 'string',
'description' => __('Fetch all values of a field from a collection in all it collection items'),
'enum' => ['all_field_values']
];
$endpoint_args['context'] = array(
'type' => 'string',
'default' => 'view',
'items' => array( 'view, edit' )
);
} elseif ($method === WP_REST_Server::CREATABLE || $method === WP_REST_Server::EDITABLE) {
$map = $this->field_repository->get_map();
foreach ($map as $mapped => $value){
$set_ = 'set_'. $mapped;
// Show only args that has a method set
if( !method_exists(new Entities\Field(), "$set_") ){
unset($map[$mapped]);
}
}
$endpoint_args = $map;
}
return $endpoint_args;
}
}
?>

View File

@ -19,6 +19,25 @@ class TAINACAN_REST_Filter_Types_Controller extends TAINACAN_REST_Controller {
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'get_items'),
'permission_callback' => array($this, 'get_items_permissions_check'),
'args' => [
'filter-type' => [
'description' => __('The structure of objects returned.'),
'items' => [
'className' => [
'type' => 'string'
],
'component' => [
'type' => 'string'
],
'supported_types' => [
'type' => 'array',
'items' => [
'type' => 'string'
]
]
]
]
]
)
)
);
@ -46,7 +65,7 @@ class TAINACAN_REST_Filter_Types_Controller extends TAINACAN_REST_Controller {
* @return WP_Error|WP_REST_Response
*/
public function get_items( $request ) {
global $Tainacan_Filters;
$Tainacan_Filters = \Tainacan\Repositories\Filters::getInstance();
$filter_types = $Tainacan_Filters->fetch_filter_types('NAME');

View File

@ -28,12 +28,11 @@ class TAINACAN_REST_Filters_Controller extends TAINACAN_REST_Controller {
*/
public function init_objects() {
$this->collection = new Entities\Collection();
$this->collection_repository = new Repositories\Collections();
$this->collection_repository = Repositories\Collections::getInstance();
$this->field = new Entities\Field();
$this->field_repository = new Repositories\Fields();
$this->field_repository = Repositories\Fields::getInstance();
$this->filter_repository = new Repositories\Filters();
$this->filter_repository = Repositories\Filters::getInstance();
}
public function register_routes() {
@ -41,48 +40,61 @@ class TAINACAN_REST_Filters_Controller extends TAINACAN_REST_Controller {
array(
'methods' => WP_REST_Server::CREATABLE,
'callback' => array($this, 'create_item'),
'permission_callback' => array($this, 'create_item_permissions_check')
'permission_callback' => array($this, 'create_item_permissions_check'),
'args' => $this->get_endpoint_args_for_item_schema(WP_REST_Server::CREATABLE)
),
));
register_rest_route($this->namespace, '/collection/(?P<collection_id>[\d]+)/' . $this->rest_base, array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'get_items'),
'permission_callback' => array($this, 'get_items_permissions_check')
'permission_callback' => array($this, 'get_items_permissions_check'),
'args' => $this->get_collection_params()
),
array(
'methods' => WP_REST_Server::CREATABLE,
'callback' => array($this, 'create_item'),
'permission_callback' => array($this, 'create_item_permissions_check')
'permission_callback' => array($this, 'create_item_permissions_check'),
'args' => $this->get_endpoint_args_for_item_schema(WP_REST_Server::CREATABLE)
)
));
register_rest_route($this->namespace, '/' . $this->rest_base, array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'get_items'),
'permission_callback' => array($this, 'get_items_permissions_check')
'permission_callback' => array($this, 'get_items_permissions_check'),
'args' => $this->get_collection_params()
),
array(
'methods' => WP_REST_Server::CREATABLE,
'callback' => array($this, 'create_item'),
'permission_callback' => array($this, 'create_item_permissions_check')
'permission_callback' => array($this, 'create_item_permissions_check'),
'args' => $this->get_endpoint_args_for_item_schema(WP_REST_Server::CREATABLE)
)
));
register_rest_route($this->namespace, '/' . $this->rest_base . '/(?P<filter_id>[\d]+)', array(
array(
'methods' => WP_REST_Server::DELETABLE,
'callback' => array($this, 'delete_item'),
'permission_callback' => array($this, 'delete_item_permissions_check')
'permission_callback' => array($this, 'delete_item_permissions_check'),
'args' => array(
'body_args' => array(
'description' => __('To delete permanently, in body you can pass \'is_permanently\' as true. By default this will only trash collection'),
'default' => 'false'
),
)
),
array(
'methods' => WP_REST_Server::EDITABLE,
'callback' => array($this, 'update_item'),
'permission_callback' => array($this, 'update_item_permissions_check')
'permission_callback' => array($this, 'update_item_permissions_check'),
'args' => $this->get_endpoint_args_for_item_schema(WP_REST_Server::EDITABLE)
),
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'get_item'),
'permission_callback' => array($this, 'get_item_permissions_check')
'permission_callback' => array($this, 'get_item_permissions_check'),
'args' => $this->get_endpoint_args_for_item_schema(WP_REST_Server::READABLE)
)
));
}
@ -123,7 +135,7 @@ class TAINACAN_REST_Filters_Controller extends TAINACAN_REST_Controller {
}
}
if(isset($request['collection_id']) && isset($request['filter_id'])) {
if(isset($request['collection_id']) && isset($request['field_id'])) {
$collection_id = $request['collection_id'];
$field_id = $request['field_id'];
@ -314,7 +326,7 @@ class TAINACAN_REST_Filters_Controller extends TAINACAN_REST_Controller {
if($request['context'] === 'edit'){
$item_arr['current_user_can_edit'] = $item->can_edit();
$item_arr['filter_type_object'] = $item->get_filter_type_object();
$item_arr['filter_type_object'] = $item->get_filter_type_object()->__toArray();
}
return $item_arr;
@ -359,7 +371,7 @@ class TAINACAN_REST_Filters_Controller extends TAINACAN_REST_Controller {
*/
public function get_items_permissions_check( $request ) {
if(!isset($request['collection_id'])) {
if ( 'edit' === $request['context'] && ! $this->filter_repository->can_read( $this->filter ) ) {
if ( 'edit' === $request['context'] && ! $this->filter_repository->can_read( new Entities\Filter() ) ) {
return false;
}
@ -410,5 +422,56 @@ class TAINACAN_REST_Filters_Controller extends TAINACAN_REST_Controller {
return false;
}
/**
* @param string $method
*
* @return array|mixed
*/
public function get_endpoint_args_for_item_schema( $method = null ) {
$endpoint_args = [];
if($method === WP_REST_Server::READABLE) {
$endpoint_args['context'] = array(
'type' => 'string',
'default' => 'view',
'items' => array( 'view, edit' )
);
} elseif ($method === WP_REST_Server::CREATABLE || $method === WP_REST_Server::EDITABLE) {
$map = $this->filter_repository->get_map();
foreach ($map as $mapped => $value){
$set_ = 'set_'. $mapped;
// Show only args that has a method set
if( !method_exists(new Entities\Filter(), "$set_") ){
unset($map[$mapped]);
}
}
$endpoint_args = $map;
}
return $endpoint_args;
}
/**
* @param null $object_name
*
* @return array|void
*/
public function get_collection_params( $object_name = null ) {
$query_params['context']['default'] = 'view';
$query_params = array_merge($query_params, parent::get_collection_params('filter'));
$query_params['name'] = array(
'description' => __('Limit result set to filter with specific name.'),
'type' => 'string',
);
$query_params = array_merge($query_params, parent::get_meta_queries_params());
return $query_params;
}
}
?>

View File

@ -23,10 +23,10 @@ class TAINACAN_REST_Item_Metadata_Controller extends TAINACAN_REST_Controller {
*/
public function init_objects() {
$this->field = new Entities\Field();
$this->field_repository = new Repositories\Fields();
$this->item_metadata_repository = new Repositories\Item_Metadata();
$this->item_repository = new Repositories\Items();
$this->collection_repository = new Repositories\Collections();
$this->field_repository = Repositories\Fields::getInstance();
$this->item_metadata_repository = Repositories\Item_Metadata::getInstance();
$this->item_repository = Repositories\Items::getInstance();
$this->collection_repository = Repositories\Collections::getInstance();
}
/**
@ -44,7 +44,8 @@ class TAINACAN_REST_Item_Metadata_Controller extends TAINACAN_REST_Controller {
array(
'methods' => WP_REST_Server::EDITABLE,
'callback' => array($this, 'update_item'),
'permission_callback' => array($this, 'update_item_permissions_check')
'permission_callback' => array($this, 'update_item_permissions_check'),
'args' => $this->get_endpoint_args_for_item_schema(WP_REST_Server::EDITABLE)
)
)
);
@ -54,10 +55,10 @@ class TAINACAN_REST_Item_Metadata_Controller extends TAINACAN_REST_Controller {
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'get_items'),
'permission_callback' => array($this, 'get_items_permissions_check'),
//'args' => $this->get_collection_params(),
'args' => $this->get_collection_params(),
)
)
);
);
register_rest_route($this->namespace, '/item/(?P<item_id>[\d]+)/'. $this->rest_base. '/(?P<metadata_id>[\d]+)',
array(
array(
@ -189,6 +190,7 @@ class TAINACAN_REST_Item_Metadata_Controller extends TAINACAN_REST_Controller {
$field = $this->field_repository->fetch( $field_id );
$item_metadata = new Entities\Item_Metadata_Entity( $item, $field );
if($item_metadata->is_multiple()) {
$item_metadata->set_value( $value );
} elseif(is_array($value)) {
@ -255,6 +257,41 @@ class TAINACAN_REST_Item_Metadata_Controller extends TAINACAN_REST_Controller {
return false;
}
/**
* @param string $method
*
* @return array|mixed
*/
public function get_endpoint_args_for_item_schema( $method = null ) {
$endpoint_args = [];
if ($method === WP_REST_Server::EDITABLE) {
$endpoint_args['values'] = [
'type' => 'array/string/object/integer',
'items' => [
'type' => 'array/string/object/integer'
],
'description' => __('The value(s) of item metadata')
];
}
return $endpoint_args;
}
/**
*
* Return the queries supported when getting a collection of objects
*
* @param null $object_name
*
* @return array
*/
public function get_collection_params($object_name = null) {
$query_params['context']['default'] = 'view';
return $query_params;
}
}
?>

View File

@ -30,10 +30,10 @@ class TAINACAN_REST_Items_Controller extends TAINACAN_REST_Controller {
* Initialize objects after post_type register
*/
public function init_objects() {
$this->items_repository = new Repositories\Items();
$this->items_repository = Repositories\Items::getInstance();
$this->item = new Entities\Item();
$this->item_metadata = new Repositories\Item_Metadata();
$this->collections_repository = new Repositories\Collections();
$this->item_metadata = Repositories\Item_Metadata::getInstance();
$this->collections_repository = Repositories\Collections::getInstance();
}
/**
@ -435,17 +435,6 @@ class TAINACAN_REST_Items_Controller extends TAINACAN_REST_Controller {
return $endpoint_args;
}
/**
* @return array
*/
public function get_item_schema() {
$schema['item']['type'] = 'object';
$schema['item']['description'] = __('Passed in body.');
$schema['item']['properties'] = $this->items_repository->get_map();
return $schema;
}
/**
* @param null $object_name
*

View File

@ -20,7 +20,7 @@ class TAINACAN_REST_Logs_Controller extends TAINACAN_REST_Controller {
}
public function init_objects(){
$this->logs_repository = new Repositories\Logs();
$this->logs_repository = Repositories\Logs::getInstance();
$this->log = new Entities\Log();
}
@ -31,6 +31,7 @@ class TAINACAN_REST_Logs_Controller extends TAINACAN_REST_Controller {
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'get_items'),
'permission_callback' => array($this, 'get_items_permissions_check'),
'args' => $this->get_collection_params()
)
)
);
@ -40,10 +41,10 @@ class TAINACAN_REST_Logs_Controller extends TAINACAN_REST_Controller {
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'get_item'),
'permission_callback' => array($this, 'get_item_permissions_check'),
'args' => $this->get_endpoint_args_for_item_schema(WP_REST_Server::READABLE)
)
)
);
register_rest_route($this->namespace, '/' . $this->rest_base . '/(?P<log_id>[\d]+)/approve',
array(
array(
@ -149,9 +150,11 @@ class TAINACAN_REST_Logs_Controller extends TAINACAN_REST_Controller {
*/
public function approve_item_permissions_check( $request ) {
$log = $this->logs_repository->fetch($request['log_id']);
if($log instanceof Entities\Log){
if($log->can_read()) {
$entity = $log->get_value();
if($entity instanceof Entities\Entity) {
if($entity instanceof Entities\Item_Metadata_Entity) {
$item = $entity->get_item();
@ -161,9 +164,11 @@ class TAINACAN_REST_Logs_Controller extends TAINACAN_REST_Controller {
return $entity->can_edit();
}
}
return new WP_Error();
}
}
return false;
}
@ -175,13 +180,55 @@ class TAINACAN_REST_Logs_Controller extends TAINACAN_REST_Controller {
*/
public function approve_item($request) {
$log = $this->logs_repository->fetch($request['log_id']);
if($log instanceof Entities\Log){
if($log instanceof Entities\Log){
$entity = $log->approve();
$prepared_entity = $this->prepare_item_for_response( $entity, $request );
return new WP_REST_Response($prepared_entity, 200);
}
}
/**
* @param string $method
*
* @return array|mixed
*/
public function get_endpoint_args_for_item_schema( $method = null ) {
$endpoint_args = [];
if($method === WP_REST_Server::READABLE) {
$endpoint_args['context'] = array(
'type' => 'string',
'default' => 'view',
'items' => array( 'view' )
);
}
return $endpoint_args;
}
/**
*
* Return the queries supported when getting a collection of objects
*
* @param null $object_name
*
* @return array
*/
public function get_collection_params($object_name = null) {
$query_params['context']['default'] = 'view';
$query_params = array_merge($query_params, parent::get_collection_params('log'));
$query_params['title'] = array(
'description' => __('Limit result set to log with specific title.'),
'type' => 'string',
);
$query_params = array_merge($query_params, parent::get_meta_queries_params());
return $query_params;
}
}
?>

View File

@ -23,7 +23,7 @@ class TAINACAN_REST_Taxonomies_Controller extends TAINACAN_REST_Controller {
*/
public function init_objects() {
$this->taxonomy = new Entities\Taxonomy();
$this->taxonomy_repository = new Repositories\Taxonomies();
$this->taxonomy_repository = Repositories\Taxonomies::getInstance();
}
public function register_routes() {
@ -34,11 +34,13 @@ class TAINACAN_REST_Taxonomies_Controller extends TAINACAN_REST_Controller {
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'get_items'),
'permission_callback' => array($this, 'get_items_permissions_check'),
'args' => $this->get_collection_params()
),
array(
'methods' => WP_REST_Server::CREATABLE,
'callback' => array($this, 'create_item'),
'permission_callback' => array($this, 'create_item_permissions_check'),
'args' => $this->get_endpoint_args_for_item_schema(WP_REST_Server::CREATABLE)
)
)
);
@ -49,16 +51,24 @@ class TAINACAN_REST_Taxonomies_Controller extends TAINACAN_REST_Controller {
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'get_item'),
'permission_callback' => array($this, 'get_item_permissions_check'),
'args' => $this->get_endpoint_args_for_item_schema(WP_REST_Server::READABLE)
),
array(
'methods' => WP_REST_Server::DELETABLE,
'callback' => array($this, 'delete_item'),
'permission_callback' => array($this, 'delete_item_permissions_check'),
'args' => array(
'body_args' => array(
'description' => __('To delete permanently, in body you can pass \'is_permanently\' as true. By default this will only trash collection'),
'default' => 'false'
),
)
),
array(
'methods' => WP_REST_Server::EDITABLE,
'callback' => array($this, 'update_item'),
'permission_callback' => array($this, 'update_item_permissions_check')
'permission_callback' => array($this, 'update_item_permissions_check'),
'args' => $this->get_endpoint_args_for_item_schema(WP_REST_Server::EDITABLE)
)
)
);
@ -68,7 +78,8 @@ class TAINACAN_REST_Taxonomies_Controller extends TAINACAN_REST_Controller {
array(
'methods' => WP_REST_Server::EDITABLE,
'callback' => array($this, 'update_item'),
'permission_callback' => array($this, 'update_item_permissions_check')
'permission_callback' => array($this, 'update_item_permissions_check'),
'args' => $this->get_endpoint_args_for_item_schema(WP_REST_Server::EDITABLE)
)
)
);
@ -216,14 +227,30 @@ class TAINACAN_REST_Taxonomies_Controller extends TAINACAN_REST_Controller {
public function get_items( $request ) {
$args = $this->prepare_filters($request);
$taxonomies = $this->taxonomy_repository->fetch($args, 'OBJECT');
$taxonomies = $this->taxonomy_repository->fetch($args);
$response = [];
foreach ($taxonomies as $taxonomy) {
array_push($response, $this->prepare_item_for_response( $taxonomy, $request ));
if($taxonomies->have_posts()){
while ($taxonomies->have_posts()){
$taxonomies->the_post();
$taxonomy = new Entities\Taxonomy($taxonomies->post);
array_push($response, $this->prepare_item_for_response($taxonomy, $request));
}
wp_reset_postdata();
}
return new WP_REST_Response($response, 200);
$total_taxonomies = (int) $taxonomies->found_posts;
$max_pages = ceil($total_taxonomies / (int) $taxonomies->query_vars['posts_per_page']);
$rest_response = new WP_REST_Response($response, 200);
$rest_response->header('X-WP-Total', $total_taxonomies);
$rest_response->header('X-WP-TotalPages', (int) $max_pages);
return $rest_response;
}
/**
@ -345,6 +372,65 @@ class TAINACAN_REST_Taxonomies_Controller extends TAINACAN_REST_Controller {
return false;
}
/**
* @param string $method
*
* @return array|mixed
*/
public function get_endpoint_args_for_item_schema( $method = null ) {
$endpoint_args = [];
if($method === WP_REST_Server::READABLE) {
$endpoint_args['fetch_only'] = array(
'type' => 'string/array',
'description' => __( 'Fetch only specific attribute. The specifics attributes are the same in schema.' ),
);
$endpoint_args['context'] = array(
'type' => 'string',
'default' => 'view',
'items' => array( 'view, edit' )
);
} elseif ($method === WP_REST_Server::CREATABLE || $method === WP_REST_Server::EDITABLE) {
$map = $this->taxonomy_repository->get_map();
foreach ($map as $mapped => $value){
$set_ = 'set_'. $mapped;
// Show only args that has a method set
if( !method_exists($this->taxonomy, "$set_") ){
unset($map[$mapped]);
}
}
$endpoint_args = $map;
}
return $endpoint_args;
}
/**
*
* Return the queries supported when getting a collection of objects
*
* @param null $object_name
*
* @return array
*/
public function get_collection_params($object_name = null) {
$query_params['context']['default'] = 'view';
$query_params = array_merge($query_params, parent::get_collection_params('tax'));
$query_params['name'] = array(
'description' => __('Limit result set to taxonomy with specific name.'),
'type' => 'string',
);
$query_params = array_merge($query_params, parent::get_meta_queries_params());
return $query_params;
}
}
?>

View File

@ -25,9 +25,9 @@ class TAINACAN_REST_Terms_Controller extends TAINACAN_REST_Controller {
*/
public function init_objects() {
$this->term = new Entities\Term();
$this->terms_repository = new Repositories\Terms();
$this->terms_repository = Repositories\Terms::getInstance();
$this->taxonomy = new Entities\Taxonomy();
$this->taxonomy_repository = new Repositories\Taxonomies();
$this->taxonomy_repository = Repositories\Taxonomies::getInstance();
}
public function register_routes() {
@ -36,12 +36,14 @@ class TAINACAN_REST_Terms_Controller extends TAINACAN_REST_Controller {
array(
'methods' => WP_REST_Server::CREATABLE,
'callback' => array($this, 'create_item'),
'permission_callback' => array($this, 'create_item_permissions_check')
'permission_callback' => array($this, 'create_item_permissions_check'),
'args' => $this->get_endpoint_args_for_item_schema(WP_REST_Server::CREATABLE)
),
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'get_items'),
'permission_callback' => array($this, 'get_items_permissions_check')
'permission_callback' => array($this, 'get_items_permissions_check'),
'args' => $this->get_collection_params()
)
)
);
@ -50,17 +52,24 @@ class TAINACAN_REST_Terms_Controller extends TAINACAN_REST_Controller {
array(
'methods' => WP_REST_Server::DELETABLE,
'callback' => array($this, 'delete_item'),
'permission_callback' => array($this, 'delete_item_permissions_check')
'permission_callback' => array($this, 'delete_item_permissions_check'),
'args' => [
'info' => [
'description' => __('Delete term permanently.')
]
]
),
array(
'methods' => WP_REST_Server::EDITABLE,
'callback' => array($this, 'update_item'),
'permission_callback' => array($this, 'update_item_permissions_check')
'permission_callback' => array($this, 'update_item_permissions_check'),
'args' => $this->get_endpoint_args_for_item_schema(WP_REST_Server::EDITABLE)
),
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'get_item'),
'permission_callback' => array($this, 'get_item_permissions_check')
'permission_callback' => array($this, 'get_item_permissions_check'),
'args' => $this->get_endpoint_args_for_item_schema(WP_REST_Server::READABLE)
)
)
);
@ -344,6 +353,60 @@ class TAINACAN_REST_Terms_Controller extends TAINACAN_REST_Controller {
return false;
}
/**
* @param string $method
*
* @return array|mixed
*/
public function get_endpoint_args_for_item_schema( $method = null ) {
$endpoint_args = [];
if($method === WP_REST_Server::READABLE) {
$endpoint_args['context'] = array(
'type' => 'string',
'default' => 'view',
'items' => array( 'view, edit' )
);
} elseif ($method === WP_REST_Server::CREATABLE || $method === WP_REST_Server::EDITABLE) {
$map = $this->terms_repository->get_map();
foreach ($map as $mapped => $value){
$set_ = 'set_'. $mapped;
// Show only args that has a method set
if( !method_exists($this->term, "$set_") ){
unset($map[$mapped]);
}
}
$endpoint_args = $map;
}
return $endpoint_args;
}
/**
*
* Return the queries supported when getting a collection of objects
*
* @param null $object_name
*
* @return array
*/
public function get_collection_params($object_name = null) {
$query_params['context']['default'] = 'view';
$query_params = array_merge($query_params, parent::get_collection_params('term'));
$query_params['name'] = array(
'description' => __('Limit result set to term with specific name.'),
'type' => 'string',
);
$query_params = array_merge($query_params, parent::get_meta_queries_params());
return $query_params;
}
}
?>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Camada_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="12.815px" height="12.815px" viewBox="0 0 12.815 12.815" enable-background="new 0 0 12.815 12.815" xml:space="preserve">
<g>
<circle cx="1.469" cy="1.469" r="1.469"/>
<circle cx="6.407" cy="1.469" r="1.469"/>
<circle cx="11.346" cy="1.469" r="1.469"/>
<circle cx="1.469" cy="6.407" r="1.469"/>
<circle cx="6.407" cy="6.407" r="1.469"/>
<circle cx="11.346" cy="6.407" r="1.469"/>
<circle cx="1.469" cy="11.346" r="1.469"/>
<circle cx="6.407" cy="11.346" r="1.469"/>
<circle cx="11.346" cy="11.346" r="1.469"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 915 B

View File

@ -270,11 +270,22 @@ class Capabilities {
]
],
];
private static $instance = null;
public static function getInstance()
{
if(!isset(self::$instance))
{
self::$instance = new self();
}
return self::$instance;
}
/**
* Register hooks
*/
function __construct() {
private function __construct() {
add_action('tainacan-insert-tainacan-collection', array(&$this, 'new_collection'));
add_action('tainacan-add-collection-moderators', array(&$this, 'add_moderators'), 10, 2);
@ -381,7 +392,7 @@ class Capabilities {
}
}
global $Tainacan_Collections;
$Tainacan_Collections = \Tainacan\Repositories\Collections::getInstance();
$collections = $Tainacan_Collections->fetch([], 'OBJECT');
foreach ($collections as $collection) {
$this->set_items_capabilities($collection, $defaults_caps);

View File

@ -9,285 +9,336 @@ defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
*/
class Collection extends Entity {
/**
/**
* {@inheritDoc}
* @see \Tainacan\Entities\Entity::post_type
* @see \Tainacan\Entities\Entity::post_type
* @var string
*/
protected static $post_type = 'tainacan-collection';
/**
* {@inheritDoc}
* @see \Tainacan\Entities\Entity::repository
* @var string
*/
protected $repository = 'Tainacan_Collections';
/**
* Prefix used to create the db_identifier
* @var string
*/
static $db_identifier_prefix = 'tnc_col_';
/**
* sufix used to create the db_identifier
* @var string
*/
static $db_identifier_sufix = '_item';
protected static $post_type = 'tainacan-collection';
/**
* {@inheritDoc}
* @see \Tainacan\Entities\Entity::repository
* @var string
*/
protected $repository = 'Collections';
public function __toString(){
return 'Hello, my name is '. $this->get_name();
}
/**
* Prefix used to create the db_identifier
*
* @var string
*/
static $db_identifier_prefix = 'tnc_col_';
/**
* sufix used to create the db_identifier
*
* @var string
*/
static $db_identifier_sufix = '_item';
public function __toString() {
return 'Hello, my name is ' . $this->get_name();
}
public function __toArray() {
$array_collection = parent::__toArray();
$array_collection['featured_image'] = $this->get_featured_image();
$array_collection['featured_img_id'] = $this->get_featured_img_id();
$array_collection['attachments'] = $this->get_attachments();
$array_collection['author_name'] = $this->get_author_name();
return $array_collection;
}
/**
* Register the post type for this collection
*
* Each collection is a post type, and each item inside a collection is a post of this post type
*
* This method register the post type for a collection, so that items can be created.
*
* @return \WP_Post_Type|\WP_Error
*/
function register_collection_item_post_type() {
$repository = $this->get_repository();
$cpt_labels = $repository->get_cpt_labels();
/**
* Register the post type for this collection
*
* Each collection is a post type, and each item inside a collection is a post of this post type
*
* This method register the post type for a collection, so that items can be created.
*
* @return \WP_Post_Type|\WP_Error
*/
function register_collection_item_post_type() {
global ${$this->repository};
$cpt_labels = ${$this->repository}->get_cpt_labels();
$cpt_labels['menu_name'] = $this->get_name();
$cpt_slug = $this->get_db_identifier();
$capabilities = $this->get_items_capabilities();
$cpt_slug = $this->get_db_identifier();
$capabilities = $this->get_items_capabilities();
$args = array(
'labels' => $cpt_labels,
'hierarchical' => true,
//'supports' => array('title'),
//'taxonomies' => array(self::TAXONOMY),
'public' => true,
'show_ui' => tnc_enable_dev_wp_interface(),
'show_in_menu' => tnc_enable_dev_wp_interface(),
//'menu_position' => 5,
//'show_in_nav_menus' => false,
'publicly_queryable' => true,
'exclude_from_search' => true,
'has_archive' => true,
'query_var' => true,
'can_export' => true,
'rewrite' => [
'slug' => $this->get_slug()
],
'map_meta_cap' => true,
'capabilities' => (array) $capabilities,
'supports' => [
'title',
'editor',
'thumbnail',
'revisions',
'page-attributes',
'post-formats'
]
);
$args = array(
'labels' => $cpt_labels,
'hierarchical' => true,
//'supports' => array('title'),
//'taxonomies' => array(self::TAXONOMY),
'public' => true,
'show_ui' => tnc_enable_dev_wp_interface(),
'show_in_menu' => tnc_enable_dev_wp_interface(),
//'menu_position' => 5,
//'show_in_nav_menus' => false,
'publicly_queryable' => true,
'exclude_from_search' => true,
'has_archive' => true,
'query_var' => true,
'can_export' => true,
'rewrite' => [
'slug' => $this->get_slug()
],
'map_meta_cap' => true,
'capabilities' => (array) $capabilities,
'supports' => [
'title',
'editor',
'thumbnail',
'revisions',
'page-attributes',
'post-formats'
]
);
if (post_type_exists($this->get_db_identifier()))
unregister_post_type($this->get_db_identifier());
if ( post_type_exists( $this->get_db_identifier() ) ) {
unregister_post_type( $this->get_db_identifier() );
}
return register_post_type($cpt_slug, $args);
}
/**
* Get the capabilities list for the post type of the items of this collection
*
* @uses get_post_type_capabilities to get the list.
*
* This method is usefull for getting the capabilities of the collection's items post type
* regardless if it has been already registered or not.
*
* @return object Object with all the capabilities as member variables.
*/
function get_items_capabilities() {
$args = [
'map_meta_cap' => true,
'capability_type' => $this->get_db_identifier(),
'capabilities' => array()
];
return get_post_type_capabilities((object) $args);
}
return register_post_type( $cpt_slug, $args );
}
/**
* Get the capabilities list for the post type of the items of this collection
*
* @uses get_post_type_capabilities to get the list.
*
* This method is usefull for getting the capabilities of the collection's items post type
* regardless if it has been already registered or not.
*
* @return object Object with all the capabilities as member variables.
*/
function get_items_capabilities() {
$args = [
'map_meta_cap' => true,
'capability_type' => $this->get_db_identifier(),
'capabilities' => array()
];
return get_post_type_capabilities( (object) $args );
}
/**
* @return array
*/
function get_attachments() {
$collection_id = $this->get_id();
$attachments_query = [
'post_type' => 'attachment',
'post_per_page' => - 1,
'post_parent' => $collection_id,
'exclude' => get_post_thumbnail_id( $collection_id )
];
$attachments = get_posts( $attachments_query );
$attachments_prepared = [];
if ( $attachments ) {
foreach ( $attachments as $attachment ) {
$prepared = [
'id' => $attachment->ID,
'title' => $attachment->post_title,
'description' => $attachment->post_content,
'mime_type' => $attachment->post_mime_type,
'url' => $attachment->guid,
];
array_push( $attachments_prepared, $prepared );
}
}
return $attachments_prepared;
}
/**
* @return mixed|null
* @return string
*/
function get_featured_img(){
return $this->get_mapped_property('featured_image');
}
function get_author_name() {
return get_the_author_meta( 'display_name', $this->get_author_id() );
}
/**
* @return false|string
*/
function get_featured_image() {
return get_the_post_thumbnail_url( $this->get_id(), 'full' );
}
/**
* @param $id
*/
function set_featured_img_id($id){
$this->set_mapped_property('featured_image_id', $id );
}
function set_featured_img_id( $id ) {
$this->set_mapped_property( 'featured_img_id', $id );
}
/**
* @return mixed|null
* @return int|string
*/
function get_attachments(){
return $this->get_mapped_property( 'attachments');
function get_featured_img_id() {
if ( isset( $this->featured_img_id ) ) {
return $this->featured_img_id;
}
return get_post_thumbnail_id( $this->get_id() );
}
/**
* @return mixed|null
*/
function get_modification_date(){
return $this->get_mapped_property('modification_date');
}
function get_modification_date() {
return $this->get_mapped_property( 'modification_date' );
}
/**
* @return mixed|null
*/
function get_creation_date(){
return $this->get_mapped_property('creation_date');
}
function get_creation_date() {
return $this->get_mapped_property( 'creation_date' );
}
/**
* @return mixed|null
*/
function get_author_id(){
return $this->get_mapped_property('author_id');
}
function get_author_id() {
return $this->get_mapped_property( 'author_id' );
}
/**
* @return mixed|null
*/
function get_author_name(){
return $this->get_mapped_property('author_name');
}
function get_url() {
return $this->get_mapped_property( 'url' );
}
/**
* @return mixed|null
* Get collection name
*
* @return string
*/
function get_url(){
return $this->get_mapped_property('url');
}
function get_name() {
return $this->get_mapped_property( 'name' );
}
/**
* Get collection name
*
* @return string
*/
function get_name() {
return $this->get_mapped_property('name');
}
/**
* Get collection slug
*
* @return string
*/
function get_slug() {
return $this->get_mapped_property( 'slug' );
}
/**
* Get collection slug
*
* @return string
*/
function get_slug() {
return $this->get_mapped_property('slug');
}
/**
* Get collection order
*
* @return integer
*/
function get_order() {
return $this->get_mapped_property( 'order' );
}
/**
* Get collection order
*
* @return integer
*/
function get_order() {
return $this->get_mapped_property('order');
}
/**
* Get collection parent ID
*
* @return integer
*/
function get_parent() {
return $this->get_mapped_property( 'parent' );
}
/**
* Get collection parent ID
*
* @return integer
*/
function get_parent() {
return $this->get_mapped_property('parent');
}
/**
* Get collection description
*
* @return string
*/
function get_description() {
return $this->get_mapped_property( 'description' );
}
/**
* Get collection description
*
* @return string
*/
function get_description() {
return $this->get_mapped_property('description');
}
/**
* Get collection default order
*
* @return string
*/
function get_default_order() {
return $this->get_mapped_property('default_order');
}
/**
* Get collection default orderby
*
* @return string
*/
function get_default_orderby() {
return $this->get_mapped_property('default_orderby');
}
/**
* Get collection columns option
*
* @return string
*/
function get_columns() {
return $this->get_mapped_property('columns');
}
/**
* Get collection default_view_mode option
*
* @return string
*/
function get_default_view_mode() {
return $this->get_mapped_property('default_view_mode');
}
/**
* Get collection default order
*
* @return string
*/
function get_default_order() {
return $this->get_mapped_property( 'default_order' );
}
/**
* Get collection fields ordination
*
* @return string
*/
function get_fields_order() {
return $this->get_mapped_property('fields_order');
}
/**
* Get collection default orderby
*
* @return string
*/
function get_default_orderby() {
return $this->get_mapped_property( 'default_orderby' );
}
/**
* Get collection filters ordination
*
* @return string
*/
function get_filters_order() {
return $this->get_mapped_property('filters_order');
}
/**
* Get collection columns option
*
* @return string
*/
function get_columns() {
return $this->get_mapped_property( 'columns' );
}
/**
* Get collection moderators ids
*
* @return array
*/
function get_moderators_ids() {
return $this->get_mapped_property('moderators_ids');
}
/**
* Get collection default_view_mode option
*
* @return string
*/
function get_default_view_mode() {
return $this->get_mapped_property( 'default_view_mode' );
}
/**
* Get collection DB identifier
*
* This identifier is used to register the collection post type and never changes, even if you change the name and the slug of the collection.
*
* @return string
*/
function get_db_identifier() {
return $this->get_id() ? Collection::$db_identifier_prefix . $this->get_id() . Collection::$db_identifier_sufix : false;
}
/**
* Get collection fields ordination
*
* @return string
*/
function get_fields_order() {
return $this->get_mapped_property( 'fields_order' );
}
/**
* Get collection filters ordination
*
* @return string
*/
function get_filters_order() {
return $this->get_mapped_property( 'filters_order' );
}
/**
* Get collection moderators ids
*
* @return array
*/
function get_moderators_ids() {
return $this->get_mapped_property( 'moderators_ids' );
}
/**
* Get collection DB identifier
*
* This identifier is used to register the collection post type and never changes, even if you change the name and the slug of the collection.
*
* @return string
*/
function get_db_identifier() {
return $this->get_id() ? Collection::$db_identifier_prefix . $this->get_id() . Collection::$db_identifier_sufix : false;
}
/**
* Get collection field.
@ -299,192 +350,219 @@ class Collection extends Entity {
* @return [\Tainacan\Entities\Field] array
* @throws \Exception
*/
function get_fields() {
$Tainacan_Fields = new \Tainacan\Repositories\Fields();
return $Tainacan_Fields->fetch_by_collection( $this, [], 'OBJECT' );
}
function get_fields() {
$Tainacan_Fields = \Tainacan\Repositories\Fields::getInstance();
/**
* Set the collection name
*
* @param [string] $value
* @return void
*/
function set_name($value) {
$this->set_mapped_property('name', $value);
}
return $Tainacan_Fields->fetch_by_collection( $this, [], 'OBJECT' );
}
/**
* Set the collection slug
*
* If you dont set the collection slug, it will be set automatically based on the name and
* following WordPress default behavior of creating slugs for posts.
*
* If you set the slug for an existing one, WordPress will append a number at the end of in order
* to make it unique (e.g slug-1, slug-2)
*
* @param [string] $value
* @return void
*/
function set_slug($value) {
$this->set_mapped_property('slug', $value);
}
/**
* Set the collection name
*
* @param [string] $value
*
* @return void
*/
function set_name( $value ) {
$this->set_mapped_property( 'name', $value );
}
/**
* Set collection order
*
* @param [string] $value
* @return void
*/
function set_order($value) {
$this->set_mapped_property('order', $value);
}
/**
* Set the collection slug
*
* If you dont set the collection slug, it will be set automatically based on the name and
* following WordPress default behavior of creating slugs for posts.
*
* If you set the slug for an existing one, WordPress will append a number at the end of in order
* to make it unique (e.g slug-1, slug-2)
*
* @param [string] $value
*
* @return void
*/
function set_slug( $value ) {
$this->set_mapped_property( 'slug', $value );
}
/**
* Set collection parent ID
*
* @param [integer] $value
* @return void
*/
function set_parent($value) {
$this->set_mapped_property('parent', $value);
}
/**
* Set collection order
*
* @param [string] $value
*
* @return void
*/
function set_order( $value ) {
$this->set_mapped_property( 'order', $value );
}
/**
* Set collection description
*
* @param [string] $value
* @return void
*/
function set_description($value) {
$this->set_mapped_property('description', $value);
}
/**
* Set collection default order option
*
* @param [string] $value
* @return void
*/
function set_default_order($value) {
$this->set_mapped_property('default_order', $value);
}
/**
* Set collection default_orderby option
*
* @param [string] $value
* @return void
*/
function set_default_orderby($value) {
$this->set_mapped_property('default_orderby', $value);
}
/**
* Set collection columns option
*
* @param [string] $value
* @return void
*/
function set_columns($value) {
$this->set_mapped_property('columns', $value);
}
/**
* Set collection default_view_mode option
*
* @param [string] $value
* @return void
*/
function set_default_view_mode($value) {
$this->set_mapped_property('default_view_mode', $value);
}
/**
* Set collection parent ID
*
* @param [integer] $value
*
* @return void
*/
function set_parent( $value ) {
$this->set_mapped_property( 'parent', $value );
}
/**
* Set collection fields ordination
*
* @param [string] $value
* @return void
*/
function set_fields_order($value) {
$this->set_mapped_property('fields_order', $value);
}
/**
* Set collection description
*
* @param [string] $value
*
* @return void
*/
function set_description( $value ) {
$this->set_mapped_property( 'description', $value );
}
/**
* Set collection filters ordination
*
* @param [string] $value
* @return void
*/
function set_filters_order($value) {
$this->set_mapped_property('filters_order', $value);
}
/**
* Set collection moderators ids
*
* @param [string] $value
* @return void
*/
function set_moderators_ids($value) {
$this->set_mapped_property('moderators_ids', $value);
}
// Moderators methods
/**
* Add a moderator ID to the moderators_ids list
* @param int $user_id The user ID to be added
* @return boolean Wether the ID was added or not. (if it already existed in the list it returns false)
*/
function add_moderator_id($user_id) {
if (is_integer($user_id)) {
$current_moderators = $this->get_moderators_ids();
if (!in_array($user_id, $current_moderators)) {
$current_moderators[] = $user_id;
$this->set_moderators_ids($current_moderators);
return true;
}
}
return false;
}
/**
* Remove a moderator ID to the moderators_ids list
* @param int $user_id The user ID to be removed
* @return boolean Wether the ID was added or not. (if it did not exist in the list it returns false)
*/
function remove_moderator_id($user_id) {
if (is_integer($user_id)) {
$current_moderators = $this->get_moderators_ids();
if (($key = array_search($user_id, $current_moderators)) !== false) {
unset($current_moderators[$key]);
$this->set_moderators_ids($current_moderators);
return true;
}
}
return false;
}
/**
* TODO implement the following methods to handle moderators_ids
*
* set_moderators
* get_moderators
* (the same as moderators_ids but gets and sets WP_User objects)
*
*/
/**
* Validate Collection
* @return bool
*/
function validate() {
if ( !in_array($this->get_status(), apply_filters('tainacan-status-require-validation', ['publish','future','private'])) )
return true;
return parent::validate();
/**
* Set collection default order option
*
* @param [string] $value
*
* @return void
*/
function set_default_order( $value ) {
$this->set_mapped_property( 'default_order', $value );
}
/**
* Set collection default_orderby option
*
* @param [string] $value
*
* @return void
*/
function set_default_orderby( $value ) {
$this->set_mapped_property( 'default_orderby', $value );
}
/**
* Set collection columns option
*
* @param [string] $value
*
* @return void
*/
function set_columns( $value ) {
$this->set_mapped_property( 'columns', $value );
}
/**
* Set collection default_view_mode option
*
* @param [string] $value
*
* @return void
*/
function set_default_view_mode( $value ) {
$this->set_mapped_property( 'default_view_mode', $value );
}
/**
* Set collection fields ordination
*
* @param [string] $value
*
* @return void
*/
function set_fields_order( $value ) {
$this->set_mapped_property( 'fields_order', $value );
}
/**
* Set collection filters ordination
*
* @param [string] $value
*
* @return void
*/
function set_filters_order( $value ) {
$this->set_mapped_property( 'filters_order', $value );
}
/**
* Set collection moderators ids
*
* @param [string] $value
*
* @return void
*/
function set_moderators_ids( $value ) {
$this->set_mapped_property( 'moderators_ids', $value );
}
// Moderators methods
/**
* Add a moderator ID to the moderators_ids list
*
* @param int $user_id The user ID to be added
*
* @return boolean Wether the ID was added or not. (if it already existed in the list it returns false)
*/
function add_moderator_id( $user_id ) {
if ( is_integer( $user_id ) ) {
$current_moderators = $this->get_moderators_ids();
if ( ! in_array( $user_id, $current_moderators ) ) {
$current_moderators[] = $user_id;
$this->set_moderators_ids( $current_moderators );
return true;
}
}
return false;
}
/**
* Remove a moderator ID to the moderators_ids list
*
* @param int $user_id The user ID to be removed
*
* @return boolean Wether the ID was added or not. (if it did not exist in the list it returns false)
*/
function remove_moderator_id( $user_id ) {
if ( is_integer( $user_id ) ) {
$current_moderators = $this->get_moderators_ids();
if ( ( $key = array_search( $user_id, $current_moderators ) ) !== false ) {
unset( $current_moderators[ $key ] );
$this->set_moderators_ids( $current_moderators );
return true;
}
}
return false;
}
/**
* TODO implement the following methods to handle moderators_ids
*
* set_moderators
* get_moderators
* (the same as moderators_ids but gets and sets WP_User objects)
*
*/
/**
* Validate Collection
*
* @return bool
*/
function validate() {
if ( ! in_array( $this->get_status(), apply_filters( 'tainacan-status-require-validation', [
'publish',
'future',
'private'
] ) ) ) {
return true;
}
return parent::validate();
}
}
}

View File

@ -124,7 +124,15 @@ class Entity {
}
}
}
public function get_repository()
{
$namespace = '\Tainacan\Repositories\\'.$this->repository;
$repository = $namespace::getInstance();
return $repository;
}
/**
* return the value for a mapped property
* @param string $prop id of property
@ -135,8 +143,9 @@ class Entity {
return $this->$prop;
}
//prop is not set at object, try to get from database
global ${$this->repository};
return ${$this->repository}->get_mapped_property($this, $prop);
$repository = $this->get_repository();
return $repository->get_mapped_property($this, $prop);
}
/**
@ -166,9 +175,9 @@ class Entity {
* @return boolean
*/
public function validate() {
global ${$this->repository};
$map = ${$this->repository}->get_map();
$repository = $this->get_repository();
$map = $repository->get_map();
$is_valid = true;
@ -190,8 +199,8 @@ class Entity {
* @return boolean
*/
public function validate_prop($prop) {
global ${$this->repository};
$map = ${$this->repository}->get_map();
$repository = $this->get_repository();
$map = $repository->get_map();
$mapped = $map[$prop];
$is_valid = true;
@ -289,8 +298,8 @@ class Entity {
}
public function __toArray(){
global ${$this->repository};
$map = ${$this->repository}->get_map();
$repository = $this->get_repository();
$map = $repository->get_map();
$attributes = [];
foreach($map as $prop => $content) {
@ -310,8 +319,8 @@ class Entity {
* @return bool
*/
public function can_read($user = null) {
global ${$this->repository};
return ${$this->repository}->can_read($this, $user);
$repository = $this->get_repository();
return $repository->can_read($this, $user);
}
/**
@ -320,8 +329,8 @@ class Entity {
* @return bool
*/
public function can_edit($user = null) {
global ${$this->repository};
return ${$this->repository}->can_edit($this, $user);
$repository = $this->get_repository();
return $repository->can_edit($this, $user);
}
/**
@ -330,8 +339,8 @@ class Entity {
* @return bool
*/
public function can_delete($user = null) {
global ${$this->repository};
return ${$this->repository}->can_delete($this, $user);
$repository = $this->get_repository();
return $repository->can_delete($this, $user);
}
/**
@ -340,8 +349,8 @@ class Entity {
* @return bool
*/
public function can_publish($user = null) {
global ${$this->repository};
return ${$this->repository}->can_publish($this, $user);
$repository = $this->get_repository();
return $repository->can_publish($this, $user);
}
/**
@ -356,9 +365,9 @@ class Entity {
*/
public function get_capabilities() {
$args = [
'map_meta_cap' => true,
'map_meta_cap' => true,
'capability_type' => self::get_capability_type(),
'capabilities' => array()
'capabilities' => array()
];
return get_post_type_capabilities((object) $args);
@ -370,8 +379,8 @@ class Entity {
* @return array
*/
public function diff($which = 0) {
global ${$this->repository};
return ${$this->repository}->diff($which, $this);
$repository = $this->get_repository();
return $repository->diff($which, $this);
}
}

View File

@ -12,7 +12,7 @@ class Field extends Entity {
// Collection getter and setter declared here
use \Tainacan\Traits\Entity_Collection_Relation;
public $disabled_for_collection = false;
public $enabled_for_collection = true;
protected static $post_type = 'tainacan-field';
/**
@ -20,7 +20,7 @@ class Field extends Entity {
* @see \Tainacan\Entities\Entity::repository
* @var string
*/
protected $repository = 'Tainacan_Fields';
protected $repository = 'Fields';
public function __toString(){
return 'Hello, my name is '. $this->get_name();
@ -348,11 +348,11 @@ class Field extends Entity {
* Used by the API to tell front end when a field is disabled
*
*/
public function get_disabled_for_collection() {
return $this->disabled_for_collection;
public function get_enabled_for_collection() {
return $this->enabled_for_collection;
}
public function set_disabled_for_collection($value) {
$this->disabled_for_collection = $value;
public function set_enabled_for_collection($value) {
$this->enabled_for_collection = $value;
}

View File

@ -17,12 +17,27 @@ class Filter extends Entity {
* @see \Tainacan\Entities\Entity::repository
* @var string
*/
protected $repository = 'Tainacan_Filters';
protected $repository = 'Filters';
public function __toString(){
return 'Hello, my name is '. $this->get_name();
}
/**
* @return array
* @throws \Exception
*/
public function __toArray(){
$filter_array = parent::__toArray();
$field_id = $filter_array['field'];
$filter_array['field'] = [];
$filter_array['field']['field_id'] = $field_id;
$filter_array['field']['field_name'] = $this->get_field()->get_name();
return $filter_array;
}
/**
* Return the filter name
*

View File

@ -14,7 +14,7 @@ class Item_Metadata_Entity extends Entity {
* @see \Tainacan\Entities\Entity::repository
* @var string
*/
protected $repository = 'Tainacan_Item_Metadata';
protected $repository = 'Item_Metadata';
function __construct(Item $item, Field $field) {
@ -27,8 +27,8 @@ class Item_Metadata_Entity extends Entity {
}
public function __toArray(){
$as_array['value'] = $this->get_value();
$as_array['item'] = $this->get_item()->__toArray();
$as_array['value'] = $this->get_value();
$as_array['item'] = $this->get_item()->__toArray();
$as_array['field'] = $this->get_field()->__toArray();
return $as_array;
@ -91,7 +91,7 @@ class Item_Metadata_Entity extends Entity {
if (isset($this->value))
return $this->value;
global $Tainacan_Item_Metadata;
$Tainacan_Item_Metadata = \Tainacan\Repositories\Item_Metadata::getInstance();
return $Tainacan_Item_Metadata->get_value($this);
}
@ -187,12 +187,12 @@ class Item_Metadata_Entity extends Entity {
}
if ($this->is_collection_key()) {
$Tainacan_Items = new \Tainacan\Repositories\Items();
$Tainacan_Items = \Tainacan\Repositories\Items::getInstance();
$test = $Tainacan_Items->fetch([
'meta_query' => [
'meta_query' => [
[
'key' => $this->field->get_id(),
'key' => $this->field->get_id(),
'value' => $value
],
]

View File

@ -14,259 +14,330 @@ class Item extends Entity {
* @see \Tainacan\Entities\Entity::repository
* @var string
*/
protected $repository = 'Tainacan_Items';
protected $repository = 'Items';
/**
* {@inheritDoc}
*/
function __construct($which = 0) {
parent::__construct($which);
if($which !== 0 ) $this->set_cap();
function __construct( $which = 0 ) {
parent::__construct( $which );
if ( $which !== 0 ) {
$this->set_cap();
}
}
public function __toString(){
return 'Hello, my name is '. $this->get_title();
public function __toString() {
return 'Hello, my name is ' . $this->get_title();
}
public function __toArray() {
$array_item = parent::__toArray();
$array_item['featured_image'] = $this->get_featured_image();
$array_item['featured_img_id'] = $this->get_featured_img_id();
$array_item['attachments'] = $this->get_attachments();
$array_item['author_name'] = $this->get_author_name();
return $array_item;
}
/**
* @param $value
*/
function set_terms($value){
$this->set_mapped_property('terms', $value);
function set_terms( $value ) {
$this->set_mapped_property( 'terms', $value );
}
/**
* @return mixed|null
*/
function get_terms(){
return $this->get_mapped_property('terms');
function get_terms() {
return $this->get_mapped_property( 'terms' );
}
/**
* @return mixed|null
* @return array
*/
function get_featured_img(){
return $this->get_mapped_property('featured_image');
function get_attachments() {
$item_id = $this->get_id();
$attachments_query = [
'post_type' => 'attachment',
'post_per_page' => - 1,
'post_parent' => $item_id,
'exclude' => get_post_thumbnail_id( $item_id )
];
$attachments = get_posts( $attachments_query );
$attachments_prepared = [];
if ( $attachments ) {
foreach ( $attachments as $attachment ) {
$prepared = [
'id' => $attachment->ID,
'title' => $attachment->post_title,
'description' => $attachment->post_content,
'mime_type' => $attachment->post_mime_type,
'url' => $attachment->guid,
];
array_push( $attachments_prepared, $prepared );
}
}
return $attachments_prepared;
}
/**
* @return string
*/
function get_author_name() {
return get_the_author_meta( 'display_name', $this->get_author_id() );
}
/**
* @return false|string
*/
function get_featured_image() {
return get_the_post_thumbnail_url( $this->get_id(), 'full' );
}
/**
* @param $id
*/
function set_featured_img_id($id){
$this->set_mapped_property('featured_image_id', $id );
function set_featured_img_id( $id ) {
$this->set_mapped_property( 'featured_img_id', $id );
}
/**
* @return int|string
*/
function get_featured_img_id() {
if ( isset( $this->featured_img_id ) ) {
return $this->featured_img_id;
}
return get_post_thumbnail_id( $this->get_id() );
}
/**
* @return mixed|null
*/
function get_attachments(){
return $this->get_mapped_property('attachments');
function get_modification_date() {
return $this->get_mapped_property( 'modification_date' );
}
/**
* @return mixed|null
*/
function get_modification_date(){
return $this->get_mapped_property('modification_date');
function get_creation_date() {
return $this->get_mapped_property( 'creation_date' );
}
/**
* @return mixed|null
*/
function get_creation_date(){
return $this->get_mapped_property('creation_date');
function get_author_id() {
return $this->get_mapped_property( 'author_id' );
}
/**
* @return mixed|null
*/
function get_author_id(){
return $this->get_mapped_property('author_id');
function get_url() {
return $this->get_mapped_property( 'url' );
}
/**
* @return mixed|null
* Return the item ID
*
* @return integer
*/
function get_author_name(){
return $this->get_mapped_property('author_name');
function get_id() {
return $this->get_mapped_property( 'id' );
}
/**
* @return mixed|null
* Return the item title
*
* @return string
*/
function get_url(){
return $this->get_mapped_property('url');
function get_title() {
return $this->get_mapped_property( 'title' );
}
/**
* Return the item ID
*
* @return integer
*/
function get_id() {
return $this->get_mapped_property('id');
}
/**
* Return the item title
*
* @return string
*/
function get_title() {
return $this->get_mapped_property('title');
}
/**
* Return the item order type
*
* @return string
*/
function get_order() {
return $this->get_mapped_property( 'order' );
}
/**
* Return the item order type
*
* @return string
*/
function get_order() {
return $this->get_mapped_property('order');
}
/**
* Return the parent ID
*
* @return integer
*/
function get_parent() {
return $this->get_mapped_property( 'parent' );
}
/**
* Return the parent ID
*
* @return integer
*/
function get_parent() {
return $this->get_mapped_property('parent');
}
/**
* Return the item description
*
* @return string
*/
function get_description() {
return $this->get_mapped_property( 'description' );
}
/**
* Return the item description
*
* @return string
*/
function get_description() {
return $this->get_mapped_property('description');
}
/**
*
* {@inheritDoc}
* @see \Tainacan\Entities\Entity::get_db_identifier()
*/
public function get_db_identifier() {
return $this->get_mapped_property('collection_id');
}
/**
* Use especial Item capabilities
* {@inheritDoc}
* @see \Tainacan\Entities\Entity::get_capabilities()
*/
public function get_capabilities() {
return $this->get_collection()->get_items_capabilities();
}
/**
* Define the title
*
* @param [string] $value
* @return void
*/
function set_title($value) {
$this->set_mapped_property('title', $value);
}
/**
*
* {@inheritDoc}
* @see \Tainacan\Entities\Entity::get_db_identifier()
*/
public function get_db_identifier() {
return $this->get_mapped_property( 'collection_id' );
}
/**
* Define the order type
*
* @param [string] $value
* @return void
*/
function set_order($value) {
$this->set_mapped_property('order', $value);
}
/**
* Use especial Item capabilities
* {@inheritDoc}
*
* @see \Tainacan\Entities\Entity::get_capabilities()
*/
public function get_capabilities() {
return $this->get_collection()->get_items_capabilities();
}
/**
* Define the parent ID
*
* @param [integer] $value
* @return void
*/
function set_parent($value) {
$this->set_mapped_property('parent', $value);
}
/**
* Define the title
*
* @param [string] $value
*
* @return void
*/
function set_title( $value ) {
$this->set_mapped_property( 'title', $value );
}
/**
* Define the description
*
* @param [string] $value
* @return void
*/
function set_description($value) {
$this->set_mapped_property('description', $value);
}
/**
* Define the order type
*
* @param [string] $value
*
* @return void
*/
function set_order( $value ) {
$this->set_mapped_property( 'order', $value );
}
/**
* Return a List of ItemMetadata objects
*
* It will return all fields associeated with the collection this item is part of.
*
* If the item already has a value for any of the fields, it will be available.
*
* @return array Array of ItemMetadata objects
*/
function get_fields() {
global $Tainacan_Item_Metadata;
return $Tainacan_Item_Metadata->fetch($this, 'OBJECT');
/**
* Define the parent ID
*
* @param [integer] $value
*
* @return void
*/
function set_parent( $value ) {
$this->set_mapped_property( 'parent', $value );
}
}
/**
* Define the description
*
* @param [string] $value
*
* @return void
*/
function set_description( $value ) {
$this->set_mapped_property( 'description', $value );
}
/**
* set meta cap object
*/
protected function set_cap() {
$item_collection = $this->get_collection();
if ($item_collection) {
$this->cap = $item_collection->get_items_capabilities();
}
}
/**
* Return a List of ItemMetadata objects
*
* It will return all fields associeated with the collection this item is part of.
*
* If the item already has a value for any of the fields, it will be available.
*
* @return array Array of ItemMetadata objects
*/
function get_fields() {
$Tainacan_Item_Metadata = \Tainacan\Repositories\Item_Metadata::getInstance();
/**
*
* {@inheritDoc}
* @see \Tainacan\Entities\Entity::validate()
*/
function validate(){
if ( !in_array($this->get_status(), apply_filters('tainacan-status-require-validation', ['publish','future','private'])) )
return true;
if( parent::validate() ){
$arrayItemMetadata = $this->get_fields();
if( $arrayItemMetadata ){
foreach ( $arrayItemMetadata as $itemMetadata ) {
return $Tainacan_Item_Metadata->fetch( $this, 'OBJECT' );
// avoid core fields to re-validate
$pos = strpos($itemMetadata->get_field()->get_field_type(), 'Core');
if( $pos !== false ){
continue;
}
}
if( !$itemMetadata->validate() ){
$errors = $itemMetadata->get_errors();
$this->add_error( $itemMetadata->get_field()->get_name(), $errors );
return false;
}
}
}
return true;
}
return false;
}
/**
* set meta cap object
*/
protected function set_cap() {
$item_collection = $this->get_collection();
if ( $item_collection ) {
$this->cap = $item_collection->get_items_capabilities();
}
}
/**
* {@inheritDoc}
* @see \Tainacan\Entities\Entity::validate()
*/
public function validate_core_fields(){
if ( !in_array($this->get_status(), apply_filters('tainacan-status-require-validation', ['publish','future','private'])) )
return true;
/**
*
* {@inheritDoc}
* @see \Tainacan\Entities\Entity::validate()
*/
function validate() {
return parent::validate();
}
if ( ! in_array( $this->get_status(), apply_filters( 'tainacan-status-require-validation', [
'publish',
'future',
'private'
] ) ) ) {
return true;
}
if ( parent::validate() ) {
$arrayItemMetadata = $this->get_fields();
if ( $arrayItemMetadata ) {
foreach ( $arrayItemMetadata as $itemMetadata ) {
// avoid core fields to re-validate
$pos = strpos( $itemMetadata->get_field()->get_field_type(), 'Core' );
if ( $pos !== false ) {
continue;
}
if ( ! $itemMetadata->validate() ) {
$errors = $itemMetadata->get_errors();
$this->add_error( $itemMetadata->get_field()->get_name(), $errors );
return false;
}
}
}
return true;
}
return false;
}
/**
* {@inheritDoc}
* @see \Tainacan\Entities\Entity::validate()
*/
public function validate_core_fields() {
if ( ! in_array( $this->get_status(), apply_filters( 'tainacan-status-require-validation', [
'publish',
'future',
'private'
] ) ) ) {
return true;
}
return parent::validate();
}
}

View File

@ -14,7 +14,7 @@ class Log extends Entity {
* @see \Tainacan\Entities\Entity::repository
* @var string
*/
protected $repository = 'Tainacan_Logs';
protected $repository = 'Logs';
public function __construct($which=0) {
parent::__construct($which);
@ -211,7 +211,7 @@ class Log extends Entity {
throw new \Exception('msn or new_value is need to log');
}
global $Tainacan_Logs;
$Tainacan_Logs = \Tainacan\Repositories\Logs::getInstance();
if ($log->validate()) {
return $Tainacan_Logs->insert($log);
@ -226,7 +226,8 @@ class Log extends Entity {
* @see \Tainacan\Repositories\Logs::approve
*/
public function approve() {
global ${$this->repository};
return ${$this->repository}->approve($this);
$repository = $this->get_repository();
return $repository->approve($this);
}
}

View File

@ -29,7 +29,7 @@ class Taxonomy extends Entity {
* @see \Tainacan\Entities\Entity::repository
* @var string
*/
protected $repository = 'Tainacan_Taxonomies';
protected $repository = 'Taxonomies';
public function __toString(){
return 'Hello, my name is '. $this->get_name();
@ -173,4 +173,23 @@ class Taxonomy extends Entity {
function set_allow_insert($value) {
$this->set_mapped_property('allow_insert', $value);
}
/**
* Validate Taxonomy
*
* @return bool
*/
function validate() {
if ( ! in_array( $this->get_status(), apply_filters( 'tainacan-status-require-validation', [
'publish',
'future',
'private'
] ) ) ) {
return true;
}
return parent::validate();
}
}

View File

@ -14,7 +14,7 @@ class Term extends Entity {
* @see \Tainacan\Entities\Entity::repository
* @var string
*/
protected $repository = 'Tainacan_Terms';
protected $repository = 'Terms';
/**
* Term constructor.

View File

@ -0,0 +1,126 @@
<template>
<div>
<span>
<a
class="button"
@click="showForm = !showForm"><b-icon size="is-small" icon="plus"></b-icon>&nbsp;{{ $i18n.get('label_add_new_term') }}</a>
</span>
<div class="columns">
<transition name="fade">
<section
v-if="showForm"
class="column is-one-third"
style="padding-left: 0px;">
<b-field :label="$i18n.get('label_name')">
<b-input v-model="name"></b-input>
</b-field>
<b-field :label="$i18n.get('label_parent_term')">
<b-select
v-model="parent">
<option :value="0" selected> ---{{ $i18n.get('label_parent_term') }}--- </option>
<option
v-for="option,index in options"
:key="index"
:value="option.term_id"
v-html="setSpaces( option.level ) + option.name"></option>
</b-select>
</b-field>
<a
class="button is-primary"
@click="save">{{ $i18n.get('save') }}</a>
</section>
</transition>
</div>
</div>
</template>
<script>
import { tainacan as axios } from '../../../js/axios/axios'
export default {
data(){
return {
name: '',
parent: 0,
showForm: false,
field_id: this.field.field.id
}
},
props: {
id: String,
item_id: [Number,String],
field: [Number,String],
taxonomy_id: [Number,String],
value:[ Array, Boolean, Number ],
options: {
type: Array
}
},
methods: {
setSpaces( level ){
let result = '';
let space = '&nbsp;&nbsp;'
for(let i = 0;i < level; i++)
result += space;
return result;
},
save(){
if( this.name.trim() === ''){
this.$toast.open({
duration: 2000,
message: this.$i18n.get('info_name_is_required'),
position: 'is-bottom',
type: 'is-danger'
})
} else {
const instance = this;
axios.post(`/taxonomy/${this.taxonomy_id}/terms`, {
name: this.name,
parent: this.parent
})
.then( res => {
instance.name = '';
instance.parent = 0;
if( res.data && res.data.term_id || res.term_id ){
let term_id = ( res.term_id ) ? res.term_id : res.data.term_id;
let val = this.value;
if( !Array.isArray( val ) && this.field.field.multiple === 'no' ){
axios.patch(`/item/${this.item_id}/metadata/${this.field_id}`, {
values: term_id,
}).then( res => {
instance.$emit('newTerm', term_id);
})
} else {
val = ( val ) ? val : [];
val.push( term_id );
axios.patch(`/item/${this.item_id}/metadata/${this.field_id}`, {
values: val,
}).then( res => {
instance.$emit('newTerm', val);
})
}
}
});
}
}
}
}
</script>
<style scoped>
button{
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
}
</style>

View File

@ -0,0 +1,144 @@
<template>
<div>
<component
:is="getComponent()"
v-model="valueComponent"
:allowNew="allowNew"
:terms="terms"
:options="getOptions(0)"></component>
<add-new-term
class="add-new-term"
v-if="getComponent() !== 'tainacan-category-tag-input' && allowNew"
:taxonomy_id="taxonomy"
:field="field"
:item_id="field.item.id"
:value="valueComponent"
:options="getOptions(0)"
@newTerm="reload"></add-new-term>
</div>
</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 AddNewTerm from './AddNewTerm.vue'
export default {
created(){
let field_type_options = this.field.field.field_type_options;
this.component = ( field_type_options && field_type_options.input_type )
? this.field.field.field_type_options.input_type : this.componentAttribute
this.collectionId = this.field.field.collection_id;
this.taxonomy = field_type_options.taxonomy_id;
if( field_type_options && field_type_options.allow_new_terms ){
this.allowNew = field_type_options.allow_new_terms === 'yes'
}
this.getTermsFromTaxonomy();
this.getTermsId();
},
components: {
TainacanCategoryRadio,
TainacanCategoryCheckbox,
TainacanCategoryTagInput,
TainacanCategorySelectbox,
AddNewTerm
},
data(){
return {
valueComponent: null,
component: '',
collectionId: '',
taxonomy: '',
terms:[], // object with names
allowNew: false
}
},
watch: {
valueComponent( val ){
this.valueComponent = val;
this.$emit('input', val);
this.$emit('blur');
}
},
props: {
field: {
type: Object
},
componentAttribute: {
type: String
},
value: [ Number, String, Array,Object ],
id: ''
},
methods: {
getComponent(){
if( this.field.field
&& this.field.field.field_type_options && this.field.field.field_type_options.input_type ){
return this.field.field.field_type_options.input_type;
}
},
getTermsFromTaxonomy(){
axios.get('/taxonomy/' + this.taxonomy + '/terms?hideempty=0' ).then( res => {
for (let item of res.data) {
this.terms.push( item );
}
})
.catch(error => {
console.log(error);
});
},
getOptions( parent, level = 0 ){ // retrieve only ids
let result = [];
if ( this.terms ){
for( let term of this.terms ){
if( term.parent == parent ){
term['level'] = level;
result.push( term );
const levelTerm = level + 1;
const children = this.getOptions( term.term_id, levelTerm);
result = result.concat( children );
}
}
}
return result;
},
getTermsId(){
let values = [];
if( this.value && this.value.length > 0){
for( let term of this.value ){
if( term && term.term_id)
values.push(term.term_id);
}
}
if( values.length > 0 && this.field.field){
this.valueComponent = ( this.field.field && this.field.field.multiple === 'no' ) ? values[0] : values
}
},
onInput($event) {
this.inputValue = $event;
this.$emit('input', this.inputValue);
this.$emit('blur');
},
reload( val ){
this.valueComponent = val;
this.terms = [];
this.getTermsFromTaxonomy();
this.getTermsId();
}
}
}
</script>
<style scoped>
.add-new-term{
margin-top: 15px;
margin-bottom: 30px;
}
</style>

View File

@ -0,0 +1,53 @@
<template>
<div>
<div v-for="option,index in options">
<b-checkbox
:id="id"
:style="{ paddingLeft: (option.level * 30) + 'px' }"
:key="index"
v-model="checked"
@input="onChecked(option)"
:native-value="option.term_id"
border>
{{ option.name }}
</b-checkbox>
<br>
</div>
</div>
</template>
<script>
export default {
created(){
if( this.value && this.value.length > 0)
this.checked = this.value;
},
data(){
return {
checked: []
}
},
watch: {
value( val ){
this.checked = val;
}
},
props: {
options: {
type: Array
},
value: [ Number, String, Array ]
},
methods: {
onChecked(option) {
this.$emit('blur');
this.onInput(this.checked)
},
onInput($event) {
this.inputValue = $event;
this.$emit('input', this.inputValue);
}
}
}
</script>

View File

@ -0,0 +1,49 @@
<template>
<div>
<div v-for="option,index in options">
<b-radio
:id="id"
:style="{ paddingLeft: (option.level * 30) + 'px' }"
:key="index"
v-model="checked"
@input="onChecked(option)"
:native-value="option.term_id"
border>
{{ option.name }}
</b-radio>
<br>
</div>
</div>
</template>
<script>
export default {
data(){
return {
checked: ( this.value ) ? this.value : ''
}
},
watch: {
value( val ){
this.checked = val;
}
},
props: {
options: {
type: Array
},
value: [ Number, String, Array ]
},
methods: {
onChecked(option) {
this.$emit('blur');
this.onInput(this.checked)
},
onInput($event) {
this.inputValue = $event;
this.$emit('input', this.inputValue);
}
}
}
</script>

View File

@ -0,0 +1,59 @@
<template>
<div>
<div class="block">
<b-select
:id="id"
v-model="selected"
@input="emitChange()"
:placeholder="$i18n.get('label_select_category')" expanded>
<option
v-for="option,index in options"
:key="index"
:value="option.term_id"
v-html="setSpaces( option.level ) + option.name"></option>
</b-select>
</div>
</div>
</template>
<script>
export default {
created(){
if( this.value )
this.selected = this.value;
},
data(){
return {
selected: ''
}
},
watch: {
value( val ){
this.selected = val;
}
},
props: {
id: String,
options: {
type: Array
},
value: [ Number, String, Array ]
},
methods: {
emitChange() {
this.$emit('input', this.selected);
this.$emit('blur');
},
setSpaces( level ){
let result = '';
let space = '&nbsp;&nbsp;'
for(let i = 0;i < level; i++)
result += space;
return result;
}
}
}
</script>

View File

@ -0,0 +1,81 @@
<template>
<div class="block">
<b-taginput
size="is-small"
rounded
icon="magnify"
:allowNew="allowNew"
@input="emitChange"
v-model="selected"
:data="labels"
field="label"
autocomplete
@typing="search">
</b-taginput>
</div>
</template>
<script>
export default {
data(){
return {
selected: [],
labels: []
}
},
watch: {
terms( val ){
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.term_id})
}
}
},
selectedValues(){
if( this.value && this.value.length > 0 && this.selected.length === 0){
let result = this.terms.filter( ( item ) => {
let id = item.term_id;
return ( this.value.indexOf( id ) >= 0 )
});
let selected = [];
for( let term of result){
selected.push({label: term.name, value: term.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

@ -2,10 +2,17 @@
<section
v-if="isReady"
:listen="setError">
<b-field :label="$i18n.get('label_select_category')"
<b-field :addons="false"
:type="taxonomyType"
:message="taxonomyMessage"
>
<label class="label">
{{ $i18n.get('label_select_category') }}<span :class="taxonomyType" >&nbsp;*&nbsp;</span>
<help-button
:title="$i18n.getHelperTitle('tainacan-category', 'taxonomy_id')"
:message="$i18n.getHelperMessage('tainacan-category', 'taxonomy_id')">
</help-button>
</label>
<b-select
name="field_type_options[taxonomy_id]"
placeholder="Select the taxonomy"
@ -23,8 +30,14 @@
</b-select>
</b-field>
<b-field :label="$i18n.get('label_select_category_input_type')">
<b-field :addons="false">
<label class="label">
{{ $i18n.get('label_select_category_input_type') }}
<help-button
:title="$i18n.getHelperTitle('tainacan-category', 'input_type')"
:message="$i18n.getHelperMessage('tainacan-category', 'input_type')">
</help-button>
</label>
<b-select
v-if="listInputType"
name="field_type_options[component_type]"
@ -56,15 +69,21 @@
</b-field>
<b-field :label="$i18n.get('label_category_allow_new_terms')">
<b-field :addons="false">
<label class="label">
{{ $i18n.get('label_category_allow_new_terms') }}
<help-button
:title="$i18n.getHelperTitle('tainacan-category', 'allow_new_terms')"
:message="$i18n.getHelperMessage('tainacan-category', 'allow_new_terms')">
</help-button>
</label>
<div class="block">
<b-switch v-model="allow_new_terms"
type="is-primary"
<b-checkbox v-model="allow_new_terms"
@input="emitValues()"
true-value="yes"
false-value="no">
{{ labelNewTerms() }}
</b-switch>
{{ labelNewTerms() }}
</b-checkbox>
</div>
</b-field>
@ -73,8 +92,10 @@
<script>
import { tainacan as axios } from '../../../js/axios/axios';
import BCheckbox from "../../../../node_modules/buefy/src/components/checkbox/Checkbox.vue";
export default {
components: {BCheckbox},
props: {
value: [ String, Object, Array ],
field: [ String, Object ],
@ -114,7 +135,7 @@
},
setError(){
if( this.errors && this.errors.taxonomy_id !== '' ){
this.taxonomyType = 'is-warning';
this.taxonomyType = 'is-danger';
this.taxonomyMessage = this.errors.taxonomy_id;
} else {
this.taxonomyType = '';

View File

@ -12,15 +12,35 @@ class Category extends Field_Type {
function __construct(){
// call field type constructor
parent::__construct();
parent::set_primitive_type('term');
$this->set_primitive_type('term');
$this->set_default_options([
'allow_new_terms' => false
]);
$this->form_component = 'tainacan-form-category';
$this->set_form_component('tainacan-form-category');
// TODO: Set component depending on options. If multiple is checkbox. if single, select. etc.
$this->component = 'tainacan-category';
$this->set_component('tainacan-category');
}
/**
* @inheritdoc
*/
public function get_form_labels(){
return [
'taxonomy_id' => [
'title' => __( 'Collection Related', 'tainacan' ),
'description' => __( 'Select the collection to fetch items', 'tainacan' ),
],
'input_type' => [
'title' => __( 'Input type', 'tainacan' ),
'description' => __( 'The html type of the terms list ', 'tainacan' ),
],
'allow_new_terms' => [
'title' => __( 'Allow new terms', 'tainacan' ),
'description' => __( 'Allow create new terms', 'tainacan' ),
]
];
}
/**
@ -29,7 +49,7 @@ class Category extends Field_Type {
*/
public function render( $itemMetadata ){
$options = ( isset( $this->options['options'] ) ) ? $this->options['options'] : '';
$options = ( isset( $this->get_options()['options'] ) ) ? $this->get_options()['options'] : '';
return '<tainacan-selectbox
options="' . $options . '"
field_id ="'.$itemMetadata->get_field()->get_id().'"
@ -46,7 +66,7 @@ class Category extends Field_Type {
if (empty($this->get_option('taxonomy_id')))
return ['taxonomy_id' => __('Please select a category', 'tainacan')];
global $Tainacan_Fields;
$Tainacan_Fields = \Tainacan\Repositories\Fields::getInstance();
$category_fields = $Tainacan_Fields->fetch([
'collection_id' => $field->get_collection_id(),

View File

@ -1,65 +0,0 @@
<template>
<div class="block">
<div
v-for="option,index in getOptions"
class="field">
<b-checkbox
:id="id"
v-model="checked"
:native-value="option"
>{{ option }}</b-checkbox>
</div>
</div>
</template>
<script>
export default {
data(){
return {
checked:[]
}
},
created(){
if(this.value instanceof Array)
this.checked = this.value;
},
props: {
field: {
type: Object
},
options: {
type: String
},
value: [String, Number, Array],
id: ''
},
watch: {
checked: function(val){
this.checked = val;
this.onChecked();
}
},
computed: {
getOptions(){
if ( this.options && this.options !== '' ){
return this.options.split("\n");
}
else if (this.field) {
const fields = this.field.field.field_type_options.options;
return ( fields ) ? fields.split("\n") : [];
}
return [];
}
},
methods: {
onChecked() {
this.$emit('blur');
this.onInput(this.checked)
},
onInput($event) {
this.inputValue = $event;
this.$emit('input', this.inputValue);
}
}
}
</script>

View File

@ -1,32 +0,0 @@
<?php
namespace Tainacan\Field_Types;
defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
/**
* Class TainacanFieldType
*/
class Checkbox extends Field_Type {
function __construct(){
// call field type constructor
parent::__construct();
parent::set_primitive_type('date');
$this->component = 'tainacan-checkbox';
}
/**
* @param $itemMetadata \Tainacan\Entities\Item_Metadata_Entity The instace of the entity itemMetadata
* @return string
*/
public function render( $itemMetadata ){
$options = $this->get_option('options');
return '<tainacan-checkbox options="'.$options.'"
field_id ="'.$itemMetadata->get_field()->get_id().'"
item_id="'.$itemMetadata->get_item()->get_id().'"
value=\''.json_encode( $itemMetadata->get_value() ).'\'
name="'.$itemMetadata->get_field()->get_name().'"></tainacan-checkbox>';
}
}

View File

@ -12,10 +12,10 @@ class Core_Description extends Field_Type {
function __construct(){
// call field type constructor
parent::__construct();
parent::set_primitive_type('string');
$this->core = true;
$this->related_mapped_prop = 'description';
$this->component = 'tainacan-textarea';
$this->set_primitive_type('string');
$this->set_core(true);
$this->set_related_mapped_prop('description');
$this->set_component('tainacan-textarea');
}
/**

View File

@ -12,10 +12,10 @@ class Core_Title extends Field_Type {
function __construct(){
// call field type constructor
parent::__construct();
parent::set_primitive_type('string');
$this->core = true;
$this->related_mapped_prop = 'title';
$this->component = 'tainacan-text';
$this->set_primitive_type('string');
$this->set_core(true);
$this->set_related_mapped_prop('title');
$this->set_component('tainacan-text');
}
/**

View File

@ -2,15 +2,14 @@
<b-datepicker
:id="id"
v-model="dateValue"
@blur="onBlur"
@input="onInput($event)"></b-datepicker>
</template>
<script>
export default {
created(){
if( this.field && this.field.value ){
this.inputValue = this.field.value
if( this.value ){
this.inputValue = this.value
}
},
data() {
@ -26,12 +25,13 @@
value: [String, Number, Array],
},
methods: {
onBlur() {
this.$emit('blur');
},
onInput($event) {
this.dateValue = $event;
this.$emit('input', this.dateValue);
let date_init = this.dateValue.getUTCFullYear() + '-' +
('00' + (this.dateValue.getUTCMonth() + 1)).slice(-2) + '-' +
('00' + this.dateValue.getUTCDate()).slice(-2);
this.$emit('input', date_init);
this.$emit('blur');
}
}
}

View File

@ -13,8 +13,8 @@ class Date extends Field_Type {
function __construct(){
// call field type constructor
parent::__construct();
parent::set_primitive_type('date');
$this->component = 'tainacan-date';
$this->set_primitive_type('date');
$this->set_component('tainacan-date');
}
/**

View File

@ -24,45 +24,45 @@ abstract class Field_Type {
private $primitive_type;
/**
* Array of options spececific to this field type. Stored in field_type_options property of the Field object
* @var Array
* Array of options specific to this field type. Stored in field_type_options property of the Field object
* @var array
*/
public $options = [];
private $options = [];
/**
* The default values for the field type options array
* @var Array
* @var array
*/
public $default_options = [];
private $default_options = [];
public $errors;
private $errors;
/**
* Indicates wether this is a core Field Type or not
* Indicates whether this is a core Field Type or not
*
* Core field types are used by Title and description fields. These fields:
* * Can only be used once, they belong to the repository and can not be deleted
* * Its values are saved in th wp_post table, and not as post_meta
*
*/
public $core = false;
private $core = false;
/**
* Used by core field types to indicate where it should be saved
*/
public $related_mapped_prop = false;
private $related_mapped_prop = false;
/**
* The name of the web component used by this field type
* @var string
*/
public $component;
private $component;
/**
* The name of the web component used by the Form
* @var bool | string
*/
public $form_component = false;
private $form_component = false;
abstract function render( $itemMetadata );
@ -73,6 +73,14 @@ abstract class Field_Type {
public function validate(\Tainacan\Entities\Item_Metadata_Entity $item_metadata) {
return true;
}
public function get_related_mapped_prop(){
return $this->related_mapped_prop;
}
public function set_related_mapped_prop($related_mapped_prop){
$this->related_mapped_prop = $related_mapped_prop;
}
public function get_validation_errors() {
return [];
@ -94,15 +102,23 @@ abstract class Field_Type {
return $this->component;
}
public function set_component($component){
$this->component = $component;
}
public function get_form_component() {
return $this->form_component;
}
public function set_form_component($form_component){
$this->form_component = $form_component;
}
/**
* @param $options
*/
public function set_options( $options ){
$this->options = ( is_array( $options ) ) ? $options : unserialize( $options );
$this->options = ( is_array( $options ) ) ? $options : (!is_array(unserialize( $options )) ? [] : unserialize( $options ));
}
public function set_default_options(Array $options) {
@ -112,7 +128,7 @@ abstract class Field_Type {
/**
* Gets the options for this field types, including default values for options
* that were not set yet.
* @return Array Fielt type options
* @return array Field type options
*/
public function get_options() {
return array_merge($this->default_options, $this->options);
@ -131,6 +147,12 @@ abstract class Field_Type {
return isset($options[$key]) ? $options[$key] : '';
}
/**
* allow i18n from messages
*/
public function get_form_labels(){
return [];
}
/**
* generate the fields for this field type
*/
@ -140,12 +162,15 @@ abstract class Field_Type {
public function __toArray(){
$attributes = [];
$attributes['className'] = get_class($this);
$attributes['core'] = $this->core;
$attributes['component'] = $this->get_component();
$attributes['primitive_type'] = $this->get_primitive_type();
$attributes['form_component'] = $this->get_form_component();
$attributes['errors'] = $this->get_errors();
$attributes['related_mapped_prop'] = $this->get_related_mapped_prop();
$attributes['options'] = $this->get_options();
$attributes['className'] = get_class($this);
$attributes['core'] = $this->get_core();
$attributes['component'] = $this->get_component();
$attributes['primitive_type'] = $this->get_primitive_type();
$attributes['form_component'] = $this->get_form_component();
return $attributes;
@ -163,4 +188,14 @@ abstract class Field_Type {
return true;
}
/**
* @return mixed
*/
public function get_core() {
return $this->core;
}
public function set_core($core){
$this->core = $core;
}
}

View File

@ -3,6 +3,7 @@
:id="id"
type="number"
:value="inputValue"
step="0.01"
@blur="onBlur"
@change="onBlur"
@input="onInput($event)"></b-input>
@ -11,8 +12,8 @@
<script>
export default {
created(){
if( this.field && this.field.value ){
this.inputValue = this.field.value
if( this.value ){
this.inputValue = this.value
}
},
data() {

View File

@ -12,8 +12,8 @@ class Numeric extends Field_Type {
function __construct(){
// call field type constructor
parent::__construct();
parent::set_primitive_type('float');
$this->component = 'tainacan-numeric';
$this->set_primitive_type('float');
$this->set_component('tainacan-numeric');
}
/**

View File

@ -1,54 +0,0 @@
<template>
<div>
<b-radio
:id="id"
v-for="option,index in getOptions"
:key="index"
v-model="checked"
@input="onChecked(option)"
:label="option"
:native-value="option"
border>{{ option }}</b-radio>
</div>
</template>
<script>
export default {
data(){
return {
checked:''
}
},
props: {
field: {
type: Object
},
options: {
type: String
},
id: ''
},
computed: {
getOptions(){
if ( this.options && this.options !== '' ){
return this.options.split("\n");
}
else if (this.field) {
const fields = this.field.field.field_type_options.options;
return ( fields ) ? fields.split("\n") : [];
}
return [];
}
},
methods: {
onChecked(option) {
this.$emit('blur');
this.onInput(this.checked)
},
onInput($event) {
this.inputValue = $event;
this.$emit('input', this.inputValue);
}
}
}
</script>

View File

@ -1,50 +0,0 @@
<?php
namespace Tainacan\Field_Types;
defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
/**
* Class TainacanFieldType
*/
class Radio extends Field_Type {
function __construct(){
// call field type constructor
parent::__construct();
parent::set_primitive_type('');
$this->component = 'tainacan-radio';
}
/**
* @param $itemMetadata \Tainacan\Entities\Item_Metadata_Entity The instace of the entity itemMetadata
* @return string
*/
public function render( $itemMetadata ){
$options = $this->get_option('options');
return '<tainacan-radio
options="' . $options . '"
field_id ="'.$itemMetadata->get_field()->get_id().'"
item_id="'.$itemMetadata->get_item()->get_id().'"
value=\''.json_encode( $itemMetadata->get_value() ).'\'
options="'.$options.'" name="'.$itemMetadata->get_field()->get_name().'"></tainacan-radio>';
}
/**
* generate the fields for this field type
*/
public function form(){
?>
<tr>
<td>
<label><?php echo __('Options','tainacan'); ?></label><br/>
<small><?php echo __('Insert the options, separate by lines for the field value','tainacan'); ?></small>
</td>
<td>
<textarea name="field_type_options[options]"><?php echo $this->get_option('options'); ?></textarea>
</td>
</tr>
<?php
}
}

View File

@ -1,10 +1,17 @@
<template>
<section>
<b-field
:label="$i18n.get('label_collection_related')"
:addons="false"
:listen="setError"
:type="collectionType"
:message="collectionMessage">
<label class="label">
{{ $i18n.get('label_collection_related') }}<span :class="collectionType" >&nbsp;*&nbsp;</span>
<help-button
:title="$i18n.getHelperTitle('tainacan-relationship', 'collection_id')"
:message="$i18n.getHelperMessage('tainacan-relationship', 'collection_id')">
</help-button>
</label>
<b-select
name="field_type_relationship[collection_id]"
placeholder="Select the collection to fetch items"
@ -28,7 +35,14 @@
class="loading-spinner"></div>
<b-field
v-if="hasFields"
:label="$i18n.get('label_fields_for_search')">
:addons="false">
<label class="label">
{{ $i18n.get('label_fields_for_search') }}
<help-button
:title="$i18n.getHelperTitle('tainacan-relationship', 'search')"
:message="$i18n.getHelperMessage('tainacan-relationship', 'search')">
</help-button>
</label>
<div class="block">
<div
v-for="option in fields"
@ -46,15 +60,21 @@
</transition>
<b-field :label="$i18n.get('label_allow_repeated_items')">
<b-field :addons="false">
<label class="label">
{{ $i18n.get('label_allow_repeated_items') }}
<help-button
:title="$i18n.getHelperTitle('tainacan-relationship', 'repeated')"
:message="$i18n.getHelperMessage('tainacan-relationship', 'repeated')">
</help-button>
</label>
<div class="block">
<b-switch v-model="modelRepeated"
type="is-primary"
<b-checkbox v-model="modelRepeated"
@input="emitValues()"
true-value="yes"
false-value="no">
{{ labelRepeated() }}
</b-switch>
{{ labelRepeated() }}
</b-checkbox>
</div>
</b-field>
</section>
@ -122,7 +142,7 @@
computed: {
setError(){
if( this.errors && this.errors.collection_id !== '' ){
this.collectionType = 'is-warning';
this.collectionType = 'is-danger';
this.collectionMessage = this.errors.collection_id;
} else {
this.collectionType = '';

View File

@ -75,6 +75,10 @@
this.$emit('blur');
},
search(query){
if( this.selected.length > 0 && this.field.field.multiple === 'no'){
return '';
}
if (query !== '') {
this.loading = true;
this.options = [];

View File

@ -14,9 +14,29 @@ class Relationship extends Field_Type {
function __construct(){
// call field type constructor
parent::__construct();
parent::set_primitive_type('item');
$this->component = 'tainacan-relationship';
$this->form_component = 'tainacan-form-relationship';
$this->set_primitive_type('item');
$this->set_component('tainacan-relationship');
$this->set_form_component('tainacan-form-relationship');
}
/**
* @inheritdoc
*/
public function get_form_labels(){
return [
'collection_id' => [
'title' => __( 'Collection Related', 'tainacan' ),
'description' => __( 'Select the collection to fetch items', 'tainacan' ),
],
'search' => [
'title' => __( 'Fields for search', 'tainacan' ),
'description' => __( 'Select the fields to help the search', 'tainacan' ),
],
'repeated' => [
'title' =>__( 'Allow repeated items', 'tainacan' ),
'description' => __( 'Allow different items with the same item selected', 'tainacan' ),
]
];
}
/**
@ -26,7 +46,7 @@ class Relationship extends Field_Type {
public function render( $itemMetadata ){
return '<tainacan-relationship
collection_id="' . $this->options['collection_id'] . '"
collection_id="' . $this->get_options()['collection_id'] . '"
field_id ="'.$itemMetadata->get_field()->get_id().'"
item_id="'.$itemMetadata->get_item()->get_id().'"
value=\''.json_encode( $itemMetadata->get_value() ).'\'

View File

@ -1,10 +1,17 @@
<template>
<section
:listen="setError">
<b-field :label="$i18n.get('label_options')"
<b-field :addons="false"
:type="optionType"
:message="optionMessage"
>
<label class="label">
{{ $i18n.getHelperTitle('tainacan-selectbox', 'options') }}<span :class="optionType" >&nbsp;*&nbsp;</span>
<help-button
:title="$i18n.getHelperTitle('tainacan-selectbox', 'options')"
:message="$i18n.getHelperMessage('tainacan-selectbox', 'options')">
</help-button>
</label>
<b-taginput
v-model="options"
@input="emitValues()"
@ -38,7 +45,7 @@
computed: {
setError(){
if( this.errors && this.errors.options !== '' ){
this.optionType = 'is-warning';
this.optionType = 'is-danger';
this.optionMessage = this.errors.options;
} else {
this.optionType = '';

View File

@ -18,8 +18,8 @@
export default {
created(){
if( this.field && this.field.value ){
this.selected = this.field.value
if( this.value && this.value ){
this.selected = this.value
}
},
data(){

View File

@ -12,11 +12,22 @@ class Selectbox extends Field_Type {
function __construct(){
// call field type constructor
parent::__construct();
parent::set_primitive_type('string');
$this->component = 'tainacan-selectbox';
$this->form_component = 'tainacan-form-selectbox';
$this->set_primitive_type('string');
$this->set_component('tainacan-selectbox');
$this->set_form_component('tainacan-form-selectbox');
}
/**
* @inheritdoc
*/
public function get_form_labels(){
return [
'options' => [
'title' => __( 'Options', 'tainacan' ),
'description' => __( 'Create the options for the select, hit enter to add new one', 'tainacan' ),
]
];
}
/**
* @param $itemMetadata \Tainacan\Entities\Item_Metadata_Entity The instace of the entity itemMetadata
* @return string

View File

@ -1,8 +1,14 @@
<template>
<b-field :label="field.field.name"
:message="getErrorMessage"
:type="fieldTypeMessage">
<div>
<b-field
:addons="false"
:label="field.field.name"
:message="getErrorMessage"
:type="fieldTypeMessage">
<help-button
:title="field.field.name"
:message="field.field.description">
</help-button>
<div v-if="isTextInputComponent( field.field.field_type_object.component )">
<component :id="field.field.field_type_object.component + '-' + field.field.slug" :is="field.field.field_type_object.component" v-model="inputs[0]" :field="field" @blur="changeValue()"></component>
<div v-if="field.field.multiple == 'yes'">
<div v-if="index > 0" v-for="(input, index) in inputsList " v-bind:key="index" class="multiple-inputs">
@ -11,6 +17,12 @@
<a class="button" @click="addInput">+</a>
</div>
</div>
<div v-else>
<component
:id="field.field.field_type_object.component + '-' + field.field.slug"
:is="field.field.field_type_object.component" v-model="inputs"
:field="field" @blur="changeValue()"></component>
</div>
</b-field>
</template>
@ -69,6 +81,10 @@
removeInput(index) {
this.inputs.splice(index, 1);
this.changeValue();
},
isTextInputComponent( component ){
let array = ['tainacan-relationship','tainacan-category'];
return !( array.indexOf( component ) >= 0 );
}
}
}

View File

@ -9,8 +9,8 @@
<script>
export default {
created(){
if( this.field && this.field.value ){
this.inputValue = this.field.value
if( this.value ){
this.inputValue = this.value
}
},
data() {

View File

@ -13,7 +13,7 @@ class Text extends Field_Type {
// call field type constructor
parent::__construct();
parent::set_primitive_type('string');
$this->component = 'tainacan-text';
parent::set_component('tainacan-text');
}
/**

View File

@ -10,8 +10,8 @@
<script>
export default {
created(){
if( this.field && this.field.value ){
this.inputValue = this.field.value
if( this.value ){
this.inputValue = this.value
}
},
data() {

View File

@ -12,8 +12,8 @@ class Textarea extends Field_Type {
function __construct(){
// call field type constructor
parent::__construct();
parent::set_primitive_type('string');
$this->component = 'tainacan-textarea';
$this->set_primitive_type('string');
$this->set_component('tainacan-textarea');
}
/**

View File

@ -10,18 +10,51 @@
:loading="loading"
field="label"
@select="option => setResults(option) ">
<template slot-scope="props">
<div class="media">
<div class="media-left" v-if="props.option.img">
<img width="32" :src="`${props.option.img}`">
</div>
<div class="media-content">
{{ props.option.label }}
</div>
</div>
</template>
</b-autocomplete>
<br>
<div class="field has-text-centered">
<b-tag v-if="results !== ''"
type="is-primary"
size="is-small"
closable
@close="clearSearch()">
{{ results }}
</b-tag>
</div>
</div>
</template>
<script>
import { tainacan as axios } from '../../../js/axios/axios'
import { filter_type_mixin } from '../filter-types-mixin'
export default {
created(){
this.collection = ( this.collection_id ) ? this.collection_id : this.filter.collection_id;
this.field = ( this.field_id ) ? this.field_id : this.filter.collection_id;
this.type = ( this.filter_type ) ? this.filter_type : this.filter.field.field_type;
this.field = ( this.field_id ) ? this.field_id : this.filter.field.field_id;
const vm = this;
axios.get('/collection/' + this.collection + '/fields/' + this.field )
.then( res => {
let result = res.data;
if( result && result.field_type ){
vm.field_object = result;
vm.type = result.field_type;
vm.selectedValues();
}
})
.catch(error => {
console.log(error);
});
},
data(){
return {
@ -32,18 +65,9 @@
type: '',
collection: '',
field: '',
selected: '',
}
},
props: {
filter: {
type: Object // concentrate all attributes field id and type
},
field_id: [Number], // not required, but overrides the filter field id if is set
collection_id: [Number], // not required, but overrides the filter field id if is set
filter_type: [String], // not required, but overrides the filter field type if is set
id: ''
},
mixins: [filter_type_mixin],
methods: {
setResults(option){
if(!option)
@ -52,77 +76,86 @@
this.onSelect()
},
onSelect(){
let filter = null;
if ( this.type ) {
filter = 'term';
} else {
filter = 'selectbox';
}
this.$emit('input', {
filter: filter,
field_id: ( this.field_id ) ? this.field_id : this.filter.field,
collection_id: ( this.collection_id ) ? this.collection_id : this.filter.collection_id,
filter: 'autocomplete',
field_id: this.field,
collection_id: this.collection,
value: this.results
});
},
search( query ){
let promise = null;
this.options = [];
if ( this.type === 'Tainacan\Field_types\Relationship' ) {
let collectionTarget = ( this.filter && this.filter.field.field_type_options.collection_id ) ?
this.filter.field.field_type_options.collection_id : this.collection_id;
if ( this.type === 'Tainacan\\Field_Types\\Relationship' ) {
let collectionTarget = ( this.field_object && this.field_object.field_type_options.collection_id ) ?
this.field_object.field_type_options.collection_id : this.collection_id;
promise = this.getValuesRelationship( collectionTarget, query );
} else if ( this.type === 'Tainacan\Field_types\Category' ) {
let collectionTarget = ( this.filter && this.filter.field.field_type_options.taxonomy ) ?
this.filter.field.field_type_options.taxonomy : this.taxonomy;
promise = this.getValuesCategory( collectionTarget, query );
} else {
promise = this.getValuesPlainText( this.field, query );
}
promise.then( data => {
this.isLoading = false;
})
.catch( error => {
}).catch( error => {
console.log('error select', error );
this.isLoading = false;
});
},
getValuesPlainText( field_id ){
return axios.get( '/collection/' + this.collection_id + '/fields/' + field_id + '?fetch=all_field_values')
.then( res => {
for (let metadata of res.data) {
let index = this.options.findIndex(itemMetadata => itemMetadata.value === metadata.mvalue);
if( index < 0 ){
this.options.push({ label: metadata.mvalue, value: metadata.mvalue })
}
selectedValues(){
const instance = this;
if ( !this.query || !this.query.metaquery || !Array.isArray( this.query.metaquery ) )
return false;
}
})
.catch(error => {
console.log(error);
});
let index = this.query.metaquery.findIndex(newField => newField.key === this.field );
if ( index >= 0){
let metadata = this.query.metaquery[ index ];
let collectionTarget = ( this.field_object && this.field_object.field_type_options.collection_id ) ?
this.field_object.field_type_options.collection_id : this.collection_id;
if ( this.type === 'Tainacan\\Field_Types\\Relationship' ) {
let query = qs.stringify({ postin: metadata.value });
axios.get('/collection/' + collectionTarget + '/items?' + query)
.then( res => {
for (let item of res.data) {
// instance.selected.push({ label: item.title, value: item.id, img: '' });
console.log(item.title);
instance.results = item.title;
}
})
.catch(error => {
console.log(error);
});
} else {
instance.results = metadata.value;
}
} else {
return false;
}
},
getValuesCategory( taxonomy ){
// TODO: get taxonomy terms
},
getValuesRelationship( collectionTarget, search ){
return axios.get( '/collection/' + collectionTarget + '/items?s=' + search )
.then( res => {
for (let item of res.data) {
this.options.push({ label: item.title, value: item.id })
}
})
.catch(error => {
console.log(error);
});
clearSearch(){
this.results = '';
this.selected = '';
this.$emit('input', {
filter: 'autocomplete',
field_id: this.field,
collection_id: ( this.collection_id ) ? this.collection_id : this.filter.collection_id,
value: ''
});
},
}
}
</script>
</script>
<style scoped>
#profileImage {
width: 32px;
height: 32px;
font-size: 35px;
color: #fff;
text-align: center;
line-height: 150px;
margin: 20px 0;
}
</style>

View File

@ -9,8 +9,8 @@ defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
class Autocomplete extends Filter_Type {
function __construct(){
parent::set_supported_types(['string','item']);
$this->component = 'tainacan-filter-autocomplete';
$this->set_supported_types(['string','item']);
$this->set_component('tainacan-filter-autocomplete');
}
/**

View File

@ -1,17 +1,16 @@
<?php
namespace Tainacan\Filter_Types\Category;
use Tainacan\Filter_Types;
namespace Tainacan\Filter_Types;
defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
/**
* Class TainacanFieldType
*/
class Checkbox extends Filter_Types\Filter_Type {
class CategoryCheckbox extends Filter_Type {
function __construct(){
parent::set_supported_types(['term']);
$this->component = 'tainacan-filter-category-checkbox';
$this->set_supported_types(['term']);
$this->set_component('tainacan-filter-category-checkbox');
}
/**

View File

@ -1,17 +1,16 @@
<?php
namespace Tainacan\Filter_Types\Category;
use Tainacan\Filter_Types;
namespace Tainacan\Filter_Types;
defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
/**
* Class TainacanFieldType
*/
class Selectbox extends Filter_Types\Filter_Type {
class CategorySelectbox extends Filter_Type {
function __construct(){
parent::set_supported_types(['term']);
$this->component = 'tainacan-filter-category-selectbox';
$this->set_supported_types(['term']);
$this->set_component('tainacan-filter-category-selectbox');
}
/**

View File

@ -1,17 +1,16 @@
<?php
namespace Tainacan\Filter_Types\Category;
use Tainacan\Filter_Types;
namespace Tainacan\Filter_Types;
defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
/**
* Class Taginput
*/
class Taginput extends Filter_Types\Filter_Type {
class CategoryTaginput extends Filter_Type {
function __construct(){
parent::set_supported_types(['term']);
$this->component = 'tainacan-filter-category-taginput';
$this->set_supported_types(['term']);
$this->set_component('tainacan-filter-category-taginput');
}
/**

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