Begins implementation of Related Items list on the item single edition page. #521

This commit is contained in:
mateuswetah 2021-06-23 17:33:29 -03:00
parent 476a0021f5
commit 8fbe444f11
4 changed files with 323 additions and 6 deletions

View File

@ -561,6 +561,33 @@
</div>
</b-tab-item>
<!-- Related items -->
<b-tab-item v-if="totalRelatedItems">
<template slot="header">
<span class="icon has-text-gray4">
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-processes tainacan-icon-rotate-270"/>
</span>
<span>
{{ $i18n.get('label_related_items') }}
<span class="has-text-gray">
({{ totalRelatedItems }})
</span>
</span>
</template>
<div class="attachments-list-heading">
<p>
{{ $i18n.get("info_related_items") }}
</p>
</div>
<related-items-list
:related-items="item.related_items"
:is-editable="true"
:is-loading.sync="isLoading" />
</b-tab-item>
</b-tabs>
</div>
</div>
@ -800,6 +827,7 @@ import { eventBusItemMetadata } from '../../js/event-bus-item-metadata';
import wpMediaFrames from '../../js/wp-media-frames';
import FileItem from '../other/file-item.vue';
import DocumentItem from '../other/document-item.vue';
import RelatedItemsList from '../lists/related-items-list.vue';
import CustomDialog from '../other/custom-dialog.vue';
import AttachmentsList from '../lists/attachments-list.vue';
import { formHooks } from '../../js/mixins';
@ -811,6 +839,7 @@ export default {
FileItem,
DocumentItem,
AttachmentsList,
RelatedItemsList,
ItemMetadatumErrorsTooltip
},
mixins: [ formHooks ],
@ -873,6 +902,9 @@ export default {
totalAttachments() {
return this.getTotalAttachments();
},
totalRelatedItems() {
return (this.item && this.item.related_items) ? Object.values(this.item.related_items).reduce((totalItems, aRelatedItemsGroup) => totalItems + parseInt(aRelatedItemsGroup.total_items), 0) : false;
},
formErrors() {
return eventBusItemMetadata && eventBusItemMetadata.errors && eventBusItemMetadata.errors.length ? eventBusItemMetadata.errors : []
}
@ -1501,7 +1533,7 @@ export default {
this.fetchItem({
itemId: this.itemId,
contextEdit: true,
fetchOnly: 'title,thumbnail,status,modification_date,document_type,document,comment_status,document_as_html'
fetchOnly: 'title,thumbnail,status,modification_date,document_type,document,comment_status,document_as_html,related_items'
})
.then((resp) => {
resp.request.then((res) => {

View File

@ -0,0 +1,240 @@
<template>
<div>
<div class="table-container">
<b-loading
is-full-page="false"
:active.sync="isLoading" />
<div class="table-wrapper">
<div class="related-items-list">
<div
v-for="(relatedItemGroup, index) of relatedItemsArray"
:key="index"
class="related-item-group">
<div class="columns">
<div class="column is-narrow">
<div class="section-status">
<div class="field has-addons">
<span>
<span class="icon">
<i class="tainacan-icon tainacan-icon-collection"/>
</span>
{{ relatedItemGroup.collection_name ? relatedItemGroup.collection_name : '' }}
</span>
</div>
</div>
</div>
<div class="column is-narrow">
<div class="section-status">
<div class="field has-addons">
<span>
<span class="icon">
<i class="tainacan-icon tainacan-icon-metadata"/>
</span>
{{ relatedItemGroup.metadata_name ? relatedItemGroup.metadata_name : '' }}
</span>
</div>
</div>
</div>
</div>
<table class="tainacan-table">
<thead>
<tr>
<!-- Status -->
<th>
&nbsp;
</th>
<!-- Displayed Metadata -->
<th
v-for="(column, columnIndex) in displayedMetadata"
:key="columnIndex"
class="column-default-width"
:class="{
'thumbnail-cell': column.metadatum == 'row_thumbnail',
'column-small-width' : column.metadata_type_object != undefined ? (column.metadata_type_object.primitive_type == 'date' ||
column.metadata_type_object.primitive_type == 'float' ||
column.metadata_type_object.primitive_type == 'int') : false,
'column-medium-width' : column.metadata_type_object != undefined ? (column.metadata_type_object.primitive_type == 'term' ||
column.metadata_type_object.primitive_type == 'item') : false,
'column-large-width' : column.metadata_type_object != undefined ? (column.metadata_type_object.primitive_type == 'long_string' ||
column.metadata_type_object.primitive_type == 'compound' ||
column.metadata_type_object.related_mapped_prop == 'description') : false,
}">
<div class="th-wrap">{{ column.name }}</div>
</th>
<th
v-if="isEditable && relatedItemGroup.items.findIndex((relatedItem) => relatedItem.current_user_can_edit || relatedItem.current_user_can_delete) >= 0"
class="actions-header">
&nbsp;
<!-- nothing to show on header for actions cell-->
</th>
</tr>
</thead>
<tbody>
<tr
v-for="(relatedItem, itemIndex) of relatedItemGroup.items"
:key="itemIndex">
<!-- Checking list -->
<td class="status-cell">
<span
v-if="$statusHelper.hasIcon(relatedItem.status)"
class="icon has-text-gray"
v-tooltip="{
content: $i18n.get('status_' + relatedItem.status),
autoHide: true,
placement: 'auto-start'
}">
<i
class="tainacan-icon tainacan-icon-1em"
:class="$statusHelper.getIcon(relatedItem.status)"
/>
</span>
</td>
<!-- Item Displayed Metadata -->
<td
:key="columnIndex"
v-for="(column, columnIndex) in displayedMetadata"
class="column-default-width"
:class="{ 'metadata-type-textarea': column.metadata_type_object != undefined && column.metadata_type_object.component == 'tainacan-textarea',
'thumbnail-cell': column.metadatum == 'row_thumbnail',
'column-main-content' : column.metadata_type_object != undefined ? (column.metadata_type_object.related_mapped_prop == 'title') : false,
'column-needed-width column-align-right' : column.metadata_type_object != undefined ? (column.metadata_type_object.primitive_type == 'float' ||
column.metadata_type_object.primitive_type == 'int' ) : false,
'column-small-width' : column.metadata_type_object != undefined ? (column.metadata_type_object.primitive_type == 'date' ||
column.metadata_type_object.primitive_type == 'int' ||
column.metadata_type_object.primitive_type == 'float') : false,
'column-medium-width' : column.metadata_type_object != undefined ? (column.metadata_type_object.primitive_type == 'item' ||
column.metadata_type_object.primitive_type == 'term') : false,
'column-large-width' : column.metadata_type_object != undefined ? (column.metadata_type_object.primitive_type == 'long_string' ||
column.metadata_type_object.primitive_type == 'compound' ||
column.metadata_type_object.related_mapped_prop == 'description') : false,
}">
<p
v-tooltip="{
delay: {
show: 500,
hide: 300,
},
content: relatedItem.title != undefined && relatedItem.title != '' ? relatedItem.title : `<span class='has-text-gray3 is-italic'>` + $i18n.get('label_value_not_provided') + `</span>`,
html: true,
autoHide: false,
placement: 'auto-start'
}"
v-if="collectionId == undefined &&
column.metadata_type_object != undefined &&
column.metadata_type_object.related_mapped_prop == 'title'"
v-html="`<span class='sr-only'>` + column.name + ': </span>' + ((relatedItem.title != undefined && relatedItem.title != '') ? relatedItem.title : `<span class='has-text-gray3 is-italic'>` + $i18n.get('label_value_not_provided') + `</span>`)"/>
<span
v-if="column.metadatum == 'row_thumbnail'"
class="table-thumb">
<blur-hash-image
:width="$thumbHelper.getWidth(relatedItem['thumbnail'], 'tainacan-small', 40)"
:height="$thumbHelper.getHeight(relatedItem['thumbnail'], 'tainacan-small', 40)"
:hash="$thumbHelper.getBlurhashString(relatedItem['thumbnail'], 'tainacan-small')"
:src="$thumbHelper.getSrc(relatedItem['thumbnail'], 'tainacan-small', relatedItem.document_mimetype)"
:alt="relatedItem.thumbnail_alt ? relatedItem.thumbnail_alt : $i18n.get('label_thumbnail')"
:transition-duration="500"
/>
</span>
</td>
<!-- Actions -->
<td
v-if="isEditable && (relatedItem.current_user_can_edit || relatedItem.current_user_can_delete)"
class="actions-cell"
:label="$i18n.get('label_actions')">
<div class="actions-container">
<a
v-if="!relatedItem.status != 'trash'"
id="button-edit"
:aria-label="$i18n.getFrom('items','edit_item')">
<span
v-tooltip="{
content: $i18n.get('edit'),
autoHide: true,
placement: 'auto'
}"
class="icon">
<i class="has-text-secondary tainacan-icon tainacan-icon-1-25em tainacan-icon-edit"/>
</span>
</a>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'RelatedItemsList',
props: {
relatedItems: Object,
isLoading: Boolean,
isEditable: Boolean,
},
data() {
return {
displayedMetadata: [
{
name: this.$i18n.get('label_thumbnail'),
metadatum: 'row_thumbnail',
slug: 'thumbnail',
},
{
name: this.$i18n.get('label_title'),
metadatum: 'row_title',
metadata_type_object: {core: true, related_mapped_prop: 'title'},
slug: 'title',
}
]
}
},
computed: {
relatedItemsArray() {
return this.relatedItems ? Object.values(this.relatedItems).filter((aRelatedItemGroup) => aRelatedItemGroup.total_items) : [];
}
}
}
</script>
<style lang="scss" scoped>
.section-status {
padding-bottom: 16px;
margin-left: -0.875rem;
font-size: 0.875em;
.field {
padding: 10px 0 14px 0px !important;
.icon {
font-size: 1.125em !important;
color: var(--tainacan-info-color);
}
}
}
.related-items-list {
.related-item-group {
&:not(:last-child) {
border-bottom: 1px dashed var(--tainacan-info-color);
}
.tainacan-table {
margin-top: -2rem;
margin-bottom: 1rem;
}
}
}
</style>

