mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-11-08 07:21:03 +08:00
Merge pull request #6991 from ivanscinote/SCI-10010-ik
Add wrong-version modal for SciNote Edit [SCI-10010]
This commit is contained in:
commit
1458fd20a8
11 changed files with 159 additions and 54 deletions
|
|
@ -57,11 +57,15 @@
|
|||
:fileName="attachment.attributes.file_name"
|
||||
@confirm="showNoPredefinedAppModal = false"
|
||||
/>
|
||||
<UpdateVersionModal
|
||||
v-if="showUpdateVersionModal"
|
||||
@cancel="showUpdateVersionModal = false"
|
||||
/>
|
||||
<editLaunchingApplicationModal
|
||||
v-if="editAppModal"
|
||||
:fileName="attachment.attributes.file_name"
|
||||
:application="this.localAppName"
|
||||
@cancel="editAppModal = false"
|
||||
v-if="editAppModal"
|
||||
:fileName="attachment.attributes.file_name"
|
||||
:application="this.localAppName"
|
||||
@cancel="editAppModal = false"
|
||||
/>
|
||||
</Teleport>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,43 +1,52 @@
|
|||
import axios from '../../../../../packs/custom_axios.js';
|
||||
import { satisfies } from 'compare-versions';
|
||||
import editLaunchingApplicationModal from '../../modal/edit_launching_application_modal.vue';
|
||||
import NoPredefinedAppModal from '../../modal/no_predefined_app_modal.vue';
|
||||
import UpdateVersionModal from '../../modal/update_version_modal.vue';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
localAppName: null,
|
||||
scinoteEditRunning: false,
|
||||
scinoteEditVersion: null,
|
||||
showNoPredefinedAppModal: false,
|
||||
showUpdateVersionModal: false,
|
||||
editAppModal: false
|
||||
};
|
||||
},
|
||||
components: {
|
||||
editLaunchingApplicationModal,
|
||||
NoPredefinedAppModal
|
||||
NoPredefinedAppModal,
|
||||
UpdateVersionModal
|
||||
},
|
||||
computed: {
|
||||
attributes() {
|
||||
return this.attachment.attributes;
|
||||
},
|
||||
canOpenLocally() {
|
||||
return this.scinoteEditRunning &&
|
||||
!!this.attachment.attributes.urls.open_locally &&
|
||||
this.attachment.attributes.asset_type !== 'gene_sequence' &&
|
||||
this.attachment.attributes.asset_type !== 'marvinjs'
|
||||
return this.scinoteEditRunning
|
||||
&& !!this.attributes.urls.open_locally
|
||||
&& this.attributes.asset_type !== 'gene_sequence'
|
||||
&& this.attributes.asset_type !== 'marvinjs';
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async fetchLocalAppInfo() {
|
||||
try {
|
||||
const statusResponse = await axios.get(
|
||||
`${this.attachment.attributes.urls.open_locally_api}/status`
|
||||
`${this.attributes.urls.open_locally_api}/status`
|
||||
);
|
||||
|
||||
if (statusResponse.status === 200) {
|
||||
this.scinoteEditRunning = true;
|
||||
this.scinoteEditVersion = statusResponse.data.version;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await axios.get(
|
||||
`${this.attachment.attributes.urls.open_locally_api}/default-application/${this.attachment.attributes.file_extension}`
|
||||
`${this.attributes.urls.open_locally_api}/default-application/${this.attributes.file_extension}`
|
||||
);
|
||||
|
||||
if (response.data.application.toLowerCase() !== 'pick an app') {
|
||||
|
|
@ -48,18 +57,25 @@ export default {
|
|||
}
|
||||
},
|
||||
async openLocally() {
|
||||
if (this.localAppName === null) {
|
||||
if (this.isWrongVersion(this.scinoteEditVersion)) {
|
||||
this.showUpdateVersionModal = true;
|
||||
return;
|
||||
} else if (this.localAppName === null) {
|
||||
this.showNoPredefinedAppModal = true;
|
||||
return;
|
||||
}
|
||||
|
||||
this.editAppModal = true;
|
||||
try {
|
||||
const { data } = await axios.get(this.attachment.attributes.urls.open_locally);
|
||||
await axios.post(this.attachment.attributes.urls.open_locally_api + '/download', data);
|
||||
const { data } = await axios.get(this.attributes.urls.open_locally);
|
||||
await axios.post(`${this.attributes.urls.open_locally_api}/download`, data);
|
||||
} catch (error) {
|
||||
console.error('Error in request:', error);
|
||||
}
|
||||
},
|
||||
isWrongVersion(version) {
|
||||
const { min, max } = this.attributes.edit_version_range;
|
||||
return !satisfies(version, `${min} - ${max}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
<template>
|
||||
<div class="sn-open-locally-menu">
|
||||
<div v-if="!this.canOpenLocally && (this.attachment.attributes.wopi && this.attachment.attributes.urls.edit_asset)">
|
||||
<a :href="`${this.attachment.attributes.urls.edit_asset}`" target="_blank"
|
||||
class="block whitespace-nowrap rounded px-3 py-2.5
|
||||
hover:!text-sn-blue hover:no-underline cursor-pointer hover:bg-sn-super-light-grey">
|
||||
{{ this.attachment.attributes.wopi_context.button_text }}
|
||||
</a>
|
||||
<div class="sn-open-locally-menu" @mouseenter="fetchLocalAppInfo">
|
||||
<div v-if="!canOpenLocally && (attachment.attributes.wopi && attachment.attributes.urls.edit_asset)">
|
||||
<a :href="`${attachment.attributes.urls.edit_asset}`" target="_blank"
|
||||
class="block whitespace-nowrap rounded px-3 py-2.5
|
||||
hover:!text-sn-blue hover:no-underline cursor-pointer hover:bg-sn-super-light-grey">
|
||||
{{ attachment.attributes.wopi_context.button_text }}
|
||||
</a>
|
||||
</div>
|
||||
<div v-else>
|
||||
<MenuDropdown
|
||||
|
|
@ -16,11 +16,11 @@
|
|||
:position="'right'"
|
||||
:btnText="i18n.t('attachments.open_in')"
|
||||
:caret="true"
|
||||
@openLocally="openLocally"
|
||||
@openImageEditor="openImageEditor"
|
||||
@open-locally="openLocally"
|
||||
@open-image-editor="openImageEditor"
|
||||
></MenuDropdown>
|
||||
<a v-else-if="this.menu.length === 1" class="btn btn-light" :href="this.menu[0].url" :target="this.menu[0].target" @click="this[this.menu[0].emit]()">
|
||||
{{ this.menu[0].text }}
|
||||
<a v-else-if="menu.length === 1" class="btn btn-light !bg-sn-white" :href="menu[0].url" :target="menu[0].target" @click="this[this.menu[0].emit]()">
|
||||
{{ menu[0].text }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
@ -31,10 +31,14 @@
|
|||
@confirm="showNoPredefinedAppModal = false"
|
||||
/>
|
||||
<editLaunchingApplicationModal
|
||||
v-if="editAppModal"
|
||||
:fileName="attachment.attributes.file_name"
|
||||
:application="this.localAppName"
|
||||
@cancel="editAppModal = false"
|
||||
v-if="editAppModal"
|
||||
:fileName="attachment.attributes.file_name"
|
||||
:application="this.localAppName"
|
||||
@cancel="editAppModal = false"
|
||||
/>
|
||||
<UpdateVersionModal
|
||||
v-if="showUpdateVersionModal"
|
||||
@cancel="showUpdateVersionModal = false"
|
||||
/>
|
||||
</Teleport>
|
||||
</div>
|
||||
|
|
@ -43,17 +47,21 @@
|
|||
<script>
|
||||
import OpenLocallyMixin from './mixins/open_locally.js';
|
||||
import MenuDropdown from '../../menu_dropdown.vue';
|
||||
import UpdateVersionModal from '../modal/update_version_modal.vue';
|
||||
|
||||
export default {
|
||||
name: 'OpenLocallyMenu',
|
||||
mixins: [OpenLocallyMixin],
|
||||
components: { MenuDropdown },
|
||||
components: { MenuDropdown, UpdateVersionModal },
|
||||
props: {
|
||||
data: { type: String, required: true },
|
||||
attachment: { type: Object, required: true }
|
||||
},
|
||||
created() {
|
||||
this.attachment = { attributes: JSON.parse(this.data) };
|
||||
this.fetchLocalAppInfo();
|
||||
window.openLocallyMenu = this;
|
||||
},
|
||||
beforeUnmount() {
|
||||
delete window.openLocallyMenuComponent;
|
||||
},
|
||||
computed: {
|
||||
menu() {
|
||||
|
|
|
|||
|
|
@ -145,6 +145,10 @@
|
|||
:fileName="attachment.attributes.file_name"
|
||||
@confirm="showNoPredefinedAppModal = false"
|
||||
/>
|
||||
<UpdateVersionModal
|
||||
v-if="showUpdateVersionModal"
|
||||
@cancel="showUpdateVersionModal = false"
|
||||
/>
|
||||
<a class="image-edit-button hidden"
|
||||
v-if="attachment.attributes.asset_type != 'marvinjs'
|
||||
&& attachment.attributes.image_editable
|
||||
|
|
@ -167,7 +171,6 @@ 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 NoPredefinedAppModal from '../modal/no_predefined_app_modal.vue';
|
||||
import MoveMixin from './mixins/move.js';
|
||||
import OpenLocallyMixin from './mixins/open_locally.js';
|
||||
import { vOnClickOutside } from '@vueuse/components';
|
||||
|
|
@ -179,7 +182,6 @@ export default {
|
|||
ContextMenu,
|
||||
deleteAttachmentModal,
|
||||
MoveAssetModal,
|
||||
NoPredefinedAppModal,
|
||||
MenuDropdown
|
||||
},
|
||||
props: {
|
||||
|
|
@ -196,8 +198,7 @@ export default {
|
|||
return {
|
||||
showOptions: false,
|
||||
deleteModal: false,
|
||||
isMenuOpen: false,
|
||||
showNoPredefinedAppModal: false
|
||||
isMenuOpen: false
|
||||
};
|
||||
},
|
||||
directives: {
|
||||
|
|
|
|||
|
|
@ -5,14 +5,14 @@
|
|||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i class="sn-icon sn-icon-close"></i></button>
|
||||
<h4 class="modal-title" id="modal-delete-result-element">
|
||||
{{ i18n.t('assets.asset_sync.set_up_app') }}
|
||||
{{ i18n.t('assets.no_predefined_app_modal.set_up_app') }}
|
||||
</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p v-html="i18n.t('assets.asset_sync.body_text_html', { file_name: fileName })"></p>
|
||||
<p v-html="i18n.t('assets.no_predefined_app_modal.body_text_html', { file_name: fileName })"></p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-primary" @click="confirm">{{ this.i18n.t('assets.asset_sync.no_predefined_app') }}</button>
|
||||
<button class="btn btn-primary" @click="confirm">{{ this.i18n.t('assets.no_predefined_app_modal.understand_button') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
<template>
|
||||
<div ref="modal" @keydown.esc="cancel" class="modal" id="modalUpdateVersion" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-md" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i class="sn-icon sn-icon-close"></i></button>
|
||||
<h4 class="modal-title" id="modal-delete-result-element">
|
||||
{{ i18n.t('assets.update_version_modal.title') }}
|
||||
</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p v-html="i18n.t('assets.update_version_modal.body_text_html')"></p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" @click="cancel">{{ i18n.t('general.cancel') }}</button>
|
||||
<ScinoteEditDownload
|
||||
:data="userAgent"
|
||||
:isUpdateVersionModal="true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ScinoteEditDownload from '../../../../vue/shared/scinote_edit_download.vue';
|
||||
|
||||
export default {
|
||||
name: 'UpdateVersionModal',
|
||||
components: {
|
||||
ScinoteEditDownload
|
||||
},
|
||||
props: {
|
||||
fileName: String
|
||||
},
|
||||
computed: {
|
||||
userAgent() {
|
||||
return window.navigator.userAgent;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
$(this.$refs.modal).modal('show');
|
||||
$(this.$refs.modal).on('hidden.bs.modal', () => {
|
||||
this.$emit('cancel');
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
cancel() {
|
||||
$(this.$refs.modal).modal('hide');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="buttons">
|
||||
<template v-if="isWindows">
|
||||
<a :href="responseData[0]['url']"
|
||||
<a :href="getWindowsHref"
|
||||
class="btn btn-primary new-project-btn"
|
||||
:title="i18n.t('users.settings.account.addons.desktop_app.windows_button')"
|
||||
role="button"
|
||||
|
|
@ -9,13 +9,13 @@
|
|||
target="_blank">
|
||||
<span class="hidden-xs">{{ i18n.t('users.settings.account.addons.desktop_app.windows_button') }}</span>
|
||||
</a>
|
||||
<div class="text-xs pt-2 pb-6" style="color: var(--sn-sleepy-grey);">
|
||||
<div v-if="showButtonLabel" class="text-xs pt-2 pb-6" style="color: var(--sn-sleepy-grey);">
|
||||
{{ i18n.t('users.settings.account.addons.desktop_app.version', { version: this.responseData[0]['version']}) }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else-if="isMac">
|
||||
<a :href="responseData[1]['url']"
|
||||
<a :href="getMacHref"
|
||||
class="btn btn-primary new-project-btn"
|
||||
:title="i18n.t('users.settings.account.addons.desktop_app.macos_button')"
|
||||
role="button"
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
target="_blank">
|
||||
<span class="hidden-xs">{{ i18n.t('users.settings.account.addons.desktop_app.macos_button') }}</span>
|
||||
</a>
|
||||
<div class="text-xs pt-2 pb-6" style="color: var(--sn-sleepy-grey);">
|
||||
<div v-if="showButtonLabel" class="text-xs pt-2 pb-6" style="color: var(--sn-sleepy-grey);">
|
||||
{{ i18n.t('users.settings.account.addons.desktop_app.version', { version: this.responseData[1]['version']}) }}
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
<template v-else>
|
||||
<div class="flex">
|
||||
<div>
|
||||
<a :href="responseData[0]['url']"
|
||||
<a :href="getWindowsHref"
|
||||
class="btn btn-primary new-project-btn"
|
||||
:title="i18n.t('users.settings.account.addons.desktop_app.windows_button')"
|
||||
role="button"
|
||||
|
|
@ -39,7 +39,7 @@
|
|||
target="_blank">
|
||||
<span class="hidden-xs">{{ i18n.t('users.settings.account.addons.desktop_app.windows_button') }}</span>
|
||||
</a>
|
||||
<div class="text-xs pt-2 pb-6" style="color: var(--sn-sleepy-grey);">
|
||||
<div v-if="showButtonLabel" class="text-xs pt-2 pb-6" style="color: var(--sn-sleepy-grey);">
|
||||
{{ i18n.t('users.settings.account.addons.desktop_app.version',
|
||||
{ version: this.responseData[0]['version']})
|
||||
}}
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
</div>
|
||||
|
||||
<div class="ml-2">
|
||||
<a :href="responseData[1]['url']"
|
||||
<a :href="getMacHref"
|
||||
class="btn btn-primary new-project-btn"
|
||||
:title="i18n.t('users.settings.account.addons.desktop_app.macos_button')"
|
||||
role="button"
|
||||
|
|
@ -55,7 +55,7 @@
|
|||
target="_blank">
|
||||
<span class="hidden-xs">{{ i18n.t('users.settings.account.addons.desktop_app.macos_button') }}</span>
|
||||
</a>
|
||||
<p class="text-xs pt-2 pb-6" style="color: var(--sn-sleepy-grey);">
|
||||
<p v-if="showButtonLabel" class="text-xs pt-2 pb-6" style="color: var(--sn-sleepy-grey);">
|
||||
{{ i18n.t('users.settings.account.addons.desktop_app.version',
|
||||
{ version: this.responseData[1]['version']})
|
||||
}}
|
||||
|
|
@ -78,12 +78,13 @@
|
|||
export default {
|
||||
name: 'ScinoteEditDownload',
|
||||
props: {
|
||||
data: { type: String, required: true }
|
||||
data: { type: String, required: true },
|
||||
isUpdateVersionModal: { type: Boolean, required: false }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
userAgent: this.data,
|
||||
responseData: {}
|
||||
responseData: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -92,6 +93,15 @@ export default {
|
|||
},
|
||||
isMac() {
|
||||
return /Mac OS/.test(this.userAgent);
|
||||
},
|
||||
showButtonLabel() {
|
||||
return this.responseData && this.responseData.length > 0 && !this.isUpdateVersionModal;
|
||||
},
|
||||
getWindowsHref() {
|
||||
return this.responseData && this.responseData.length > 0 ? this.responseData[0].url : '#';
|
||||
},
|
||||
getMacHref() {
|
||||
return this.responseData && this.responseData.length > 0 ? this.responseData[1].url : '#';
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ class AssetSerializer < ActiveModel::Serializer
|
|||
attributes :file_name, :file_extension, :view_mode, :icon, :urls, :updated_at_formatted,
|
||||
:file_size, :medium_preview, :large_preview, :asset_type, :wopi,
|
||||
:wopi_context, :pdf_previewable, :file_size_formatted, :asset_order,
|
||||
:updated_at, :metadata, :image_editable, :image_context, :pdf, :attached, :parent_type
|
||||
:updated_at, :metadata, :image_editable, :image_context, :pdf, :attached, :parent_type, :edit_version_range
|
||||
|
||||
def icon
|
||||
file_fa_icon_class(object)
|
||||
|
|
@ -117,6 +117,10 @@ class AssetSerializer < ActiveModel::Serializer
|
|||
end
|
||||
end
|
||||
|
||||
def edit_version_range
|
||||
{ min: Constants::MIN_SCINOTE_EDIT_VERSION, max: Constants::MAX_SCINOTE_EDIT_VERSION }
|
||||
end
|
||||
|
||||
def urls
|
||||
urls = {
|
||||
preview: asset_file_preview_path(object),
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<% if can_edit && !preview %>
|
||||
<% if wopi_enabled? && wopi_file?(asset) %>
|
||||
<div id="openLocallyMenu" data-behaviour="vue">
|
||||
<open-locally-menu data="<%= AssetSerializer.new(asset, scope: { user: current_user }).to_json %>"/>
|
||||
<open-locally-menu :attachment="<%= { attributes: AssetSerializer.new(asset, scope: { user: current_user }).as_json }.to_json %>" />
|
||||
</div>
|
||||
<% elsif asset.file.metadata[:asset_type] == 'marvinjs' %>
|
||||
<button class="btn btn-light marvinjs-edit-button"
|
||||
|
|
@ -40,7 +40,7 @@
|
|||
</button>
|
||||
<% end %>
|
||||
<div id="openLocallyMenu" data-behaviour="vue">
|
||||
<open-locally-menu data="<%= AssetSerializer.new(asset, scope: { user: current_user }).to_json %>"/>
|
||||
<open-locally-menu :attachment="<%= { attributes: AssetSerializer.new(asset, scope: { user: current_user }).as_json }.to_json %>" />
|
||||
</div>
|
||||
<% end %>
|
||||
<a class="btn btn-light file-download-link" href="<%= rails_blob_path(asset.file, disposition: 'attachment') %>" data-turbolinks="false">
|
||||
|
|
|
|||
|
|
@ -434,6 +434,10 @@ class Constants
|
|||
# Grover timeout in ms
|
||||
GROVER_TIMEOUT_MS = 300000
|
||||
|
||||
# SciNote Edit supported versions
|
||||
MIN_SCINOTE_EDIT_VERSION = ENV['MIN_SCINOTE_EDIT_VERSION'].freeze
|
||||
MAX_SCINOTE_EDIT_VERSION = ENV['MAX_SCINOTE_EDIT_VERSION'].freeze
|
||||
|
||||
# ) \ / (
|
||||
# /|\ )\_/( /|\
|
||||
# * / | \ (/\|/\) / | \ *
|
||||
|
|
|
|||
|
|
@ -401,6 +401,7 @@ en:
|
|||
open_locally_in: "Open in %{application}"
|
||||
open_in: "Open in"
|
||||
open_locally: "Open locally"
|
||||
open_in: "Open in"
|
||||
new:
|
||||
description: 'New'
|
||||
uploading: 'Uploading'
|
||||
|
|
@ -3614,10 +3615,13 @@ en:
|
|||
empty_office_file:
|
||||
description: "The file is empty. Please add some data before saving the file."
|
||||
reload: "Reload file"
|
||||
asset_sync:
|
||||
no_predefined_app_modal:
|
||||
body_text_html: "The specified application for accessing the <b>%{file_name}</b> is not preconfigured. To successfully open this file, please set up the appropriate application in your local environment beforehand.</p>"
|
||||
no_predefined_app: "I understand"
|
||||
understand_button: "I understand"
|
||||
set_up_app: "Set up an application to open this file"
|
||||
update_version_modal:
|
||||
title: "Update required"
|
||||
body_text_html: "The current version of the SciNote Edit application is no longer supported. To ensure a seamless and secure user experience, we recommend installing to the latest version."
|
||||
edit_launching_application_modal:
|
||||
title: "Launching application"
|
||||
description: "%{file_name} will now open in %{application}. Saved changes in %{application} will automatically be synced in SciNote."
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue