Signed-off-by: Julius Härtl <jus@bitgrid.net>
This commit is contained in:
Julius Härtl 2023-12-27 13:56:11 +01:00
Родитель 5945876f8c
Коммит c6306bb4a3
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4C614C6ED2CDE6DF
18 изменённых файлов: 323 добавлений и 421 удалений

Просмотреть файл

@ -21,5 +21,8 @@ module.exports = {
'jsdoc/check-values': 'off',
'jsdoc/valid-types': 'off',
'jsdoc/no-undefined-types': 'off',
'jsdoc/require-param-description': 'off',
'jsdoc/require-param-type': 'off',
'jsdoc/require-property-description': 'off',
}
}

Просмотреть файл

@ -83,12 +83,12 @@ describe('Nextcloud integration', function() {
cy.get('#w2ui-overlay-download-as-menu .menu-text').eq(1).click()
})
cy.get('.oc-dialog').should('be.visible')
cy.get('.oc-dialog input[type=text]')
cy.get('.saveas-dialog').should('be.visible')
cy.get('.saveas-dialog input[type=text]')
.should('be.visible')
.should('have.value', 'document.rtf')
.should('have.value', '/document.rtf')
cy.get('.oc-dialog button.primary').click()
cy.get('.saveas-dialog button.button-vue--vue-primary').click()
cy.get('@loleafletframe').within(() => {
cy.get('#closebutton').click()

Просмотреть файл

@ -1,4 +1,6 @@
import './init-shared.js'
import Vue from 'vue'
import axios from '@nextcloud/axios'
import { generateUrl } from '@nextcloud/router'
import AdminSettings from './components/AdminSettings.vue'
import '../css/admin.scss'
@ -59,11 +61,8 @@ function deleteTemplate(event) {
elmt.classList.remove('icon-delete')
// send request
$.ajax({
url: remote,
type: 'DELETE',
})
.done(function() {
axios.delete(remote)
.then(function() {
// remove template
elmt.parentElement.remove()
// is list empty? Only the default template is left
@ -72,7 +71,7 @@ function deleteTemplate(event) {
emptyElmt.classList.remove('hidden')
}
})
.fail(function(e) {
.catch(function(e) {
// failure, show warning
elmt.textContent = t('richdocuments', 'Error')
elmt.classList.remove('icon-loading')
@ -139,6 +138,6 @@ function initTemplateManager() {
})
}
$(document).ready(function() {
document.addEventListener('DOMContentLoaded', () => {
initTemplateManager()
})

Просмотреть файл

@ -0,0 +1,77 @@
<template>
<NcModal>
<div class="confirmation-dialog">
<h1>{{ name }}</h1>
<p>{{ description }}</p>
<div class="confirmation-dialog--buttons">
<NcButton type="secondary"
@click="() => close(false)">
{{ cancelButtonText }}
</NcButton>
<NcButton type="primary"
@click="() => close(true)">
{{ confirmButtonText }}
</NcButton>
</div>
</div>
</NcModal>
</template>
<script>
import { NcButton, NcModal } from '@nextcloud/vue'
import { translate as t } from '@nextcloud/l10n'
export default {
name: 'Confirmation',
components: {
NcButton,
NcModal,
},
props: {
name: {
type: String,
default: '',
},
description: {
type: String,
default: '',
},
confirmButtonText: {
type: String,
default: t('richdocuments', 'Confirm'),
},
cancelButtonText: {
type: String,
default: t('richdocuments', 'Cancel'),
},
},
emits: ['close'],
methods: {
t,
close(result) {
this.$emit('close', result)
},
},
}
</script>
<style lang="scss" scoped>
.confirmation-dialog {
display: flex;
flex-direction: column;
align-items: flex-start;
margin: 24px;
h1 {
font-size: 120%;
font-weight: bold;
margin-bottom: 12px;
}
&--buttons {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
width: 100%;
margin-top: 24px;
}
}
</style>

Просмотреть файл

@ -0,0 +1,149 @@
<!--
- @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>
<NcModal>
<div class="saveas-dialog">
<h1>{{ name }}</h1>
<p>{{ description }}</p>
<NcTextField ref="nameInput"
v-model="newFileName"
:label-visible="true"
:label="t('richdocuments', 'Path to save')"
:placeholder="'/path/to/save'" />
<div class="saveas-dialog--buttons">
<NcButton type="secondary"
@click="cancel">
{{ t('richdocuments', 'Cancel') }}
</NcButton>
<NcButton type="primary"
@click="close">
{{ t('richdocuments', 'Save') }}
</NcButton>
</div>
</div>
</NcModal>
</template>
<script>
import { translate as t } from '@nextcloud/l10n'
import { NcModal, NcButton, NcTextField } from '@nextcloud/vue'
export default {
name: 'SaveAs',
components: {
NcModal,
NcButton,
NcTextField,
},
props: {
name: {
type: String,
default: t('richdocuments', 'Save As'),
},
description: {
type: String,
default: '',
},
buttonText: {
type: String,
default: t('richdocuments', 'Save'),
},
path: {
type: String,
default: '',
},
format: {
type: String,
default: '',
},
},
emits: ['close'],
data() {
return {
selectedPath: '',
}
},
computed: {
newFileName: {
get() {
if (this.selectedPath !== '') {
return this.selectedPath
}
const filename = this.path
const extension = filename.split('.').pop()
const filenameWithoutExtension = filename.substring(0, filename.length - extension.length - 1)
return filenameWithoutExtension + '.' + (this.format !== '' ? this.format : extension)
},
set(event) {
this.selectedPath = event.target.value
},
},
},
mounted() {
// prepare filename for having a separate picker for the path (.split('/').pop())
const filename = this.path
const extension = filename.split('.').pop()
const filenameWithoutExtension = filename.substring(0, filename.length - extension.length - 1)
this.$nextTick(() => {
const input = this.$refs.nameInput.$refs.inputField.$el.querySelector('input')
input.setSelectionRange(0, filenameWithoutExtension.length)
input.focus()
})
},
methods: {
t,
close() {
this.$emit('close', this.newFileName)
},
cancel() {
this.$emit('close', null)
},
},
}
</script>
<style lang="scss" scoped>
.saveas-dialog {
display: flex;
flex-direction: column;
align-items: flex-start;
margin: 24px;
h1 {
font-size: 120%;
font-weight: bold;
margin-bottom: 12px;
}
p {
margin-bottom: 12px;
}
&--buttons {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
width: 100%;
margin-top: 24px;
}
}
</style>

Просмотреть файл

@ -66,6 +66,7 @@ export default {
},
data() {
return {
uuid: '',
inputValObjects: [],
groups: {},
}

Просмотреть файл

@ -1,208 +0,0 @@
<!--
- @copyright Copyright (c) 2019 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>
<NcMultiselect v-model="inputValObjects"
:options="tags"
:options-limit="5"
:placeholder="label"
track-by="id"
:custom-label="tagLabel"
class="multiselect-vue"
:multiple="true"
:close-on-select="false"
:tag-width="60"
:disabled="disabled"
@input="update"
@search-change="asyncFind">
<span slot="noResult">{{ t('settings', 'No results') }}</span>
<template #option="scope">
{{ tagLabel(scope.option) }}
</template>
</NcMultiselect>
</template>
<script>
import axios from '@nextcloud/axios'
import { generateRemoteUrl } from '@nextcloud/router'
import { NcMultiselect } from '@nextcloud/vue'
const xmlToJson = (xml) => {
let obj = {}
if (xml.nodeType === 1) {
if (xml.attributes.length > 0) {
obj['@attributes'] = {}
for (let j = 0; j < xml.attributes.length; j++) {
const attribute = xml.attributes.item(j)
obj['@attributes'][attribute.nodeName] = attribute.nodeValue
}
}
} else if (xml.nodeType === 3) {
obj = xml.nodeValue
}
if (xml.hasChildNodes()) {
for (let i = 0; i < xml.childNodes.length; i++) {
const item = xml.childNodes.item(i)
const nodeName = item.nodeName
if (typeof (obj[nodeName]) === 'undefined') {
obj[nodeName] = xmlToJson(item)
} else {
if (typeof obj[nodeName].push === 'undefined') {
const old = obj[nodeName]
obj[nodeName] = []
obj[nodeName].push(old)
}
obj[nodeName].push(xmlToJson(item))
}
}
}
return obj
}
const parseXml = (xml) => {
let dom = null
try {
dom = (new DOMParser()).parseFromString(xml, 'text/xml')
} catch (e) {
console.error('Failed to parse xml document', e)
}
return dom
}
const xmlToTagList = (xml) => {
const json = xmlToJson(parseXml(xml))
const list = json['d:multistatus']['d:response']
const result = []
for (const index in list) {
const tag = list[index]['d:propstat']
if (!tag) {
continue
}
if ((tag['d:status']['#text'] ?? null) !== 'HTTP/1.1 200 OK') {
continue
}
result.push({
id: tag['d:prop']['oc:id']['#text'],
displayName: tag['d:prop']['oc:display-name']['#text'],
canAssign: tag['d:prop']['oc:can-assign']['#text'] === 'true',
userAssignable: tag['d:prop']['oc:user-assignable']['#text'] === 'true',
userVisible: tag['d:prop']['oc:user-visible']['#text'] === 'true',
})
}
return result
}
const searchTags = function() {
return axios({
method: 'PROPFIND',
url: generateRemoteUrl('dav') + '/systemtags/',
data: `<?xml version="1.0"?>
<d:propfind xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns">
<d:prop>
<oc:id />
<oc:display-name />
<oc:user-visible />
<oc:user-assignable />
<oc:can-assign />
</d:prop>
</d:propfind>`,
}).then((response) => {
return xmlToTagList(response.data)
})
}
let uuid = 0
export default {
name: 'SettingsSelectTag',
components: {
NcMultiselect,
},
props: {
label: {
type: String,
required: true,
},
hint: {
type: String,
default: '',
},
value: {
type: Array,
default: () => [],
},
disabled: {
type: Boolean,
default: false,
},
},
data() {
return {
inputValObjects: [],
tags: [],
}
},
computed: {
id() {
return 'settings-input-text-' + this.uuid
},
},
watch: {
value(newVal) {
this.inputValObjects = this.getValueObject()
},
},
beforeCreate() {
this.uuid = uuid.toString()
uuid += 1
searchTags().then((result) => {
this.tags = result
this.inputValObjects = this.getValueObject()
})
},
methods: {
asyncFind(query) {
},
getValueObject() {
return this.value.filter((tag) => tag !== '').map(
(id) => this.tags.find((tag) => tag.id === id),
)
},
update() {
this.$emit('input', this.inputValObjects.map((element) => element.id))
},
tagLabel({ displayName, userVisible, userAssignable }) {
if (userVisible === false) {
return `${displayName} (invisible)`
}
if (userAssignable === false) {
return `${displayName} (restricted)`
}
return displayName
},
},
}
</script>

Просмотреть файл

@ -1,5 +1,5 @@
import './init-shared.js'
import { emit } from '@nextcloud/event-bus'
import { encodePath } from '@nextcloud/paths'
import { generateOcsUrl, getRootUrl, imagePath } from '@nextcloud/router'
import { getRequestToken } from '@nextcloud/auth'
import { loadState } from '@nextcloud/initial-state'
@ -18,6 +18,8 @@ import { getWopiUrl, getSearchParam, getNextcloudUrl } from './helpers/url.js'
import '../css/document.scss'
import axios from '@nextcloud/axios'
import { spawnDialog } from '@nextcloud/dialogs'
import SaveAs from './components/Modal/SaveAs.vue'
const PostMessages = new PostMessageService({
parent: window.parent,
@ -472,13 +474,6 @@ const documentsMain = {
case 'File_Rename':
documentsMain.fileName = args.NewName
break
case 'Clicked_Button':
if (parsed.args.Id === 'Open_Local_Editor') {
documentsMain.UI.initiateOpenLocally()
} else {
console.debug('[document] Unhandled `Clicked_Button` post message', parsed)
}
break
case 'Views_List':
documentsMain.users = []
parsed.args.forEach((view) => {
@ -505,30 +500,14 @@ const documentsMain = {
}
if (msgId === 'UI_SaveAs') {
// TODO Move to file picker dialog with input field
OC.dialogs.prompt(
t('richdocuments', 'Please enter the filename to store the document as.'),
t('richdocuments', 'Save As'),
function(result, value) {
if (result === true && value) {
PostMessages.sendWOPIPostMessage('loolframe', 'Action_SaveAs', { Filename: value, Notify: true })
}
spawnDialog(
SaveAs,
{
path: documentsMain.filename,
format: args.Format,
},
true,
t('richdocuments', 'New filename'),
false,
).then(function() {
const $dialog = $('.oc-dialog:visible')
const $buttons = $dialog.find('.oc-dialog-buttonrow button')
$buttons.eq(0).text(t('richdocuments', 'Cancel'))
$buttons.eq(1).text(t('richdocuments', 'Save'))
const nameInput = $dialog.find('input')[0]
nameInput.style.minWidth = '250px'
nameInput.style.maxWidth = '400px'
nameInput.value = args.format ? documentsMain.fileName.substring(0, documentsMain.fileName.lastIndexOf('.') + 1) + args.format : documentsMain.fileName
nameInput.selectionStart = 0
nameInput.selectionEnd = documentsMain.fileName.lastIndexOf('.')
})
(value) => value && this.sendPostMessage('Action_SaveAs', { Filename: value, Notify: true }),
)
} else if (msgId === 'Action_Save_Resp') {
if (args.success && args.fileName) {
documentsMain.fileName = args.fileName
@ -559,26 +538,6 @@ const documentsMain = {
})
},
initiateOpenLocally() {
OC.dialogs.confirmDestructive(
t('richdocuments', 'When opening a file locally, the document will close for all users currently viewing the document.'),
t('richdocuments', 'Open file locally'),
{
type: OC.dialogs.YES_NO_BUTTONS,
confirm: t('richdocuments', 'Open locally'),
confirmClasses: 'error',
cancel: t('richdocuments', 'Continue editing online'),
},
(decision) => {
if (!decision) {
return
}
documentsMain.openingLocally = true
PostMessages.sendWOPIPostMessage('loolframe', 'Get_Views')
},
)
},
removeViews(views) {
PostMessages.sendWOPIPostMessage('loolframe', 'Action_Save', {
DontTerminateEdit: false,
@ -600,43 +559,6 @@ const documentsMain = {
return axios.post(unlockUrl, { access_token: documentsMain.token }, unlockConfig)
},
openLocally() {
if (documentsMain.openingLocally) {
documentsMain.openingLocally = false
axios.post(
OC.linkToOCS('apps/files/api/v1', 2) + 'openlocaleditor?format=json',
{ path: documentsMain.fullPath },
).then((result) => {
const url = 'nc://open/'
+ Config.get('userId') + '@' + getNextcloudUrl()
+ encodePath(documentsMain.fullPath)
+ '?token=' + result.data.ocs.data.token
this.showOpenLocalConfirmation(url, window.top)
window.location.href = url
})
}
},
showOpenLocalConfirmation(url, _window) {
_window.OC.dialogs.confirmDestructive(
t('richdocuments', 'If the file does not open in your local editor, make sure the Nextcloud desktop app is installed and open and try again.'),
t('richdocuments', 'Opening file locally …'),
{
type: OC.dialogs.YES_NO_BUTTONS,
confirm: t('richdocuments', 'Try again'),
cancel: t('richdocuments', 'Close'),
},
(decision) => {
if (decision) {
_window.location = url
this.showOpenLocalConfirmation(url, _window)
}
},
)
},
async sendUserList(search) {
let users = documentsMain.users

Просмотреть файл

@ -1,3 +1,5 @@
import './init-shared.js'
import '../css/filetypes.scss'
import '../css/files.scss'

4
src/init-shared.js Normal file
Просмотреть файл

@ -0,0 +1,4 @@
// eslint-disable-next-line
__webpack_nonce__ = btoa(OC.requestToken)
// eslint-disable-next-line
__webpack_public_path__ = OC.linkTo('richdocuments', 'js/')

Просмотреть файл

@ -21,11 +21,12 @@
import { getCurrentUser } from '@nextcloud/auth'
import axios from '@nextcloud/axios'
import { spawnDialog } from '@nextcloud/dialogs'
import { encodePath } from '@nextcloud/paths'
import { getRootUrl, generateOcsUrl } from '@nextcloud/router'
import { getNextcloudUrl } from '../helpers/url.js'
import Confirmation from '../components/Modal/Confirmation.vue'
// FIXME: Migrate to vue component
export default {
data() {
return {
@ -52,14 +53,13 @@ export default {
},
showOpenLocalConfirmation() {
window.OC.dialogs.confirmDestructive(
t('richdocuments', 'When opening a file locally, the document will close for all users currently viewing the document.'),
t('richdocuments', 'Open file locally'),
spawnDialog(
Confirmation,
{
type: OC.dialogs.YES_NO_BUTTONS,
confirm: t('richdocuments', 'Open locally'),
confirmClasses: 'error',
cancel: t('richdocuments', 'Continue editing online'),
name: t('richdocuments', 'Open file locally'),
description: t('richdocuments', 'When opening a file locally, the document will close for all users currently viewing the document.'),
confirmButtonText: t('richdocuments', 'Open locally'),
cancelButtonText: t('richdocuments', 'Continue editing online'),
},
(decision) => {
if (!decision) {
@ -67,19 +67,19 @@ export default {
}
this.openingLocally = true
this.sendPostMessage('Get_Views')
})
},
)
},
showOpenLocalFinished() {
const fileName = this.filename
window.OC.dialogs.confirmDestructive(
t('richdocuments', 'The file should now open locally. If you don\'t see this happening, make sure that the desktop client is installed on your system.'),
t('richdocuments', 'Open file locally'),
spawnDialog(
Confirmation,
{
type: OC.dialogs.YES_NO_BUTTONS,
confirm: t('richdocuments', 'Retry to open locally'),
confirmClasses: 'primary',
cancel: t('richdocuments', 'Continue editing online'),
name: t('richdocuments', 'Open file locally'),
description: t('richdocuments', 'The file should now open locally. If you don\'t see this happening, make sure that the desktop client is installed on your system.'),
confirmButtonText: t('richdocuments', 'Retry to open locally'),
cancelButtonText: t('richdocuments', 'Continue editing online'),
},
(decision) => {
if (!decision) {
@ -88,7 +88,8 @@ export default {
}
this.openingLocally = true
this.sendPostMessage('Get_Views')
})
},
)
},
unlockFile() {

Просмотреть файл

@ -19,33 +19,21 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// FIXME: Migrate to vue component
import { spawnDialog } from '@nextcloud/dialogs'
import SaveAs from '../components/Modal/SaveAs.vue'
export default {
methods: {
async saveAs(format) {
window.OC.dialogs.prompt(
t('richdocuments', 'Please enter the filename to store the document as.'),
t('richdocuments', 'Save As'),
(result, value) => {
if (result === true && value) {
this.sendPostMessage('Action_SaveAs', { Filename: value, Notify: true })
}
spawnDialog(
SaveAs,
{
path: this.filename,
format,
description: t('richdocuments', 'Save a copy of the file as a new name and continue editing the new file'),
},
true,
t('richdocuments', 'New filename'),
false,
).then(() => {
const $dialog = $('.oc-dialog:visible')
const $buttons = $dialog.find('.oc-dialog-buttonrow button')
$buttons.eq(0).text(t('richdocuments', 'Cancel'))
$buttons.eq(1).text(t('richdocuments', 'Save'))
const nameInput = $dialog.find('input')[0]
nameInput.style.minWidth = '250px'
nameInput.style.maxWidth = '400px'
nameInput.value = format ? this.basename.substring(0, this.basename.lastIndexOf('.') + 1) + format : this.basename
nameInput.selectionStart = 0
nameInput.selectionEnd = this.basename.lastIndexOf('.')
})
(value) => value && this.sendPostMessage('Action_SaveAs', { Filename: value, Notify: true }),
)
},
},
}

Просмотреть файл

@ -1,11 +1,9 @@
import './init-shared.js'
import '../css/admin.scss'
import { generateFilePath } from '@nextcloud/router'
import { showError } from '@nextcloud/dialogs'
$(function() {
$('[data-toggle="tooltip"]').tooltip()
(function() {
const PersonalSettings = function() {
this.templateInput = document.getElementById('templateInputField')
this.templateSelectButton = document.getElementById('templateSelectButton')
@ -91,4 +89,4 @@ $(function() {
}
return new PersonalSettings()
})
})()

Просмотреть файл

@ -19,6 +19,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import './init-shared.js'
import Vue from 'vue'
import { translate as t } from '@nextcloud/l10n'

Просмотреть файл

@ -25,9 +25,9 @@
</div>
<div v-else class="office-target-picker">
<h2>{{ t('richdocuments', 'Link to office document section') }}</h2>
<NcLoadingIcon v-if="!sections || !fileId" :size="44" />
<NcLoadingIcon v-if="sections === null || !fileId" :size="44" />
<div v-else>
<NcEmptyContent v-if="sections.length === 0" :title="t('richdocuments', 'Could not find any section in the document')">
<NcEmptyContent v-if="sections.length === 0" :name="t('richdocuments', 'Could not find any section in the document')">
<template #icon>
<TableOfContentsIcon />
</template>
@ -38,7 +38,7 @@
<ul>
<NcListItem v-for="entry in section.entries"
:key="entry.id"
:title="entry.name"
:name="entry.name"
:class="{ 'list-item__wrapper--active': entry.id === target }"
@click="setTarget(entry)">
<template v-if="entry.preview" #icon>
@ -58,7 +58,7 @@
</template>
<script>
import { FilePickerType } from '@nextcloud/dialogs'
import { getFilePickerBuilder } from '@nextcloud/dialogs'
import { generateUrl, generateOcsUrl } from '@nextcloud/router'
import axios from '@nextcloud/axios'
import { NcButton, NcEmptyContent, NcListItem, NcLoadingIcon } from '@nextcloud/vue'
@ -106,25 +106,20 @@ export default {
},
async openFilePicker() {
const self = this
OC.dialogs.filepicker(
t('files', 'Select file or folder to link to'),
function(file) {
const client = OC.Files.getClient()
client.getFileInfo(file).then((_status, fileInfo) => {
self.fileId = fileInfo.id
})
self.filePath = file
self.fetchReferences()
},
false, // multiselect
OC.getCapabilities().richdocuments.mimetypes, // mime filter
false, // modal
FilePickerType.Choose, // type
'',
{
target: this.$refs.picker,
},
)
await getFilePickerBuilder(t('files', 'Select file or folder to link to'))
.setMimeTypeFilter(OC.getCapabilities().richdocuments.mimetypes)
.addButton({
label: t('richdocuments', 'Insert image'),
callback: (files) => {
const file = files[0]
this.fileId = file.fileid
self.filePath = file.path
self.fetchReferences()
},
})
.setContainer(this.$refs.picker)
.build()
.pick()
},
setTarget(entry) {
this.target = entry.id

Просмотреть файл

@ -22,7 +22,7 @@
import { generateUrl } from '@nextcloud/router'
import { getCurrentUser } from '@nextcloud/auth'
import { getFilePickerBuilder } from '@nextcloud/dialogs'
import { getFilePickerBuilder, spawnDialog } from '@nextcloud/dialogs'
import axios from '@nextcloud/axios'
import { emit } from '@nextcloud/event-bus'
import { getCurrentDirectory } from '../helpers/filesApp.js'
@ -32,6 +32,7 @@ import {
davResultToNode,
davRootPath,
} from '@nextcloud/files'
import SaveAs from '../components/Modal/SaveAs.vue'
const isPublic = document.getElementById('isPublic') && document.getElementById('isPublic').value === '1'
@ -256,31 +257,6 @@ export default {
this.renderAvatars()
},
_addAvatarList() {
// Add the avatar toolbar if possible
const avatarList = $('<div id="richdocuments-avatars">')
avatarList.on('click', function(e) {
e.stopPropagation()
$('#editors-menu').toggle()
})
$('#richdocuments-header').append(avatarList)
},
_addHeaderShareButton() {
if ($('header').length) {
const isInverted = Boolean(window?.OCA?.Theming?.inverted)
const $button = $('<div id="richdocuments-sharing"><a class="icon-collabora icon-shared ' + (isInverted ? 'icon-black' : 'icon-white') + '"></a></div>')
$('#richdocuments-header').append($button)
$button.on('click', () => {
if (!$('#app-sidebar').is(':visible')) {
return this.share()
}
OC.Apps.hideAppSidebar()
})
$('.searchbox').hide()
}
},
_addHeaderFileActions() {
console.debug('[FilesAppIntegration] Adding header file actions')
OC.unregisterMenu($('#richdocuments-actions .icon-more'), $('#richdocuments-actions-menu'))
@ -468,11 +444,15 @@ export default {
return
}
OC.dialogs.prompt(
t('richdocuments', 'Please enter the filename for the new document'),
t('richdocuments', 'Save As'),
function(result, value) {
if (result === true && value) {
spawnDialog(
SaveAs,
{
name: t('richdocuments', 'New file'),
description: t('richdocuments', 'Please enter the filename for the new file'),
buttonText: t('richdocuments', 'Create'),
},
(value) => {
if (value) {
if (type === 'text') {
type = 'document'
}
@ -480,15 +460,7 @@ export default {
window.open(url, '_blank')
}
},
true,
t('richdocuments', 'New filename'),
false,
).then(function() {
const $dialog = parent.$('.oc-dialog:visible')
const $buttons = $dialog.find('button')
$buttons.eq(0).text(t('richdocuments', 'Cancel'))
$buttons.eq(1).text(t('richdocuments', 'Create a new document'))
})
)
},
loggingContext() {

Просмотреть файл

@ -25,6 +25,7 @@ import { getCurrentDirectory } from '../helpers/filesApp.js'
import Types from '../helpers/types.js'
import { createEmptyFile } from '../services/api.js'
import { generateUrl, generateFilePath, generateOcsUrl } from '@nextcloud/router'
import { showError } from '@nextcloud/dialogs'
/** @type OC.Plugin */
const NewFileMenu = {
@ -113,7 +114,7 @@ const NewFileMenu = {
fileActions: FileList.fileActions,
})
} else {
OC.dialogs.alert(response.data.message, t('core', 'Could not create file'))
showError(t('core', 'Could not create file') + ': ' + response.data.message)
}
})
},

Просмотреть файл

@ -21,16 +21,12 @@
*
*/
import './init-shared.js'
import '../css/filetypes.scss'
import Office from './view/Office.vue'
import { getCapabilities } from '@nextcloud/capabilities'
// eslint-disable-next-line
__webpack_nonce__ = btoa(OC.requestToken)
// eslint-disable-next-line
__webpack_public_path__ = OC.linkTo('richdocuments', 'js/')
const supportedMimes = getCapabilities().richdocuments.mimetypes
if (OCA.Viewer) {