Replace OC.Notification with toastify js (#15124)

Replace OC.Notification with toastify js
This commit is contained in:
John Molakvoæ 2019-06-07 08:24:15 +02:00 committed by GitHub
commit b968987ed4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 348 additions and 264 deletions

View File

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

49
core/css/toast.scss Normal file
View File

@ -0,0 +1,49 @@
.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;
position: absolute;
z-index: 9000;
border-radius: var(--border-radius);
.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);
}

26
core/js/dist/login.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

54
core/js/dist/main.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -900,75 +900,74 @@ describe('Core base tests', function() {
var hideSpy; var hideSpy;
var clock; var clock;
var getInnerText = function($node) {
return $node.contents().filter(function(){
return this.nodeType === 3;
})[0].nodeValue;
}
beforeEach(function() { beforeEach(function() {
clock = sinon.useFakeTimers(); clock = sinon.useFakeTimers();
showSpy = sinon.spy(OC.Notification, 'show'); showSpy = sinon.spy(OCP.Toast, 'message');
showHtmlSpy = sinon.spy(OC.Notification, 'showHtml');
hideSpy = sinon.spy(OC.Notification, 'hide'); hideSpy = sinon.spy(OC.Notification, 'hide');
$('#testArea').append('<div id="notification"></div>'); $('#testArea').append('<div id="content"></div>');
}); });
afterEach(function() { afterEach(function() {
showSpy.restore(); showSpy.restore();
showHtmlSpy.restore();
hideSpy.restore(); hideSpy.restore();
// jump past animations // jump past animations
clock.tick(10000); clock.tick(10000);
clock.restore(); clock.restore();
$('#testArea .toastify').remove();
}); });
describe('showTemporary', function() { describe('showTemporary', function() {
it('shows a plain text notification with default timeout', function() { it('shows a plain text notification with default timeout', function() {
var $row = OC.Notification.showTemporary('My notification test'); OC.Notification.showTemporary('My notification test');
expect(showSpy.calledOnce).toEqual(true); expect(showSpy.calledOnce).toEqual(true);
expect(showSpy.firstCall.args[0]).toEqual('My notification test'); expect(showSpy.firstCall.args[0]).toEqual('My notification test');
expect(showSpy.firstCall.args[1]).toEqual({isHTML: false, timeout: 7}); //expect(showSpy.firstCall.args[1]).toEqual({isHTML: false, timeout: 7});
var $row = $('#testArea .toastify');
expect($row).toBeDefined(); expect($row).toBeDefined();
expect($row.text()).toEqual('My notification test'); expect(getInnerText($row)).toEqual('My notification test');
}); });
it('shows a HTML notification with default timeout', function() { it('shows a HTML notification with default timeout', function() {
var $row = OC.Notification.showTemporary('<a>My notification test</a>', { isHTML: true }); OC.Notification.showTemporary('<a>My notification test</a>', { isHTML: true });
expect(showSpy.notCalled).toEqual(true); expect(showSpy.calledOnce).toEqual(true);
expect(showHtmlSpy.calledOnce).toEqual(true); expect(showSpy.firstCall.args[0]).toEqual('<a>My notification test</a>');
expect(showHtmlSpy.firstCall.args[0]).toEqual('<a>My notification test</a>'); expect(showSpy.firstCall.args[1].isHTML).toEqual(true)
expect(showHtmlSpy.firstCall.args[1]).toEqual({isHTML: true, timeout: 7});
var $row = $('#testArea .toastify');
expect($row).toBeDefined(); expect($row).toBeDefined();
expect($row.text()).toEqual('My notification test'); expect(getInnerText($row)).toEqual('<a>My notification test</a>');
}); });
it('hides itself after 7 seconds', function() { it('hides itself after 7 seconds', function() {
var $row = OC.Notification.showTemporary(''); OC.Notification.showTemporary('');
var $row = $('#testArea .toastify');
expect($row).toBeDefined();
// travel in time +7000 milliseconds // travel in time +7000 milliseconds
clock.tick(7000); clock.tick(7500);
expect(hideSpy.calledOnce).toEqual(true); $row = $('#testArea .toastify');
expect(hideSpy.firstCall.args[0]).toEqual($row); expect($row.length).toEqual(0);
}); });
}); });
describe('show', function() { describe('show', function() {
it('hides itself after a given time', function() { it('hides itself after a given time', function() {
OC.Notification.show('', { timeout: 10 }); OC.Notification.showTemporary('', {timeout: 10});
// travel in time +9 seconds var $row = $('#testArea .toastify');
clock.tick(9000); expect($row).toBeDefined();
expect(hideSpy.notCalled).toEqual(true); clock.tick(11500);
// travel in time +1 seconds $row = $('#testArea .toastify');
clock.tick(1000); expect($row.length).toEqual(0);
expect(hideSpy.calledOnce).toEqual(true);
});
it('does not hide itself after a given time if a timeout of 0 is defined', function() {
OC.Notification.show('', { timeout: 0 });
// travel in time +1000 seconds
clock.tick(1000000);
expect(hideSpy.notCalled).toEqual(true);
}); });
it('does not hide itself if no timeout given to show', function() { it('does not hide itself if no timeout given to show', function() {
OC.Notification.show(''); OC.Notification.show('');
@ -984,92 +983,34 @@ describe('Core base tests', function() {
var $row2 = OC.Notification.showTemporary('Two', {timeout: 2}); var $row2 = OC.Notification.showTemporary('Two', {timeout: 2});
var $row3 = OC.Notification.showTemporary('Three'); var $row3 = OC.Notification.showTemporary('Three');
var $el = $('#notification'); var $el = $('#testArea');
var $rows = $el.find('.row'); var $rows = $el.find('.toastify');
expect($rows.length).toEqual(3); expect($rows.length).toEqual(3);
expect($rows.eq(0).is($row1)).toEqual(true); expect($rows.eq(0).is($row3)).toEqual(true);
expect($rows.eq(1).is($row2)).toEqual(true); expect($rows.eq(1).is($row2)).toEqual(true);
expect($rows.eq(2).is($row3)).toEqual(true); expect($rows.eq(2).is($row1)).toEqual(true);
clock.tick(3000); clock.tick(3000);
$rows = $el.find('.row'); $rows = $el.find('.toastify');
expect($rows.length).toEqual(2); expect($rows.length).toEqual(2);
expect($rows.eq(0).is($row1)).toEqual(true); expect($rows.eq(0).is($row3)).toEqual(true);
expect($rows.eq(1).is($row3)).toEqual(true); expect($rows.eq(1).is($row1)).toEqual(true);
});
it('shows close button for error types', function() {
var $row = OC.Notification.showTemporary('One');
var $rowError = OC.Notification.showTemporary('Two', {type: 'error'});
expect($row.find('.close').length).toEqual(0);
expect($rowError.find('.close').length).toEqual(1);
// after clicking, row is gone
$rowError.find('.close').click();
var $rows = $('#notification').find('.row');
expect($rows.length).toEqual(1);
expect($rows.eq(0).is($row)).toEqual(true);
});
it('fades out the last notification but not the other ones', function() {
var fadeOutStub = sinon.stub($.fn, 'fadeOut');
var $row1 = OC.Notification.show('One', {type: 'error'});
var $row2 = OC.Notification.show('Two', {type: 'error'});
OC.Notification.showTemporary('Three', {timeout: 2});
var $el = $('#notification');
var $rows = $el.find('.row');
expect($rows.length).toEqual(3);
clock.tick(3000);
$rows = $el.find('.row');
expect($rows.length).toEqual(2);
$row1.find('.close').click();
clock.tick(1000);
expect(fadeOutStub.notCalled).toEqual(true);
$row2.find('.close').click();
clock.tick(1000);
expect(fadeOutStub.calledOnce).toEqual(true);
expect($el.is(':empty')).toEqual(false);
fadeOutStub.yield();
expect($el.is(':empty')).toEqual(true);
fadeOutStub.restore();
});
it('hides the first notification when calling hide without arguments', function() {
OC.Notification.show('One');
var $row2 = OC.Notification.show('Two');
spyOn(console, 'warn');
var $el = $('#notification');
var $rows = $el.find('.row');
expect($rows.length).toEqual(2);
OC.Notification.hide();
expect(console.warn).toHaveBeenCalled();
$rows = $el.find('.row');
expect($rows.length).toEqual(1);
expect($rows.eq(0).is($row2)).toEqual(true);
}); });
it('hides the given notification when calling hide with argument', function() { it('hides the given notification when calling hide with argument', function() {
var $row1 = OC.Notification.show('One'); var $row1 = OC.Notification.show('One');
var $row2 = OC.Notification.show('Two'); var $row2 = OC.Notification.show('Two');
var $el = $('#notification'); var $el = $('#testArea');
var $rows = $el.find('.row'); var $rows = $el.find('.toastify');
expect($rows.length).toEqual(2); expect($rows.length).toEqual(2);
OC.Notification.hide($row2); OC.Notification.hide($row2);
clock.tick(3000);
$rows = $el.find('.row'); $rows = $el.find('.toastify');
expect($rows.length).toEqual(1); expect($rows.length).toEqual(1);
expect($rows.eq(0).is($row1)).toEqual(true); expect($rows.eq(0).is($row1)).toEqual(true);
}); });

View File

@ -957,7 +957,7 @@ describe('OC.Share.ShareDialogView', function() {
var showTemporaryNotificationStub; var showTemporaryNotificationStub;
beforeEach(function() { beforeEach(function() {
showTemporaryNotificationStub = sinon.stub(OC.Notification, 'show'); showTemporaryNotificationStub = sinon.stub(OC.Notification, 'showTemporary');
}); });
afterEach(function() { afterEach(function() {

View File

@ -21,24 +21,22 @@
import _ from 'underscore' import _ from 'underscore'
import $ from 'jquery' import $ from 'jquery'
import Toastify from 'toastify-js'
/** /**
* @todo Write documentation * @todo Write documentation
* @deprecated 17.0.0 use OCP.Toast
* @namespace OC.Notification * @namespace OC.Notification
*/ */
export default { export default {
queuedNotifications: [],
updatableNotification: null,
getDefaultNotificationFunction: null, getDefaultNotificationFunction: null,
/**
* @type Array<int>
* @description array of notification timers
*/
notificationTimers: [],
/** /**
* @param callback * @param callback
* @todo Write documentation * @deprecated 17.0.0 use OCP.Toast
*/ */
setDefault: function (callback) { setDefault: function (callback) {
this.getDefaultNotificationFunction = callback; this.getDefaultNotificationFunction = callback;
@ -52,10 +50,11 @@ export default {
* *
* @param {jQuery} [$row] notification row * @param {jQuery} [$row] notification row
* @param {Function} [callback] callback * @param {Function} [callback] callback
* @deprecated 17.0.0 use OCP.Toast
*/ */
hide: function ($row, callback) { hide: function ($row, callback) {
var self = this; var self = this;
var $notification = $('#notification'); var $notification = $('#content');
if (_.isFunction($row)) { if (_.isFunction($row)) {
// first arg is the callback // first arg is the callback
@ -64,46 +63,23 @@ export default {
} }
if (!$row) { if (!$row) {
console.warn('Missing argument $row in OC.Notification.hide() call, caller needs to be adjusted to only dismiss its own notification'); console.error('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 return;
$row = $notification.find('.row:first');
} }
if ($row && $notification.find('.row').length > 1) {
// remove the row directly // remove the row directly
$row.remove(); $row.each(function () {
$(this)[0].toastify.hideToast()
if (this === this.updatableNotification) {
this.updatableNotification = null
}
})
if (callback) { if (callback) {
callback.call(); callback.call()
} }
return; if (this.getDefaultNotificationFunction) {
this.getDefaultNotificationFunction()
} }
_.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();
});
});
}, },
/** /**
@ -116,45 +92,14 @@ export default {
* @param {string} [options.type] notification type * @param {string} [options.type] notification type
* @param {int} [options.timeout=0] timeout value, defaults to 0 (permanent) * @param {int} [options.timeout=0] timeout value, defaults to 0 (permanent)
* @return {jQuery} jQuery element for notification row * @return {jQuery} jQuery element for notification row
* @deprecated 17.0.0 use OCP.Toast
*/ */
showHtml: function (html, options) { showHtml: function (html, options) {
options = options || {}; options = options || {}
_.defaults(options, { options.showHtml = true
timeout: 0 options.timeout = (options.timeout === 0) ? -1 : options.timeout
}); const toast = window.OCP.Toast.message(html, options)
return $(toast.toastElement)
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;
}, },
/** /**
@ -165,9 +110,11 @@ export default {
* @param {string} [options.type] notification type * @param {string} [options.type] notification type
* @param {int} [options.timeout=0] timeout value, defaults to 0 (permanent) * @param {int} [options.timeout=0] timeout value, defaults to 0 (permanent)
* @return {jQuery} jQuery element for notification row * @return {jQuery} jQuery element for notification row
* @deprecated 17.0.0 use OCP.Toast
*/ */
show: function (text, options) { 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 * @param {string} text Message to display
* @return {jQuery} JQuery element for notificaiton row * @return {jQuery} JQuery element for notificaiton row
* @deprecated 17.0.0 use OCP.Toast
*/ */
showUpdate: function (text) { showUpdate: function (text) {
var $notification = $('#notification'); if (this.updatableNotification) {
// sanitise this.updatableNotification.hideToast();
var $html = $('<div/>').text(text).html();
// new notification
if (text && $notification.find('.row').length == 0) {
return this.showHtml($html);
} }
this.updatableNotification = OCP.Toast.message(text, {timeout: -1})
var $row = $('<div class="row"></div>').prepend($html); return $(this.updatableNotification.toastElement);
// just update html in notification
$notification.html($row);
return $row;
}, },
/** /**
@ -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 {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 {boolean} [options.isHTML=false] an indicator for HTML notifications (true) or text (false)
* @param {string} [options.type] notification type * @param {string} [options.type] notification type
* @deprecated 17.0.0 use OCP.Toast
*/ */
showTemporary: function (text, options) { showTemporary: function (text, options) {
var defaults = { options = options || {}
isHTML: false, options.timeout = options.timeout || 7;
timeout: 7 const toast = window.OCP.Toast.message(text, options);
}; return $(toast.toastElement);
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. * Returns whether a notification is hidden.
* @return {boolean} * @return {boolean}
* @deprecated 17.0.0 use OCP.Toast
*/ */
isHidden: function () { 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 * as InitialState from './initialstate'
import Loader from './loader' import Loader from './loader'
import Collaboration from './collaboration' import Collaboration from './collaboration'
import Toast from './toast'
import * as WhatsNew from './whatsnew' import * as WhatsNew from './whatsnew'
/** @namespace OCP */ /** @namespace OCP */
export default { export default {
AppConfig, AppConfig,
Collaboration,
Comments, Comments,
InitialState, InitialState,
Loader, Loader,
WhatsNew, Toast,
Collaboration 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: !window.TESTING ? 'content' : 'testArea',
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", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
"dev": true "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", "optimist": "^0.6.1",
"source-map": "^0.6.1", "source-map": "^0.6.1",
"uglify-js": "^3.1.4" "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": { "handlebars-loader": {
@ -4740,9 +4783,9 @@
} }
}, },
"minimist": { "minimist": {
"version": "0.0.10", "version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
}, },
"mississippi": { "mississippi": {
"version": "3.0.0", "version": "3.0.0",
@ -6950,6 +6993,11 @@
"repeat-string": "^1.6.1" "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": { "tough-cookie": {
"version": "2.4.3", "version": "2.4.3",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",

View File

@ -48,6 +48,7 @@
"query-string": "^5.1.1", "query-string": "^5.1.1",
"snap.js": "^2.0.9", "snap.js": "^2.0.9",
"strengthify": "git+https://github.com/MorrisJobke/strengthify.git#0.5.8", "strengthify": "git+https://github.com/MorrisJobke/strengthify.git#0.5.8",
"toastify-js": "^1.5.0",
"underscore": "^1.9.1", "underscore": "^1.9.1",
"v-tooltip": "^2.0.2", "v-tooltip": "^2.0.2",
"vue": "^2.6.10", "vue": "^2.6.10",