parent
b6d8fc97af
commit
6130f1a78e
@ -0,0 +1,39 @@ |
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
/** |
||||
* @copyright Copyright (c) 2022 Julius Härtl <jus@bitgrid.net> |
||||
* |
||||
* @author Julius Härtl <jus@bitgrid.net> |
||||
* |
||||
* @license GNU AGPL version 3 or any later version |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License as |
||||
* published by the Free Software Foundation, either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
*/ |
||||
|
||||
namespace OCA\Files\Listener; |
||||
|
||||
use OCP\Collaboration\Reference\RenderReferenceEvent; |
||||
use OCP\EventDispatcher\Event; |
||||
use OCP\EventDispatcher\IEventListener; |
||||
|
||||
class RenderReferenceEventListener implements IEventListener { |
||||
public function handle(Event $event): void { |
||||
if (!$event instanceof RenderReferenceEvent) { |
||||
return; |
||||
} |
||||
|
||||
\OCP\Util::addScript('files', 'reference-files'); |
||||
} |
||||
} |
@ -0,0 +1,58 @@ |
||||
/** |
||||
* @copyright Copyright (c) 2022 Julius Härtl <jus@bitgrid.net> |
||||
* |
||||
* @author Julius Härtl <jus@bitgrid.net> |
||||
* |
||||
* @license GNU AGPL version 3 or any later version |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License as |
||||
* published by the Free Software Foundation, either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU Affero General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
|
||||
import Vue from 'vue' |
||||
import { translate as t } from '@nextcloud/l10n' |
||||
|
||||
import { registerWidget, registerCustomPickerElement, NcCustomPickerRenderResult } from '@nextcloud/vue/dist/Components/NcRichText.js' |
||||
|
||||
import FileWidget from './views/ReferenceFileWidget.vue' |
||||
import FileReferencePickerElement from './views/FileReferencePickerElement.vue' |
||||
|
||||
Vue.mixin({ |
||||
methods: { |
||||
t, |
||||
}, |
||||
}) |
||||
|
||||
registerWidget('file', (el, { richObjectType, richObject, accessible }) => { |
||||
const Widget = Vue.extend(FileWidget) |
||||
new Widget({ |
||||
propsData: { |
||||
richObjectType, |
||||
richObject, |
||||
accessible, |
||||
}, |
||||
}).$mount(el) |
||||
}) |
||||
|
||||
registerCustomPickerElement('files', (el, { providerId, accessible }) => { |
||||
const Element = Vue.extend(FileReferencePickerElement) |
||||
const vueElement = new Element({ |
||||
propsData: { |
||||
providerId, |
||||
accessible, |
||||
}, |
||||
}).$mount(el) |
||||
return new NcCustomPickerRenderResult(vueElement.$el, vueElement) |
||||
}, (el, renderResult) => { |
||||
renderResult.object.$destroy() |
||||
}) |
@ -0,0 +1,113 @@ |
||||
<!-- |
||||
- @copyright Copyright (c) 2023 Julius Härtl <jus@bitgrid.net> |
||||
- |
||||
- @author Julius Härtl <jus@bitgrid.net> |
||||
- |
||||
- @license GNU AGPL version 3 or any later version |
||||
- |
||||
- This program is free software: you can redistribute it and/or modify |
||||
- it under the terms of the GNU Affero General Public License as |
||||
- published by the Free Software Foundation, either version 3 of the |
||||
- License, or (at your option) any later version. |
||||
- |
||||
- This program is distributed in the hope that it will be useful, |
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
- GNU Affero General Public License for more details. |
||||
- |
||||
- You should have received a copy of the GNU Affero General Public License |
||||
- along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
--> |
||||
|
||||
<template> |
||||
<div ref="picker" class="reference-file-picker" /> |
||||
</template> |
||||
|
||||
<script> |
||||
import { FilePickerType } from '@nextcloud/dialogs' |
||||
import { generateUrl } from '@nextcloud/router' |
||||
export default { |
||||
name: 'FileReferencePickerElement', |
||||
components: { |
||||
}, |
||||
props: { |
||||
providerId: { |
||||
type: String, |
||||
required: true, |
||||
}, |
||||
accessible: { |
||||
type: Boolean, |
||||
default: false, |
||||
}, |
||||
}, |
||||
mounted() { |
||||
this.openFilePicker() |
||||
window.addEventListener('click', this.onWindowClick) |
||||
}, |
||||
beforeDestroy() { |
||||
window.removeEventListener('click', this.onWindowClick) |
||||
}, |
||||
methods: { |
||||
onWindowClick(e) { |
||||
if (e.target.tagName === 'A' && e.target.classList.contains('oc-dialog-close')) { |
||||
this.$emit('cancel') |
||||
} |
||||
}, |
||||
async openFilePicker() { |
||||
OC.dialogs.filepicker( |
||||
t('files', 'Select file or folder to link to'), |
||||
(file) => { |
||||
const client = OC.Files.getClient() |
||||
client.getFileInfo(file).then((_status, fileInfo) => { |
||||
this.submit(fileInfo.id) |
||||
}) |
||||
}, |
||||
false, // multiselect |
||||
[], // mime filter |
||||
false, // modal |
||||
FilePickerType.Choose, // type |
||||
'', |
||||
{ |
||||
target: this.$refs.picker, |
||||
}, |
||||
) |
||||
}, |
||||
submit(fileId) { |
||||
const fileLink = window.location.protocol + '//' + window.location.host |
||||
+ generateUrl('/f/{fileId}', { fileId }) |
||||
this.$emit('submit', fileLink) |
||||
}, |
||||
}, |
||||
} |
||||
</script> |
||||
|
||||
<style scoped lang="scss"> |
||||
.reference-file-picker { |
||||
flex-grow: 1; |
||||
margin-top: 44px; |
||||
|
||||
&:deep(.oc-dialog) { |
||||
transform: none !important; |
||||
box-shadow: none !important; |
||||
flex-grow: 1 !important; |
||||
position: static !important; |
||||
width: 100% !important; |
||||
height: auto !important; |
||||
padding: 0 !important; |
||||
max-width: initial; |
||||
|
||||
.oc-dialog-close { |
||||
display: none; |
||||
} |
||||
|
||||
.oc-dialog-buttonrow.onebutton.aside { |
||||
position: absolute; |
||||
padding: 12px 32px; |
||||
} |
||||
|
||||
.oc-dialog-content { |
||||
max-width: 100% !important; |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,182 @@ |
||||
<!-- |
||||
- @copyright Copyright (c) 2022 Julius Härtl <jus@bitgrid.net> |
||||
- |
||||
- @author Julius Härtl <jus@bitgrid.net> |
||||
- |
||||
- @license GNU AGPL version 3 or any later version |
||||
- |
||||
- This program is free software: you can redistribute it and/or modify |
||||
- it under the terms of the GNU Affero General Public License as |
||||
- published by the Free Software Foundation, either version 3 of the |
||||
- License, or (at your option) any later version. |
||||
- |
||||
- This program is distributed in the hope that it will be useful, |
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
- GNU Affero General Public License for more details. |
||||
- |
||||
- You should have received a copy of the GNU Affero General Public License |
||||
- along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
--> |
||||
|
||||
<template> |
||||
<div v-if="!accessible" class="widget-file widget-file--no-access"> |
||||
<div class="widget-file--image widget-file--image--icon icon-folder" /> |
||||
<div class="widget-file--details"> |
||||
<p class="widget-file--title"> |
||||
{{ t('files', 'File cannot be accessed') }} |
||||
</p> |
||||
<p class="widget-file--description"> |
||||
{{ t('files', 'You might not have have permissions to view it, ask the sender to share it') }} |
||||
</p> |
||||
</div> |
||||
</div> |
||||
<a v-else |
||||
class="widget-file" |
||||
:href="richObject.link" |
||||
@click.prevent="navigate"> |
||||
<div class="widget-file--image" :class="filePreviewClass" :style="filePreview" /> |
||||
<div class="widget-file--details"> |
||||
<p class="widget-file--title">{{ richObject.name }}</p> |
||||
<p class="widget-file--description">{{ fileSize }}<br>{{ fileMtime }}</p> |
||||
<p class="widget-file--link">{{ filePath }}</p> |
||||
</div> |
||||
</a> |
||||
</template> |
||||
<script> |
||||
import { generateUrl } from '@nextcloud/router' |
||||
import path from 'path' |
||||
|
||||
export default { |
||||
name: 'ReferenceFileWidget', |
||||
props: { |
||||
richObject: { |
||||
type: Object, |
||||
required: true, |
||||
}, |
||||
accessible: { |
||||
type: Boolean, |
||||
default: true, |
||||
}, |
||||
}, |
||||
data() { |
||||
return { |
||||
previewUrl: window.OC.MimeType.getIconUrl(this.richObject.mimetype), |
||||
} |
||||
}, |
||||
computed: { |
||||
fileSize() { |
||||
return window.OC.Util.humanFileSize(this.richObject.size) |
||||
}, |
||||
fileMtime() { |
||||
return window.OC.Util.relativeModifiedDate(this.richObject.mtime * 1000) |
||||
}, |
||||
filePath() { |
||||
return path.dirname(this.richObject.path) |
||||
}, |
||||
filePreview() { |
||||
if (this.previewUrl) { |
||||
return { |
||||
backgroundImage: 'url(' + this.previewUrl + ')', |
||||
} |
||||
} |
||||
|
||||
return { |
||||
backgroundImage: 'url(' + window.OC.MimeType.getIconUrl(this.richObject.mimetype) + ')', |
||||
} |
||||
|
||||
}, |
||||
filePreviewClass() { |
||||
if (this.previewUrl) { |
||||
return 'widget-file--image--preview' |
||||
} |
||||
return 'widget-file--image--icon' |
||||
|
||||
}, |
||||
}, |
||||
mounted() { |
||||
if (this.richObject['preview-available']) { |
||||
const previewUrl = generateUrl('/core/preview?fileId={fileId}&x=250&y=250', { |
||||
fileId: this.richObject.id, |
||||
}) |
||||
const img = new Image() |
||||
img.onload = () => { |
||||
this.previewUrl = previewUrl |
||||
} |
||||
img.onerror = err => { |
||||
console.error('could not load recommendation preview', err) |
||||
} |
||||
img.src = previewUrl |
||||
} |
||||
}, |
||||
methods: { |
||||
navigate() { |
||||
if (OCA.Viewer && OCA.Viewer.mimetypes.indexOf(this.richObject.mimetype) !== -1) { |
||||
OCA.Viewer.open({ path: this.richObject.path }) |
||||
return |
||||
} |
||||
window.location = generateUrl('/f/' + this.id) |
||||
}, |
||||
}, |
||||
} |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.widget-file { |
||||
display: flex; |
||||
flex-grow: 1; |
||||
color: var(--color-main-text) !important; |
||||
text-decoration: none !important; |
||||
|
||||
&--image { |
||||
min-width: 40%; |
||||
background-position: center; |
||||
background-size: cover; |
||||
background-repeat: no-repeat; |
||||
|
||||
&.widget-file--image--icon { |
||||
min-width: 88px; |
||||
background-size: 44px; |
||||
} |
||||
} |
||||
|
||||
&--title { |
||||
overflow: hidden; |
||||
text-overflow: ellipsis; |
||||
white-space: nowrap; |
||||
font-weight: bold; |
||||
} |
||||
|
||||
&--details { |
||||
padding: 12px; |
||||
flex-grow: 1; |
||||
display: flex; |
||||
flex-direction: column; |
||||
|
||||
p { |
||||
margin: 0; |
||||
padding: 0; |
||||
} |
||||
} |
||||
|
||||
&--description { |
||||
overflow: hidden; |
||||
text-overflow: ellipsis; |
||||
display: -webkit-box; |
||||
-webkit-line-clamp: 3; |
||||
line-clamp: 3; |
||||
-webkit-box-orient: vertical; |
||||
} |
||||
|
||||
&--link { |
||||
color: var(--color-text-maxcontrast); |
||||
} |
||||
|
||||
&.widget-file--no-access { |
||||
padding: 12px; |
||||
|
||||
.widget-file--details { |
||||
padding: 0; |
||||
} |
||||
} |
||||
} |
||||
</style> |
Loading…
Reference in new issue