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

296 lines
11 KiB
Vue
Raw Normal View History

2022-05-12 23:05:07 +08:00
<template>
<div class="attachment-container asset"
:data-asset-id="attachment.id"
@mouseenter="handleMouseEnter"
@mouseleave="handleMouseLeave"
v-click-outside="handleClickOutsideThumbnail"
2022-05-12 23:05:07 +08:00
>
<a :class="{ hidden: showOptions }"
:href="attachment.attributes.urls.blob"
2022-05-12 23:05:07 +08:00
class="file-preview-link file-name"
:id="`modal_link${attachment.id}`"
data-no-turbolink="true"
:data-id="attachment.id"
:data-gallery-view-id="parentId"
2022-05-12 23:05:07 +08:00
:data-preview-url="attachment.attributes.urls.preview"
:data-e2e="`e2e-BT-attachment-${attachment.id}`"
2022-05-12 23:05:07 +08:00
>
2022-05-13 19:07:50 +08:00
<div class="attachment-preview" :class= "attachment.attributes.asset_type">
<img v-if="attachment.attributes.medium_preview !== null"
2023-09-18 21:32:53 +08:00
class="rounded-sm"
2022-05-13 19:07:50 +08:00
:src="attachment.attributes.medium_preview"
2022-05-12 23:05:07 +08:00
style='opacity: 0' />
2023-09-18 21:32:53 +08:00
<div v-else class="w-[186px] h-[186px] bg-sn-super-light-grey rounded-sm"></div>
2022-05-12 23:05:07 +08:00
</div>
<div class="attachment-label"
data-toggle="tooltip"
data-placement="bottom"
:title="`${ attachment.attributes.file_name }`">
2022-05-12 23:05:07 +08:00
{{ attachment.attributes.file_name }}
</div>
</a>
<div :class="{ hidden: !showOptions }" class="hovered-thumbnail h-full">
<a
:href="attachment.attributes.urls.blob"
class="file-preview-link file-name"
:id="`modal_link${attachment.id}`"
data-no-turbolink="true"
:data-id="attachment.id"
:data-gallery-view-id="parentId"
:data-preview-url="attachment.attributes.urls.preview"
>
{{ attachment.attributes.file_name }}
</a>
2023-09-25 20:15:08 +08:00
<div class="absolute bottom-16 text-sn-grey">
2022-05-13 19:07:50 +08:00
{{ attachment.attributes.file_size_formatted }}
2022-05-12 23:05:07 +08:00
</div>
<div class="absolute bottom-4 w-[184px] grid grid-cols-[repeat(4,_2.5rem)] justify-between">
<MenuDropdown
v-if="multipleOpenOptions.length > 1"
:listItems="multipleOpenOptions"
:btnClasses="'btn btn-light icon-btn thumbnail-action-btn'"
:position="'left'"
:btnIcon="'sn-icon sn-icon-open'"
:title="i18n.t('attachments.thumbnail.buttons.open')"
@menu-toggle="toggleMenu"
@open_locally="openLocally"
@open_scinote_editor="openScinoteEditor"
></MenuDropdown>
<a class="btn btn-light icon-btn thumbnail-action-btn"
v-else-if="canOpenLocally"
@click="openLocally"
:title="i18n.t('attachments.thumbnail.buttons.open')"
>
<i class="sn-icon sn-icon-open"></i>
</a>
<a class="btn btn-light icon-btn thumbnail-action-btn"
v-else-if="this.attachment.attributes.wopi && this.attachment.attributes.urls.edit_asset"
:href="attachment.attributes.urls.edit_asset"
:title="i18n.t('attachments.thumbnail.buttons.open')"
id="wopi_file_edit_button"
:class="attachment.attributes.wopi_context.edit_supported ? '' : 'disabled'"
2023-10-05 21:44:41 +08:00
target="_blank"
>
<i class="sn-icon sn-icon-open"></i>
</a>
<a class="btn btn-light icon-btn thumbnail-action-btn ove-edit-button"
v-else-if="attachment.attributes.asset_type == 'gene_sequence' && attachment.attributes.urls.open_vector_editor_edit"
@click="openOVEditor(attachment.attributes.urls.open_vector_editor_edit)"
>
<i class="sn-icon sn-icon-open"></i>
</a>
<a class="btn btn-light icon-btn thumbnail-action-btn marvinjs-edit-button"
v-else-if="attachment.attributes.asset_type == 'marvinjs' && attachment.attributes.urls.marvin_js_start_edit"
:data-sketch-id="attachment.id"
:data-update-url="attachment.attributes.urls.marvin_js"
:data-sketch-start-edit-url="attachment.attributes.urls.marvin_js_start_edit"
:data-sketch-name="attachment.attributes.metadata.name"
:data-sketch-description="attachment.attributes.metadata.description"
>
<i class="sn-icon sn-icon-open"></i>
</a>
<a class="btn btn-light icon-btn thumbnail-action-btn image-edit-button"
v-else-if="attachment.attributes.image_editable && attachment.attributes.urls.edit_asset"
:title="i18n.t('attachments.thumbnail.buttons.open')"
:data-image-id="attachment.id"
:data-image-name="attachment.attributes.file_name"
:data-image-url="attachment.attributes.urls.asset_file"
:data-image-quality="attachment.attributes.image_context && attachment.attributes.image_context.quality"
:data-image-mime-type="attachment.attributes.image_context && attachment.attributes.image_context.type"
:data-image-start-edit-url="attachment.attributes.urls.start_edit_image"
>
<i class="sn-icon sn-icon-open"></i>
</a>
<a v-if="attachment.attributes.urls.move" @click.prevent.stop="showMoveModal" class="btn btn-light icon-btn thumbnail-action-btn" :title="i18n.t('attachments.thumbnail.buttons.move')">
<i class="sn-icon sn-icon-move"></i>
</a>
<a class="btn btn-light icon-btn thumbnail-action-btn"
:title="i18n.t('attachments.thumbnail.buttons.download')"
:href="attachment.attributes.urls.download" data-turbolinks="false">
<i class="sn-icon sn-icon-export"></i>
</a>
2024-04-30 16:32:24 +08:00
<ContextMenu
class="!relative !top-0 !left-0"
v-show="showOptions"
:attachment="attachment"
:hideEdit="true"
@attachment:viewMode="updateViewMode"
@attachment:delete="deleteAttachment"
@attachment:moved="attachmentMoved"
@attachment:uploaded="reloadAttachments"
@attachment:changed="$emit('attachment:changed', $event)"
@attachment:update="$emit('attachment:update', $event)"
@menu-visibility-changed="handleMenuVisibilityChange"
@menu-toggle="toggleMenu"
:withBorder="true"
/>
</div>
</div>
<Teleport to="body">
<deleteAttachmentModal
v-if="deleteModal"
:fileName="attachment.attributes.file_name"
@confirm="deleteAttachment"
@cancel="deleteModal = false"
/>
<MoveAssetModal
v-if="movingAttachment"
:parent_type="attachment.attributes.parent_type"
:targets_url="attachment.attributes.urls.move_targets"
@confirm="moveAttachment($event)" @cancel="closeMoveModal"
/>
<NoPredefinedAppModal
v-if="showNoPredefinedAppModal"
:fileName="attachment.attributes.file_name"
2024-02-15 21:10:24 +08:00
@close="showNoPredefinedAppModal = false"
/>
<UpdateVersionModal
v-if="showUpdateVersionModal"
2024-02-15 21:10:24 +08:00
@close="showUpdateVersionModal = false"
/>
<editLaunchingApplicationModal
v-if="editAppModal"
:fileName="attachment.attributes.file_name"
:application="this.localAppName"
@close="editAppModal = false"
/>
</Teleport>
<a class="image-edit-button hidden"
v-if="attachment.attributes.asset_type != 'marvinjs'
&& attachment.attributes.image_editable
&& attachment.attributes.urls.start_edit_image"
ref="imageEditButton"
:data-image-id="attachment.id"
:data-image-name="attachment.attributes.file_name"
:data-image-url="attachment.attributes.urls.asset_file"
:data-image-quality="attachment.attributes.image_context.quality"
:data-image-mime-type="attachment.attributes.image_context.type"
:data-image-start-edit-url="attachment.attributes.urls.start_edit_image"
></a>
2022-05-12 23:05:07 +08:00
</div>
</template>
<script>
2024-01-04 20:59:54 +08:00
import AttachmentMovedMixin from './mixins/attachment_moved.js';
import ContextMenuMixin from './mixins/context_menu.js';
import ContextMenu from './context_menu.vue';
import deleteAttachmentModal from './delete_modal.vue';
import MenuDropdown from '../../../shared/menu_dropdown.vue';
import MoveAssetModal from '../modal/move.vue';
import MoveMixin from './mixins/move.js';
import OpenLocallyMixin from './mixins/open_locally.js';
import { vOnClickOutside } from '@vueuse/components';
2024-01-04 17:15:06 +08:00
export default {
name: 'thumbnailAttachment',
mixins: [ContextMenuMixin, AttachmentMovedMixin, MoveMixin, OpenLocallyMixin],
2024-01-04 20:59:54 +08:00
components: {
ContextMenu,
deleteAttachmentModal,
MoveAssetModal,
MenuDropdown
},
2024-01-04 17:15:06 +08:00
props: {
attachment: {
type: Object,
required: true
},
2024-01-04 17:15:06 +08:00
parentId: {
type: Number,
required: true
}
},
data() {
return {
2024-01-15 20:44:50 +08:00
showOptions: false,
2024-01-04 17:15:06 +08:00
deleteModal: false,
isMenuOpen: false
2024-01-04 17:15:06 +08:00
};
},
directives: {
'click-outside': vOnClickOutside
},
computed: {
multipleOpenOptions() {
2024-01-04 20:59:54 +08:00
const options = [];
if (this.attachment.attributes.wopi && this.attachment.attributes.urls.edit_asset) {
options.push({
text: this.attachment.attributes.wopi_context.button_text,
url: this.attachment.attributes.urls.edit_asset,
url_target: '_blank'
});
}
if (this.attachment.attributes.asset_type !== 'marvinjs'
&& this.attachment.attributes.image_editable
&& this.attachment.attributes.urls.start_edit_image) {
options.push({
text: this.i18n.t('assets.file_preview.edit_in_scinote'),
2024-01-04 20:59:54 +08:00
emit: 'open_scinote_editor'
});
}
if (this.canOpenLocally) {
2024-01-04 20:59:54 +08:00
const text = this.localAppName
? this.i18n.t('attachments.open_locally_in', { application: this.localAppName })
: this.i18n.t('attachments.open_locally');
options.push({
2024-01-04 20:59:54 +08:00
text,
emit: 'open_locally',
data_e2e: 'e2e-BT-attachmentOptions-openLocally'
});
}
return options;
},
},
2024-01-04 17:15:06 +08:00
mounted() {
2024-01-04 20:59:54 +08:00
$(this.$nextTick(() => {
$('.attachment-preview img')
2024-01-04 17:15:06 +08:00
.on('error', (event) => ActiveStoragePreviews.reCheckPreview(event))
2024-01-04 20:59:54 +08:00
.on('load', (event) => ActiveStoragePreviews.showPreview(event));
}));
2024-01-04 17:15:06 +08:00
},
watch: {
2024-01-15 20:44:50 +08:00
showOptions(newValue) {
2024-01-04 17:15:06 +08:00
// reload thumbnail on mouse out
if (newValue) return;
2024-01-04 20:59:54 +08:00
$(this.$nextTick(() => {
$('.attachment-preview img')
.on('error', (event) => ActiveStoragePreviews.reCheckPreview(event))
2024-01-04 20:59:54 +08:00
.on('load', (event) => ActiveStoragePreviews.showPreview(event));
}));
2024-01-04 17:15:06 +08:00
}
},
methods: {
openOVEditor(url) {
window.showIFrameModal(url);
},
openScinoteEditor() {
this.$refs.imageEditButton.click();
},
handleMouseLeave() {
if (!this.isMenuOpen) {
this.showOptions = false;
}
},
async handleMouseEnter() {
await this.fetchLocalAppInfo();
this.showOptions = true;
},
toggleMenu(isMenuOpen) {
this.isMenuOpen = isMenuOpen;
if (isMenuOpen) {
this.showOptions = true;
}
},
handleClickOutsideThumbnail(event) {
const isClickInsideModal = event.target.closest('.modal');
if (!isClickInsideModal) {
this.showOptions = false;
this.isMenuOpen = false;
}
},
2022-05-12 23:05:07 +08:00
}
2024-01-04 20:59:54 +08:00
};
2022-05-12 23:05:07 +08:00
</script>