mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-11-08 07:21:03 +08:00
Merge branch 'hotfix/1.36.2.1' into develop
This commit is contained in:
commit
ae25f8097e
25 changed files with 329 additions and 129 deletions
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
1.36.2
|
||||
1.36.2.1
|
||||
|
|
|
|||
|
|
@ -19,5 +19,6 @@ const GLOBAL_CONSTANTS = {
|
|||
ASSET_POLLING_INTERVAL: <%= Constants::ASSET_POLLING_INTERVAL %>,
|
||||
ASSET_SYNC_URL: '<%= Constants::ASSET_SYNC_URL %>',
|
||||
GLOBAL_SEARCH_PREVIEW_LIMIT: <%= Constants::GLOBAL_SEARCH_PREVIEW_LIMIT %>,
|
||||
SEARCH_LIMIT: <%= Constants::SEARCH_LIMIT %>
|
||||
SEARCH_LIMIT: <%= Constants::SEARCH_LIMIT %>,
|
||||
SCINOTE_EDIT_RESTRICTED_EXTENSIONS: <%= Constants::SCINOTE_EDIT_RESTRICTED_EXTENSIONS %>
|
||||
};
|
||||
|
|
|
|||
14
app/javascript/vue/label_template/renderers/default.vue
Normal file
14
app/javascript/vue/label_template/renderers/default.vue
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<template>
|
||||
<i v-if="params.data.default" class="sn-icon sn-icon-approval"></i>
|
||||
<span v-else></span>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
params: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
17
app/javascript/vue/label_template/renderers/format.vue
Normal file
17
app/javascript/vue/label_template/renderers/format.vue
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<template>
|
||||
<span>
|
||||
<span v-html="params.data.icon_url"></span>
|
||||
<span>{{ params.data.format }}</span>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
params: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
16
app/javascript/vue/label_template/renderers/name.vue
Normal file
16
app/javascript/vue/label_template/renderers/name.vue
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<template>
|
||||
<a :href="params.data.urls.show" :title="params.data.name">
|
||||
{{ params.data.name }}
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
params: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -30,28 +30,34 @@ import axios from '../../packs/custom_axios.js';
|
|||
|
||||
import DataTable from '../shared/datatable/table.vue';
|
||||
import DeleteModal from '../shared/confirmation_modal.vue';
|
||||
import NameRenderer from './renderers/name.vue';
|
||||
import DefaultRenderer from './renderers/default.vue';
|
||||
import FormatRenderer from './renderers/format.vue';
|
||||
|
||||
export default {
|
||||
name: 'LabelTemplatesTable',
|
||||
components: {
|
||||
DataTable,
|
||||
DeleteModal,
|
||||
NameRenderer,
|
||||
DefaultRenderer,
|
||||
FormatRenderer
|
||||
},
|
||||
props: {
|
||||
dataSource: {
|
||||
type: String,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
actionsUrl: {
|
||||
type: String,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
createUrl: {
|
||||
type: String,
|
||||
type: String
|
||||
},
|
||||
syncFluicsUrl: {
|
||||
type: String,
|
||||
},
|
||||
type: String
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
@ -60,40 +66,40 @@ export default {
|
|||
{
|
||||
field: 'default',
|
||||
headerName: this.i18n.t('label_templates.index.default_label'),
|
||||
cellRenderer: this.defaultRenderer,
|
||||
sortable: true,
|
||||
cellRenderer: 'DefaultRenderer',
|
||||
sortable: true
|
||||
}, {
|
||||
field: 'name',
|
||||
headerName: this.i18n.t('label_templates.index.thead_name'),
|
||||
cellRenderer: this.labelNameRenderer,
|
||||
sortable: true,
|
||||
cellRenderer: 'NameRenderer',
|
||||
sortable: true
|
||||
}, {
|
||||
field: 'format',
|
||||
headerName: this.i18n.t('label_templates.index.format'),
|
||||
sortable: true,
|
||||
cellRenderer: ({ data: { format, icon_url: iconUrl } }) => `<span>${iconUrl}</span> <span>${format}</span>`
|
||||
cellRenderer: 'FormatRenderer'
|
||||
}, {
|
||||
field: 'description',
|
||||
headerName: this.i18n.t('label_templates.index.description'),
|
||||
sortable: true,
|
||||
sortable: true
|
||||
}, {
|
||||
field: 'modified_by',
|
||||
headerName: this.i18n.t('label_templates.index.updated_by'),
|
||||
sortable: true,
|
||||
sortable: true
|
||||
}, {
|
||||
field: 'updated_at',
|
||||
headerName: this.i18n.t('label_templates.index.updated_at'),
|
||||
sortable: true,
|
||||
sortable: true
|
||||
}, {
|
||||
field: 'created_by',
|
||||
headerName: this.i18n.t('label_templates.index.created_by'),
|
||||
sortable: true,
|
||||
sortable: true
|
||||
}, {
|
||||
field: 'created_at',
|
||||
headerName: this.i18n.t('label_templates.index.created_at'),
|
||||
sortable: true,
|
||||
},
|
||||
],
|
||||
sortable: true
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -106,7 +112,7 @@ export default {
|
|||
label: this.i18n.t('label_templates.index.toolbar.new'),
|
||||
type: 'emit',
|
||||
path: this.createUrl,
|
||||
buttonStyle: 'btn btn-primary',
|
||||
buttonStyle: 'btn btn-primary'
|
||||
});
|
||||
}
|
||||
if (this.syncFluicsUrl) {
|
||||
|
|
@ -121,21 +127,11 @@ export default {
|
|||
}
|
||||
return {
|
||||
left,
|
||||
right: [],
|
||||
right: []
|
||||
};
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
labelNameRenderer(params) {
|
||||
const editUrl = params.data.urls.show;
|
||||
return `<a href="${editUrl}" title="${params.data.name}">
|
||||
${params.data.name}
|
||||
</a>`;
|
||||
},
|
||||
defaultRenderer(params) {
|
||||
const defaultSelected = params.data.default;
|
||||
return defaultSelected ? '<i class="sn-icon sn-icon-approval"></i>' : '';
|
||||
},
|
||||
setDefault(action) {
|
||||
axios.post(action.path).then((response) => {
|
||||
this.reloadingTable = true;
|
||||
|
|
@ -175,8 +171,8 @@ export default {
|
|||
HelperModule.flashAlertMsg(error.response.data.error, 'danger');
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
:hiddenDataMessage="i18n.t('experiments.empty_state.no_active_modules_archived_branch')"
|
||||
scrollMode="infinite"
|
||||
@tableReloaded="reloadingTable = false"
|
||||
@reloadTable="reloadingTable = true"
|
||||
@create="newModalOpen = true"
|
||||
@edit="edit"
|
||||
@move="move"
|
||||
|
|
@ -56,6 +57,9 @@
|
|||
import axios from '../../packs/custom_axios.js';
|
||||
import DataTable from '../shared/datatable/table.vue';
|
||||
import ConfirmationModal from '../shared/confirmation_modal.vue';
|
||||
import NameRenderer from './renderers/name.vue';
|
||||
import ResultsRenderer from './renderers/results.vue';
|
||||
import StatusRenderer from './renderers/status.vue';
|
||||
import DueDateRenderer from './renderers/due_date.vue';
|
||||
import DesignatedUsers from './renderers/designated_users.vue';
|
||||
import TagsModal from './modals/tags.vue';
|
||||
|
|
@ -77,7 +81,10 @@ export default {
|
|||
NewModal,
|
||||
EditModal,
|
||||
MoveModal,
|
||||
AccessModal
|
||||
AccessModal,
|
||||
NameRenderer,
|
||||
ResultsRenderer,
|
||||
StatusRenderer
|
||||
},
|
||||
props: {
|
||||
dataSource: { type: String, required: true },
|
||||
|
|
@ -115,7 +122,7 @@ export default {
|
|||
field: 'name',
|
||||
headerName: this.i18n.t('experiments.table.column.task_name_html'),
|
||||
sortable: true,
|
||||
cellRenderer: this.nameRenderer
|
||||
cellRenderer: NameRenderer
|
||||
},
|
||||
{
|
||||
field: 'code',
|
||||
|
|
@ -133,7 +140,7 @@ export default {
|
|||
field: 'results',
|
||||
headerName: this.i18n.t('experiments.table.column.results_html'),
|
||||
sortable: true,
|
||||
cellRenderer: this.resultsRenderer
|
||||
cellRenderer: ResultsRenderer
|
||||
},
|
||||
{
|
||||
field: 'age',
|
||||
|
|
@ -144,7 +151,7 @@ export default {
|
|||
field: 'status',
|
||||
headerName: this.i18n.t('experiments.table.column.status_html'),
|
||||
sortable: true,
|
||||
cellRenderer: this.statusRenderer,
|
||||
cellRenderer: StatusRenderer,
|
||||
minWidth: 120
|
||||
}
|
||||
];
|
||||
|
|
@ -321,53 +328,6 @@ export default {
|
|||
roles_path: this.userRolesUrl
|
||||
};
|
||||
},
|
||||
checkProvisioning(params) {
|
||||
if (params.data.provisioning_status === 'done') return;
|
||||
|
||||
axios.get(params.data.urls.provisioning_status).then((response) => {
|
||||
const provisioningStatus = response.data.provisioning_status;
|
||||
if (provisioningStatus === 'done') {
|
||||
this.reloadingTable = true;
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
this.checkProvisioning(params);
|
||||
}, 5000);
|
||||
}
|
||||
});
|
||||
},
|
||||
// Renderers
|
||||
nameRenderer(params) {
|
||||
const { name, urls } = params.data;
|
||||
const provisioningStatus = params.data.provisioning_status;
|
||||
if (provisioningStatus === 'in_progress') {
|
||||
setTimeout(() => {
|
||||
this.checkProvisioning(params);
|
||||
}, 5000);
|
||||
return `
|
||||
<span class="flex gap-2 items-center">
|
||||
<div title="${this.i18n.t('experiments.duplicate_tasks.duplicating')}"
|
||||
class="loading-overlay w-6 h-6 !relative shrink-0" data-toggle="tooltip" data-placement="right"></div>
|
||||
<span class="truncate">${name}</span>
|
||||
</span>`;
|
||||
}
|
||||
|
||||
return `<a href="${urls.show}" title="${name}" ><span class="truncate">${name}</span></a>`;
|
||||
},
|
||||
statusRenderer(params) {
|
||||
const { status } = params.data;
|
||||
|
||||
return `<span
|
||||
class="px-2 py-1 border border-solid rounded truncate ${!status.light_color ? 'text-sn-white' : ''}"
|
||||
style="background-color: ${status.color};"
|
||||
>
|
||||
${status.name}
|
||||
</span>`;
|
||||
},
|
||||
resultsRenderer(params) {
|
||||
const { results, urls } = params.data;
|
||||
|
||||
return `<a href="${urls.results}" >${results}</a>`;
|
||||
},
|
||||
usersFilterRenderer(option) {
|
||||
return `<div class="flex items-center gap-2">
|
||||
<img src="${option[2].avatar_url}" class="rounded-full w-6 h-6" />
|
||||
|
|
|
|||
50
app/javascript/vue/my_modules/renderers/name.vue
Normal file
50
app/javascript/vue/my_modules/renderers/name.vue
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
<template>
|
||||
<template v-if="params.data.provisioning_status === 'in_progress'">
|
||||
<span class="flex gap-2 items-center">
|
||||
<div :title="this.i18n.t('experiments.duplicate_tasks.duplicating')"
|
||||
class="loading-overlay w-6 h-6 !relative shrink-0" data-toggle="tooltip" data-placement="right"></div>
|
||||
<span class="truncate">{{ params.data.name }}</span>
|
||||
</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<a :href="params.data.urls.show" :title="params.data.name" >
|
||||
<i v-if="params.data.locked" class="sn-icon sn-icon-locked-task"></i>
|
||||
<span class="truncate">{{ params.data.name }}</span>
|
||||
</a>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from '../../../packs/custom_axios.js';
|
||||
|
||||
export default {
|
||||
name: 'NameRenderer',
|
||||
props: {
|
||||
params: {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (this.params.data.provisioning_status === 'in_progress') {
|
||||
setTimeout(() => {
|
||||
this.checkProvisioning();
|
||||
}, 5000);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
checkProvisioning() {
|
||||
if (this.params.data.provisioning_status === 'done') return;
|
||||
axios.get(this.params.data.urls.provisioning_status).then((response) => {
|
||||
const provisioningStatus = response.data.provisioning_status;
|
||||
if (provisioningStatus === 'done') {
|
||||
this.params.dtComponent.$emit('reloadTable', null, [this.params.data]);
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
this.checkProvisioning();
|
||||
}, 5000);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
14
app/javascript/vue/my_modules/renderers/results.vue
Normal file
14
app/javascript/vue/my_modules/renderers/results.vue
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<template>
|
||||
<a :href="params.data.urls.results" >{{ params.data.results }}</a>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ResultsRenderer',
|
||||
props: {
|
||||
params: {
|
||||
required: true
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
20
app/javascript/vue/my_modules/renderers/status.vue
Normal file
20
app/javascript/vue/my_modules/renderers/status.vue
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<template>
|
||||
<span
|
||||
class="px-2 py-1 border border-solid rounded truncate"
|
||||
:class="{'text-sn-white' : !params.data.status.light_color}"
|
||||
:style="{'background-color': params.data.status.color}"
|
||||
>
|
||||
{{ params.data.status.name }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'StatusRenderer',
|
||||
props: {
|
||||
params: {
|
||||
required: true
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -68,6 +68,7 @@ import axios from '../../packs/custom_axios.js';
|
|||
|
||||
import DataTable from '../shared/datatable/table.vue';
|
||||
import UsersRenderer from './renderers/users.vue';
|
||||
import NameRenderer from './renderers/name.vue';
|
||||
import CommentsRenderer from '../shared/datatable/renderers/comments.vue';
|
||||
import ProjectCard from './card.vue';
|
||||
import ConfirmationModal from '../shared/confirmation_modal.vue';
|
||||
|
|
@ -84,6 +85,7 @@ export default {
|
|||
components: {
|
||||
DataTable,
|
||||
UsersRenderer,
|
||||
NameRenderer,
|
||||
ProjectCard,
|
||||
ConfirmationModal,
|
||||
EditProjectModal,
|
||||
|
|
@ -129,7 +131,7 @@ export default {
|
|||
flex: 1,
|
||||
headerName: this.i18n.t('projects.index.card.name'),
|
||||
sortable: true,
|
||||
cellRenderer: this.nameRenderer
|
||||
cellRenderer: 'NameRenderer'
|
||||
},
|
||||
{
|
||||
field: 'code',
|
||||
|
|
@ -252,16 +254,6 @@ export default {
|
|||
<span title="${option[1]}" class="truncate">${option[1]}</span>
|
||||
</div>`;
|
||||
},
|
||||
nameRenderer(params) {
|
||||
const showUrl = params.data.urls.show;
|
||||
return `<a href="${showUrl}"
|
||||
class="flex items-center gap-1 hover:no-underline
|
||||
${!showUrl ? 'pointer-events-none text-sn-grey' : ''}"
|
||||
title="${params.data.name}">
|
||||
${params.data.folder ? '<i class="sn-icon mini sn-icon-mini-folder-left"></i>' : ''}
|
||||
<span class="truncate">${params.data.name} </span>
|
||||
</a>`;
|
||||
},
|
||||
openComments(_params, rows) {
|
||||
$(this.$refs.commentButton).data('objectId', rows[0].id);
|
||||
this.$refs.commentButton.click();
|
||||
|
|
|
|||
21
app/javascript/vue/projects/renderers/name.vue
Normal file
21
app/javascript/vue/projects/renderers/name.vue
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<template>
|
||||
<a :href="params.data.urls.show"
|
||||
class="flex items-center gap-1 hover:no-underline"
|
||||
:class="{
|
||||
'pointer-events-none text-sn-grey': !params.data.urls.show
|
||||
}"
|
||||
:title="params.data.name">
|
||||
<i v-if="params.data.folder" class="sn-icon mini sn-icon-mini-folder-left"></i>
|
||||
<span class="truncate">{{ params.data.name }}</span>
|
||||
</a>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'NameRenderer',
|
||||
props: {
|
||||
params: {
|
||||
required: true
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -19,8 +19,8 @@ export default {
|
|||
name: 'UsersRenderer',
|
||||
props: {
|
||||
params: {
|
||||
required: true,
|
||||
},
|
||||
required: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
users() {
|
||||
|
|
|
|||
21
app/javascript/vue/protocols/renderers/name.vue
Normal file
21
app/javascript/vue/protocols/renderers/name.vue
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<template>
|
||||
<a v-if="params.data.urls.show"
|
||||
:href="params.data.urls.show"
|
||||
:title="params.data.name">
|
||||
{{ params.data.name }}
|
||||
</a>
|
||||
<span v-else class="text-sn-grey" :title="params.data.name">
|
||||
{{ params.data.name }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
params: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -42,6 +42,7 @@ import axios from '../../packs/custom_axios.js';
|
|||
|
||||
import DataTable from '../shared/datatable/table.vue';
|
||||
import UsersRenderer from '../projects/renderers/users.vue';
|
||||
import NameRenderer from './renderers/name.vue';
|
||||
import NewProtocolModal from './modals/new.vue';
|
||||
import AccessModal from '../shared/access_modal/modal.vue';
|
||||
import KeywordsRenderer from './renderers/keywords.vue';
|
||||
|
|
@ -55,6 +56,7 @@ export default {
|
|||
components: {
|
||||
DataTable,
|
||||
UsersRenderer,
|
||||
NameRenderer,
|
||||
NewProtocolModal,
|
||||
AccessModal,
|
||||
KeywordsRenderer,
|
||||
|
|
@ -116,7 +118,7 @@ export default {
|
|||
headerName: this.i18n.t('protocols.index.thead.name'),
|
||||
sortable: true,
|
||||
notSelectable: true,
|
||||
cellRenderer: this.nameRenderer
|
||||
cellRenderer: 'NameRenderer'
|
||||
},
|
||||
{
|
||||
field: 'code',
|
||||
|
|
@ -337,14 +339,6 @@ export default {
|
|||
linkedMyModules(_event, rows) {
|
||||
[this.linkedMyModulesModalObject] = rows;
|
||||
},
|
||||
// renderers
|
||||
nameRenderer(params) {
|
||||
const { urls, name } = params.data;
|
||||
if (urls.show) {
|
||||
return `<a href="${urls.show}" title="${name}">${name}</a>`;
|
||||
}
|
||||
return `<span class="text-sn-grey" title="${name}">${name}</span>`;
|
||||
},
|
||||
usersFilterRenderer(option) {
|
||||
return `<div class="flex items-center gap-2">
|
||||
<img src="${option[2].avatar_url}" class="rounded-full w-6 h-6" />
|
||||
|
|
|
|||
16
app/javascript/vue/reports/renderers/name.vue
Normal file
16
app/javascript/vue/reports/renderers/name.vue
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<template>
|
||||
<span :title="params.data.name">
|
||||
{{ params.data.name }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
params: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -43,6 +43,7 @@ import axios from '../../packs/custom_axios.js';
|
|||
import DataTable from '../shared/datatable/table.vue';
|
||||
import DocxRenderer from './renderers/docx.vue';
|
||||
import PdfRenderer from './renderers/pdf.vue';
|
||||
import NameRenderer from './renderers/name.vue';
|
||||
import ConfirmationModal from '../shared/confirmation_modal.vue';
|
||||
import SaveToInventoryModal from './modals/save_to_inventory.vue';
|
||||
import UpdateReportModal from './modals/update.vue';
|
||||
|
|
@ -60,6 +61,7 @@ export default {
|
|||
DataTable,
|
||||
DocxRenderer,
|
||||
PdfRenderer,
|
||||
NameRenderer,
|
||||
ConfirmationModal,
|
||||
SaveToInventoryModal,
|
||||
UpdateReportModal
|
||||
|
|
@ -108,7 +110,7 @@ export default {
|
|||
field: 'name',
|
||||
headerName: this.i18n.t('projects.reports.index.thead_name'),
|
||||
sortable: true,
|
||||
cellRenderer: ({ data: { name } }) => `<span title="${name}">${name}</span>`
|
||||
cellRenderer: 'NameRenderer'
|
||||
}, {
|
||||
field: 'code',
|
||||
headerName: this.i18n.t('projects.reports.index.thead_id'),
|
||||
|
|
|
|||
22
app/javascript/vue/repositories/renderers/name.vue
Normal file
22
app/javascript/vue/repositories/renderers/name.vue
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<template>
|
||||
<a class="hover:no-underline flex items-center gap-1"
|
||||
:title="params.data.name"
|
||||
:href="params.data.urls.show"
|
||||
>
|
||||
<span class="truncate">
|
||||
<i v-if="params.data.shared || params.data.ishared" class="fas fa-users"></i>
|
||||
{{ params.data.name }}
|
||||
</span>
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
params: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -68,6 +68,7 @@ import EditRepositoryModal from './modals/edit.vue';
|
|||
import DuplicateRepositoryModal from './modals/duplicate.vue';
|
||||
import ShareRepositoryModal from './modals/share.vue';
|
||||
import DataTable from '../shared/datatable/table.vue';
|
||||
import NameRenderer from './renderers/name.vue';
|
||||
|
||||
export default {
|
||||
name: 'RepositoriesTable',
|
||||
|
|
@ -78,7 +79,8 @@ export default {
|
|||
NewRepositoryModal,
|
||||
EditRepositoryModal,
|
||||
DuplicateRepositoryModal,
|
||||
ShareRepositoryModal
|
||||
ShareRepositoryModal,
|
||||
NameRenderer
|
||||
},
|
||||
props: {
|
||||
dataSource: {
|
||||
|
|
@ -138,7 +140,7 @@ export default {
|
|||
headerName: this.i18n.t('libraries.index.table.name'),
|
||||
sortable: true,
|
||||
notSelectable: true,
|
||||
cellRenderer: this.nameRenderer
|
||||
cellRenderer: 'NameRenderer'
|
||||
},
|
||||
{
|
||||
field: 'code',
|
||||
|
|
@ -277,23 +279,6 @@ export default {
|
|||
share(_event, rows) {
|
||||
const [repository] = rows;
|
||||
this.shareRepository = repository;
|
||||
},
|
||||
// Renderers
|
||||
nameRenderer(params) {
|
||||
const {
|
||||
name,
|
||||
urls,
|
||||
shared,
|
||||
ishared
|
||||
} = params.data;
|
||||
let sharedIcon = '';
|
||||
if (shared || ishared) {
|
||||
sharedIcon = '<i class="fas fa-users"></i>';
|
||||
}
|
||||
return `<a class="hover:no-underline flex items-center gap-1"
|
||||
title="${name}" href="${urls.show}">
|
||||
<span class="truncate">${sharedIcon}${name}</span>
|
||||
</a>`;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
/* global GLOBAL_CONSTANTS */
|
||||
|
||||
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 RestrictedExtensionModal from '../../modal/restricted_extension_modal.vue';
|
||||
import UpdateVersionModal from '../../modal/update_version_modal.vue';
|
||||
|
||||
export default {
|
||||
|
|
@ -10,15 +13,17 @@ export default {
|
|||
localAppName: null,
|
||||
scinoteEditRunning: null,
|
||||
showNoPredefinedAppModal: false,
|
||||
showRestrictedExtensionModal: false,
|
||||
showUpdateVersionModal: false,
|
||||
editAppModal: false,
|
||||
pollingInterval: null,
|
||||
pollingInterval: null
|
||||
};
|
||||
},
|
||||
components: {
|
||||
editLaunchingApplicationModal,
|
||||
NoPredefinedAppModal,
|
||||
UpdateVersionModal
|
||||
UpdateVersionModal,
|
||||
RestrictedExtensionModal
|
||||
},
|
||||
computed: {
|
||||
attributes() {
|
||||
|
|
@ -93,9 +98,16 @@ export default {
|
|||
}
|
||||
},
|
||||
async openLocally() {
|
||||
const restrictedExtension = GLOBAL_CONSTANTS.SCINOTE_EDIT_RESTRICTED_EXTENSIONS.includes(
|
||||
this.attributes.file_extension.toUpperCase()
|
||||
);
|
||||
|
||||
if (this.isWrongVersion(window.scinoteEditVersion)) {
|
||||
this.showUpdateVersionModal = true;
|
||||
return;
|
||||
} else if (restrictedExtension) {
|
||||
this.showRestrictedExtensionModal = true;
|
||||
return;
|
||||
} else if (this.localAppName === null) {
|
||||
this.showNoPredefinedAppModal = true;
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,10 @@
|
|||
:fileName="attachment.attributes.file_name"
|
||||
@close="showNoPredefinedAppModal = false"
|
||||
/>
|
||||
<RestrictedExtensionModal
|
||||
v-if="showRestrictedExtensionModal"
|
||||
@close="showRestrictedExtensionModal = false"
|
||||
/>
|
||||
<editLaunchingApplicationModal
|
||||
v-if="editAppModal"
|
||||
:fileName="attachment.attributes.file_name"
|
||||
|
|
|
|||
|
|
@ -93,6 +93,10 @@
|
|||
:fileName="attachment.attributes.file_name"
|
||||
@close="showNoPredefinedAppModal = false"
|
||||
/>
|
||||
<RestrictedExtensionModal
|
||||
v-if="showRestrictedExtensionModal"
|
||||
@close="showRestrictedExtensionModal = false"
|
||||
/>
|
||||
<UpdateVersionModal
|
||||
v-if="showUpdateVersionModal"
|
||||
@close="showUpdateVersionModal = false"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
<template>
|
||||
<div ref="modal" @keydown.esc="cancel" class="modal" id="RestrictedExtensionModal" 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.restricted_extension_modal.title') }}
|
||||
</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p v-html="i18n.t('assets.restricted_extension_modal.body')"></p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-primary" @click="close">{{ this.i18n.t('assets.restricted_extension_modal.action') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import modalMixin from '../../modal_mixin';
|
||||
|
||||
export default {
|
||||
name: 'RestrictedExtensionModal',
|
||||
mixins: [modalMixin]
|
||||
};
|
||||
</script>
|
||||
|
|
@ -447,6 +447,12 @@ class Constants
|
|||
MIN_SCINOTE_EDIT_VERSION = ENV['MIN_SCINOTE_EDIT_VERSION'].freeze
|
||||
MAX_SCINOTE_EDIT_VERSION = ENV['MAX_SCINOTE_EDIT_VERSION'].freeze
|
||||
|
||||
# SciNote Edit unsupported extensions
|
||||
SCINOTE_EDIT_RESTRICTED_EXTENSIONS = %w(
|
||||
ACTION APP BIN COMMAND CSH OSX WORKFLOW DMG BAT BIN CAB CMD COM CPL EX_ EXE GADGET INF1 INS INX ISU JOB
|
||||
JSE LNK MSC MSI MSP MST PAF PIF PS1 REG RGS SCR SCT SHB SHS U3P VB VBE VBS VBSCRIPT WS WSF WSH
|
||||
).freeze
|
||||
|
||||
# quick search
|
||||
QUICK_SEARCH_LIMIT = 5
|
||||
QUICK_SEARCH_SEARCHABLE_OBJECTS = %w(project experiment my_module protocol repository_row
|
||||
|
|
|
|||
|
|
@ -3907,6 +3907,10 @@ en:
|
|||
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>"
|
||||
understand_button: "I understand"
|
||||
set_up_app: "Set up an application to open this file"
|
||||
restricted_extension_modal:
|
||||
title: "Open file - Security warning"
|
||||
body: "This file type appears to be executable and can potentially harm your computer. It cannot be opened with SciNote Edit. To open the file please download it manually."
|
||||
action: "I understand"
|
||||
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 updating to the latest version."
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue