]> source.dussan.org Git - nextcloud-server.git/commitdiff
Add toastify js as a OC.Notification replacement
authorJulius Härtl <jus@bitgrid.net>
Fri, 1 Mar 2019 12:02:12 +0000 (13:02 +0100)
committerJulius Härtl <jus@bitgrid.net>
Fri, 7 Jun 2019 05:32:16 +0000 (07:32 +0200)
Signed-off-by: Julius Härtl <jus@bitgrid.net>
core/css/server.scss
core/css/toast.scss [new file with mode: 0644]
core/src/OC/notification.js
core/src/OCP/index.js
core/src/OCP/toast.js [new file with mode: 0644]
package-lock.json
package.json

index 7269847ad91c21d8db3377f05cbce8ee5da90764..a0fc551a1875e1822e1db8429858d0e8d3e6fc5b 100644 (file)
@@ -8,4 +8,5 @@
 @import 'fixes.scss';
 @import 'mobile.scss';
 @import 'tooltip.scss';
-@import 'public.scss';
\ No newline at end of file
+@import 'toast.scss';
+@import 'public.scss';
diff --git a/core/css/toast.scss b/core/css/toast.scss
new file mode 100644 (file)
index 0000000..242ae03
--- /dev/null
@@ -0,0 +1,46 @@
+.toastify.toast {
+       min-width: 200px;
+       background: none;
+       background-color: var(--color-main-background);
+       color: var(--color-main-text);
+       box-shadow: 0 0 6px 0 var(--color-box-shadow);
+       padding: 12px;
+       padding-right: 34px;
+       margin-top: 45px;
+
+       .toast-close {
+               position: absolute;
+               top: 0;
+               right: 0;
+               width: 38px;
+               opacity: 0.4;
+               padding: 12px;
+               @include icon-color('close', 'actions', $color-black, 2, true);
+               background-position: center;
+               background-repeat: no-repeat;
+               text-indent: 200%;
+               white-space: nowrap;
+               overflow: hidden;
+
+               &:hover, &:focus, &:active {
+                       cursor: pointer;
+                       opacity: 1;
+               }
+       }
+}
+.toastify.toastify-top {
+       right: 10px;
+}
+
+.toast-error {
+       border-left: 3px solid var(--color-error);
+}
+.toast-info {
+       border-left: 3px solid var(--color-primary);
+}
+.toast-warning {
+       border-left: 3px solid var(--color-warning);
+}
+.toast-success {
+       border-left: 3px solid var(--color-success);
+}
index 73220c71bdd7ee9f57eb9d3013320344f3c90e84..45af15841231a5269ba1bbdbde09d181b0741c75 100644 (file)
 
 import _ from 'underscore'
 import $ from 'jquery'
+import Toastify from 'toastify-js'
 
 /**
  * @todo Write documentation
+ * @deprecated 17.0.0 use OCP.Toast
  * @namespace OC.Notification
  */
 export default {
-       queuedNotifications: [],
-       getDefaultNotificationFunction: null,
 
-       /**
-        * @type Array<int>
-        * @description array of notification timers
-        */
-       notificationTimers: [],
+       updatableNotification: null,
+
+       getDefaultNotificationFunction: null,
 
        /**
         * @param callback
-        * @todo Write documentation
+        * @deprecated 17.0.0 use OCP.Toast
         */
        setDefault: function (callback) {
                this.getDefaultNotificationFunction = callback;
@@ -52,10 +50,11 @@ export default {
         *
         * @param {jQuery} [$row] notification row
         * @param {Function} [callback] callback
+        * @deprecated 17.0.0 use OCP.Toast
         */
        hide: function ($row, callback) {
                var self = this;
-               var $notification = $('#notification');
+               var $notification = $('#content');
 
                if (_.isFunction($row)) {
                        // first arg is the callback
@@ -64,46 +63,23 @@ export default {
                }
 
                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();
-                       }
+                       console.error('Missing argument $row in OC.Notification.hide() call, caller needs to be adjusted to only dismiss its own notification');
                        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;
+               // remove the row directly
+               $row.each(function () {
+                       $(this)[0].toastify.hideToast()
+                       if (this === this.updatableNotification) {
+                               this.updatableNotification = null
                        }
-
-                       // 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();
-                       });
-               });
+               })
+               if (callback) {
+                       callback.call()
+               }
+               if (this.getDefaultNotificationFunction) {
+                       this.getDefaultNotificationFunction()
+               }
        },
 
        /**
@@ -116,45 +92,14 @@ export default {
         * @param {string} [options.type] notification type
         * @param {int} [options.timeout=0] timeout value, defaults to 0 (permanent)
         * @return {jQuery} jQuery element for notification row
+        * @deprecated 17.0.0 use OCP.Toast
         */
        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;
