Adds pagination to attachments list. Creates separate component for it. #289

This commit is contained in:
Mateus Machado Luna 2019-08-06 12:12:44 -03:00
parent d75d30baa8
commit 4bf95048c7
8 changed files with 291 additions and 123 deletions

View File

@ -496,47 +496,28 @@
<span>
{{ $i18n.get('label_attachments') }}
<span
v-if="attachmentsList && attachmentsList.length"
v-if="totalAttachments != null && totalAttachments != undefined"
class="has-text-gray">
({{ attachmentsList.length }})
({{ totalAttachments }})
</span>
</span>
</template>
<div class="section-box section-attachments">
<div v-if="item != undefined && item.id != undefined">
<br>
<button
style="margin-left: calc(4.666667% + 12px)"
type="button"
class="button is-secondary"
@click.prevent="attachmentMediaFrame.openFrame($event)">
{{ $i18n.get("label_edit_attachments") }}
</button>
<div class="uploaded-files">
<div
class="file-item-container"
v-for="(attachment, index) in attachmentsList"
:key="index">
<file-item
:style="{ margin: 15 + 'px'}"
v-if="attachmentsList.length > 0"
:modal-on-click="true"
:show-name="true"
:file="attachment"/>
<span class="file-item-control">
<a
@click="deleteAttachment(attachment)"
v-tooltip="{
content: $i18n.get('delete'),
autoHide: true,
placement: 'bottom'
}"
class="icon">
<i class="tainacan-icon tainacan-icon-20px tainacan-icon-delete"/>
</a>
</span>
</div>
<p v-if="attachmentsList.length <= 0"><br>{{ $i18n.get('info_no_attachments_on_item_yet') }}</p>
</div>
<attachments-list
v-if="item != undefined && item.id != undefined"
:item="item"
:is-editable="true"
@onDeleteAttachment="deleteAttachment($event)"/>
</div>
</b-tab-item>
@ -729,6 +710,7 @@ import wpMediaFrames from '../../js/wp-media-frames';
import FileItem from '../other/file-item.vue';
import DocumentItem from '../other/document-item.vue';
import CustomDialog from '../other/custom-dialog.vue';
import AttachmentsList from '../lists/attachments-list.vue';
import { formHooks } from '../../js/mixins';
export default {
@ -777,9 +759,6 @@ export default {
metadatumList() {
return JSON.parse(JSON.stringify(this.getMetadata()));
},
attachmentsList(){
return this.getAttachments().filter((attachment) => attachment.id != this.item.document && attachment.id != this.form.document);
},
lastUpdated() {
return this.getLastUpdated();
},
@ -788,11 +767,15 @@ export default {
},
itemIdInSequence() {
return this.getItemIdInSequence();
},
totalAttachments() {
return this.getTotalAttachments();
}
},
components: {
FileItem,
DocumentItem
DocumentItem,
AttachmentsList
},
watch: {
'$route.params.itemPosition'(newItemPosition, oldItemPosition) {
@ -835,15 +818,15 @@ export default {
'fetchItem',
'cleanMetadata',
'sendAttachments',
'updateThumbnail',
'fetchAttachments',
'updateThumbnail',
'cleanLastUpdated',
'setLastUpdated',
'removeAttachmentFromItem'
]),
...mapGetters('item',[
'getMetadata',
'getAttachments',
'getTotalAttachments',
'getLastUpdated'
]),
...mapActions('collection', [
@ -945,7 +928,7 @@ export default {
this.form.comment_status = this.item.comment_status;
this.loadMetadata();
this.fetchAttachments(this.itemId);
this.fetchAttachments({ page: 1, attachmentsPerPage: 24, itemId: this.itemId });
})
.catch(error => this.$console.error(error));
@ -1045,13 +1028,17 @@ export default {
item_id: this.itemId,
document: this.form.document,
document_type: this.form.document_type
}).catch((errors) => {
for (let error of errors.errors) {
for (let metadatum of Object.keys(error)){
eventBus.errors.push({ metadatum_id: metadatum, errors: error[metadatum]});
}
})
.then(() => {
this.fetchAttachments({ page: 1, attachmentsPerPage: 24, itemId: this.itemId, documentId: this.item.document });
})
.catch((errors) => {
for (let error of errors.errors) {
for (let metadatum of Object.keys(error)){
eventBus.errors.push({ metadatum_id: metadatum, errors: error[metadatum]});
}
this.formErrorMessage = errors.error_message;
}
this.formErrorMessage = errors.error_message;
});
},
deleteThumbnail() {
@ -1064,7 +1051,6 @@ export default {
});
},
deleteAttachment(attachment) {
this.$modal.open({
parent: this,
component: CustomDialog,
@ -1074,7 +1060,9 @@ export default {
message: this.$i18n.get('info_warning_attachment_delete'),
onConfirm: () => {
this.removeAttachmentFromItem(attachment.id)
.then(() => { })
.then(() => {
this.fetchAttachments({ page: 1, attachmentsPerPage: 24, itemId: this.itemId, documentId: this.item.document });
})
.catch((error) => {
this.$console.error(error);
});
@ -1144,7 +1132,7 @@ export default {
relatedPostId: this.itemId,
onSave: () => {
// Fetch current existing attachments
this.fetchAttachments(this.itemId);
this.fetchAttachments({ page: 1, attachmentsPerPage: 24, itemId: this.itemId, documentId: this.item.document });
}
}
);
@ -1232,7 +1220,7 @@ export default {
});
// Fetch current existing attachments
this.fetchAttachments(this.itemId);
this.fetchAttachments({ page: 1, attachmentsPerPage: 24, itemId: this.itemId, documentId: this.item.document });
},
onNextInSequence() {
this.sequenceRightDirection = true;
@ -1502,48 +1490,8 @@ export default {
}
}
}
.section-attachments {
margin-top: 0px;
p { margin: 4px 15px }
}
.uploaded-files {
display: flex;
flex-flow: wrap;
margin-left: -15px;
margin-right: -15px;
.file-item-container {
position: relative;
&:hover .file-item-control {
display: block;
visibility: visible;
opacity: 1;
}
.file-item-control {
position: absolute;
background-color: $gray1;
width: 112px;
margin: 15px;
bottom: 0px;
padding: 2px 8px 4px 8px;
text-align: right;
display: none;
visibility: hidden;
opacity: 0;
transition: opacity ease 0.2s, visibility ease 0.2s, display ease 0.2s;
.icon {
cursor: pointer;
}
}
}
}
.document-field {
.document-buttons-row {
text-align: right;
top: -21px;

View File

@ -0,0 +1,213 @@
<template>
<div>
<div class="table-container">
<div
v-if="attachments.length > 0"
class="table-wrapper">
<div class="uploaded-files">
<div
v-for="(attachment, index) in attachments"
:key="index"
class="file-item-container">
<file-item
:show-name="true"
:modal-on-click="true"
:file="attachment"/>
<span
v-if="isEditable"
class="file-item-control">
<a
@click="onDeleteAttachment(attachment)"
v-tooltip="{
content: $i18n.get('delete'),
autoHide: true,
placement: 'bottom'
}"
class="icon">
<i class="tainacan-icon tainacan-icon-20px tainacan-icon-delete"/>
</a>
</span>
</div>
</div>
</div>
<!-- Empty state image -->
<div v-if="(totalAttachments <= 0 || !totalAttachments) && !isLoading">
<section class="section">
<div class="content has-text-grey has-text-centered">
<span class="icon">
<i class="tainacan-icon tainacan-icon-20px tainacan-icon-attachments"/>
</span>
<p>{{ $i18n.get('info_no_attachments_on_item_yet') }}</p>
</div>
</section>
</div>
</div>
<div
class="pagination-area"
v-if="attachments.length > 0">
<div class="shown-items">
{{
$i18n.get('info_showing_attachments') +
(attachmentsPerPage * (attachmentsPage - 1) + 1) +
$i18n.get('info_to') +
getLastAttachmentsNumber() +
$i18n.get('info_of') + totalAttachments + '.'
}}
</div>
<!-- <div class="items-per-page">
<b-field
horizontal
:label="$i18n.get('label_attachments_per_page')">
<b-select
:value="attachmentsPerPage"
@input="onChangeAttachmentsPerPage"
:disabled="attachments.length <= 0">
<option value="12">12</option>
<option value="24">24</option>
<option value="48">48</option>
<option value="96">96</option>
</b-select>
</b-field>
</div> -->
<div class="pagination">
<b-pagination
@change="onPageChange"
:total="totalAttachments"
:current.sync="attachmentsPage"
order="is-centered"
size="is-small"
:per-page="attachmentsPerPage"
:aria-next-label="$i18n.get('label_next_page')"
:aria-previous-label="$i18n.get('label_previous_page')"
:aria-page-label="$i18n.get('label_page')"
:aria-current-label="$i18n.get('label_current_page')"/>
</div>
</div>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex';
import FileItem from '../../components/other/file-item.vue';
export default {
name: 'AttachmentsList',
components: {
FileItem
},
data() {
return {
isLoading: false,
attachmentsPage: 1,
attachmentsPerPage: 24
}
},
props: {
item: Object,
isEditable: Boolean
},
computed: {
attachments() {
return this.getAttachments();
},
totalAttachments() {
return this.getTotalAttachments();
}
},
methods: {
...mapActions('item', [
'fetchAttachments',
]),
...mapGetters('item', [
'getAttachments',
'getTotalAttachments'
]),
onChangeAttachmentsPerPage(value) {
if (value != this.attachmentsPerPage) {
this.$userPrefs.set('attachments_per_page', value)
.then((newValue) => {
this.attachmentsPerPage = newValue;
})
.catch(() => {
this.$console.log("Error settings user prefs for attachments per page")
});
}
this.attachmentsPerPage = value;
this.loadAttachments();
},
onPageChange(page) {
this.attachmentsPage = page;
this.loadAttachments();
},
getLastAttachmentsNumber() {
let last = (Number(this.attachmentsPerPage * (this.attachmentsPage - 1)) + Number(this.attachmentsPerPage));
return last > this.totalAttachments ? this.totalAttachments : last;
},
loadAttachments() {
this.isLoading = true;
this.fetchAttachments({
page: this.attachmentsPage,
attachmentsPerPage: this.attachmentsPerPage,
itemId: this.item.id,
documentId: this.item.document
})
.then((response) => {
this.isLoading = false;
this.totalAttachments = response.total;
})
.catch((error) => {
this.isLoading = false;
this.$console.error(error);
})
},
onDeleteAttachment(attachment) {
this.$emit('onDeleteAttachment', attachment);
}
},
created() {
// Get attachments
this.loadAttachments();
}
}
</script>
<style lang="scss" scoped>
.uploaded-files {
display: flex;
flex-flow: wrap;
.file-item-container {
margin: 15px;
position: relative;
&:hover .file-item-control {
display: block;
visibility: visible;
opacity: 1;
}
.file-item-control {
position: absolute;
background-color: #f2f2f2;
width: 112px;
margin: 6px 0;
bottom: 0px;
padding: 2px 8px 4px 8px;
text-align: right;
display: none;
visibility: hidden;
opacity: 0;
transition: opacity ease 0.2s, visibility ease 0.2s, display ease 0.2s;
.icon {
cursor: pointer;
}
}
}
}
</style>

View File

@ -233,27 +233,16 @@
<span>
{{ $i18n.get('label_attachments') }}
<span
v-if="attachmentsList && attachmentsList.length"
v-if="totalAttachments != null && totalAttachments != undefined"
class="has-text-gray">
({{ attachmentsList.length }})
({{ totalAttachments }})
</span>
</span>
</template>
<div class="section-box section-attachments">
<div class="uploaded-files">
<file-item
:style="{ margin: 15 + 'px'}"
v-if="attachmentsList.length > 0"
v-for="(attachment, index) in attachmentsList"
:key="index"
:show-name="true"
:modal-on-click="true"
:file="attachment"/>
<p v-if="attachmentsList.length <= 0"><br>{{
$i18n.get('info_no_attachments_on_item_yet') }}</p>
</div>
</div>
<attachments-list
v-if="item != undefined && item.id != undefined"
:item="item" />
</b-tab-item>
<b-tab-item>
@ -322,6 +311,7 @@
import {formHooks} from '../../js/mixins';
import ActivitiesPage from '../lists/activities-page.vue';
import ExposersModal from '../../components/other/exposers-modal.vue';
import AttachmentsList from '../../components/lists/attachments-list.vue';
export default {
name: 'ItemPage',
@ -330,7 +320,8 @@
FileItem,
DocumentItem,
ActivitiesPage,
ExposersModal
ExposersModal,
AttachmentsList
},
data() {
return {
@ -355,14 +346,13 @@
metadatumList() {
return JSON.parse(JSON.stringify(this.getMetadata()));
},
attachmentsList() {
return this.getAttachments().filter((attachment) => attachment.id != this.item.document);
},
totalAttachments() {
return this.getTotalAttachments();
}
},
methods: {
...mapActions('item', [
'fetchItem',
'fetchAttachments',
'fetchMetadata',
]),
...mapActions('collection', [
@ -372,7 +362,7 @@
...mapGetters('item', [
'getItem',
'getMetadata',
'getAttachments'
'getTotalAttachments'
]),
loadMetadata() {
// Obtains Item Metadatum
@ -416,15 +406,12 @@
this.loadMetadata();
});
// Obtains collection name
if (!this.isRepositoryLevel) {
this.fetchCollectionName(this.collectionId).then((collectionName) => {
this.collectionName = collectionName;
});
}
// Get attachments
this.fetchAttachments(this.itemId);
// Obtains collection name
if (!this.isRepositoryLevel) {
this.fetchCollectionName(this.collectionId).then((collectionName) => {
this.collectionName = collectionName;
});
}
// Obtains collection Comment Status
this.fetchCollectionAllowComments(this.collectionId).then((collectionAllowComments) => {

View File

@ -171,6 +171,7 @@ return apply_filters( 'tainacan-admin-i18n', [
'label_taxonomies_per_page' => __( 'Taxonomies per Page:', 'tainacan' ),
'label_activities_per_page' => __( 'Activities per Page:', 'tainacan' ),
'label_items_per_page' => __( 'Items per Page:', 'tainacan' ),
'label_attachments_per_page' => __( 'Attachments per Page:', 'tainacan' ),
'label_processes_per_page' => __( 'Processes per Page:', 'tainacan' ),
'label_go_to_page' => __( 'Go to Page:', 'tainacan' ),
'label_active_metadata' => __( 'Active Metadata', 'tainacan' ),
@ -551,6 +552,7 @@ return apply_filters( 'tainacan-admin-i18n', [
'info_warning_collection_related' => __( 'The metadata Collection related is required', 'tainacan' ),
'info_warning_no_metadata_found' => __( 'No metadata found in this collection', 'tainacan' ),
'info_showing_items' => __( 'Showing items ', 'tainacan' ),
'info_showing_attachments' => __( 'Showing attachments ', 'tainacan' ),
'info_showing_collections' => __( 'Showing collections ', 'tainacan' ),
'info_showing_taxonomies' => __( 'Showing taxonomies ', 'tainacan' ),
'info_showing_activities' => __( 'Showing activities ', 'tainacan' ),

View File

@ -202,14 +202,23 @@ export const removeAttachmentFromItem = ( { commit }, attachmentId) => {
});
};
export const fetchAttachments = ({ commit }, item_id) => {
export const fetchAttachments = ({ commit }, { page, attachmentsPerPage, itemId, documentId }) => {
commit('cleanAttachments');
commit('setTotalAttachments', null);
return new Promise((resolve, reject) => {
axios.wp.get('/media/?parent=' + item_id + '&per_page=100&paged=1')
axios.wp.get('/media/?parent=' + itemId + '&per_page=' + attachmentsPerPage + '&page=' + page)
.then(res => {
let attachments = res.data;
let attachments = res.data.filter((attachment) => attachment.id != documentId);
let total = documentId ? res.headers['x-wp-total'] - 1 : res.headers['x-wp-total'];
commit('setAttachments', attachments);
resolve( attachments );
commit('setTotalAttachments', total);
resolve( {
attachments: attachments,
total: total
});
})
.catch(error => {
reject( error );

View File

@ -17,3 +17,7 @@ export const getItemTitle = state => {
export const getAttachments = state => {
return state.attachments;
}
export const getTotalAttachments = state => {
return state.totalAttachments;
}

View File

@ -10,7 +10,8 @@ const state = {
attachment: {},
attachments: [],
lastUpdated: '',
comment_status: ''
comment_status: '',
totalAttachments: 0
};

View File

@ -42,6 +42,10 @@ export const cleanAttachments = (state) => {
state.attachments = [];
}
export const setTotalAttachments = ( state, total) => {
state.totalAttachments = total;
}
export const setItemTitle = ( state, itemTitle ) => {
state.itemTitle = itemTitle;
}