diff options
Diffstat (limited to 'core/src/OC/dialogs.js')
-rw-r--r-- | core/src/OC/dialogs.js | 393 |
1 files changed, 158 insertions, 235 deletions
diff --git a/core/src/OC/dialogs.js b/core/src/OC/dialogs.js index 6ce960ee41c..5c6934e67a2 100644 --- a/core/src/OC/dialogs.js +++ b/core/src/OC/dialogs.js @@ -1,46 +1,7 @@ /** - * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at> - * @copyright Copyright (c) 2019 Gary Kim <gary@garykim.dev> - * - * @author Bartek Przybylski <bart.p.pl@gmail.com> - * @author Christopher Schäpers <kondou@ts.unde.re> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Daniel Calviño Sánchez <danxuliu@gmail.com> - * @author Daniel Kesselberg <mail@danielkesselberg.de> - * @author Florian Schunk <florian.schunk@rwth-aachen.de> - * @author Gary Kim <gary@garykim.dev> - * @author Hendrik Leppelsack <hendrik@leppelsack.de> - * @author Jan-Christoph Borchardt <hey@jancborchardt.net> - * @author Joas Schilling <coding@schilljs.com> - * @author John Molakvoæ <skjnldsv@protonmail.com> - * @author Jörn Friedrich Dreyer <jfd@butonic.de> - * @author Julius Härtl <jus@bitgrid.net> - * @author Loïc Hermann <loic.hermann@sciam.fr> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Olivier Paroz <github@oparoz.com> - * @author Robin Appelman <robin@icewind.nl> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Sujith Haridasan <Sujith_Haridasan@mentor.com> - * @author Thomas Citharel <nextcloud@tcit.fr> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * @author Thomas Tanghus <thomas@tanghus.net> - * @author Vincent Petry <vincent@nextcloud.com> - * - * @license AGPL-3.0-or-later - * - * 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/>. - * + * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2015 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-or-later */ /* eslint-disable */ @@ -48,18 +9,22 @@ import _ from 'underscore' import $ from 'jquery' import IconMove from '@mdi/svg/svg/folder-move.svg?raw' -import IconCopy from '@mdi/svg/svg/folder-multiple.svg?raw' +import IconCopy from '@mdi/svg/svg/folder-multiple-outline.svg?raw' import OC from './index.js' -import { FilePickerType, getFilePickerBuilder } from '@nextcloud/dialogs' +import { DialogBuilder, FilePickerType, getFilePickerBuilder, spawnDialog } from '@nextcloud/dialogs' +import { translate as t } from '@nextcloud/l10n' import { basename } from 'path' +import { defineAsyncComponent } from 'vue' /** * this class to ease the usage of jquery dialogs */ const Dialogs = { // dialog button types + /** @deprecated use `@nextcloud/dialogs` */ YES_NO_BUTTONS: 70, + /** @deprecated use `@nextcloud/dialogs` */ OK_BUTTONS: 71, /** @deprecated use FilePickerType from `@nextcloud/dialogs` */ @@ -73,15 +38,14 @@ const Dialogs = { /** @deprecated use FilePickerType from `@nextcloud/dialogs` */ FILEPICKER_TYPE_CUSTOM: 5, - // used to name each dialog - dialogsCounter: 0, - /** * displays alert dialog * @param {string} text content of dialog * @param {string} title dialog title * @param {function} callback which will be triggered when user presses OK * @param {boolean} [modal] make the dialog modal + * + * @deprecated 30.0.0 Use `@nextcloud/dialogs` instead or build your own with `@nextcloud/vue` NcDialog */ alert: function(text, title, callback, modal) { this.message( @@ -93,12 +57,15 @@ const Dialogs = { modal ) }, + /** * displays info dialog * @param {string} text content of dialog * @param {string} title dialog title * @param {function} callback which will be triggered when user presses OK * @param {boolean} [modal] make the dialog modal + * + * @deprecated 30.0.0 Use `@nextcloud/dialogs` instead or build your own with `@nextcloud/vue` NcDialog */ info: function(text, title, callback, modal) { this.message(text, title, 'info', Dialogs.OK_BUTTON, callback, modal) @@ -111,6 +78,8 @@ const Dialogs = { * @param {function} callback which will be triggered when user presses OK (true or false would be passed to callback respectively) * @param {boolean} [modal] make the dialog modal * @returns {Promise} + * + * @deprecated 30.0.0 Use `@nextcloud/dialogs` instead or build your own with `@nextcloud/vue` NcDialog */ confirm: function(text, title, callback, modal) { return this.message( @@ -130,16 +99,34 @@ const Dialogs = { * @param {function} callback which will be triggered when user presses OK (true or false would be passed to callback respectively) * @param {boolean} [modal] make the dialog modal * @returns {Promise} + * + * @deprecated 30.0.0 Use `@nextcloud/dialogs` instead or build your own with `@nextcloud/vue` NcDialog */ - confirmDestructive: function(text, title, buttons, callback, modal) { - return this.message( - text, - title, - 'none', - buttons, - callback, - modal === undefined ? true : modal - ) + confirmDestructive: function(text, title, buttons = Dialogs.OK_BUTTONS, callback = () => {}, modal) { + return (new DialogBuilder()) + .setName(title) + .setText(text) + .setButtons( + buttons === Dialogs.OK_BUTTONS + ? [ + { + label: t('core', 'Yes'), + type: 'error', + callback: () => { + callback.clicked = true + callback(true) + }, + } + ] + : Dialogs._getLegacyButtons(buttons, callback) + ) + .build() + .show() + .then(() => { + if (!callback.clicked) { + callback(false) + } + }) }, /** * displays confirmation dialog @@ -148,17 +135,35 @@ const Dialogs = { * @param {function} callback which will be triggered when user presses OK (true or false would be passed to callback respectively) * @param {boolean} [modal] make the dialog modal * @returns {Promise} + * + * @deprecated 30.0.0 Use `@nextcloud/dialogs` instead or build your own with `@nextcloud/vue` NcDialog */ confirmHtml: function(text, title, callback, modal) { - return this.message( - text, - title, - 'notice', - Dialogs.YES_NO_BUTTONS, - callback, - modal, - true - ) + return (new DialogBuilder()) + .setName(title) + .setText('') + .setButtons([ + { + label: t('core', 'No'), + callback: () => {}, + }, + { + label: t('core', 'Yes'), + type: 'primary', + callback: () => { + callback.clicked = true + callback(true) + }, + }, + ]) + .build() + .setHTML(text) + .show() + .then(() => { + if (!callback.clicked) { + callback(false) + } + }) }, /** * displays prompt dialog @@ -169,69 +174,25 @@ const Dialogs = { * @param {string} name name of the input field * @param {boolean} password whether the input should be a password input * @returns {Promise} + * + * @deprecated Use NcDialog from `@nextcloud/vue` instead */ prompt: function(text, title, callback, modal, name, password) { - return $.when(this._getMessageTemplate()).then(function($tmpl) { - var dialogName = 'oc-dialog-' + Dialogs.dialogsCounter + '-content' - var dialogId = '#' + dialogName - var $dlg = $tmpl.octemplate({ - dialog_name: dialogName, - title: title, - message: text, - type: 'notice' - }) - var input = $('<input/>') - input.attr('type', password ? 'password' : 'text').attr('id', dialogName + '-input').attr('placeholder', name) - var label = $('<label/>').attr('for', dialogName + '-input').text(name + ': ') - $dlg.append(label) - $dlg.append(input) - if (modal === undefined) { - modal = false - } - $('body').append($dlg) - - // wrap callback in _.once(): - // only call callback once and not twice (button handler and close - // event) but call it for the close event, if ESC or the x is hit - if (callback !== undefined) { - callback = _.once(callback) - } - - var buttonlist = [{ - text: t('core', 'No'), - click: function() { - if (callback !== undefined) { - // eslint-disable-next-line standard/no-callback-literal - callback(false, input.val()) - } - $(dialogId).ocdialog('close') - } - }, { - text: t('core', 'Yes'), - click: function() { - if (callback !== undefined) { - // eslint-disable-next-line standard/no-callback-literal - callback(true, input.val()) - } - $(dialogId).ocdialog('close') + return new Promise((resolve) => { + spawnDialog( + defineAsyncComponent(() => import('../components/LegacyDialogPrompt.vue')), + { + text, + name: title, + callback, + inputName: name, + isPassword: !!password }, - defaultButton: true - }] - - $(dialogId).ocdialog({ - closeOnEscape: true, - modal: modal, - buttons: buttonlist, - close: function() { - // callback is already fired if Yes/No is clicked directly - if (callback !== undefined) { - // eslint-disable-next-line standard/no-callback-literal - callback(false, input.val()) - } - } - }) - input.focus() - Dialogs.dialogsCounter++ + (...args) => { + callback(...args) + resolve() + }, + ) }) }, @@ -317,13 +278,13 @@ const Dialogs = { } else { builder.setButtonFactory((nodes, path) => { const buttons = [] - const node = nodes?.[0]?.attributes?.displayName || nodes?.[0]?.basename - const target = node || basename(path) + const [node] = nodes + const target = node?.displayname || node?.basename || basename(path) if (type === FilePickerType.Choose) { buttons.push({ callback: legacyCallback(callback, FilePickerType.Choose), - label: node && !this.multiSelect ? t('core', 'Choose {file}', { file: node }) : t('core', 'Choose'), + label: node && !this.multiSelect ? t('core', 'Choose {file}', { file: target }) : t('core', 'Choose'), type: 'primary', }) } @@ -363,105 +324,81 @@ const Dialogs = { /** * Displays raw dialog * You better use a wrapper instead ... + * + * @deprecated 30.0.0 Use `@nextcloud/dialogs` instead or build your own with `@nextcloud/vue` NcDialog */ - message: function(content, title, dialogType, buttons, callback, modal, allowHtml) { - return $.when(this._getMessageTemplate()).then(function($tmpl) { - var dialogName = 'oc-dialog-' + Dialogs.dialogsCounter + '-content' - var dialogId = '#' + dialogName - var $dlg = $tmpl.octemplate({ - dialog_name: dialogName, - title: title, - message: content, - type: dialogType - }, allowHtml ? { escapeFunction: '' } : {}) - if (modal === undefined) { - modal = false + message: function(content, title, dialogType, buttons, callback = () => {}, modal, allowHtml) { + const builder = (new DialogBuilder()) + .setName(title) + .setText(allowHtml ? '' : content) + .setButtons(Dialogs._getLegacyButtons(buttons, callback)) + + switch (dialogType) { + case 'alert': + builder.setSeverity('warning') + break + case 'notice': + builder.setSeverity('info') + break + default: + break + } + + const dialog = builder.build() + + if (allowHtml) { + dialog.setHTML(content) + } + + return dialog.show().then(() => { + if(!callback._clicked) { + callback(false) } - $('body').append($dlg) - var buttonlist = [] - switch (buttons) { + }) + }, + + /** + * Helper for legacy API + * @deprecated + */ + _getLegacyButtons(buttons, callback) { + const buttonList = [] + + switch (typeof buttons === 'object' ? buttons.type : buttons) { case Dialogs.YES_NO_BUTTONS: - buttonlist = [{ - text: t('core', 'No'), - click: function() { - if (callback !== undefined) { - callback(false) - } - $(dialogId).ocdialog('close') - } - }, - { - text: t('core', 'Yes'), - click: function() { - if (callback !== undefined) { - callback(true) - } - $(dialogId).ocdialog('close') + buttonList.push({ + label: buttons?.cancel ?? t('core', 'No'), + callback: () => { + callback._clicked = true + callback(false) }, - defaultButton: true - }] + }) + buttonList.push({ + label: buttons?.confirm ?? t('core', 'Yes'), + type: 'primary', + callback: () => { + callback._clicked = true + callback(true) + }, + }) break - case Dialogs.OK_BUTTON: - var functionToCall = function() { - $(dialogId).ocdialog('close') - if (callback !== undefined) { - callback() - } - } - buttonlist[0] = { - text: t('core', 'OK'), - click: functionToCall, - defaultButton: true - } + case Dialogs.OK_BUTTONS: + buttonList.push({ + label: buttons?.confirm ?? t('core', 'OK'), + type: 'primary', + callback: () => { + callback._clicked = true + callback(true) + }, + }) break default: - if (typeof(buttons) === 'object') { - switch (buttons.type) { - case Dialogs.YES_NO_BUTTONS: - buttonlist = [{ - text: buttons.cancel || t('core', 'No'), - click: function() { - if (callback !== undefined) { - callback(false) - } - $(dialogId).ocdialog('close') - } - }, - { - text: buttons.confirm || t('core', 'Yes'), - click: function() { - if (callback !== undefined) { - callback(true) - } - $(dialogId).ocdialog('close') - }, - defaultButton: true, - classes: buttons.confirmClasses - }] - break - } - } + console.error('Invalid call to OC.dialogs') break - } - - $(dialogId).ocdialog({ - closeOnEscape: true, - closeCallback: () => { callback && callback(false) }, - modal: modal, - buttons: buttonlist - }) - Dialogs.dialogsCounter++ - }) - .fail(function(status, error) { - // If the method is called while navigating away from - // the page, we still want to deliver the message. - if (status === 0) { - alert(title + ': ' + content) - } else { - alert(t('core', 'Error loading message template: {error}', { error: error })) - } - }) + } + return buttonList }, + _fileexistsshown: false, /** * Displays file exists dialog @@ -470,6 +407,8 @@ const Dialogs = { * @param {object} replacement file with name, size and mtime * @param {object} controller with onCancel, onSkip, onReplace and onRename methods * @returns {Promise} jquery promise that resolves after the dialog template was loaded + * + * @deprecated 29.0.0 Use openConflictPicker from the @nextcloud/upload package instead */ fileexists: function(data, original, replacement, controller) { var self = this @@ -829,27 +768,11 @@ const Dialogs = { return dialogDeferred.promise() }, - _getMessageTemplate: function() { - var defer = $.Deferred() - if (!this.$messageTemplate) { - var self = this - $.get(OC.filePath('core', 'templates', 'message.html'), function(tmpl) { - self.$messageTemplate = $(tmpl) - defer.resolve(self.$messageTemplate) - }) - .fail(function(jqXHR, textStatus, errorThrown) { - defer.reject(jqXHR.status, errorThrown) - }) - } else { - defer.resolve(this.$messageTemplate) - } - return defer.promise() - }, _getFileExistsTemplate: function() { var defer = $.Deferred() if (!this.$fileexistsTemplate) { var self = this - $.get(OC.filePath('files', 'templates', 'fileexists.html'), function(tmpl) { + $.get(OC.filePath('core', 'templates/legacy', 'fileexists.html'), function(tmpl) { self.$fileexistsTemplate = $(tmpl) defer.resolve(self.$fileexistsTemplate) }) |