Merge pull request #603 from tainacan/feature/573
Feature/573: create terms on submission item
This commit is contained in:
commit
90b8a7e3db
|
@ -5,7 +5,6 @@ namespace Tainacan\API\EndPoints;
|
|||
use \Tainacan\API\REST_Controller;
|
||||
use Tainacan\Repositories;
|
||||
use Tainacan\Entities;
|
||||
use Tainacan\Tests\Collections;
|
||||
|
||||
/**
|
||||
* Represents the Items REST Controller
|
||||
|
@ -38,6 +37,7 @@ class REST_Items_Controller extends REST_Controller {
|
|||
$this->item_metadata = Repositories\Item_Metadata::get_instance();
|
||||
$this->collections_repository = Repositories\Collections::get_instance();
|
||||
$this->metadatum_repository = Repositories\Metadata::get_instance();
|
||||
$this->terms_repository = \Tainacan\Repositories\Terms::get_instance();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -897,11 +897,13 @@ class REST_Items_Controller extends REST_Controller {
|
|||
return $this->item_metadata->suggest( $item_metadata );
|
||||
}
|
||||
else {
|
||||
$this->submission_rollback_new_terms();
|
||||
return new \WP_REST_Response( [
|
||||
'error_message' => __( 'The metadatum does not accept suggestions', 'tainacan' ),
|
||||
], 400 );
|
||||
}
|
||||
} else {
|
||||
$this->submission_rollback_new_terms();
|
||||
return new \WP_REST_Response( [
|
||||
'error_message' => __( 'Please verify, invalid value(s)', 'tainacan' ),
|
||||
'errors' => $item_metadata->get_errors(),
|
||||
|
@ -910,6 +912,43 @@ class REST_Items_Controller extends REST_Controller {
|
|||
}
|
||||
}
|
||||
|
||||
private $new_terms_ids = [];
|
||||
private function submission_process_terms ($value, $taxonomy) {
|
||||
if (is_numeric($value)) return $value;
|
||||
$split_value = explode(">>", $value);
|
||||
if(count($split_value) == 1 ) {
|
||||
$exist = $this->terms_repository->term_exists($split_value[0], $taxonomy, null, true);
|
||||
if ($exist)
|
||||
return $split_value[0];
|
||||
$new_term = new Entities\Term();
|
||||
$new_term->set_taxonomy( $taxonomy->get_db_identifier() );
|
||||
$new_term->set('name', $split_value[0]);
|
||||
if ( $new_term->validate() ) {
|
||||
$new_term = $this->terms_repository->insert( $new_term );
|
||||
$this->new_terms_ids[] = ['term_id' => $new_term->get_term_id(), 'taxonomy' => $new_term->get_taxonomy()];
|
||||
}
|
||||
return $new_term;
|
||||
} else if (count($split_value) == 2 ) {
|
||||
$new_term = new Entities\Term();
|
||||
$new_term->set_taxonomy( $taxonomy->get_db_identifier() );
|
||||
$new_term->set('name', $split_value[1]);
|
||||
$new_term->set('parent', $split_value[0]);
|
||||
if ( $new_term->validate() ) {
|
||||
$new_term = $this->terms_repository->insert( $new_term );
|
||||
$this->new_terms_ids[] = ['term_id' => $new_term->get_term_id(), 'taxonomy' => $new_term->get_taxonomy()];
|
||||
}
|
||||
return $new_term;
|
||||
}
|
||||
return count($split_value) > 1 ? $value : filter_var($value, FILTER_SANITIZE_STRING);
|
||||
}
|
||||
|
||||
private function submission_rollback_new_terms () {
|
||||
foreach($this->new_terms_ids as $term) {
|
||||
$remove_term = new Entities\Term($term['term_id'], $term['taxonomy']);
|
||||
$this->terms_repository->delete( $remove_term, true );
|
||||
}
|
||||
}
|
||||
|
||||
public function submission_item ($request) {
|
||||
$collection_id = $request['collection_id'];
|
||||
$item = json_decode($request->get_body(), true);
|
||||
|
@ -936,7 +975,7 @@ class REST_Items_Controller extends REST_Controller {
|
|||
|
||||
if ( $item->validate() ) {
|
||||
$item = $this->items_repository->insert( $item );
|
||||
$item_id = $item->get_id();
|
||||
|
||||
foreach ( $metadata as $m ) {
|
||||
if ( !isset($m['value']) || $m['value'] == null ) continue;
|
||||
$value = $m['value'];
|
||||
|
@ -988,6 +1027,25 @@ class REST_Items_Controller extends REST_Controller {
|
|||
$parent_meta_id = $item_metadata_child->get_parent_meta_id();
|
||||
}
|
||||
}
|
||||
} else if ($metadatum->get_metadata_type_object()->get_primitive_type() == 'term') {
|
||||
$taxonomy_id = $metadatum->get_metadata_type_object()->get_option( 'taxonomy_id' );
|
||||
$taxonomy = new Entities\Taxonomy( $taxonomy_id );
|
||||
if (is_array($value) == true) {
|
||||
$value = array_map( function($v) use ($taxonomy) {
|
||||
return $this->submission_process_terms($v, $taxonomy);
|
||||
}, $value);
|
||||
} else {
|
||||
$value = $this->submission_process_terms($value, $taxonomy);
|
||||
}
|
||||
if ($item_metadata->is_multiple()) {
|
||||
$item_metadata->set_value( is_array($value) ? $value : [$value] );
|
||||
} else {
|
||||
$item_metadata->set_value( is_array($value) ? implode(' ', $value) : $value);
|
||||
}
|
||||
$item_metadata = $this->submission_item_metadada($item_metadata, $request);
|
||||
if ($item_metadata instanceof \WP_REST_Response) {
|
||||
return $item_metadata;
|
||||
}
|
||||
} else {
|
||||
if (is_array($value) == true) {
|
||||
$value = array_map( function($v) { return is_numeric($v) ? $v : filter_var($v, FILTER_SANITIZE_STRING); }, $value);
|
||||
|
@ -1011,14 +1069,19 @@ class REST_Items_Controller extends REST_Controller {
|
|||
$fake_id = md5(uniqid(mt_rand(), true));
|
||||
$id = $item->get_id();
|
||||
if (set_transient('tnc_transient_submission_' . $fake_id, $id, 300) == true) {
|
||||
set_transient('tnc_transient_submission_' . $fake_id . '_new_terms_ids', $this->new_terms_ids, 300);
|
||||
$response_item = $this->prepare_item_for_response($item, $request);
|
||||
$response_item['id'] = $fake_id;
|
||||
return new \WP_REST_Response($response_item, 201 );
|
||||
} else return new \WP_REST_Response([
|
||||
'error_message' => __('unable create submission ID.', 'tainacan'),
|
||||
], 400);
|
||||
} else {
|
||||
$this->submission_rollback_new_terms();
|
||||
return new \WP_REST_Response([
|
||||
'error_message' => __('unable create submission ID.', 'tainacan'),
|
||||
], 400);
|
||||
}
|
||||
|
||||
} else {
|
||||
$this->submission_rollback_new_terms();
|
||||
return new \WP_REST_Response([
|
||||
'error_message' => __('One or more values are invalid.', 'tainacan'),
|
||||
'errors' => $item->get_errors(),
|
||||
|
@ -1026,6 +1089,7 @@ class REST_Items_Controller extends REST_Controller {
|
|||
], 400);
|
||||
}
|
||||
} else {
|
||||
$this->submission_rollback_new_terms();
|
||||
return new \WP_REST_Response([
|
||||
'error_message' => __('One or more values are invalid.', 'tainacan'),
|
||||
'errors' => $item->get_errors(),
|
||||
|
@ -1033,6 +1097,7 @@ class REST_Items_Controller extends REST_Controller {
|
|||
], 400);
|
||||
}
|
||||
} catch (\Exception $exception){
|
||||
$this->submission_rollback_new_terms();
|
||||
return new \WP_REST_Response($exception->getMessage(), 400);
|
||||
}
|
||||
}
|
||||
|
@ -1047,6 +1112,7 @@ class REST_Items_Controller extends REST_Controller {
|
|||
'error_message' => __('submission ID not exist.', 'tainacan'),
|
||||
], 400);
|
||||
}
|
||||
$this->new_terms_ids = get_transient('tnc_transient_submission_' . $submission_id . '_new_terms_ids');
|
||||
|
||||
$item = $this->items_repository->fetch($item_id);
|
||||
$collection = $this->collections_repository->fetch($collection_id);
|
||||
|
@ -1120,6 +1186,7 @@ class REST_Items_Controller extends REST_Controller {
|
|||
delete_transient('tnc_transient_submission_' . $submission_id);
|
||||
return new \WP_REST_Response($this->prepare_item_for_response($item, $request), 201 );
|
||||
} else {
|
||||
$this->submission_rollback_new_terms();
|
||||
return new \WP_REST_Response([
|
||||
'error_message' => __('One or more values are invalid.', 'tainacan'),
|
||||
'errors' => array_merge($item->get_errors(), $entities_erros),
|
||||
|
|
|
@ -8,14 +8,14 @@ defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
|
|||
* Represents the Entity Term
|
||||
*/
|
||||
class Term extends Entity {
|
||||
protected
|
||||
$term_id,
|
||||
$name,
|
||||
$parent,
|
||||
$description,
|
||||
$user,
|
||||
protected
|
||||
$term_id,
|
||||
$name,
|
||||
$parent,
|
||||
$description,
|
||||
$user,
|
||||
$header_image_id,
|
||||
$taxonomy;
|
||||
$taxonomy;
|
||||
|
||||
|
||||
static $post_type = false;
|
||||
|
@ -34,22 +34,22 @@ class Term extends Entity {
|
|||
*/
|
||||
function __construct($which = 0, $taxonomy = false ) {
|
||||
|
||||
if ($taxonomy)
|
||||
$this->set_taxonomy( $taxonomy );
|
||||
if ($taxonomy)
|
||||
$this->set_taxonomy( $taxonomy );
|
||||
|
||||
if ( is_numeric( $which ) && $which > 0) {
|
||||
$post = get_term_by('id', $which, $taxonomy);
|
||||
|
||||
if ( $post instanceof \WP_Term) {
|
||||
$this->WP_Term = get_term_by('id', $which, $taxonomy);
|
||||
}
|
||||
if ( is_numeric( $which ) && $which > 0) {
|
||||
$post = get_term_by('id', $which, $taxonomy);
|
||||
|
||||
if ( $post instanceof \WP_Term) {
|
||||
$this->WP_Term = get_term_by('id', $which, $taxonomy);
|
||||
}
|
||||
|
||||
} elseif ( $which instanceof \WP_Term ) {
|
||||
$this->WP_Term = $which;
|
||||
} else {
|
||||
$this->WP_Term = new \StdClass();
|
||||
}
|
||||
}
|
||||
} elseif ( $which instanceof \WP_Term ) {
|
||||
$this->WP_Term = $which;
|
||||
} else {
|
||||
$this->WP_Term = new \StdClass();
|
||||
}
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return (string) apply_filters("tainacan-term-to-string", $this->get_name(), $this);
|
||||
|
@ -70,7 +70,7 @@ class Term extends Entity {
|
|||
return apply_filters('tainacan-term-to-array', $term_array, $this);
|
||||
}
|
||||
|
||||
// Getters
|
||||
// Getters
|
||||
|
||||
/**
|
||||
* Return the unique identifier
|
||||
|
@ -78,11 +78,11 @@ class Term extends Entity {
|
|||
* @return integer
|
||||
*/
|
||||
function get_id() {
|
||||
return $this->get_term_id();
|
||||
}
|
||||
return $this->get_term_id();
|
||||
}
|
||||
function get_term_id() {
|
||||
return $this->get_mapped_property('term_id');
|
||||
}
|
||||
return $this->get_mapped_property('term_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name
|
||||
|
@ -90,8 +90,8 @@ class Term extends Entity {
|
|||
* @return string
|
||||
*/
|
||||
function get_name() {
|
||||
return $this->get_mapped_property('name');
|
||||
}
|
||||
return $this->get_mapped_property('name');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the parent ID
|
||||
|
@ -99,8 +99,8 @@ class Term extends Entity {
|
|||
* @return integer
|
||||
*/
|
||||
function get_parent() {
|
||||
return $this->get_mapped_property('parent');
|
||||
}
|
||||
return $this->get_mapped_property('parent');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the description
|
||||
|
@ -108,8 +108,8 @@ class Term extends Entity {
|
|||
* @return string
|
||||
*/
|
||||
function get_description() {
|
||||
return $this->get_mapped_property('description');
|
||||
}
|
||||
return $this->get_mapped_property('description');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the user ID
|
||||
|
@ -117,8 +117,8 @@ class Term extends Entity {
|
|||
* @return integer
|
||||
*/
|
||||
function get_user() {
|
||||
return $this->get_mapped_property('user');
|
||||
}
|
||||
return $this->get_mapped_property('user');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the taxonomy
|
||||
|
@ -126,8 +126,8 @@ class Term extends Entity {
|
|||
* @return integer
|
||||
*/
|
||||
function get_taxonomy() {
|
||||
return $this->get_mapped_property('taxonomy');
|
||||
}
|
||||
return $this->get_mapped_property('taxonomy');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Header Image ID attribute
|
||||
|
@ -155,7 +155,7 @@ class Term extends Entity {
|
|||
return $url;
|
||||
}
|
||||
|
||||
// Setters
|
||||
// Setters
|
||||
|
||||
/**
|
||||
* Define the name
|
||||
|
@ -163,8 +163,8 @@ class Term extends Entity {
|
|||
* @param [string] $value
|
||||
*/
|
||||
function set_name($value) {
|
||||
$this->set_mapped_property('name', $value);
|
||||
}
|
||||
$this->set_mapped_property('name', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the parent ID
|
||||
|
@ -172,8 +172,8 @@ class Term extends Entity {
|
|||
* @param [integer] $value
|
||||
*/
|
||||
function set_parent($value) {
|
||||
$this->set_mapped_property('parent', $value);
|
||||
}
|
||||
$this->set_mapped_property('parent', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the description
|
||||
|
@ -181,8 +181,8 @@ class Term extends Entity {
|
|||
* @param [string] $value
|
||||
*/
|
||||
function set_description($value) {
|
||||
$this->set_mapped_property('description', $value);
|
||||
}
|
||||
$this->set_mapped_property('description', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the user associated
|
||||
|
@ -190,8 +190,8 @@ class Term extends Entity {
|
|||
* @param [integer] $value
|
||||
*/
|
||||
function set_user($value) {
|
||||
$this->set_mapped_property('user', $value);
|
||||
}
|
||||
$this->set_mapped_property('user', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the taxonomy associated
|
||||
|
@ -199,8 +199,8 @@ class Term extends Entity {
|
|||
* @param [integer] $value
|
||||
*/
|
||||
function set_taxonomy($value) {
|
||||
$this->set_mapped_property('taxonomy', $value);
|
||||
}
|
||||
$this->set_mapped_property('taxonomy', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Header Image ID
|
||||
|
|
|
@ -227,7 +227,7 @@
|
|||
|
||||
<script>
|
||||
import { formHooks } from "../../js/mixins";
|
||||
import {mapActions, mapGetters} from 'vuex';
|
||||
import { mapActions, mapGetters } from 'vuex';
|
||||
import wpMediaFrames from '../../js/wp-media-frames';
|
||||
|
||||
export default {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
:maxtags="maxtags != undefined ? maxtags : (itemMetadatum.metadatum.multiple == 'yes' || allowNew === true ? (maxMultipleValues !== undefined ? maxMultipleValues : null) : 1)"
|
||||
v-model="valueComponent"
|
||||
:allow-select-to-create="allowSelectToCreate"
|
||||
:allow-new="allowNew"
|
||||
:allow-new="allowNewFromOptions"
|
||||
:taxonomy-id="taxonomyId"
|
||||
:item-metadatum="itemMetadatum"
|
||||
@showAddNewTerm="openTermCreationModal"
|
||||
|
@ -17,7 +17,7 @@
|
|||
:id="'tainacan-item-metadatum_id-' + itemMetadatum.metadatum.id + (itemMetadatum.parent_meta_id ? ('_parent_meta_id-' + itemMetadatum.parent_meta_id) : '')"
|
||||
:is-modal="false"
|
||||
:parent="0"
|
||||
:allow-new="allowNew"
|
||||
:allow-new="allowNewFromOptions"
|
||||
@showAddNewTerm="openTermCreationModal"
|
||||
:taxonomy_id="taxonomyId"
|
||||
:selected="!valueComponent ? [] : valueComponent"
|
||||
|
@ -33,7 +33,7 @@
|
|||
/>
|
||||
|
||||
<div
|
||||
v-if="displayCreateNewTerm"
|
||||
v-if="displayCreateNewTerm && !isTermCreationPanelOpen"
|
||||
class="add-new-term">
|
||||
<a
|
||||
@click="openTermCreationModal"
|
||||
|
@ -46,6 +46,7 @@
|
|||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Term creation modal, used on admin for a complete term creation -->
|
||||
<b-modal
|
||||
v-model="isTermCreationModalOpen"
|
||||
trap-focus
|
||||
|
@ -61,6 +62,17 @@
|
|||
@onEditionCanceled="() => $console.log('Edition canceled')"
|
||||
@onErrorFound="($event) => $console.log('Form with errors: ' + $event)" />
|
||||
</b-modal>
|
||||
|
||||
<!-- Term creation panel, used on item submission block for a simpler term creation -->
|
||||
<transition name="filter-item">
|
||||
<term-creation-panel
|
||||
v-if="isTermCreationPanelOpen"
|
||||
:taxonomy-id="taxonomyId"
|
||||
:edit-form="{ id: 'new', name: newTermName ? newTermName : '' }"
|
||||
@onEditionFinished="($event) => addTermToBeCreated($event)"
|
||||
@onEditionCanceled="() => isTermCreationPanelOpen = false"
|
||||
@onErrorFound="($event) => $console.log('Form with errors: ' + $event)" />
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -80,9 +92,8 @@
|
|||
disabled: false,
|
||||
forcedComponentType: '',
|
||||
maxtags: '',
|
||||
allowNew: false,
|
||||
allowSelectToCreate: false,
|
||||
isTermCreationModalOpen: false,
|
||||
newTermName: ''
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
|
@ -90,8 +101,11 @@
|
|||
taxonomyId: '',
|
||||
taxonomy: '',
|
||||
terms:[],
|
||||
allowNew: false,
|
||||
isAddingNewTermVaue: false
|
||||
isAddingNewTermVaue: false,
|
||||
isTermCreationModalOpen: false,
|
||||
isTermCreationPanelOpen: false,
|
||||
newTermName: '',
|
||||
allowNewFromOptions: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -107,7 +121,10 @@
|
|||
return '';
|
||||
},
|
||||
displayCreateNewTerm() {
|
||||
return this.allowNew && (this.maxMultipleValues === undefined || this.maxMultipleValues > this.value.length);
|
||||
return this.allowNewFromOptions;
|
||||
},
|
||||
isOnItemSubmissionForm() {
|
||||
return !this.itemMetadatum.item || !this.itemMetadatum.item.id;
|
||||
},
|
||||
maxMultipleValues() {
|
||||
return (this.itemMetadatum && this.itemMetadatum.metadatum && this.itemMetadatum.metadatum.cardinality && !isNaN(this.itemMetadatum.metadatum.cardinality)) ? this.itemMetadatum.metadatum.cardinality : undefined;
|
||||
|
@ -124,9 +141,8 @@
|
|||
this.taxonomyId = metadata_type_options.taxonomy_id;
|
||||
this.taxonomy = metadata_type_options.taxonomy;
|
||||
|
||||
if (this.itemMetadatum.item && this.itemMetadatum.item.id && metadata_type_options && metadata_type_options.allow_new_terms && this.itemMetadatum.item)
|
||||
this.allowNew = metadata_type_options.allow_new_terms == 'yes';
|
||||
|
||||
this.allowNewFromOptions = this.allowNew === false ? false : metadata_type_options.allow_new_terms == 'yes';
|
||||
|
||||
this.getTermsId();
|
||||
},
|
||||
methods: {
|
||||
|
@ -168,9 +184,21 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
addTermToBeCreated(term) {
|
||||
this.isTermCreationPanelOpen = false;
|
||||
|
||||
if (this.itemMetadatum.metadatum.multiple === 'no')
|
||||
this.valueComponent = term.parent ? (term.parent + '>>' + term.name) : term.name;
|
||||
else
|
||||
this.valueComponent.push(term.parent ? (term.parent + '>>' + term.name) : term.name);
|
||||
},
|
||||
openTermCreationModal(newTerm) {
|
||||
this.newTermName = newTerm.name;
|
||||
this.isTermCreationModalOpen = true;
|
||||
|
||||
if (this.isOnItemSubmissionForm)
|
||||
this.isTermCreationPanelOpen = true;
|
||||
else
|
||||
this.isTermCreationModalOpen = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -291,7 +291,7 @@
|
|||
closable
|
||||
class="is-small"
|
||||
@close="selected instanceof Array ? selected.splice(index, 1) : selected = ''">
|
||||
<span v-html="(isTaxonomy || metadatum_type === 'Tainacan\\Metadata_Types\\Relationship') ? selectedTagsName[term] : term" />
|
||||
<span v-html="(isTaxonomy || metadatum_type === 'Tainacan\\Metadata_Types\\Relationship') ? selectedTagsName[term] : term" />
|
||||
</b-tag>
|
||||
</div>
|
||||
</b-field>
|
||||
|
@ -441,23 +441,33 @@
|
|||
},
|
||||
fetchSelectedLabels() {
|
||||
|
||||
let selected = this.selected instanceof Array ? this.selected : [this.selected];
|
||||
let allSelected = this.selected instanceof Array ? this.selected : [this.selected];
|
||||
|
||||
if (this.taxonomy_id && selected.length) {
|
||||
// If a new item was added from item submission block, the value will be a string, and the term does not exists yet.
|
||||
let selected = allSelected.filter((aValue) => !isNaN(aValue));
|
||||
let selectedFromItemSubmission = allSelected.filter((aValue) => isNaN(aValue));
|
||||
|
||||
this.isSelectedTermsLoading = true;
|
||||
if (this.taxonomy_id) {
|
||||
|
||||
axios.get(`/taxonomy/${this.taxonomy_id}/terms/?${qs.stringify({ hideempty: 0, include: selected})}`)
|
||||
.then((res) => {
|
||||
for (const term of res.data)
|
||||
this.saveSelectedTagName(term.id, term.name, term.url);
|
||||
if (selected.length) {
|
||||
this.isSelectedTermsLoading = true;
|
||||
axios.get(`/taxonomy/${this.taxonomy_id}/terms/?${qs.stringify({ hideempty: 0, include: selected})}`)
|
||||
.then((res) => {
|
||||
for (const term of res.data)
|
||||
this.saveSelectedTagName(term.id, term.name, term.url);
|
||||
|
||||
this.isSelectedTermsLoading = false;
|
||||
})
|
||||
.catch((error) => {
|
||||
this.$console.log(error);
|
||||
this.isSelectedTermsLoading = false;
|
||||
});
|
||||
this.isSelectedTermsLoading = false;
|
||||
})
|
||||
.catch((error) => {
|
||||
this.$console.log(error);
|
||||
this.isSelectedTermsLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
if (selectedFromItemSubmission) {
|
||||
for (const term of selectedFromItemSubmission)
|
||||
this.saveSelectedTagName(term, term.split('>')[term.split('>').length - 1], '');
|
||||
}
|
||||
|
||||
} else if (this.metadatum_type === 'Tainacan\\Metadata_Types\\Relationship' && selected.length) {
|
||||
this.isSelectedTermsLoading = true;
|
||||
|
|
|
@ -67,7 +67,7 @@ export default {
|
|||
padding: 0.8em 0.8em 0em 0.8em;
|
||||
|
||||
h5 {
|
||||
font-size: 0.875em;
|
||||
font-size: 0.875em !important;
|
||||
font-weight: bold;
|
||||
color: var(--tainacan-secondary);
|
||||
margin-bottom: 0;
|
||||
|
|
|
@ -108,7 +108,7 @@ export default {
|
|||
padding: 0.8em 0.8em 0em 0.8em;
|
||||
|
||||
h5 {
|
||||
font-size: 0.875em;
|
||||
font-size: 0.875em !important;
|
||||
font-weight: bold;
|
||||
color: var(--tainacan-red2);
|
||||
margin-bottom: 0;
|
||||
|
|
|
@ -22,6 +22,7 @@ import ItemSubmission from '../../../item-submission/item-submission.vue';
|
|||
|
||||
// Remaining imports
|
||||
import TainacanFormItem from '../../../admin/components/metadata-types/tainacan-form-item.vue';
|
||||
import TermCreationPanel from '../../../item-submission/components/term-creation-panel.vue';
|
||||
import HelpButton from '../../../admin/components/other/help-button.vue';
|
||||
import store from '../../../admin/js/store/store';
|
||||
import { I18NPlugin, UserPrefsPlugin, RouterHelperPlugin, ConsolePlugin, StatusHelperPlugin, CommentsStatusHelperPlugin } from '../../../admin/js/admin-utilities';
|
||||
|
@ -83,6 +84,7 @@ export default (element) => {
|
|||
|
||||
/* Others */
|
||||
Vue.component('tainacan-form-item', TainacanFormItem);
|
||||
Vue.component('term-creation-panel', TermCreationPanel);
|
||||
Vue.component('help-button', HelpButton);
|
||||
|
||||
const VueItemSubmission = new Vue({
|
||||
|
|
|
@ -0,0 +1,278 @@
|
|||
<template>
|
||||
<form
|
||||
autofocus
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
aria-modal
|
||||
id="termEditForm"
|
||||
class="tainacan-form term-creation-panel"
|
||||
@submit.prevent="saveEdition(editForm)">
|
||||
|
||||
<h4>{{ editForm & editForm.id && editForm.id != 'new' ? $i18n.get("title_term_edition") : $i18n.get("title_term_creation") }}</h4>
|
||||
|
||||
<div>
|
||||
<b-loading
|
||||
:is-full-page="false"
|
||||
:active.sync="isLoading" />
|
||||
|
||||
<!-- Name -------------- -->
|
||||
<b-field
|
||||
:addons="false"
|
||||
:type="((formErrors.name !== '' || formErrors.repeated !== '') && (formErrors.name !== undefined || formErrors.repeated !== undefined )) ? 'is-danger' : ''"
|
||||
:message="formErrors.name ? formErrors.name : formErrors.repeated">
|
||||
<label class="label is-inline">
|
||||
{{ $i18n.get('label_name') }}
|
||||
<span class="required-term-asterisk">*</span>
|
||||
<help-button
|
||||
:title="$i18n.get('label_name')"
|
||||
:message="$i18n.get('info_help_term_name')"/>
|
||||
</label>
|
||||
<b-input
|
||||
:placeholder="$i18n.get('label_term_without_name')"
|
||||
v-model="editForm.name"
|
||||
name="name"
|
||||
@focus="clearErrors({ name: 'name', repeated: 'repeated' })"/>
|
||||
</b-field>
|
||||
|
||||
<!-- Parent -------------- -->
|
||||
<b-field
|
||||
:addons="false"
|
||||
:type="((formErrors.parent !== '' || formErrors.repeated !== '') && (formErrors.parent !== undefined || formErrors.repeated !== undefined )) ? 'is-danger' : ''"
|
||||
:message="formErrors.parent ? formErrors : formErrors.repeated">
|
||||
<label class="label is-inline">
|
||||
{{ $i18n.get('label_parent_term') }}
|
||||
<b-switch
|
||||
@input="onToggleSwitch()"
|
||||
id="tainacan-checkbox-has-parent"
|
||||
size="is-small"
|
||||
v-model="hasParent" />
|
||||
<help-button
|
||||
:title="$i18n.get('label_parent_term')"
|
||||
:message="$i18n.get('info_help_parent_term')"/>
|
||||
</label>
|
||||
<b-autocomplete
|
||||
id="tainacan-add-parent-field"
|
||||
:placeholder="$i18n.get('instruction_parent_term')"
|
||||
:data="parentTerms"
|
||||
field="name"
|
||||
clearable
|
||||
v-model="parentTermName"
|
||||
@select="onSelectParentTerm($event)"
|
||||
:loading="isFetchingParentTerms"
|
||||
@input="fetchParentTerms"
|
||||
@focus="clearErrors('parent');"
|
||||
:disabled="!hasParent"
|
||||
check-infinite-scroll
|
||||
@infinite-scroll="fetchMoreParentTerms">
|
||||
<template slot-scope="props">
|
||||
<div class="media">
|
||||
<div
|
||||
v-if="props.option.header_image"
|
||||
class="media-left">
|
||||
<img
|
||||
width="28"
|
||||
:src="props.option.header_image">
|
||||
</div>
|
||||
<div class="media-content">
|
||||
{{ props.option.name }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template slot="empty">{{ $i18n.get('info_no_parent_term_found') }}</template>
|
||||
</b-autocomplete>
|
||||
</b-field>
|
||||
|
||||
<!-- Submit buttons -------------- -->
|
||||
<div class="field is-grouped form-submit">
|
||||
<div class="control">
|
||||
<button
|
||||
type="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('label_create_and_select') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { formHooks } from "../../admin/js/mixins";
|
||||
import { mapActions, mapGetters } from 'vuex';
|
||||
|
||||
export default {
|
||||
name: 'TermEditionForm',
|
||||
mixins: [ formHooks ],
|
||||
props: {
|
||||
editForm: Object,
|
||||
taxonomyId: ''
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
formErrors: {},
|
||||
isFetchingParentTerms: false,
|
||||
parentTerms: [],
|
||||
parentTermName: '',
|
||||
hasParent: false,
|
||||
hasChangedParent: false,
|
||||
initialParentId: undefined,
|
||||
entityName: 'term',
|
||||
isLoading: false,
|
||||
parentTermSearchQuery: '',
|
||||
parentTermSearchOffset: 0
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
||||
this.hasParent = this.editForm.parent != undefined && this.editForm.parent > 0;
|
||||
this.initialParentId = this.editForm.parent;
|
||||
|
||||
if (this.hasParent) {
|
||||
this.isFetchingParentTerms = true;
|
||||
this.fetchParentName({ taxonomyId: this.taxonomyId, parentId: this.editForm.parent })
|
||||
.then((parentName) => {
|
||||
this.parentTermName = parentName;
|
||||
this.isFetchingParentTerms = false;
|
||||
this.showCheckboxesWarning = false;
|
||||
})
|
||||
.catch((error) => {
|
||||
this.$console.error(error);
|
||||
this.isFetchingParentTerms = false;
|
||||
this.showCheckboxesWarning = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions('taxonomy', [
|
||||
'sendChildTerm',
|
||||
'updateChildTerm',
|
||||
'fetchParentName',
|
||||
'fetchPossibleParentTerms'
|
||||
]),
|
||||
...mapGetters('taxonomy', [
|
||||
'getTerms'
|
||||
]),
|
||||
saveEdition(term) {
|
||||
|
||||
if (term.id === 'new') {
|
||||
this.$emit('onEditionFinished', { name: this.editForm.name, parent: this.editForm.parent });
|
||||
this.editForm = {};
|
||||
this.formErrors = {};
|
||||
this.isLoading = false;
|
||||
}
|
||||
},
|
||||
cancelEdition() {
|
||||
this.$emit('onEditionCanceled', this.editForm);
|
||||
},
|
||||
clearErrors(attributes) {
|
||||
if (attributes instanceof Object){
|
||||
for(let attribute in attributes){
|
||||
this.formErrors[attribute] = undefined;
|
||||
}
|
||||
} else {
|
||||
this.formErrors[attributes] = undefined;
|
||||
}
|
||||
},
|
||||
fetchParentTerms: _.debounce(function(search) {
|
||||
|
||||
// String update
|
||||
if (search != this.parentTermSearchQuery) {
|
||||
this.parentTermSearchQuery = search;
|
||||
this.parentTerms = [];
|
||||
this.parentTermSearchOffset = 0;
|
||||
}
|
||||
|
||||
// String cleared
|
||||
if (!search.length) {
|
||||
this.parentTermSearchQuery = search;
|
||||
this.parentTerms = [];
|
||||
this.parentTermSearchOffset = 0;
|
||||
}
|
||||
|
||||
// No need to load more
|
||||
if (this.parentTermSearchOffset > 0 && this.parentTerms.length >= this.totalTerms)
|
||||
return
|
||||
|
||||
this.isFetchingParentTerms = true;
|
||||
|
||||
this.fetchPossibleParentTerms({
|
||||
taxonomyId: this.taxonomyId,
|
||||
termId: this.editForm.id,
|
||||
search: this.parentTermSearchQuery,
|
||||
offset: this.parentTermSearchOffset })
|
||||
.then((res) => {
|
||||
for (let term of res.parentTerms)
|
||||
this.parentTerms.push(term);
|
||||
|
||||
this.parentTermSearchOffset += 12;
|
||||
this.totalTerms = res.totalTerms;
|
||||
this.isFetchingParentTerms = false;
|
||||
})
|
||||
.catch((error) => {
|
||||
this.$console.error(error);
|
||||
this.isFetchingParentTerms = false;
|
||||
});
|
||||
}, 500),
|
||||
fetchMoreParentTerms: _.debounce(function () {
|
||||
this.fetchParentTerms(this.parentTermSearchQuery)
|
||||
}, 250),
|
||||
onToggleSwitch() {
|
||||
|
||||
if (this.editForm.parent == 0)
|
||||
this.hasChangedParent = this.hasParent;
|
||||
else
|
||||
this.hasChangedParent = !this.hasParent;
|
||||
|
||||
this.showCheckboxesWarning = true;
|
||||
this.clearErrors('parent');
|
||||
},
|
||||
onSelectParentTerm(selectedParentTerm) {
|
||||
this.hasChangedParent = this.initialParentId != selectedParentTerm.id;
|
||||
this.editForm.parent = selectedParentTerm.id;
|
||||
this.selectedParentTerm = selectedParentTerm;
|
||||
this.parentTermName = selectedParentTerm.name;
|
||||
this.showCheckboxesWarning = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.term-creation-panel {
|
||||
padding-top: 6px;
|
||||
|
||||
h4 {
|
||||
font-size: 0.875em !important;
|
||||
}
|
||||
&>div {
|
||||
padding: 0 16px 16px;
|
||||
border-left: 1px solid var(--tainacan-input-border-color, #dbdbdb);
|
||||
border-bottom: 1px solid var(--tainacan-input-border-color, #dbdbdb);
|
||||
column-count: 2;
|
||||
|
||||
@media screen and (max-width: 1024px) {
|
||||
column-count: 1;
|
||||
}
|
||||
|
||||
.field {
|
||||
break-inside: avoid;
|
||||
}
|
||||
.form-submit {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
column-span: all;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
Loading…
Reference in New Issue