@@ -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);
|
||||||
|
|||||||
@@ -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()">
|
||||||
</button>
|
{{ t('deck', 'Upload new files') }}
|
||||||
|
</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,8 +50,9 @@
|
|||||||
<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"
|
||||||
@click.prevent="showViewer(attachment)" />
|
:style="mimetypeForAttachment(attachment)"
|
||||||
|
@click.prevent="showViewer(attachment)" />
|
||||||
<div class="details">
|
<div class="details">
|
||||||
<a @click.prevent="showViewer(attachment)">
|
<a @click.prevent="showViewer(attachment)">
|
||||||
<div class="filename">
|
<div class="filename">
|
||||||
@@ -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: {
|
||||||
this.$store.dispatch('fetchAttachments', this.cardId)
|
cardId: {
|
||||||
|
immediate: true,
|
||||||
|
handler() {
|
||||||
|
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) {
|
||||||
window.OCA.Viewer.open(attachment.path)
|
if (window.OCA.Viewer.availableHandlers.map(handler => handler.mimes).flat().includes(attachment.extendedData.mimetype)) {
|
||||||
|
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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user