389 lines
8.0 KiB
Vue
389 lines
8.0 KiB
Vue
<template>
|
|
<div class="uploadFiles">
|
|
<div class="pure-menu pure-menu-horizontal toolbar">
|
|
<ul class="pure-menu-list">
|
|
<li class="pure-menu-item"><a href="#" class="pure-menu-link" @click.prevent="startAssign()"><fa icon="user"></fa> {{ $t('admin.uploads.assign') }}</a></li>
|
|
<li class="pure-menu-item"><a href="#" class="pure-menu-link" @click.prevent="startDelete()"><fa icon="trash-alt"></fa> {{ $t('admin.delete') }}</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div v-if="showAssign" class="confirmToolbar pure-form pure-form-horizontal">
|
|
<select v-model="assignUser">
|
|
<option v-for="user in assignUsers" v-if="user.id !== group.lastUpload.userId" :value="user.id">{{ user.name }}</option>
|
|
</select>
|
|
|
|
<button class="pure-button pure-button-primary" @click.prevent="confirmAssign()" :disabled="!hasAssignUser"><fa icon="spinner" spin v-if="assigning"></fa> {{ $t('admin.uploads.assignApply') }}</button>
|
|
<button class="pure-button" @click.prevent="cancelAssign()">{{ $t('admin.cancel') }}</button>
|
|
</div>
|
|
|
|
<div v-if="showDelete" class="confirmToolbar pure-form pure-form-horizontal">
|
|
<button class="pure-button pure-button-confirm-delete" @click.prevent="confirmDelete()" :disabled="!isAnySelected"><fa icon="spinner" spin v-if="deleting"></fa> {{ $t('admin.deleteApply') }}</button>
|
|
<button class="pure-button" @click.prevent="cancelDelete()">{{ $t('admin.cancel') }}</button>
|
|
|
|
<button class="pure-button separator" @click.prevent="selectAll()"><fa :icon="['far', 'check-square']"></fa></button>
|
|
<button class="pure-button" @click.prevent="selectNone()"><fa :icon="['far', 'square']"></fa></button>
|
|
</div>
|
|
|
|
<template v-for="upload in group.uploads">
|
|
<template v-for="file in orderedFiles(upload.files)">
|
|
<div class="pure-g file" @click.prevent="fileClick(upload, file)" :title="file.name">
|
|
<div class="pure-u-1-2 filename">
|
|
<input type="checkbox" v-if="showDelete" v-bind:checked="getSelected(upload, file)" @input="(v) => setSelected(upload, file, v)" />
|
|
<a :href="getDownloadUrl(file)"><img :src="getFileIconUrl(file.name)" class="icon"> {{ file.name }}</a>
|
|
</div>
|
|
<div class="pure-u-1-4 date">
|
|
{{ upload.created | formatDateTime }}
|
|
</div>
|
|
<div class="pure-u-1-4 size">
|
|
{{ file.size | formatSizeSI }}
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import axios from 'axios';
|
|
import shared from '../../../shared';
|
|
import orderBy from 'lodash/orderBy';
|
|
import forEach from 'lodash/forEach';
|
|
|
|
export default {
|
|
props: ['group', 'assignUsers'],
|
|
|
|
data()
|
|
{
|
|
return {
|
|
showDelete: false,
|
|
deleting: false,
|
|
showAssign: false,
|
|
assigning: false,
|
|
assignUser: null,
|
|
selection: {}
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
hasAssignUser()
|
|
{
|
|
var self = this;
|
|
return self.assignUser !== null;
|
|
},
|
|
|
|
|
|
isAnySelected()
|
|
{
|
|
var self = this;
|
|
|
|
for (var fileId in self.selection)
|
|
{
|
|
if (self.selection.hasOwnProperty(fileId) && self.selection[fileId])
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
orderedFiles(files)
|
|
{
|
|
return orderBy(files, ['name'], ['asc']);
|
|
},
|
|
|
|
|
|
getFileIconUrl(filename)
|
|
{
|
|
var ext = this.getExtension(filename);
|
|
if (ext == '')
|
|
ext = '_blank';
|
|
|
|
return '/images/fileicons/16px/' + ext + '.png';
|
|
},
|
|
|
|
|
|
getExtension(filename)
|
|
{
|
|
var parts = filename.split('.');
|
|
return parts.length > 0 ? parts.pop() : '';
|
|
},
|
|
|
|
|
|
getDownloadUrl(file)
|
|
{
|
|
return '/admin/download/' + encodeURIComponent(file.id) + '/' + encodeURIComponent(file.name);
|
|
},
|
|
|
|
|
|
getSelected(upload, file)
|
|
{
|
|
var self = this;
|
|
|
|
let uniqueId = upload.id + ';' + file.id;
|
|
|
|
if (typeof self.selection[uniqueId] === 'undefined')
|
|
self.$set(self.selection, uniqueId, true);
|
|
|
|
return self.selection[uniqueId];
|
|
},
|
|
|
|
|
|
setSelected(upload, file, value)
|
|
{
|
|
var self = this;
|
|
|
|
let uniqueId = upload.id + ';' + file.id;
|
|
|
|
if (typeof self.selection[uniqueId] === 'undefined')
|
|
self.$set(self.selection, uniqueId, value);
|
|
else
|
|
self.selection[uniqueId] = value;
|
|
},
|
|
|
|
|
|
fileClick(upload, file)
|
|
{
|
|
var self = this;
|
|
|
|
if (self.showDelete)
|
|
self.setSelected(upload, file, !self.getSelected(upload, file));
|
|
else
|
|
location.href = self.getDownloadUrl(file);
|
|
},
|
|
|
|
|
|
startDelete()
|
|
{
|
|
var self = this;
|
|
|
|
if (self.showDelete)
|
|
self.cancelDelete();
|
|
else
|
|
{
|
|
self.showDelete = !self.showDelete;
|
|
self.showAssign = false;
|
|
}
|
|
},
|
|
|
|
|
|
confirmDelete()
|
|
{
|
|
var self = this;
|
|
|
|
if (self.deleting)
|
|
return;
|
|
|
|
let deleteFiles = [];
|
|
|
|
forEach(self.group.uploads, (upload) =>
|
|
{
|
|
forEach(upload.files, (file) =>
|
|
{
|
|
if (self.getSelected(upload, file))
|
|
{
|
|
deleteFiles.push({
|
|
uploadId: upload.id,
|
|
fileId: file.id
|
|
});
|
|
}
|
|
});
|
|
});
|
|
|
|
self.deleting = true;
|
|
|
|
axios.delete('/admin/fileuploads/', {
|
|
data: deleteFiles,
|
|
headers: {
|
|
Authorization: 'Bearer ' + shared.adminToken
|
|
}})
|
|
.then((response) =>
|
|
{
|
|
self.$emit('files-deleted', deleteFiles);
|
|
})
|
|
.catch((error) => { shared.$emit('apiError', error, this.$router) })
|
|
.then(() =>
|
|
{
|
|
self.deleting = false;
|
|
self.showDelete = false;
|
|
self.selection = {};
|
|
});
|
|
},
|
|
|
|
|
|
setAllSelected(value)
|
|
{
|
|
var self = this;
|
|
|
|
for (var fileId in self.selection)
|
|
{
|
|
if (self.selection.hasOwnProperty(fileId))
|
|
self.selection[fileId] = value;
|
|
}
|
|
},
|
|
|
|
|
|
selectAll()
|
|
{
|
|
var self = this;
|
|
self.setAllSelected(true);
|
|
},
|
|
|
|
|
|
selectNone()
|
|
{
|
|
var self = this;
|
|
self.setAllSelected(false);
|
|
},
|
|
|
|
|
|
cancelDelete()
|
|
{
|
|
var self = this;
|
|
|
|
self.showDelete = false
|
|
self.selection = {};
|
|
},
|
|
|
|
|
|
startAssign()
|
|
{
|
|
var self = this;
|
|
|
|
if (self.showAssign)
|
|
self.cancelAssign();
|
|
else
|
|
{
|
|
self.showAssign = !self.showAssign;
|
|
self.showDelete = false;
|
|
}
|
|
},
|
|
|
|
|
|
confirmAssign()
|
|
{
|
|
var self = this;
|
|
|
|
if (self.assigning)
|
|
return;
|
|
|
|
let userId = self.assignUser;
|
|
if (!userId)
|
|
return;
|
|
|
|
let codeId = self.group.lastUpload.codeId;
|
|
|
|
self.assignUser = null;
|
|
self.assigning = false;
|
|
|
|
axios.post('/admin/assign/code', {
|
|
id: codeId,
|
|
userId: userId
|
|
}, {
|
|
headers: {
|
|
Authorization: 'Bearer ' + shared.adminToken
|
|
}
|
|
})
|
|
.then((response) =>
|
|
{
|
|
self.$emit('code-assigned', codeId, userId);
|
|
})
|
|
.catch((error) => { shared.$emit('apiError', error, this.$router) })
|
|
.then(() =>
|
|
{
|
|
self.assigning = false;
|
|
self.showAssign = false;
|
|
})
|
|
},
|
|
|
|
|
|
cancelAssign()
|
|
{
|
|
var self = this;
|
|
|
|
self.showAssign = false;
|
|
self.assignUser = null;
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.file
|
|
{
|
|
border: solid 1px transparent;
|
|
font-size: 75%;
|
|
padding: .5rem;
|
|
vertical-align: middle;
|
|
cursor: pointer;
|
|
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
|
|
a
|
|
{
|
|
color: black;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.icon
|
|
{
|
|
display: inline-block;
|
|
}
|
|
|
|
|
|
.date
|
|
{
|
|
text-align: right;
|
|
}
|
|
|
|
|
|
.size
|
|
{
|
|
color: #808080;
|
|
text-align: right;
|
|
}
|
|
|
|
|
|
&:hover
|
|
{
|
|
background-color: #d3e9f8;
|
|
border: solid 1px #a7d3f1;
|
|
}
|
|
}
|
|
|
|
|
|
.upload
|
|
{
|
|
background-color: #fafafa;
|
|
border-bottom: solid 1px #f4f4f4;
|
|
padding: .2rem;
|
|
}
|
|
|
|
|
|
.codedescription
|
|
{
|
|
font-weight: bold;
|
|
}
|
|
|
|
|
|
.toolbar
|
|
{
|
|
border-bottom: solid 2px #f0f0f0;
|
|
}
|
|
|
|
|
|
.confirmToolbar
|
|
{
|
|
margin-top: .5rem;
|
|
margin-bottom: .5rem;
|
|
font-size: 75%;
|
|
}
|
|
|
|
|
|
.separator
|
|
{
|
|
margin-left: 2rem;
|
|
}
|
|
</style> |