+               options = options || {}
+               options.showHtml = true
+               options.timeout = (options.timeout === 0) ? -1 : options.timeout
+               const toast = window.OCP.Toast.message(html, options)
+               return $(toast.toastElement)
        },
 
        /**
@@ -165,9 +110,11 @@ export default {
         * @param {string} [options.type] notification type
         * @param {int} [options.timeout=0] timeout value, defaults to 0 (permanent)
         * @return {jQuery} jQuery element for notification row
+        * @deprecated 17.0.0 use OCP.Toast
         */
        show: function (text, options) {
-               return this.showHtml($('<div/>').text(text).html(), options);
+               const toast = window.OCP.Toast.message(text, options);
+               return $(toast.toastElement);
        },
 
        /**
@@ -175,23 +122,14 @@ export default {
         *
         * @param {string} text Message to display
         * @return {jQuery} JQuery element for notificaiton row
+        * @deprecated 17.0.0 use OCP.Toast
         */
        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);
+               if (this.updatableNotification) {
+                       this.updatableNotification.hideToast();
                }
-
-               var $row = $('<div class="row"></div>').prepend($html);
-
-               // just update html in notification
-               $notification.html($row);
-
-               return $row;
+               this.updatableNotification = OCP.Toast.message(text, {timeout: -1})
+               return $(this.updatableNotification.toastElement);
        },
 
        /**
@@ -203,30 +141,21 @@ export default {
         * @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
+        * @deprecated 17.0.0 use OCP.Toast
         */
        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;
+               options = options || {}
+               options.timeout = options.timeout || 7;
+               const toast = window.OCP.Toast.message(text, options);
+               return $(toast.toastElement);
        },
 
        /**
         * Returns whether a notification is hidden.
         * @return {boolean}
+        * @deprecated 17.0.0 use OCP.Toast
         */
        isHidden: function () {
-               return !$("#notification").find('.row').length;
+               return !$('#content').find('.toastify').length;
        }
 }
index 67945318362b994b152f2fc3082d06f69e75428d..a4d8f46b88d10230b7f12c5cedafb2dd7863db7a 100644 (file)
@@ -6,14 +6,16 @@ import * as Comments from './comments'
 import * as InitialState from './initialstate'
 import Loader from './loader'
 import Collaboration from './collaboration'
+import Toast from './toast'
 import * as WhatsNew from './whatsnew'
 
 /** @namespace OCP */
 export default {
        AppConfig,
+       Collaboration,
        Comments,
        InitialState,
        Loader,
-       WhatsNew,
-       Collaboration
+       Toast,
+       WhatsNew
 };
