Select Git revision
-
Leštáková, Michaela authoredLeštáková, Michaela authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
DetailView.vue 15.23 KiB
<template>
<b-modal
size="xl"
id="detail-view"
ref="modal"
:title="showDetail === true ? $t('detailViewTitleEdit') : $t('detailViewTitleUpload')"
:hide-footer= true
@show="checkInputContraints()"
@ok="cleanup"
@hide="cleanup"
@cancel="cleanup"
@close="cleanup"
>
<b-container>
<b-row>
<b-col cols="9">
<b-row class="paddingDifference">
<b-col cols="4">{{ $t('detailViewSelectLabel') }}</b-col>
<b-col cols="8">
<b-form-select
v-model="selected"
:options="getOptions()"
multiple
class="select-fullwidth"
/>
<b-alert v-model="showBadFileNameAlert" variant="danger" dismissible>
{{ $t('detailViewBadFileName') }}
</b-alert>
</b-col>
</b-row>
<b-row class="modalContent" v-if="editableFiles.length > 0">
<b-col class='metadataContent' cols="12">
<h5>{{ $t('metadataHeadline') }}</h5>
<b-row>
<b-col class='fileInfo col-form-label text-sm-right' cols="3">{{ $t('infoFileName') }}</b-col>
<b-col class='col-form-label'>{{ fileInfo.name === null || fileInfo.name === '' ? $t('infoFileNoInformation') : fileInfo.name }}</b-col>
</b-row>
<b-row>
<b-col class='fileInfo col-form-label text-sm-right' cols="3">{{ $t('infoFileLastModified') }}</b-col>
<b-col class='col-form-label'>{{ fileInfo.lastModified === null || fileInfo.lastModified === '' ? $t('infoFileNoInformation') : new Date ( fileInfo.lastModified ) }}</b-col>
</b-row>
<b-row>
<b-col class='fileInfo col-form-label text-sm-right' cols="3">{{ $t('infoFileCreated') }}</b-col>
<b-col class='col-form-label'>{{ fileInfo.created === null || fileInfo.created === '' ? $t('infoFileNoInformation') : new Date( fileInfo.created) }}</b-col>
</b-row>
<b-row>
<b-col class='fileInfo col-form-label text-sm-right' cols="3">{{ $t('infoFileSize') }}</b-col>
<b-col class='col-form-label'>{{ fileInfo.size === null || fileInfo.size === '' ? $t('infoFileNoInformation') : (fileInfo.size + " Bytes") }}</b-col>
</b-row>
<component class='generatedForm'
:is="currentComponent"
:projectId="projectId"
:resourceId="resourceId"
:applicationProfileId="applicationProfileId"
:SHACLResponse="SHACLResponse"/>
</b-col>
</b-row>
<b-row class='modalContent' v-else>
<b-col class='metadataContent' cols="12">
<h5>{{ $t('metadataHeadline') }}</h5>
<component class='generatedForm'
:is="currentComponent"
:projectId="projectId"
:resourceId="resourceId"
:applicationProfileId="applicationProfileId"
:SHACLResponse="SHACLResponse"/>
</b-col>
</b-row>
</b-col>
<b-col class="detail-view-button" v-if="showDetail">
<b-button variant="success" @click="download()">{{ $t('detailViewBtnDownload') }}</b-button>
<b-button class="hiddenButton" variant="secondary" @click="reuse()">{{ $t('detailViewBtnReuse') }}</b-button>
<b-button class="hiddenButton" variant="secondary" @click="move()">{{ $t('detailViewBtnMove') }}</b-button>
<b-button class="hiddenButton" variant="secondary" @click="publish()">{{ $t('detailViewBtnPublish') }}</b-button>
<b-button class="hiddenButton" variant="secondary" @click="archive()">{{ $t('detailViewBtnArchive') }}</b-button>
</b-col>
<b-col class="detail-view-button" v-else>
<b-button variant="secondary" @click="selectFiles()" :placeholder="$t('detailViewBtnSelectFiles')">{{ $t('detailViewBtnSelectFiles') }}</b-button>
<b-form-file ref="fileTrigger" multiple v-model="filesToUpload" class="mt-3" plain></b-form-file>
</b-col>
</b-row>
<b-row>
<b-col cols="3" class="detail-view-button">
<b-button v-if="showDetail" variant="danger" @click="deleteFiles()">{{ $t('detailViewBtnDelete') }}</b-button>
<b-button v-else variant="secondary" @click="cancel()">{{ $t('detailViewBtnCancel') }}</b-button>
</b-col>
<b-col></b-col>
<b-col cols="3" class="detail-view-button">
<b-button v-if="showDetail" variant="primary" @click="update()">{{ $t('detailViewBtnUpdate') }}</b-button>
<b-button v-else variant="primary" :disabled="uploadInProgess || !inputOk" @click="upload()">{{ $t('detailViewBtnUpload') }}</b-button>
</b-col>
</b-row>
</b-container>
<loading :active.sync="isWaitingForResponse"
:can-cancel="false"
:height="128"
:width="128"
:z-index="1500"
:color="color"
:is-full-page="true"></loading>
</b-modal>
</template>
<script lang="ts">
import Vue from 'vue';
import {
DataSourceApi,
ResourceApi,
MetadataApi,
defaultOnCatch,
redirectToProject,
} from '@coscine/api-connection';
import Loading from 'vue-loading-overlay';
import 'vue-loading-overlay/dist/vue-loading.css';
import FormGenerator from '@coscine/form-generator';
Vue.use(FormGenerator);
export default Vue.extend({
name: 'DetailView',
data() {
return {
selected: [] as object[],
filesToUpload: [] as object[],
numberOfCurrentlyProcessedFiles: 0,
isWaitingForResponse: false,
uploadInProgess: false,
inputOk: false,
showBadFileNameAlert: false,
color: '#00549f',
currentComponent: 'FormGenerator',
applicationProfiles: [] as object[],
SHACLResponse: {} as { [index: string]: any},
projectId: '',
version: '1.0.0',
};
},
components: {
Loading,
},
props: {
filesSelected: Boolean,
resourceId: String,
fileInfo: Object,
editableFiles: Array,
showDetail: Boolean,
uploadableFiles: Array,
folder: Array,
currentFolder: {
default: '/',
type: String,
},
applicationProfileId: String,
},
created() {
this.projectId = this.getProjectId();
},
methods: {
getProjectId() {
const baseUrl = (_spPageContextInfo as any).siteAbsoluteUrl;
const splitUrl = baseUrl.split('/');
const projectUri = splitUrl[splitUrl.length - 1];
return projectUri;
},
fileNamesOk() {
const charFilter = new RegExp('[\\/:?*<>|]+');
const allUploadFiles: File[] = [... new Set([...this.filesToUpload, ...this.uploadableFiles])] as File[];
if (allUploadFiles.length === 0) {
return false;
}
for (const file of allUploadFiles) {
if (charFilter.test(file.name)) {
this.showBadFileNameAlert = true;
return false;
}
}
this.showBadFileNameAlert = false;
return true;
},
checkInputContraints() {
// TODO also consider application profile form validation results here
// also make sure that input changes/ changes with form validation
// and consider the file name restraints before activating the button
if (this.fileNamesOk()) {
this.inputOk = true;
}
},
upload() {
this.numberOfCurrentlyProcessedFiles = this.filesToUpload.length + this.uploadableFiles.length;
if (this.numberOfCurrentlyProcessedFiles > 0) {
this.isWaitingForResponse = true;
this.uploadInProgess = true;
}
for (const fileToUpload of this.filesToUpload) {
const file = fileToUpload as any;
this.uploadFile(file);
}
for (const uploadableFile of this.uploadableFiles) {
const file = uploadableFile as any;
this.uploadFile(file);
}
this.cleanup();
},
uploadFile(file: any) {
const me = this;
const absolutepath = (this.currentFolder !== '/' ? this.currentFolder : '') + file.name;
const reader = new FileReader();
reader.onload = (event: any) => {
const contents = event.target.result;
if (me.folder.find( (x) => (x as any).name === file.name) === undefined ) {
DataSourceApi.Upload(
me.resourceId,
absolutepath,
file.type,
contents,
(response: any) => {
me.folder.push({
isFolder: false,
name: file.name,
absolutepath: '/' + absolutepath,
lastModified: new Date(),
created: new Date(),
size: file.size,
});
me.numberOfCurrentlyProcessedFiles -= 1;
if (me.numberOfCurrentlyProcessedFiles === 0 ) {
me.$bvModal.hide('detail-view');
me.isWaitingForResponse = false;
me.uploadInProgess = false;
}
},
defaultOnCatch,
);
} else {
DataSourceApi.Update(
me.resourceId,
absolutepath,
file.type,
contents,
(response: any) => {
const tmp = me.folder.find( (x) => (x as any).name === file.name);
(tmp as any).lastModified = new Date();
(tmp as any).created = new Date();
(tmp as any).size = file.size;
me.numberOfCurrentlyProcessedFiles -= 1;
if (me.numberOfCurrentlyProcessedFiles === 0 ) {
me.$bvModal.hide('detail-view');
me.isWaitingForResponse = false;
me.uploadInProgess = false;
}
},
defaultOnCatch,
);
}
MetadataApi.storeMetadataForFile(this.resourceId, this.currentFolder + file.name, this.version,
this.SHACLResponse, null, defaultOnCatch);
};
reader.readAsArrayBuffer(file);
},
download() {
DataSourceApi.downloadDataSourceFile(
this.resourceId,
this.fileInfo.absolutepath,
this.fileInfo.name,
defaultOnCatch,
);
},
selectFiles() {
(this.$refs.fileTrigger as any).$el.click();
},
update() {
const me = this;
this.numberOfCurrentlyProcessedFiles = this.editableFiles.length;
if (this.numberOfCurrentlyProcessedFiles > 0) {
this.isWaitingForResponse = true;
this.uploadInProgess = true;
}
const folder = this.fileInfo.absolutepath.substring( 0, this.fileInfo.absolutepath.indexOf('/') + 1);
for (const editableFile of this.editableFiles) {
const file = editableFile as any;
MetadataApi.storeMetadataForFile(this.resourceId, folder + file.text, this.version,
this.SHACLResponse, (response: any) => {
me.numberOfCurrentlyProcessedFiles -= 1;
if (me.numberOfCurrentlyProcessedFiles === 0 ) {
me.$bvModal.hide('detail-view');
me.isWaitingForResponse = false;
me.uploadInProgess = false;
}
}, defaultOnCatch);
}
},
cancel() {
this.cleanup();
this.$bvModal.hide('detail-view');
},
deleteFiles() {
this.numberOfCurrentlyProcessedFiles = this.editableFiles.length;
if (this.numberOfCurrentlyProcessedFiles > 0) {
this.isWaitingForResponse = true;
this.uploadInProgess = true;
}
const folder = this.fileInfo.absolutepath.substring( 0, this.fileInfo.absolutepath.indexOf('/') + 1);
for (const editableFile of this.editableFiles) {
const file = editableFile as any;
this.deleteFile(folder + file.text);
}
this.cleanup();
},
deleteFile(file: any) {
const me = this;
DataSourceApi.delete(
this.resourceId,
file,
(response: any) => {
me.numberOfCurrentlyProcessedFiles -= 1;
if (me.numberOfCurrentlyProcessedFiles === 0 ) {
me.$bvModal.hide('detail-view');
me.isWaitingForResponse = false;
me.uploadInProgess = false;
location.reload();
}
},
defaultOnCatch,
);
},
reuse() {
// TODO implement
},
move() {
// TODO implement
},
publish() {
// TODO implement
},
archive() {
// TODO implement
},
getOptions() {
const shown = [] as object[];
if (this.filesToUpload.length !== 0) {
for (const fileToUpload of this.filesToUpload) {
shown.push({ value: fileToUpload, text: (fileToUpload as any).name});
}
} else if (this.uploadableFiles.length !== 0) {
for (const uploadableFile of this.uploadableFiles) {
shown.push({ value: uploadableFile, text: (uploadableFile as any).name});
}
} else if (this.editableFiles.length !== 0) {
for (const editableFile of this.editableFiles) {
shown.push(editableFile as any);
}
}
return shown;
},
loadMetadata() {
if (this.fileInfo !== undefined && this.fileInfo.absolutepath !== undefined) {
const folder = this.fileInfo.absolutepath.substring( 0, this.fileInfo.absolutepath.indexOf('/') + 1);
if (this.editableFiles.length >= 1) {
const file = (this.editableFiles[0] as any);
this.$set(this, 'SHACLResponse', {});
MetadataApi.getMetadataForFile(this.resourceId, folder + file.text, this.version, (response: any) => {
const json = JSON.parse(response.data);
const objectKeys = Object.keys(json);
if (response.data !== undefined && objectKeys.length === 1) {
this.$set(this, 'SHACLResponse', json[objectKeys[0]]);
} else if (response.data !== undefined && objectKeys.length > 1) {
this.$set(this, 'SHACLResponse', json);
}
}, defaultOnCatch);
}
}
},
cleanup() {
this.filesToUpload.length = 0;
this.uploadableFiles.length = 0;
},
},
watch: {
fileInfo() {
this.loadMetadata();
},
filesToUpload() {
this.checkInputContraints();
},
},
});
</script>
<style>
.modal-header .modal-title {
margin-block-start: 0;
margin-block-end: 0;
margin-left: 0;
}
.modal-header button.close {
text-align: end;
min-width: 1em;
}
.modal footer button {
min-width: auto;
}
.detail-view-button button {
width: 100%;
}
.select-fullwidth {
width: 100%;
}
.detail-view-button input[type=file] {
display: none;
font-size: 0px;
position: absolute;
left: 0;
top: 0;
opacity: 0;
}
.modal-backdrop {
opacity: .5;
}
.metadataContent{
overflow-y: auto;
max-height: inherit;
}
.metadataContent .fileInfo{
padding-right: 0px;
}
.modalContent{
max-height: 700px;
}
.generatedForm{
margin-top: 10px;
}
.fileInfo{
font-weight: bold;
}
</style>
<style scoped>
.paddingDifference {
padding-bottom: 1em;
}
.invalid-tooltip {
margin-top: -20px;
}
#displayName {
font-size: large;
padding-bottom: 0.3em;
}
.hiddenButton{
display: none;
}
</style>