зеркало из https://github.com/nextcloud/spreed.git
Merge pull request #7491 from nextcloud/feature/#5330/create-text-document-within-conversation
🗒️ Create text document within conversation
This commit is contained in:
Коммит
2fb3ee8220
|
@ -376,7 +376,7 @@ export default {
|
|||
|
||||
const availableHandlers = OCA.Viewer.availableHandlers
|
||||
for (let i = 0; i < availableHandlers.length; i++) {
|
||||
if (availableHandlers[i]?.mimes?.includes(this.mimetype)) {
|
||||
if (availableHandlers[i]?.mimes?.includes && availableHandlers[i].mimes.includes(this.mimetype)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,27 +43,41 @@
|
|||
:disabled="disabled"
|
||||
:aria-label="t('spreed', 'Share files to the conversation')"
|
||||
:aria-haspopup="true">
|
||||
<Paperclip slot="icon"
|
||||
:size="16" />
|
||||
<template #icon>
|
||||
<Paperclip :size="16" />
|
||||
</template>
|
||||
|
||||
<NcActionButton v-if="canUploadFiles"
|
||||
:close-after-click="true"
|
||||
icon="icon-upload"
|
||||
@click.prevent="clickImportInput">
|
||||
{{ t('spreed', 'Upload new files') }}
|
||||
<template #icon>
|
||||
<Upload :size="20" />
|
||||
</template>
|
||||
{{ t('spreed', 'Upload from device') }}
|
||||
</NcActionButton>
|
||||
<NcActionButton v-if="canShareFiles"
|
||||
:close-after-click="true"
|
||||
icon="icon-folder"
|
||||
@click.prevent="handleFileShare">
|
||||
{{ t('spreed', 'Share from Files') }}
|
||||
<template #icon>
|
||||
<Folder :size="20" />
|
||||
</template>
|
||||
{{ shareFromNextcloudLabel }}
|
||||
</NcActionButton>
|
||||
<template v-if="canShareFiles">
|
||||
<NcActionButton v-for="(provider, i) in fileTemplateOptions"
|
||||
:key="i"
|
||||
:close-after-click="true"
|
||||
:icon="provider.iconClass"
|
||||
@click.prevent="showTextFileDialog = i">
|
||||
{{ provider.label }}
|
||||
</NcActionButton>
|
||||
</template>
|
||||
<NcActionButton v-if="canCreatePoll"
|
||||
:close-after-click="true"
|
||||
@click.prevent="toggleSimplePollsEditor(true)">
|
||||
<Poll slot="icon"
|
||||
:size="20"
|
||||
decorative
|
||||
title="" />
|
||||
<template #icon>
|
||||
<Poll :size="20" />
|
||||
</template>
|
||||
{{ t('spreed', 'Create new poll') }}
|
||||
</NcActionButton>
|
||||
</NcActions>
|
||||
|
@ -141,15 +155,65 @@
|
|||
</template>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<SimplePollsEditor v-if="showSimplePollsEditor"
|
||||
:token="token"
|
||||
@close="toggleSimplePollsEditor(false)" />
|
||||
|
||||
<!-- Text file creation dialog -->
|
||||
<NcModal v-if="showTextFileDialog !== false"
|
||||
size="normal"
|
||||
class="templates-picker"
|
||||
@close="dismissTextFileCreation">
|
||||
<div class="new-text-file">
|
||||
<h2>
|
||||
{{ t('spreed', 'Create and share a new file') }}
|
||||
</h2>
|
||||
<form class="new-text-file__form templates-picker__form"
|
||||
:style="style"
|
||||
@submit.prevent="handleCreateTextFile">
|
||||
<NcTextField id="new-file-form-name"
|
||||
ref="textFileTitleInput"
|
||||
:error="!!newFileError"
|
||||
:helper-text="newFileError"
|
||||
:label="t('spreed', 'Name of the new file')"
|
||||
:placeholder="textFileTitle"
|
||||
:value.sync="textFileTitle" />
|
||||
|
||||
<template v-if="fileTemplate.templates.length">
|
||||
<ul class="templates-picker__list">
|
||||
<TemplatePreview v-bind="emptyTemplate"
|
||||
:checked="checked === emptyTemplate.fileid"
|
||||
@check="onCheck" />
|
||||
|
||||
<TemplatePreview v-for="template in fileTemplate.templates"
|
||||
:key="template.fileid"
|
||||
v-bind="template"
|
||||
:checked="checked === template.fileid"
|
||||
:ratio="fileTemplate.ratio"
|
||||
@check="onCheck" />
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<div class="new-text-file__buttons">
|
||||
<NcButton type="tertiary"
|
||||
@click="dismissTextFileCreation">
|
||||
{{ t('spreed', 'Close') }}
|
||||
</NcButton>
|
||||
<NcButton type="primary"
|
||||
@click="handleCreateTextFile">
|
||||
{{ t('spreed', 'Create file') }}
|
||||
</NcButton>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</NcModal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AdvancedInput from './AdvancedInput/AdvancedInput.vue'
|
||||
import { getFilePickerBuilder } from '@nextcloud/dialogs'
|
||||
import { getFilePickerBuilder, showError } from '@nextcloud/dialogs'
|
||||
import { getCapabilities } from '@nextcloud/capabilities'
|
||||
import Quote from '../Quote.vue'
|
||||
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
|
||||
|
@ -157,7 +221,7 @@ import NcActions from '@nextcloud/vue/dist/Components/NcActions.js'
|
|||
import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js'
|
||||
import NcEmojiPicker from '@nextcloud/vue/dist/Components/NcEmojiPicker.js'
|
||||
import { EventBus } from '../../services/EventBus.js'
|
||||
import { shareFile } from '../../services/filesSharingServices.js'
|
||||
import { shareFile, createTextFile } from '../../services/filesSharingServices.js'
|
||||
import { CONVERSATION, PARTICIPANT } from '../../constants.js'
|
||||
import Paperclip from 'vue-material-design-icons/Paperclip.vue'
|
||||
import EmoticonOutline from 'vue-material-design-icons/EmoticonOutline.vue'
|
||||
|
@ -166,6 +230,11 @@ import BellOff from 'vue-material-design-icons/BellOff.vue'
|
|||
import AudioRecorder from './AudioRecorder/AudioRecorder.vue'
|
||||
import SimplePollsEditor from './SimplePollsEditor/SimplePollsEditor.vue'
|
||||
import Poll from 'vue-material-design-icons/Poll.vue'
|
||||
import NcModal from '@nextcloud/vue/dist/Components/NcModal.js'
|
||||
import Folder from 'vue-material-design-icons/Folder.vue'
|
||||
import Upload from 'vue-material-design-icons/Upload.vue'
|
||||
import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'
|
||||
import TemplatePreview from './TemplatePreview.vue'
|
||||
|
||||
const picker = getFilePickerBuilder(t('spreed', 'File to share'))
|
||||
.setMultiSelect(false)
|
||||
|
@ -174,8 +243,14 @@ const picker = getFilePickerBuilder(t('spreed', 'File to share'))
|
|||
.allowDirectories()
|
||||
.build()
|
||||
|
||||
const border = 2
|
||||
const margin = 8
|
||||
const width = margin * 20
|
||||
|
||||
export default {
|
||||
|
||||
name: 'NewMessageForm',
|
||||
|
||||
components: {
|
||||
AdvancedInput,
|
||||
Quote,
|
||||
|
@ -190,6 +265,11 @@ export default {
|
|||
BellOff,
|
||||
SimplePollsEditor,
|
||||
Poll,
|
||||
NcModal,
|
||||
Folder,
|
||||
Upload,
|
||||
TemplatePreview,
|
||||
NcTextField,
|
||||
},
|
||||
|
||||
props: {
|
||||
|
@ -207,6 +287,12 @@ export default {
|
|||
// True when the audiorecorder component is recording
|
||||
isRecordingAudio: false,
|
||||
showSimplePollsEditor: false,
|
||||
showTextFileDialog: false,
|
||||
textFileTitle: t('spreed', 'New file'),
|
||||
newFileError: '',
|
||||
|
||||
// Check empty template by default
|
||||
checked: -1,
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -304,7 +390,42 @@ export default {
|
|||
} else {
|
||||
return t('spreed', 'The participants will not be notified about this message')
|
||||
}
|
||||
},
|
||||
|
||||
shareFromNextcloudLabel() {
|
||||
return t('spreed', 'Share from {nextcloud}', { nextcloud: window.oc_defaults.productName })
|
||||
},
|
||||
|
||||
fileTemplateOptions() {
|
||||
return this.$store.getters.getFileTemplates()
|
||||
},
|
||||
|
||||
fileTemplate() {
|
||||
return this.fileTemplateOptions[this.showTextFileDialog]
|
||||
},
|
||||
|
||||
emptyTemplate() {
|
||||
return {
|
||||
basename: t('files', 'Blank'),
|
||||
fileid: -1,
|
||||
filename: t('files', 'Blank'),
|
||||
hasPreview: false,
|
||||
mime: this.fileTemplate?.mimetypes[0] || this.fileTemplate?.mimetypes,
|
||||
}
|
||||
},
|
||||
|
||||
selectedTemplate() {
|
||||
return this.fileTemplate.templates.find(template => template.fileid === this.checked)
|
||||
},
|
||||
|
||||
style() {
|
||||
return {
|
||||
'--margin': margin + 'px',
|
||||
'--width': width + 'px',
|
||||
'--border': border + 'px',
|
||||
'--fullwidth': width + 2 * margin + 2 * border + 'px',
|
||||
'--height': this.fileTemplate.ratio ? Math.round(width / this.fileTemplate.ratio) + 'px' : null,
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -324,6 +445,16 @@ export default {
|
|||
this.text = ''
|
||||
}
|
||||
},
|
||||
|
||||
showTextFileDialog(newValue) {
|
||||
if (newValue !== false) {
|
||||
const fileTemplate = this.fileTemplateOptions[newValue]
|
||||
this.textFileTitle = fileTemplate.label + fileTemplate.extension
|
||||
this.$nextTick(() => {
|
||||
this.focusTextDialogInput()
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
|
@ -331,6 +462,10 @@ export default {
|
|||
EventBus.$on('retry-message', this.handleRetryMessage)
|
||||
this.text = this.$store.getters.currentMessageInput(this.token) || ''
|
||||
// this.startRecording()
|
||||
|
||||
if (!this.$store.getters.areFileTemplatesInitialised) {
|
||||
this.$store.dispatch('getFileTemplates')
|
||||
}
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
|
@ -575,6 +710,88 @@ export default {
|
|||
toggleSimplePollsEditor(value) {
|
||||
this.showSimplePollsEditor = value
|
||||
},
|
||||
|
||||
/**
|
||||
* Manages the radio template picker change
|
||||
*
|
||||
* @param {number} fileid the selected template file id
|
||||
*/
|
||||
onCheck(fileid) {
|
||||
this.checked = fileid
|
||||
},
|
||||
|
||||
// Create text file and share it to a conversation
|
||||
async handleCreateTextFile() {
|
||||
this.newFileError = ''
|
||||
let filePath = this.$store.getters.getAttachmentFolder() + '/' + this.textFileTitle.replace('/', '')
|
||||
|
||||
if (!filePath.endsWith(this.fileTemplate.extension)) {
|
||||
filePath += this.fileTemplate.extension
|
||||
}
|
||||
|
||||
let fileData
|
||||
try {
|
||||
const response = await createTextFile(
|
||||
filePath,
|
||||
this.selectedTemplate?.filename,
|
||||
this.selectedTemplate?.templateType,
|
||||
)
|
||||
fileData = response.data.ocs.data
|
||||
} catch (error) {
|
||||
console.error('Error while creating file', error)
|
||||
if (error?.response?.data?.ocs?.meta?.message) {
|
||||
showError(error.response.data.ocs.meta.message)
|
||||
this.newFileError = error.response.data.ocs.meta.message
|
||||
} else {
|
||||
showError(t('spreed', 'Error while creating file'))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
await shareFile(filePath, this.token, '', '')
|
||||
|
||||
// The Viewer expects a file to be set in the sidebar if the sidebar
|
||||
// is open.
|
||||
if (this.$store.getters.getSidebarStatus) {
|
||||
OCA.Files.Sidebar.state.file = filePath
|
||||
}
|
||||
|
||||
OCA.Viewer.open({
|
||||
// Viewer expects an internal absolute path starting with "/".
|
||||
path: filePath,
|
||||
list: [
|
||||
fileData,
|
||||
],
|
||||
})
|
||||
|
||||
// FIXME Remove this hack once it is possible to set the parent
|
||||
// element of the viewer.
|
||||
// By default the viewer is a sibling of the fullscreen element, so
|
||||
// it is not visible when in fullscreen mode. It is not possible to
|
||||
// specify the parent nor to know when the viewer was actually
|
||||
// opened, so for the time being it is reparented if needed shortly
|
||||
// after calling it.
|
||||
setTimeout(() => {
|
||||
if (this.$store.getters.isFullscreen()) {
|
||||
document.getElementById('content-vue').appendChild(document.getElementById('viewer'))
|
||||
}
|
||||
}, 1000)
|
||||
|
||||
this.dismissTextFileCreation()
|
||||
},
|
||||
|
||||
dismissTextFileCreation() {
|
||||
this.showTextFileDialog = false
|
||||
this.textFileTitle = t('spreed', 'New file')
|
||||
this.newFileError = ''
|
||||
},
|
||||
|
||||
// Focus and select the text within the input field
|
||||
focusTextDialogInput() {
|
||||
// this.$refs.textFileTitleInput.$refs.inputField.$refs.input.focus()
|
||||
this.$refs.textFileTitleInput.$refs.inputField.$refs.input.select()
|
||||
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
@ -648,4 +865,38 @@ export default {
|
|||
opacity: .5 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.new-text-file {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
gap: 28px;
|
||||
padding: 20px;
|
||||
|
||||
&__buttons {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
justify-content: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
&__form {
|
||||
width: 100%;
|
||||
|
||||
.templates-picker__list {
|
||||
margin-top: 20px;
|
||||
display: grid;
|
||||
grid-gap: calc(var(--margin) * 2);
|
||||
grid-auto-columns: 1fr;
|
||||
// We want maximum 5 columns. Putting 6 as we don't count the grid gap. So it will always be lower than 6
|
||||
max-width: calc(var(--fullwidth) * 6);
|
||||
grid-template-columns: repeat(auto-fit, var(--fullwidth));
|
||||
// Make sure all rows are the same height
|
||||
grid-auto-rows: 1fr;
|
||||
// Center the columns set
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,240 @@
|
|||
<!--
|
||||
- @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com>
|
||||
-
|
||||
- @author John Molakvoæ <skjnldsv@protonmail.com>
|
||||
-
|
||||
- @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/>.
|
||||
-
|
||||
-->
|
||||
|
||||
<!-- FIXME COPY FROM apps/files/src/components/TemplatePreview.vue should be deduplicated -->
|
||||
<template>
|
||||
<li class="template-picker__item">
|
||||
<input :id="id"
|
||||
:checked="checked"
|
||||
type="radio"
|
||||
class="radio"
|
||||
name="template-picker"
|
||||
@change="onCheck">
|
||||
|
||||
<label :for="id" class="template-picker__label">
|
||||
<div class="template-picker__preview"
|
||||
:class="failedPreview ? 'template-picker__preview--failed' : ''">
|
||||
<img class="template-picker__image"
|
||||
:src="realPreviewUrl"
|
||||
alt=""
|
||||
draggable="false"
|
||||
@error="onFailure">
|
||||
</div>
|
||||
|
||||
<span class="template-picker__title">
|
||||
{{ nameWithoutExt }}
|
||||
</span>
|
||||
</label>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { generateUrl } from '@nextcloud/router'
|
||||
import { getCurrentUser } from '@nextcloud/auth'
|
||||
|
||||
const encodeFilePath = function(path) {
|
||||
const pathSections = (path.startsWith('/') ? path : `/${path}`).split('/')
|
||||
let relativePath = ''
|
||||
pathSections.forEach((section) => {
|
||||
if (section !== '') {
|
||||
relativePath += '/' + encodeURIComponent(section)
|
||||
}
|
||||
})
|
||||
return relativePath
|
||||
}
|
||||
|
||||
const isPublic = function() {
|
||||
return !getCurrentUser()
|
||||
}
|
||||
|
||||
const getToken = function() {
|
||||
return document.getElementById('sharingToken') && document.getElementById('sharingToken').value
|
||||
}
|
||||
|
||||
// preview width generation
|
||||
const previewWidth = 256
|
||||
|
||||
export default {
|
||||
name: 'TemplatePreview',
|
||||
inheritAttrs: false,
|
||||
|
||||
props: {
|
||||
basename: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
checked: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
fileid: {
|
||||
type: [String, Number],
|
||||
required: true,
|
||||
},
|
||||
filename: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
previewUrl: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
hasPreview: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
mime: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
ratio: {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
failedPreview: false,
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
/**
|
||||
* Strip away extension from name
|
||||
*
|
||||
* @return {string}
|
||||
*/
|
||||
nameWithoutExt() {
|
||||
return this.basename.indexOf('.') > -1 ? this.basename.split('.').slice(0, -1).join('.') : this.basename
|
||||
},
|
||||
|
||||
id() {
|
||||
return `template-picker-${this.fileid}`
|
||||
},
|
||||
|
||||
realPreviewUrl() {
|
||||
// If original preview failed, fallback to mime icon
|
||||
if (this.failedPreview && this.mimeIcon) {
|
||||
return this.mimeIcon
|
||||
}
|
||||
|
||||
if (this.previewUrl) {
|
||||
return this.previewUrl
|
||||
}
|
||||
// TODO: find a nicer standard way of doing this?
|
||||
if (isPublic()) {
|
||||
return generateUrl(`/apps/files_sharing/publicpreview/${getToken()}?fileId=${this.fileid}&file=${encodeFilePath(this.filename)}&x=${previewWidth}&y=${previewWidth}&a=1`)
|
||||
}
|
||||
return generateUrl(`/core/preview?fileId=${this.fileid}&x=${previewWidth}&y=${previewWidth}&a=1`)
|
||||
},
|
||||
|
||||
mimeIcon() {
|
||||
return OC.MimeType.getIconUrl(this.mime)
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
onCheck() {
|
||||
this.$emit('check', this.fileid)
|
||||
},
|
||||
onFailure() {
|
||||
this.failedPreview = true
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.template-picker {
|
||||
&__item {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&__label {
|
||||
display: flex;
|
||||
// Align in the middle of the grid
|
||||
align-items: center;
|
||||
flex: 1 1;
|
||||
flex-direction: column;
|
||||
|
||||
&, * {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
&::before {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
&__preview {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
// Stretch so all entries are the same width
|
||||
flex: 1 1;
|
||||
width: var(--width);
|
||||
min-height: var(--height);
|
||||
max-height: var(--height);
|
||||
padding: 0;
|
||||
border: var(--border) solid var(--color-border);
|
||||
border-radius: var(--border-radius-large);
|
||||
|
||||
input:checked + label > & {
|
||||
border-color: var(--color-primary);
|
||||
}
|
||||
|
||||
&--failed {
|
||||
// Make sure to properly center fallback icon
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
&__image {
|
||||
max-width: 100%;
|
||||
background-color: var(--color-main-background);
|
||||
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
// Failed preview, fallback to mime icon
|
||||
&__preview--failed &__image {
|
||||
width: calc(var(--margin) * 8);
|
||||
// Center mime icon
|
||||
margin: auto;
|
||||
background-color: transparent !important;
|
||||
|
||||
object-fit: initial;
|
||||
}
|
||||
|
||||
&__title {
|
||||
overflow: hidden;
|
||||
// also count preview border
|
||||
max-width: calc(var(--width) + 2*2px);
|
||||
padding: var(--margin);
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -30,11 +30,11 @@ import { showError } from '@nextcloud/dialogs'
|
|||
* @param {string} token The conversation's token
|
||||
* e.g. `/myfile.txt`
|
||||
* @param {string} referenceId An optional reference id to recognize the message later
|
||||
* @param {Array} metadata the metadata json encoded array
|
||||
* @param {string} metadata the metadata json encoded array
|
||||
*/
|
||||
const shareFile = async function(path, token, referenceId, metadata) {
|
||||
try {
|
||||
return axios.post(
|
||||
return await axios.post(
|
||||
generateOcsUrl('apps/files_sharing/api/v1/shares'),
|
||||
{
|
||||
shareType: 10, // OC.Share.SHARE_TYPE_ROOM,
|
||||
|
@ -55,6 +55,28 @@ const shareFile = async function(path, token, referenceId, metadata) {
|
|||
}
|
||||
}
|
||||
|
||||
const getFileTemplates = async () => {
|
||||
return await axios.get(generateOcsUrl('apps/files/api/v1/templates'))
|
||||
}
|
||||
|
||||
/**
|
||||
* Share a text file to a conversation
|
||||
*
|
||||
* @param {string} filePath The new file destination path
|
||||
* @param {string} templatePath The template source path
|
||||
* @param {string} templateType The template type e.g 'user'
|
||||
* @return { object } the file object
|
||||
*/
|
||||
const createTextFile = async function(filePath, templatePath, templateType) {
|
||||
return await axios.post(generateOcsUrl('apps/files/api/v1/templates/create'), {
|
||||
filePath,
|
||||
templatePath,
|
||||
templateType,
|
||||
})
|
||||
}
|
||||
|
||||
export {
|
||||
shareFile,
|
||||
getFileTemplates,
|
||||
createTextFile,
|
||||
}
|
||||
|
|
|
@ -27,7 +27,10 @@ import fromStateOr from './helper.js'
|
|||
import { findUniquePath, getFileExtension } from '../utils/fileUpload.js'
|
||||
import moment from '@nextcloud/moment'
|
||||
import { EventBus } from '../services/EventBus.js'
|
||||
import { shareFile } from '../services/filesSharingServices.js'
|
||||
import {
|
||||
getFileTemplates,
|
||||
shareFile,
|
||||
} from '../services/filesSharingServices.js'
|
||||
import { setAttachmentFolder } from '../services/settingsService.js'
|
||||
|
||||
const state = {
|
||||
|
@ -36,6 +39,9 @@ const state = {
|
|||
uploads: {
|
||||
},
|
||||
currentUploadId: undefined,
|
||||
|
||||
fileTemplatesInitialised: false,
|
||||
fileTemplates: [],
|
||||
}
|
||||
|
||||
const getters = {
|
||||
|
@ -93,6 +99,14 @@ const getters = {
|
|||
currentUploadId: (state) => {
|
||||
return state.currentUploadId
|
||||
},
|
||||
|
||||
areFileTemplatesInitialised: (state) => {
|
||||
return state.fileTemplatesInitialised
|
||||
},
|
||||
|
||||
getFileTemplates: (state) => () => {
|
||||
return state.fileTemplates
|
||||
},
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
|
@ -182,6 +196,11 @@ const mutations = {
|
|||
discardUpload(state, { uploadId }) {
|
||||
Vue.delete(state.uploads, uploadId)
|
||||
},
|
||||
|
||||
storeFilesTemplates(state, { template }) {
|
||||
state.fileTemplates.push(template)
|
||||
state.fileTemplatesInitialised = true
|
||||
},
|
||||
}
|
||||
|
||||
const actions = {
|
||||
|
@ -406,6 +425,17 @@ const actions = {
|
|||
commit('removeFileFromSelection', temporaryMessageId)
|
||||
},
|
||||
|
||||
async getFileTemplates({ commit }) {
|
||||
try {
|
||||
const response = await getFileTemplates()
|
||||
|
||||
response.data.ocs.data.forEach(template => {
|
||||
commit('storeFilesTemplates', { template })
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('An error happened when trying to load the templates', error)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
export default { state, mutations, getters, actions }
|
||||
|
|
Загрузка…
Ссылка в новой задаче