View File

@ -253,7 +253,7 @@
<b-tabs v-model="activeTab">
<b-tab-item>
<template slot="header">
<span class="icon has-text-gray4">
<span class="icon has-text-gray5">
<i class="tainacan-icon tainacan-icon-18px tainacan-icon-metadata"/>
</span>
<span>{{ $i18n.get('metadata') }}</span>
@ -293,7 +293,7 @@
<b-tab-item>
<template slot="header">
<span class="icon has-text-gray4">
<span class="icon has-text-gray5">
<i class="tainacan-icon tainacan-icon-18px tainacan-icon-attachments"/>
</span>
<span>
@ -313,9 +313,36 @@
@isLoadingAttachments="(isLoading) => isLoadingAttachments = isLoading" />
</b-tab-item>
<!-- Related items -->
<b-tab-item v-if="totalRelatedItems">
<template slot="header">
<span class="icon has-text-gray5">
<i class="tainacan-icon tainacan-icon-1-25em tainacan-icon-processes tainacan-icon-rotate-270"/>
</span>
<span>
{{ $i18n.get('label_related_items') }}
<span class="has-text-gray">
({{ totalRelatedItems }})
</span>
</span>
</template>
<div class="attachments-list-heading">
<p>
{{ $i18n.get("info_related_items") }}
</p>
</div>
<related-items-list
:related-items="item.related_items"
:is-editable="false"
:is-loading.sync="isLoading" />
</b-tab-item>
<b-tab-item>
<template slot="header">
<span class="icon has-text-gray4">
<span class="icon has-text-gray5">
<i class="tainacan-icon tainacan-icon-18px tainacan-icon-activities"/>
</span>
<span>{{ $i18n.get('activities') }}</span>
@ -380,6 +407,7 @@
import ActivitiesPage from '../lists/activities-page.vue';
import ExposersModal from '../../components/modals/exposers-modal.vue';
import AttachmentsList from '../../components/lists/attachments-list.vue';
import RelatedItemsList from '../../components/lists/related-items-list.vue';
export default {
name: 'ItemPage',
@ -387,6 +415,7 @@
FileItem,
DocumentItem,
ActivitiesPage,
RelatedItemsList,
AttachmentsList
},
mixins: [formHooks],
@ -414,6 +443,9 @@
metadatumList() {
return JSON.parse(JSON.stringify(this.getItemMetadata()));
},
totalRelatedItems() {
return (this.item && this.item.related_items) ? Object.values(this.item.related_items).reduce((totalItems, aRelatedItemsGroup) => totalItems + parseInt(aRelatedItemsGroup.total_items), 0) : false;
},
totalAttachments() {
return this.getTotalAttachments();
},
@ -437,7 +469,7 @@
this.fetchItem({
itemId: this.itemId,
contextEdit: true,
fetchOnly: 'title,thumbnail,status,modification_date,document_type,document_mimetype,document,comment_status,document_as_html'
fetchOnly: 'title,thumbnail,status,modification_date,document_type,document_mimetype,document,comment_status,document_as_html,related_items'
})
.then((resp) => {
resp.request.then((item) => {
@ -717,6 +749,17 @@
}
}
.attachments-list-heading {
display: flex;
align-items: center;
margin-top: 24px;
margin-bottom: 24px;
button {
margin-right: 12px;
}
}
.footer {
padding: 18px var(--tainacan-one-column);
position: absolute;

View File

@ -586,6 +586,7 @@ return apply_filters( 'tainacan-admin-i18n', [
'label_pan_selection' => __( 'Pan selection', 'tainacan'),
'label_reset_zoom' => __( 'Reset zoom', 'tainacan'),
'label_chart_export_options' => __( 'Chart export options', 'tainacan'),
'label_related_items' => __( 'Items that are related', 'tainacan'),
// Instructions. More complex sentences to guide user and placeholders
'instruction_delete_selected_collections' => __( 'Delete selected collections', 'tainacan' ),
@ -870,7 +871,8 @@ return apply_filters( 'tainacan-admin-i18n', [
'info_no_taxonomy_metadata_created' => __( 'No taxonomy metadata created yet', 'tainacan'),
'label_amount_of_metadata_of_type' => __( 'Amount of metadata of this type', 'tainacan'),
'info_child_terms_chart' => __( 'Click on the term bar on the chart aside to see its child terms (if any) in this panel', 'tainacan' ),
'info_related_items' => __( 'These are items that are related to this item via their own relationship type metadata. You can edit such relation on their pages.', 'tainacan'),
/* Activity actions */
'action_update-metadata-value' => __( 'Item Metadata Value Updates', 'tainacan'),
'action_update' => __( 'General Updates', 'tainacan'),