Add toastify js as a OC.Notification replacement

Signed-off-by: Julius Härtl <jus@bitgrid.net>
This commit is contained in:
Julius Härtl 2019-03-01 13:02:12 +01:00
parent 07ffe4a34a
commit 2d0337332d
No known key found for this signature in database
GPG key ID: 4C614C6ED2CDE6DF
7 changed files with 235 additions and 119 deletions

View file

@ -8,4 +8,5 @@
@import 'fixes.scss';
@import 'mobile.scss';
@import 'tooltip.scss';
@import 'public.scss';
@import 'toast.scss';
@import 'public.scss';

46
core/css/toast.scss Normal file
View file

@ -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);
}

View file

@ -21,24 +21,22 @@
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: [],
updatableNotification: null,
getDefaultNotificationFunction: null,
/**
* @type Array<int>
* @description array of notification timers
*/
notificationTimers: [],
/**
* @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;
}
}

View 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
};

89
core/src/OCP/toast.js Normal file
View file

@ -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

54
package-lock.json generated
View file

@ -2330,6 +2330,34 @@
"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"
}
}
}
},
@ -3782,6 +3810,21 @@
"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": {
@ -4740,9 +4783,9 @@
}
},
"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",
@ -6950,6 +6993,11 @@
"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",

View 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",