This is an automated email from the ASF dual-hosted git repository.

dhavalrajpara pushed a commit to branch ranger-2.6
in repository https://gitbox.apache.org/repos/asf/ranger.git


The following commit(s) were added to refs/heads/ranger-2.6 by this push:
     new 2004fe096 RANGER-4833 : Upgrade from Bootbox.js to Bootprompt.js
2004fe096 is described below

commit 2004fe096a38e8ffd4a739db8640afcd4d1d8b8a
Author: Dhaval.Rajpara <[email protected]>
AuthorDate: Mon Sep 9 14:59:33 2024 +0530

    RANGER-4833 : Upgrade from Bootbox.js to Bootprompt.js
    
    Signed-off-by: Dhaval.Rajpara <[email protected]>
---
 .../main/webapp/libs/bower/bootbox/js/bootbox.js   | 1246 --------------------
 .../webapp/libs/bower/bootprompt/bootprompt.js     | 1138 ++++++++++++++++++
 security-admin/src/main/webapp/scripts/Init.js     |    8 +-
 .../src/main/webapp/scripts/routers/Router.js      |   41 +-
 .../src/main/webapp/scripts/utils/XALangSupport.js |   57 -
 .../src/main/webapp/scripts/utils/XAUtils.js       |   26 +-
 .../views/permissions/ModulePermsTableLayout.js    |    1 -
 .../webapp/scripts/views/service/ServiceCreate.js  |   22 +-
 8 files changed, 1192 insertions(+), 1347 deletions(-)