diff --git a/core/src/OCP/toast.js b/core/src/OCP/toast.js
new file mode 100644 (file)
index 0000000..a9c96f1
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * @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/>.
+ *
+ */
+
+import Toastify from 'toastify-js'
+
+const TOAST_TYPE_CLASES = {
+       error: 'toast-error',
+       info: 'toast-info',
+       warning: 'toast-warning',
+       success: 'toast-success',
+       permanent: 'permanent'
+}
+
+const Toast = {
+
+       success(text, options = {}) {
+               options.type = 'success';
+               return this.message(text, options)
+       },
+
+       warning(text, options = {}) {
+               options.type = 'warning';
+               return this.message(text, options)
+       },
+
+       error(text, options = {}) {
+               options.type = 'error';
+               return this.message(text, options)
+       },
+
+       info(text, options = {}) {
+               options.type = 'info';
+               return this.message(text, options)
+       },
+
+       message(text, options) {
+               options = options || {};
+               _.defaults(options, {
+                       timeout: 7,
+                       showHtml: false,
+                       type: undefined,
+                       close: true,
+                       callback: () => {}
+               });
+               if (!options.showHtml) {
+                       text = $('<div/>').text(text).html()
+               }
+               let classes = ''
+               if (options.type) {
+                       classes = TOAST_TYPE_CLASES[options.type]
+               }
+
+               const toast = Toastify({
+                       text: text,
+                       duration: options.timeout ? options.timeout*1000 : null,
+                       callback: options.callback,
+                       close: options.close,
+                       gravity: 'top',
+                       selector: 'content',
+                       positionLeft: false,
+                       backgroundColor: '',
+                       className: 'toast ' + classes
+               })
+               toast.showToast()
+               // add toastify object to the element for reference in legacy OC.Notification
+               toast.toastElement.toastify = toast;
+               return toast
+       }
+}
+export default Toast
index 5074a8d51f0865f566955d63e954291e9a8e97de..4c0cd78057d272edb8dc13e7bf8f9203f40232b0 100644 (file)
           "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
           "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
           "dev": true
+        },
+        "jsesc": {
+          "version": "0.5.0",
+          "resolved": "http://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+          "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0="
+        },
+        "regexpu-core": {
+          "version": "1.0.0",
+          "resolved": "http://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz",
+          "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=",
+          "requires": {
+            "regenerate": "^1.2.1",
+            "regjsgen": "^0.2.0",
+            "regjsparser": "^0.1.4"
+          }
+        },
+        "regjsgen": {
+          "version": "0.2.0",
+          "resolved": "http://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
+          "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc="
+        },
+        "regjsparser": {
+          "version": "0.1.5",
+          "resolved": "http://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz",
+          "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=",
+          "requires": {
+            "jsesc": "~0.5.0"
+          }
         }
       }
     },
         "optimist": "^0.6.1",
         "source-map": "^0.6.1",
         "uglify-js": "^3.1.4"
+      },
+      "dependencies": {
+        "async": {
+          "version": "2.6.1",
+          "resolved": "http://registry.npmjs.org/async/-/async-2.6.1.tgz",
+          "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==",
+          "requires": {
+            "lodash": "^4.17.10"
+          }
+        },
+        "source-map": {
+          "version": "0.6.1",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+        }
       }
     },
     "handlebars-loader": {
       }
     },
     "minimist": {
-      "version": "0.0.10",
-      "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
-      "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="
+      "version": "0.0.8",
+      "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+      "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
     },
     "mississippi": {
       "version": "3.0.0",
         "repeat-string": "^1.6.1"
       }
     },
+    "toastify-js": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/toastify-js/-/toastify-js-1.5.0.tgz",
+      "integrity": "sha512-tupU/X7DqwxYxTgT6n9SSEZLIGuwL1hFWg9uGQOzi8G04FLXoziw0GRF/TmuARrSQQCfIarfzoKEdDPG14Pr3Q=="
+    },
     "tough-cookie": {
       "version": "2.4.3",
       "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
index 106d11a8233ba6d9b3c27846c23cd05f4dbedf64..3c53855a0df9fd91816e31bdd9d68d148354dcae 100644 (file)
@@ -48,6 +48,7 @@
     "query-string": "^5.1.1",
     "snap.js": "^2.0.9",
     "strengthify": "git+https://github.com/MorrisJobke/strengthify.git#0.5.8",
+    "toastify-js": "^1.5.0",
     "underscore": "^1.9.1",
     "v-tooltip": "^2.0.2",
     "vue": "^2.6.10",