scinote-web/app/javascript/vue/shared/content/attachments.vue

194 lines
6.3 KiB
Vue
Raw Normal View History

2022-05-19 17:13:34 +08:00
<template>
2023-10-19 17:45:01 +08:00
<div class="content__attachments pr-8" :id='"content__attachments-" + parent.id'>
2023-10-09 17:28:18 +08:00
<div class="sci-divider my-6"></div>
<div class="content__attachments-actions">
2022-05-19 17:13:34 +08:00
<div class="title">
2023-09-14 18:12:15 +08:00
{{ i18n.t('protocols.steps.files', {count: attachments.length}) }}
2022-05-19 17:13:34 +08:00
</div>
2023-07-25 21:10:09 +08:00
<div class="flex items-center gap-2" v-if="parent.attributes.attachments_manageble && attachmentsReady">
<MenuDropdown
:listItems="this.viewModeMenu"
:btnText="i18n.t('attachments.preview_menu')"
:position="'right'"
:caret="true"
@attachment:viewMode = "changeAttachmentsViewMode"
></MenuDropdown>
<MenuDropdown
:listItems="this.sortMenu"
:btnIcon="'sn-icon sn-icon-sort-down'"
:btnClasses="'btn btn-light icon-btn'"
:position="'right'"
@attachment:order = "changeAttachmentsOrder"
></MenuDropdown>
2022-05-19 17:13:34 +08:00
</div>
</div>
<div class="attachments" :data-parent-id="parent.id">
<component
v-for="(attachment, index) in attachmentsOrdered"
:key="attachment.id"
:is="attachment_view_mode(attachmentsOrdered[index])"
:attachment="attachment"
:parentId="parseInt(parent.id)"
@attachment:viewMode="updateAttachmentViewMode"
@attachment:delete="deleteAttachment(attachment.id)"
@attachment:moved="attachmentMoved"
2023-10-05 21:44:41 +08:00
@attachment:uploaded="$emit('attachment:uploaded')"
/>
2022-05-19 17:13:34 +08:00
</div>
</div>
</template>
<script>
import AttachmentMovedMixin from './attachments/mixins/attachment_moved.js'
import listAttachment from './attachments/list.vue'
import inlineAttachment from './attachments/inline.vue'
import thumbnailAttachment from './attachments/thumbnail.vue'
import uploadingAttachment from './attachments/uploading.vue'
import emptyAttachment from './attachments/empty.vue'
import MenuDropdown from '../menu_dropdown.vue'
2022-05-19 17:13:34 +08:00
import WopiFileModal from './attachments/mixins/wopi_file_modal.js'
2022-05-19 17:13:34 +08:00
export default {
name: 'Attachments',
props: {
attachments: {
type: Array,
required: true
},
parent: {
2022-05-19 17:13:34 +08:00
type: Object,
required: true
},
attachmentsReady: {
type: Boolean,
required: true
2022-05-19 17:13:34 +08:00
}
},
data() {
return {
viewModeOptions: ['inline', 'thumbnail', 'list'],
orderOptions: ['new', 'old', 'atoz', 'ztoa']
2022-05-19 17:13:34 +08:00
}
},
mixins: [WopiFileModal, AttachmentMovedMixin],
2022-05-19 17:13:34 +08:00
components: {
thumbnailAttachment,
inlineAttachment,
listAttachment,
uploadingAttachment,
emptyAttachment,
MenuDropdown
2022-05-19 17:13:34 +08:00
},
watch: {
attachmentsReady() {
if (this.attachmentsReady) {
this.$nextTick(() => {
this.initMarvinJS();
})
}
}
},
2022-05-19 17:13:34 +08:00
computed: {
attachmentsOrdered() {
return this.attachments.sort((a, b) => {
if (a.attributes.asset_order == b.attributes.asset_order) {
switch(this.parent.attributes.assets_order) {
2022-05-19 17:13:34 +08:00
case 'new':
return b.attributes.updated_at - a.attributes.updated_at;
case 'old':
return a.attributes.updated_at - b.attributes.updated_at;
case 'atoz':
return a.attributes.file_name.toLowerCase() > b.attributes.file_name.toLowerCase() ? 1 : -1;
case 'ztoa':
return b.attributes.file_name.toLowerCase() > a.attributes.file_name.toLowerCase() ? 1 : -1;
}
}
return a.attributes.asset_order > b.attributes.asset_order ? 1 : -1;
})
},
viewModeMenu() {
let menu = [];
this.viewModeOptions.forEach((viewMode) => {
menu.push({
active: this.parent.attributes.assets_view_mode == viewMode,
text: this.i18n.t(`attachments.view_mode.${viewMode}_html`),
emit: 'attachment:viewMode',
params: viewMode
})
})
return menu;
},
sortMenu() {
let menu = [];
2023-10-09 17:28:18 +08:00
this.orderOptions.forEach((orderOption) => {
menu.push({
text: this.i18n.t(`general.sort_new.${orderOption}`),
emit: 'attachment:order',
params: orderOption,
active: this.parent.attributes.assets_order === orderOption
})
})
return menu;
2022-05-19 17:13:34 +08:00
}
},
mounted() {
this.initMarvinJS();
$(this.$refs.actionsDropdownButton).on('shown.bs.dropdown hidden.bs.dropdown', this.handleDropdownPosition);
},
2022-05-19 17:13:34 +08:00
methods: {
changeAttachmentsOrder(order) {
this.$emit('attachments:order', order)
},
changeAttachmentsViewMode(viewMode) {
this.$emit('attachments:viewMode', viewMode)
},
updateAttachmentViewMode(id, viewMode) {
this.$emit('attachment:viewMode', id, viewMode)
},
attachment_view_mode(attachment) {
if (attachment.attributes.uploading) {
return 'uploadingAttachment'
} else if (!attachment.attributes.attached) {
return 'emptyAttachment'
}
return `${attachment.attributes.view_mode}Attachment`
},
deleteAttachment(id) {
2023-08-25 15:46:53 +08:00
this.$emit('attachment:deleted', id)
},
initMarvinJS() {
// legacy logic from app/assets/javascripts/sitewide/marvinjs_editor.js
MarvinJsEditor.initNewButton(
`#content__attachments-${this.parent.id} .new-marvinjs-upload-button`,
() => this.$emit('attachment:uploaded')
);
},
openWopiFileModal() {
this.initWopiFileModal(this.parent, (_e, data, status) => {
if (status === 'success') {
this.$emit('attachment:uploaded', data);
} else {
HelperModule.flashAlertMsg(this.i18n.t('errors.general'), 'danger');
}
});
},
handleDropdownPosition() {
this.$refs.actionsDropdownButton.classList.toggle("dropup", !this.isInViewport(this.$refs.actionsDropdown));
},
isInViewport(el) {
let rect = el.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || $(window).height()) &&
rect.right <= (window.innerWidth || $(window).width())
);
},
2022-05-19 17:13:34 +08:00
}
}
</script>