diff --git a/Bootstrap.Admin/Views/Shared/_Admin.cshtml b/Bootstrap.Admin/Views/Shared/_Admin.cshtml
index 62aba882..26f7643b 100644
--- a/Bootstrap.Admin/Views/Shared/_Admin.cshtml
+++ b/Bootstrap.Admin/Views/Shared/_Admin.cshtml
@@ -18,13 +18,14 @@
+
+
-
@RenderSection("javascript", false)
diff --git a/Bootstrap.Admin/wwwroot/js/toastr.js b/Bootstrap.Admin/wwwroot/js/toastr.js
new file mode 100644
index 00000000..9be91eef
--- /dev/null
+++ b/Bootstrap.Admin/wwwroot/js/toastr.js
@@ -0,0 +1,415 @@
+/*
+ * Toastr
+ * Copyright 2012-2015
+ * Authors: John Papa, Hans Fjällemark, and Tim Ferrell.
+ * All Rights Reserved.
+ * Use, reproduction, distribution, and modification of this code is subject to the terms and
+ * conditions of the MIT license, available at http://www.opensource.org/licenses/mit-license.php
+ *
+ * ARIA Support: Greta Krafsig
+ *
+ * Project: https://github.com/CodeSeven/toastr
+ */
+/* global define */
+; (function (define) {
+ define(['jquery'], function ($) {
+ return (function () {
+ var $container;
+ var listener;
+ var toastId = 0;
+ var toastType = {
+ error: 'error',
+ info: 'info',
+ success: 'success',
+ warning: 'warning'
+ };
+
+ var toastr = {
+ clear: clear,
+ remove: remove,
+ error: error,
+ getContainer: getContainer,
+ info: info,
+ options: {},
+ subscribe: subscribe,
+ success: success,
+ version: '2.1.1',
+ warning: warning
+ };
+
+ var previousToast;
+
+ return toastr;
+
+ ////////////////
+
+ function error(message, title, optionsOverride) {
+ return notify({
+ type: toastType.error,
+ iconClass: getOptions().iconClasses.error,
+ message: message,
+ optionsOverride: optionsOverride,
+ title: title
+ });
+ }
+
+ function getContainer(options, create) {
+ if (!options) { options = getOptions(); }
+ $container = $('#' + options.containerId);
+ if ($container.length) {
+ return $container;
+ }
+ if (create) {
+ $container = createContainer(options);
+ }
+ return $container;
+ }
+
+ function info(message, title, optionsOverride) {
+ return notify({
+ type: toastType.info,
+ iconClass: getOptions().iconClasses.info,
+ message: message,
+ optionsOverride: optionsOverride,
+ title: title
+ });
+ }
+
+ function subscribe(callback) {
+ listener = callback;
+ }
+
+ function success(message, title, optionsOverride) {
+ return notify({
+ type: toastType.success,
+ iconClass: getOptions().iconClasses.success,
+ message: message,
+ optionsOverride: optionsOverride,
+ title: title
+ });
+ }
+
+ function warning(message, title, optionsOverride) {
+ return notify({
+ type: toastType.warning,
+ iconClass: getOptions().iconClasses.warning,
+ message: message,
+ optionsOverride: optionsOverride,
+ title: title
+ });
+ }
+
+ function clear($toastElement, clearOptions) {
+ var options = getOptions();
+ if (!$container) { getContainer(options); }
+ if (!clearToast($toastElement, options, clearOptions)) {
+ clearContainer(options);
+ }
+ }
+
+ function remove($toastElement) {
+ var options = getOptions();
+ if (!$container) { getContainer(options); }
+ if ($toastElement && $(':focus', $toastElement).length === 0) {
+ removeToast($toastElement);
+ return;
+ }
+ if ($container.children().length) {
+ $container.remove();
+ }
+ }
+
+ // internal functions
+
+ function clearContainer (options) {
+ var toastsToClear = $container.children();
+ for (var i = toastsToClear.length - 1; i >= 0; i--) {
+ clearToast($(toastsToClear[i]), options);
+ }
+ }
+
+ function clearToast ($toastElement, options, clearOptions) {
+ var force = clearOptions && clearOptions.force ? clearOptions.force : false;
+ if ($toastElement && (force || $(':focus', $toastElement).length === 0)) {
+ $toastElement[options.hideMethod]({
+ duration: options.hideDuration,
+ easing: options.hideEasing,
+ complete: function () { removeToast($toastElement); }
+ });
+ return true;
+ }
+ return false;
+ }
+
+ function createContainer(options) {
+ $container = $('
')
+ .attr('id', options.containerId)
+ .addClass(options.positionClass)
+ .attr('aria-live', 'polite')
+ .attr('role', 'alert');
+
+ $container.appendTo($(options.target));
+ return $container;
+ }
+
+ function getDefaults() {
+ return {
+ tapToDismiss: true,
+ toastClass: 'toast',
+ containerId: 'toast-container',
+ debug: false,
+
+ showMethod: 'fadeIn', //fadeIn, slideDown, and show are built into jQuery
+ showDuration: 300,
+ showEasing: 'swing', //swing and linear are built into jQuery
+ onShown: undefined,
+ hideMethod: 'fadeOut',
+ hideDuration: 1000,
+ hideEasing: 'swing',
+ onHidden: undefined,
+
+ extendedTimeOut: 1000,
+ iconClasses: {
+ error: 'toast-error',
+ info: 'toast-info',
+ success: 'toast-success',
+ warning: 'toast-warning'
+ },
+ iconClass: 'toast-info',
+ positionClass: 'toast-top-right',
+ timeOut: 5000, // Set timeOut and extendedTimeOut to 0 to make it sticky
+ titleClass: 'toast-title',
+ messageClass: 'toast-message',
+ target: 'body',
+ closeHtml: '',
+ newestOnTop: true,
+ preventDuplicates: false,
+ progressBar: false
+ };
+ }
+
+ function publish(args) {
+ if (!listener) { return; }
+ listener(args);
+ }
+
+ function notify(map) {
+ var options = getOptions();
+ var iconClass = map.iconClass || options.iconClass;
+
+ if (typeof (map.optionsOverride) !== 'undefined') {
+ options = $.extend(options, map.optionsOverride);
+ iconClass = map.optionsOverride.iconClass || iconClass;
+ }
+
+ if (shouldExit(options, map)) { return; }
+
+ toastId++;
+
+ $container = getContainer(options, true);
+
+ var intervalId = null;
+ var $toastElement = $('');
+ var $titleElement = $('');
+ var $messageElement = $('');
+ var $progressElement = $('');
+ var $closeElement = $(options.closeHtml);
+ var progressBar = {
+ intervalId: null,
+ hideEta: null,
+ maxHideTime: null
+ };
+ var response = {
+ toastId: toastId,
+ state: 'visible',
+ startTime: new Date(),
+ options: options,
+ map: map
+ };
+
+ personalizeToast();
+
+ displayToast();
+
+ handleEvents();
+
+ publish(response);
+
+ if (options.debug && console) {
+ console.log(response);
+ }
+
+ return $toastElement;
+
+ function personalizeToast() {
+ setIcon();
+ setTitle();
+ setMessage();
+ setCloseButton();
+ setProgressBar();
+ setSequence();
+ }
+
+ function handleEvents() {
+ $toastElement.hover(stickAround, delayedHideToast);
+ if (!options.onclick && options.tapToDismiss) {
+ $toastElement.click(hideToast);
+ }
+
+ if (options.closeButton && $closeElement) {
+ $closeElement.click(function (event) {
+ if (event.stopPropagation) {
+ event.stopPropagation();
+ } else if (event.cancelBubble !== undefined && event.cancelBubble !== true) {
+ event.cancelBubble = true;
+ }
+ hideToast(true);
+ });
+ }
+
+ if (options.onclick) {
+ $toastElement.click(function () {
+ options.onclick();
+ hideToast();
+ });
+ }
+ }
+
+ function displayToast() {
+ $toastElement.hide();
+
+ $toastElement[options.showMethod](
+ {duration: options.showDuration, easing: options.showEasing, complete: options.onShown}
+ );
+
+ if (options.timeOut > 0) {
+ intervalId = setTimeout(hideToast, options.timeOut);
+ progressBar.maxHideTime = parseFloat(options.timeOut);
+ progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime;
+ if (options.progressBar) {
+ progressBar.intervalId = setInterval(updateProgress, 10);
+ }
+ }
+ }
+
+ function setIcon() {
+ if (map.iconClass) {
+ $toastElement.addClass(options.toastClass).addClass(iconClass);
+ }
+ }
+
+ function setSequence() {
+ if (options.newestOnTop) {
+ $container.prepend($toastElement);
+ } else {
+ $container.append($toastElement);
+ }
+ }
+
+ function setTitle() {
+ if (map.title) {
+ $titleElement.append(map.title).addClass(options.titleClass);
+ $toastElement.append($titleElement);
+ }
+ }
+
+ function setMessage() {
+ if (map.message) {
+ $messageElement.append(map.message).addClass(options.messageClass);
+ $toastElement.append($messageElement);
+ }
+ }
+
+ function setCloseButton() {
+ if (options.closeButton) {
+ $closeElement.addClass('toast-close-button').attr('role', 'button');
+ $toastElement.prepend($closeElement);
+ }
+ }
+
+ function setProgressBar() {
+ if (options.progressBar) {
+ $progressElement.addClass('toast-progress');
+ $toastElement.prepend($progressElement);
+ }
+ }
+
+ function shouldExit(options, map) {
+ if (options.preventDuplicates) {
+ if (map.message === previousToast) {
+ return true;
+ } else {
+ previousToast = map.message;
+ }
+ }
+ return false;
+ }
+
+ function hideToast(override) {
+ if ($(':focus', $toastElement).length && !override) {
+ return;
+ }
+ clearTimeout(progressBar.intervalId);
+ return $toastElement[options.hideMethod]({
+ duration: options.hideDuration,
+ easing: options.hideEasing,
+ complete: function () {
+ removeToast($toastElement);
+ if (options.onHidden && response.state !== 'hidden') {
+ options.onHidden();
+ }
+ response.state = 'hidden';
+ response.endTime = new Date();
+ publish(response);
+ }
+ });
+ }
+
+ function delayedHideToast() {
+ if (options.timeOut > 0 || options.extendedTimeOut > 0) {
+ intervalId = setTimeout(hideToast, options.extendedTimeOut);
+ progressBar.maxHideTime = parseFloat(options.extendedTimeOut);
+ progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime;
+ }
+ }
+
+ function stickAround() {
+ clearTimeout(intervalId);
+ progressBar.hideEta = 0;
+ $toastElement.stop(true, true)[options.showMethod](
+ {duration: options.showDuration, easing: options.showEasing}
+ );
+ }
+
+ function updateProgress() {
+ var percentage = ((progressBar.hideEta - (new Date().getTime())) / progressBar.maxHideTime) * 100;
+ $progressElement.width(percentage + '%');
+ }
+ }
+
+ function getOptions() {
+ return $.extend({}, getDefaults(), toastr.options);
+ }
+
+ function removeToast($toastElement) {
+ if (!$container) { $container = getContainer(); }
+ if ($toastElement.is(':visible')) {
+ return;
+ }
+ $toastElement.remove();
+ $toastElement = null;
+ if ($container.children().length === 0) {
+ $container.remove();
+ previousToast = undefined;
+ }
+ }
+
+ })();
+ });
+}(typeof define === 'function' && define.amd ? define : function (deps, factory) {
+ if (typeof module !== 'undefined' && module.exports) { //Node
+ module.exports = factory(require('jquery'));
+ } else {
+ window['toastr'] = factory(window['jQuery']);
+ }
+}));
diff --git a/Bootstrap.Client/Views/Shared/_Layout.cshtml b/Bootstrap.Client/Views/Shared/_Layout.cshtml
index 1e0b62e0..0586f8f0 100644
--- a/Bootstrap.Client/Views/Shared/_Layout.cshtml
+++ b/Bootstrap.Client/Views/Shared/_Layout.cshtml
@@ -29,13 +29,14 @@
+
+
-
@RenderSection("javascript", false)
diff --git a/Bootstrap.Client/wwwroot/js/toastr.js b/Bootstrap.Client/wwwroot/js/toastr.js
new file mode 100644
index 00000000..9be91eef
--- /dev/null
+++ b/Bootstrap.Client/wwwroot/js/toastr.js
@@ -0,0 +1,415 @@
+/*
+ * Toastr
+ * Copyright 2012-2015
+ * Authors: John Papa, Hans Fjällemark, and Tim Ferrell.
+ * All Rights Reserved.
+ * Use, reproduction, distribution, and modification of this code is subject to the terms and
+ * conditions of the MIT license, available at http://www.opensource.org/licenses/mit-license.php
+ *
+ * ARIA Support: Greta Krafsig
+ *
+ * Project: https://github.com/CodeSeven/toastr
+ */
+/* global define */
+; (function (define) {
+ define(['jquery'], function ($) {
+ return (function () {
+ var $container;
+ var listener;
+ var toastId = 0;
+ var toastType = {
+ error: 'error',
+ info: 'info',
+ success: 'success',
+ warning: 'warning'
+ };
+
+ var toastr = {
+ clear: clear,
+ remove: remove,
+ error: error,
+ getContainer: getContainer,
+ info: info,
+ options: {},
+ subscribe: subscribe,
+ success: success,
+ version: '2.1.1',
+ warning: warning
+ };
+
+ var previousToast;
+
+ return toastr;
+
+ ////////////////
+
+ function error(message, title, optionsOverride) {
+ return notify({
+ type: toastType.error,
+ iconClass: getOptions().iconClasses.error,
+ message: message,
+ optionsOverride: optionsOverride,
+ title: title
+ });
+ }
+
+ function getContainer(options, create) {
+ if (!options) { options = getOptions(); }
+ $container = $('#' + options.containerId);
+ if ($container.length) {
+ return $container;
+ }
+ if (create) {
+ $container = createContainer(options);
+ }
+ return $container;
+ }
+
+ function info(message, title, optionsOverride) {
+ return notify({
+ type: toastType.info,
+ iconClass: getOptions().iconClasses.info,
+ message: message,
+ optionsOverride: optionsOverride,
+ title: title
+ });
+ }
+
+ function subscribe(callback) {
+ listener = callback;
+ }
+
+ function success(message, title, optionsOverride) {
+ return notify({
+ type: toastType.success,
+ iconClass: getOptions().iconClasses.success,
+ message: message,
+ optionsOverride: optionsOverride,
+ title: title
+ });
+ }
+
+ function warning(message, title, optionsOverride) {
+ return notify({
+ type: toastType.warning,
+ iconClass: getOptions().iconClasses.warning,
+ message: message,
+ optionsOverride: optionsOverride,
+ title: title
+ });
+ }
+
+ function clear($toastElement, clearOptions) {
+ var options = getOptions();
+ if (!$container) { getContainer(options); }
+ if (!clearToast($toastElement, options, clearOptions)) {
+ clearContainer(options);
+ }
+ }
+
+ function remove($toastElement) {
+ var options = getOptions();
+ if (!$container) { getContainer(options); }
+ if ($toastElement && $(':focus', $toastElement).length === 0) {
+ removeToast($toastElement);
+ return;
+ }
+ if ($container.children().length) {
+ $container.remove();
+ }
+ }
+
+ // internal functions
+
+ function clearContainer (options) {
+ var toastsToClear = $container.children();
+ for (var i = toastsToClear.length - 1; i >= 0; i--) {
+ clearToast($(toastsToClear[i]), options);
+ }
+ }
+
+ function clearToast ($toastElement, options, clearOptions) {
+ var force = clearOptions && clearOptions.force ? clearOptions.force : false;
+ if ($toastElement && (force || $(':focus', $toastElement).length === 0)) {
+ $toastElement[options.hideMethod]({
+ duration: options.hideDuration,
+ easing: options.hideEasing,
+ complete: function () { removeToast($toastElement); }
+ });
+ return true;
+ }
+ return false;
+ }
+
+ function createContainer(options) {
+ $container = $('')
+ .attr('id', options.containerId)
+ .addClass(options.positionClass)
+ .attr('aria-live', 'polite')
+ .attr('role', 'alert');
+
+ $container.appendTo($(options.target));
+ return $container;
+ }
+
+ function getDefaults() {
+ return {
+ tapToDismiss: true,
+ toastClass: 'toast',
+ containerId: 'toast-container',
+ debug: false,
+
+ showMethod: 'fadeIn', //fadeIn, slideDown, and show are built into jQuery
+ showDuration: 300,
+ showEasing: 'swing', //swing and linear are built into jQuery
+ onShown: undefined,
+ hideMethod: 'fadeOut',
+ hideDuration: 1000,
+ hideEasing: 'swing',
+ onHidden: undefined,
+
+ extendedTimeOut: 1000,
+ iconClasses: {
+ error: 'toast-error',
+ info: 'toast-info',
+ success: 'toast-success',
+ warning: 'toast-warning'
+ },
+ iconClass: 'toast-info',
+ positionClass: 'toast-top-right',
+ timeOut: 5000, // Set timeOut and extendedTimeOut to 0 to make it sticky
+ titleClass: 'toast-title',
+ messageClass: 'toast-message',
+ target: 'body',
+ closeHtml: '',
+ newestOnTop: true,
+ preventDuplicates: false,
+ progressBar: false
+ };
+ }
+
+ function publish(args) {
+ if (!listener) { return; }
+ listener(args);
+ }
+
+ function notify(map) {
+ var options = getOptions();
+ var iconClass = map.iconClass || options.iconClass;
+
+ if (typeof (map.optionsOverride) !== 'undefined') {
+ options = $.extend(options, map.optionsOverride);
+ iconClass = map.optionsOverride.iconClass || iconClass;
+ }
+
+ if (shouldExit(options, map)) { return; }
+
+ toastId++;
+
+ $container = getContainer(options, true);
+
+ var intervalId = null;
+ var $toastElement = $('');
+ var $titleElement = $('');
+ var $messageElement = $('');
+ var $progressElement = $('');
+ var $closeElement = $(options.closeHtml);
+ var progressBar = {
+ intervalId: null,
+ hideEta: null,
+ maxHideTime: null
+ };
+ var response = {
+ toastId: toastId,
+ state: 'visible',
+ startTime: new Date(),
+ options: options,
+ map: map
+ };
+
+ personalizeToast();
+
+ displayToast();
+
+ handleEvents();
+
+ publish(response);
+
+ if (options.debug && console) {
+ console.log(response);
+ }
+
+ return $toastElement;
+
+ function personalizeToast() {
+ setIcon();
+ setTitle();
+ setMessage();
+ setCloseButton();
+ setProgressBar();
+ setSequence();
+ }
+
+ function handleEvents() {
+ $toastElement.hover(stickAround, delayedHideToast);
+ if (!options.onclick && options.tapToDismiss) {
+ $toastElement.click(hideToast);
+ }
+
+ if (options.closeButton && $closeElement) {
+ $closeElement.click(function (event) {
+ if (event.stopPropagation) {
+ event.stopPropagation();
+ } else if (event.cancelBubble !== undefined && event.cancelBubble !== true) {
+ event.cancelBubble = true;
+ }
+ hideToast(true);
+ });
+ }
+
+ if (options.onclick) {
+ $toastElement.click(function () {
+ options.onclick();
+ hideToast();
+ });
+ }
+ }
+
+ function displayToast() {
+ $toastElement.hide();
+
+ $toastElement[options.showMethod](
+ {duration: options.showDuration, easing: options.showEasing, complete: options.onShown}
+ );
+
+ if (options.timeOut > 0) {
+ intervalId = setTimeout(hideToast, options.timeOut);
+ progressBar.maxHideTime = parseFloat(options.timeOut);
+ progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime;
+ if (options.progressBar) {
+ progressBar.intervalId = setInterval(updateProgress, 10);
+ }
+ }
+ }
+
+ function setIcon() {
+ if (map.iconClass) {
+ $toastElement.addClass(options.toastClass).addClass(iconClass);
+ }
+ }
+
+ function setSequence() {
+ if (options.newestOnTop) {
+ $container.prepend($toastElement);
+ } else {
+ $container.append($toastElement);
+ }
+ }
+
+ function setTitle() {
+ if (map.title) {
+ $titleElement.append(map.title).addClass(options.titleClass);
+ $toastElement.append($titleElement);
+ }
+ }
+
+ function setMessage() {
+ if (map.message) {
+ $messageElement.append(map.message).addClass(options.messageClass);
+ $toastElement.append($messageElement);
+ }
+ }
+
+ function setCloseButton() {
+ if (options.closeButton) {
+ $closeElement.addClass('toast-close-button').attr('role', 'button');
+ $toastElement.prepend($closeElement);
+ }
+ }
+
+ function setProgressBar() {
+ if (options.progressBar) {
+ $progressElement.addClass('toast-progress');
+ $toastElement.prepend($progressElement);
+ }
+ }
+
+ function shouldExit(options, map) {
+ if (options.preventDuplicates) {
+ if (map.message === previousToast) {
+ return true;
+ } else {
+ previousToast = map.message;
+ }
+ }
+ return false;
+ }
+
+ function hideToast(override) {
+ if ($(':focus', $toastElement).length && !override) {
+ return;
+ }
+ clearTimeout(progressBar.intervalId);
+ return $toastElement[options.hideMethod]({
+ duration: options.hideDuration,
+ easing: options.hideEasing,
+ complete: function () {
+ removeToast($toastElement);
+ if (options.onHidden && response.state !== 'hidden') {
+ options.onHidden();
+ }
+ response.state = 'hidden';
+ response.endTime = new Date();
+ publish(response);
+ }
+ });
+ }
+
+ function delayedHideToast() {
+ if (options.timeOut > 0 || options.extendedTimeOut > 0) {
+ intervalId = setTimeout(hideToast, options.extendedTimeOut);
+ progressBar.maxHideTime = parseFloat(options.extendedTimeOut);
+ progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime;
+ }
+ }
+
+ function stickAround() {
+ clearTimeout(intervalId);
+ progressBar.hideEta = 0;
+ $toastElement.stop(true, true)[options.showMethod](
+ {duration: options.showDuration, easing: options.showEasing}
+ );
+ }
+
+ function updateProgress() {
+ var percentage = ((progressBar.hideEta - (new Date().getTime())) / progressBar.maxHideTime) * 100;
+ $progressElement.width(percentage + '%');
+ }
+ }
+
+ function getOptions() {
+ return $.extend({}, getDefaults(), toastr.options);
+ }
+
+ function removeToast($toastElement) {
+ if (!$container) { $container = getContainer(); }
+ if ($toastElement.is(':visible')) {
+ return;
+ }
+ $toastElement.remove();
+ $toastElement = null;
+ if ($container.children().length === 0) {
+ $container.remove();
+ previousToast = undefined;
+ }
+ }
+
+ })();
+ });
+}(typeof define === 'function' && define.amd ? define : function (deps, factory) {
+ if (typeof module !== 'undefined' && module.exports) { //Node
+ module.exports = factory(require('jquery'));
+ } else {
+ window['toastr'] = factory(window['jQuery']);
+ }
+}));