Source: widgets/database-widget.js

/*
 * Copyright 2013-2015 Hewlett-Packard Development Company, L.P.
 * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
 */

/**
 * @module settings/js/widgets/database-widget
 */
define([
    'settings/js/server-widget',
    'settings/js/controls/password-view',
    'text!settings/templates/widgets/database-widget.html',
    'text!settings/templates/widgets/databases-widget.html'
], function (ServerWidget, PasswordView, template, selectionTemplate) {
    /**
     * @typedef DatabaseWidgetStrings
     * @desc Includes all properties from ServerWidgetStrings and PasswordViewStrings
     * @property {string} databaseCheckbox Label for the database checkbox
     * @property {string} databaseLabel Label for the database field
     * @property {string} flywayMigrationFromEmpty String to display if the database will need to be set up for the
     * application
     * @property {string} flywayMigrationUpgrade String to display if the database schema needs to be upgraded
     * @property {string} hostPlaceholder Placeholder for the host input
     * @property {string} portPlaceholder Placeholder for the port input
     * @property {string} usernameLabel Label for the username input
     * @property {string} validateDatabaseBlank Message to display if the database is blank
     * @property {string} validateHostBlank Message to display if the host is blank
     * @property {string} validateUsernameBlank Message to display if the username is blank
     */
    /**
     * @typedef DatabaseWidgetOptions
     * @desc Extends ServerWidgetOptions
     * @property {boolean} canDisable True if the database can be disabled; false otherwise
     * @property {DatabaseWidgetStrings} strings Strings for the widget
     */
    /**
     * @name module:settings/js/widgets/database-widget.DatabaseWidget
     * @desc Widget for configuring a relational database
     * @constructor
     * @param {DatabaseWidgetOptions} options Options for the widget
     * @extends module:settings/js/server-widget.ServerWidget
     */
    return ServerWidget.extend(/** @lends module:settings/js/widgets/database-widget.DatabaseWidget.prototype */{
        className: ServerWidget.prototype.className,

        /**
         * @typedef DatabaseWidgetTemplateParameters
         * @property {DatabaseWidgetStrings} strings Strings for the template
         */
        /**
         * @callback module:settings/js/widgets/database-widget.DatabaseWidget~DatabaseTemplate
         * @param {DatabaseWidgetTemplateParameters} parameters
         */
        /**
         * @desc Base template for the widget. Override if using Bootstrap 3
         * @type module:settings/js/widgets/database-widget.DatabaseWidget~DatabaseTemplate
         */
        databaseTemplate: _.template(template),
        databasesTemplate: _.template(selectionTemplate),

        formControlClass: '',

        initialize: function (options) {
            ServerWidget.prototype.initialize.call(this, options);
            this.passwordView = new PasswordView({
                strings: this.strings,
                className: this.controlGroupClass,
                formControlClass: this.formControlClass
            });

            this.databaseTypes = {
                postgres: {
                    protocol: 'jdbc:postgresql',
                    hibernateDialect: 'org.hibernate.dialect.PostgreSQL82Dialect',
                    driverClassName: 'org.postgresql.Driver',
                    buildUrl: _.bind(function () {
                        var database = this.$databaseCheckbox.prop('checked') ? this.$username.val() : this.$database.val();
                        return 'jdbc:postgresql://' + this.$host.val() + ':' + this.$port.val() + '/' + database;
                    }, this),
                    parseUrl: function (url) {
                        var captureGroups = /^jdbc:postgresql:\/\/([^:]*):(\d*)\/(.*)$/.exec(url);
                        return captureGroups ? {
                            protocol: 'jdbc:postgresql',
                            host: captureGroups[1],
                            port: captureGroups[2],
                            database: captureGroups[3]
                        } : {protocol: 'jdbc:postgresql'}
                    }
                },
                h2: {
                    hibernateDialect: 'org.hibernate.dialect.H2Dialect',
                    driverClassName: 'org.h2.Driver',
                    username: 'sa',
                    buildUrl: function () {
                        return 'jdbc:h2:' + (options.databaseDir ? 'file:' + options.databaseDir + '/data/' : 'mem:') + options.databaseName + ';DB_CLOSE_ON_EXIT=FALSE';
                    }
                }
            };

            this.databaseType = options.databaseType;
        },

        /**
         * @desc Renders the widget
         */
        render: function () {
            ServerWidget.prototype.render.call(this);

            this.$validateButtonParent = this.$('button[name=validate]').parent();
            this.$validateButtonParent.before(this.databasesTemplate({
                strings: this.strings
            }));

            this.$('.database-config').append(this.databaseTemplate({
                strings: this.strings
            }));

            this.$databaseType = this.$('.database-type-input');
            this.$database = this.$('input[name=database]');
            this.$databaseCheckbox = this.$('input[type="checkbox"]');
            this.$host = this.$('input[name=host]');
            this.$port = this.$('input[name=port]');
            this.$username = this.$('input[name=username]');
            this.$protocol = this.$('.protocol');

            this.passwordView.render();
            this.$databaseCheckbox.parent().before(this.passwordView.$el);

            if (this.databaseType) {
                this.$('.database-type-selection').addClass('hide');
            }

            this.toggleInputs = _.bind(function () {
                var databaseType = this.databaseType || this.$databaseType.val();
                this.$('.database-config').toggleClass('hide', databaseType === 'h2');
                this.$protocol.text(this.databaseTypes[databaseType].protocol);
            }, this);

            this.$databaseType.on('input', this.toggleInputs);

            this.toggleInputs();
        },

        /**
         * @desc Returns the configuration for the widget
         * @returns The configuration for the widget
         */
        getConfig: function () {
            var databaseType = this.databaseType || this.$databaseType.val();
            var datasourceInfo = this.databaseTypes[databaseType];
            var dataBaseOptions = {
                platform: databaseType,
                hibernateDialect: datasourceInfo.hibernateDialect,
                driverClassName: datasourceInfo.driverClassName,
                url: datasourceInfo.buildUrl(),
                username: datasourceInfo.username || this.$username.val(),
                password: '',
                passwordRedacted: false
            };

            // user cant set embedded password.
            return databaseType === 'h2' ? dataBaseOptions : _.extend(dataBaseOptions, this.passwordView.getConfig());
        },

        /**
         * @desc Handles input validation. Checking the database checkbox disables the database input. If the database
         * checkbox is checked, sets value of the database input to the value of the username input
         * @param {Event} evt jQuery event
         */
        handleInputChange: function (evt) {
            ServerWidget.prototype.handleInputChange.apply(this, arguments);
            var $input = $(evt.target);

            if ($input.is(this.$databaseCheckbox)) {
                this.$database.prop('disabled', this.$databaseCheckbox.prop('checked'));
            }

            if (this.$databaseCheckbox.prop('checked') && ($input.is(this.$databaseCheckbox) || $input.is(this.$username))) {
                this.$database.val(this.$username.val());
            }
        },

        /**
         * @typedef DatabaseValidationResponse
         * @property {string} data.version String defining the version of the migration
         */
        /**
         * @desc Returns a message stating validation was successful. If response.data.sourceVersion === '0', returns
         * this.strings.flywayMigrationFromEmpty. If response.data is defined, returns
         * this.strings.flywayMigrationUpgrade. Otherwise returns this.strings.validateSuccess.
         * @param {DatabaseValidationResponse} response
         * @returns {string}
         */
        getValidationSuccessMessage: function (response) {
            // if we get back flyway migration data, use that in the message
            if (response.data) {
                if (response.data.sourceVersion === '0') {
                    return this.strings.flywayMigrationFromEmpty;
                }
                else {
                    return this.strings.flywayMigrationUpgrade;
                }
            }
            else {
                return ServerWidget.prototype.getValidationSuccessMessage.call(this, response);
            }
        },

        /**
         * @returns {boolean} True
         */
        shouldValidate: function () {
            return true;
        },

        /**
         * @desc Updates the widget with new configuration
         * @param config The new config for the wizard
         */
        updateConfig: function (config) {
            ServerWidget.prototype.updateConfig.apply(this, arguments);

            if (config.platform && config.platform !== 'h2') {
                var serverConfig = this.databaseTypes[config.platform].parseUrl(config.url);
                this.protocol = serverConfig.protocol;
                this.$protocol.text(this.protocol);
                this.$database.val(serverConfig.database);
                this.$host.val(serverConfig.host);
                this.$port.val(serverConfig.port);
                this.$username.val(config.username);
                this.passwordView.updateConfig(config);

                if (!serverConfig.database && config.username) {
                    this.$database.val(config.username);
                }

                this.$databaseType.val(config.platform);
                this.toggleInputs();

            }

            var checkboxState = this.$database.val() === this.$username.val();
            this.$databaseCheckbox.prop('checked', checkboxState);
            this.$database.prop('disabled', checkboxState);
        },

        /**
         * @desc Validates the widget and applies formatting appropriately
         * @returns {boolean} False if any of host, username and database are blank or the password is invalid; true
         * otherwise
         */
        validateInputs: function () {
            var isValid = true;

            if (this.shouldValidate()) {
                var config = this.getConfig();
                isValid = this.validateDatasourceConfig(config);
            }

            return isValid;
        },

        validateDatasourceConfig: function (config) {
            var isValid = true;

            if (config.platform && config.platform !== 'h2') {
                var serverConfig = this.databaseTypes[config.platform].parseUrl(config.url);
                if (!serverConfig.host) {
                    isValid = false;
                    this.updateInputValidation(this.$host, false);
                }

                if (!config.username) {
                    isValid = false;
                    this.updateInputValidation(this.$username, false);
                }

                if (!serverConfig.database) {
                    isValid = false;
                    this.updateInputValidation(this.$database, false);
                }

                // needs to be this way round to apply formatting
                isValid = this.passwordView.validateInputs() && isValid;
            }

            return isValid;
        }
    });

});
Copyright 2013--2018 Micro Focus International plc. Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
Documentation generated by JSDoc 3.4.3 on Fri Jun 22nd 14:40 2018 using the DocStrap template.