diff --git a/.eslintrc.js b/.eslintrc.js index 4e9065badf..6ec5569256 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -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', } } diff --git a/cypress/e2e/integration.spec.js b/cypress/e2e/integration.spec.js index 2a17f945fd..f477aec94d 100644 --- a/cypress/e2e/integration.spec.js +++ b/cypress/e2e/integration.spec.js @@ -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() diff --git a/src/admin.js b/src/admin.js index 77251424d3..66a141c65a 100644 --- a/src/admin.js +++ b/src/admin.js @@ -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() }) diff --git a/src/components/Modal/Confirmation.vue b/src/components/Modal/Confirmation.vue new file mode 100644 index 0000000000..691c220d6d --- /dev/null +++ b/src/components/Modal/Confirmation.vue @@ -0,0 +1,77 @@ + + + diff --git a/src/components/Modal/SaveAs.vue b/src/components/Modal/SaveAs.vue new file mode 100644 index 0000000000..9366b7d7e0 --- /dev/null +++ b/src/components/Modal/SaveAs.vue @@ -0,0 +1,149 @@ + + + + + + diff --git a/src/document.js b/src/document.js index fdd8901b62..d45c2323bc 100644 --- a/src/document.js +++ b/src/document.js @@ -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 diff --git a/src/files.js b/src/files.js index 6e0821f713..3eb5b6b710 100644 --- a/src/files.js +++ b/src/files.js @@ -1,3 +1,5 @@ +import './init-shared.js' + import '../css/filetypes.scss' import '../css/files.scss' diff --git a/src/init-shared.js b/src/init-shared.js new file mode 100644 index 0000000000..1ca3518480 --- /dev/null +++ b/src/init-shared.js @@ -0,0 +1,4 @@ +// eslint-disable-next-line +__webpack_nonce__ = btoa(OC.requestToken) +// eslint-disable-next-line +__webpack_public_path__ = OC.linkTo('richdocuments', 'js/') \ No newline at end of file diff --git a/src/mixins/openLocal.js b/src/mixins/openLocal.js index c2388ef56b..5335bf0789 100644 --- a/src/mixins/openLocal.js +++ b/src/mixins/openLocal.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() { diff --git a/src/mixins/saveAs.js b/src/mixins/saveAs.js index 4c7de34a3e..c4874a1823 100644 --- a/src/mixins/saveAs.js +++ b/src/mixins/saveAs.js @@ -19,33 +19,21 @@ * along with this program. If not, see . */ -// 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 }), + ) }, }, } diff --git a/src/personal.js b/src/personal.js index 26d390a0f5..d3f7fb0882 100644 --- a/src/personal.js +++ b/src/personal.js @@ -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() -}) +})() diff --git a/src/reference.js b/src/reference.js index 487b8ed2fe..e4bf96bb92 100644 --- a/src/reference.js +++ b/src/reference.js @@ -19,6 +19,8 @@ * along with this program. If not, see . */ +import './init-shared.js' + import Vue from 'vue' import { translate as t } from '@nextcloud/l10n' diff --git a/src/view/DocumentTargetPicker.vue b/src/view/DocumentTargetPicker.vue index d16c0ca69e..015fcf0090 100644 --- a/src/view/DocumentTargetPicker.vue +++ b/src/view/DocumentTargetPicker.vue @@ -25,9 +25,9 @@

{{ t('richdocuments', 'Link to office document section') }}

- +
- + @@ -38,7 +38,7 @@