diff --git a/security-admin/src/main/webapp/libs/bower/bootbox/js/bootbox.js 
b/security-admin/src/main/webapp/libs/bower/bootbox/js/bootbox.js
deleted file mode 100644
index e27cf404c..000000000
--- a/security-admin/src/main/webapp/libs/bower/bootbox/js/bootbox.js
+++ /dev/null
@@ -1,1246 +0,0 @@
-/*! @preserve
- * bootbox.js
- * version: 5.5.3
- * author: Nick Payne <[email protected]>
- * license: MIT
- * http://bootboxjs.com/
- */
-(function (root, factory) {
-  'use strict';
-  if (typeof define === 'function' && define.amd) {
-    // AMD
-    define(['jquery'], factory);
-  } else if (typeof exports === 'object') {
-    // Node, CommonJS-like
-    module.exports = factory(require('jquery'));
-  } else {
-    // Browser globals (root is window)
-    root.bootbox = factory(root.jQuery);
-  }
-}(this, function init($, undefined) {
-  'use strict';
-
-  //  Polyfills Object.keys, if necessary.
-  //  @see 
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
-  if (!Object.keys) {
-    Object.keys = (function () {
-      var hasOwnProperty = Object.prototype.hasOwnProperty,
-        hasDontEnumBug = !({ toString: null 
}).propertyIsEnumerable('toString'),
-        dontEnums = [
-          'toString',
-          'toLocaleString',
-          'valueOf',
-          'hasOwnProperty',
-          'isPrototypeOf',
-          'propertyIsEnumerable',
-          'constructor'
-        ],
-        dontEnumsLength = dontEnums.length;
-
-      return function (obj) {
-        if (typeof obj !== 'function' && (typeof obj !== 'object' || obj === 
null)) {
-          throw new TypeError('Object.keys called on non-object');
-        }
-
-        var result = [], prop, i;
-
-        for (prop in obj) {
-          if (hasOwnProperty.call(obj, prop)) {
-            result.push(prop);
-          }
-        }
-
-        if (hasDontEnumBug) {
-          for (i = 0; i < dontEnumsLength; i++) {
-            if (hasOwnProperty.call(obj, dontEnums[i])) {
-              result.push(dontEnums[i]);
-            }
-          }
-        }
-
-        return result;
-      };
-    }());
-  }
-
-  var exports = {};
-
-  var VERSION = '5.5.3';
-  exports.VERSION = VERSION;
-
-  var locales = {
-    en : {
-      OK      : 'OK',
-      CANCEL  : 'Cancel',
-      CONFIRM : 'OK'
-    }
-  };
-
-  var templates = {
-    dialog:
-    '<div class="bootbox modal" tabindex="-1" role="dialog" 
aria-hidden="true">' +
-    '<div class="modal-dialog">' +
-    '<div class="modal-content">' +
-    '<div class="modal-body"><div class="bootbox-body"></div></div>' +
-    '</div>' +
-    '</div>' +
-    '</div>',
-    header:
-    '<div class="modal-header">' +
-    '<h5 class="modal-title"></h5>' +
-    '</div>',
-    footer:
-    '<div class="modal-footer"></div>',
-    closeButton:
-    '<button type="button" class="bootbox-close-button close" 
aria-hidden="true">&times;</button>',
-    form:
-    '<form class="bootbox-form"></form>',
-    button:
-    '<button type="button" class="btn"></button>',
-    option:
-    '<option></option>',
-    promptMessage:
-    '<div class="bootbox-prompt-message"></div>',
-    inputs: {
-      text:
-      '<input class="bootbox-input bootbox-input-text form-control" 
autocomplete="off" type="text" />',
-      textarea:
-      '<textarea class="bootbox-input bootbox-input-textarea 
form-control"></textarea>',
-      email:
-      '<input class="bootbox-input bootbox-input-email form-control" 
autocomplete="off" type="email" />',
-      select:
-      '<select class="bootbox-input bootbox-input-select 
form-control"></select>',
-      checkbox:
-      '<div class="form-check checkbox"><label class="form-check-label"><input 
class="form-check-input bootbox-input bootbox-input-checkbox" type="checkbox" 
/></label></div>',
-      radio:
-      '<div class="form-check radio"><label class="form-check-label"><input 
class="form-check-input bootbox-input bootbox-input-radio" type="radio" 
name="bootbox-radio" /></label></div>',
-      date:
-      '<input class="bootbox-input bootbox-input-date form-control" 
autocomplete="off" type="date" />',
-      time:
-      '<input class="bootbox-input bootbox-input-time form-control" 
autocomplete="off" type="time" />',
-      number:
-      '<input class="bootbox-input bootbox-input-number form-control" 
autocomplete="off" type="number" />',
-      password:
-      '<input class="bootbox-input bootbox-input-password form-control" 
autocomplete="off" type="password" />',
-      range:
-      '<input class="bootbox-input bootbox-input-range form-control-range" 
autocomplete="off" type="range" />'
-    }
-  };
-
-
-  var defaults = {
-    // default language
-    locale: 'en',
-    // show backdrop or not. Default to static so user has to interact with 
dialog
-    backdrop: 'static',
-    // animate the modal in/out
-    animate: true,
-    // additional class string applied to the top level dialog
-    className: null,
-    // whether or not to include a close button
-    closeButton: true,
-    // show the dialog immediately by default
-    show: true,
-    // dialog container
-    container: 'body',
-    // default value (used by the prompt helper)
-    value: '',
-    // default input type (used by the prompt helper)
-    inputType: 'text',
-    // switch button order from cancel/confirm (default) to confirm/cancel
-    swapButtonOrder: false,
-    // center modal vertically in page
-    centerVertical: false,
-    // Append "multiple" property to the select when using the "prompt" helper
-    multiple: false,
-    // Automatically scroll modal content when height exceeds viewport height
-    scrollable: false,
-    // whether or not to destroy the modal on hide
-    reusable: false,
-    // the element that triggered the dialog opening
-    relatedTarget: null
-  };
-
-
-  // PUBLIC FUNCTIONS
-  // 
*************************************************************************************************************
-
-  // Return all currently registered locales, or a specific locale if "name" 
is defined
-  exports.locales = function (name) {
-    return name ? locales[name] : locales;
-  };
-
-
-  // Register localized strings for the OK, CONFIRM, and CANCEL buttons
-  exports.addLocale = function (name, values) {
-    $.each(['OK', 'CANCEL', 'CONFIRM'], function (_, v) {
-      if (!values[v]) {
-        throw new Error('Please supply a translation for "' + v + '"');
-      }
-    });
-
-    locales[name] = {
-      OK: values.OK,
-      CANCEL: values.CANCEL,
-      CONFIRM: values.CONFIRM
-    };
-
-    return exports;
-  };
-
-
-  // Remove a previously-registered locale
-  exports.removeLocale = function (name) {
-    if (name !== 'en') {
-      delete locales[name];
-    }
-    else {
-      throw new Error('"en" is used as the default and fallback locale and 
cannot be removed.');
-    }
-
-    return exports;
-  };
-
-
-  // Set the default locale
-  exports.setLocale = function (name) {
-    return exports.setDefaults('locale', name);
-  };
-
-
-  // Override default value(s) of Bootbox.
-  exports.setDefaults = function () {
-    var values = {};
-
-    if (arguments.length === 2) {
-      // allow passing of single key/value...
-      values[arguments[0]] = arguments[1];
-    } else {
-      // ... and as an object too
-      values = arguments[0];
-    }
-
-    $.extend(defaults, values);
-
-    return exports;
-  };
-
-
-  // Hides all currently active Bootbox modals
-  exports.hideAll = function () {
-    $('.bootbox').modal('hide');
-
-    return exports;
-  };
-
-
-  // Allows the base init() function to be overridden
-  exports.init = function (_$) {
-    return init(_$ || $);
-  };
-
-
-  // CORE HELPER FUNCTIONS
-  // 
*************************************************************************************************************
-
-  // Core dialog function
-  exports.dialog = function (options) {
-    if ($.fn.modal === undefined) {
-      throw new Error(
-        '"$.fn.modal" is not defined; please double check you have included ' +
-        'the Bootstrap JavaScript library. See 
https://getbootstrap.com/docs/4.4/getting-started/javascript/ ' +
-        'for more details.'
-      );
-    }
-
-    options = sanitize(options);
-
-    if ($.fn.modal.Constructor.VERSION) {
-      options.fullBootstrapVersion = $.fn.modal.Constructor.VERSION;
-      var i = options.fullBootstrapVersion.indexOf('.');
-      options.bootstrap = options.fullBootstrapVersion.substring(0, i);
-    }
-    else {
-      // Assuming version 2.3.2, as that was the last "supported" 2.x version
-      options.bootstrap = '2';
-      options.fullBootstrapVersion = '2.3.2';
-      console.warn('Bootbox will *mostly* work with Bootstrap 2, but we do not 
officially support it. Please upgrade, if possible.');
-    }
-
-    var dialog = $(templates.dialog);
-    var innerDialog = dialog.find('.modal-dialog');
-    var body = dialog.find('.modal-body');
-    var header = $(templates.header);
-    var footer = $(templates.footer);
-    var buttons = options.buttons;
-
-    var callbacks = {
-      onEscape: options.onEscape
-    };
-
-    body.find('.bootbox-body').html(options.message);
-
-    // Only attempt to create buttons if at least one has 
-    // been defined in the options object
-    if (getKeyLength(options.buttons) > 0) {
-      each(buttons, function (key, b) {
-        var button = $(templates.button);
-        button.data('bb-handler', key);
-        button.addClass(b.className);
-
-        switch (key) {
-          case 'ok':
-          case 'confirm':
-            button.addClass('bootbox-accept');
-            break;
-
-          case 'cancel':
-            button.addClass('bootbox-cancel');
-            break;
-        }
-
-        button.html(b.label);
-        footer.append(button);
-
-        callbacks[key] = b.callback;
-      });
-
-      body.after(footer);
-    }
-
-    if (options.animate === true) {
-      dialog.addClass('fade');
-    }
-
-    if (options.className) {
-      dialog.addClass(options.className);
-    }
-
-    if (options.size) {
-      // Requires Bootstrap 3.1.0 or higher
-      if (options.fullBootstrapVersion.substring(0, 3) < '3.1') {
-        console.warn('"size" requires Bootstrap 3.1.0 or higher. You appear to 
be using ' + options.fullBootstrapVersion + '. Please upgrade to use this 
option.');
-      }
-
-      switch (options.size) {
-        case 'small':
-        case 'sm':
-          innerDialog.addClass('modal-sm');
-          break;
-
-        case 'large':
-        case 'lg':
-          innerDialog.addClass('modal-lg');
-          break;
-
-        case 'extra-large':
-        case 'xl':
-          innerDialog.addClass('modal-xl');
-
-          // Requires Bootstrap 4.2.0 or higher
-          if (options.fullBootstrapVersion.substring(0, 3) < '4.2') {
-            console.warn('Using size "xl"/"extra-large" requires Bootstrap 
4.2.0 or higher. You appear to be using ' + options.fullBootstrapVersion + '. 
Please upgrade to use this option.');
-          }
-          break;
-      }
-    }
-
-    if (options.scrollable) {
-      innerDialog.addClass('modal-dialog-scrollable');
-
-      // Requires Bootstrap 4.3.0 or higher
-      if (options.fullBootstrapVersion.substring(0, 3) < '4.3') {
-        console.warn('Using "scrollable" requires Bootstrap 4.3.0 or higher. 
You appear to be using ' + options.fullBootstrapVersion + '. Please upgrade to 
use this option.');
-      }
-    }
-
-    if (options.title) {
-      body.before(header);
-      dialog.find('.modal-title').html(options.title);
-    }
-
-    if (options.closeButton) {
-      var closeButton = $(templates.closeButton);
-
-      if (options.title) {
-        if (options.bootstrap > 3) {
-          dialog.find('.modal-header').append(closeButton);
-        }
-        else {
-          dialog.find('.modal-header').prepend(closeButton);
-        }
-      } else {
-        closeButton.prependTo(body);
-      }
-    }
-
-    if (options.centerVertical) {
-      innerDialog.addClass('modal-dialog-centered');
-
-      // Requires Bootstrap 4.0.0-beta.3 or higher
-      if (options.fullBootstrapVersion < '4.0.0') {
-        console.warn('"centerVertical" requires Bootstrap 4.0.0-beta.3 or 
higher. You appear to be using ' + options.fullBootstrapVersion + '. Please 
upgrade to use this option.');
-      }
-    }
-
-    // Bootstrap event listeners; these handle extra
-    // setup & teardown required after the underlying
-    // modal has performed certain actions.
-
-    if(!options.reusable) {
-      // make sure we unbind any listeners once the dialog has definitively 
been dismissed
-      dialog.one('hide.bs.modal', { dialog: dialog }, unbindModal);
-    }
-
-    if (options.onHide) {
-      if ($.isFunction(options.onHide)) {
-        dialog.on('hide.bs.modal', options.onHide);
-      }
-      else {
-        throw new Error('Argument supplied to "onHide" must be a function');
-      }
-    }
-
-    if(!options.reusable) {
-      dialog.one('hidden.bs.modal', { dialog: dialog }, destroyModal);
-    }
-
-    if (options.onHidden) {
-      if ($.isFunction(options.onHidden)) {
-        dialog.on('hidden.bs.modal', options.onHidden);
-      }
-      else {
-        throw new Error('Argument supplied to "onHidden" must be a function');
-      }
-    }
-
-    if (options.onShow) {
-      if ($.isFunction(options.onShow)) {
-        dialog.on('show.bs.modal', options.onShow);
-      }
-      else {
-        throw new Error('Argument supplied to "onShow" must be a function');
-      }
-    }
-
-    dialog.one('shown.bs.modal', { dialog: dialog }, focusPrimaryButton);
-
-    if (options.onShown) {
-      if ($.isFunction(options.onShown)) {
-        dialog.on('shown.bs.modal', options.onShown);
-      }
-      else {
-        throw new Error('Argument supplied to "onShown" must be a function');
-      }
-    }
-
-    // Bootbox event listeners; used to decouple some
-    // behaviours from their respective triggers
-
-    if (options.backdrop === true) {
-      // A boolean true/false according to the Bootstrap docs
-      // should show a dialog the user can dismiss by clicking on
-      // the background.
-      // We always only ever pass static/false to the actual
-      // $.modal function because with "true" we can't trap
-      // this event (the .modal-backdrop swallows it)
-      // However, we still want to sort-of respect true
-      // and invoke the escape mechanism instead
-      dialog.on('click.dismiss.bs.modal', function (e) {
-        // @NOTE: the target varies in >= 3.3.x releases since the modal 
backdrop
-        // moved *inside* the outer dialog rather than *alongside* it
-        if (dialog.children('.modal-backdrop').length) {
-          e.currentTarget = dialog.children('.modal-backdrop').get(0);
-        }
-
-        if (e.target !== e.currentTarget) {
-          return;
-        }
-
-        dialog.trigger('escape.close.bb');
-      });
-    }
-
-    dialog.on('escape.close.bb', function (e) {
-      // the if statement looks redundant but it isn't; without it
-      // if we *didn't* have an onEscape handler then processCallback
-      // would automatically dismiss the dialog
-      if (callbacks.onEscape) {
-        processCallback(e, dialog, callbacks.onEscape);
-      }
-    });
-
-
-    dialog.on('click', '.modal-footer button:not(.disabled)', function (e) {
-      var callbackKey = $(this).data('bb-handler');
-
-      if (callbackKey !== undefined) {
-        // Only process callbacks for buttons we recognize:
-        processCallback(e, dialog, callbacks[callbackKey]);
-      }
-    });
-
-    dialog.on('click', '.bootbox-close-button', function (e) {
-      // onEscape might be falsy but that's fine; the fact is
-      // if the user has managed to click the close button we
-      // have to close the dialog, callback or not
-      processCallback(e, dialog, callbacks.onEscape);
-    });
-
-    dialog.on('keyup', function (e) {
-      if (e.which === 27) {
-        dialog.trigger('escape.close.bb');
-      }
-    });
-
-    // the remainder of this method simply deals with adding our
-    // dialog element to the DOM, augmenting it with Bootstrap's modal
-    // functionality and then giving the resulting object back
-    // to our caller
-
-    $(options.container).append(dialog);
-
-    dialog.modal({
-      backdrop: options.backdrop,
-      keyboard: false,
-      show: false
-    });
-
-    if (options.show) {
-      dialog.modal('show', options.relatedTarget);
-    }
-
-    return dialog;
-  };
-
-
-  // Helper function to simulate the native alert() behavior. **NOTE**: This 
is non-blocking, so any
-  // code that must happen after the alert is dismissed should be placed 
within the callback function 
-  // for this alert.
-  exports.alert = function () {
-    var options;
-
-    options = mergeDialogOptions('alert', ['ok'], ['message', 'callback'], 
arguments);
-
-    // @TODO: can this move inside exports.dialog when we're iterating over 
each
-    // button and checking its button.callback value instead?
-    if (options.callback && !$.isFunction(options.callback)) {
-      throw new Error('alert requires the "callback" property to be a function 
when provided');
-    }
-
-    // override the ok and escape callback to make sure they just invoke
-    // the single user-supplied one (if provided)
-    options.buttons.ok.callback = options.onEscape = function () {
-      if ($.isFunction(options.callback)) {
-        return options.callback.call(this);
-      }
-
-      return true;
-    };
-
-    return exports.dialog(options);
-  };
-
-
-  // Helper function to simulate the native confirm() behavior. **NOTE**: This 
is non-blocking, so any
-  // code that must happen after the confirm is dismissed should be placed 
within the callback function 
-  // for this confirm.
-  exports.confirm = function () {
-    var options;
-
-    options = mergeDialogOptions('confirm', ['cancel', 'confirm'], ['message', 
'callback'], arguments);
-
-    // confirm specific validation; they don't make sense without a callback 
so make
-    // sure it's present
-    if (!$.isFunction(options.callback)) {
-      throw new Error('confirm requires a callback');
-    }
-
-    // overrides; undo anything the user tried to set they shouldn't have
-    options.buttons.cancel.callback = options.onEscape = function () {
-      return options.callback.call(this, false);
-    };
-
-    options.buttons.confirm.callback = function () {
-      return options.callback.call(this, true);
-    };
-
-    return exports.dialog(options);
-  };
-
-
-  // Helper function to simulate the native prompt() behavior. **NOTE**: This 
is non-blocking, so any
-  // code that must happen after the prompt is dismissed should be placed 
within the callback function 
-  // for this prompt.
-  exports.prompt = function () {
-    var options;
-    var promptDialog;
-    var form;
-    var input;
-    var shouldShow;
-    var inputOptions;
-
-    // we have to create our form first otherwise
-    // its value is undefined when gearing up our options
-    // @TODO this could be solved by allowing message to
-    // be a function instead...
-    form = $(templates.form);
-
-    // prompt defaults are more complex than others in that
-    // users can override more defaults
-    options = mergeDialogOptions('prompt', ['cancel', 'confirm'], ['title', 
'callback'], arguments);
-
-    if (!options.value) {
-      options.value = defaults.value;
-    }
-
-    if (!options.inputType) {
-      options.inputType = defaults.inputType;
-    }
-
-    // capture the user's show value; we always set this to false before
-    // spawning the dialog to give us a chance to attach some handlers to
-    // it, but we need to make sure we respect a preference not to show it
-    shouldShow = (options.show === undefined) ? defaults.show : options.show;
-
-    // This is required prior to calling the dialog builder below - we need to 
-    // add an event handler just before the prompt is shown
-    options.show = false;
-
-    // Handles the 'cancel' action
-    options.buttons.cancel.callback = options.onEscape = function () {
-      return options.callback.call(this, null);
-    };
-
-    // Prompt submitted - extract the prompt value. This requires a bit of 
work, 
-    // given the different input types available.
-    options.buttons.confirm.callback = function () {
-      var value;
-
-      if (options.inputType === 'checkbox') {
-        value = input.find('input:checked').map(function () {
-          return $(this).val();
-        }).get();
-      } else if (options.inputType === 'radio') {
-        value = input.find('input:checked').val();
-      }
-      else {
-        if (input[0].checkValidity && !input[0].checkValidity()) {
-          // prevents button callback from being called
-          return false;
-        } else {
-          if (options.inputType === 'select' && options.multiple === true) {
-            value = input.find('option:selected').map(function () {
-              return $(this).val();
-            }).get();
-          }
-          else {
-            value = input.val();
-          }
-        }
-      }
-
-      return options.callback.call(this, value);
-    };
-
-    // prompt-specific validation
-    if (!options.title) {
-      throw new Error('prompt requires a title');
-    }
-
-    if (!$.isFunction(options.callback)) {
-      throw new Error('prompt requires a callback');
-    }
-
-    if (!templates.inputs[options.inputType]) {
-      throw new Error('Invalid prompt type');
-    }
-
-    // create the input based on the supplied type
-    input = $(templates.inputs[options.inputType]);
-
-    switch (options.inputType) {
-      case 'text':
-      case 'textarea':
-      case 'email':
-      case 'password':
-        input.val(options.value);
-
-        if (options.placeholder) {
-          input.attr('placeholder', options.placeholder);
-        }
-
-        if (options.pattern) {
-          input.attr('pattern', options.pattern);
-        }
-
-        if (options.maxlength) {
-          input.attr('maxlength', options.maxlength);
-        }
-
-        if (options.required) {
-          input.prop({ 'required': true });
-        }
-
-        if (options.rows && !isNaN(parseInt(options.rows))) {
-          if (options.inputType === 'textarea') {
-            input.attr({ 'rows': options.rows });
-          }
-        }
-
-        break;
-
-
-      case 'date':
-      case 'time':
-      case 'number':
-      case 'range':
-        input.val(options.value);
-
-        if (options.placeholder) {
-          input.attr('placeholder', options.placeholder);
-        }
-
-        if (options.pattern) {
-          input.attr('pattern', options.pattern);
-        }
-
-        if (options.required) {
-          input.prop({ 'required': true });
-        }
-
-        // These input types have extra attributes which affect their input 
validation.
-        // Warning: For most browsers, date inputs are buggy in their 
implementation of 'step', so 
-        // this attribute will have no effect. Therefore, we don't set the 
attribute for date inputs.
-        // @see 
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date#Setting_maximum_and_minimum_dates
-        if (options.inputType !== 'date') {
-          if (options.step) {
-            if (options.step === 'any' || (!isNaN(options.step) && 
parseFloat(options.step) > 0)) {
-              input.attr('step', options.step);
-            }
-            else {
-              throw new Error('"step" must be a valid positive number or the 
value "any". See 
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-step for 
more information.');
-            }
-          }
-        }
-
-        if (minAndMaxAreValid(options.inputType, options.min, options.max)) {
-          if (options.min !== undefined) {
-            input.attr('min', options.min);
-          }
-          if (options.max !== undefined) {
-            input.attr('max', options.max);
-          }
-        }
-
-        break;
-
-
-      case 'select':
-        var groups = {};
-        inputOptions = options.inputOptions || [];
-
-        if (!$.isArray(inputOptions)) {
-          throw new Error('Please pass an array of input options');
-        }
-
-        if (!inputOptions.length) {
-          throw new Error('prompt with "inputType" set to "select" requires at 
least one option');
-        }
-
-        // placeholder is not actually a valid attribute for select,
-        // but we'll allow it, assuming it might be used for a plugin
-        if (options.placeholder) {
-          input.attr('placeholder', options.placeholder);
-        }
-
-        if (options.required) {
-          input.prop({ 'required': true });
-        }
-
-        if (options.multiple) {
-          input.prop({ 'multiple': true });
-        }
-
-        each(inputOptions, function (_, option) {
-          // assume the element to attach to is the input...
-          var elem = input;
-
-          if (option.value === undefined || option.text === undefined) {
-            throw new Error('each option needs a "value" property and a "text" 
property');
-          }
-
-          // ... but override that element if this option sits in a group
-
-          if (option.group) {
-            // initialise group if necessary
-            if (!groups[option.group]) {
-              groups[option.group] = $('<optgroup />').attr('label', 
option.group);
-            }
-
-            elem = groups[option.group];
-          }
-
-          var o = $(templates.option);
-          o.attr('value', option.value).text(option.text);
-          elem.append(o);
-        });
-
-        each(groups, function (_, group) {
-          input.append(group);
-        });
-
-        // safe to set a select's value as per a normal input
-        input.val(options.value);
-
-        break;
-
-
-      case 'checkbox':
-        var checkboxValues = $.isArray(options.value) ? options.value : 
[options.value];
-        inputOptions = options.inputOptions || [];
-
-        if (!inputOptions.length) {
-          throw new Error('prompt with "inputType" set to "checkbox" requires 
at least one option');
-        }
-
-        // checkboxes have to nest within a containing element, so
-        // they break the rules a bit and we end up re-assigning
-        // our 'input' element to this container instead
-        input = $('<div class="bootbox-checkbox-list"></div>');
-
-        each(inputOptions, function (_, option) {
-          if (option.value === undefined || option.text === undefined) {
-            throw new Error('each option needs a "value" property and a "text" 
property');
-          }
-
-          var checkbox = $(templates.inputs[options.inputType]);
-
-          checkbox.find('input').attr('value', option.value);
-          checkbox.find('label').append('\n' + option.text);
-
-          // we've ensured values is an array so we can always iterate over it
-          each(checkboxValues, function (_, value) {
-            if (value === option.value) {
-              checkbox.find('input').prop('checked', true);
-            }
-          });
-
-          input.append(checkbox);
-        });
-        break;
-
-
-      case 'radio':
-        // Make sure that value is not an array (only a single radio can ever 
be checked)
-        if (options.value !== undefined && $.isArray(options.value)) {
-          throw new Error('prompt with "inputType" set to "radio" requires a 
single, non-array value for "value"');
-        }
-
-        inputOptions = options.inputOptions || [];
-
-        if (!inputOptions.length) {
-          throw new Error('prompt with "inputType" set to "radio" requires at 
least one option');
-        }
-
-        // Radiobuttons have to nest within a containing element, so
-        // they break the rules a bit and we end up re-assigning
-        // our 'input' element to this container instead
-        input = $('<div class="bootbox-radiobutton-list"></div>');
-
-        // Radiobuttons should always have an initial checked input checked in 
a "group".
-        // If value is undefined or doesn't match an input option, select the 
first radiobutton
-        var checkFirstRadio = true;
-
-        each(inputOptions, function (_, option) {
-          if (option.value === undefined || option.text === undefined) {
-            throw new Error('each option needs a "value" property and a "text" 
property');
-          }
-
-          var radio = $(templates.inputs[options.inputType]);
-
-          radio.find('input').attr('value', option.value);
-          radio.find('label').append('\n' + option.text);
-
-          if (options.value !== undefined) {
-            if (option.value === options.value) {
-              radio.find('input').prop('checked', true);
-              checkFirstRadio = false;
-            }
-          }
-
-          input.append(radio);
-        });
-
-        if (checkFirstRadio) {
-          input.find('input[type="radio"]').first().prop('checked', true);
-        }
-        break;
-    }
-
-    // now place it in our form
-    form.append(input);
-
-    form.on('submit', function (e) {
-      e.preventDefault();
-      // Fix for SammyJS (or similar JS routing library) hijacking the form 
post.
-      e.stopPropagation();
-
-      // @TODO can we actually click *the* button object instead?
-      // e.g. buttons.confirm.click() or similar
-      promptDialog.find('.bootbox-accept').trigger('click');
-    });
-
-    if ($.trim(options.message) !== '') {
-      // Add the form to whatever content the user may have added.
-      var message = $(templates.promptMessage).html(options.message);
-      form.prepend(message);
-      options.message = form;
-    }
-    else {
-      options.message = form;
-    }
-
-    // Generate the dialog
-    promptDialog = exports.dialog(options);
-
-    // clear the existing handler focusing the submit button...
-    promptDialog.off('shown.bs.modal', focusPrimaryButton);
-
-    // ...and replace it with one focusing our input, if possible
-    promptDialog.on('shown.bs.modal', function () {
-      // need the closure here since input isn't
-      // an object otherwise
-      input.focus();
-    });
-
-    if (shouldShow === true) {
-      promptDialog.modal('show');
-    }
-
-    return promptDialog;
-  };
-
-
-  // INTERNAL FUNCTIONS
-  // 
*************************************************************************************************************
-
-  // Map a flexible set of arguments into a single returned object
-  // If args.length is already one just return it, otherwise
-  // use the properties argument to map the unnamed args to
-  // object properties.
-  // So in the latter case:
-  //  mapArguments(["foo", $.noop], ["message", "callback"])
-  //  -> { message: "foo", callback: $.noop }
-  function mapArguments(args, properties) {
-    var argn = args.length;
-    var options = {};
-
-    if (argn < 1 || argn > 2) {
-      throw new Error('Invalid argument length');
-    }
-
-    if (argn === 2 || typeof args[0] === 'string') {
-      options[properties[0]] = args[0];
-      options[properties[1]] = args[1];
-    } else {
-      options = args[0];
-    }
-
-    return options;
-  }
-
-
-  //  Merge a set of default dialog options with user supplied arguments
-  function mergeArguments(defaults, args, properties) {
-    return $.extend(
-      // deep merge
-      true,
-      // ensure the target is an empty, unreferenced object
-      {},
-      // the base options object for this type of dialog (often just buttons)
-      defaults,
-      // args could be an object or array; if it's an array properties will
-      // map it to a proper options object
-      mapArguments(
-        args,
-        properties
-      )
-    );
-  }
-
-
-  //  This entry-level method makes heavy use of composition to take a simple
-  //  range of inputs and return valid options suitable for passing to 
bootbox.dialog
-  function mergeDialogOptions(className, labels, properties, args) {
-    var locale;
-    if (args && args[0]) {
-      locale = args[0].locale || defaults.locale;
-      var swapButtons = args[0].swapButtonOrder || defaults.swapButtonOrder;
-
-      if (swapButtons) {
-        labels = labels.reverse();
-      }
-    }
-
-    //  build up a base set of dialog properties
-    var baseOptions = {
-      className: 'bootbox-' + className,
-      buttons: createLabels(labels, locale)
-    };
-
-    // Ensure the buttons properties generated, *after* merging
-    // with user args are still valid against the supplied labels
-    return validateButtons(
-      // merge the generated base properties with user supplied arguments
-      mergeArguments(
-        baseOptions,
-        args,
-        // if args.length > 1, properties specify how each arg maps to an 
object key
-        properties
-      ),
-      labels
-    );
-  }
-
-
-  //  Checks each button object to see if key is valid. 
-  //  This function will only be called by the alert, confirm, and prompt 
helpers. 
-  function validateButtons(options, buttons) {
-    var allowedButtons = {};
-    each(buttons, function (key, value) {
-      allowedButtons[value] = true;
-    });
-
-    each(options.buttons, function (key) {
-      if (allowedButtons[key] === undefined) {
-        throw new Error('button key "' + key + '" is not allowed (options are 
' + buttons.join(' ') + ')');
-      }
-    });
-
-    return options;
-  }
-
-
-
-  //  From a given list of arguments, return a suitable object of button 
labels.
-  //  All this does is normalise the given labels and translate them where 
possible.
-  //  e.g. "ok", "confirm" -> { ok: "OK", cancel: "Annuleren" }
-  function createLabels(labels, locale) {
-    var buttons = {};
-
-    for (var i = 0, j = labels.length; i < j; i++) {
-      var argument = labels[i];
-      var key = argument.toLowerCase();
-      var value = argument.toUpperCase();
-
-      buttons[key] = {
-        label: getText(value, locale)
-      };
-    }
-
-    return buttons;
-  }
-
-
-
-  //  Get localized text from a locale. Defaults to 'en' locale if no locale 
-  //  provided or a non-registered locale is requested
-  function getText(key, locale) {
-    var labels = locales[locale];
-
-    return labels ? labels[key] : locales.en[key];
-  }
-
-
-
-  //  Filter and tidy up any user supplied parameters to this dialog.
-  //  Also looks for any shorthands used and ensures that the options
-  //  which are returned are all normalized properly
-  function sanitize(options) {
-    var buttons;
-    var total;
-
-    if (typeof options !== 'object') {
-      throw new Error('Please supply an object of options');
-    }
-
-    if (!options.message) {
-      throw new Error('"message" option must not be null or an empty string.');
-    }
-
-    // make sure any supplied options take precedence over defaults
-    options = $.extend({}, defaults, options);
-
-    //make sure backdrop is either true, false, or 'static'
-    if (!options.backdrop) {
-      options.backdrop = (options.backdrop === false || options.backdrop === 
0) ? false : 'static';
-    } else {
-      options.backdrop = typeof options.backdrop === 'string' && 
options.backdrop.toLowerCase() === 'static' ? 'static' : true;
-    } 
-
-    // no buttons is still a valid dialog but it's cleaner to always have
-    // a buttons object to iterate over, even if it's empty
-    if (!options.buttons) {
-      options.buttons = {};
-    }
-    
-    buttons = options.buttons;
-
-    total = getKeyLength(buttons);
-
-    each(buttons, function (key, button, index) {
-      if ($.isFunction(button)) {
-        // short form, assume value is our callback. Since button
-        // isn't an object it isn't a reference either so re-assign it
-        button = buttons[key] = {
-          callback: button
-        };
-      }
-
-      // before any further checks make sure by now button is the correct type
-      if ($.type(button) !== 'object') {
-        throw new Error('button with key "' + key + '" must be an object');
-      }
-
-      if (!button.label) {
-        // the lack of an explicit label means we'll assume the key is good 
enough
-        button.label = key;
-      }
-
-      if (!button.className) {
-        var isPrimary = false;
-        if (options.swapButtonOrder) {
-          isPrimary = index === 0;
-        }
-        else {
-          isPrimary = index === total - 1;
-        }
-
-        if (total <= 2 && isPrimary) {
-          // always add a primary to the main option in a one or two-button 
dialog
-          button.className = 'btn-primary';
-        } else {
-          // adding both classes allows us to target both BS3 and BS4 without 
needing to check the version
-          button.className = 'btn-secondary btn-default';
-        }
-      }
-    });
-
-    return options;
-  }
-
-
-  //  Returns a count of the properties defined on the object
-  function getKeyLength(obj) {
-    return Object.keys(obj).length;
-  }
-
-
-  //  Tiny wrapper function around jQuery.each; just adds index as the third 
parameter
-  function each(collection, iterator) {
-    var index = 0;
-    $.each(collection, function (key, value) {
-      iterator(key, value, index++);
-    });
-  }
-
-
-  function focusPrimaryButton(e) {
-    e.data.dialog.find('.bootbox-accept').first().trigger('focus');
-  }
-
-
-  function destroyModal(e) {
-    // ensure we don't accidentally intercept hidden events triggered
-    // by children of the current dialog. We shouldn't need to handle this 
anymore, 
-    // now that Bootstrap namespaces its events, but still worth doing.
-    if (e.target === e.data.dialog[0]) {
-      e.data.dialog.remove();
-    }
-  }
-
-
-  function unbindModal(e) {
-    if (e.target === e.data.dialog[0]) {
-      e.data.dialog.off('escape.close.bb');
-      e.data.dialog.off('click');
-    }
-  }
-
-
-  //  Handle the invoked dialog callback
-  function processCallback(e, dialog, callback) {
-    e.stopPropagation();
-    e.preventDefault();
-
-    // by default we assume a callback will get rid of the dialog,
-    // although it is given the opportunity to override this
-
-    // so, if the callback can be invoked and it *explicitly returns false*
-    // then we'll set a flag to keep the dialog active...
-    var preserveDialog = $.isFunction(callback) && callback.call(dialog, e) 
=== false;
-
-    // ... otherwise we'll bin it
-    if (!preserveDialog) {
-      dialog.modal('hide');
-    }
-  }
-
-  // Validate `min` and `max` values based on the current `inputType` value
-  function minAndMaxAreValid(type, min, max) {
-    var result = false;
-    var minValid = true;
-    var maxValid = true;
-
-    if (type === 'date') {
-      if (min !== undefined && !(minValid = dateIsValid(min))) {
-        console.warn('Browsers which natively support the "date" input type 
expect date values to be of the form "YYYY-MM-DD" (see ISO-8601 
https://www.iso.org/iso-8601-date-and-time-format.html). Bootbox does not 
enforce this rule, but your min value may not be enforced by this browser.');
-      }
-      else if (max !== undefined && !(maxValid = dateIsValid(max))) {
-        console.warn('Browsers which natively support the "date" input type 
expect date values to be of the form "YYYY-MM-DD" (see ISO-8601 
https://www.iso.org/iso-8601-date-and-time-format.html). Bootbox does not 
enforce this rule, but your max value may not be enforced by this browser.');
-      }
-    }
-    else if (type === 'time') {
-      if (min !== undefined && !(minValid = timeIsValid(min))) {
-        throw new Error('"min" is not a valid time. See 
https://www.w3.org/TR/2012/WD-html-markup-20120315/datatypes.html#form.data.time
 for more information.');
-      }
-      else if (max !== undefined && !(maxValid = timeIsValid(max))) {
-        throw new Error('"max" is not a valid time. See 
https://www.w3.org/TR/2012/WD-html-markup-20120315/datatypes.html#form.data.time
 for more information.');
-      }
-    }
-    else {
-      if (min !== undefined && isNaN(min)) {
-        minValid = false;
-        throw new Error('"min" must be a valid number. See 
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-min for 
more information.');
-      }
-
-      if (max !== undefined && isNaN(max)) {
-        maxValid = false;
-        throw new Error('"max" must be a valid number. See 
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-max for 
more information.');
-      }
-    }
-
-    if (minValid && maxValid) {
-      if (max <= min) {
-        throw new Error('"max" must be greater than "min". See 
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-max for 
more information.');
-      }
-      else {
-        result = true;
-      }
-    }
-
-    return result;
-  }
-
-  function timeIsValid(value) {
-    return /([01][0-9]|2[0-3]):[0-5][0-9]?:[0-5][0-9]/.test(value);
-  }
-
-  function dateIsValid(value) {
-    return /(\d{4})-(\d{2})-(\d{2})/.test(value);
-  }
-
-  //  The Bootbox object
-  return exports;
-}));
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/libs/bower/bootprompt/bootprompt.js 
b/security-admin/src/main/webapp/libs/bower/bootprompt/bootprompt.js
new file mode 100644
index 000000000..a9e923ef5
--- /dev/null
+++ b/security-admin/src/main/webapp/libs/bower/bootprompt/bootprompt.js
@@ -0,0 +1,1138 @@
+/**
+     * bootprompt.js
+     * license: MIT
+     * http://github.com/lddubeau/bootprompt
+     * [email protected]
+*/
+
+
+(function (global, factory) {
+    typeof exports === 'object' && typeof module !== 'undefined' ? 
factory(exports, require('bootstrap'), require('jquery')) :
+    typeof define === 'function' && define.amd ? define(['exports', 
'bootstrap', 'jquery'], factory) :
+    (global = global || self, factory(global.bootprompt = {}, null, global.$));
+}(this, function (exports, bootstrap, $) { 'use strict';
+
+    $ = $ && $.hasOwnProperty('default') ? $['default'] : $;
+
+    var __assign = (undefined && undefined.__assign) || function () {
+        __assign = Object.assign || function(t) {
+            for (var s, i = 1, n = arguments.length; i < n; i++) {
+                s = arguments[i];
+                for (var p in s) if (Object.prototype.hasOwnProperty.call(s, 
p))
+                    t[p] = s[p];
+            }
+            return t;
+        };
+        return __assign.apply(this, arguments);
+    };
+    var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, 
_arguments, P, generator) {
+        return new (P || (P = Promise))(function (resolve, reject) {
+            function fulfilled(value) { try { step(generator.next(value)); } 
catch (e) { reject(e); } }
+            function rejected(value) { try { step(generator["throw"](value)); 
} catch (e) { reject(e); } }
+            function step(result) { result.done ? resolve(result.value) : new 
P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
+            step((generator = generator.apply(thisArg, _arguments || 
[])).next());
+        });
+    };
+    var __generator = (undefined && undefined.__generator) || function 
(thisArg, body) {
+        var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; 
return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+        return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, 
typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; 
}), g;
+        function verb(n) { return function (v) { return step([n, v]); }; }
+        function step(op) {
+            if (f) throw new TypeError("Generator is already executing.");
+            while (_) try {
+                if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? 
y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, 
op[1])).done) return t;
+                if (y = 0, t) op = [op[0] & 2, t.value];
+                switch (op[0]) {
+                    case 0: case 1: t = op; break;
+                    case 4: _.label++; return { value: op[1], done: false };
+                    case 5: _.label++; y = op[1]; op = [0]; continue;
+                    case 7: op = _.ops.pop(); _.trys.pop(); continue;
+                    default:
+                        if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) 
&& (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+                        if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < 
t[3]))) { _.label = op[1]; break; }
+                        if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t 
= op; break; }
+                        if (t && _.label < t[2]) { _.label = t[2]; 
_.ops.push(op); break; }
+                        if (t[2]) _.ops.pop();
+                        _.trys.pop(); continue;
+                }
+                op = body.call(thisArg, _);
+            } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+            if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 
0, done: true };
+        }
+    };
+    var __values = (undefined && undefined.__values) || function (o) {
+        var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
+        if (m) return m.call(o);
+        return {
+            next: function () {
+                if (o && i >= o.length) o = void 0;
+                return { value: o && o[i++], done: !o };
+            }
+        };
+    };
+    // We use this to keep versync happy.
+    var version = "6.0.2";
+    // But export this.
+    /** Bootprompt's version */
+    var VERSION = version;
+    var LOCALE_FIELDS = ["OK", "CANCEL", "CONFIRM"];
+    var definedLocales = Object.create(null);
+    var templates = {
+        dialog: "<div class=\"bootprompt modal\" tabindex=\"-1\" 
role=\"dialog\" aria-hidden=\"true\"> <div class=\"modal-dialog\">  <div 
class=\"modal-content\">   <div class=\"modal-body\"><div 
class=\"bootprompt-body\"></div></div>  </div> </div></div>",
+        header: "<div class=\"modal-header\"> <h5 
class=\"modal-title\"></h5></div>",
+        footer: "<div class=\"modal-footer\"></div>",
+        closeButton: "\n<button type=\"button\" 
class=\"bootprompt-close-button close\" aria-hidden=\"true\">&times;</button>",
+        form: "<form class=\"bootprompt-form\"></form>",
+        button: "<button type=\"button\" class=\"btn\"></button>",
+        option: "<option></option>",
+        promptMessage: "<div class=\"bootprompt-prompt-message\"></div>",
+        inputs: {
+            text: "<input class=\"bootprompt-input bootprompt-input-text 
form-control\" autocomplete=\"off\" type=\"text\" />",
+            textarea: "<textarea class=\"bootprompt-input 
bootprompt-input-textarea form-control\"></textarea>",
+            email: "<input class=\"bootprompt-input bootprompt-input-email 
form-control\" autocomplete=\"off\" type=\"email\" />",
+            select: "<select class=\"bootprompt-input bootprompt-input-select 
form-control\"></select>",
+            checkbox: "<div class=\"form-check checkbox\"><label 
class=\"form-check-label\"> <input class=\"form-check-input bootprompt-input 
bootprompt-input-checkbox\"\n        type=\"checkbox\" /></label></div>",
+            radio: "<div class=\"form-check radio\"><label 
class=\"form-check-label\"><input class=\"form-check-input bootprompt-input 
bootprompt-input-radio\"        type=\"radio\" name=\"bootprompt-radio\" 
/></label></div>",
+            date: "<input class=\"bootprompt-input bootprompt-input-date 
form-control\" autocomplete=\"off\" type=\"date\" />",
+            time: "<input class=\"bootprompt-input bootprompt-input-time 
form-control\" autocomplete=\"off\" type=\"time\" />",
+            number: "<input class=\"bootprompt-input bootprompt-input-number 
form-control\"        autocomplete=\"off\" type=\"number\" />",
+            password: "<input class=\"bootprompt-input 
bootprompt-input-password form-control\" autocomplete=\"off\" type=\"password\" 
/>",
+            range: "<input class=\"bootprompt-input bootprompt-input-range 
form-control-range\"\nautocomplete=\"off\" type=\"range\" />",
+        },
+    };
+    var currentLocale = "en";
+    var animate = true;
+    function locales(name) {
+        return name !== undefined ? definedLocales[name] : definedLocales;
+    }
+    /**
+     * Register a locale.
+     *
+     * @param name The name of the locale.
+     *
+     * @param values The locale specification, which determines how to 
translate
+     * each field.
+     *
+     * @throws {Error} If a field is missing from ``values``.
+     */
+    function addLocale(name, values) {
+        var e_1, _a;
+        try {
+            for (var LOCALE_FIELDS_1 = __values(LOCALE_FIELDS), 
LOCALE_FIELDS_1_1 = LOCALE_FIELDS_1.next(); !LOCALE_FIELDS_1_1.done; 
LOCALE_FIELDS_1_1 = LOCALE_FIELDS_1.next()) {
+                var field = LOCALE_FIELDS_1_1.value;
+                if (typeof values[field] !== "string") {
+                    throw new Error("Please supply a translation for \"" + 
field + "\"");
+                }
+            }
+        }
+        catch (e_1_1) { e_1 = { error: e_1_1 }; }
+        finally {
+            try {
+                if (LOCALE_FIELDS_1_1 && !LOCALE_FIELDS_1_1.done && (_a = 
LOCALE_FIELDS_1.return)) _a.call(LOCALE_FIELDS_1);
+            }
+            finally { if (e_1) throw e_1.error; }
+        }
+        definedLocales[name] = values;
+    }
+    /**
+     * Remove a locale. Removing an unknown locale is a no-op.
+     *
+     * @param name The name of the locale.
+     *
+     * @throws {Error} If ``name`` is ``"en"``. This locale cannot be removed.
+     */
+    function removeLocale(name) {
+        if (name !== "en") {
+            delete definedLocales[name];
+        }
+        else {
+            throw new Error("\"en\" is used as the default and fallback locale 
and cannot be removed.");
+        }
+    }
+    /**
+     * Set the default locale. Note that this function does not check whether 
the
+     * locale is known.
+     */
+    function setLocale(name) {
+        currentLocale = name;
+    }
+    /**
+     * Set the ``animate`` flag. When the flag is on, the modals produced by 
this
+     * library are animated. When off, they are not animated.
+     *
+     * **NOTE**: The reason this function exists is to be able to turn off
+     * animations during testing. Having the animations turned on can turn 
simple
+     * tests into complicated afairs because it takes a while for a modal to 
show
+     * up or be removed. We do not recommend using this function in production.
+     */
+    function setAnimate(value) {
+        animate = value;
+    }
+    /**
+     * Hide all modals created with bootprompt.
+     */
+    function hideAll() {
+        $(".bootprompt").modal("hide");
+    }
+    //
+    // CORE HELPER FUNCTIONS
+    //
+    // tslint:disable-next-line:no-any
+    var fnModal = $.fn.modal;
+    /* istanbul ignore if: we do not test with incorrect environments. */
+    if (fnModal === undefined) {
+        throw new Error("\"$.fn.modal\" is not defined; please double check 
you have included the Bootstrap JavaScript library. See 
http://getbootstrap.com/javascript/ for more details.");
+    }
+    /* istanbul ignore if: we do not test with incorrect environments. */
+    if (!fnModal.Constructor.VERSION) {
+        throw new Error("Bootprompt cannot determine the version of Bootstrap 
used");
+    }
+    var fullBootstrapVersion = fnModal.Constructor.VERSION;
+    var bootstrapVersion = Number(fullBootstrapVersion.substring(0, 
fullBootstrapVersion.indexOf(".")));
+    /* istanbul ignore if: we do not test with incorrect environments. */
+    if (bootstrapVersion < 3) {
+        throw new Error("Bootprompt does not work with Bootstrap 2 and 
lower.");
+    }
+    /**
+     * This is a general-purpose function allowing to create custom dialogs.
+     *
+     * @param options The options that govern how the dialog is created.
+     *
+     * @returns The jQuery object which models the dialog.
+     */
+    // tslint:disable-next-line:max-func-body-length cyclomatic-complexity
+    function dialog(options) {
+        var e_2, _a, e_3, _b;
+        var finalOptions = sanitize(options);
+        var $modal = $(templates.dialog);
+        var modal = $modal[0];
+        var innerDialog = modal.getElementsByClassName("modal-dialog")[0];
+        var body = modal.getElementsByClassName("modal-body")[0];
+        var footer = $(templates.footer)[0];
+        var callbacks = {
+            onEscape: finalOptions.onEscape,
+            onClose: finalOptions.onClose,
+        };
+        if (callbacks.onEscape === undefined) {
+            callbacks.onEscape = true;
+        }
+        var buttons = finalOptions.buttons, backdrop = finalOptions.backdrop, 
className = finalOptions.className, closeButton = finalOptions.closeButton, 
message = finalOptions.message, size = finalOptions.size, title = 
finalOptions.title;
+        // tslint:disable-next-line:no-non-null-assertion
+        var bpBody = body.getElementsByClassName("bootprompt-body")[0];
+        if (typeof message === "string") {
+            // tslint:disable-next-line:no-inner-html
+            bpBody.innerHTML = message;
+        }
+        else {
+            // tslint:disable-next-line:no-inner-html
+            bpBody.innerHTML = "";
+            $(bpBody).append(message);
+        }
+        var hadButtons = false;
+        // tslint:disable-next-line:forin
+        for (var key in buttons) {
+            hadButtons = true;
+            var b = buttons[key];
+            var $button = $(templates.button);
+            var button = $button[0];
+            $button.data("bp-handler", key);
+            try {
+                // On IE10/11 it is not possible to just do x.classList.add(a, 
b, c).
+                for (var _c = __values(b.className.split(" ")), _d = 
_c.next(); !_d.done; _d = _c.next()) {
+                    var cl = _d.value;
+                    button.classList.add(cl);
+                }
+            }
+            catch (e_2_1) { e_2 = { error: e_2_1 }; }
+            finally {
+                try {
+                    if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
+                }
+                finally { if (e_2) throw e_2.error; }
+            }
+            switch (key) {
+                case "ok":
+                case "confirm":
+                    button.classList.add("bootprompt-accept");
+                    break;
+                case "cancel":
+                    button.classList.add("bootprompt-cancel");
+                    break;
+                default:
+            }
+            // tslint:disable-next-line:no-inner-html
+            button.innerHTML = b.label;
+            footer.appendChild(button);
+            callbacks[key] = b.callback;
+        }
+        // Only attempt to create buttons if at least one has been defined in 
the
+        // options object.
+        if (hadButtons) {
+            // tslint:disable-next-line:no-non-null-assertion
+            body.parentNode.insertBefore(footer, body.nextSibling);
+        }
+        if (finalOptions.animate === true) {
+            modal.classList.add("fade");
+        }
+        if (className !== undefined) {
+            try {
+                // On IE10/11 it is not possible to just do x.classList.add(a, 
b, c).
+                for (var _e = __values(className.split(" ")), _f = _e.next(); 
!_f.done; _f = _e.next()) {
+                    var cl = _f.value;
+                    modal.classList.add(cl);
+                }
+            }
+            catch (e_3_1) { e_3 = { error: e_3_1 }; }
+            finally {
+                try {
+                    if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
+                }
+                finally { if (e_3) throw e_3.error; }
+            }
+        }
+        if (size !== undefined) {
+            // Requires Bootstrap 3.1.0 or higher
+            /* istanbul ignore if: we don't systematically test with old 
versions */
+            if (fullBootstrapVersion.substring(0, 3) < "3.1") {
+                // tslint:disable-next-line:no-console
+                console.warn("\"size\" requires Bootstrap 3.1.0 or higher. You 
appear to be using " + fullBootstrapVersion + ". Please upgrade to use this 
option.");
+            }
+            switch (size) {
+                case "large":
+                    innerDialog.classList.add("modal-lg");
+                    break;
+                case "small":
+                    innerDialog.classList.add("modal-sm");
+                    break;
+                default:
+                    var q = size;
+                    throw new Error("unknown size value: " + q);
+            }
+        }
+        if (title !== undefined) {
+            // tslint:disable-next-line:no-non-null-assertion
+            body.parentNode.insertBefore($(templates.header)[0], body);
+            var modalTitle = modal.getElementsByClassName("modal-title")[0];
+            if (typeof title === "string") {
+                // tslint:disable-next-line:no-inner-html
+                modalTitle.innerHTML = title;
+            }
+            else {
+                // tslint:disable-next-line:no-inner-html
+                modalTitle.innerHTML = "";
+                $(modalTitle).append(title);
+            }
+        }
+        if (closeButton === true) {
+            var closeButtonEl = $(templates.closeButton)[0];
+            if (title !== undefined) {
+                var modalHeader = 
modal.getElementsByClassName("modal-header")[0];
+                /* istanbul ignore else: we don't systematically test on old 
versions */
+                if (bootstrapVersion > 3) {
+                    modalHeader.appendChild(closeButtonEl);
+                }
+                else {
+                    modalHeader.insertBefore(closeButtonEl, 
modalHeader.firstChild);
+                }
+            }
+            else {
+                body.insertBefore(closeButtonEl, body.firstChild);
+            }
+        }
+        if (finalOptions.centerVertical !== undefined) {
+            // Requires Bootstrap 4.0.0 or higher
+            /* istanbul ignore if: we don't systematically test with old 
versions */
+            if (fullBootstrapVersion < "4.0.0") {
+                // tslint:disable-next-line:no-console
+                console.warn("\"centerVertical\" requires Bootstrap 4.0.0 or 
higher. You appear to be using " + fullBootstrapVersion + ". Please upgrade to 
use this option.");
+            }
+            innerDialog.classList.add("modal-dialog-centered");
+        }
+        // Bootstrap event listeners; these handle extra setup & teardown 
required
+        // after the underlying modal has performed certain actions.
+        $modal.one("hidden.bs.modal", function () {
+            $modal.off("escape.close.bp");
+            $modal.off("click");
+            $modal.remove();
+        });
+        $modal.one("shown.bs.modal", function () {
+            // tslint:disable-next-line:no-non-null-assertion
+            $(modal.querySelector(".btn-primary")).trigger("focus");
+        });
+        // Bootprompt event listeners; used to decouple some
+        // behaviours from their respective triggers
+        if (backdrop !== "static") {
+            // A boolean true/false according to the Bootstrap docs
+            // should show a dialog the user can dismiss by clicking on
+            // the background.
+            // We always only ever pass static/false to the actual
+            // $.modal function because with "true" we can't trap
+            // this event (the .modal-backdrop swallows it)
+            // However, we still want to sort of respect true
+            // and invoke the escape mechanism instead
+            $modal.on("click.dismiss.bs.modal", function (e) {
+                // The target varies in 3.3.x releases since the modal 
backdrop moved
+                // *inside* the outer dialog rather than *alongside* it
+                var backdrops = modal.getElementsByClassName("modal-backdrop");
+                var target = backdrops.length !== 0 ?
+                    /* istanbul ignore next: we don't systematically test with 
3.3.x */
+                    backdrops[0] :
+                    e.currentTarget;
+                if (e.target !== target) {
+                    return;
+                }
+                $modal.trigger("escape.close.bp");
+            });
+        }
+        $modal.on("escape.close.bp", function (e) {
+            // the if statement looks redundant but it isn't; without it
+            // if we *didn't* have an onEscape handler then processCallback
+            // would automatically dismiss the dialog
+            if (callbacks.onEscape === true ||
+                typeof callbacks.onEscape === "function") {
+                processCallback(e, $modal, callbacks.onEscape);
+            }
+        });
+        $modal.on("click", ".modal-footer button", function (e) {
+            var callbackKey = $(this).data("bp-handler");
+            processCallback(e, $modal, callbacks[callbackKey]);
+        });
+        $modal.on("click", ".bootprompt-close-button", function (e) {
+            // onEscape might be falsy but that's fine; the fact is
+            // if the user has managed to click the close button we
+            // have to close the dialog, callback or not
+            processCallback(e, $modal, callbacks.onClose);
+        });
+        $modal.on("keyup", function (e) {
+            if (e.which === 27) {
+                $modal.trigger("escape.close.bp");
+            }
+        });
+        // The interface defined for $ messes up type inferrence so we have to 
assert
+        // the type here.
+        $(finalOptions.container).append($modal);
+        $modal.modal({
+            backdrop: (backdrop === true || backdrop === "static") ? "static" 
: false,
+            keyboard: false,
+            show: false,
+        });
+        if (finalOptions.show === true) {
+            $modal.modal("show");
+        }
+        return $modal;
+    }
+    function _alert(options, callback) {
+        var finalOptions = mergeDialogOptions("alert", ["ok"], options, 
callback);
+        var finalCallback = finalOptions.callback;
+        // tslint:disable-next-line:no-suspicious-comment
+        // @TODO: can this move inside exports.dialog when we're iterating 
over each
+        // button and checking its button.callback value instead?
+        if (finalCallback !== undefined && typeof finalCallback !== 
"function") {
+            throw new Error("alert requires callback property to be a function 
when \
+provided");
+        }
+        var customCallback = function () {
+            return typeof finalCallback === "function" ?
+                finalCallback.call(this) : true;
+        };
+        finalOptions.buttons.ok.callback = customCallback;
+        setupEscapeAndCloseCallbacks(finalOptions, customCallback);
+        return dialog(finalOptions);
+    }
+    function alert(messageOrOptions, callback) {
+        return _alert(typeof messageOrOptions === "string" ?
+            { message: messageOrOptions } :
+            messageOrOptions, callback);
+    }
+    /**
+     * Specialized function that provides a dialog similar to the one provided 
by
+     * the DOM ``alert()`` function.
+     *
+     * **NOTE**: This function is non-blocking, so any code that must happen 
after
+     * the dialog is dismissed should await the promise returned by this 
function.
+     *
+     * @param messageOrOptions The message to display, or an object specifying 
the
+     * options for the dialog.
+     *
+     * @returns A promise that resolves once the dialog has been dismissed.
+     */
+    function alert$(messageOrOptions) {
+        return __awaiter(this, void 0, void 0, function () {
+            return __generator(this, function (_a) {
+                return [2 /*return*/, new Promise(function (resolve) {
+                        _alert(typeof messageOrOptions === "string" ?
+                            { message: messageOrOptions } : messageOrOptions, 
undefined)
+                            .one("hidden.bs.modal", function () {
+                            resolve();
+                        });
+                    })];
+            });
+        });
+    }
+    function _confirm(options, callback) {
+        var finalOptions = mergeDialogOptions("confirm", ["cancel", 
"confirm"], options, callback);
+        var finalCallback = finalOptions.callback, buttons = 
finalOptions.buttons;
+        // confirm specific validation; they don't make sense without a 
callback so
+        // make sure it's present
+        if (typeof finalCallback !== "function") {
+            throw new Error("confirm requires a callback");
+        }
+        var cancelCallback = function () {
+            return finalCallback.call(this, false);
+        };
+        buttons.cancel.callback = cancelCallback;
+        setupEscapeAndCloseCallbacks(finalOptions, cancelCallback);
+        buttons.confirm.callback =
+            function () {
+                return finalCallback.call(this, true);
+            };
+        return dialog(finalOptions);
+    }
+    function confirm(messageOrOptions, callback) {
+        return _confirm(typeof messageOrOptions === "string" ?
+            { message: messageOrOptions } :
+            messageOrOptions, callback);
+    }
+    /**
+     * Specialized function that provides a dialog similar to the one provided 
by
+     * the DOM ``confirm()`` function.
+     *
+     * **NOTE**: This function is non-blocking, so any code that must happen 
after
+     * the dialog is dismissed should await the promise returned by this 
function.
+     *
+     * @param messageOrOptions The message to display, or an object specifying 
the
+     * options for the dialog.
+     *
+     * @returns A promise that resolves once the dialog has been dismissed.
+     */
+    function confirm$(messageOrOptions) {
+        return __awaiter(this, void 0, void 0, function () {
+            return __generator(this, function (_a) {
+                return [2 /*return*/, new Promise(function (resolve) {
+                        var options = typeof messageOrOptions === "string" ?
+                            { message: messageOrOptions } : messageOrOptions;
+                        var callback = options.callback;
+                        var result = null;
+                        _confirm(options, function (value) {
+                            result = value;
+                            if (callback !== undefined) {
+                                return callback.call(this, result);
+                            }
+                        }).one("hidden.bs.modal", function () {
+                            resolve(result);
+                        });
+                    })];
+            });
+        });
+    }
+    function setupTextualInput(input, options) {
+        var value = options.value, placeholder = options.placeholder, pattern 
= options.pattern, maxlength = options.maxlength, required = options.required;
+        // tslint:disable-next-line:no-non-null-assertion
+        input.val(value);
+        if (placeholder !== undefined) {
+            input.attr("placeholder", placeholder);
+        }
+        if (pattern !== undefined) {
+            input.attr("pattern", pattern);
+        }
+        if (maxlength !== undefined) {
+            input.attr("maxlength", maxlength);
+        }
+        if (required === true) {
+            input.prop({ required: true });
+        }
+    }
+    function setupNumberLikeInput(input, options) {
+        var value = options.value, placeholder = options.placeholder, pattern 
= options.pattern, required = options.required, inputType = options.inputType;
+        if (value !== undefined) {
+            input.val(String(value));
+        }
+        if (placeholder !== undefined) {
+            input.attr("placeholder", placeholder);
+        }
+        if (pattern !== undefined) {
+            input.attr("pattern", pattern);
+        }
+        if (required === true) {
+            input.prop({ required: true });
+        }
+        // These input types have extra attributes which affect their input
+        // validation.  Warning: For most browsers, date inputs are buggy in 
their
+        // implementation of 'step', so this attribute will have no
+        // effect. Therefore, we don't set the attribute for date inputs.  @see
+        // tslint:disable-next-line:max-line-length
+        // 
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date#Setting_maximum_and_minimum_dates
+        if (inputType !== "date") {
+            var step = options.step;
+            if (step !== undefined) {
+                var stepNumber = Number(step);
+                if (step === "any" || (!isNaN(stepNumber) && stepNumber > 0)) {
+                    input.attr("step", step);
+                }
+                else {
+                    throw new Error("\"step\" must be a valid positive number 
or the value \"any\". See 
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-step for 
more information.");
+                }
+            }
+        }
+        validateMinOrMaxValue(input, "min", options);
+        validateMinOrMaxValue(input, "max", options);
+    }
+    function validateInputOptions(inputOptions) {
+        var e_4, _a;
+        try {
+            for (var inputOptions_1 = __values(inputOptions), inputOptions_1_1 
= inputOptions_1.next(); !inputOptions_1_1.done; inputOptions_1_1 = 
inputOptions_1.next()) {
+                var _b = inputOptions_1_1.value, value = _b.value, text = 
_b.text;
+                if (value === undefined || text === undefined) {
+                    throw new Error("each option needs a \"value\" and a 
\"text\" property");
+                }
+                if (typeof value === "number") {
+                    throw new Error("bootprompt does not allow numbers for 
\"value\" in inputOptions");
+                }
+            }
+        }
+        catch (e_4_1) { e_4 = { error: e_4_1 }; }
+        finally {
+            try {
+                if (inputOptions_1_1 && !inputOptions_1_1.done && (_a = 
inputOptions_1.return)) _a.call(inputOptions_1);
+            }
+            finally { if (e_4) throw e_4.error; }
+        }
+    }
+    function setupSelectInput(input, options) {
+        var e_5, _a;
+        var inputOptions = options.inputOptions !== undefined ?
+            options.inputOptions : [];
+        if (!Array.isArray(inputOptions)) {
+            throw new Error("Please pass an array of input options");
+        }
+        if (inputOptions.length === 0) {
+            throw new Error("prompt with select requires at least one option \
+value");
+        }
+        var required = options.required, multiple = options.multiple;
+        if (required === true) {
+            input.prop({ required: true });
+        }
+        if (multiple === true) {
+            input.prop({ multiple: true });
+        }
+        validateInputOptions(inputOptions);
+        var firstValue;
+        var groups = Object.create(null);
+        try {
+            for (var inputOptions_2 = __values(inputOptions), inputOptions_2_1 
= inputOptions_2.next(); !inputOptions_2_1.done; inputOptions_2_1 = 
inputOptions_2.next()) {
+                var _b = inputOptions_2_1.value, value = _b.value, text = 
_b.text, group = _b.group;
+                // assume the element to attach to is the input...
+                var elem = input[0];
+                // ... but override that element if this option sits in a group
+                if (group !== undefined && group !== "") {
+                    var groupEl = groups[group];
+                    if (groupEl === undefined) {
+                        groups[group] = groupEl = 
document.createElement("optgroup");
+                        groupEl.setAttribute("label", group);
+                    }
+                    elem = groupEl;
+                }
+                var o = $(templates.option);
+                o.attr("value", value).text(text);
+                elem.appendChild(o[0]);
+                if (firstValue === undefined) {
+                    firstValue = value;
+                }
+            }
+        }
+        catch (e_5_1) { e_5 = { error: e_5_1 }; }
+        finally {
+            try {
+                if (inputOptions_2_1 && !inputOptions_2_1.done && (_a = 
inputOptions_2.return)) _a.call(inputOptions_2);
+            }
+            finally { if (e_5) throw e_5.error; }
+        }
+        // Conditions are such that an undefined firstValue here is an 
internal error.
+        /* istanbul ignore if: we cannot cause this intentionally */
+        if (firstValue === undefined) {
+            throw new Error("firstValue cannot be undefined at this point");
+        }
+        // tslint:disable-next-line:forin
+        for (var groupName in groups) {
+            input.append(groups[groupName]);
+        }
+        input.val(options.value !== undefined ? options.value : firstValue);
+    }
+    function setupCheckbox(input, options, inputTemplate) {
+        var e_6, _a;
+        var checkboxValues = Array.isArray(options.value) ? options.value : 
[options.value];
+        var inputOptions = options.inputOptions !== undefined ?
+            options.inputOptions : [];
+        if (inputOptions.length === 0) {
+            throw new Error("prompt with checkbox requires options");
+        }
+        validateInputOptions(inputOptions);
+        try {
+            for (var inputOptions_3 = __values(inputOptions), inputOptions_3_1 
= inputOptions_3.next(); !inputOptions_3_1.done; inputOptions_3_1 = 
inputOptions_3.next()) {
+                var _b = inputOptions_3_1.value, value = _b.value, text = 
_b.text;
+                var checkbox = $(inputTemplate);
+                checkbox.find("input").attr("value", value);
+                checkbox.find("label").append("\n" + text);
+                if (checkboxValues.indexOf(value) !== -1) {
+                    checkbox.find("input").prop("checked", true);
+                }
+                input.append(checkbox);
+            }
+        }
+        catch (e_6_1) { e_6 = { error: e_6_1 }; }
+        finally {
+            try {
+                if (inputOptions_3_1 && !inputOptions_3_1.done && (_a = 
inputOptions_3.return)) _a.call(inputOptions_3);
+            }
+            finally { if (e_6) throw e_6.error; }
+        }
+    }
+    function setupRadio(input, options, inputTemplate) {
+        var e_7, _a;
+        // Make sure that value is not an array (only a single radio can ever 
be
+        // checked)
+        var initialValue = options.value;
+        if (initialValue !== undefined && Array.isArray(initialValue)) {
+            throw new Error("prompt with radio requires a single, non-array 
value for \"value\".");
+        }
+        var inputOptions = options.inputOptions !== undefined ?
+            options.inputOptions : [];
+        if (inputOptions.length === 0) {
+            throw new Error("prompt with radio requires options");
+        }
+        validateInputOptions(inputOptions);
+        // Radiobuttons should always have an initial checked input checked in 
a
+        // "group".  If value is undefined or doesn't match an input option,
+        // select the first radiobutton
+        var checkFirstRadio = true;
+        try {
+            for (var inputOptions_4 = __values(inputOptions), inputOptions_4_1 
= inputOptions_4.next(); !inputOptions_4_1.done; inputOptions_4_1 = 
inputOptions_4.next()) {
+                var _b = inputOptions_4_1.value, value = _b.value, text = 
_b.text;
+                var radio = $(inputTemplate);
+                radio.find("input").attr("value", value);
+                radio.find("label").append("\n" + text);
+                if (initialValue !== undefined && value === initialValue) {
+                    radio.find("input").prop("checked", true);
+                    checkFirstRadio = false;
+                }
+                input.append(radio);
+            }
+        }
+        catch (e_7_1) { e_7 = { error: e_7_1 }; }
+        finally {
+            try {
+                if (inputOptions_4_1 && !inputOptions_4_1.done && (_a = 
inputOptions_4.return)) _a.call(inputOptions_4);
+            }
+            finally { if (e_7) throw e_7.error; }
+        }
+        if (checkFirstRadio) {
+            input.find("input[type='radio']").first().prop("checked", true);
+        }
+    }
+    // tslint:disable-next-line:max-func-body-length
+    function _prompt(options, callback) {
+        // prompt defaults are more complex than others in that users can 
override
+        // more defaults
+        var finalOptions = mergeDialogOptions("prompt", ["cancel", "confirm"], 
options, callback);
+        if (typeof finalOptions.value === "number") {
+            throw new Error("bootprompt does not allow numbers as values");
+        }
+        // capture the user's show value; we always set this to false before 
spawning
+        // the dialog to give us a chance to attach some handlers to it, but 
we need
+        // to make sure we respect a preference not to show it
+        var shouldShow = finalOptions.show === undefined ? true : 
finalOptions.show;
+        // This is required prior to calling the dialog builder below - we 
need to add
+        // an event handler just before the prompt is shown
+        finalOptions.show = false;
+        // prompt-specific validation
+        if (finalOptions.title === undefined || finalOptions.title === "") {
+            throw new Error("prompt requires a title");
+        }
+        var finalCallback = finalOptions.callback, buttons = 
finalOptions.buttons;
+        if (typeof finalCallback !== "function") {
+            throw new Error("prompt requires a callback");
+        }
+        if (finalOptions.inputType === undefined) {
+            finalOptions.inputType = "text";
+        }
+        var inputTemplate = templates.inputs[finalOptions.inputType];
+        var input;
+        switch (finalOptions.inputType) {
+            case "text":
+            case "textarea":
+            case "email":
+            case "password":
+                input = $(inputTemplate);
+                setupTextualInput(input, finalOptions);
+                break;
+            case "date":
+            case "time":
+            case "number":
+            case "range":
+                input = $(inputTemplate);
+                setupNumberLikeInput(input, finalOptions);
+                break;
+            case "select":
+                input = $(inputTemplate);
+                setupSelectInput(input, finalOptions);
+                break;
+            case "checkbox":
+                // checkboxes have to nest within a containing element
+                input = $("<div class=\"bootprompt-checkbox-list\"></div>");
+                setupCheckbox(input, finalOptions, inputTemplate);
+                break;
+            case "radio":
+                // radio buttons have to nest within a containing element
+                // tslint:disable-next-line:no-jquery-raw-elements
+                input = $("<div class='bootprompt-radiobutton-list'></div>");
+                setupRadio(input, finalOptions, inputTemplate);
+                break;
+            default:
+                // The type assertion is needed in TS 3.2.4 which is the 
latest version
+                // that typedoc currently runs. *grumble*...
+                // tslint:disable-next-line:no-unnecessary-type-assertion
+                var q = finalOptions.inputType;
+                throw new Error("Unknown input type: " + q);
+        }
+        var cancelCallback = function () {
+            return finalCallback.call(this, null);
+        };
+        buttons.cancel.callback = cancelCallback;
+        setupEscapeAndCloseCallbacks(finalOptions, cancelCallback);
+        // Prompt submitted - extract the prompt value. This requires a bit of 
work,
+        // given the different input types available.
+        // tslint:disable-next-line:no-non-null-assertion
+        buttons.confirm.callback = function () {
+            var value;
+            switch (finalOptions.inputType) {
+                case "checkbox":
+                    value = input.find("input:checked")
+                        .map(function () {
+                        return $(this).val();
+                    }).get();
+                    break;
+                case "radio":
+                    value = input.find("input:checked").val();
+                    break;
+                default:
+                    var rawInput = input[0];
+                    if (rawInput.checkValidity !== undefined && 
!rawInput.checkValidity()) {
+                        // prevents button callback from being called
+                        return false;
+                    }
+                    if (finalOptions.inputType === "select" &&
+                        finalOptions.multiple === true) {
+                        value = input.find("option:selected")
+                            .map(function () {
+                            return $(this).val();
+                        }).get();
+                    }
+                    else {
+                        value = input.val();
+                    }
+            }
+            // TS type inferrence fails here.
+            // tslint:disable-next-line:no-any
+            return finalCallback.call(this, value);
+        };
+        var form = $(templates.form);
+        form.append(input);
+        var message = finalOptions.message;
+        if (typeof message === "string" && message.trim() !== "") {
+            // Add the form to whatever content the user may have added.
+            // tslint:disable-next-line:no-inner-html
+            form.prepend($(templates.promptMessage).html(message));
+        }
+        finalOptions.message = form;
+        // Generate the dialog
+        var promptDialog = dialog(finalOptions);
+        form.on("submit", function (e) {
+            e.preventDefault();
+            // Fix for SammyJS (or similar JS routing library) hijacking the 
form post.
+            e.stopPropagation();
+            // tslint:disable-next-line:no-suspicious-comment
+            // @TODO can we actually click *the* button object instead?
+            // e.g. buttons.confirm.click() or similar
+            promptDialog.find(".bootprompt-accept").trigger("click");
+        });
+        // clear the existing handler focusing the submit button...
+        // ...and replace it with one focusing our input, if possible
+        promptDialog.off("shown.bs.modal").on("shown.bs.modal", function () {
+            input.focus();
+        });
+        if (shouldShow === true) {
+            promptDialog.modal("show");
+        }
+        return promptDialog;
+    }
+    // tslint:disable-next-line:max-func-body-length
+    function prompt(messageOrOptions, callback) {
+        return _prompt(typeof messageOrOptions === "string" ?
+            { title: messageOrOptions } :
+            messageOrOptions, callback);
+    }
+    function prompt$(messageOrOptions) {
+        return __awaiter(this, void 0, void 0, function () {
+            return __generator(this, function (_a) {
+                return [2 /*return*/, new Promise(function (resolve) {
+                        var options = typeof messageOrOptions === "string" ?
+                            // 
tslint:disable-next-line:no-object-literal-type-assertion
+                            { title: messageOrOptions } : messageOrOptions;
+                        var callback = options.callback;
+                        var result = null;
+                        _prompt(options, function (value) {
+                            result = value;
+                            if (callback !== undefined) {
+                                // We assert the type of callback because TS's 
type inference fails
+                                // here.
+                                // tslint:disable-next-line:no-any
+                                return callback.call(this, result);
+                            }
+                        }).one("hidden.bs.modal", function () {
+                            resolve(result);
+                        });
+                    })];
+            });
+        });
+    }
+    //
+    // INTERNAL FUNCTIONS
+    //
+    function setupEscapeAndCloseCallbacks(options, callback) {
+        var onEscape = options.onEscape, onClose = options.onClose;
+        options.onEscape = (onEscape === undefined || onEscape === true) ?
+            callback :
+            function (ev) {
+                if (onEscape === false || onEscape.call(this, ev) === false) {
+                    return false;
+                }
+                return callback.call(this, ev);
+            };
+        options.onClose = onClose === undefined ?
+            callback :
+            function (ev) {
+                if (onClose.call(this, ev) === false) {
+                    return false;
+                }
+                return callback.call(this, ev);
+            };
+    }
+    /**
+     * Get localized text from a locale. Defaults to ``en`` locale if no locale
+     * provided or a non-registered locale is requested.
+     *
+     * @param key The field to get from the locale.
+     *
+     * @param locale The locale name.
+     *
+     * @returns The field from the locale.
+     */
+    function getText(key, locale) {
+        var labels = definedLocales[locale];
+        return labels !== undefined ? labels[key] : definedLocales.en[key];
+    }
+    /**
+     *
+     * Make buttons from a series of labels. All this does is normalise the 
given
+     * labels and translate them where possible.
+     *
+     * @param labels The button labels.
+     *
+     * @param locale A locale name.
+     *
+     * @returns The created buttons.
+     *
+     */
+    function makeButtons(labels, locale) {
+        var e_8, _a;
+        var buttons = Object.create(null);
+        try {
+            for (var labels_1 = __values(labels), labels_1_1 = 
labels_1.next(); !labels_1_1.done; labels_1_1 = labels_1.next()) {
+                var label = labels_1_1.value;
+                buttons[label.toLowerCase()] = {
+                    label: getText(label.toUpperCase(), locale),
+                };
+            }
+        }
+        catch (e_8_1) { e_8 = { error: e_8_1 }; }
+        finally {
+            try {
+                if (labels_1_1 && !labels_1_1.done && (_a = labels_1.return)) 
_a.call(labels_1);
+            }
+            finally { if (e_8) throw e_8.error; }
+        }
+        return buttons;
+    }
+    /**
+     * Produce a DialogOptions object from the options, or arguments passed to 
the
+     * specialized functions (alert, confirm, prompt).
+     *
+     * @param kind The kind of specialized function that was called.
+     *
+     * @param labels The button labels that the specialized function uses.
+     *
+     * @param options: The first argument of the specialized functions is 
either an
+     * options object, or a string. The value of that first argument must be 
passed
+     * here.
+     *
+     * @returns Options to pass to [[dialog]].
+     */
+    function mergeDialogOptions(kind, labels, options, callback) {
+        // An earlier implementation was building a hash from ``buttons``. 
However,
+        // the ``buttons`` array is very small. Profiling in other projects 
have shown
+        // that for very small arrays, there's no benefit to creating a table 
for
+        // lookup.
+        //
+        // An earlier implementation was also performing the check on the 
merged
+        // options (the return value of this function) but that was pointless 
as it is
+        // not possible to add invalid buttons with makeButtons.
+        //
+        for (var key in options.buttons) {
+            // tslint:disable-next-line:no-any
+            if (labels.indexOf(key) === -1) {
+                throw new Error("button key \"" + key + "\" is not allowed 
(options are " + labels.join(" ") + ")");
+            }
+        }
+        var locale = options.locale, swapButtonOrder = options.swapButtonOrder;
+        return $.extend(true, // deep merge
+        Object.create(null), {
+            className: "bootprompt-" + kind,
+            buttons: makeButtons(swapButtonOrder === true ? 
labels.slice().reverse() :
+                labels, locale !== undefined ? locale : currentLocale),
+        }, options, { callback: callback });
+    }
+    //  Filter and tidy up any user supplied parameters to this dialog.
+    //  Also looks for any shorthands used and ensures that the options
+    //  which are returned are all normalized properly
+    function sanitize(options) {
+        if (typeof options !== "object") {
+            throw new Error("Please supply an object of options");
+        }
+        if (options.message === undefined) {
+            throw new Error("Please specify a message");
+        }
+        var finalOptions = __assign({ locale: currentLocale, backdrop: 
"static", animate: animate, closeButton: true, show: true, container: 
document.body }, options);
+        // no buttons is still a valid dialog but it's cleaner to always have
+        // a buttons object to iterate over, even if it's empty
+        var buttons = finalOptions.buttons;
+        if (buttons === undefined) {
+            buttons = finalOptions.buttons = Object.create(null);
+        }
+        var total = Object.keys(buttons).length;
+        var index = 0;
+        // tslint:disable-next-line:forin
+        for (var key in buttons) {
+            var button = buttons[key];
+            if (typeof button === "function") {
+                // short form, assume value is our callback. Since button
+                // isn't an object it isn't a reference either so re-assign it
+                button = buttons[key] = {
+                    callback: button,
+                };
+            }
+            // before any further checks make sure by now button is the 
correct type
+            if (typeof button !== "object") {
+                throw new Error("button with key \"" + key + "\" must be an 
object");
+            }
+            if (button.label === undefined) {
+                // the lack of an explicit label means we'll assume the key is 
good enough
+                button.label = key;
+            }
+            if (button.className === undefined) {
+                var isPrimary = index === (finalOptions.swapButtonOrder === 
true ? 0 : total - 1);
+                // always add a primary to the main option in a one or 
two-button dialog
+                button.className = (total <= 2 && isPrimary) ?
+                    "btn-primary" :
+                    "btn-secondary btn-default";
+            }
+            index++;
+        }
+        // TS cannot infer that we have SanitizedDialogOptions at this point.
+        return finalOptions;
+    }
+    function throwMaxMinError(name) {
+        throw new Error("\"max\" must be greater than \"min\". See 
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-"; + name + 
" for more information.");
+    }
+    //  Handle the invoked dialog callback
+    function processCallback(e, $forDialog, callback) {
+        e.stopPropagation();
+        e.preventDefault();
+        // By default we assume a callback will get rid of the dialog, 
although it is
+        // given the opportunity to override this so, if the callback can be 
invoked
+        // and it *explicitly returns false* then we keep the dialog active...
+        // otherwise we'll bin it
+        if (!(typeof callback === "function" &&
+            callback.call($forDialog, e) === false)) {
+            $forDialog.modal("hide");
+        }
+    }
+    // Helper function, since the logic for validating min and max attributes 
is
+    // almost identical
+    function validateMinOrMaxValue(input, name, options) {
+        var value = options[name];
+        if (value === undefined) {
+            return;
+        }
+        var compareValue = options[name === "min" ? "max" : "min"];
+        input.attr(name, value);
+        var min = options.min, max = options.max;
+        // Type inference fails to realize the real type of value...
+        switch (options.inputType) {
+            case "date":
+                /* istanbul ignore if: we don't test the positive case */
+                if (!/(\d{4})-(\d{2})-(\d{2})/.test(value)) {
+                    // tslint:disable-next-line:no-console
+                    console.warn("Browsers which natively support the \"date\" 
input type expect date values to be of the form \"YYYY-MM-DD\" (see ISO-8601 
https://www.iso.org/iso-8601-date-and-time-format.html). Bootprompt does not 
enforce this rule, but your " + name + " value may not be enforced by this 
browser.");
+                }
+                break;
+            case "time":
+                if (!/([01][0-9]|2[0-3]):[0-5][0-9]?:[0-5][0-9]/.test(value)) {
+                    throw new Error("\"" + name + "\" is not a valid time. See 
https://www.w3.org/TR/2012/WD-html-markup-20120315/datatypes.html#form.data.time
 for more information.");
+                }
+                // tslint:disable-next-line:no-non-null-assertion
+                if (!(compareValue === undefined || max > min)) {
+                    return throwMaxMinError(name);
+                }
+                break;
+            default:
+                // Yes we force the string into isNaN. It works.
+                if (isNaN(value)) {
+                    throw new Error("\"" + name + "\" must be a valid number. 
See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-"; + 
name + " for more information.");
+                }
+                var minNumber = Number(min);
+                var maxNumber = Number(max);
+                // tslint:disable-next-line:no-non-null-assertion
+                if (!(compareValue === undefined || maxNumber > minNumber) &&
+                    // Yes we force the string into isNaN. It works.
+                    !isNaN(compareValue)) {
+                    return throwMaxMinError(name);
+                }
+        }
+    }
+    //  Register the default locale
+    addLocale("en", {
+        OK: "OK",
+        CANCEL: "Cancel",
+        CONFIRM: "OK",
+    });
+
+    exports.VERSION = VERSION;
+    exports.addLocale = addLocale;
+    exports.alert = alert;
+    exports.alert$ = alert$;
+    exports.confirm = confirm;
+    exports.confirm$ = confirm$;
+    exports.dialog = dialog;
+    exports.hideAll = hideAll;
+    exports.locales = locales;
+    exports.prompt = prompt;
+    exports.prompt$ = prompt$;
+    exports.removeLocale = removeLocale;
+    exports.setAnimate = setAnimate;
+    exports.setLocale = setLocale;
+
+    Object.defineProperty(exports, '__esModule', { value: true });
+
+}));
+//# sourceMappingURL=bootprompt.js.map
\ No newline at end of file
diff --git a/security-admin/src/main/webapp/scripts/Init.js 
b/security-admin/src/main/webapp/scripts/Init.js
index 5909f93a9..bff79b3c4 100644
--- a/security-admin/src/main/webapp/scripts/Init.js
+++ b/security-admin/src/main/webapp/scripts/Init.js
@@ -83,9 +83,6 @@ require.config({
         'select2': {
             deps: ['jquery', 'bootstrap']
         },
-        'bootbox': {
-            deps: ['jquery']
-        },
         'esprima': {
             'exports': 'esprima'
         },
@@ -95,6 +92,9 @@ require.config({
         'Backgrid.ColumnManager' : {
             deps: ['backbone', 'backgrid', 'underscore', 'jquery']
         },
+        'bootprompt': {
+            deps: ['jquery', 'bootstrap']
+        },
     },
 
     paths: {
@@ -134,7 +134,6 @@ require.config({
         'jquery-toggles': '../libs/bower/jquery-toggles/js/toggles.min',
         'tag-it': '../libs/bower/tag-it/js/tag-it',
         'select2': '../libs/bower/select2/select2',
-        'bootbox': '../libs/bower/bootbox/js/bootbox',
         'visualsearch': '../libs/other/visualsearch/js/visualsearch',
         'globalize': '../libs/bower/globalize/lib/globalize',
         /* handlebars from the require handlerbars plugin below */
@@ -145,6 +144,7 @@ require.config({
         'esprima': '../libs/bower/esprima/esprima',
         'tmpl': '../templates',
         'Backgrid.ColumnManager': 
'../libs/other/backgrid-column-manager/Backgrid.ColumnManager.min',
+        'bootprompt' : '../libs/bower/bootprompt/bootprompt',
     },
 
     hbs: {
diff --git a/security-admin/src/main/webapp/scripts/routers/Router.js 
b/security-admin/src/main/webapp/scripts/routers/Router.js
index 448659eb2..753477fc0 100644
--- a/security-admin/src/main/webapp/scripts/routers/Router.js
+++ b/security-admin/src/main/webapp/scripts/routers/Router.js
@@ -23,9 +23,9 @@
        'utils/XALangSupport',
        'models/VAppState',
        'utils/XAUtils',
-       'bootbox'
+       'bootprompt'
 ],
-function(Backbone, Marionette, localization, MAppState, XAUtil, bootbox){
+function(Backbone, Marionette, localization, MAppState, XAUtil, bootprompt){
     'use strict';
 
        return Backbone.Marionette.AppRouter.extend({
@@ -97,22 +97,29 @@ function(Backbone, Marionette, localization, MAppState, 
XAUtil, bootbox){
                                callbackArgs = arguments;
                                var formStatus = 
$('.form-horizontal').find('.dirtyField').length > 0 ? true : false
                                if (window._preventNavigation && formStatus) {
-                                       
bootbox.dialog(window._preventNavigationMsg, [{
-                                               "label": "Stay on this page!",
-                                               "class": "btn-success btn-sm",
-                                               "callback": function() {
-                                                       
router.navigate(MAppState.get('previousFragment'), {
-                                                               trigger: false
-                                                       });
+                                       bootprompt.dialog(
+                                       {
+                                               message: 
window._preventNavigationMsg,
+                                               buttons: {
+                                                       noclose: {
+                                                               "label" : 
localization.tt('btn.stayOnPage'),
+                                                               "className" : 
"btn-success btn-sm",
+                                                               "callback": 
function() {
+                                                                       
router.navigate(MAppState.get('previousFragment'), {
+                                                                               
trigger: false
+                                                                       });
+                                                               }
+                                                       },
+                                                       cancel: {
+                                                               "label" : 
localization.tt('btn.leavePage'),
+                                                               "className" : 
"btn-danger btn-sm",
+                                                               "callback": 
function() {
+                                                                       
XAUtil.allowNavigation();
+                                                                       
proceedWithCallback();
+                                                               }
+                                                       }
                                                }
-                                       }, {
-                                               "label": "Leave this page",
-                                               "class": "btn-danger btn-sm",
-                                               "callback": function() {
-                                                       
XAUtil.allowNavigation();
-                                                       proceedWithCallback();
-                                               }
-                                       }]);
+                                       });
 
                                } else {
                                        proceedWithCallback();
diff --git a/security-admin/src/main/webapp/scripts/utils/XALangSupport.js 
b/security-admin/src/main/webapp/scripts/utils/XALangSupport.js
index 1f8a08944..9df967cec 100644
--- a/security-admin/src/main/webapp/scripts/utils/XALangSupport.js
+++ b/security-admin/src/main/webapp/scripts/utils/XALangSupport.js
@@ -81,63 +81,6 @@ 
define(['require','modules/Vent','globalize','modules/globalize/message/en'],fun
     localization.getDaysOfWeek = function(label){
                return Globalize.culture().calendars.standard.days.namesAbbr;
     }
-
-    localization.chooseCulture = function(culture){
-               var dfd = $.Deferred();
-               dfd.done(function(validationMessages){
-                       require([ 'validationEngine'],function(){
-                               setCulture(culture);
-                               validationMessages.setupMessages();
-                               vent.trigger('Layouts:rerender');
-                       });
-               });
-        switch(culture){
-            case "pt-BR" : 
-                 require(['gblMessages/message/pt-BR'], function() {
-                                        require([ 'validationEngineEn' 
],function(validationMessages){
-                                                
dfd.resolve(validationMessages);
-                                                console.log('Language Changed 
to pt-BR');
-                                        });
-                                        $.fn.datepicker.dates['pt-BR'] = {
-                                                               days: 
["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado", 
"Domingo"],
-                                                               daysShort: 
["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb", "Dom"],
-                                                               daysMin: ["Do", 
"Se", "Te", "Qu", "Qu", "Se", "Sa", "Do"],
-                                                               months: 
["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", 
"Setembro", "Outubro", "Novembro", "Dezembro"],
-                                                               monthsShort: 
["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", 
"Dez"],
-                                                               today: "Hoje",
-                                                               clear: "Limpar"
-                                       };
-                                       bootbox.setLocale('pt-BR'); 
-                });
-                break;
-                       case "es" : 
-                 require(['gblMessages/message/es'], function() {
-                                        require([ 'validationEngineEn' 
],function(validationMessages){
-                                                
dfd.resolve(validationMessages);
-                                                console.log('Language Changed 
to es');
-                                        });
-                                        $.fn.datepicker.dates['es'] = {
-                                                               days: 
["Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado", 
"Domingo"],
-                                                               daysShort: 
["Dom", "Lun", "Mar", "Mié", "Jue", "Vie", "Sáb", "Dom"],
-                                                               daysMin: ["Do", 
"Lu", "Ma", "Mi", "Ju", "Vi", "Sa", "Do"],
-                                                               months: 
["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", 
"Septiembre", "Octubre", "Noviembre", "Diciembre"],
-                                                               monthsShort: 
["Ene", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", 
"Dic"],
-                                                               today: "Hoy"
-                                       };
-                                       bootbox.setLocale('es'); 
-                });
-                break;
-            default : 
-                 require(['gblMessages/message/en'], function() {
-                                        require([ 'validationEngineEn' 
],function(validationMessages){
-                                                
dfd.resolve(validationMessages);
-                                                console.log('Language Changed 
to en');
-                                        });
-                                        bootbox.setLocale('en');
-                });
-                break;
-        }
-    }
     
     localization.formatDate = function(val,format){
        if(!val) return "";
diff --git a/security-admin/src/main/webapp/scripts/utils/XAUtils.js 
b/security-admin/src/main/webapp/scripts/utils/XAUtils.js
index fc3ff5b5d..31d9a04ff 100644
--- a/security-admin/src/main/webapp/scripts/utils/XAUtils.js
+++ b/security-admin/src/main/webapp/scripts/utils/XAUtils.js
@@ -24,7 +24,7 @@ define(function(require) {
        var localization = require('utils/XALangSupport');
        var XAUtils = {};
        var notify = require('bootstrap-notify');
-       var bootbox = require('bootbox');
+       var bootprompt = require('bootprompt');
     var moment = require('moment');
 
        // ///////////////////////////////////////////////////////
@@ -348,7 +348,7 @@ define(function(require) {
 
                        e.preventDefault();
                        e.stopImmediatePropagation();
-                       bootbox.dialog(
+                       bootprompt.dialog(
                        {
                                message: msg,
                                buttons: {
@@ -387,35 +387,35 @@ define(function(require) {
        };
        
        /**
-        * Bootbox wrapper for alert
+        * Bootprompt wrapper for alert
         * 
         * @param {Object}
         *            params - The params
         */
        XAUtils.alertPopup = function(params) {
-               bootbox.hideAll();
+               bootprompt.hideAll();
                if (params.callback == undefined) {
-                       bootbox.alert(params.msg);
+                       bootprompt.alert(params.msg);
                } else {
-                       bootbox.alert(params.msg, params.callback);
+                       bootprompt.alert(params.msg, params.callback);
                }
        };
      
        //Alert box with time set 
        XAUtils.alertBoxWithTimeSet = function(msg) {
-               var alert = bootbox.alert(msg);
+               var alert = bootprompt.alert(msg);
        return(setTimeout(function(){alert.modal('hide'); }, 4000));
        }
        
        /**
-        * Bootbox wrapper for confirm
+        * Bootprompt wrapper for confirm
         * 
         * @param {Object}
         *            params - The params
         */
        XAUtils.confirmPopup = function(params) {
-               bootbox.hideAll();
-               bootbox.confirm(params.msg, function(result) {
+               bootprompt.hideAll();
+               bootprompt.confirm(params.msg, function(result) {
                        if (result) {
                                params.callback();
                        }
@@ -1975,7 +1975,7 @@ define(function(require) {
             if (timeLeft == 0 ) {
                 clearTimeout(timerId);
                 if (!moment().isAfter(moment(idleTimeVal))) {
-                    bootbox.hideAll()
+                    bootprompt.hideAll()
                 } else {
                     localStorage.setItem('idleTimerLoggedOut', 'false');
                     XAUtils.idleActivityLogout();
@@ -1987,7 +1987,7 @@ define(function(require) {
                     localStorage.setItem('idleTimerLoggedOut', 'false');
                     XAUtils.idleActivityLogout();
                 } else if (!moment().isAfter(moment(idleTimeVal))) {
-                    bootbox.hideAll()
+                    bootprompt.hideAll()
                     clearTimeout(timerId);
                 } else {
                     $.find('#Timer')[0].innerHTML ='Time left : '+ timeLeft + 
' seconds remaining';
@@ -1995,7 +1995,7 @@ define(function(require) {
                 }
             }
         }
-        bootbox.dialog({
+        bootprompt.dialog({
             title: 'Session Expiration Warning',
             message: '<span class="inline-block">' + 
localization.tt('dialogMsg.idleTimeOutMsg') +'<br>'+ $elem + '</span>',
             closeButton: false,
diff --git 
a/security-admin/src/main/webapp/scripts/views/permissions/ModulePermsTableLayout.js
 
b/security-admin/src/main/webapp/scripts/views/permissions/ModulePermsTableLayout.js
index f53bb724e..26f60bbdd 100644
--- 
a/security-admin/src/main/webapp/scripts/views/permissions/ModulePermsTableLayout.js
+++ 
b/security-admin/src/main/webapp/scripts/views/permissions/ModulePermsTableLayout.js
@@ -37,7 +37,6 @@ define(function(require){
 
        require('backgrid-filter');
        require('backgrid-paginator');
-       require('bootbox');
 
        var ModulePermsTableLayout = Backbone.Marionette.Layout.extend(
        /** @lends ModulePermsTableLayout */
diff --git 
a/security-admin/src/main/webapp/scripts/views/service/ServiceCreate.js 
b/security-admin/src/main/webapp/scripts/views/service/ServiceCreate.js
index b980b0a70..799577673 100644
--- a/security-admin/src/main/webapp/scripts/views/service/ServiceCreate.js
+++ b/security-admin/src/main/webapp/scripts/views/service/ServiceCreate.js
@@ -31,7 +31,7 @@ define(function(require){
        var XAEnums                     = require('utils/XAEnums');
        var XALinks             = require('modules/XALinks');
        var localization        = require('utils/XALangSupport');
-       var bootbox             = require('bootbox');
+       var bootprompt          = require('bootprompt');
 
        var ServiceForm         = require('views/service/ServiceForm');
        var RangerServiceDef    = require('models/RangerServiceDef');
@@ -249,25 +249,29 @@ define(function(require){
                                                        }];
                                   }
                                    var msgHtml = '<b>Connection 
Failed.</b></br>'+msResponse.msgDesc;
-                                    bootbox.dialog({
+                                    bootprompt.dialog({
                                         message : msgHtml,
                                         buttons: popupBtnOpts
                                     });
                                                                } else {
-                                                                               
bootbox.alert("Connection Failed.");
+                                                                               
bootprompt.alert("Connection Failed.");
                                                                }
                                                        } else {
-                                                               
bootbox.alert("Connection Failed.");
+                                                               
bootprompt.alert("Connection Failed.");
                                                        }
                                                } else {
-                                                       
bootbox.alert("Connected Successfully.");
+                                                       
bootprompt.alert("Connected Successfully.");
                                                }
                                        },
                                        error: function (msResponse, options) {
-                                                if(msResponse.status === 419){
-                                                        
XAUtil.defaultErrorHandler(options , msResponse);
-                                                }
-                                               bootbox.alert("Connection 
Failed.");
+                                               if(msResponse.status === 419){
+                                                       
XAUtil.defaultErrorHandler(options , msResponse);
+                                               }
+                                               if(msResponse && 
msResponse.responseJSON && msResponse.responseJSON.msgDesc) {
+                                                       
bootprompt.alert(msResponse.responseJSON.msgDesc)
+                                               } else {
+                                                       
bootprompt.alert("Connection Failed.");
+                                               }
                                        }
                                });
                },

Reply via email to