Splits metadata list into two components. #184.

This commit is contained in:
mateuswetah 2022-04-17 13:29:45 -03:00
parent 2e4f77fbbe
commit d8ae83b22f
6 changed files with 1770 additions and 1192 deletions

View File

@ -243,7 +243,7 @@ class REST_Metadata_Sections_Controller extends REST_Controller {
* @return array|\WP_Error|\WP_REST_Response
*/
public function prepare_item_for_response( $item, $request ) {
if(!empty($item)){
if (!empty($item)){
$item_arr = $item->_toArray();
if ($request['context'] === 'edit') {
$item_arr['current_user_can_edit'] = $item->can_edit();
@ -251,13 +251,11 @@ class REST_Metadata_Sections_Controller extends REST_Controller {
// $item_arr['enabled'] = $item->get_enabled_for_collection();
}
if( !empty($item_arr['metadata_list']) ) {
$metadata_list = $item_arr['metadata_list'];
$item_arr['metadata_object_list'] = [];
foreach($metadata_list as $metadatum_id) {
$meta = $this->metadata_repository->fetch($metadatum_id, 'OBJECT');
$item_arr['metadata_object_list'][] = $meta->_toArray();
}
$metadata_list = !empty($item_arr['metadata_list']) ? $item_arr['metadata_list'] : [];
$item_arr['metadata_object_list'] = [];
foreach($metadata_list as $metadatum_id) {
$meta = $this->metadata_repository->fetch($metadatum_id, 'OBJECT');
$item_arr['metadata_object_list'][] = $meta->_toArray();
}
/**

View File

@ -0,0 +1,814 @@
<template>
<div class="column">
<b-loading :active.sync="isLoadingMetadataSections"/>
<div class="tainacan-form sub-header">
<h3>{{ $i18n.get('metadata') }}<span class="has-text-gray">{{ ( activeMetadatumList && activeMetadatumList.length ? (' (' + activeMetadatumList.length + ')') : '' ) }}</span></h3>
<template v-if="activeMetadatumList && !isLoadingMetadata">
<b-field class="header-item">
<b-dropdown
:mobile-modal="true"
:disabled="activeMetadatumList.length <= 0"
class="show metadata-options-dropdown"
aria-role="list"
trap-focus>
<button
:aria-label="$i18n.get('label_filter_by_metadata_type')"
class="button is-white"
slot="trigger">
<span>{{ $i18n.get('label_filter_by_metadata_type') }}</span>
<span class="icon">
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-arrowdown"/>
</span>
</button>
<div class="metadata-options-container">
<b-dropdown-item
v-for="(metadataType, index) in metadataTypeFilterOptions"
:key="index"
class="control"
custom
aria-role="listitem">
<b-checkbox
v-model="metadataType.enabled"
:native-value="metadataType.enabled">
{{ metadataType.name }}
</b-checkbox>
</b-dropdown-item>
</div>
</b-dropdown>
</b-field>
<b-field class="header-item">
<b-input
:placeholder="$i18n.get('instruction_type_search_metadata_filter')"
v-model="metadataNameFilterString"
icon="magnify"
size="is-small"
icon-right="close-circle"
icon-right-clickable
@icon-right-click="metadataNameFilterString = ''" />
</b-field>
</template>
</div>
<button
aria-controls="filters-items-list"
:aria-expanded="!collapseAll"
v-if="activeMetadatumList.length > 0"
class="link-style collapse-all"
@click="collapseAll = !collapseAll">
<span class="icon">
<i
:class="{ 'tainacan-icon-arrowdown' : collapseAll, 'tainacan-icon-arrowright' : !collapseAll }"
class="has-text-secondary tainacan-icon tainacan-icon-1-125em"/>
</span>
<span class="collapse-all__text">
{{ collapseAll ? $i18n.get('label_collapse_all') : $i18n.get('label_expand_all') }}
</span>
</button>
<section
v-if="activeMetadatumList.length <= 0 && !isLoadingMetadata"
class="field is-grouped-centered section">
<div class="content has-text-gray has-text-centered">
<p>
<span class="icon is-large">
<i class="tainacan-icon tainacan-icon-36px tainacan-icon-metadata"/>
</span>
</p>
<p>{{ $i18n.get('info_there_is_no_metadatum' ) }}</p>
<p>{{ $i18n.get('info_create_metadata' ) }}</p>
</div>
</section>
<!-- The Metadata Sections list -->
<draggable
v-model="activeMetadataSectionsList"
class="active-metadata-sections-area"
@change="handleSectionChange($event)"
:group="{ name:'metadata-sections', pull: false, put: true }"
:sort="(openedMetadataSectionId == '' || openedMetadataSectionId == undefined) && (openedMetadatumId == '' || openedMetadatumId == undefined)"
:handle="'.handle'"
ghost-class="sortable-ghost"
chosen-class="sortable-chosen"
filter=".not-sortable-item"
:prevent-on-filter="false"
:animation="250">
<div
v-for="(metadataSection, sectionIndex) in activeMetadataSectionsList"
:key="metadataSection.id">
<div
class="active-metadata-sections-item"
:class="{
'is-compact-item': !isCollapseOpen(metadataSection.id),
'not-sortable-item':
metadataSection.id == undefined ||
openedMetadatumId != '' ||
openedMetadataSectionId != '' ||
isUpdatingMetadataOrder ||
isUpdatingMetadataSectionsOrder ||
metadataNameFilterString != '' ||
hasSomeMetadataTypeFilterApplied,
'not-focusable-item': openedMetadataSectionId == metadataSection.id,
'disabled-metadatum': metadataSection.enabled == false,
'inherited-metadatum': false
}">
<div
:ref="'metadata-section-handler-' + metadataSection.id"
class="handle">
<span
:style="{ opacity: !(metadataSection.id == undefined || openedMetadatumId != '' || isUpdatingMetadataOrder || openedMetadataSectionId != '' || isUpdatingMetadataSectionsOrder || metadataNameFilterString != '' || hasSomeMetadataTypeFilterApplied) ? '1.0' : '0.0' }"
v-tooltip="{
content: metadataSection.id == undefined || openedMetadatumId != '' || isUpdatingMetadataOrder || openedMetadataSectionId != '' || isUpdatingMetadataSectionsOrder ? $i18n.get('info_not_allowed_change_order_metadata_sections') : $i18n.get('instruction_drag_and_drop_metadata_sections_sort'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip'],
placement: 'auto-start'
}"
class="icon grip-icon">
<svg
xmlns="http://www.w3.org/2000/svg"
height="24px"
viewBox="0 0 24 24"
width="24px"
fill="currentColor">
<path
d="M0 0h24v24H0V0z"
fill="transparent"/>
<path d="M11 18c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zm-2-8c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0-6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm6 4c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/>
</svg>
</span>
<span class="metadatum-name">
{{ metadataSection.name }}
</span>
<span
v-if="metadataSection.id != undefined"
class="label-details">
({{ metadataSection.name }})
<span
v-if="metadataSection.status === 'private'"
class="icon"
v-tooltip="{
content: $i18n.get('status_private'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip'],
placement: 'auto-start'
}">
<i class="tainacan-icon tainacan-icon-private"/>
</span>
</span>
<span
class="loading-spinner"
v-if="metadataSection.id == undefined"/>
<span
class="controls"
v-if="metadataSection.id !== undefined">
<b-switch
:disabled="isUpdatingMetadataSectionsOrder"
size="is-small"
:value="metadataSection.enabled"
@input="onChangeEnableSection($event, sectionIndex)"/>
<a
v-if="metadataSection.current_user_can_edit"
:style="{ visibility:
metadataSection.collection_id != collectionId
? 'hidden' : 'visible'
}"
@click.prevent="toggleMetadataSectionEdition(metadataSection)">
<span
v-tooltip="{
content: $i18n.get('edit'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip'],
placement: 'auto-start'
}"
class="icon">
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-edit"/>
</span>
</a>
<a
v-if="metadataSection.current_user_can_delete"
:style="{ visibility: metadataSection.collection_id != collectionId || metadataSection.core ? 'hidden' : 'visible' }"
@click.prevent="removeMetadataSection(metadataSection)">
<span
v-tooltip="{
content: $i18n.get('delete'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip'],
placement: 'auto-start'
}"
class="icon">
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-delete"/>
</span>
</a>
</span>
</div>
</div>
<!-- The Metadata list, inside each metadata section -->
<draggable
v-model="activeMetadatumList"
class="active-metadata-area"
@change="handleChange($event, metadataSection.id)"
:group="{ name:'metadata', pull: false, put: true }"
:sort="(openedMetadatumId == '' || openedMetadatumId == undefined)"
:handle="'.handle'"
ghost-class="sortable-ghost"
chosen-class="sortable-chosen"
filter=".not-sortable-item"
:prevent-on-filter="false"
:animation="250">
<div
v-for="(metadatum, index) in activeMetadatumList.filter((meta) => meta != undefined && meta.parent == 0)"
:key="metadatum.id"
v-show="(metadataNameFilterString == '' || filterByMetadatumName(metadatum)) && filterByMetadatumType(metadatum)">
<div
class="active-metadatum-item"
:class="{
'is-compact-item': !isCollapseOpen(metadatum.id),
'not-sortable-item': metadatum.id == undefined || openedMetadatumId != '' || isUpdatingMetadataOrder || metadataNameFilterString != '' || hasSomeMetadataTypeFilterApplied,
'not-focusable-item': openedMetadatumId == metadatum.id,
'disabled-metadatum': metadatum.enabled == false,
'inherited-metadatum': metadatum.inherited,
'child-metadatum': metadatum.parent > 0
}">
<div
:ref="'metadatum-handler-' + metadatum.id"
class="handle">
<span
:style="{ opacity: !(metadatum.id == undefined || openedMetadatumId != '' || isUpdatingMetadataOrder || metadataNameFilterString != '' || hasSomeMetadataTypeFilterApplied) ? '1.0' : '0.0' }"
v-tooltip="{
content: metadatum.id == undefined || openedMetadatumId != '' || isUpdatingMetadataOrder ? $i18n.get('info_not_allowed_change_order_metadata') : $i18n.get('instruction_drag_and_drop_metadatum_sort'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip'],
placement: 'auto-start'
}"
class="icon grip-icon">
<svg
xmlns="http://www.w3.org/2000/svg"
height="24px"
viewBox="0 0 24 24"
width="24px"
fill="currentColor">
<path
d="M0 0h24v24H0V0z"
fill="transparent"/>
<path d="M11 18c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zm-2-8c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0-6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm6 4c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/>
</svg>
</span>
<span
v-tooltip="{
content: $i18n.get('label_view_metadata_details'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip'],
placement: 'auto-start'
}"
@click="$set(collapses, metadatum.id, !isCollapseOpen(metadatum.id))"
class="gray-icon icon"
:style="{ cursor: 'pointer', opacity: openedMetadatumId != metadatum.id ? '1.0' : '0.0' }">
<i :class="'tainacan-icon tainacan-icon-1-25em tainacan-icon-' + (isCollapseOpen(metadatum.id) ? 'arrowdown' : 'arrowright')" />
</span>
<span class="metadatum-name">
{{ metadatum.name }}
</span>
<span
v-if="metadatum.id != undefined && metadatum.metadata_type_object"
class="label-details"
:class="{ 'has-text-weight-bold': metadatum.metadata_type_object.core }">
<span
v-if="metadatum.required === 'yes'"
v-tooltip="{
content: $i18n.get('label_required'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip'],
placement: 'auto-start'
}">
*&nbsp;
</span>
({{ metadatum.metadata_type_object.name }})
<span
v-if="metadatum.status === 'private'"
class="icon"
v-tooltip="{
content: $i18n.get('status_private'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip'],
placement: 'auto-start'
}">
<i class="tainacan-icon tainacan-icon-private"/>
</span>
<span
v-tooltip="{
content: (metadatum.collection_id == 'default') ? $i18n.get('label_repository_metadatum') : $i18n.get('label_collection_metadatum'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip'],
placement: 'auto-start'
}"
class="icon icon-level-identifier">
<i
:class="{
'has-text-turquoise5': metadatum.enabled,
'has-text-gray3': !metadatum.enabled
}"
class="tainacan-icon tainacan-icon-collection" />
</span>
</span>
<span
class="loading-spinner"
v-if="metadatum.id == undefined"/>
<span
class="controls"
v-if="metadatum.id !== undefined">
<b-switch
:disabled="isUpdatingMetadataOrder"
size="is-small"
:value="metadatum.enabled"
@input="onChangeEnable($event, index)"/>
<a
v-if="metadatum.current_user_can_edit"
:style="{ visibility:
metadatum.collection_id != collectionId
? 'hidden' : 'visible'
}"
@click.prevent="toggleMetadatumEdition(metadatum)">
<span
v-tooltip="{
content: $i18n.get('edit'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip'],
placement: 'auto-start'
}"
class="icon">
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-edit"/>
</span>
</a>
<a
v-if="metadatum.current_user_can_delete"
:style="{ visibility: metadatum.collection_id != collectionId || metadatum.metadata_type_object.core ? 'hidden' : 'visible' }"
@click.prevent="removeMetadatum(metadatum)">
<span
v-tooltip="{
content: $i18n.get('delete'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip'],
placement: 'auto-start'
}"
class="icon">
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-delete"/>
</span>
</a>
</span>
</div>
<transition name="form-collapse">
<metadatum-details
v-if="isCollapseOpen(metadatum.id) && openedMetadatumId !== metadatum.id"
:metadatum="metadatum" />
</transition>
</div>
<!-- Child metadata list, inside each compound metadata -->
<child-metadata-list
v-if="metadatum.metadata_type_object && metadatum.metadata_type_object.component == 'tainacan-compound'"
:parent.sync="activeMetadatumList[index]"
:metadata-name-filter-string="metadataNameFilterString"
:metadata-type-filter-options="metadataTypeFilterOptions"
:has-some-metadata-type-filter-applied="hasSomeMetadataTypeFilterApplied"
:is-parent-multiple="metadatum.multiple == 'yes'"
:is-repository-level="false"
:collapse-all="collapseAll" />
<!-- Metadata edition form, for each metadata -->
<b-modal
@close="onEditionCanceled()"
:active="openedMetadatumId == metadatum.id"
trap-focus
aria-modal
aria-role="dialog"
custom-class="tainacan-modal"
:close-button-aria-label="$i18n.get('close')">
<metadatum-edition-form
:collection-id="collectionId"
:original-metadatum="metadatum"
:is-repository-level="false"
@onEditionFinished="onEditionFinished()"
@onEditionCanceled="onEditionCanceled()"
:index="index" />
</b-modal>
</div>
</draggable><!-- End of .active-metadata-area -->
<!-- Metadata Section edition form, for each metadata section -->
<b-modal
@close="onSectionEditionCanceled()"
:active="openedMetadataSectionId == metadataSection.id"
trap-focus
aria-modal
aria-role="dialog"
custom-class="tainacan-modal"
:close-button-aria-label="$i18n.get('close')">
<metadata-section-edition-form
:collection-id="collectionId"
:original-metadata-section="metadataSection"
@onEditionFinished="onSectionEditionFinished()"
@onEditionCanceled="onSectionEditionCanceled()"
:index="sectionIndex" />
</b-modal>
</div>
</draggable> <!-- End of .active-metadata-sections-area -->
</div> <!-- End of .columns -->
</template>
<script>
import MetadatumEditionForm from '../../components/edition/metadatum-edition-form.vue';
import MetadataSectionEditionForm from '../../components/edition/metadata-section-edition-form.vue';
import MetadatumDetails from '../../components/other/metadatum-details.vue';
import ChildMetadataList from '../../components/metadata-types/compound/child-metadata-list.vue';
import CustomDialog from '../../components/other/custom-dialog.vue';
import { mapGetters, mapActions } from 'vuex';
export default {
name: 'CollectionMetadataList',
components: {
MetadatumEditionForm,
MetadataSectionEditionForm,
ChildMetadataList,
MetadatumDetails
},
props: {
metadataTypeFilterOptions: Array
},
data() {
return {
collectionId: '',
isLoadingMetadata: false,
isLoadingMetadataSections: false,
isUpdatingMetadataOrder: false,
openedMetadatumId: '',
openedMetadataSectionId: '',
hightlightedMetadatum: '',
collapses: {},
collapseAll: false,
metadataNameFilterString: '',
isUpdatingMetadataSectionsOrder: false,
metadataSearchCancel: undefined
}
},
computed: {
hasSomeMetadataTypeFilterApplied() {
return this.metadataTypeFilterOptions.length && this.metadataTypeFilterOptions.some((metadatumType) => metadatumType.enabled);
},
activeMetadatumList: {
get() {
return this.getMetadata();
},
set(value) {
this.updateMetadata(value);
}
},
activeMetadataSectionsList: {
get() {
return this.getMetadataSections();
},
set(value) {
this.updateMetadataSections(value);
}
}
},
watch: {
'$route.query': {
handler(newQuery) {
if (newQuery.edit != undefined) {
let existingMetadataIndex = this.activeMetadatumList.findIndex((metadatum) => metadatum && (metadatum.id == newQuery.edit));
if (existingMetadataIndex >= 0)
this.editMetadatum(this.activeMetadatumList[existingMetadataIndex])
} else if (newQuery.sectionEdit != undefined) {
let existingMetadataSectionIndex = this.activeMetadataSectionsList.findIndex((metadataSection) => metadataSection && (metadataSection.id == newQuery.sectionEdit));
if (existingMetadataSectionIndex >= 0)
this.editMetadataSection(this.activeMetadataSectionsList[existingMetadataSectionIndex])
}
},
immediate: true
},
collapseAll(isCollapsed) {
this.activeMetadatumList.forEach((metadatum) => this.$set(this.collapses, metadatum.id, isCollapsed));
}
},
mounted() {
this.cleanMetadata();
this.cleanMetadataSections();
this.collectionId = this.$route.params.collectionId;
this.isLoadingMetadataSections = true;
this.fetchMetadataSections({ collectionId: this.collectionId })
.then(() => {
this.activeMetadataSectionsList.forEach((aMetadataSection) => {
this.refreshMetadata(aMetadataSection);
});
this.isLoadingMetadataSections = false;
})
.catch((error) => {
this.$console.error(error);
this.isLoadingMetadataSections = false;
});
},
beforeDestroy() {
// Cancels previous Request
if (this.metadataSearchCancel != undefined)
this.metadataSearchCancel.cancel('Metadata search Canceled.');
},
methods: {
...mapActions('metadata', [
'fetchMetadata',
'sendMetadatum',
'sendMetadataSection',
'deleteMetadatum',
'updateMetadata',
'updateCollectionMetadataOrder',
'updateCollectionMetadataSectionsOrder',
'cleanMetadata',
'updateMetadataSections',
'fetchMetadataSections',
'cleanMetadataSections'
]),
...mapGetters('metadata',[
'getMetadata',
'getMetadataSections'
]),
handleSectionChange(event) {
if (event.added)
this.addNewMetadataSection(event.added.element, event.added.newIndex);
else if (event.removed)
this.removeMetadataSection(event.removed.element);
else if (event.moved) {
this.updateMetadataSectionsOrder();
}
},
handleChange(event, metadataSectionId) {
if (event.added)
this.addNewMetadatum(event.added.element, event.added.newIndex, metadataSectionId);
else if (event.removed)
this.removeMetadatum(event.removed.element);
else if (event.moved) {
this.updateMetadataOrder();
}
},
updateMetadataOrder() {
let metadataOrder = [];
for (let metadatum of this.activeMetadatumList)
if (metadatum != undefined)
metadataOrder.push({ 'id': metadatum.id, 'enabled': metadatum.enabled });
this.isUpdatingMetadataOrder = true;
this.updateCollectionMetadataOrder({ collectionId: this.collectionId, metadataOrder: metadataOrder })
.then(() => this.isUpdatingMetadataOrder = false)
.catch(() => this.isUpdatingMetadataOrder = false);
},
updateMetadataSectionsOrder() {
let metadataSectionsOrder = [];
for (let metadataSection of this.activeMetadataSectionsList)
if (metadataSection != undefined)
metadataSectionsOrder.push({ 'id': metadataSection.id, 'enabled': metadataSection.enabled });
this.isUpdatingMetadataSectionsOrder = true;
this.updateCollectionMetadataSectionsOrder({ collectionId: this.collectionId, metadataSectionsOrder: metadataSectionsOrder })
.then(() => this.isUpdatingMetadataSectionsOrder = false)
.catch(() => this.isUpdatingMetadataSectionsOrder = false);
},
onChangeEnable($event, index) {
let metadataOrder = [];
for (let metadatum of this.activeMetadatumList)
if (metadatum != undefined)
metadataOrder.push({'id': metadatum.id, 'enabled': metadatum.enabled});
metadataOrder[index].enabled = $event;
this.isUpdatingMetadataOrder = true;
this.updateCollectionMetadataOrder({ collectionId: this.collectionId, metadataOrder: metadataOrder })
.then(() => this.isUpdatingMetadataOrder = false)
.catch(() => this.isUpdatingMetadataOrder = false);
},
onChangeEnableSection($event, index) {
let metadataSectionsOrder = [];
for (let metadataSection of this.activeMetadataSectionsList)
if (metadataSection != undefined)
metadataSectionsOrder.push({'id': metadataSection.id, 'enabled': metadataSection.enabled});
metadataSectionsOrder[index].enabled = $event;
this.isUpdatingMetadataSectionsOrder = true;
this.updateCollectionMetadataSectionsOrder({ collectionId: this.collectionId, metadataSectionsOrder: metadataSectionsOrder })
.then(() => this.isUpdatingMetadataSectionsOrder = false)
.catch(() => this.isUpdatingMetadataSectionsOrder = false);
},
addMetadatumViaButton(metadatumType) {
let lastIndex = this.activeMetadatumList.length;
this.addNewMetadatum(metadatumType, lastIndex);
// Higlights the clicked metadatum
this.hightlightedMetadatum = metadatumType.name;
this.$emit('onUpdatehightlightedMetadatum', this.hightlightedMetadatum);
},
addMetadataSectionViaButton() {
let lastIndex = this.activeMetadataSectionsList.length;
this.addNewMetadataSection(lastIndex);
},
addNewMetadatum(newMetadatum, newIndex, metadataSectionId) {
this.sendMetadatum({
collectionId: this.collectionId,
name: newMetadatum.name,
metadatumType: newMetadatum.className,
status: 'auto-draft',
isRepositoryLevel: false,
newIndex: newIndex,
parent: '0',
sectionId: metadataSectionId
})
.then((metadatum) => {
this.updateMetadataOrder();
this.toggleMetadatumEdition(metadatum)
this.hightlightedMetadatum = '';
this.$emit('onUpdatehightlightedMetadatum', this.hightlightedMetadatum);
})
.catch((error) => {
this.$console.error(error);
});
},
addNewMetadataSection(newIndex) {
this.sendMetadataSection({
collectionId: this.collectionId,
name: '',
status: 'auto-draft',
newIndex: newIndex
})
.then((metadataSection) => {
//this.updateMetadataSectionsOrder();
this.toggleMetadataSectionEdition(metadataSection)
})
.catch((error) => {
this.$console.error(error);
});
},
removeMetadatum(removedMetadatum) {
this.$buefy.modal.open({
parent: this,
component: CustomDialog,
props: {
icon: 'alert',
title: this.$i18n.get('label_warning'),
message: this.$i18n.get('info_warning_metadatum_delete'),
onConfirm: () => {
this.deleteMetadatum({
collectionId: this.collectionId,
metadatumId: removedMetadatum.id,
isRepositoryLevel: false
})
.then(() => {
this.updateMetadataOrder();
})
.catch(() => {
this.$console.log("Error deleting metadatum.")
});
}
},
trapFocus: true,
customClass: 'tainacan-modal',
closeButtonAriaLabel: this.$i18n.get('close')
});
},
removeMetadataSection(removedMetadataSection) {
this.$buefy.modal.open({
parent: this,
component: CustomDialog,
props: {
icon: 'alert',
title: this.$i18n.get('label_warning'),
message: this.$i18n.get('info_warning_metadata_section_delete'),
onConfirm: () => {
this.deleteMetadataSection({ collectionId: this.collectionId, metadataSectionId: removedMetadataSection.id })
.then(() => {
//this.updateMetadataSectionsOrder();
})
.catch(() => {
this.$console.log("Error deleting metadata section.")
});
}
},
trapFocus: true,
customClass: 'tainacan-modal',
closeButtonAriaLabel: this.$i18n.get('close')
});
},
toggleMetadatumEdition(metadatum) {
this.$router.push({ query: { edit: metadatum.id } });
},
toggleMetadataSectionEdition(metadataSection) {
this.$router.push({ query: { sectionEdit: metadataSection.id } });
},
editMetadatum(metadatum) {
this.openedMetadatumId = metadatum.id;
},
editMetadataSection(metadataSection) {
this.openedMetadataSectionId = metadataSection.id;
},
onEditionFinished() {
this.openedMetadatumId = '';
this.$router.push({ query: {}});
},
onEditionCanceled() {
this.openedMetadatumId = '';
this.$router.push({ query: {}});
},
onSectionEditionFinished() {
this.openedMetadataSectionId = '';
this.$router.push({ query: {}});
},
onSectionEditionCanceled() {
this.openedMetadataSectionId = '';
this.$router.push({ query: {}});
},
refreshMetadata(metadataSection) {
this.isLoadingMetadata = true;
// Cancels previous Request
if (this.metadataSearchCancel != undefined)
this.metadataSearchCancel.cancel('Metadata search Canceled.');
this.fetchMetadata({
collectionId: this.collectionId,
isRepositoryLevel: false,
isContextEdit: true,
includeDisabled: true,
parent: '0',
includeOptionsAsHtml: true
}).then((resp) => {
resp.request
.then(() => {
this.isLoadingMetadata = false;
// Checks URL as router watcher would not wait for list to load
if (this.$route.query.edit != undefined) {
let existingMetadataIndex = this.activeMetadatumList.findIndex((metadatum) => metadatum.id == this.$route.query.edit);
if (existingMetadataIndex >= 0)
this.editMetadatum(this.activeMetadatumList[existingMetadataIndex]);
}
})
.catch(() => {
this.isLoadingMetadata = false;
});
// Search Request Token for cancelling
this.metadataSearchCancel = resp.source;
})
.catch(() => this.isLoadingMetadata = false);
},
filterByMetadatumName(metadatum) {
if (metadatum.metadata_type_object &&
metadatum.metadata_type_object.component == 'tainacan-compound' &&
metadatum.metadata_type_options &&
metadatum.metadata_type_options.children_objects &&
metadatum.metadata_type_options.children_objects.length
) {
let childNamesArray = metadatum.metadata_type_options.children_objects.map((children) => children.name);
childNamesArray.push(metadatum.name);
return childNamesArray.some((childName) => childName.toString().toLowerCase().indexOf(this.metadataNameFilterString.toString().toLowerCase()) >= 0);
}
else
return metadatum.name.toString().toLowerCase().indexOf(this.metadataNameFilterString.toString().toLowerCase()) >= 0;
},
filterByMetadatumType(metadatum) {
if (!this.hasSomeMetadataTypeFilterApplied)
return true;
if (metadatum.metadata_type_object &&
metadatum.metadata_type_object.component == 'tainacan-compound' &&
metadatum.metadata_type_options &&
metadatum.metadata_type_options.children_objects &&
metadatum.metadata_type_options.children_objects.length
) {
let childTypesArray = metadatum.metadata_type_options.children_objects.map((children) => children.metadata_type);
childTypesArray.push(metadatum.metadata_type);
for (let metadatumType of this.metadataTypeFilterOptions) {
if (metadatumType.enabled && childTypesArray.some((childType) => childType == metadatumType.type))
return true;
}
} else {
for (let metadatumType of this.metadataTypeFilterOptions) {
if (metadatumType.enabled && metadatum.metadata_type == metadatumType.type)
return true;
}
}
return false;
},
isCollapseOpen(metadatumId) {
return this.collapses[metadatumId] == true;
}
}
}
</script>

View File

@ -0,0 +1,406 @@
<template>
<div
v-if="(isRepositoryLevel && $userCaps.hasCapability('tnc_rep_edit_metadata')) || !isRepositoryLevel"
class="column available-metadata-area" >
<b-loading :active.sync="isLoadingMetadataTypes"/>
<div class="field">
<h3 class="label">{{ $i18n.get('label_available_metadata_types') }}</h3>
<draggable
v-model="availableMetadatumList"
:sort="false"
:group="{ name:'metadata', pull: 'clone', put: false, revertClone: true }"
drag-class="sortable-drag">
<div
:id="metadatum.component"
@click.prevent="addMetadatumViaButton(metadatum)"
class="available-metadatum-item"
:class="{ 'hightlighted-metadatum' : hightlightedMetadatum == metadatum.name, 'inherited-metadatum': metadatum.inherited || isRepositoryLevel }"
v-for="(metadatum, index) in availableMetadatumList"
:key="index">
<span
v-tooltip="{
content: $i18n.get('instruction_click_or_drag_metadatum_create'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip', isRepositoryLevel ? 'tainacan-repository-tooltip' : ''],
placement: 'auto-start'
}"
class="icon grip-icon">
<!-- <i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-drag"/> -->
<svg
xmlns="http://www.w3.org/2000/svg"
height="24px"
viewBox="0 0 24 24"
width="24px"
fill="currentColor">
<path
d="M0 0h24v24H0V0z"
fill="transparent"/>
<path d="M11 18c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zm-2-8c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0-6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm6 4c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/>
</svg>
</span>
<span class="metadatum-name">
{{ metadatum.name }}
<span
v-tooltip="{
popperClass: ['tainacan-tooltip', 'tooltip', isRepositoryLevel ? 'tainacan-repository-tooltip' : '', 'metadata-type-preview-tooltip'],
content: getPreviewTemplateContent(metadatum),
html: true,
delay: {
shown: 0,
hide: 100,
},
placement: 'top',
}"
class="icon preview-help-icon has-text-secondary">
<i class="tainacan-icon tainacan-icon-help"/>
</span>
</span>
<span
class="loading-spinner"
v-if="hightlightedMetadatum == metadatum.name"/>
</div>
</draggable>
<draggable
v-if="!isRepositoryLevel"
v-model="availableMetadataSectionsList"
:sort="false"
:group="{ name:'metadata', pull: 'clone', put: false, revertClone: true }"
drag-class="sortable-drag">
<div
:id="metadataSection.id"
@click.prevent="addMetadataSectionViaButton()"
class="available-metadata-section-item"
v-for="(metadataSection, index) in availableMetadataSectionsList"
:key="index">
<span
v-tooltip="{
content: $i18n.get('instruction_click_or_drag_metadatum_create'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip', isRepositoryLevel ? 'tainacan-repository-tooltip' : ''],
placement: 'auto-start'
}"
class="icon grip-icon">
<!-- <i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-drag"/> -->
<svg
xmlns="http://www.w3.org/2000/svg"
height="24px"
viewBox="0 0 24 24"
width="24px"
fill="currentColor">
<path
d="M0 0h24v24H0V0z"
fill="transparent"/>
<path d="M11 18c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zm-2-8c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0-6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm6 4c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/>
</svg>
</span>
<span class="metadatum-name">
{{ metadataSection.label }}
<span
v-tooltip="{
popperClass: ['tainacan-tooltip', 'tooltip', isRepositoryLevel ? 'tainacan-repository-tooltip' : '', 'metadata-type-preview-tooltip'],
content: '',//getPreviewTemplateContent(metadatum),
html: true,
delay: {
shown: 0,
hide: 100,
},
placement: 'top',
}"
class="icon preview-help-icon has-text-secondary">
<i class="tainacan-icon tainacan-icon-help"/>
</span>
</span>
</div>
</draggable>
</div>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex';
export default {
name: 'MetadataTypesList',
props: {
isRepositoryLevel: Boolean,
hightlightedMetadatum: String
},
data() {
return {
isLoadingMetadataTypes: true,
availableMetadataSectionsList: [{
label: this.$i18n.get('label_add_new_section'),
id: 'metadataSectionCreator'
}],
}
},
computed: {
availableMetadatumList: {
get() {
return this.getMetadatumTypes();
},
set(value) {
return this.updateMetadatumTypes(value);
}
},
},
mounted() {
this.isLoadingMetadataTypes = true;
this.fetchMetadatumTypes()
.then(() => {
this.$emit('onFinishedLoadingMetadataTypes');
this.isLoadingMetadataTypes = false;
})
.catch(() => {
this.isLoadingMetadataTypes = false;
});
},
methods: {
...mapActions('metadata', [
'fetchMetadatumTypes'
]),
...mapGetters('metadata',[
'getMetadatumTypes'
]),
addMetadatumViaVutton(metadatumType) {
this.$emit('onAddMetadatumTypeViaButton', metadatumType);
},
addMetadataSectionViaVutton() {
this.$emit('onAddMetadataSectionTypeViaButton');
},
getPreviewTemplateContent(metadatum) {
return `<div class="metadata-type-preview tainacan-form">
<span class="metadata-type-label">` + this.$i18n.get('label_metadatum_type_preview') + `</span>
<div class="field">
<span class="collapse-handle">
<span class="icon">
<i class="has-text-secondary tainacan-icon tainacan-icon-1-25em tainacan-icon-arrowdown"></i>
</span>
<label class="label has-tooltip">`
+ metadatum.name +
`</label>
</span>
<div>` + metadatum.preview_template + `</div>
</div>
</div>`;
},
}
}
</script>
<style lang="scss">
.available-metadata-area {
padding: 10px 0px 10px 10px;
margin: 0;
max-width: 500px;
min-width: 20.8333333%;
font-size: 0.875em;
@media screen and (max-width: 769px) {
max-width: 100%;
padding: 10px;
h3 {
margin: 1em 0em 1em 0em !important;
}
.available-metadatum-item::before,
.available-metadatum-item::after,
.available-metadata-section-item::before,
.available-metadata-section-item::after {
display: none !important;
}
}
h3 {
margin: 0.875em 0em 1em 0em;
}
.available-metadatum-item,
.available-metadata-section-item {
padding: 0.6em;
margin: 4px 4px 4px 1.2em;
background-color: var(--tainacan-white);
cursor: pointer;
left: 0;
height: 2.8571em;
position: relative;
border: 1px solid var(--tainacan-gray2);
border-radius: 1px;
transition: left 0.2s ease;
.grip-icon {
color: var(--tainacan-gray3);
position: relative;
}
.icon {
position: relative;
bottom: 1px;
}
.preview-help-icon {
position: absolute;
top: 6px;
}
.metadatum-name {
text-overflow: ellipsis;
overflow-x: hidden;
white-space: nowrap;
font-weight: bold;
margin-left: 0.4em;
display: inline-block;
max-width: 180px;
width: 60%;
}
&::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: 1.4286em;
border-bottom-width: 1.4286em;
left: -19px;
}
&::before {
top: -1px;
border-color: transparent var(--tainacan-gray2) transparent transparent;
border-right-width: 16px;
border-top-width: 1.4286em;
border-bottom-width: 1.4286em;
left: -20px;
}
}
.available-metadata-section-item {
margin-top: 2em;
color: var(--tainacan-secondary);
border-color: var(--tainacan-secondary);
&::before {
border-color: transparent var(--tainacan-secondary) transparent transparent;
}
}
.sortable-drag {
opacity: 1 !important;
}
.sortable-chosen {
.metadata-type-preview {
display: none;
}
}
@keyframes hightlighten {
0% {
color: #222;
background-color: var(--tainacan-white);
border-color: var(--tainacan-white);
}
25% {
color: var(--tainacan-white);
background-color: var(--tainacan-secondary);
border-color: var(--tainacan-secondary);
}
75% {
color: var(--tainacan-white);
background-color: var(--tainacan-secondary);
border-color: var(--tainacan-secondary);
}
100% {
color: #222;
background-color: var(--tainacan-white);
border-color: var(--tainacan-white);
}
}
@keyframes hightlighten-icon {
0% { color: var(--tainacan-gray3); }
25% { color: var(--tainacan-white); }
75% { color: var(--tainacan-white); }
100% { color: var(--tainacan-gray3); }
}
@keyframes hightlighten-arrow {
0% {
border-color: transparent white transparent transparent;
border-color: transparent white transparent transparent;
}
25% {
border-color: transparent var(--tainacan-secondary) transparent transparent;
border-color: transparent var(--tainacan-secondary) transparent transparent;
}
75% {
border-color: transparent var(--tainacan-secondary) transparent transparent;
border-color: transparent var(--tainacan-secondary)transparent transparent;
}
100% {
border-color: transparent white transparent transparent;
border-color: transparent white transparent transparent;
}
}
.hightlighted-metadatum {
background-color: var(--tainacan-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-metadatum-item:hover,
.available-metadata-section-item::hover {
background-color: var(--tainacan-turquoise1);
border-color: var(--tainacan-turquoise2);
position: relative;
left: -4px;
&:after {
border-color: transparent var(--tainacan-turquoise1) transparent transparent;
}
&:before {
border-color: transparent var(--tainacan-turquoise2) transparent transparent;
}
.grip-icon {
color: var(--tainacan-secondary);
}
}
}
.inherited-metadatum {
&.available-metadatum-item:hover,
&.available-metadata-section-item::hover {
background-color: var(--tainacan-blue1) !important;
border-color: var(--tainacan-blue2) !important;
.grip-icon {
color: var(--tainacan-blue5) !important;
}
&:after {
border-color: transparent var(--tainacan-blue1) transparent transparent !important;
}
&:before {
border-color: transparent var(--tainacan-blue2) transparent transparent !important;
}
}
}
</style>

View File

@ -0,0 +1,507 @@
<template>
<div class="column">
<b-loading :active.sync="isLoadingMetadata"/>
<div class="tainacan-form sub-header">
<h3>{{ $i18n.get('metadata') }}<span class="has-text-gray">{{ ( activeMetadatumList && activeMetadatumList.length ? (' (' + activeMetadatumList.length + ')') : '' ) }}</span></h3>
<template v-if="activeMetadatumList && !isLoadingMetadata">
<b-field class="header-item">
<b-dropdown
:mobile-modal="true"
:disabled="activeMetadatumList.length <= 0"
class="show metadata-options-dropdown"
aria-role="list"
trap-focus>
<button
:aria-label="$i18n.get('label_filter_by_metadata_type')"
class="button is-white"
slot="trigger">
<span>{{ $i18n.get('label_filter_by_metadata_type') }}</span>
<span class="icon">
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-arrowdown"/>
</span>
</button>
<div class="metadata-options-container">
<b-dropdown-item
v-for="(metadataType, index) in metadataTypeFilterOptions"
:key="index"
class="control"
custom
aria-role="listitem">
<b-checkbox
v-model="metadataType.enabled"
:native-value="metadataType.enabled">
{{ metadataType.name }}
</b-checkbox>
</b-dropdown-item>
</div>
</b-dropdown>
</b-field>
<b-field class="header-item">
<b-input
:placeholder="$i18n.get('instruction_type_search_metadata_filter')"
v-model="metadataNameFilterString"
icon="magnify"
size="is-small"
icon-right="close-circle"
icon-right-clickable
@icon-right-click="metadataNameFilterString = ''" />
</b-field>
</template>
</div>
<button
aria-controls="filters-items-list"
:aria-expanded="!collapseAll"
v-if="activeMetadatumList.length > 0"
class="link-style collapse-all"
@click="collapseAll = !collapseAll">
<span class="icon">
<i
:class="{ 'tainacan-icon-arrowdown' : collapseAll, 'tainacan-icon-arrowright' : !collapseAll }"
class="has-text-secondary tainacan-icon tainacan-icon-1-125em"/>
</span>
<span class="collapse-all__text">
{{ collapseAll ? $i18n.get('label_collapse_all') : $i18n.get('label_expand_all') }}
</span>
</button>
<section
v-if="activeMetadatumList.length <= 0 && !isLoadingMetadata"
class="field is-grouped-centered section">
<div class="content has-text-gray has-text-centered">
<p>
<span class="icon is-large">
<i class="tainacan-icon tainacan-icon-36px tainacan-icon-metadata"/>
</span>
</p>
<p>{{ $i18n.get('info_there_is_no_metadatum' ) }}</p>
<p>{{ $i18n.get('info_create_metadata' ) }}</p>
</div>
</section>
<!-- The Repository Metadata list -->
<draggable
v-model="activeMetadatumList"
class="active-metadata-area"
@change="handleChange($event)"
:group="{ name:'metadata', pull: false, put: true }"
:sort="false"
:handle="'.handle'"
ghost-class="sortable-ghost"
chosen-class="sortable-chosen"
filter=".not-sortable-item"
:prevent-on-filter="false"
:animation="250">
<div
v-for="(metadatum, index) in activeMetadatumList.filter((meta) => meta != undefined && meta.parent == 0)"
:key="metadatum.id"
v-show="(metadataNameFilterString == '' || filterByMetadatumName(metadatum)) && filterByMetadatumType(metadatum)">
<div
class="active-metadatum-item"
:class="{
'is-compact-item': !isCollapseOpen(metadatum.id),
'not-sortable-item': true,
'not-focusable-item': openedMetadatumId == metadatum.id,
'disabled-metadatum': metadatum.enabled == false,
'inherited-metadatum': true,
'child-metadatum': metadatum.parent > 0
}">
<div
:ref="'metadatum-handler-' + metadatum.id"
class="handle">
<span
:style="{ opacity: '0.0' }"
v-tooltip="{
content: $i18n.get('info_not_allowed_change_order_metadata'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip', 'tainacan-repository-tooltip'],
placement: 'auto-start'
}"
class="icon grip-icon">
<svg
xmlns="http://www.w3.org/2000/svg"
height="24px"
viewBox="0 0 24 24"
width="24px"
fill="currentColor">
<path
d="M0 0h24v24H0V0z"
fill="transparent"/>
<path d="M11 18c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zm-2-8c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0-6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm6 4c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/>
</svg>
</span>
<span
v-tooltip="{
content: $i18n.get('label_view_metadata_details'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip', 'tainacan-repository-tooltip'],
placement: 'auto-start'
}"
@click="$set(collapses, metadatum.id, !isCollapseOpen(metadatum.id))"
class="gray-icon icon"
:style="{ cursor: 'pointer', opacity: openedMetadatumId != metadatum.id ? '1.0' : '0.0' }">
<i :class="'tainacan-icon tainacan-icon-1-25em tainacan-icon-' + (isCollapseOpen(metadatum.id) ? 'arrowdown' : 'arrowright')" />
</span>
<span class="metadatum-name">
{{ metadatum.name }}
</span>
<span
v-if="metadatum.id != undefined && metadatum.metadata_type_object"
class="label-details"
:class="{ 'has-text-weight-bold': metadatum.metadata_type_object.core }">
<span
v-if="metadatum.required === 'yes'"
v-tooltip="{
content: $i18n.get('label_required'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip', 'tainacan-repository-tooltip'],
placement: 'auto-start'
}">
*&nbsp;
</span>
({{ metadatum.metadata_type_object.name }})
<span
v-if="metadatum.status === 'private'"
class="icon"
v-tooltip="{
content: $i18n.get('status_private'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip', 'tainacan-repository-tooltip'],
placement: 'auto-start'
}">
<i class="tainacan-icon tainacan-icon-private"/>
</span>
<span
v-tooltip="{
content: $i18n.get('label_repository_metadatum'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip', 'tainacan-repository-tooltip'],
placement: 'auto-start'
}"
class="icon icon-level-identifier">
<i
:class="{
'has-text-blue5': metadatum.enabled,
'has-text-gray3': !metadatum.enabled
}"
class="tainacan-icon tainacan-icon-repository" />
</span>
</span>
<span
class="loading-spinner"
v-if="metadatum.id == undefined"/>
<span
class="controls"
v-if="metadatum.id !== undefined">
<a
v-if="metadatum.current_user_can_edit"
:style="{ visibility:
metadatum.collection_id != collectionId
? 'hidden' : 'visible'
}"
@click.prevent="toggleMetadatumEdition(metadatum)">
<span
v-tooltip="{
content: $i18n.get('edit'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip', 'tainacan-repository-tooltip'],
placement: 'auto-start'
}"
class="icon">
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-edit"/>
</span>
</a>
<a
v-if="metadatum.current_user_can_delete"
:style="{ visibility: metadatum.collection_id != collectionId || metadatum.metadata_type_object.core ? 'hidden' : 'visible' }"
@click.prevent="removeMetadatum(metadatum)">
<span
v-tooltip="{
content: $i18n.get('delete'),
autoHide: true,
popperClass: ['tainacan-tooltip', 'tooltip', 'tainacan-repository-tooltip'],
placement: 'auto-start'
}"
class="icon">
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-delete"/>
</span>
</a>
</span>
</div>
<transition name="form-collapse">
<metadatum-details
v-if="isCollapseOpen(metadatum.id) && openedMetadatumId !== metadatum.id"
:metadatum="metadatum" />
</transition>
</div>
<!-- Child metadata list, inside each compound metadata -->
<child-metadata-list
v-if="metadatum.metadata_type_object && metadatum.metadata_type_object.component == 'tainacan-compound'"
:parent.sync="activeMetadatumList[index]"
:metadata-name-filter-string="metadataNameFilterString"
:metadata-type-filter-options="metadataTypeFilterOptions"
:has-some-metadata-type-filter-applied="hasSomeMetadataTypeFilterApplied"
:is-parent-multiple="metadatum.multiple == 'yes'"
:is-repository-level="true"
:collapse-all="collapseAll" />
<!-- Metadata edition form, for each metadata -->
<b-modal
@close="onEditionCanceled()"
:active="openedMetadatumId == metadatum.id"
trap-focus
aria-modal
aria-role="dialog"
custom-class="tainacan-modal"
:close-button-aria-label="$i18n.get('close')">
<metadatum-edition-form
:collection-id="collectionId"
:original-metadatum="metadatum"
:is-repository-level="true"
@onEditionFinished="onEditionFinished()"
@onEditionCanceled="onEditionCanceled()"
:index="index" />
</b-modal>
</div>
</draggable><!-- End of .active-metadata-area -->
</div> <!-- End of .columns -->
</template>
<script>
import MetadatumEditionForm from '../edition/metadatum-edition-form.vue';
import MetadatumDetails from '../other/metadatum-details.vue';
import ChildMetadataList from '../metadata-types/compound/child-metadata-list.vue';
import CustomDialog from '../other/custom-dialog.vue';
import { mapGetters, mapActions } from 'vuex';
export default {
name: 'RepositoryMetadataList',
components: {
MetadatumEditionForm,
ChildMetadataList,
MetadatumDetails
},
props: {
metadataTypeFilterOptions: Array
},
data() {
return {
collectionId: 'default',
isLoadingMetadata: false,
openedMetadatumId: '',
hightlightedMetadatum: '',
collapses: {},
collapseAll: false,
metadataNameFilterString: '',
metadataSearchCancel: undefined
}
},
computed: {
hasSomeMetadataTypeFilterApplied() {
return this.metadataTypeFilterOptions.length && this.metadataTypeFilterOptions.some((metadatumType) => metadatumType.enabled);
},
activeMetadatumList: {
get() {
return this.getMetadata();
},
set(value) {
this.updateMetadata(value);
}
},
},
watch: {
'$route.query': {
handler(newQuery) {
if (newQuery.edit != undefined) {
let existingMetadataIndex = this.activeMetadatumList.findIndex((metadatum) => metadatum && (metadatum.id == newQuery.edit));
if (existingMetadataIndex >= 0)
this.editMetadatum(this.activeMetadatumList[existingMetadataIndex])
}
},
immediate: true
},
collapseAll(isCollapsed) {
this.activeMetadatumList.forEach((metadatum) => this.$set(this.collapses, metadatum.id, isCollapsed));
}
},
mounted() {
this.cleanMetadata();
this.refreshMetadata();
},
beforeDestroy() {
// Cancels previous Request
if (this.metadataSearchCancel != undefined)
this.metadataSearchCancel.cancel('Metadata search Canceled.');
},
methods: {
...mapActions('metadata', [
'fetchMetadata',
'sendMetadatum',
'deleteMetadatum',
'updateMetadata',
'cleanMetadata'
]),
...mapGetters('metadata',[
'getMetadata'
]),
handleChange(event) {
if (event.added)
this.addNewMetadatum(event.added.element, event.added.newIndex);
else if (event.removed)
this.removeMetadatum(event.removed.element);
},
addMetadatumViaButton(metadatumType) {
let lastIndex = this.activeMetadatumList.length;
this.addNewMetadatum(metadatumType, lastIndex);
// Higlights the clicked metadatum
this.hightlightedMetadatum = metadatumType.name;
this.$emit('onUpdatehightlightedMetadatum', this.hightlightedMetadatum);
},
addNewMetadatum(newMetadatum, newIndex) {
this.sendMetadatum({
collectionId: this.collectionId,
name: newMetadatum.name,
metadatumType: newMetadatum.className,
status: 'auto-draft',
isRepositoryLevel: true,
newIndex: newIndex,
parent: '0'
})
.then((metadatum) => {
this.toggleMetadatumEdition(metadatum);
this.hightlightedMetadatum = '';
this.$emit('onUpdatehightlightedMetadatum', this.hightlightedMetadatum);
})
.catch((error) => {
this.$console.error(error);
});
},
removeMetadatum(removedMetadatum) {
this.$buefy.modal.open({
parent: this,
component: CustomDialog,
props: {
icon: 'alert',
title: this.$i18n.get('label_warning'),
message: this.$i18n.get('info_warning_metadatum_delete'),
onConfirm: () => {
this.deleteMetadatum({
collectionId: this.collectionId,
metadatumId: removedMetadatum.id,
isRepositoryLevel: true
})
.catch(() => {
this.$console.log("Error deleting metadatum.")
});
}
},
trapFocus: true,
customClass: 'tainacan-modal',
closeButtonAriaLabel: this.$i18n.get('close')
});
},
toggleMetadatumEdition(metadatum) {
this.$router.push({ query: { edit: metadatum.id } });
},
editMetadatum(metadatum) {
this.openedMetadatumId = metadatum.id;
},
onEditionFinished() {
this.openedMetadatumId = '';
this.$router.push({ query: {}});
},
onEditionCanceled() {
this.openedMetadatumId = '';
this.$router.push({ query: {}});
},
refreshMetadata() {
this.isLoadingMetadata = true;
// Cancels previous Request
if (this.metadataSearchCancel != undefined)
this.metadataSearchCancel.cancel('Metadata search Canceled.');
this.fetchMetadata({
collectionId: this.collectionId,
isRepositoryLevel: true,
isContextEdit: true,
includeDisabled: true,
parent: '0',
includeOptionsAsHtml: true
}).then((resp) => {
resp.request
.then(() => {
this.isLoadingMetadata = false;
// Checks URL as router watcher would not wait for list to load
if (this.$route.query.edit != undefined) {
let existingMetadataIndex = this.activeMetadatumList.findIndex((metadatum) => metadatum.id == this.$route.query.edit);
if (existingMetadataIndex >= 0)
this.editMetadatum(this.activeMetadatumList[existingMetadataIndex]);
}
})
.catch(() => {
this.isLoadingMetadata = false;
});
// Search Request Token for cancelling
this.metadataSearchCancel = resp.source;
})
.catch(() => this.isLoadingMetadata = false);
},
filterByMetadatumName(metadatum) {
if (metadatum.metadata_type_object &&
metadatum.metadata_type_object.component == 'tainacan-compound' &&
metadatum.metadata_type_options &&
metadatum.metadata_type_options.children_objects &&
metadatum.metadata_type_options.children_objects.length
) {
let childNamesArray = metadatum.metadata_type_options.children_objects.map((children) => children.name);
childNamesArray.push(metadatum.name);
return childNamesArray.some((childName) => childName.toString().toLowerCase().indexOf(this.metadataNameFilterString.toString().toLowerCase()) >= 0);
}
else
return metadatum.name.toString().toLowerCase().indexOf(this.metadataNameFilterString.toString().toLowerCase()) >= 0;
},
filterByMetadatumType(metadatum) {
if (!this.hasSomeMetadataTypeFilterApplied)
return true;
if (metadatum.metadata_type_object &&
metadatum.metadata_type_object.component == 'tainacan-compound' &&
metadatum.metadata_type_options &&
metadatum.metadata_type_options.children_objects &&
metadatum.metadata_type_options.children_objects.length
) {
let childTypesArray = metadatum.metadata_type_options.children_objects.map((children) => children.metadata_type);
childTypesArray.push(metadatum.metadata_type);
for (let metadatumType of this.metadataTypeFilterOptions) {
if (metadatumType.enabled && childTypesArray.some((childType) => childType == metadatumType.type))
return true;
}
} else {
for (let metadatumType of this.metadataTypeFilterOptions) {
if (metadatumType.enabled && metadatum.metadata_type == metadatumType.type)
return true;
}
}
return false;
},
isCollapseOpen(metadatumId) {
return this.collapses[metadatumId] == true;
}
}
}
</script>

View File

@ -100,7 +100,7 @@ export const setMetadataSectionMetadata = (state, { metadataSectionId, metadata
if (existingIndex >= 0) {
let metadataSection = state.metadataSections[existingIndex];
Vue.set(metadataSection, 'metadata_list', metadata);
metadataSection['metadata_list'] = metadata;
Vue.set(state.metadataSections, existingIndex, metadataSection);
}
}

File diff suppressed because it is too large Load Diff