diff options
author | Roeland Jago Douma <rullzer@users.noreply.github.com> | 2019-02-01 08:20:03 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-02-01 08:20:03 +0100 |
commit | dc3b44c02dc316215f10eb1e92d1b09328465470 (patch) | |
tree | a44609185e85074414a60dfe62a0936d75adb600 /core/src | |
parent | 2124ff65b673698dcb305b835b3ba4bbd438c074 (diff) | |
parent | 3d1a3b66442698601597d4f777d47d5f0ea744c2 (diff) | |
download | nextcloud-server-dc3b44c02dc316215f10eb1e92d1b09328465470.tar.gz nextcloud-server-dc3b44c02dc316215f10eb1e92d1b09328465470.zip |
Merge pull request #13956 from nextcloud/refactor/oc-plugins-msg-notifications-II
Move OC.Plugins, OC.msg and OC.Notification to the server bundle
Diffstat (limited to 'core/src')
-rw-r--r-- | core/src/OC/index.js | 6 | ||||
-rw-r--r-- | core/src/OC/msg.js | 117 | ||||
-rw-r--r-- | core/src/OC/notification.js | 232 | ||||
-rw-r--r-- | core/src/OC/plugins.js | 89 |
4 files changed, 444 insertions, 0 deletions
diff --git a/core/src/OC/index.js b/core/src/OC/index.js index ba63780a879..9d416f687a2 100644 --- a/core/src/OC/index.js +++ b/core/src/OC/index.js @@ -25,6 +25,9 @@ import Backbone from './backbone' import ContactsMenu from './contactsmenu' import EventSource from './eventsource' import L10N from './l10n' +import msg from './msg' +import Notification from './notification' +import Plugins from './plugins' /** @namespace OC */ export default { @@ -34,4 +37,7 @@ export default { ContactsMenu, EventSource, L10N, + msg, + Notification, + Plugins, } diff --git a/core/src/OC/msg.js b/core/src/OC/msg.js new file mode 100644 index 00000000000..1d43b4375e7 --- /dev/null +++ b/core/src/OC/msg.js @@ -0,0 +1,117 @@ +/* global t */ + +/* + * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @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 $ from 'jquery'; + +/** + * A little class to manage a status field for a "saving" process. + * It can be used to display a starting message (e.g. "Saving...") and then + * replace it with a green success message or a red error message. + * + * @namespace OC.msg + */ +export default { + /** + * Displayes a "Saving..." message in the given message placeholder + * + * @param {Object} selector Placeholder to display the message in + */ + startSaving: function (selector) { + this.startAction(selector, t('core', 'Saving...')); + }, + + /** + * Displayes a custom message in the given message placeholder + * + * @param {Object} selector Placeholder to display the message in + * @param {string} message Plain text message to display (no HTML allowed) + */ + startAction: function (selector, message) { + $(selector).text(message) + .removeClass('success') + .removeClass('error') + .stop(true, true) + .show(); + }, + + /** + * Displayes an success/error message in the given selector + * + * @param {Object} selector Placeholder to display the message in + * @param {Object} response Response of the server + * @param {Object} response.data Data of the servers response + * @param {string} response.data.message Plain text message to display (no HTML allowed) + * @param {string} response.status is being used to decide whether the message + * is displayed as an error/success + */ + finishedSaving: function (selector, response) { + this.finishedAction(selector, response); + }, + + /** + * Displayes an success/error message in the given selector + * + * @param {Object} selector Placeholder to display the message in + * @param {Object} response Response of the server + * @param {Object} response.data Data of the servers response + * @param {string} response.data.message Plain text message to display (no HTML allowed) + * @param {string} response.status is being used to decide whether the message + * is displayed as an error/success + */ + finishedAction: function (selector, response) { + if (response.status === "success") { + this.finishedSuccess(selector, response.data.message); + } else { + this.finishedError(selector, response.data.message); + } + }, + + /** + * Displayes an success message in the given selector + * + * @param {Object} selector Placeholder to display the message in + * @param {string} message Plain text success message to display (no HTML allowed) + */ + finishedSuccess: function (selector, message) { + $(selector).text(message) + .addClass('success') + .removeClass('error') + .stop(true, true) + .delay(3000) + .fadeOut(900) + .show(); + }, + + /** + * Displayes an error message in the given selector + * + * @param {Object} selector Placeholder to display the message in + * @param {string} message Plain text error message to display (no HTML allowed) + */ + finishedError: function (selector, message) { + $(selector).text(message) + .addClass('error') + .removeClass('success') + .show(); + } +} diff --git a/core/src/OC/notification.js b/core/src/OC/notification.js new file mode 100644 index 00000000000..73220c71bdd --- /dev/null +++ b/core/src/OC/notification.js @@ -0,0 +1,232 @@ +/* + * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @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 _ from 'underscore' +import $ from 'jquery' + +/** + * @todo Write documentation + * @namespace OC.Notification + */ +export default { + queuedNotifications: [], + getDefaultNotificationFunction: null, + + /** + * @type Array<int> + * @description array of notification timers + */ + notificationTimers: [], + + /** + * @param callback + * @todo Write documentation + */ + setDefault: function (callback) { + this.getDefaultNotificationFunction = callback; + }, + + /** + * Hides a notification. + * + * If a row is given, only hide that one. + * If no row is given, hide all notifications. + * + * @param {jQuery} [$row] notification row + * @param {Function} [callback] callback + */ + hide: function ($row, callback) { + var self = this; + var $notification = $('#notification'); + + if (_.isFunction($row)) { + // first arg is the callback + callback = $row; + $row = undefined; + } + + if (!$row) { + console.warn('Missing argument $row in OC.Notification.hide() call, caller needs to be adjusted to only dismiss its own notification'); + // assume that the row to be hidden is the first one + $row = $notification.find('.row:first'); + } + + if ($row && $notification.find('.row').length > 1) { + // remove the row directly + $row.remove(); + if (callback) { + callback.call(); + } + return; + } + + _.defer(function () { + // fade out is supposed to only fade when there is a single row + // however, some code might call hide() and show() directly after, + // which results in more than one element + // in this case, simply delete that one element that was supposed to + // fade out + // + // FIXME: remove once all callers are adjusted to only hide their own notifications + if ($notification.find('.row').length > 1) { + $row.remove(); + return; + } + + // else, fade out whatever was present + $notification.fadeOut('400', function () { + if (self.isHidden()) { + if (self.getDefaultNotificationFunction) { + self.getDefaultNotificationFunction.call(); + } + } + if (callback) { + callback.call(); + } + $notification.empty(); + }); + }); + }, + + /** + * Shows a notification as HTML without being sanitized before. + * If you pass unsanitized user input this may lead to a XSS vulnerability. + * Consider using show() instead of showHTML() + * + * @param {string} html Message to display + * @param {Object} [options] options + * @param {string} [options.type] notification type + * @param {int} [options.timeout=0] timeout value, defaults to 0 (permanent) + * @return {jQuery} jQuery element for notification row + */ + showHtml: function (html, options) { + options = options || {}; + _.defaults(options, { + timeout: 0 + }); + + var self = this; + var $notification = $('#notification'); + if (this.isHidden()) { + $notification.fadeIn().css('display', 'inline-block'); + } + var $row = $('<div class="row"></div>'); + if (options.type) { + $row.addClass('type-' + options.type); + } + if (options.type === 'error') { + // add a close button + var $closeButton = $('<a class="action close icon-close" href="#"></a>'); + $closeButton.attr('alt', t('core', 'Dismiss')); + $row.append($closeButton); + $closeButton.one('click', function () { + self.hide($row); + return false; + }); + $row.addClass('closeable'); + } + + $row.prepend(html); + $notification.append($row); + + if (options.timeout > 0) { + // register timeout to vanish notification + this.notificationTimers.push(setTimeout(function () { + self.hide($row); + }, (options.timeout * 1000))); + } + + return $row; + }, + + /** + * Shows a sanitized notification + * + * @param {string} text Message to display + * @param {Object} [options] options + * @param {string} [options.type] notification type + * @param {int} [options.timeout=0] timeout value, defaults to 0 (permanent) + * @return {jQuery} jQuery element for notification row + */ + show: function (text, options) { + return this.showHtml($('<div/>').text(text).html(), options); + }, + + /** + * Updates (replaces) a sanitized notification. + * + * @param {string} text Message to display + * @return {jQuery} JQuery element for notificaiton row + */ + showUpdate: function (text) { + var $notification = $('#notification'); + // sanitise + var $html = $('<div/>').text(text).html(); + + // new notification + if (text && $notification.find('.row').length == 0) { + return this.showHtml($html); + } + + var $row = $('<div class="row"></div>').prepend($html); + + // just update html in notification + $notification.html($row); + + return $row; + }, + + /** + * Shows a notification that disappears after x seconds, default is + * 7 seconds + * + * @param {string} text Message to show + * @param {array} [options] options array + * @param {int} [options.timeout=7] timeout in seconds, if this is 0 it will show the message permanently + * @param {boolean} [options.isHTML=false] an indicator for HTML notifications (true) or text (false) + * @param {string} [options.type] notification type + */ + showTemporary: function (text, options) { + var defaults = { + isHTML: false, + timeout: 7 + }; + options = options || {}; + // merge defaults with passed in options + _.defaults(options, defaults); + + var $row; + if (options.isHTML) { + $row = this.showHtml(text, options); + } else { + $row = this.show(text, options); + } + return $row; + }, + + /** + * Returns whether a notification is hidden. + * @return {boolean} + */ + isHidden: function () { + return !$("#notification").find('.row').length; + } +} diff --git a/core/src/OC/plugins.js b/core/src/OC/plugins.js new file mode 100644 index 00000000000..dd25610c2db --- /dev/null +++ b/core/src/OC/plugins.js @@ -0,0 +1,89 @@ +/* + * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @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 OC.Plugins + */ +export default { + + /** + * @type Array.<OC.Plugin> + */ + _plugins: {}, + + /** + * Register plugin + * + * @param {String} targetName app name / class name to hook into + * @param {OC.Plugin} plugin + */ + register: function (targetName, plugin) { + var plugins = this._plugins[targetName]; + if (!plugins) { + plugins = this._plugins[targetName] = []; + } + plugins.push(plugin); + }, + + /** + * Returns all plugin registered to the given target + * name / app name / class name. + * + * @param {String} targetName app name / class name to hook into + * @return {Array.<OC.Plugin>} array of plugins + */ + getPlugins: function (targetName) { + return this._plugins[targetName] || []; + }, + + /** + * Call attach() on all plugins registered to the given target name. + * + * @param {String} targetName app name / class name + * @param {Object} object to be extended + * @param {Object} [options] options + */ + attach: function (targetName, targetObject, options) { + var plugins = this.getPlugins(targetName); + for (var i = 0; i < plugins.length; i++) { + if (plugins[i].attach) { + plugins[i].attach(targetObject, options); + } + } + }, + + /** + * Call detach() on all plugins registered to the given target name. + * + * @param {String} targetName app name / class name + * @param {Object} object to be extended + * @param {Object} [options] options + */ + detach: function (targetName, targetObject, options) { + var plugins = this.getPlugins(targetName); + for (var i = 0; i < plugins.length; i++) { + if (plugins[i].detach) { + plugins[i].detach(targetObject, options); + } + } + } + +}
\ No newline at end of file |