Files
azuredatastudio/src/sql/base/browser/ui/modal/optionsDialogHelper.ts
2018-06-05 11:24:51 -07:00

179 lines
7.0 KiB
TypeScript

/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as DialogHelper from './dialogHelper';
import { Builder } from 'vs/base/browser/builder';
import { SelectBox } from 'sql/base/browser/ui/selectBox/selectBox';
import { MessageType } from 'vs/base/browser/ui/inputbox/inputBox';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { InputBox } from 'sql/base/browser/ui/inputBox/inputBox';
import * as types from 'vs/base/common/types';
import * as sqlops from 'sqlops';
import { localize } from 'vs/nls';
import { ServiceOptionType } from 'sql/workbench/api/common/sqlExtHostTypes';
export interface IOptionElement {
optionWidget: any;
option: sqlops.ServiceOption;
optionValue: any;
}
export function createOptionElement(option: sqlops.ServiceOption, rowContainer: Builder, options: { [name: string]: any },
optionsMap: { [optionName: string]: IOptionElement }, contextViewService: IContextViewService, onFocus: (name) => void): void {
let possibleInputs: string[] = [];
let optionValue = getOptionValueAndCategoryValues(option, options, possibleInputs);
let optionWidget: any;
let inputElement: HTMLElement;
let missingErrorMessage = localize('optionsDialog.missingRequireField', ' is required.');
let invalidInputMessage = localize('optionsDialog.invalidInput', 'Invalid input. Numeric value expected.');
if (option.valueType === ServiceOptionType.number) {
optionWidget = new InputBox(rowContainer.getHTMLElement(), contextViewService, {
validationOptions: {
validation: (value: string) => {
if (!value && option.isRequired) {
return { type: MessageType.ERROR, content: option.displayName + missingErrorMessage };
} else if (!types.isNumber(Number(value))) {
return { type: MessageType.ERROR, content: invalidInputMessage };
} else {
return null;
}
}
},
ariaLabel: option.displayName
});
optionWidget.value = optionValue;
inputElement = findElement(rowContainer, 'input');
} else if (option.valueType === ServiceOptionType.category || option.valueType === ServiceOptionType.boolean) {
optionWidget = new SelectBox(possibleInputs, optionValue.toString(), contextViewService);
DialogHelper.appendInputSelectBox(rowContainer, optionWidget);
inputElement = findElement(rowContainer, 'monaco-select-box');
} else if (option.valueType === ServiceOptionType.string || option.valueType === ServiceOptionType.password) {
optionWidget = new InputBox(rowContainer.getHTMLElement(), contextViewService, {
validationOptions: {
validation: (value: string) => (!value && option.isRequired) ? ({ type: MessageType.ERROR, content: option.displayName + missingErrorMessage }) : null
},
ariaLabel: option.displayName
});
optionWidget.value = optionValue;
if (option.valueType === ServiceOptionType.password) {
optionWidget.inputElement.type = 'password';
}
inputElement = findElement(rowContainer, 'input');
}
optionsMap[option.name] = { optionWidget: optionWidget, option: option, optionValue: optionValue };
inputElement.onfocus = () => onFocus(option.name);
}
export function getOptionValueAndCategoryValues(option: sqlops.ServiceOption, options: { [optionName: string]: any }, possibleInputs: string[]): any {
var optionValue = option.defaultValue;
if (options[option.name]) {
// if the value type is boolean, the option value can be either boolean or string
if (option.valueType === ServiceOptionType.boolean) {
if (options[option.name] === true || options[option.name] === trueInputValue) {
optionValue = trueInputValue;
} else {
optionValue = falseInputValue;
}
} else {
optionValue = options[option.name];
}
}
if (option.valueType === ServiceOptionType.boolean || option.valueType === ServiceOptionType.category) {
// If the option is not required, the empty string should be add at the top of possible choices
if (!option.isRequired) {
possibleInputs.push('');
}
if (option.valueType === ServiceOptionType.boolean) {
possibleInputs.push(trueInputValue, falseInputValue);
} else {
option.categoryValues.map(c => possibleInputs.push(c.name));
}
// If the option value is not set and default value is null, the option value should be set to the first possible input.
if (optionValue === null || optionValue === undefined) {
optionValue = possibleInputs[0];
}
}
return optionValue;
}
export function validateInputs(optionsMap: { [optionName: string]: IOptionElement }): boolean {
let isValid = true;
let isFocused = false;
for (var optionName in optionsMap) {
var optionElement: IOptionElement = optionsMap[optionName];
var widget = optionElement.optionWidget;
var isInputBox = (optionElement.option.valueType === ServiceOptionType.string ||
optionElement.option.valueType === ServiceOptionType.password ||
optionElement.option.valueType === ServiceOptionType.number);
if (isInputBox) {
if (!widget.validate()) {
isValid = false;
if (!isFocused) {
isFocused = true;
widget.focus();
}
}
}
}
return isValid;
}
export function updateOptions(options: { [optionName: string]: any }, optionsMap: { [optionName: string]: IOptionElement }): void {
for (var optionName in optionsMap) {
var optionElement: IOptionElement = optionsMap[optionName];
if (optionElement.optionWidget.value !== options[optionName]) {
if (!optionElement.optionWidget.value && options[optionName]) {
delete options[optionName];
}
if (optionElement.optionWidget.value) {
if (optionElement.option.valueType === ServiceOptionType.boolean) {
options[optionName] = (optionElement.optionWidget.value === trueInputValue) ? true : false;
} else {
options[optionName] = optionElement.optionWidget.value;
}
}
optionElement.optionValue = options[optionName];
}
}
}
export let trueInputValue: string = 'True';
export let falseInputValue: string = 'False';
export function findElement(container: Builder, className: string): HTMLElement {
var elementBuilder: Builder = container;
while (elementBuilder.getHTMLElement()) {
var htmlElement = elementBuilder.getHTMLElement();
if (htmlElement.className === className) {
break;
}
elementBuilder = elementBuilder.child(0);
}
return elementBuilder.getHTMLElement();
}
export function groupOptionsByCategory(options: sqlops.ServiceOption[]): { [category: string]: sqlops.ServiceOption[] } {
var connectionOptionsMap: { [category: string]: sqlops.ServiceOption[] } = {};
options.forEach(option => {
var groupName = option.groupName;
if (groupName === null || groupName === undefined) {
groupName = 'General';
}
if (!!connectionOptionsMap[groupName]) {
connectionOptionsMap[groupName].push(option);
} else {
connectionOptionsMap[groupName] = [option];
}
});
return connectionOptionsMap;
}