Attachments sidebar

Signed-off-by: Julius Härtl <jus@bitgrid.net>
This commit is contained in:
Julius Härtl
2020-12-16 16:48:11 +01:00
parent 02237040d4
commit 67c90b1da8
2 changed files with 71 additions and 20 deletions

View File

@@ -42,6 +42,7 @@ use OCP\ICache;
use OCP\ICacheFactory; use OCP\ICacheFactory;
use OCP\IDBConnection; use OCP\IDBConnection;
use OCP\IL10N; use OCP\IL10N;
use OCP\IPreview;
use OCP\Share\IShare; use OCP\Share\IShare;
class AttachmentService { class AttachmentService {
@@ -132,9 +133,11 @@ class AttachmentService {
} }
private function getFilesAppAttachments($cardId) { private function getFilesAppAttachments($cardId) {
/** @var IPreview $previewManager */
$previewManager = \OC::$server->get(IPreview::class);
$userFolder = \OC::$server->getRootFolder()->getUserFolder($this->userId); $userFolder = \OC::$server->getRootFolder()->getUserFolder($this->userId);
$shares = $this->shareProvider->getSharedWithByType($cardId, IShare::TYPE_DECK, -1, 0); $shares = $this->shareProvider->getSharedWithByType($cardId, IShare::TYPE_DECK, -1, 0);
return array_map(function (IShare $share) use ($cardId, $userFolder) { return array_map(function (IShare $share) use ($cardId, $userFolder, $previewManager) {
$file = $share->getNode(); $file = $share->getNode();
$nodes = $userFolder->getById($file->getId()); $nodes = $userFolder->getById($file->getId());
$userNode = array_shift($nodes); $userNode = array_shift($nodes);
@@ -152,7 +155,8 @@ class AttachmentService {
'extendedData' => [ 'extendedData' => [
'filesize' => $file->getSize(), 'filesize' => $file->getSize(),
'mimetype' => $file->getMimeType(), 'mimetype' => $file->getMimeType(),
'info' => pathinfo($file->getName()) 'info' => pathinfo($file->getName()),
'hasPreview' => $previewManager->isAvailable($file),
] ]
]; ];
}, $shares); }, $shares);

View File

@@ -22,9 +22,14 @@
<template> <template>
<AttachmentDragAndDrop :card-id="cardId" class="drop-upload--sidebar"> <AttachmentDragAndDrop :card-id="cardId" class="drop-upload--sidebar">
<button class="icon-upload" @click="clickAddNewAttachmment()"> <div class="button-group">
{{ t('deck', 'Upload attachment') }} <button class="icon-upload" @click="uploadNewFile()">
{{ t('deck', 'Upload new files') }}
</button> </button>
<button class="icon-folder" @click="shareFromFiles()">
{{ t('deck', 'Share from Files') }}
</button>
</div>
<input ref="localAttachments" <input ref="localAttachments"
type="file" type="file"
style="display: none;" style="display: none;"
@@ -45,7 +50,8 @@
<li v-for="attachment in attachments" <li v-for="attachment in attachments"
:key="attachment.id" :key="attachment.id"
class="attachment"> class="attachment">
<a class="fileicon" :style="mimetypeForAttachment(attachment.extendedData.mimetype)" <a class="fileicon"
:style="mimetypeForAttachment(attachment)"
@click.prevent="showViewer(attachment)" /> @click.prevent="showViewer(attachment)" />
<div class="details"> <div class="details">
<a @click.prevent="showViewer(attachment)"> <a @click.prevent="showViewer(attachment)">
@@ -62,18 +68,18 @@
{{ t('deck', 'Add this attachment') }} {{ t('deck', 'Add this attachment') }}
</ActionButton> </ActionButton>
</Actions> </Actions>
<Actions v-if="removable"> <Actions v-if="removable" :force-menu="true">
<ActionLink v-if="attachment.fileid" icon="icon-folder" :href="'/index.php/f/'+attachment.fileid"> <ActionLink v-if="attachment.fileid" icon="icon-folder" :href="'/index.php/f/'+attachment.fileid">
{{ t('deck', 'Show in files') }} {{ t('deck', 'Show in files') }}
</ActionLink> </ActionLink>
<ActionButton icon="icon-delete"> <ActionButton v-if="attachment.fileid" icon="icon-delete">
{{ t('deck', 'Unshare file') }} {{ t('deck', 'Unshare file') }}
</ActionButton> </ActionButton>
<ActionButton v-if="attachment.deletedAt === 0" icon="icon-delete" @click="$emit('deleteAttachment', attachment)">
<ActionButton v-if="!attachment.fileid && attachment.deletedAt === 0" icon="icon-delete" @click="$emit('deleteAttachment', attachment)">
{{ t('deck', 'Delete Attachment') }} {{ t('deck', 'Delete Attachment') }}
</ActionButton> </ActionButton>
<ActionButton v-else-if="!attachment.fileid" icon="icon-history" @click="$emit('restoreAttachment', attachment)">
<ActionButton v-else icon="icon-history" @click="$emit('restoreAttachment', attachment)">
{{ t('deck', 'Restore Attachment') }} {{ t('deck', 'Restore Attachment') }}
</ActionButton> </ActionButton>
</Actions> </Actions>
@@ -91,8 +97,16 @@ import { generateUrl } from '@nextcloud/router'
import { mapState } from 'vuex' import { mapState } from 'vuex'
import { loadState } from '@nextcloud/initial-state' import { loadState } from '@nextcloud/initial-state'
import attachmentUpload from '../../mixins/attachmentUpload' import attachmentUpload from '../../mixins/attachmentUpload'
import { getFilePickerBuilder } from '@nextcloud/dialogs'
const maxUploadSizeState = loadState('deck', 'maxUploadSize') const maxUploadSizeState = loadState('deck', 'maxUploadSize')
const picker = getFilePickerBuilder(t('deck', 'File to share'))
.setMultiSelect(false)
.setModal(true)
.setType(1)
.allowDirectories()
.build()
export default { export default {
name: 'AttachmentList', name: 'AttachmentList',
components: { components: {
@@ -131,14 +145,17 @@ export default {
return [...this.$store.getters.attachmentsByCard(this.cardId)].sort((a, b) => b.id - a.id) return [...this.$store.getters.attachmentsByCard(this.cardId)].sort((a, b) => b.id - a.id)
}, },
mimetypeForAttachment() { mimetypeForAttachment() {
return (mimetype) => { return (attachment) => {
const url = OC.MimeType.getIconUrl(mimetype) const url = attachment.extendedData.hasPreview ? this.attachmentPreview(attachment) : OC.MimeType.getIconUrl(attachment.extendedData.mimetype)
const styles = { const styles = {
'background-image': `url("${url}")`, 'background-image': `url("${url}")`,
} }
return styles return styles
} }
}, },
attachmentPreview() {
return (attachment) => (attachment.fileid ? generateUrl(`/core/preview?fileId=${attachment.fileid}&x=64&y=64&a=true`) : null)
},
attachmentUrl() { attachmentUrl() {
return (attachment) => generateUrl(`/apps/deck/cards/${attachment.cardId}/attachment/${attachment.id}`) return (attachment) => generateUrl(`/apps/deck/cards/${attachment.cardId}/attachment/${attachment.id}`)
}, },
@@ -159,8 +176,13 @@ export default {
} }
}, },
}, },
created() { watch: {
cardId: {
immediate: true,
handler() {
this.$store.dispatch('fetchAttachments', this.cardId) this.$store.dispatch('fetchAttachments', this.cardId)
}
},
}, },
methods: { methods: {
handleUploadFile(event) { handleUploadFile(event) {
@@ -170,11 +192,28 @@ export default {
} }
event.target.value = '' event.target.value = ''
}, },
uploadNewFile() {
this.$refs.localAttachments.click()
},
shareFromFiles() {
picker.pick()
.then(async(path) => {
console.debug(`path ${path} selected for sharing`)
if (!path.startsWith('/')) {
throw new Error(t('files', 'Invalid path selected'))
}
// FIXME: Share file
})
},
clickAddNewAttachmment() { clickAddNewAttachmment() {
this.$refs.localAttachments.click() this.$refs.localAttachments.click()
}, },
showViewer(attachment) { showViewer(attachment) {
if (window.OCA.Viewer.availableHandlers.map(handler => handler.mimes).flat().includes(attachment.extendedData.mimetype)) {
window.OCA.Viewer.open(attachment.path) window.OCA.Viewer.open(attachment.path)
return
}
window.location = generateUrl('/f/' + attachment.fileid)
}, },
}, },
} }
@@ -182,9 +221,17 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
.icon-upload { .button-group {
padding-left: 35px; display: flex;
background-position: 10px center;
.icon-upload, .icon-folder {
padding-left: 44px;
background-position: 16px center;
flex-grow: 1;
height: 44px;
margin-bottom: 12px;
text-align: left;
}
} }
.attachment-list { .attachment-list {