diff --git a/src/sql/base/browser/builder.ts b/src/sql/base/browser/builder.ts deleted file mode 100644 index 9aa571d2c2..0000000000 --- a/src/sql/base/browser/builder.ts +++ /dev/null @@ -1,1435 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 'vs/css!sql/base/browser/builder'; -import * as types from 'vs/base/common/types'; -import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle'; -import * as strings from 'vs/base/common/strings'; -import * as assert from 'vs/base/common/assert'; -import * as DOM from 'vs/base/browser/dom'; - -/** - * Welcome to the monaco builder. The recommended way to use it is: - * - * import Builder = require('sql/base/browser/builder'); - * let $ = Builder.$; - * $(....).fn(...); - * - * See below for examples how to invoke the $(): - * - * $() - creates an offdom builder - * $(builder) - wraps the given builder - * $(builder[]) - wraps the given builders into a multibuilder - * $('div') - creates a div - * $('.big') - creates a div with class `big` - * $('#head') - creates a div with id `head` - * $('ul#head') - creates an unordered list with id `head` - * $('') - constructs a builder from the given HTML - * $('a', { href: 'back'}) - constructs a builder, similarly to the Builder#element() call - */ -export interface QuickBuilder { - (): Builder; - (builders: Builder[]): Builder; - (element: HTMLElement): Builder; - (element: HTMLElement[]): Builder; - (window: Window): Builder; - (htmlOrQuerySyntax: string): Builder; // Or, MultiBuilder - (name: string, args?: any, fn?: (builder: Builder) => any): Builder; - (one: string, two: string, three: string): Builder; - (builder: Builder): Builder; -} - -// --- Implementation starts here - -let MS_DATA_KEY = '_msDataKey'; -let DATA_BINDING_ID = '__$binding'; -let LISTENER_BINDING_ID = '__$listeners'; -let VISIBILITY_BINDING_ID = '__$visibility'; - -function data(element: any): any { - if (!element[MS_DATA_KEY]) { - element[MS_DATA_KEY] = {}; - } - - return element[MS_DATA_KEY]; -} - -function hasData(element: any): boolean { - return !!element[MS_DATA_KEY]; -} - -/** - * Wraps around the provided element to manipulate it and add more child elements. - */ -export class Builder implements IDisposable { - private currentElement: HTMLElement; - private offdom: boolean; - private container: HTMLElement; - private createdElements: HTMLElement[]; - private toDispose: { [type: string]: IDisposable[]; }; - private captureToDispose: { [type: string]: IDisposable[]; }; - - constructor(element?: HTMLElement, offdom?: boolean) { - this.offdom = offdom; - - this.container = element; - - this.currentElement = element; - this.createdElements = []; - - this.toDispose = {}; - this.captureToDispose = {}; - } - - /** - * Returns a new builder that lets the current HTML Element of this builder be the container - * for future additions on the builder. - */ - asContainer(): Builder { - return withBuilder(this, this.offdom); - } - - /** - * Clones the builder providing the same properties as this one. - */ - clone(): Builder { - let builder = new Builder(this.container, this.offdom); - builder.currentElement = this.currentElement; - builder.createdElements = this.createdElements; - builder.captureToDispose = this.captureToDispose; - builder.toDispose = this.toDispose; - - return builder; - } - - /** - * Inserts all created elements of this builder as children to the given container. If the - * container is not provided, the element that was passed into the Builder at construction - * time is being used. The caller can provide the index of insertion, or omit it to append - * at the end. - * This method is a no-op unless the builder was created with the offdom option to be true. - */ - build(container?: Builder, index?: number): Builder; - build(container?: HTMLElement, index?: number): Builder; - build(container?: any, index?: number): Builder { - assert.ok(this.offdom, 'This builder was not created off-dom, so build() can not be called.'); - - // Use builders own container if present - if (!container) { - container = this.container; - } - - // Handle case of passed in Builder - else if (container instanceof Builder) { - container = (container).getHTMLElement(); - } - - assert.ok(container, 'Builder can only be build() with a container provided.'); - assert.ok(DOM.isHTMLElement(container), 'The container must either be a HTMLElement or a Builder.'); - - let htmlContainer = container; - - // Append - let i: number, len: number; - let childNodes = htmlContainer.childNodes; - if (types.isNumber(index) && index < childNodes.length) { - for (i = 0, len = this.createdElements.length; i < len; i++) { - htmlContainer.insertBefore(this.createdElements[i], childNodes[index++]); - } - } else { - for (i = 0, len = this.createdElements.length; i < len; i++) { - htmlContainer.appendChild(this.createdElements[i]); - } - } - - return this; - } - - /** - * Similar to #build, but does not require that the builder is off DOM, and instead - * attached the current element. If the current element has a parent, it will be - * detached from that parent. - */ - appendTo(container?: Builder, index?: number): Builder; - appendTo(container?: HTMLElement, index?: number): Builder; - appendTo(container?: any, index?: number): Builder { - - // Use builders own container if present - if (!container) { - container = this.container; - } - - // Handle case of passed in Builder - else if (container instanceof Builder) { - container = (container).getHTMLElement(); - } - - assert.ok(container, 'Builder can only be build() with a container provided.'); - assert.ok(DOM.isHTMLElement(container), 'The container must either be a HTMLElement or a Builder.'); - - let htmlContainer = container; - - // Remove node from parent, if needed - if (this.currentElement.parentNode) { - this.currentElement.parentNode.removeChild(this.currentElement); - } - - let childNodes = htmlContainer.childNodes; - if (types.isNumber(index) && index < childNodes.length) { - htmlContainer.insertBefore(this.currentElement, childNodes[index]); - } else { - htmlContainer.appendChild(this.currentElement); - } - - return this; - } - - /** - * Performs the exact reverse operation of #append. - * Doing `a.append(b)` is the same as doing `b.appendTo(a)`, with the difference - * of the return value being the builder which called the operation (`a` in the - * first case; `b` in the second case). - */ - append(child: HTMLElement, index?: number): Builder; - append(child: Builder, index?: number): Builder; - append(child: any, index?: number): Builder { - assert.ok(child, 'Need a child to append'); - - if (DOM.isHTMLElement(child)) { - child = withElement(child); - } - - assert.ok(child instanceof Builder || child instanceof MultiBuilder, 'Need a child to append'); - - (child).appendTo(this, index); - - return this; - } - - /** - * Removes the current element of this builder from its parent node. - */ - offDOM(): Builder { - if (this.currentElement.parentNode) { - this.currentElement.parentNode.removeChild(this.currentElement); - } - - return this; - } - - /** - * Returns the HTML Element the builder is currently active on. - */ - getHTMLElement(): HTMLElement { - return this.currentElement; - } - - /** - * Returns the HTML Element the builder is building in. - */ - getContainer(): HTMLElement { - return this.container; - } - - // HTML Elements - - /** - * Creates a new element of this kind as child of the current element or parent. - * Accepts an object literal as first parameter that can be used to describe the - * attributes of the element. - * Accepts a function as second parameter that can be used to create child elements - * of the element. The function will be called with a new builder created with the - * provided element. - */ - div(attributes?: any, fn?: (builder: Builder) => void): Builder { - return this.doElement('div', attributes, fn); - } - - /** - * Creates a new element of this kind as child of the current element or parent. - * Accepts an object literal as first parameter that can be used to describe the - * attributes of the element. - * Accepts a function as second parameter that can be used to create child elements - * of the element. The function will be called with a new builder created with the - * provided element. - */ - p(attributes?: any, fn?: (builder: Builder) => void): Builder { - return this.doElement('p', attributes, fn); - } - - /** - * Creates a new element of this kind as child of the current element or parent. - * Accepts an object literal as first parameter that can be used to describe the - * attributes of the element. - * Accepts a function as second parameter that can be used to create child elements - * of the element. The function will be called with a new builder created with the - * provided element. - */ - ul(attributes?: any, fn?: (builder: Builder) => void): Builder { - return this.doElement('ul', attributes, fn); - } - - /** - * Creates a new element of this kind as child of the current element or parent. - * Accepts an object literal as first parameter that can be used to describe the - * attributes of the element. - * Accepts a function as second parameter that can be used to create child elements - * of the element. The function will be called with a new builder created with the - * provided element. - */ - li(attributes?: any, fn?: (builder: Builder) => void): Builder { - return this.doElement('li', attributes, fn); - } - - /** - * Creates a new element of this kind as child of the current element or parent. - * Accepts an object literal as first parameter that can be used to describe the - * attributes of the element. - * Accepts a function as second parameter that can be used to create child elements - * of the element. The function will be called with a new builder created with the - * provided element. - */ - span(attributes?: any, fn?: (builder: Builder) => void): Builder { - return this.doElement('span', attributes, fn); - } - - /** - * Creates a new element of this kind as child of the current element or parent. - * Accepts an object literal as first parameter that can be used to describe the - * attributes of the element. - * Accepts a function as second parameter that can be used to create child elements - * of the element. The function will be called with a new builder created with the - * provided element. - */ - img(attributes?: any, fn?: (builder: Builder) => void): Builder { - return this.doElement('img', attributes, fn); - } - - /** - * Creates a new element of this kind as child of the current element or parent. - * Accepts an object literal as first parameter that can be used to describe the - * attributes of the element. - * Accepts a function as second parameter that can be used to create child elements - * of the element. The function will be called with a new builder created with the - * provided element. - */ - a(attributes?: any, fn?: (builder: Builder) => void): Builder { - return this.doElement('a', attributes, fn); - } - - /** - * Creates a new element of given tag name as child of the current element or parent. - * Accepts an object literal as first parameter that can be used to describe the - * attributes of the element. - * Accepts a function as second parameter that can be used to create child elements - * of the element. The function will be called with a new builder created with the - * provided element. - */ - element(name: string, attributes?: any, fn?: (builder: Builder) => void): Builder { - return this.doElement(name, attributes, fn); - } - - private doElement(name: string, attributesOrFn?: any, fn?: (builder: Builder) => void): Builder { - - // Create Element - let element = document.createElement(name); - this.currentElement = element; - - // Off-DOM: Remember in array of created elements - if (this.offdom) { - this.createdElements.push(element); - } - - // Object (apply properties as attributes to HTML element) - if (types.isObject(attributesOrFn)) { - this.attr(attributesOrFn); - } - - // Support second argument being function - if (types.isFunction(attributesOrFn)) { - fn = attributesOrFn; - } - - // Apply Functions (Elements created in Functions will be added as child to current element) - if (types.isFunction(fn)) { - let builder = new Builder(element); - fn.call(builder, builder); // Set both 'this' and the first parameter to the new builder - } - - // Add to parent - if (!this.offdom) { - this.container.appendChild(element); - } - - return this; - } - - /** - * Calls focus() on the current HTML element; - */ - domFocus(): Builder { - this.currentElement.focus(); - - return this; - } - - /** - * Calls blur() on the current HTML element; - */ - domBlur(): Builder { - this.currentElement.blur(); - - return this; - } - - /** - * Registers listener on event types on the current element. - */ - on(type: string, fn: (e: E, builder: Builder, unbind: IDisposable) => void, listenerToDisposeContainer?: IDisposable[], useCapture?: boolean): Builder; - on(typeArray: string[], fn: (e: E, builder: Builder, unbind: IDisposable) => void, listenerToDisposeContainer?: IDisposable[], useCapture?: boolean): Builder; - on(arg1: any, fn: (e: E, builder: Builder, unbind: IDisposable) => void, listenerToDisposeContainer?: IDisposable[], useCapture?: boolean): Builder { - - // Event Type Array - if (types.isArray(arg1)) { - arg1.forEach((type: string) => { - this.on(type, fn, listenerToDisposeContainer, useCapture); - }); - } - - // Single Event Type - else { - let type = arg1; - - // Add Listener - let unbind: IDisposable = DOM.addDisposableListener(this.currentElement, type, (e) => { - fn(e, this, unbind); // Pass in Builder as Second Argument - }, useCapture || false); - - // Remember for off() use - if (useCapture) { - if (!this.captureToDispose[type]) { - this.captureToDispose[type] = []; - } - this.captureToDispose[type].push(unbind); - } else { - if (!this.toDispose[type]) { - this.toDispose[type] = []; - } - this.toDispose[type].push(unbind); - } - - // Bind to Element - let listenerBinding: IDisposable[] = this.getProperty(LISTENER_BINDING_ID, []); - listenerBinding.push(unbind); - this.setProperty(LISTENER_BINDING_ID, listenerBinding); - - // Add to Array if passed in - if (listenerToDisposeContainer && types.isArray(listenerToDisposeContainer)) { - listenerToDisposeContainer.push(unbind); - } - } - - return this; - } - - /** - * Removes all listeners from all elements created by the builder for the given event type. - */ - off(type: string, useCapture?: boolean): Builder; - off(typeArray: string[], useCapture?: boolean): Builder; - off(arg1: any, useCapture?: boolean): Builder { - - // Event Type Array - if (types.isArray(arg1)) { - arg1.forEach((type: string) => { - this.off(type); - }); - } - - // Single Event Type - else { - let type = arg1; - if (useCapture) { - if (this.captureToDispose[type]) { - this.captureToDispose[type] = dispose(this.captureToDispose[type]); - } - } else { - if (this.toDispose[type]) { - this.toDispose[type] = dispose(this.toDispose[type]); - } - } - } - - return this; - } - - /** - * Registers listener on event types on the current element and removes - * them after first invocation. - */ - once(type: string, fn: (e: E, builder: Builder, unbind: IDisposable) => void, listenerToDisposeContainer?: IDisposable[], useCapture?: boolean): Builder; - once(typesArray: string[], fn: (e: E, builder: Builder, unbind: IDisposable) => void, listenerToDisposeContainer?: IDisposable[], useCapture?: boolean): Builder; - once(arg1: any, fn: (e: E, builder: Builder, unbind: IDisposable) => void, listenerToDisposeContainer?: IDisposable[], useCapture?: boolean): Builder { - - // Event Type Array - if (types.isArray(arg1)) { - arg1.forEach((type: string) => { - this.once(type, fn); - }); - } - - // Single Event Type - else { - let type = arg1; - - // Add Listener - let unbind: IDisposable = DOM.addDisposableListener(this.currentElement, type, (e) => { - fn(e, this, unbind); // Pass in Builder as Second Argument - unbind.dispose(); - }, useCapture || false); - - // Add to Array if passed in - if (listenerToDisposeContainer && types.isArray(listenerToDisposeContainer)) { - listenerToDisposeContainer.push(unbind); - } - } - - return this; - } - - /** - * This method has different characteristics based on the parameter provided: - * a) a single string passed in as argument will return the attribute value using the - * string as key from the current element of the builder. - * b) two strings passed in will set the value of an attribute identified by the first - * parameter to match the second parameter - * c) an object literal passed in will apply the properties of the literal as attributes - * to the current element of the builder. - */ - attr(name: string): string; - attr(name: string, value: string): Builder; - attr(name: string, value: boolean): Builder; - attr(name: string, value: number): Builder; - attr(attributes: any): Builder; - attr(firstP: any, secondP?: any): any { - - // Apply Object Literal to Attributes of Element - if (types.isObject(firstP)) { - for (let prop in firstP) { - if (firstP.hasOwnProperty(prop)) { - let value = firstP[prop]; - this.doSetAttr(prop, value); - } - } - - return this; - } - - // Get Attribute Value - if (types.isString(firstP) && !types.isString(secondP)) { - return this.currentElement.getAttribute(firstP); - } - - // Set Attribute Value - if (types.isString(firstP)) { - if (!types.isString(secondP)) { - secondP = String(secondP); - } - this.doSetAttr(firstP, secondP); - } - - return this; - } - - private doSetAttr(prop: string, value: any): void { - if (prop === 'class') { - prop = 'addClass'; // Workaround for the issue that a function name can not be 'class' in ES - } - - if ((this)[prop]) { - if (types.isArray(value)) { - (this)[prop].apply(this, value); - } else { - (this)[prop].call(this, value); - } - } else { - this.currentElement.setAttribute(prop, value); - } - } - - /** - * Removes an attribute by the given name. - */ - removeAttribute(prop: string): void { - this.currentElement.removeAttribute(prop); - } - - /** - * Sets the id attribute to the value provided for the current HTML element of the builder. - */ - id(id: string): Builder { - this.currentElement.setAttribute('id', id); - - return this; - } - - /** - * Sets the title attribute to the value provided for the current HTML element of the builder. - */ - title(title: string): Builder { - this.currentElement.setAttribute('title', title); - - return this; - } - - /** - * Sets the type attribute to the value provided for the current HTML element of the builder. - */ - type(type: string): Builder { - this.currentElement.setAttribute('type', type); - - return this; - } - - /** - * Sets the value attribute to the value provided for the current HTML element of the builder. - */ - value(value: string): Builder { - this.currentElement.setAttribute('value', value); - - return this; - } - - /** - * Sets the tabindex attribute to the value provided for the current HTML element of the builder. - */ - tabindex(index: number): Builder { - this.currentElement.setAttribute('tabindex', index.toString()); - - return this; - } - - /** - * This method has different characteristics based on the parameter provided: - * a) a single string passed in as argument will return the style value using the - * string as key from the current element of the builder. - * b) two strings passed in will set the style value identified by the first - * parameter to match the second parameter. The second parameter can be null - * to unset a style - * c) an object literal passed in will apply the properties of the literal as styles - * to the current element of the builder. - */ - style(name: string): string; - style(name: string, value: string): Builder; - style(attributes: any): Builder; - style(firstP: any, secondP?: any): any { - - // Apply Object Literal to Styles of Element - if (types.isObject(firstP)) { - for (let prop in firstP) { - if (firstP.hasOwnProperty(prop)) { - let value = firstP[prop]; - this.doSetStyle(prop, value); - } - } - - return this; - } - - const hasFirstP = types.isString(firstP); - - // Get Style Value - if (hasFirstP && types.isUndefined(secondP)) { - return this.currentElement.style[this.cssKeyToJavaScriptProperty(firstP)]; - } - - // Set Style Value - else if (hasFirstP) { - this.doSetStyle(firstP, secondP); - } - - return this; - } - - private doSetStyle(key: string, value: string): void { - if (key.indexOf('-') >= 0) { - let segments = key.split('-'); - key = segments[0]; - for (let i = 1; i < segments.length; i++) { - let segment = segments[i]; - key = key + segment.charAt(0).toUpperCase() + segment.substr(1); - } - } - - this.currentElement.style[this.cssKeyToJavaScriptProperty(key)] = value; - } - - private cssKeyToJavaScriptProperty(key: string): string { - // Automagically convert dashes as they are not allowed when programmatically - // setting a CSS style property - - if (key.indexOf('-') >= 0) { - let segments = key.split('-'); - key = segments[0]; - for (let i = 1; i < segments.length; i++) { - let segment = segments[i]; - key = key + segment.charAt(0).toUpperCase() + segment.substr(1); - } - } - - // Float is special too - else if (key === 'float') { - key = 'cssFloat'; - } - - return key; - } - - /** - * Returns the computed CSS style for the current HTML element of the builder. - */ - getComputedStyle(): CSSStyleDeclaration { - return DOM.getComputedStyle(this.currentElement); - } - - /** - * Adds the variable list of arguments as class names to the current HTML element of the builder. - */ - addClass(...classes: string[]): Builder { - classes.forEach((nameValue: string) => { - let names = nameValue.split(' '); - names.forEach((name: string) => { - DOM.addClass(this.currentElement, name); - }); - }); - - return this; - } - - /** - * Sets the class name of the current HTML element of the builder to the provided className. - * If shouldAddClass is provided - for true class is added, for false class is removed. - */ - setClass(className: string, shouldAddClass: boolean = null): Builder { - if (shouldAddClass === null) { - this.currentElement.className = className; - } else if (shouldAddClass) { - this.addClass(className); - } else { - this.removeClass(className); - } - - return this; - } - - /** - * Returns whether the current HTML element of the builder has the provided class assigned. - */ - hasClass(className: string): boolean { - return DOM.hasClass(this.currentElement, className); - } - - /** - * Removes the variable list of arguments as class names from the current HTML element of the builder. - */ - removeClass(...classes: string[]): Builder { - classes.forEach((nameValue: string) => { - let names = nameValue.split(' '); - names.forEach((name: string) => { - DOM.removeClass(this.currentElement, name); - }); - }); - - return this; - } - - /** - * Adds or removes the provided className for the current HTML element of the builder. - */ - toggleClass(className: string): Builder { - if (this.hasClass(className)) { - this.removeClass(className); - } else { - this.addClass(className); - } - - return this; - } - - /** - * Sets the CSS property color. - */ - color(color: string): Builder { - this.currentElement.style.color = color; - - return this; - } - - /** - * Sets the CSS property padding. - */ - padding(padding: string): Builder; - padding(top: number, right?: number, bottom?: number, left?: number): Builder; - padding(top: string, right?: string, bottom?: string, left?: string): Builder; - padding(top: any, right?: any, bottom?: any, left?: any): Builder { - if (types.isString(top) && top.indexOf(' ') >= 0) { - return this.padding.apply(this, top.split(' ')); - } - - if (!types.isUndefinedOrNull(top)) { - this.currentElement.style.paddingTop = this.toPixel(top); - } - - if (!types.isUndefinedOrNull(right)) { - this.currentElement.style.paddingRight = this.toPixel(right); - } - - if (!types.isUndefinedOrNull(bottom)) { - this.currentElement.style.paddingBottom = this.toPixel(bottom); - } - - if (!types.isUndefinedOrNull(left)) { - this.currentElement.style.paddingLeft = this.toPixel(left); - } - - return this; - } - - /** - * Sets the CSS property margin. - */ - margin(margin: string): Builder; - margin(top: number, right?: number, bottom?: number, left?: number): Builder; - margin(top: string, right?: string, bottom?: string, left?: string): Builder; - margin(top: any, right?: any, bottom?: any, left?: any): Builder { - if (types.isString(top) && top.indexOf(' ') >= 0) { - return this.margin.apply(this, top.split(' ')); - } - - if (!types.isUndefinedOrNull(top)) { - this.currentElement.style.marginTop = this.toPixel(top); - } - - if (!types.isUndefinedOrNull(right)) { - this.currentElement.style.marginRight = this.toPixel(right); - } - - if (!types.isUndefinedOrNull(bottom)) { - this.currentElement.style.marginBottom = this.toPixel(bottom); - } - - if (!types.isUndefinedOrNull(left)) { - this.currentElement.style.marginLeft = this.toPixel(left); - } - - return this; - } - - /** - * Sets the CSS property position. - */ - position(position: string): Builder; - position(top: number, right?: number, bottom?: number, left?: number, position?: string): Builder; - position(top: string, right?: string, bottom?: string, left?: string, position?: string): Builder; - position(top: any, right?: any, bottom?: any, left?: any, position?: string): Builder { - if (types.isString(top) && top.indexOf(' ') >= 0) { - return this.position.apply(this, top.split(' ')); - } - - if (!types.isUndefinedOrNull(top)) { - this.currentElement.style.top = this.toPixel(top); - } - - if (!types.isUndefinedOrNull(right)) { - this.currentElement.style.right = this.toPixel(right); - } - - if (!types.isUndefinedOrNull(bottom)) { - this.currentElement.style.bottom = this.toPixel(bottom); - } - - if (!types.isUndefinedOrNull(left)) { - this.currentElement.style.left = this.toPixel(left); - } - - if (!position) { - position = 'absolute'; - } - - this.currentElement.style.position = position; - - return this; - } - - /** - * Sets the CSS property size. - */ - size(size: string): Builder; - size(width: number, height?: number): Builder; - size(width: string, height?: string): Builder; - size(width: any, height?: any): Builder { - if (types.isString(width) && width.indexOf(' ') >= 0) { - return this.size.apply(this, width.split(' ')); - } - - if (!types.isUndefinedOrNull(width)) { - this.currentElement.style.width = this.toPixel(width); - } - - if (!types.isUndefinedOrNull(height)) { - this.currentElement.style.height = this.toPixel(height); - } - - return this; - } - - /** - * Sets the CSS property display. - */ - display(display: string): Builder { - this.currentElement.style.display = display; - - return this; - } - - /** - * Shows the current element of the builder. - */ - show(): Builder { - if (this.hasClass('monaco-builder-hidden')) { - this.removeClass('monaco-builder-hidden'); - } - - this.attr('aria-hidden', 'false'); - - // Cancel any pending showDelayed() invocation - this.cancelVisibilityTimeout(); - - return this; - } - - /** - * Shows the current builder element after the provided delay. If the builder - * was set to hidden using the hide() method before this method executed, the - * function will return without showing the current element. This is useful to - * only show the element when a specific delay is reached (e.g. for a long running - * operation. - */ - showDelayed(delay: number): Builder { - - // Cancel any pending showDelayed() invocation - this.cancelVisibilityTimeout(); - - // Install new delay for showing - const handle = setTimeout(() => { - this.removeProperty(VISIBILITY_BINDING_ID); - this.show(); - }, delay); - - this.setProperty(VISIBILITY_BINDING_ID, toDisposable(() => clearTimeout(handle))); - - return this; - } - - /** - * Hides the current element of the builder. - */ - hide(): Builder { - if (!this.hasClass('monaco-builder-hidden')) { - this.addClass('monaco-builder-hidden'); - } - this.attr('aria-hidden', 'true'); - - // Cancel any pending showDelayed() invocation - this.cancelVisibilityTimeout(); - - return this; - } - - /** - * Returns true if the current element of the builder is hidden. - */ - isHidden(): boolean { - return this.hasClass('monaco-builder-hidden') || this.currentElement.style.display === 'none'; - } - - private cancelVisibilityTimeout(): void { - const visibilityDisposable = this.getProperty(VISIBILITY_BINDING_ID) as IDisposable; - if (visibilityDisposable) { - visibilityDisposable.dispose(); - this.removeProperty(VISIBILITY_BINDING_ID); - } - } - - private toPixel(obj: any): string { - if (obj.toString().indexOf('px') === -1) { - return obj.toString() + 'px'; - } - - return obj; - } - - /** - * Sets the innerHTML attribute. - */ - innerHtml(html: string, append?: boolean): Builder { - if (append) { - this.currentElement.innerHTML += html; - } else { - this.currentElement.innerHTML = html; - } - - return this; - } - - /** - * Sets the textContent property of the element. - * All HTML special characters will be escaped. - */ - text(text: string, append?: boolean): Builder { - if (append) { - // children is child Elements versus childNodes includes textNodes - if (this.currentElement.children.length === 0) { - this.currentElement.textContent += text; - } - else { - // if there are elements inside this node, append the string as a new text node - // to avoid wiping out the innerHTML and replacing it with only text content - this.currentElement.appendChild(document.createTextNode(text)); - } - } else { - this.currentElement.textContent = text; - } - - return this; - } - - /** - * Sets the innerHTML attribute in escaped form. - */ - safeInnerHtml(html: string, append?: boolean): Builder { - return this.innerHtml(strings.escape(html), append); - } - - /** - * Allows to store arbritary data into the current element. - */ - setProperty(key: string, value: any): Builder { - setPropertyOnElement(this.currentElement, key, value); - - return this; - } - - /** - * Allows to get arbritary data from the current element. - */ - getProperty(key: string, fallback?: any): any { - return getPropertyFromElement(this.currentElement, key, fallback); - } - - /** - * Removes a property from the current element that is stored under the given key. - */ - removeProperty(key: string): Builder { - if (hasData(this.currentElement)) { - delete data(this.currentElement)[key]; - } - - return this; - } - - /** - * Returns a new builder with the child at the given index. - */ - child(index = 0): Builder { - let children = this.currentElement.children; - - return withElement(children.item(index)); - } - - /** - * Recurse through all descendant nodes and remove their data binding. - */ - private unbindDescendants(current: HTMLElement): void { - if (current && current.children) { - for (let i = 0, length = current.children.length; i < length; i++) { - let element = current.children.item(i); - - // Unbind - if (hasData(element)) { - - // Listeners - let listeners: IDisposable[] = data(element)[LISTENER_BINDING_ID]; - if (types.isArray(listeners)) { - while (listeners.length) { - listeners.pop().dispose(); - } - } - - // Delete Data Slot - delete element[MS_DATA_KEY]; - } - - // Recurse - this.unbindDescendants(element); - } - } - } - - /** - * Removes all HTML elements from the current element of the builder. Will also clean up any - * event listners registered and also clear any data binding and properties stored - * to any child element. - */ - empty(): Builder { - this.unbindDescendants(this.currentElement); - - this.clearChildren(); - - if (this.offdom) { - this.createdElements = []; - } - - return this; - } - - /** - * Removes all HTML elements from the current element of the builder. - */ - clearChildren(): Builder { - - // Remove Elements - if (this.currentElement) { - DOM.clearNode(this.currentElement); - } - - return this; - } - - /** - * Removes the current HTML element and all its children from its parent and unbinds - * all listeners and properties set to the data slots. - */ - destroy(): void { - - if (this.currentElement) { - - // Remove from parent - if (this.currentElement.parentNode) { - this.currentElement.parentNode.removeChild(this.currentElement); - } - - // Empty to clear listeners and bindings from children - this.empty(); - - // Unbind - if (hasData(this.currentElement)) { - - // Listeners - let listeners: IDisposable[] = data(this.currentElement)[LISTENER_BINDING_ID]; - if (types.isArray(listeners)) { - while (listeners.length) { - listeners.pop().dispose(); - } - } - - // Delete Data Slot - delete this.currentElement[MS_DATA_KEY]; - } - } - - let type: string; - - for (type in this.toDispose) { - if (this.toDispose.hasOwnProperty(type) && types.isArray(this.toDispose[type])) { - this.toDispose[type] = dispose(this.toDispose[type]); - } - } - - for (type in this.captureToDispose) { - if (this.captureToDispose.hasOwnProperty(type) && types.isArray(this.captureToDispose[type])) { - this.captureToDispose[type] = dispose(this.captureToDispose[type]); - } - } - - // Nullify fields - this.currentElement = null; - this.container = null; - this.offdom = null; - this.createdElements = null; - this.captureToDispose = null; - this.toDispose = null; - } - - /** - * Removes the current HTML element and all its children from its parent and unbinds - * all listeners and properties set to the data slots. - */ - dispose(): void { - this.destroy(); - } - - /** - * Gets the size (in pixels) of an element, including the margin. - */ - getTotalSize(): DOM.Dimension { - let totalWidth = DOM.getTotalWidth(this.currentElement); - let totalHeight = DOM.getTotalHeight(this.currentElement); - - return new DOM.Dimension(totalWidth, totalHeight); - } - - /** - * Another variant of getting the inner dimensions of an element. - */ - getClientArea(): DOM.Dimension { - return DOM.getClientArea(this.currentElement); - } -} - -/** - * The multi builder provides the same methods as the builder, but allows to call - * them on an array of builders. - */ -export class MultiBuilder extends Builder { - - length: number; - - private builders: Builder[]; - - constructor(multiBuilder: MultiBuilder); - constructor(builder: Builder); - constructor(builders: Builder[]); - constructor(elements: HTMLElement[]); - constructor(builders: any) { - assert.ok(types.isArray(builders) || builders instanceof MultiBuilder, 'Expected Array or MultiBuilder as parameter'); - - super(); - this.length = 0; - this.builders = []; - - // Add Builders to Array - if (types.isArray(builders)) { - for (let i = 0; i < builders.length; i++) { - if (builders[i] instanceof HTMLElement) { - this.push(withElement(builders[i])); - } else { - this.push(builders[i]); - } - } - } else { - for (let i = 0; i < (builders).length; i++) { - this.push((builders).item(i)); - } - } - - // Mixin Builder functions to operate on all builders - let $outer = this; - let propertyFn = (prop: string) => { - ($outer)[prop] = function (): any { - let args = Array.prototype.slice.call(arguments); - - let returnValues: any[]; - let mergeBuilders = false; - - for (let i = 0; i < $outer.length; i++) { - let res = ($outer.item(i))[prop].apply($outer.item(i), args); - - // Merge MultiBuilders into one - if (res instanceof MultiBuilder) { - if (!returnValues) { - returnValues = []; - } - mergeBuilders = true; - - for (let j = 0; j < (res).length; j++) { - returnValues.push((res).item(j)); - } - } - - // Any other Return Type (e.g. boolean, integer) - else if (!types.isUndefined(res) && !(res instanceof Builder)) { - if (!returnValues) { - returnValues = []; - } - - returnValues.push(res); - } - } - - if (returnValues && mergeBuilders) { - return new MultiBuilder(returnValues); - } - - return returnValues || $outer; - }; - }; - - for (let prop in Builder.prototype) { - if (prop !== 'clone' && prop !== 'and') { // Skip methods that are explicitly defined in MultiBuilder - if (Builder.prototype.hasOwnProperty(prop) && types.isFunction((Builder).prototype[prop])) { - propertyFn(prop); - } - } - } - } - - item(i: number): Builder { - return this.builders[i]; - } - - push(...items: Builder[]): void { - for (let i = 0; i < items.length; i++) { - this.builders.push(items[i]); - } - - this.length = this.builders.length; - } - - clone(): MultiBuilder { - return new MultiBuilder(this); - } -} - -function withBuilder(builder: Builder, offdom?: boolean): Builder { - if (builder instanceof MultiBuilder) { - return new MultiBuilder((builder)); - } - - return new Builder(builder.getHTMLElement(), offdom); -} - -export function withElement(element: HTMLElement, offdom?: boolean): Builder { - return new Builder(element, offdom); -} - -function offDOM(): Builder { - return new Builder(null, true); -} - -// Binding functions - -/** - * Allows to store arbritary data into element. - */ -export function setPropertyOnElement(element: HTMLElement, key: string, value: any): void { - data(element)[key] = value; -} - -/** - * Allows to get arbritary data from element. - */ -export function getPropertyFromElement(element: HTMLElement, key: string, fallback?: any): any { - if (hasData(element)) { - let value = data(element)[key]; - if (!types.isUndefined(value)) { - return value; - } - } - - return fallback; -} - -/** - * Adds the provided object as property to the given element. Call getBinding() - * to retrieve it again. - */ -export function bindElement(element: HTMLElement, object: any): void { - setPropertyOnElement(element, DATA_BINDING_ID, object); -} - -let SELECTOR_REGEX = /([\w\-]+)?(#([\w\-]+))?((.([\w\-]+))*)/; - -export const $: QuickBuilder = function (arg?: any): Builder { - - // Off-DOM use - if (types.isUndefined(arg)) { - return offDOM(); - } - - // Falsified values cause error otherwise - if (!arg) { - throw new Error('Bad use of $'); - } - - // Wrap the given element - if (DOM.isHTMLElement(arg) || arg === window) { - return withElement(arg); - } - - // Wrap the given builders - if (types.isArray(arg)) { - return new MultiBuilder(arg); - } - - // Wrap the given builder - if (arg instanceof Builder) { - return withBuilder((arg)); - } - - if (types.isString(arg)) { - - // Use the argument as HTML code - if (arg[0] === '<') { - let element: Node; - let container = document.createElement('div'); - container.innerHTML = strings.format.apply(strings, <[string, ...any[]]>(arguments)); - - if (container.children.length === 0) { - throw new Error('Bad use of $'); - } - - if (container.children.length === 1) { - element = container.firstChild; - container.removeChild(element); - - return withElement(element); - } - - let builders: Builder[] = []; - while (container.firstChild) { - element = container.firstChild; - container.removeChild(element); - builders.push(withElement(element)); - } - - return new MultiBuilder(builders); - } - - // Use the argument as a selector constructor - else if (arguments.length === 1) { - let match = SELECTOR_REGEX.exec(arg); - if (!match) { - throw new Error('Bad use of $'); - } - - let tag = match[1] || 'div'; - let id = match[3] || undefined; - let classes = (match[4] || '').replace(/\./g, ' '); - - let props: any = {}; - if (id) { - props['id'] = id; - } - - if (classes) { - props['class'] = classes; - } - - return offDOM().element(tag, props); - } - - // Use the arguments as the arguments to Builder#element(...) - else { - let result = offDOM(); - result.element.apply(result, <[string, any?, ((builder: Builder) => void)?]>(arguments)); - return result; - } - } else { - throw new Error('Bad use of $'); - } -}; diff --git a/src/sql/base/browser/builder.css b/src/sql/base/browser/dom.ts similarity index 77% rename from src/sql/base/browser/builder.css rename to src/sql/base/browser/dom.ts index 393cd62c7d..f086a96b78 100644 --- a/src/sql/base/browser/builder.css +++ b/src/sql/base/browser/dom.ts @@ -3,6 +3,6 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ - .monaco-builder-hidden { - display: none !important; -} \ No newline at end of file +export function isHidden(element: HTMLElement): boolean { + return element.style.display === 'none'; +} diff --git a/src/sql/parts/disasterRecovery/backup/backupDialog.ts b/src/sql/parts/disasterRecovery/backup/backupDialog.ts index d664830bb8..756b2b2793 100644 --- a/src/sql/parts/disasterRecovery/backup/backupDialog.ts +++ b/src/sql/parts/disasterRecovery/backup/backupDialog.ts @@ -8,28 +8,25 @@ import { IConnectionProfile } from 'sql/platform/connection/common/interfaces'; import { BackupModule } from 'sql/parts/disasterRecovery/backup/backup.module'; import { BACKUP_SELECTOR } from 'sql/parts/disasterRecovery/backup/backup.component'; import { attachModalDialogStyler } from 'sql/platform/theme/common/styler'; -import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement'; import * as TelemetryKeys from 'sql/common/telemetryKeys'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { Builder } from 'sql/base/browser/builder'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { bootstrapAngular } from 'sql/services/bootstrap/bootstrapService'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; +import { append, $ } from 'vs/base/browser/dom'; export class BackupDialog extends Modal { - private _bodyBuilder: Builder; + private _body: HTMLElement; private _backupTitle: string; - private _uniqueSelector: string; private _moduleRef: any; constructor( @IThemeService themeService: IThemeService, @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, - @IConnectionManagementService private _connectionManagementService: IConnectionManagementService, @ITelemetryService telemetryService: ITelemetryService, @IContextKeyService contextKeyService: IContextKeyService, @IInstantiationService private _instantiationService: IInstantiationService, @@ -39,9 +36,7 @@ export class BackupDialog extends Modal { } protected renderBody(container: HTMLElement) { - new Builder(container).div({ 'class': 'backup-dialog' }, (builder) => { - this._bodyBuilder = builder; - }); + this._body = append(container, $('.backup-dialog')); } public render() { @@ -49,14 +44,14 @@ export class BackupDialog extends Modal { attachModalDialogStyler(this, this._themeService); // Add angular component template to dialog body - this.bootstrapAngular(this._bodyBuilder.getHTMLElement()); + this.bootstrapAngular(this._body); } /** * Get the bootstrap params and perform the bootstrap */ private bootstrapAngular(bodyContainer: HTMLElement) { - this._uniqueSelector = bootstrapAngular(this._instantiationService, + bootstrapAngular(this._instantiationService, BackupModule, bodyContainer, BACKUP_SELECTOR, diff --git a/src/sql/parts/disasterRecovery/restore/restoreDialog.ts b/src/sql/parts/disasterRecovery/restore/restoreDialog.ts index 8e772193fb..b31e4b27ee 100644 --- a/src/sql/parts/disasterRecovery/restore/restoreDialog.ts +++ b/src/sql/parts/disasterRecovery/restore/restoreDialog.ts @@ -3,9 +3,8 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; import 'vs/css!./media/restoreDialog'; -import { Builder, $ } from 'sql/base/browser/builder'; + import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { Event, Emitter } from 'vs/base/common/event'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; @@ -18,6 +17,8 @@ import { localize } from 'vs/nls'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { mixin } from 'vs/base/common/objects'; import * as strings from 'vs/base/common/strings'; +import { ILayoutService } from 'vs/platform/layout/browser/layoutService'; +import * as DOM from 'vs/base/browser/dom'; import * as azdata from 'azdata'; @@ -41,8 +42,6 @@ import { TabbedPanel, PanelTabIdentifier } from 'sql/base/browser/ui/panel/panel import { ServiceOptionType } from 'sql/workbench/api/common/sqlExtHostTypes'; import { IClipboardService } from 'sql/platform/clipboard/common/clipboardService'; import { IFileBrowserDialogController } from 'sql/workbench/services/fileBrowser/common/fileBrowserDialogController'; -import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; -import { ILayoutService } from 'vs/platform/layout/browser/layoutService'; interface FileListElement { logicalFileName: string; @@ -129,7 +128,7 @@ export class RestoreDialog extends Modal { constructor( optionsMetadata: azdata.ServiceOption[], - @IWorkbenchLayoutService layoutService: ILayoutService, + @ILayoutService layoutService: ILayoutService, @IThemeService themeService: IThemeService, @IContextViewService private _contextViewService: IContextViewService, @ITelemetryService telemetryService: ITelemetryService, @@ -137,11 +136,11 @@ export class RestoreDialog extends Modal { @IFileBrowserDialogController private fileBrowserDialogService: IFileBrowserDialogController, @IClipboardService clipboardService: IClipboardService, ) { - super(localize('RestoreDialogTitle', 'Restore database'), TelemetryKeys.Restore, telemetryService, layoutService, clipboardService, themeService, contextKeyService, { hasErrors: true, isWide: true, hasSpinner: true }); - this._restoreTitle = localize('restoreDialog.restoreTitle', 'Restore database'); - this._databaseTitle = localize('restoreDialog.database', 'Database'); - this._backupFileTitle = localize('restoreDialog.backupFile', 'Backup file'); - this._restoreLabel = localize('restoreDialog.restore', 'Restore'); + super(localize('RestoreDialogTitle', "Restore database"), TelemetryKeys.Restore, telemetryService, layoutService, clipboardService, themeService, contextKeyService, { hasErrors: true, isWide: true, hasSpinner: true }); + this._restoreTitle = localize('restoreDialog.restoreTitle', "Restore database"); + this._databaseTitle = localize('restoreDialog.database', "Database"); + this._backupFileTitle = localize('restoreDialog.backupFile', "Backup file"); + this._restoreLabel = localize('restoreDialog.restore', "Restore"); // view model this.viewModel = new RestoreViewModel(optionsMetadata); @@ -169,225 +168,176 @@ export class RestoreDialog extends Modal { } protected renderBody(container: HTMLElement) { + const restoreFromElement = DOM.$('.restore-from'); + this.createLabelElement(restoreFromElement, localize('source', "Source"), true); + this._restoreFromSelectBox = this.createSelectBoxHelper(restoreFromElement, localize('restoreFrom', "Restore from"), [this._databaseTitle, this._backupFileTitle], this._databaseTitle); - let restoreFromElement; - $().div({ class: 'restore-from' }, (restoreFromContainer) => { - restoreFromElement = restoreFromContainer.getHTMLElement(); - this.createLabelElement(restoreFromContainer, localize('source', 'Source'), true); - this._restoreFromSelectBox = this.createSelectBoxHelper(restoreFromContainer, localize('restoreFrom', 'Restore from'), [this._databaseTitle, this._backupFileTitle], this._databaseTitle); - }); + this._restoreFromBackupFileElement = DOM.$('.backup-file-path'); + DOM.hide(this._restoreFromBackupFileElement); + const errorMessage = localize('missingBackupFilePathError', "Backup file path is required."); + const validationOptions: IInputOptions = { + validationOptions: { + validation: (value: string) => !value ? ({ type: MessageType.ERROR, content: errorMessage }) : null + }, + placeholder: localize('multipleBackupFilePath', "Please enter one or more file paths separated by commas"), + ariaLabel: LocalizedStrings.BACKFILEPATH + }; + const filePathInputContainer = DOM.append(this._restoreFromBackupFileElement, DOM.$('.dialog-input-section')); + DOM.append(filePathInputContainer, DOM.$('.dialog-label')).innerText = LocalizedStrings.BACKFILEPATH; - $().div({ class: 'backup-file-path' }, (filePathContainer) => { - filePathContainer.hide(); - this._restoreFromBackupFileElement = filePathContainer.getHTMLElement(); - let errorMessage = localize('missingBackupFilePathError', 'Backup file path is required.'); - let validationOptions: IInputOptions = { - validationOptions: { - validation: (value: string) => !value ? ({ type: MessageType.ERROR, content: errorMessage }) : null - }, - placeholder: localize('multipleBackupFilePath', 'Please enter one or more file paths separated by commas'), - ariaLabel: LocalizedStrings.BACKFILEPATH - }; + this._filePathInputBox = new InputBox(DOM.append(filePathInputContainer, DOM.$('.dialog-input')), this._contextViewService, validationOptions); - filePathContainer.div({ class: 'dialog-input-section' }, (inputContainer) => { - inputContainer.div({ class: 'dialog-label' }, (labelContainer) => { - labelContainer.safeInnerHtml(LocalizedStrings.BACKFILEPATH); - }); + this._browseFileButton = new Button(DOM.append(filePathInputContainer, DOM.$('.file-browser'))); + this._browseFileButton.label = '...'; - inputContainer.div({ class: 'dialog-input' }, (inputCellContainer) => { - this._filePathInputBox = new InputBox(inputCellContainer.getHTMLElement(), this._contextViewService, validationOptions); - }); - - inputContainer.div({ class: 'file-browser' }, (inputCellContainer) => { - this._browseFileButton = new Button(inputCellContainer.getHTMLElement()); - this._browseFileButton.label = '...'; - }); - }); - }); - - let sourceDatabasesElement; - $().div({ class: 'source-database-list' }, (sourceDatabasesContainer) => { - sourceDatabasesElement = sourceDatabasesContainer.getHTMLElement(); - this._sourceDatabaseSelectBox = this.createSelectBoxHelper(sourceDatabasesContainer, localize('database', 'Database'), [], ''); - }); + const sourceDatabasesElement = DOM.$('.source-database-list'); + this._sourceDatabaseSelectBox = this.createSelectBoxHelper(sourceDatabasesElement, localize('database', "Database"), [], ''); // Source section - let sourceElement: HTMLElement; - $().div({ class: 'source-section new-section' }, (sourceContainer) => { - sourceElement = sourceContainer.getHTMLElement(); - sourceContainer.append(restoreFromElement); - sourceContainer.append(this._restoreFromBackupFileElement); - sourceContainer.append(sourceDatabasesElement); - }); + const sourceElement = DOM.$('.source-section.new-section'); + sourceElement.append(restoreFromElement); + sourceElement.append(this._restoreFromBackupFileElement); + sourceElement.append(sourceDatabasesElement); // Destination section - let destinationElement: HTMLElement; - $().div({ class: 'destination-section new-section' }, (destinationContainer) => { - destinationElement = destinationContainer.getHTMLElement(); - this.createLabelElement(destinationContainer, localize('destination', 'Destination'), true); + const destinationElement = DOM.$('.destination-section.new-section'); + this.createLabelElement(destinationElement, localize('destination', "Destination"), true); - destinationContainer.div({ class: 'dialog-input-section' }, (inputContainer) => { - inputContainer.div({ class: 'dialog-label' }, (labelContainer) => { - labelContainer.text(LocalizedStrings.TARGETDATABASE); - }); + const destinationInputContainer = DOM.append(destinationElement, DOM.$('.dialog-input-section')); + DOM.append(destinationInputContainer, DOM.$('.dialog-label')).innerText = LocalizedStrings.TARGETDATABASE; - inputContainer.div({ class: 'dialog-input' }, (inputCellContainer) => { - // Get the bootstrap params and perform the bootstrap - inputCellContainer.style('width', '100%'); - this._databaseDropdown = new Dropdown(inputCellContainer.getHTMLElement(), this._contextViewService, this.layoutService, - { - strictSelection: false, - ariaLabel: LocalizedStrings.TARGETDATABASE, - actionLabel: localize('restoreDialog.toggleDatabaseNameDropdown', 'Select Database Toggle Dropdown') - } - ); - this._databaseDropdown.onValueChange(s => { - this.databaseSelected(s); - }); + const dropdownContainer = DOM.append(destinationInputContainer, DOM.$('.dialog-input')); - this._databaseDropdown.onBlur(() => { - this.databaseSelected(this._databaseDropdown.value); - }); + // Get the bootstrap params and perform the bootstrap + dropdownContainer.style.width = '100%'; - this._databaseDropdown.onFocus(() => { - this._onDatabaseListFocused.fire(); - }); - - this._databaseDropdown.value = this.viewModel.targetDatabaseName; - attachEditableDropdownStyler(this._databaseDropdown, this._themeService); - }); - }); - - this._destinationRestoreToInputBox = this.createInputBoxHelper(destinationContainer, localize('restoreTo', 'Restore to')); + this._databaseDropdown = new Dropdown(dropdownContainer, this._contextViewService, this.layoutService, + { + strictSelection: false, + ariaLabel: LocalizedStrings.TARGETDATABASE, + actionLabel: localize('restoreDialog.toggleDatabaseNameDropdown', 'Select Database Toggle Dropdown') + } + ); + this._databaseDropdown.onValueChange(s => { + this.databaseSelected(s); }); + this._databaseDropdown.onBlur(() => { + this.databaseSelected(this._databaseDropdown.value); + }); + + this._databaseDropdown.onFocus(() => { + this._onDatabaseListFocused.fire(); + }); + + this._databaseDropdown.value = this.viewModel.targetDatabaseName; + attachEditableDropdownStyler(this._databaseDropdown, this._themeService); + + this._destinationRestoreToInputBox = this.createInputBoxHelper(destinationElement, localize('restoreTo', "Restore to")); // Restore plan section - let restorePlanElement: HTMLElement; - $().div({ class: 'restore-plan-section new-section' }, (restorePlanContainer) => { - restorePlanElement = restorePlanContainer.getHTMLElement(); - this.createLabelElement(restorePlanContainer, localize('restorePlan', 'Restore plan'), true); - this.createLabelElement(restorePlanContainer, localize('backupSetsToRestore', 'Backup sets to restore')); + const restorePlanElement = DOM.$('.restore-plan-section.new-section'); + this.createLabelElement(restorePlanElement, localize('restorePlan', "Restore plan"), true); + this.createLabelElement(restorePlanElement, localize('backupSetsToRestore', "Backup sets to restore")); - // Backup sets table - restorePlanContainer.div({ class: 'dialog-input-section restore-list' }, (labelContainer) => { - this._restorePlanTableContainer = labelContainer.getHTMLElement(); - labelContainer.hide(); - this._restorePlanData = new TableDataView(); - this._restorePlanTable = new Table(labelContainer.getHTMLElement(), - { dataProvider: this._restorePlanData, columns: this._restorePlanColumn }, { enableColumnReorder: false }); - this._restorePlanTable.setSelectionModel(new RowSelectionModel({ selectActiveRow: false })); - this._restorePlanTable.onSelectedRowsChanged((e, data) => this.backupFileCheckboxChanged(e, data)); - }); - }); + // Backup sets table + this._restorePlanTableContainer = DOM.append(restorePlanElement, DOM.$('.dialog-input-section.restore-list')); + DOM.hide(this._restorePlanTableContainer); + this._restorePlanData = new TableDataView(); + this._restorePlanTable = new Table(this._restorePlanTableContainer, + { dataProvider: this._restorePlanData, columns: this._restorePlanColumn }, { enableColumnReorder: false }); + this._restorePlanTable.setSelectionModel(new RowSelectionModel({ selectActiveRow: false })); + this._restorePlanTable.onSelectedRowsChanged((e, data) => this.backupFileCheckboxChanged(e, data)); // Content in general tab - let generalTab = $('.restore-dialog'); + const generalTab = DOM.$('.restore-dialog'); generalTab.append(sourceElement); generalTab.append(destinationElement); generalTab.append(restorePlanElement); // Content in file tab - let fileContentElement: HTMLElement; - $().div({ class: 'restore-dialog' }, (builder) => { - fileContentElement = builder.getHTMLElement(); + const fileContentElement = DOM.$('.restore-dialog'); + const restoreAsSectionContainer = DOM.append(fileContentElement, DOM.$('.new-section')); - // Restore database file as section - builder.div({ class: 'new-section' }, (sectionContainer) => { - this.createLabelElement(sectionContainer, localize('restoreDatabaseFileAs', 'Restore database files as'), true); - this.createOptionControl(sectionContainer, this._relocateDatabaseFilesOption); - sectionContainer.div({ class: 'sub-section' }, (subSectionContainer) => { - this.createOptionControl(subSectionContainer, this._relocatedDataFileFolderOption); - this.createOptionControl(subSectionContainer, this._relocatedLogFileFolderOption); - }); - }); + this.createLabelElement(restoreAsSectionContainer, localize('restoreDatabaseFileAs', "Restore database files as"), true); + this.createOptionControl(restoreAsSectionContainer, this._relocateDatabaseFilesOption); + const subSectionContainer = DOM.append(restoreAsSectionContainer, DOM.$('.sub-section')); + this.createOptionControl(subSectionContainer, this._relocatedDataFileFolderOption); + this.createOptionControl(subSectionContainer, this._relocatedLogFileFolderOption); - // Restore database file details section - builder.div({ class: 'new-section' }, (sectionContainer) => { - this.createLabelElement(sectionContainer, localize('restoreDatabaseFileDetails', 'Restore database file details'), true); - // file list table - sectionContainer.div({ class: 'dialog-input-section restore-list' }, (fileNameContainer) => { - this._fileListTableContainer = fileNameContainer.getHTMLElement(); - fileNameContainer.hide(); - let logicalFileName = localize('logicalFileName', 'Logical file Name'); - let fileType = localize('fileType', 'File type'); - let originalFileName = localize('originalFileName', 'Original File Name'); - let restoreAs = localize('restoreAs', 'Restore as'); - var columns = [{ - id: 'logicalFileName', - name: logicalFileName, - field: 'logicalFileName' - }, { - id: 'fileType', - name: fileType, - field: 'fileType' - }, { - id: 'originalFileName', - name: originalFileName, - field: 'originalFileName' - }, { - id: 'restoreAs', - name: restoreAs, - field: 'restoreAs' - }]; - this._fileListData = new TableDataView(); - this._fileListTable = new Table(fileNameContainer.getHTMLElement(), - { dataProvider: this._fileListData, columns }, { enableColumnReorder: false }); - this._fileListTable.setSelectionModel(new RowSelectionModel()); - }); - }); - }); + // Restore database file details section + + const restoreFileSectionContainer = DOM.append(fileContentElement, DOM.$('.new-section')); + this.createLabelElement(restoreFileSectionContainer, localize('restoreDatabaseFileDetails', "Restore database file details"), true); + // file list table + this._fileListTableContainer = DOM.append(restoreFileSectionContainer, DOM.$('.dialog-input-section.restore-list')); + DOM.hide(this._fileListTableContainer); + const logicalFileName = localize('logicalFileName', "Logical file Name"); + const fileType = localize('fileType', "File type"); + const originalFileName = localize('originalFileName', "Original File Name"); + const restoreAs = localize('restoreAs', "Restore as"); + const columns = [{ + id: 'logicalFileName', + name: logicalFileName, + field: 'logicalFileName' + }, { + id: 'fileType', + name: fileType, + field: 'fileType' + }, { + id: 'originalFileName', + name: originalFileName, + field: 'originalFileName' + }, { + id: 'restoreAs', + name: restoreAs, + field: 'restoreAs' + }]; + this._fileListData = new TableDataView(); + this._fileListTable = new Table(this._fileListTableContainer, + { dataProvider: this._fileListData, columns }, { enableColumnReorder: false }); + this._fileListTable.setSelectionModel(new RowSelectionModel()); // Content in options tab - let optionsContentElement: HTMLElement; - $().div({ class: 'restore-dialog' }, (builder) => { - optionsContentElement = builder.getHTMLElement(); + const optionsContentElement = DOM.$('.restore-dialog'); + // Restore options section + const restoreOptions = DOM.append(optionsContentElement, DOM.$('.new-section')); + this.createLabelElement(restoreOptions, localize('restoreOptions', "Restore options"), true); + this.createOptionControl(restoreOptions, this._withReplaceDatabaseOption); + this.createOptionControl(restoreOptions, this._withKeepReplicationOption); + this.createOptionControl(restoreOptions, this._withRestrictedUserOption); + this.createOptionControl(restoreOptions, this._recoveryStateOption); - // Restore options section - builder.div({ class: 'new-section' }, (sectionContainer) => { - this.createLabelElement(sectionContainer, localize('restoreOptions', 'Restore options'), true); - this.createOptionControl(sectionContainer, this._withReplaceDatabaseOption); - this.createOptionControl(sectionContainer, this._withKeepReplicationOption); - this.createOptionControl(sectionContainer, this._withRestrictedUserOption); - this.createOptionControl(sectionContainer, this._recoveryStateOption); + this.createOptionControl(DOM.append(restoreOptions, DOM.$('.sub-section')), this._standbyFileOption); - sectionContainer.div({ class: 'sub-section' }, (subSectionContainer) => { - this.createOptionControl(subSectionContainer, this._standbyFileOption); - }); - }); + // Tail-Log backup section + const tailLog = DOM.append(optionsContentElement, DOM.$('.new-section')); + this.createLabelElement(tailLog, localize('taillogBackup', "Tail-Log backup"), true); + this.createOptionControl(tailLog, this._takeTaillogBackupOption); + const tailLogOptions = DOM.append(tailLog, DOM.$('.sub-section')); + this.createOptionControl(tailLogOptions, this._tailLogWithNoRecoveryOption); + this.createOptionControl(tailLogOptions, this._tailLogBackupFileOption); - // Tail-Log backup section - builder.div({ class: 'new-section' }, (sectionContainer) => { - this.createLabelElement(sectionContainer, localize('taillogBackup', 'Tail-Log backup'), true); - this.createOptionControl(sectionContainer, this._takeTaillogBackupOption); - sectionContainer.div({ class: 'sub-section' }, (subSectionContainer) => { - this.createOptionControl(subSectionContainer, this._tailLogWithNoRecoveryOption); - this.createOptionControl(subSectionContainer, this._tailLogBackupFileOption); - }); - }); + // Server connections section + const serverConnections = DOM.append(optionsContentElement, DOM.$('.new-section')); + this.createLabelElement(serverConnections, localize('serverConnection', "Server connections"), true); + this.createOptionControl(serverConnections, this._closeExistingConnectionsOption); - // Server connections section - builder.div({ class: 'new-section' }, (sectionContainer) => { - this.createLabelElement(sectionContainer, localize('serverConnection', 'Server connections'), true); - this.createOptionControl(sectionContainer, this._closeExistingConnectionsOption); - }); - }); - - let restorePanel = $('.restore-panel'); - container.appendChild(restorePanel.getHTMLElement()); - this._panel = new TabbedPanel(restorePanel.getHTMLElement()); + const restorePanel = DOM.$('.restore-panel'); + container.appendChild(restorePanel); + this._panel = new TabbedPanel(restorePanel); this._generalTabId = this._panel.pushTab({ identifier: 'general', title: localize('generalTitle', 'General'), view: { render: c => { - generalTab.appendTo(c); + DOM.append(c, generalTab); }, layout: () => { } } }); - let fileTab = this._panel.pushTab({ + const fileTab = this._panel.pushTab({ identifier: 'fileContent', title: localize('filesTitle', 'Files'), view: { @@ -469,19 +419,17 @@ export class RestoreDialog extends Modal { this._databaseDropdown.values = vals; } - private createLabelElement(container: Builder, content: string, isHeader?: boolean) { + private createLabelElement(container: HTMLElement, content: string, isHeader?: boolean) { let className = 'dialog-label'; if (isHeader) { className += ' header'; } - container.div({ class: className }, (labelContainer) => { - labelContainer.text(content); - }); + DOM.append(container, DOM.$(`.${className}`)).innerText = content; } - private createOptionControl(container: Builder, optionName: string): void { - let option = this.viewModel.getOptionMetadata(optionName); - let propertyWidget: any; + private createOptionControl(container: HTMLElement, optionName: string): void { + const option = this.viewModel.getOptionMetadata(optionName); + let propertyWidget: SelectBox | InputBox | Checkbox; switch (option.valueType) { case ServiceOptionType.boolean: propertyWidget = this.createCheckBoxHelper(container, option.description, @@ -522,63 +470,46 @@ export class RestoreDialog extends Modal { } } - private createCheckBoxHelper(container: Builder, label: string, isChecked: boolean, onCheck: (viaKeyboard: boolean) => void): Checkbox { - let checkbox: Checkbox; - container.div({ class: 'dialog-input-section' }, (inputCellContainer) => { - checkbox = new Checkbox(inputCellContainer.getHTMLElement(), { - label: label, - checked: isChecked, - onChange: onCheck, - ariaLabel: label - }); + private createCheckBoxHelper(container: HTMLElement, label: string, isChecked: boolean, onCheck: (viaKeyboard: boolean) => void): Checkbox { + const checkbox = new Checkbox(DOM.append(container, DOM.$('.dialog-input-section')), { + label: label, + checked: isChecked, + onChange: onCheck, + ariaLabel: label }); this._register(attachCheckboxStyler(checkbox, this._themeService)); return checkbox; } - private createSelectBoxHelper(container: Builder, label: string, options: string[], selectedOption: string): SelectBox { - let selectBox: SelectBox; - container.div({ class: 'dialog-input-section' }, (inputContainer) => { - inputContainer.div({ class: 'dialog-label' }, (labelContainer) => { - labelContainer.text(label); - }); - - inputContainer.div({ class: 'dialog-input' }, (inputCellContainer) => { - selectBox = new SelectBox(options, selectedOption, this._contextViewService, inputCellContainer.getHTMLElement(), { ariaLabel: label }); - selectBox.render(inputCellContainer.getHTMLElement()); - }); - }); + private createSelectBoxHelper(container: HTMLElement, label: string, options: string[], selectedOption: string): SelectBox { + const inputContainer = DOM.append(container, DOM.$('.dialog-input-section')); + DOM.append(inputContainer, DOM.$('.dialog-label')).innerText = label; + const inputCellContainer = DOM.append(inputContainer, DOM.$('.dialog-input')); + const selectBox = new SelectBox(options, selectedOption, this._contextViewService, inputCellContainer, { ariaLabel: label }); + selectBox.render(inputCellContainer); return selectBox; } - private createInputBoxHelper(container: Builder, label: string, options?: IInputOptions): InputBox { - let inputBox: InputBox; - let ariaOptions = { + private createInputBoxHelper(container: HTMLElement, label: string, options?: IInputOptions): InputBox { + const ariaOptions = { ariaLabel: label }; - container.div({ class: 'dialog-input-section' }, (inputContainer) => { - inputContainer.div({ class: 'dialog-label' }, (labelContainer) => { - labelContainer.safeInnerHtml(label); - }); - - inputContainer.div({ class: 'dialog-input' }, (inputCellContainer) => { - inputBox = new InputBox(inputCellContainer.getHTMLElement(), this._contextViewService, mixin(ariaOptions, options)); - }); - }); - return inputBox; + const inputContainer = DOM.append(container, DOM.$('.dialog-input-section')); + DOM.append(inputContainer, DOM.$('.dialog-label')).innerText = label; + return new InputBox(DOM.append(inputContainer, DOM.$('.dialog-input')), this._contextViewService, mixin(ariaOptions, options)); } private clearRestorePlanDataTable(): void { if (this._restorePlanData.getLength() > 0) { this._restorePlanData.clear(); - new Builder(this._restorePlanTableContainer).hide(); + DOM.hide(this._restorePlanTableContainer); } } private clearFileListTable(): void { if (this._fileListData.getLength() > 0) { this._fileListData.clear(); - new Builder(this._fileListTableContainer).hide(); + DOM.hide(this._fileListTableContainer); } } @@ -672,7 +603,7 @@ export class RestoreDialog extends Modal { } private onFileBrowsed(filepath: string) { - var oldFilePath = this._filePathInputBox.value; + const oldFilePath = this._filePathInputBox.value; if (strings.isFalsyOrWhitespace(this._filePathInputBox.value)) { this._filePathInputBox.value = filepath; } else { @@ -708,10 +639,10 @@ export class RestoreDialog extends Modal { this.removeErrorMessage(); if (selectedRestoreFrom === this._backupFileTitle) { this.viewModel.onRestoreFromChanged(true); - new Builder(this._restoreFromBackupFileElement).show(); + DOM.show(this._restoreFromBackupFileElement); } else { this.viewModel.onRestoreFromChanged(false); - new Builder(this._restoreFromBackupFileElement).hide(); + DOM.hide(this._restoreFromBackupFileElement); } this.resetRestoreContent(); } @@ -821,7 +752,7 @@ export class RestoreDialog extends Modal { } private updateRestoreOption(optionParam: RestoreOptionParam) { - let widget = this._optionsMap[optionParam.optionName]; + const widget = this._optionsMap[optionParam.optionName]; if (widget) { if (widget instanceof Checkbox) { (widget).checked = optionParam.value; @@ -847,7 +778,7 @@ export class RestoreDialog extends Modal { private updateRestoreDatabaseFiles(dbFiles: azdata.RestoreDatabaseFileInfo[]) { this.clearFileListTable(); if (dbFiles && dbFiles.length > 0) { - let data = []; + const data = []; for (let i = 0; i < dbFiles.length; i++) { data[i] = { logicalFileName: dbFiles[i].logicalFileName, @@ -856,7 +787,7 @@ export class RestoreDialog extends Modal { restoreAs: dbFiles[i].restoreAsFileName }; } - new Builder(this._fileListTableContainer).show(); + DOM.show(this._fileListTableContainer); this._fileListData.push(data); // Select the first row for the table by default @@ -867,7 +798,7 @@ export class RestoreDialog extends Modal { private updateBackupSetsToRestore(backupSetsToRestore: azdata.DatabaseFileInfo[]) { if (this._isBackupFileCheckboxChanged) { - let selectedRow = []; + const selectedRow = []; for (let i = 0; i < backupSetsToRestore.length; i++) { if (backupSetsToRestore[i].isSelected) { selectedRow.push(i); @@ -878,7 +809,7 @@ export class RestoreDialog extends Modal { this.clearRestorePlanDataTable(); if (backupSetsToRestore && backupSetsToRestore.length > 0) { if (!this._restorePlanColumn) { - let firstRow = backupSetsToRestore[0]; + const firstRow = backupSetsToRestore[0]; this._restorePlanColumn = firstRow.properties.map(item => { return { id: item.propertyName, @@ -887,18 +818,18 @@ export class RestoreDialog extends Modal { }; }); - let checkboxSelectColumn = new CheckboxSelectColumn({ title: this._restoreLabel, toolTip: this._restoreLabel, width: 15 }); + const checkboxSelectColumn = new CheckboxSelectColumn({ title: this._restoreLabel, toolTip: this._restoreLabel, width: 15 }); this._restorePlanColumn.unshift(checkboxSelectColumn.getColumnDefinition()); this._restorePlanTable.columns = this._restorePlanColumn; this._restorePlanTable.registerPlugin(checkboxSelectColumn); this._restorePlanTable.autosizeColumns(); } - let data = []; - let selectedRow = []; + const data = []; + const selectedRow = []; for (let i = 0; i < backupSetsToRestore.length; i++) { - let backupFile = backupSetsToRestore[i]; - let newData = {}; + const backupFile = backupSetsToRestore[i]; + const newData = {}; for (let j = 0; j < backupFile.properties.length; j++) { newData[backupFile.properties[j].propertyName] = backupFile.properties[j].propertyValueDisplayName; } @@ -907,7 +838,7 @@ export class RestoreDialog extends Modal { selectedRow.push(i); } } - new Builder(this._restorePlanTableContainer).show(); + DOM.show(this._restorePlanTableContainer); this._restorePlanData.push(data); this._restorePlanTable.setSelectedRows(selectedRow); this._restorePlanTable.setActiveCell(selectedRow[0], 0); diff --git a/src/sql/parts/jobManagement/views/jobStepsViewTree.ts b/src/sql/parts/jobManagement/views/jobStepsViewTree.ts index 34df0e7dcc..3f0175987e 100644 --- a/src/sql/parts/jobManagement/views/jobStepsViewTree.ts +++ b/src/sql/parts/jobManagement/views/jobStepsViewTree.ts @@ -10,7 +10,6 @@ import * as TreeDefaults from 'vs/base/parts/tree/browser/treeDefaults'; import { IMouseEvent } from 'vs/base/browser/mouseEvent'; import { generateUuid } from 'vs/base/common/uuid'; import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; -import { $ } from 'sql/base/browser/builder'; export class JobStepsViewRow { public stepId: string; @@ -135,7 +134,7 @@ export class JobStepsViewRenderer implements tree.IRenderer { stepIdCol.className += ' step-column-heading'; stepMessageCol.className += ' step-column-heading'; } - $(templateData.label).empty(); + DOM.clearNode(templateData.label); templateData.label.appendChild(stepIdCol); templateData.label.appendChild(stepNameCol); templateData.label.appendChild(stepMessageCol); diff --git a/src/sql/parts/modelComponents/dom.component.ts b/src/sql/parts/modelComponents/dom.component.ts index 6f58a32255..613299be84 100644 --- a/src/sql/parts/modelComponents/dom.component.ts +++ b/src/sql/parts/modelComponents/dom.component.ts @@ -5,17 +5,16 @@ import 'vs/css!./dom'; import 'vs/css!./highlight'; import 'vs/css!./markdown'; + import { - Component, Input, Inject, ChangeDetectorRef, forwardRef, ComponentFactoryResolver, - ViewChild, ViewChildren, ElementRef, Injector, OnDestroy, QueryList + Component, Input, Inject, ChangeDetectorRef, forwardRef, ElementRef, OnDestroy } from '@angular/core'; import * as azdata from 'azdata'; import * as DOM from 'vs/base/browser/dom'; -import { $, Builder } from 'sql/base/browser/builder'; import { ComponentBase } from 'sql/parts/modelComponents/componentBase'; -import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType } from 'sql/parts/modelComponents/interfaces'; +import { IComponent, IComponentDescriptor, IModelStore } from 'sql/parts/modelComponents/interfaces'; @Component({ template: '', @@ -25,8 +24,8 @@ export default class DomComponent extends ComponentBase implements IComponent, O @Input() descriptor: IComponentDescriptor; @Input() modelStore: IModelStore; private _renderedHtml: string; - private _rootElement: Builder; - private _bodyElement: Builder; + private _rootElement: HTMLElement; + private _bodyElement: HTMLElement; constructor( @Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef, @@ -48,8 +47,8 @@ export default class DomComponent extends ComponentBase implements IComponent, O } private createDomElement() { - this._rootElement = new Builder(this._el.nativeElement); - this._bodyElement = $('.dom-body'); + this._rootElement = this._el.nativeElement; + this._bodyElement = DOM.$('.dom-body'); this._rootElement.append(this._bodyElement); } @@ -57,14 +56,14 @@ export default class DomComponent extends ComponentBase implements IComponent, O private setHtml(): void { if (this.html) { this._renderedHtml = this.html; - this._bodyElement.innerHtml(this._renderedHtml); + this._bodyElement.innerHTML = this._renderedHtml; } } /// IComponent implementation public layout(): void { super.layout(); - let element = this._el.nativeElement; + const element = this._el.nativeElement; element.style.width = this.getWidth(); element.style.height = this.getHeight(); } diff --git a/src/sql/parts/objectExplorer/serverGroupDialog/serverGroupDialog.ts b/src/sql/parts/objectExplorer/serverGroupDialog/serverGroupDialog.ts index 0bb874545a..779d4f411a 100644 --- a/src/sql/parts/objectExplorer/serverGroupDialog/serverGroupDialog.ts +++ b/src/sql/parts/objectExplorer/serverGroupDialog/serverGroupDialog.ts @@ -3,9 +3,8 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; import 'vs/css!./media/serverGroupDialog'; -import { Builder } from 'sql/base/browser/builder'; + import { Checkbox } from 'vs/base/browser/ui/checkbox/checkbox'; import { MessageType } from 'vs/base/browser/ui/inputbox/inputBox'; import * as DOM from 'vs/base/browser/dom'; @@ -17,19 +16,18 @@ import { Event, Emitter } from 'vs/base/common/event'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { localize } from 'vs/nls'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { ILayoutService } from 'vs/platform/layout/browser/layoutService'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { Button } from 'sql/base/browser/ui/button/button'; import { Modal } from 'sql/workbench/browser/modal/modal'; import { InputBox } from 'sql/base/browser/ui/inputBox/inputBox'; import { ServerGroupViewModel } from 'sql/parts/objectExplorer/serverGroupDialog/serverGroupViewModel'; import { attachButtonStyler, attachModalDialogStyler } from 'sql/platform/theme/common/styler'; -import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import * as TelemetryKeys from 'sql/common/telemetryKeys'; import { IClipboardService } from 'sql/platform/clipboard/common/clipboardService'; -import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; export class ServerGroupDialog extends Modal { - private _bodyBuilder: Builder; private _addServerButton: Button; private _closeButton: Button; private _colorCheckBoxesMap: Array<{ color: string, checkbox: Checkbox }> = []; @@ -38,7 +36,7 @@ export class ServerGroupDialog extends Modal { private _groupDescriptionInputBox: InputBox; private _viewModel: ServerGroupViewModel; private _skipGroupNameValidation: boolean = false; - private $serverGroupContainer: Builder; + private _serverGroupContainer: HTMLElement; private _onAddServerGroup = new Emitter(); public onAddServerGroup: Event = this._onAddServerGroup.event; @@ -50,7 +48,7 @@ export class ServerGroupDialog extends Modal { public onCloseEvent: Event = this._onCloseEvent.event; constructor( - @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, + @ILayoutService layoutService: ILayoutService, @IThemeService themeService: IThemeService, @IContextViewService private _contextViewService: IContextViewService, @ITelemetryService telemetryService: ITelemetryService, @@ -63,8 +61,8 @@ export class ServerGroupDialog extends Modal { public render() { super.render(); attachModalDialogStyler(this, this._themeService); - let okLabel = localize('serverGroup.ok', 'OK'); - let cancelLabel = localize('serverGroup.cancel', 'Cancel'); + const okLabel = localize('serverGroup.ok', "OK"); + const cancelLabel = localize('serverGroup.cancel', "Cancel"); this._addServerButton = this.addFooterButton(okLabel, () => this.addGroup()); this._closeButton = this.addFooterButton(cancelLabel, () => this.cancel()); this.registerListeners(); @@ -75,68 +73,56 @@ export class ServerGroupDialog extends Modal { } protected renderBody(container: HTMLElement) { - new Builder(container).div({ class: 'server-group-dialog' }, (builder) => { - this._bodyBuilder = builder; - }); + const body = DOM.append(container, DOM.$('.server-group-dialog')); + // Connection Group Name - let serverGroupNameLabel = localize('connectionGroupName', 'Server group name'); - this._bodyBuilder.div({ class: 'dialog-label' }, (labelContainer) => { - labelContainer.text(serverGroupNameLabel); - }); - this._bodyBuilder.div({ class: 'input-divider' }, (inputCellContainer) => { - let errorMessage = localize('MissingGroupNameError', 'Group name is required.'); - this._groupNameInputBox = new InputBox(inputCellContainer.getHTMLElement(), this._contextViewService, { - validationOptions: { - validation: (value: string) => !value && !this._skipGroupNameValidation ? ({ type: MessageType.ERROR, content: errorMessage }) : null - }, - ariaLabel: serverGroupNameLabel - }); + const serverGroupNameLabel = localize('connectionGroupName', "Server group name"); + + DOM.append(body, DOM.$('.dialog-label')).innerText = serverGroupNameLabel; + + this._groupNameInputBox = new InputBox(DOM.append(body, DOM.$('.input-divider')), this._contextViewService, { + validationOptions: { + validation: (value: string) => !value && !this._skipGroupNameValidation ? ({ type: MessageType.ERROR, content: localize('MissingGroupNameError', "Group name is required.") }) : null + }, + ariaLabel: serverGroupNameLabel }); // Connection Group Description - let groupDescriptionLabel = localize('groupDescription', 'Group description'); - this._bodyBuilder.div({ class: 'dialog-label' }, (labelContainer) => { - labelContainer.text(groupDescriptionLabel); - }); - this._bodyBuilder.div({ class: 'input-divider' }, (inputCellContainer) => { - this._groupDescriptionInputBox = new InputBox(inputCellContainer.getHTMLElement(), this._contextViewService, { - ariaLabel: groupDescriptionLabel - }); + const groupDescriptionLabel = localize('groupDescription', "Group description"); + DOM.append(body, DOM.$('.dialog-label')).innerText = groupDescriptionLabel; + + this._groupDescriptionInputBox = new InputBox(DOM.append(body, DOM.$('.input-divider')), this._contextViewService, { + ariaLabel: groupDescriptionLabel }); // Connection Group Color - this._bodyBuilder.div({ class: 'dialog-label' }, (labelContainer) => { - let groupColorLabel = localize('groupColor', 'Group color'); - labelContainer.text(groupColorLabel); - }); + const groupColorLabel = localize('groupColor', "Group color"); + DOM.append(body, DOM.$('.dialog-label')).innerText = groupColorLabel; - this._bodyBuilder.div({ class: 'group-color-options' }, (groupColorContainer) => { - this.$serverGroupContainer = groupColorContainer; - this.fillGroupColors(groupColorContainer.getHTMLElement()); - }); + this._serverGroupContainer = DOM.append(body, DOM.$('.group-color-options')); + this.fillGroupColors(this._serverGroupContainer); - this._bodyBuilder.on(DOM.EventType.KEY_DOWN, (e: KeyboardEvent) => { - let event = new StandardKeyboardEvent(e); + DOM.addStandardDisposableListener(body, DOM.EventType.KEY_DOWN, (event: StandardKeyboardEvent) => { if (event.equals(KeyMod.Shift | KeyCode.Tab)) { - this.preventDefaultKeyboardEvent(e); + this.preventDefaultKeyboardEvent(event); this.focusPrevious(); } else if (event.equals(KeyCode.Tab)) { - this.preventDefaultKeyboardEvent(e); + this.preventDefaultKeyboardEvent(event); this.focusNext(); } else if (event.equals(KeyCode.RightArrow) || event.equals(KeyCode.LeftArrow)) { - this.preventDefaultKeyboardEvent(e); + this.preventDefaultKeyboardEvent(event); this.focusNextColor(event.equals(KeyCode.RightArrow)); } }); } - private preventDefaultKeyboardEvent(e: KeyboardEvent) { + private preventDefaultKeyboardEvent(e: StandardKeyboardEvent) { e.preventDefault(); e.stopPropagation(); } private isFocusOnColors(): boolean { - var result = false; + let result = false; this._colorCheckBoxesMap.forEach(({ checkbox }) => { if (document.activeElement === checkbox.domNode) { result = true; @@ -229,9 +215,9 @@ export class ServerGroupDialog extends Modal { private fillGroupColors(container: HTMLElement): void { for (let i = 0; i < this._viewModel.colors.length; i++) { - let color = this._viewModel.colors[i]; + const color = this._viewModel.colors[i]; - let colorCheckBox = new Checkbox({ + const colorCheckBox = new Checkbox({ actionClassName: 'server-group-color', title: color, isChecked: false @@ -277,9 +263,9 @@ export class ServerGroupDialog extends Modal { } public set viewModel(theViewModel: ServerGroupViewModel) { this._viewModel = theViewModel; - if (this.$serverGroupContainer) { - this.$serverGroupContainer.clearChildren(); - this.fillGroupColors(this.$serverGroupContainer.getHTMLElement()); + if (this._serverGroupContainer) { + DOM.clearNode(this._serverGroupContainer); + this.fillGroupColors(this._serverGroupContainer); } } diff --git a/src/sql/parts/objectExplorer/viewlet/serverTreeView.ts b/src/sql/parts/objectExplorer/viewlet/serverTreeView.ts index 692fcc51b6..e8166dce52 100644 --- a/src/sql/parts/objectExplorer/viewlet/serverTreeView.ts +++ b/src/sql/parts/objectExplorer/viewlet/serverTreeView.ts @@ -6,7 +6,6 @@ import 'vs/css!./media/serverTreeActions'; import * as errors from 'vs/base/common/errors'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import * as builder from 'sql/base/browser/builder'; import Severity from 'vs/base/common/severity'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { attachListStyler } from 'vs/platform/theme/common/styler'; @@ -14,6 +13,8 @@ import { ITree } from 'vs/base/parts/tree/browser/tree'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { localize } from 'vs/nls'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { Event, Emitter } from 'vs/base/common/event'; +import { append, $, hide, show } from 'vs/base/browser/dom'; import { ConnectionProfileGroup } from 'sql/platform/connection/common/connectionProfileGroup'; import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile'; @@ -27,28 +28,27 @@ import { IObjectExplorerService } from 'sql/workbench/services/objectExplorer/co import { IConnectionProfile } from 'sql/platform/connection/common/interfaces'; import { Button } from 'sql/base/browser/ui/button/button'; import { attachButtonStyler } from 'sql/platform/theme/common/styler'; -import { Event, Emitter } from 'vs/base/common/event'; import { TreeNode, TreeItemCollapsibleState } from 'sql/parts/objectExplorer/common/treeNode'; import { SERVER_GROUP_CONFIG, SERVER_GROUP_AUTOEXPAND_CONFIG } from 'sql/parts/objectExplorer/serverGroupDialog/serverGroup.contribution'; import { IErrorMessageService } from 'sql/platform/errorMessage/common/errorMessageService'; import { ServerTreeActionProvider } from 'sql/parts/objectExplorer/viewlet/serverTreeActionProvider'; import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService'; - -const $ = builder.$; +import { isHidden } from 'sql/base/browser/dom'; /** * ServerTreeview implements the dynamic tree view. */ export class ServerTreeView { - public messages: builder.Builder; - private _buttonSection: builder.Builder; + public messages: HTMLElement; + private _buttonSection: HTMLElement; private _treeSelectionHandler: TreeSelectionHandler; private _activeConnectionsFilterAction: ActiveConnectionsFilterAction; private _tree: ITree; private _toDispose: IDisposable[] = []; private _onSelectionOrFocusChange: Emitter; private _actionProvider: ServerTreeActionProvider; + constructor( @IConnectionManagementService private _connectionManagementService: IConnectionManagementService, @IInstantiationService private _instantiationService: IInstantiationService, @@ -101,15 +101,17 @@ export class ServerTreeView { */ public renderBody(container: HTMLElement): Thenable { // Add div to display no connections found message and hide it by default - this.messages = $('div.title').appendTo(container); - $('span').style('padding-left', '10px').text('No connections found.').appendTo(this.messages); - this.messages.hide(); + this.messages = append(container, $('.title')); + const messageText = append(this.messages, $('span')); + messageText.style.paddingLeft = '10px'; + messageText.innerText = localize('servers.noConnections', "No connections found."); + hide(this.messages); if (!this._connectionManagementService.hasRegisteredServers()) { this._activeConnectionsFilterAction.enabled = false; - this._buttonSection = $('div.button-section').appendTo(container); - var connectButton = new Button(this._buttonSection.getHTMLElement()); - connectButton.label = localize('serverTree.addConnection', 'Add Connection'); + this._buttonSection = append(container, $('.button-section')); + const connectButton = new Button(this._buttonSection); + connectButton.label = localize('serverTree.addConnection', "Add Connection"); this._toDispose.push(attachButtonStyler(connectButton, this._themeService)); this._toDispose.push(connectButton.onDidClick(() => { this._connectionManagementService.showConnectionDialog(); @@ -124,41 +126,41 @@ export class ServerTreeView { // Theme styler this._toDispose.push(attachListStyler(this._tree, this._themeService)); - const self = this; // Refresh Tree when these events are emitted this._toDispose.push(this._connectionManagementService.onAddConnectionProfile((newProfile: IConnectionProfile) => { - self.handleAddConnectionProfile(newProfile); + this.handleAddConnectionProfile(newProfile); })); this._toDispose.push(this._connectionManagementService.onDeleteConnectionProfile(() => { - self.refreshTree(); + this.refreshTree(); })); this._toDispose.push(this._connectionManagementService.onDisconnect((connectionParams) => { - if (self.isObjectExplorerConnectionUri(connectionParams.connectionUri)) { - self.deleteObjectExplorerNodeAndRefreshTree(connectionParams.connectionProfile); + if (this.isObjectExplorerConnectionUri(connectionParams.connectionUri)) { + this.deleteObjectExplorerNodeAndRefreshTree(connectionParams.connectionProfile); } })); if (this._objectExplorerService && this._objectExplorerService.onUpdateObjectExplorerNodes) { this._toDispose.push(this._objectExplorerService.onUpdateObjectExplorerNodes(args => { if (args.errorMessage) { - self.showError(args.errorMessage); + this.showError(args.errorMessage); } if (args.connection) { - self.onObjectExplorerSessionCreated(args.connection); + this.onObjectExplorerSessionCreated(args.connection); } })); } - return new Promise((resolve, reject) => { - self.refreshTree(); - let root = self._tree.getInput(); - let expandGroups: boolean = self._configurationService.getValue(SERVER_GROUP_CONFIG)[SERVER_GROUP_AUTOEXPAND_CONFIG]; + return new Promise((resolve, reject) => { + this.refreshTree(); + const root = this._tree.getInput(); + + const expandGroups: boolean = this._configurationService.getValue(SERVER_GROUP_CONFIG)[SERVER_GROUP_AUTOEXPAND_CONFIG]; if (expandGroups) { - self._tree.expandAll(ConnectionProfileGroup.getSubgroups(root)); + this._tree.expandAll(ConnectionProfileGroup.getSubgroups(root)); } if (root && !root.hasValidConnections) { - self._treeSelectionHandler.onTreeActionStateChange(true); + this._treeSelectionHandler.onTreeActionStateChange(true); resolve(); } else { resolve(); @@ -174,20 +176,20 @@ export class ServerTreeView { private async handleAddConnectionProfile(newProfile: IConnectionProfile): Promise { if (newProfile) { - let groups = this._connectionManagementService.getConnectionGroups(); - let profile = ConnectionUtils.findProfileInGroup(newProfile, groups); + const groups = this._connectionManagementService.getConnectionGroups(); + const profile = ConnectionUtils.findProfileInGroup(newProfile, groups); if (profile) { newProfile = profile; } } if (this._buttonSection) { - this._buttonSection.getHTMLElement().style.display = 'none'; + hide(this._buttonSection); this._activeConnectionsFilterAction.enabled = true; } - let currentSelections = this._tree.getSelection(); - let currentSelectedElement = currentSelections && currentSelections.length >= 1 ? currentSelections[0] : undefined; - let newProfileIsSelected = currentSelectedElement && newProfile ? currentSelectedElement.id === newProfile.id : false; + const currentSelections = this._tree.getSelection(); + const currentSelectedElement = currentSelections && currentSelections.length >= 1 ? currentSelections[0] : undefined; + const newProfileIsSelected = currentSelectedElement && newProfile ? currentSelectedElement.id === newProfile.id : false; if (newProfile && currentSelectedElement && !newProfileIsSelected) { this._tree.clearSelection(); } @@ -205,9 +207,9 @@ export class ServerTreeView { } private getConnectionInTreeInput(connectionId: string): ConnectionProfile { - let root = TreeUpdateUtils.getTreeInput(this._connectionManagementService); - let connections = ConnectionProfileGroup.getConnectionsInGroup(root); - let results = connections.filter(con => { + const root = TreeUpdateUtils.getTreeInput(this._connectionManagementService); + const connections = ConnectionProfileGroup.getConnectionsInGroup(root); + const results = connections.filter(con => { if (connectionId === con.id) { return true; } else { @@ -221,7 +223,7 @@ export class ServerTreeView { } private onObjectExplorerSessionCreated(connection: IConnectionProfile) { - var conn = this.getConnectionInTreeInput(connection.id); + const conn = this.getConnectionInTreeInput(connection.id); if (conn) { this._tree.refresh(conn).then(() => { return this._tree.expand(conn).then(() => { @@ -234,7 +236,7 @@ export class ServerTreeView { } public addObjectExplorerNodeAndRefreshTree(connection: IConnectionProfile): void { - this.messages.hide(); + hide(this.messages); if (!this._objectExplorerService.getObjectExplorerNode(connection)) { this._objectExplorerService.updateObjectExplorerNodes(connection).then(() => { // The oe request is sent. an event will be raised when the session is created @@ -245,7 +247,7 @@ export class ServerTreeView { public deleteObjectExplorerNodeAndRefreshTree(connection: IConnectionProfile): Thenable { if (connection) { - var conn = this.getConnectionInTreeInput(connection.id); + const conn = this.getConnectionInTreeInput(connection.id); if (conn) { return this._objectExplorerService.deleteObjectExplorerNode(conn).then(() => { this._tree.collapse(conn); @@ -257,7 +259,7 @@ export class ServerTreeView { } public refreshTree(): Promise { - this.messages.hide(); + hide(this.messages); this.clearOtherActions(); return TreeUpdateUtils.registeredServerUpdate(this._tree, this._connectionManagementService); } @@ -273,7 +275,7 @@ export class ServerTreeView { if (!treeInput || treeInput.length === 0) { return undefined; } - let result = treeInput.map(group => { + const result = treeInput.map(group => { // Keep active/recent connections and remove the rest if (group.connections) { group.connections = group.connections.filter(con => { @@ -305,28 +307,26 @@ export class ServerTreeView { * Set tree elements based on the view (recent/active) */ public showFilteredTree(view: string): void { - - const self = this; - this.messages.hide(); + hide(this.messages); // Clear other action views if user switched between two views this.clearOtherActions(view); - let root = TreeUpdateUtils.getTreeInput(this._connectionManagementService); + const root = TreeUpdateUtils.getTreeInput(this._connectionManagementService); let treeInput: ConnectionProfileGroup = null; if (root) { // Filter results based on view - let filteredResults = this.filterConnections([root], view); + const filteredResults = this.filterConnections([root], view); if (!filteredResults || !filteredResults[0]) { - this.messages.show(); - this.messages.domFocus(); + show(this.messages); + this.messages.focus(); } else { treeInput = filteredResults[0]; } this._tree.setInput(treeInput).then(() => { - if (this.messages.isHidden()) { - self._tree.getFocus(); - self._tree.expandAll(ConnectionProfileGroup.getSubgroups(treeInput)); + if (isHidden(this.messages)) { + this._tree.getFocus(); + this._tree.expandAll(ConnectionProfileGroup.getSubgroups(treeInput)); } else { - self._tree.clearFocus(); + this._tree.clearFocus(); } }, errors.onUnexpectedError); } else { @@ -341,25 +341,24 @@ export class ServerTreeView { if (!searchString) { return; } - const self = this; - this.messages.hide(); + hide(this.messages); // Clear other actions if user searched during other views this.clearOtherActions(); // Filter connections based on search - let filteredResults = this.searchConnections(searchString); + const filteredResults = this.searchConnections(searchString); if (!filteredResults || filteredResults.length === 0) { - this.messages.show(); - this.messages.domFocus(); + show(this.messages); + this.messages.focus(); } // Add all connections to tree root and set tree input - let treeInput = new ConnectionProfileGroup('searchroot', undefined, 'searchroot', undefined, undefined); + const treeInput = new ConnectionProfileGroup('searchroot', undefined, 'searchroot', undefined, undefined); treeInput.addConnections(filteredResults); this._tree.setInput(treeInput).then(() => { - if (this.messages.isHidden()) { - self._tree.getFocus(); - self._tree.expandAll(ConnectionProfileGroup.getSubgroups(treeInput)); + if (isHidden(this.messages)) { + this._tree.getFocus(); + this._tree.expandAll(ConnectionProfileGroup.getSubgroups(treeInput)); } else { - self._tree.clearFocus(); + this._tree.clearFocus(); } }, errors.onUnexpectedError); } @@ -369,9 +368,9 @@ export class ServerTreeView { */ private searchConnections(searchString: string): ConnectionProfile[] { - let root = TreeUpdateUtils.getTreeInput(this._connectionManagementService); - let connections = ConnectionProfileGroup.getConnectionsInGroup(root); - let results = connections.filter(con => { + const root = TreeUpdateUtils.getTreeInput(this._connectionManagementService); + const connections = ConnectionProfileGroup.getConnectionsInGroup(root); + const results = connections.filter(con => { if (searchString && (searchString.length > 0)) { return this.isMatch(con, searchString); } else { @@ -499,4 +498,4 @@ export class ServerTreeView { this._tree.dispose(); this._toDispose = dispose(this._toDispose); } -} \ No newline at end of file +} diff --git a/src/sql/parts/profiler/dialog/profilerColumnEditorDialog.ts b/src/sql/parts/profiler/dialog/profilerColumnEditorDialog.ts index 575a6f0107..03da1f043a 100644 --- a/src/sql/parts/profiler/dialog/profilerColumnEditorDialog.ts +++ b/src/sql/parts/profiler/dialog/profilerColumnEditorDialog.ts @@ -2,18 +2,18 @@ * 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 'vs/css!sql/parts/profiler/media/profiler'; import { Modal } from 'sql/workbench/browser/modal/modal'; import { attachModalDialogStyler } from 'sql/platform/theme/common/styler'; import { ProfilerInput } from 'sql/parts/profiler/editor/profilerInput'; import * as TelemetryKeys from 'sql/common/telemetryKeys'; +import { IClipboardService } from 'sql/platform/clipboard/common/clipboardService'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import * as nls from 'vs/nls'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { Builder } from 'sql/base/browser/builder'; import { SelectBox } from 'vs/base/browser/ui/selectBox/selectBox'; import { Tree } from 'vs/base/parts/tree/browser/treeImpl'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; @@ -24,7 +24,6 @@ import { Event, Emitter } from 'vs/base/common/event'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; -import { IClipboardService } from 'sql/platform/clipboard/common/clipboardService'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; class EventItem { @@ -209,8 +208,8 @@ class TreeRenderer implements IRenderer { } renderTemplate(tree: ITree, templateId: string, container: HTMLElement): RenderTemplate { - let data = Object.create(null); - let row = document.createElement('div'); + const data = Object.create(null); + const row = document.createElement('div'); row.className = 'tree-row'; DOM.append(container, row); data.toDispose = []; @@ -301,13 +300,11 @@ class TreeDataSource implements IDataSource { export class ProfilerColumnEditorDialog extends Modal { private _selectBox: SelectBox; - private _selectedValue: number = 0; private readonly _options = [ { text: nls.localize('eventSort', "Sort by event") }, { text: nls.localize('nameColumn', "Sort by column") } ]; private _tree: Tree; - private _input: ProfilerInput; private _element: SessionItem; private _treeContainer: HTMLElement; @@ -330,29 +327,22 @@ export class ProfilerColumnEditorDialog extends Modal { } protected renderBody(container: HTMLElement): void { - let builder = new Builder(container); - builder.div({}, b => { - this._selectBox = new SelectBox(this._options, 0, this._contextViewService); - this._selectBox.render(b.getHTMLElement()); - this._register(this._selectBox.onDidSelect(e => { - this._selectedValue = e.index; - this._element.changeSort(e.index === 0 ? 'event' : 'column'); - this._tree.refresh(this._element, true); - })); - }); - - builder.div({ 'class': 'profiler-column-tree' }, b => { - this._treeContainer = b.getHTMLElement(); - let renderer = new TreeRenderer(); - this._tree = new Tree(this._treeContainer, { dataSource: new TreeDataSource(), renderer }); - this._register(renderer.onSelectedChange(e => this._tree.refresh(e, true))); - this._register(attachListStyler(this._tree, this._themeService)); - }); + const body = DOM.append(container, DOM.$('')); + this._selectBox = new SelectBox(this._options, 0, this._contextViewService); + this._selectBox.render(body); + this._register(this._selectBox.onDidSelect(e => { + this._element.changeSort(e.index === 0 ? 'event' : 'column'); + this._tree.refresh(this._element, true); + })); + this._treeContainer = DOM.append(body, DOM.$('.profiler-column-tree')); + const renderer = new TreeRenderer(); + this._tree = new Tree(this._treeContainer, { dataSource: new TreeDataSource(), renderer }); + this._register(renderer.onSelectedChange(e => this._tree.refresh(e, true))); + this._register(attachListStyler(this._tree, this._themeService)); } public open(input: ProfilerInput): void { super.show(); - this._input = input; this._updateList(); } diff --git a/src/sql/parts/profiler/dialog/profilerFilterDialog.ts b/src/sql/parts/profiler/dialog/profilerFilterDialog.ts index 86283aacc4..f5f9ea75dc 100644 --- a/src/sql/parts/profiler/dialog/profilerFilterDialog.ts +++ b/src/sql/parts/profiler/dialog/profilerFilterDialog.ts @@ -3,7 +3,6 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; import 'vs/css!sql/media/icons/common-icons'; import 'vs/css!./media/profilerFilterDialog'; import { Button } from 'sql/base/browser/ui/button/button'; @@ -11,7 +10,6 @@ import { Modal } from 'sql/workbench/browser/modal/modal'; import * as TelemetryKeys from 'sql/common/telemetryKeys'; import { attachButtonStyler, attachModalDialogStyler, attachInputBoxStyler } from 'sql/platform/theme/common/styler'; import { KeyCode } from 'vs/base/common/keyCodes'; -import { Builder } from 'sql/base/browser/builder'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; @@ -29,19 +27,19 @@ import { ProfilerFilter, ProfilerFilterClause, ProfilerFilterClauseOperator } fr import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; -const ClearText: string = localize('profilerFilterDialog.clear', 'Clear All'); -const ApplyText: string = localize('profilerFilterDialog.apply', 'Apply'); -const OkText: string = localize('profilerFilterDialog.ok', 'OK'); -const CancelText: string = localize('profilerFilterDialog.cancel', 'Cancel'); -const DialogTitle: string = localize('profilerFilterDialog.title', 'Filters'); -const RemoveText: string = localize('profilerFilterDialog.remove', 'Remove'); -const AddText: string = localize('profilerFilterDialog.add', 'Add'); -const AddClausePromptText: string = localize('profilerFilterDialog.addClauseText', 'Click here to add a clause'); +const ClearText: string = localize('profilerFilterDialog.clear', "Clear All"); +const ApplyText: string = localize('profilerFilterDialog.apply', "Apply"); +const OkText: string = localize('profilerFilterDialog.ok', "OK"); +const CancelText: string = localize('profilerFilterDialog.cancel', "Cancel"); +const DialogTitle: string = localize('profilerFilterDialog.title', "Filters"); +const RemoveText: string = localize('profilerFilterDialog.remove', "Remove"); +const AddText: string = localize('profilerFilterDialog.add', "Add"); +const AddClausePromptText: string = localize('profilerFilterDialog.addClauseText', "Click here to add a clause"); const TitleIconClass: string = 'icon filterLabel'; -const FieldText: string = localize('profilerFilterDialog.fieldColumn', 'Field'); -const OperatorText: string = localize('profilerFilterDialog.operatorColumn', 'Operator'); -const ValueText: string = localize('profilerFilterDialog.valueColumn', 'Value'); +const FieldText: string = localize('profilerFilterDialog.fieldColumn', "Field"); +const OperatorText: string = localize('profilerFilterDialog.operatorColumn', "Operator"); +const ValueText: string = localize('profilerFilterDialog.valueColumn', "Value"); const Equals: string = '='; const NotEquals: string = '<>'; @@ -49,18 +47,18 @@ const LessThan: string = '<'; const LessThanOrEquals: string = '<='; const GreaterThan: string = '>'; const GreaterThanOrEquals: string = '>='; -const IsNull: string = localize('profilerFilterDialog.isNullOperator', 'Is Null'); -const IsNotNull: string = localize('profilerFilterDialog.isNotNullOperator', 'Is Not Null'); -const Contains: string = localize('profilerFilterDialog.containsOperator', 'Contains'); -const NotContains: string = localize('profilerFilterDialog.notContainsOperator', 'Not Contains'); -const StartsWith: string = localize('profilerFilterDialog.startsWithOperator', 'Starts With'); -const NotStartsWith: string = localize('profilerFilterDialog.notStartsWithOperator', 'Not Starts With'); +const IsNull: string = localize('profilerFilterDialog.isNullOperator', "Is Null"); +const IsNotNull: string = localize('profilerFilterDialog.isNotNullOperator', "Is Not Null"); +const Contains: string = localize('profilerFilterDialog.containsOperator', "Contains"); +const NotContains: string = localize('profilerFilterDialog.notContainsOperator', "Not Contains"); +const StartsWith: string = localize('profilerFilterDialog.startsWithOperator', "Starts With"); +const NotStartsWith: string = localize('profilerFilterDialog.notStartsWithOperator', "Not Starts With"); const Operators = [Equals, NotEquals, LessThan, LessThanOrEquals, GreaterThan, GreaterThanOrEquals, GreaterThan, GreaterThanOrEquals, IsNull, IsNotNull, Contains, NotContains, StartsWith, NotStartsWith]; export class ProfilerFilterDialog extends Modal { - private _clauseBuilder: Builder; + private _clauseBuilder: HTMLElement; private _okButton: Button; private _cancelButton: Button; private _clearButton: Button; @@ -110,36 +108,27 @@ export class ProfilerFilterDialog extends Modal { } protected renderBody(container: HTMLElement) { - new Builder(container).div({ 'class': 'profiler-filter-dialog' }, (bodyBuilder) => { - bodyBuilder.element('table', { 'class': 'profiler-filter-clause-table' }, (builder) => { - this._clauseBuilder = builder; - }); - this._clauseBuilder.element('tr', {}, (headerBuilder) => { - headerBuilder.element('td').text(FieldText); - headerBuilder.element('td').text(OperatorText); - headerBuilder.element('td').text(ValueText); - headerBuilder.element('td').text(''); - }); - - this._input.filter.clauses.forEach(clause => { - this.addClauseRow(true, clause.field, this.convertToOperatorString(clause.operator), clause.value); - }); - - bodyBuilder.div({ - 'class': 'profiler-filter-add-clause-prompt', - 'tabIndex': '0' - }).text(AddClausePromptText).on(DOM.EventType.CLICK, () => { - this.addClauseRow(false); - }).on(DOM.EventType.KEY_DOWN, (e: KeyboardEvent) => { - let event = new StandardKeyboardEvent(e); - if (event.equals(KeyCode.Space) || event.equals(KeyCode.Enter)) { - this.addClauseRow(false); - event.stopPropagation(); - } - }); + const body = DOM.append(container, DOM.$('.profiler-filter-dialog')); + this._clauseBuilder = DOM.append(body, DOM.$('table.profiler-filter-clause-table')); + const headerRow = DOM.append(this._clauseBuilder, DOM.$('tr')); + DOM.append(headerRow, DOM.$('td')).innerText = FieldText; + DOM.append(headerRow, DOM.$('td')).innerText = OperatorText; + DOM.append(headerRow, DOM.$('td')).innerText = ValueText; + DOM.append(headerRow, DOM.$('td')).innerText = ''; + this._input.filter.clauses.forEach(clause => { + this.addClauseRow(true, clause.field, this.convertToOperatorString(clause.operator), clause.value); }); + const prompt = DOM.append(body, DOM.$('.profiler-filter-add-clause-prompt', { tabIndex: '0' })); + prompt.innerText = AddClausePromptText; + DOM.addDisposableListener(prompt, DOM.EventType.CLICK, () => this.addClauseRow(false)); + DOM.addStandardDisposableListener(prompt, DOM.EventType.KEY_DOWN, (e: StandardKeyboardEvent) => { + if (e.equals(KeyCode.Space) || e.equals(KeyCode.Enter)) { + this.addClauseRow(false); + e.stopPropagation(); + } + }); } protected layout(height?: number): void { @@ -169,7 +158,7 @@ export class ProfilerFilterDialog extends Modal { } private createSelectBox(container: HTMLElement, options: string[], selectedOption: string, ariaLabel: string): SelectBox { - let dropdown = new SelectBox(options, selectedOption, this.contextViewService, undefined, { ariaLabel: ariaLabel }); + const dropdown = new SelectBox(options, selectedOption, this.contextViewService, undefined, { ariaLabel: ariaLabel }); dropdown.render(container); this._register(attachSelectBoxStyler(dropdown, this._themeService)); return dropdown; @@ -180,7 +169,7 @@ export class ProfilerFilterDialog extends Modal { } private getFilter(): ProfilerFilter { - let clauses: ProfilerFilterClause[] = []; + const clauses: ProfilerFilterClause[] = []; this._clauseRows.forEach(row => { clauses.push({ @@ -196,62 +185,52 @@ export class ProfilerFilterDialog extends Modal { } private addClauseRow(setInitialValue: boolean, field?: string, operator?: string, value?: string): any { - this._clauseBuilder.element('tr', {}, (rowBuilder) => { - let rowElement = rowBuilder.getHTMLElement(); - let clauseId = generateUuid(); - let fieldDropDown: SelectBox; - let operatorDropDown: SelectBox; - let valueText: InputBox; + const row = DOM.append(this._clauseBuilder, DOM.$('tr')); + const clauseId = generateUuid(); - rowBuilder.element('td', {}, (fieldCell) => { - let columns = this._input.columns.map(column => column.name); - fieldDropDown = this.createSelectBox(fieldCell.getHTMLElement(), columns, columns[0], FieldText); - }); - rowBuilder.element('td', {}, (operatorCell) => { - operatorDropDown = this.createSelectBox(operatorCell.getHTMLElement(), Operators, Operators[0], OperatorText); - }); - rowBuilder.element('td', {}, (textCell) => { - valueText = new InputBox(textCell.getHTMLElement(), undefined, {}); - this._register(attachInputBoxStyler(valueText, this._themeService)); - }); - rowBuilder.element('td', {}, (removeImageCell) => { - let removeClauseButton = removeImageCell.div({ - 'class': 'profiler-filter-remove-condition icon remove', - 'tabIndex': '0', - 'aria-label': RemoveText, - 'title': RemoveText - }); + const columns = this._input.columns.map(column => column.name); + const fieldDropDown = this.createSelectBox(DOM.append(row, DOM.$('td')), columns, columns[0], FieldText); - removeClauseButton.on(DOM.EventType.KEY_DOWN, (e: KeyboardEvent) => { - let event = new StandardKeyboardEvent(e); - if (event.equals(KeyCode.Space) || event.equals(KeyCode.Enter)) { - this.removeRow(clauseId); - event.stopPropagation(); - } - }); + const operatorDropDown = this.createSelectBox(DOM.append(row, DOM.$('td')), Operators, Operators[0], OperatorText); - removeClauseButton.on(DOM.EventType.CLICK, () => { - this.removeRow(clauseId); - }); - }); + const valueText = new InputBox(DOM.append(row, DOM.$('td')), undefined, {}); + this._register(attachInputBoxStyler(valueText, this._themeService)); - if (setInitialValue) { - fieldDropDown.selectWithOptionName(field); - operatorDropDown.selectWithOptionName(operator); - valueText.value = value; + const removeCell = DOM.append(row, DOM.$('td')); + const removeClauseButton = DOM.append(removeCell, DOM.$('.profiler-filter-remove-condition.icon.remove', { + 'tabIndex': '0', + 'aria-label': RemoveText, + 'title': RemoveText + })); + + DOM.addStandardDisposableListener(removeClauseButton, DOM.EventType.KEY_DOWN, (e: StandardKeyboardEvent) => { + if (e.equals(KeyCode.Space) || e.equals(KeyCode.Enter)) { + this.removeRow(clauseId); + e.stopPropagation(); } - this._clauseRows.push({ - id: clauseId, - row: rowElement, - field: fieldDropDown, - operator: operatorDropDown, - value: valueText - }); + }); + + DOM.addDisposableListener(removeClauseButton, DOM.EventType.CLICK, (e: MouseEvent) => { + this.removeRow(clauseId); + }); + + if (setInitialValue) { + fieldDropDown.selectWithOptionName(field); + operatorDropDown.selectWithOptionName(operator); + valueText.value = value; + } + + this._clauseRows.push({ + id: clauseId, + row, + field: fieldDropDown, + operator: operatorDropDown, + value: valueText }); } private removeRow(clauseId: string) { - let idx = this._clauseRows.findIndex((entry) => { return entry.id === clauseId; }); + const idx = this._clauseRows.findIndex((entry) => { return entry.id === clauseId; }); if (idx !== -1) { this._clauseRows[idx].row.remove(); this._clauseRows.splice(idx, 1); diff --git a/src/sql/parts/query/editor/gridPanel.ts b/src/sql/parts/query/editor/gridPanel.ts index e390715a9c..88c9d29ede 100644 --- a/src/sql/parts/query/editor/gridPanel.ts +++ b/src/sql/parts/query/editor/gridPanel.ts @@ -2,7 +2,6 @@ * 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 pretty from 'pretty-data'; @@ -23,7 +22,6 @@ import { CopyKeybind } from 'sql/base/browser/ui/table/plugins/copyKeybind.plugi import { AdditionalKeyBindings } from 'sql/base/browser/ui/table/plugins/additionalKeyBindings.plugin'; import { ITableStyles, ITableMouseEvent } from 'sql/base/browser/ui/table/interfaces'; import { warn } from 'sql/base/common/log'; -import { $ } from 'sql/base/browser/builder'; import * as azdata from 'azdata'; @@ -203,7 +201,7 @@ export class GridPanel extends ViewletPanel { } } - public resetScrollPosition() : void { + public resetScrollPosition(): void { this.splitView.setScrollPosition(this.state.scrollPosition); } @@ -813,7 +811,7 @@ class GridTable extends Disposable implements IView { } public dispose() { - $(this.container).destroy(); + this.container.remove(); this.table.dispose(); this.actionBar.dispose(); super.dispose(); diff --git a/src/sql/parts/query/editor/messagePanel.ts b/src/sql/parts/query/editor/messagePanel.ts index a31deba60c..7e4ce67e2c 100644 --- a/src/sql/parts/query/editor/messagePanel.ts +++ b/src/sql/parts/query/editor/messagePanel.ts @@ -2,13 +2,12 @@ * 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 'vs/css!./media/messagePanel'; import { IMessagesActionContext, CopyMessagesAction, CopyAllMessagesAction } from './actions'; import QueryRunner from 'sql/platform/query/common/queryRunner'; import { QueryInput } from 'sql/parts/query/common/queryInput'; -import { $ } from 'sql/base/browser/builder'; +import { IExpandableTree } from 'sql/parts/objectExplorer/viewlet/treeUpdateUtils'; import { IResultMessage, ISelectionData } from 'azdata'; @@ -30,7 +29,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; -import { IExpandableTree } from 'sql/parts/objectExplorer/viewlet/treeUpdateUtils'; +import { $ } from 'vs/base/browser/dom'; export interface IResultMessageIntern extends IResultMessage { id?: string; @@ -83,13 +82,12 @@ export class MessagePanel extends ViewletPanel { private renderer = new MessageRenderer(this.messageLineCountMap); private model = new Model(); private controller: MessageController; - private container = $('div message-tree').getHTMLElement(); + private container = $('.message-tree'); private queryRunnerDisposables: IDisposable[] = []; private _state: MessagePanelState; private tree: ITree; - private _selectAllMessages: boolean; constructor( options: IViewletPanelOptions, @@ -335,16 +333,22 @@ class MessageRenderer implements IRenderer { renderTemplate(tree: ITree, templateId: string, container: HTMLElement): IMessageTemplate | IBatchTemplate { if (templateId === TemplateIds.MESSAGE) { - $('div.time-stamp').appendTo(container); - const message = $('div.message').style('white-space', 'pre').appendTo(container).getHTMLElement(); + container.append($('.time-stamp')); + const message = $('.message'); + message.style.whiteSpace = 'pre'; + container.append(message); return { message }; } else if (templateId === TemplateIds.BATCH) { - const timeStamp = $('div.time-stamp').appendTo(container).getHTMLElement(); - const message = $('div.batch-start').style('white-space', 'pre').appendTo(container).getHTMLElement(); + const timeStamp = $('.time-stamp'); + container.append(timeStamp); + const message = $('.batch-start'); + message.style.whiteSpace = 'pre'; + container.append(message); return { message, timeStamp }; } else if (templateId === TemplateIds.ERROR) { - $('div.time-stamp').appendTo(container); - const message = $('div.error-message').appendTo(container).getHTMLElement(); + container.append($('.time-stamp')); + const message = $('.error-message'); + container.append(message); return { message }; } else { return undefined; diff --git a/src/sql/platform/accounts/browser/autoOAuthDialog.ts b/src/sql/platform/accounts/browser/autoOAuthDialog.ts index ed834a3fbb..4ff7e65b1e 100644 --- a/src/sql/platform/accounts/browser/autoOAuthDialog.ts +++ b/src/sql/platform/accounts/browser/autoOAuthDialog.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/autoOAuthDialog'; -import { Builder, $ } from 'sql/base/browser/builder'; + import { IThemeService } from 'vs/platform/theme/common/themeService'; import { attachInputBoxStyler } from 'vs/platform/theme/common/styler'; import { Event, Emitter } from 'vs/base/common/event'; @@ -12,6 +12,7 @@ import { IContextViewService } from 'vs/platform/contextview/browser/contextView import { localize } from 'vs/nls'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; +import { $, append } from 'vs/base/browser/dom'; import { Button } from 'sql/base/browser/ui/button/button'; import { Modal } from 'sql/workbench/browser/modal/modal'; @@ -82,37 +83,21 @@ export class AutoOAuthDialog extends Modal { } protected renderBody(container: HTMLElement) { - $().div({ class: 'auto-oauth-description-section new-section' }, (descriptionContainer) => { - this._descriptionElement = descriptionContainer.getHTMLElement(); - }); + this._descriptionElement = append(container, $('.auto-oauth-description-section.new-section')); - let addAccountSection; - $().div({ class: 'auto-oauth-info-section new-section' }, (addAccountContainer) => { - addAccountSection = addAccountContainer.getHTMLElement(); - this._userCodeInputBox = this.createInputBoxHelper(addAccountContainer, localize('userCode', 'User code')); - this._websiteInputBox = this.createInputBoxHelper(addAccountContainer, localize('website', 'Website')); - }); - - new Builder(container).div({ class: 'auto-oauth-dialog' }, (builder) => { - builder.append(this._descriptionElement); - builder.append(addAccountSection); - }); + const addAccountSection = append(container, $('.auto-oauth-info-section.new-section')); + this._userCodeInputBox = this.createInputBoxHelper(addAccountSection, localize('userCode', 'User code')); + this._websiteInputBox = this.createInputBoxHelper(addAccountSection, localize('website', 'Website')); } - private createInputBoxHelper(container: Builder, label: string): InputBox { - let inputBox: InputBox; - container.div({ class: 'dialog-input-section' }, (inputContainer) => { - inputContainer.div({ class: 'dialog-label' }, (labelContainer) => { - labelContainer.text(label); - }); + private createInputBoxHelper(container: HTMLElement, label: string): InputBox { + const inputContainer = append(container, $('.dialog-input-section')); + append(inputContainer, $('.dialog-label')).innerText = label; + const inputCellContainer = append(inputContainer, $('.dialog-input')); - inputContainer.div({ class: 'dialog-input' }, (inputCellContainer) => { - inputBox = new InputBox(inputCellContainer.getHTMLElement(), this._contextViewService, { - ariaLabel: label - }); - }); + return new InputBox(inputCellContainer, this._contextViewService, { + ariaLabel: label }); - return inputBox; } private registerListeners(): void { diff --git a/src/sql/platform/accounts/browser/firewallRuleDialog.ts b/src/sql/platform/accounts/browser/firewallRuleDialog.ts index a8f7fd9628..2ab3eb7f3e 100644 --- a/src/sql/platform/accounts/browser/firewallRuleDialog.ts +++ b/src/sql/platform/accounts/browser/firewallRuleDialog.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/firewallRuleDialog'; -import { Builder, $ } from 'sql/base/browser/builder'; + import * as DOM from 'vs/base/browser/dom'; import { Event, Emitter } from 'vs/base/common/event'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; @@ -18,6 +18,7 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IWindowsService } from 'vs/platform/windows/common/windows'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService'; +import { ILayoutService } from 'vs/platform/layout/browser/layoutService'; import * as azdata from 'azdata'; import { Button } from 'sql/base/browser/ui/button/button'; @@ -27,15 +28,14 @@ import { attachModalDialogStyler, attachButtonStyler } from 'sql/platform/theme/ import { InputBox } from 'sql/base/browser/ui/inputBox/inputBox'; import { IAccountPickerService } from 'sql/platform/accounts/common/accountPicker'; import * as TelemetryKeys from 'sql/common/telemetryKeys'; -import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; // TODO: Make the help link 1) extensible (01/08/2018, https://github.com/Microsoft/azuredatastudio/issues/450) // in case that other non-Azure sign in is to be used const firewallHelpUri = 'https://aka.ms/sqlopsfirewallhelp'; const LocalizedStrings = { - FROM: localize('from', 'From'), - TO: localize('to', 'To') + FROM: localize('from', "From"), + TO: localize('to', "To") }; export class FirewallRuleDialog extends Modal { @@ -62,7 +62,7 @@ export class FirewallRuleDialog extends Modal { constructor( @IAccountPickerService private _accountPickerService: IAccountPickerService, - @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, + @ILayoutService layoutService: ILayoutService, @IThemeService themeService: IThemeService, @IInstantiationService private _instantiationService: IInstantiationService, @IContextViewService private _contextViewService: IContextViewService, @@ -72,7 +72,7 @@ export class FirewallRuleDialog extends Modal { @IClipboardService clipboardService: IClipboardService ) { super( - localize('createNewFirewallRule', 'Create new firewall rule'), + localize('createNewFirewallRule', "Create new firewall rule"), TelemetryKeys.FireWallRule, telemetryService, layoutService, @@ -99,29 +99,28 @@ export class FirewallRuleDialog extends Modal { attachModalDialogStyler(this, this._themeService); this.backButton.onDidClick(() => this.cancel()); this._register(attachButtonStyler(this.backButton, this._themeService, { buttonBackground: SIDE_BAR_BACKGROUND, buttonHoverBackground: SIDE_BAR_BACKGROUND })); - this._createButton = this.addFooterButton(localize('firewall.ok', 'OK'), () => this.createFirewallRule()); - this._closeButton = this.addFooterButton(localize('firewall.cancel', 'Cancel'), () => this.cancel()); + this._createButton = this.addFooterButton(localize('firewall.ok', "OK"), () => this.createFirewallRule()); + this._closeButton = this.addFooterButton(localize('firewall.cancel', "Cancel"), () => this.cancel()); this.registerListeners(); } protected renderBody(container: HTMLElement) { - let descriptionSection; - $().div({ 'class': 'firewall-rule-description-section new-section' }, (descriptionContainer) => { - descriptionSection = descriptionContainer.getHTMLElement(); - DOM.append(descriptionContainer.getHTMLElement(), DOM.$('div.firewall-rule-icon')); + const body = DOM.append(container, DOM.$('.firewall-rule-dialog')); + const descriptionSection = DOM.append(body, DOM.$('.firewall-rule-description-section.new-section')); - const textDescriptionContainer = DOM.append(descriptionContainer.getHTMLElement(), DOM.$('div.firewall-rule-description')); - let dialogDescription = localize('firewallRuleDialogDescription', - 'Your client IP address does not have access to the server. Sign in to an Azure account and create a new firewall rule to enable access.'); - this.createLabelElement(new Builder(textDescriptionContainer), dialogDescription, false); + DOM.append(descriptionSection, DOM.$('div.firewall-rule-icon')); - this._helpLink = DOM.append(textDescriptionContainer, DOM.$('a.help-link')); - this._helpLink.setAttribute('href', firewallHelpUri); - this._helpLink.innerHTML += localize('firewallRuleHelpDescription', 'Learn more about firewall settings'); - this._helpLink.onclick = () => { - this._windowsService.openExternal(firewallHelpUri); - }; - }); + const textDescriptionContainer = DOM.append(descriptionSection, DOM.$('div.firewall-rule-description')); + const dialogDescription = localize('firewallRuleDialogDescription', + "Your client IP address does not have access to the server. Sign in to an Azure account and create a new firewall rule to enable access."); + this.createLabelElement(textDescriptionContainer, dialogDescription, false); + + this._helpLink = DOM.append(textDescriptionContainer, DOM.$('a.help-link')); + this._helpLink.setAttribute('href', firewallHelpUri); + this._helpLink.innerHTML += localize('firewallRuleHelpDescription', 'Learn more about firewall settings'); + this._helpLink.onclick = () => { + this._windowsService.openExternal(firewallHelpUri); + }; // Create account picker with event handling this._accountPickerService.addAccountCompleteEvent(() => this.spinner = false); @@ -132,88 +131,61 @@ export class FirewallRuleDialog extends Modal { this._accountPickerService.addAccountStartEvent(() => this.spinner = true); this._accountPickerService.onAccountSelectionChangeEvent((account) => this.onAccountSelectionChange(account)); - let azureAccountSection; - $().div({ 'class': 'azure-account-section new-section' }, (azureAccountContainer) => { - azureAccountSection = azureAccountContainer.getHTMLElement(); - let azureAccountLabel = localize('azureAccount', 'Azure account'); - this.createLabelElement(azureAccountContainer, azureAccountLabel, true); - azureAccountContainer.div({ 'class': 'dialog-input' }, (inputCellContainer) => { - this._accountPickerService.renderAccountPicker(inputCellContainer.getHTMLElement()); - }); + const azureAccountSection = DOM.append(body, DOM.$('.azure-account-section.new-section')); + const azureAccountLabel = localize('azureAccount', "Azure account"); + this.createLabelElement(azureAccountSection, azureAccountLabel, true); + this._accountPickerService.renderAccountPicker(DOM.append(azureAccountSection, DOM.$('.dialog-input'))); + + const firewallRuleSection = DOM.append(body, DOM.$('.firewall-rule-section.new-section')); + const firewallRuleLabel = localize('filewallRule', 'Firewall rule'); + this.createLabelElement(firewallRuleSection, firewallRuleLabel, true); + const radioContainer = DOM.append(firewallRuleSection, DOM.$('.radio-section')); + const form = DOM.append(radioContainer, DOM.$('form.firewall-rule')); + const IPAddressDiv = DOM.append(form, DOM.$('div.firewall-ip-address dialog-input')); + const subnetIPRangeDiv = DOM.append(form, DOM.$('div.firewall-subnet-ip-range dialog-input')); + + const IPAddressContainer = DOM.append(IPAddressDiv, DOM.$('div.option-container')); + this._IPAddressInput = DOM.append(IPAddressContainer, DOM.$('input.option-input')); + this._IPAddressInput.setAttribute('type', 'radio'); + this._IPAddressInput.setAttribute('name', 'firewallRuleChoice'); + this._IPAddressInput.setAttribute('value', 'ipAddress'); + const IPAddressDescription = DOM.append(IPAddressContainer, DOM.$('div.option-description')); + IPAddressDescription.innerText = localize('addIPAddressLabel', 'Add my client IP '); + this._IPAddressElement = DOM.append(IPAddressContainer, DOM.$('div.option-ip-address')); + + const subnetIpRangeContainer = DOM.append(subnetIPRangeDiv, DOM.$('div.option-container')); + this._subnetIPRangeInput = DOM.append(subnetIpRangeContainer, DOM.$('input.option-input')); + this._subnetIPRangeInput.setAttribute('type', 'radio'); + this._subnetIPRangeInput.setAttribute('name', 'firewallRuleChoice'); + this._subnetIPRangeInput.setAttribute('value', 'ipRange'); + const subnetIPRangeDescription = DOM.append(subnetIpRangeContainer, DOM.$('div.option-description')); + subnetIPRangeDescription.innerText = localize('addIpRangeLabel', 'Add my subnet IP range'); + const subnetIPRangeSection = DOM.append(subnetIPRangeDiv, DOM.$('.subnet-ip-range-input')); + + const inputContainer = DOM.append(subnetIPRangeSection, DOM.$('.dialog-input-section')); + + DOM.append(inputContainer, DOM.$('.dialog-label')).innerText = LocalizedStrings.FROM; + + this._fromRangeinputBox = new InputBox(DOM.append(inputContainer, DOM.$('.dialog-input')), this._contextViewService, { + ariaLabel: LocalizedStrings.FROM }); - let subnetIPRangeSection; - $().div({ 'class': 'subnet-ip-range-input' }, (subnetIPRangeContainer) => { - subnetIPRangeSection = subnetIPRangeContainer.getHTMLElement(); - subnetIPRangeContainer.div({ 'class': 'dialog-input-section' }, (inputContainer) => { - inputContainer.div({ 'class': 'dialog-label' }, (labelContainer) => { - labelContainer.text(LocalizedStrings.FROM); - }); + DOM.append(inputContainer, DOM.$('.dialog-label')).innerText = LocalizedStrings.TO; - inputContainer.div({ 'class': 'dialog-input' }, (inputCellContainer) => { - this._fromRangeinputBox = new InputBox(inputCellContainer.getHTMLElement(), this._contextViewService, { - ariaLabel: LocalizedStrings.FROM - }); - }); - - inputContainer.div({ 'class': 'dialog-label' }, (labelContainer) => { - labelContainer.text(LocalizedStrings.TO); - }); - - inputContainer.div({ 'class': 'dialog-input' }, (inputCellContainer) => { - this._toRangeinputBox = new InputBox(inputCellContainer.getHTMLElement(), this._contextViewService, { - ariaLabel: LocalizedStrings.TO - }); - }); - }); - }); - - let firewallRuleSection; - $().div({ 'class': 'firewall-rule-section new-section' }, (firewallRuleContainer) => { - firewallRuleSection = firewallRuleContainer.getHTMLElement(); - const firewallRuleLabel = localize('filewallRule', 'Firewall rule'); - this.createLabelElement(firewallRuleContainer, firewallRuleLabel, true); - firewallRuleContainer.div({ 'class': 'radio-section' }, (radioContainer) => { - const form = DOM.append(radioContainer.getHTMLElement(), DOM.$('form.firewall-rule')); - const IPAddressDiv = DOM.append(form, DOM.$('div.firewall-ip-address dialog-input')); - const subnetIPRangeDiv = DOM.append(form, DOM.$('div.firewall-subnet-ip-range dialog-input')); - - const IPAddressContainer = DOM.append(IPAddressDiv, DOM.$('div.option-container')); - this._IPAddressInput = DOM.append(IPAddressContainer, DOM.$('input.option-input')); - this._IPAddressInput.setAttribute('type', 'radio'); - this._IPAddressInput.setAttribute('name', 'firewallRuleChoice'); - this._IPAddressInput.setAttribute('value', 'ipAddress'); - const IPAddressDescription = DOM.append(IPAddressContainer, DOM.$('div.option-description')); - IPAddressDescription.innerText = localize('addIPAddressLabel', 'Add my client IP '); - this._IPAddressElement = DOM.append(IPAddressContainer, DOM.$('div.option-ip-address')); - - const subnetIpRangeContainer = DOM.append(subnetIPRangeDiv, DOM.$('div.option-container')); - this._subnetIPRangeInput = DOM.append(subnetIpRangeContainer, DOM.$('input.option-input')); - this._subnetIPRangeInput.setAttribute('type', 'radio'); - this._subnetIPRangeInput.setAttribute('name', 'firewallRuleChoice'); - this._subnetIPRangeInput.setAttribute('value', 'ipRange'); - const subnetIPRangeDescription = DOM.append(subnetIpRangeContainer, DOM.$('div.option-description')); - subnetIPRangeDescription.innerText = localize('addIpRangeLabel', 'Add my subnet IP range'); - DOM.append(subnetIPRangeDiv, subnetIPRangeSection); - }); - }); - - new Builder(container).div({ 'class': 'firewall-rule-dialog' }, (builder) => { - builder.append(descriptionSection); - builder.append(azureAccountSection); - builder.append(firewallRuleSection); + this._toRangeinputBox = new InputBox(DOM.append(inputContainer, DOM.$('.dialog-input')), this._contextViewService, { + ariaLabel: LocalizedStrings.TO }); this._register(this._themeService.onThemeChange(e => this.updateTheme(e))); this.updateTheme(this._themeService.getTheme()); - $(this._IPAddressInput).on(DOM.EventType.CLICK, () => { + this._register(DOM.addDisposableListener(this._IPAddressElement, DOM.EventType.CLICK, () => { this.onFirewallRuleOptionSelected(true); - }); + })); - $(this._subnetIPRangeInput).on(DOM.EventType.CLICK, () => { + this._register(DOM.addDisposableListener(this._subnetIPRangeInput, DOM.EventType.CLICK, () => { this.onFirewallRuleOptionSelected(false); - }); + })); } private onFirewallRuleOptionSelected(isIPAddress: boolean) { @@ -230,14 +202,12 @@ export class FirewallRuleDialog extends Modal { // Nothing currently laid out statically in this class } - private createLabelElement(container: Builder, content: string, isHeader?: boolean) { + private createLabelElement(container: HTMLElement, content: string, isHeader?: boolean) { let className = 'dialog-label'; if (isHeader) { className += ' header'; } - container.div({ 'class': className }, (labelContainer) => { - labelContainer.text(content); - }); + DOM.append(container, DOM.$(`.${className}`)).innerText = content; } // Update theming that is specific to firewall rule flyout body diff --git a/src/sql/workbench/parts/dashboard/dashboardEditor.ts b/src/sql/workbench/parts/dashboard/dashboardEditor.ts index edc9008262..1d6c05e009 100644 --- a/src/sql/workbench/parts/dashboard/dashboardEditor.ts +++ b/src/sql/workbench/parts/dashboard/dashboardEditor.ts @@ -23,7 +23,6 @@ import { IConnectionProfile } from 'sql/platform/connection/common/interfaces'; import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement'; import { CancellationToken } from 'vs/base/common/cancellation'; import { IStorageService } from 'vs/platform/storage/common/storage'; -import { $ } from 'sql/base/browser/builder'; export class DashboardEditor extends BaseEditor { @@ -85,7 +84,7 @@ export class DashboardEditor extends BaseEditor { super.setInput(input, options, CancellationToken.None); - $(parentElement).clearChildren(); + DOM.clearNode(parentElement); if (!input.hasBootstrapped) { const container = DOM.$('.dashboardEditor'); diff --git a/src/sql/workbench/parts/notebook/notebookEditor.ts b/src/sql/workbench/parts/notebook/notebookEditor.ts index 020acad9b6..c890b28e5a 100644 --- a/src/sql/workbench/parts/notebook/notebookEditor.ts +++ b/src/sql/workbench/parts/notebook/notebookEditor.ts @@ -16,7 +16,6 @@ import { NotebookModule } from 'sql/workbench/parts/notebook/notebook.module'; import { NOTEBOOK_SELECTOR } from 'sql/workbench/parts/notebook/notebook.component'; import { INotebookParams } from 'sql/workbench/services/notebook/common/notebookService'; import { IStorageService } from 'vs/platform/storage/common/storage'; -import { $ } from 'sql/base/browser/builder'; export class NotebookEditor extends BaseEditor { @@ -67,7 +66,7 @@ export class NotebookEditor extends BaseEditor { super.setInput(input, options, CancellationToken.None); - $(parentElement).clearChildren(); + DOM.clearNode(parentElement); if (!input.hasBootstrapped) { let container = DOM.$('.notebookEditor'); @@ -104,4 +103,3 @@ export class NotebookEditor extends BaseEditor { ); } } - diff --git a/src/sql/workbench/services/connection/browser/connectionDialogWidget.ts b/src/sql/workbench/services/connection/browser/connectionDialogWidget.ts index b8ca156f7a..adc6963309 100644 --- a/src/sql/workbench/services/connection/browser/connectionDialogWidget.ts +++ b/src/sql/workbench/services/connection/browser/connectionDialogWidget.ts @@ -21,10 +21,8 @@ import * as TelemetryKeys from 'sql/common/telemetryKeys'; import { ClearRecentConnectionsAction } from 'sql/parts/connection/common/connectionActions'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { IWorkbenchThemeService, IColorTheme } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { Event, Emitter } from 'vs/base/common/event'; -import { Builder, $ } from 'sql/base/browser/builder'; import { ICancelableEvent } from 'vs/base/parts/tree/browser/treeDefaults'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -37,7 +35,8 @@ import * as DOM from 'vs/base/browser/dom'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; -import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; +import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService'; +import { ILayoutService } from 'vs/platform/layout/browser/layoutService'; export interface OnShowUIResponse { selectedProviderType: string; @@ -45,19 +44,19 @@ export interface OnShowUIResponse { } export class ConnectionDialogWidget extends Modal { - private _bodyBuilder: Builder; - private _recentConnectionBuilder: Builder; - private _noRecentConnectionBuilder: Builder; - private _savedConnectionBuilder: Builder; - private _noSavedConnectionBuilder: Builder; - private _connectionDetailTitle: Builder; + private _body: HTMLElement; + private _recentConnection: HTMLElement; + private _noRecentConnection: HTMLElement; + private _savedConnection: HTMLElement; + private _noSavedConnection: HTMLElement; + private _connectionDetailTitle: HTMLElement; private _connectButton: Button; private _closeButton: Button; private _providerTypeSelectBox: SelectBox; private _newConnectionParams: INewConnectionParams; private _recentConnectionTree: ITree; private _savedConnectionTree: ITree; - private $connectionUIContainer: Builder; + private _connectionUIContainer: HTMLElement; private _databaseDropdownExpanded: boolean; private _actionbar: ActionBar; private _providers: string[]; @@ -91,15 +90,15 @@ export class ConnectionDialogWidget extends Modal { private providerNameToDisplayNameMap: { [providerDisplayName: string]: string }, @IInstantiationService private _instantiationService: IInstantiationService, @IConnectionManagementService private _connectionManagementService: IConnectionManagementService, - @IWorkbenchThemeService private _workbenchThemeService: IWorkbenchThemeService, - @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, + @IThemeService themeService: IThemeService, + @ILayoutService layoutService: ILayoutService, @ITelemetryService telemetryService: ITelemetryService, @IContextKeyService contextKeyService: IContextKeyService, @IContextMenuService private _contextMenuService: IContextMenuService, @IContextViewService private _contextViewService: IContextViewService, @IClipboardService clipboardService: IClipboardService ) { - super(localize('connection', 'Connection'), TelemetryKeys.Connection, telemetryService, layoutService, clipboardService, _workbenchThemeService, contextKeyService, { hasSpinner: true, hasErrors: true }); + super(localize('connection', "Connection"), TelemetryKeys.Connection, telemetryService, layoutService, clipboardService, themeService, contextKeyService, { hasSpinner: true, hasErrors: true }); } /** @@ -117,7 +116,7 @@ export class ConnectionDialogWidget extends Modal { let filteredProviderTypes = this.providerTypeOptions; if (this._newConnectionParams && this._newConnectionParams.providers) { - let validProviderNames = Object.keys(this.providerNameToDisplayNameMap).filter(x => this.includeProvider(x, this._newConnectionParams)); + const validProviderNames = Object.keys(this.providerNameToDisplayNameMap).filter(x => this.includeProvider(x, this._newConnectionParams)); if (validProviderNames && validProviderNames.length > 0) { filteredProviderTypes = filteredProviderTypes.filter(x => validProviderNames.find(v => this.providerNameToDisplayNameMap[v] === x) !== undefined); } @@ -130,90 +129,84 @@ export class ConnectionDialogWidget extends Modal { } protected renderBody(container: HTMLElement): void { - let connectionContainer = $('.connection-dialog'); - container.appendChild(connectionContainer.getHTMLElement()); + this._body = DOM.append(container, DOM.$('.connection-dialog')); - this._bodyBuilder = new Builder(connectionContainer.getHTMLElement()); - const connectTypeLabel = localize('connectType', 'Connection type'); + const connectTypeLabel = localize('connectType', "Connection type"); this._providerTypeSelectBox = new SelectBox(this.providerTypeOptions, this.selectedProviderType, this._contextViewService, undefined, { ariaLabel: connectTypeLabel }); // Recent connection tab - let recentConnectionTab = $('.connection-recent-tab'); - recentConnectionTab.div({ class: 'connection-recent', id: 'recentConnection' }, (builder) => { - this._recentConnectionBuilder = new Builder(builder.getHTMLElement()); - this._noRecentConnectionBuilder = new Builder(builder.getHTMLElement()); - this.createRecentConnections(); - this._recentConnectionBuilder.hide(); - }); + const recentConnectionTab = DOM.$('.connection-recent-tab'); + const recentConnectionContainer = DOM.append(recentConnectionTab, DOM.$('.connection-recent', { id: 'recentConnection' })); + this._recentConnection = DOM.append(recentConnectionContainer, DOM.$('div')); + this._recentConnection.style.height = '100%'; + this._noRecentConnection = DOM.append(recentConnectionContainer, DOM.$('div')); + this.createRecentConnections(); + DOM.hide(this._recentConnection); // Saved connection tab - let savedConnectionTab = $('.connection-saved-tab'); - savedConnectionTab.div({ class: 'connection-saved' }, (builder) => { - this._savedConnectionBuilder = new Builder(builder.getHTMLElement()); - this._noSavedConnectionBuilder = new Builder(builder.getHTMLElement()); - this.createSavedConnections(); - this._savedConnectionBuilder.hide(); - }); + const savedConnectionTab = DOM.$('.connection-saved-tab'); + const savedConnectionContainer = DOM.append(savedConnectionTab, DOM.$('.connection-saved')); + this._savedConnection = DOM.append(savedConnectionContainer, DOM.$('div')); + this._savedConnection.style.height = '100%'; + this._noSavedConnection = DOM.append(savedConnectionContainer, DOM.$('div')); + this.createSavedConnections(); + DOM.hide(this._savedConnection); - this._panel = new TabbedPanel(connectionContainer.getHTMLElement()); + this._panel = new TabbedPanel(this._body); this._recentConnectionTabId = this._panel.pushTab({ identifier: 'recent_connection', - title: localize('recentConnectionTitle', 'Recent Connections'), + title: localize('recentConnectionTitle', "Recent Connections"), view: { render: c => { - recentConnectionTab.appendTo(c); + c.append(recentConnectionTab); }, layout: () => { } } }); - let savedConnectionTabId = this._panel.pushTab({ + const savedConnectionTabId = this._panel.pushTab({ identifier: 'saved_connection', - title: localize('savedConnectionTitle', 'Saved Connections'), + title: localize('savedConnectionTitle', "Saved Connections"), view: { layout: () => { }, render: c => { - savedConnectionTab.appendTo(c); + c.append(savedConnectionTab); } } }); this._panel.onTabChange(async c => { // convert to old VS Code tree interface with expandable methods - let expandableTree: IExpandableTree = this._savedConnectionTree; + const expandableTree: IExpandableTree = this._savedConnectionTree; if (c === savedConnectionTabId && expandableTree.getContentHeight() === 0) { // Update saved connection tree await TreeUpdateUtils.structuralTreeUpdate(this._savedConnectionTree, 'saved', this._connectionManagementService, this._providers); if (expandableTree.getContentHeight() > 0) { - this._noSavedConnectionBuilder.hide(); - this._savedConnectionBuilder.show(); + DOM.hide(this._noSavedConnection); + DOM.show(this._savedConnection); } else { - this._noSavedConnectionBuilder.show(); - this._savedConnectionBuilder.hide(); + DOM.show(this._noSavedConnection); + DOM.hide(this._savedConnection); } this._savedConnectionTree.layout(DOM.getTotalHeight(this._savedConnectionTree.getHTMLElement())); } }); - this._bodyBuilder.div({ class: 'connection-details-title' }, (dividerContainer) => { - this._connectionDetailTitle = dividerContainer; - this._connectionDetailTitle.text(localize('connectionDetailsTitle', 'Connection Details')); - }); + this._connectionDetailTitle = DOM.append(this._body, DOM.$('.connection-details-title')); - this._bodyBuilder.div({ class: 'connection-type' }, (modelTableContent) => { - modelTableContent.element('table', { class: 'connection-table-content' }, (tableContainer) => { - DialogHelper.appendInputSelectBox( - DialogHelper.appendRow(tableContainer.getHTMLElement(), connectTypeLabel, 'connection-label', 'connection-input'), this._providerTypeSelectBox); - }); - }); + this._connectionDetailTitle.innerText = localize('connectionDetailsTitle', "Connection Details"); - this.$connectionUIContainer = $('.connection-provider-info#connectionProviderInfo'); - this.$connectionUIContainer.appendTo(this._bodyBuilder); + const tableContainer = DOM.append(this._body, DOM.$('.connection-type')); + const table = DOM.append(tableContainer, DOM.$('table.connection-table-content')); + DialogHelper.appendInputSelectBox( + DialogHelper.appendRow(table, connectTypeLabel, 'connection-label', 'connection-input'), this._providerTypeSelectBox); - let self = this; - this._register(self._workbenchThemeService.onDidColorThemeChange(e => self.updateTheme(e))); - self.updateTheme(self._workbenchThemeService.getColorTheme()); + this._connectionUIContainer = DOM.$('.connection-provider-info', { id: 'connectionProviderInfo' }); + this._body.append(this._connectionUIContainer); + + this._register(this._themeService.onThemeChange(e => this.updateTheme(e))); + this.updateTheme(this._themeService.getTheme()); } /** @@ -222,8 +215,8 @@ export class ConnectionDialogWidget extends Modal { public render() { super.render(); attachModalDialogStyler(this, this._themeService); - let connectLabel = localize('connectionDialog.connect', 'Connect'); - let cancelLabel = localize('connectionDialog.cancel', 'Cancel'); + const connectLabel = localize('connectionDialog.connect', "Connect"); + const cancelLabel = localize('connectionDialog.cancel', "Cancel"); this._connectButton = this.addFooterButton(connectLabel, () => this.connect()); this._connectButton.enabled = false; this._closeButton = this.addFooterButton(cancelLabel, () => this.cancel()); @@ -232,15 +225,15 @@ export class ConnectionDialogWidget extends Modal { } // Update theming that is specific to connection flyout body - private updateTheme(theme: IColorTheme): void { - let borderColor = theme.getColor(contrastBorder); - let border = borderColor ? borderColor.toString() : null; - let backgroundColor = theme.getColor(SIDE_BAR_BACKGROUND); + private updateTheme(theme: ITheme): void { + const borderColor = theme.getColor(contrastBorder); + const border = borderColor ? borderColor.toString() : null; + const backgroundColor = theme.getColor(SIDE_BAR_BACKGROUND); if (this._connectionDetailTitle) { - this._connectionDetailTitle.style('border-width', border ? '1px 0px' : null); - this._connectionDetailTitle.style('border-style', border ? 'solid none' : null); - this._connectionDetailTitle.style('border-color', border); - this._connectionDetailTitle.style('background-color', backgroundColor ? backgroundColor.toString() : null); + this._connectionDetailTitle.style.borderWidth = border ? '1px 0px' : null; + this._connectionDetailTitle.style.borderStyle = border ? 'solid none' : null; + this._connectionDetailTitle.style.borderColor = border; + this._connectionDetailTitle.style.backgroundColor = backgroundColor ? backgroundColor.toString() : null; } } @@ -257,8 +250,8 @@ export class ConnectionDialogWidget extends Modal { private onProviderTypeSelected(selectedProviderType: string) { // Show connection form based on server type - this.$connectionUIContainer.empty(); - this._onShowUiComponent.fire({ selectedProviderType: selectedProviderType, container: this.$connectionUIContainer.getHTMLElement() }); + DOM.clearNode(this._connectionUIContainer); + this._onShowUiComponent.fire({ selectedProviderType: selectedProviderType, container: this._connectionUIContainer }); this.initDialog(); } @@ -285,7 +278,7 @@ export class ConnectionDialogWidget extends Modal { } private cancel() { - let wasConnecting = this._connecting; + const wasConnecting = this._connecting; this._onCancel.fire(); if (!this._databaseDropdownExpanded && !wasConnecting) { this.close(); @@ -298,87 +291,71 @@ export class ConnectionDialogWidget extends Modal { } private createRecentConnectionList(): void { - this._recentConnectionBuilder.div({ class: 'connection-recent-content' }, (recentConnectionContainer) => { - recentConnectionContainer.div({ class: 'recent-titles-container' }, (container) => { - container.div({ class: 'connection-history-actions' }, (actionsContainer) => { - this._actionbar = this._register(new ActionBar(actionsContainer.getHTMLElement(), { animated: false })); - let clearAction = this._instantiationService.createInstance(ClearRecentConnectionsAction, ClearRecentConnectionsAction.ID, ClearRecentConnectionsAction.LABEL); - clearAction.useConfirmationMessage = true; - clearAction.onRecentConnectionsRemoved(() => this.open(false)); - this._actionbar.push(clearAction, { icon: true, label: true }); - }); - }); - recentConnectionContainer.div({ class: 'server-explorer-viewlet' }, (divContainer: Builder) => { - divContainer.div({ class: 'explorer-servers' }, (treeContainer: Builder) => { - let leftClick = (element: any, eventish: ICancelableEvent, origin: string) => { - // element will be a server group if the tree is clicked rather than a item - if (element instanceof ConnectionProfile) { - this.onConnectionClick({ payload: { origin: origin, originalEvent: eventish } }, element); - } - }; - let actionProvider = this._instantiationService.createInstance(RecentConnectionActionsProvider); - let controller = new RecentConnectionTreeController(leftClick, actionProvider, this._connectionManagementService, this._contextMenuService); - actionProvider.onRecentConnectionRemoved(() => { - this.open(this._connectionManagementService.getRecentConnections().length > 0); - }); - controller.onRecentConnectionRemoved(() => { - this.open(this._connectionManagementService.getRecentConnections().length > 0); - }); - this._recentConnectionTree = TreeCreationUtils.createConnectionTree(treeContainer.getHTMLElement(), this._instantiationService, controller); - - // Theme styler - this._register(styler.attachListStyler(this._recentConnectionTree, this._themeService)); - divContainer.append(this._recentConnectionTree.getHTMLElement()); - }); - }); + const recentConnectionContainer = DOM.append(this._recentConnection, DOM.$('.connection-recent-content')); + const container = DOM.append(recentConnectionContainer, DOM.$('.recent-titles-container')); + const actionsContainer = DOM.append(container, DOM.$('.connection-history-actions')); + this._actionbar = this._register(new ActionBar(actionsContainer, { animated: false })); + const clearAction = this._instantiationService.createInstance(ClearRecentConnectionsAction, ClearRecentConnectionsAction.ID, ClearRecentConnectionsAction.LABEL); + clearAction.useConfirmationMessage = true; + clearAction.onRecentConnectionsRemoved(() => this.open(false)); + this._actionbar.push(clearAction, { icon: true, label: true }); + const divContainer = DOM.append(recentConnectionContainer, DOM.$('.server-explorer-viewlet')); + const treeContainer = DOM.append(divContainer, DOM.$('.explorer-servers')); + const leftClick = (element: any, eventish: ICancelableEvent, origin: string) => { + // element will be a server group if the tree is clicked rather than a item + if (element instanceof ConnectionProfile) { + this.onConnectionClick({ payload: { origin: origin, originalEvent: eventish } }, element); + } + }; + const actionProvider = this._instantiationService.createInstance(RecentConnectionActionsProvider); + const controller = new RecentConnectionTreeController(leftClick, actionProvider, this._connectionManagementService, this._contextMenuService); + actionProvider.onRecentConnectionRemoved(() => { + this.open(this._connectionManagementService.getRecentConnections().length > 0); }); + controller.onRecentConnectionRemoved(() => { + this.open(this._connectionManagementService.getRecentConnections().length > 0); + }); + this._recentConnectionTree = TreeCreationUtils.createConnectionTree(treeContainer, this._instantiationService, controller); + + // Theme styler + this._register(styler.attachListStyler(this._recentConnectionTree, this._themeService)); } private createRecentConnections() { this.createRecentConnectionList(); - this._noRecentConnectionBuilder.div({ class: 'connection-recent-content' }, (noRecentConnectionContainer) => { - let noRecentHistoryLabel = localize('noRecentConnections', 'No recent connection'); - noRecentConnectionContainer.div({ class: 'no-recent-connections' }, (noRecentTitle) => { - noRecentTitle.text(noRecentHistoryLabel); - }); - }); + const noRecentConnectionContainer = DOM.append(this._noRecentConnection, DOM.$('.connection-recent-content')); + const noRecentHistoryLabel = localize('noRecentConnections', "No recent connection"); + DOM.append(noRecentConnectionContainer, DOM.$('.no-recent-connections')).innerText = noRecentHistoryLabel; } private createSavedConnectionList(): void { - this._savedConnectionBuilder.div({ class: 'connection-saved-content' }, (savedConnectioncontainer) => { - savedConnectioncontainer.div({ class: 'server-explorer-viewlet' }, (divContainer: Builder) => { - divContainer.div({ class: 'explorer-servers' }, (treeContainer: Builder) => { - let leftClick = (element: any, eventish: ICancelableEvent, origin: string) => { - // element will be a server group if the tree is clicked rather than a item - if (element instanceof ConnectionProfile) { - this.onConnectionClick({ payload: { origin: origin, originalEvent: eventish } }, element); - } - }; + const savedConnectioncontainer = DOM.append(this._savedConnection, DOM.$('.connection-saved-content')); + const divContainer = DOM.append(savedConnectioncontainer, DOM.$('.server-explorer-viewlet')); + const treeContainer = DOM.append(divContainer, DOM.$('.explorer-servers')); + const leftClick = (element: any, eventish: ICancelableEvent, origin: string) => { + // element will be a server group if the tree is clicked rather than a item + if (element instanceof ConnectionProfile) { + this.onConnectionClick({ payload: { origin: origin, originalEvent: eventish } }, element); + } + }; - let controller = new SavedConnectionTreeController(leftClick); - this._savedConnectionTree = TreeCreationUtils.createConnectionTree(treeContainer.getHTMLElement(), this._instantiationService, controller); + const controller = new SavedConnectionTreeController(leftClick); + this._savedConnectionTree = TreeCreationUtils.createConnectionTree(treeContainer, this._instantiationService, controller); - // Theme styler - this._register(styler.attachListStyler(this._savedConnectionTree, this._themeService)); - divContainer.append(this._savedConnectionTree.getHTMLElement()); - }); - }); - }); + // Theme styler + this._register(styler.attachListStyler(this._savedConnectionTree, this._themeService)); } private createSavedConnections() { this.createSavedConnectionList(); - this._noSavedConnectionBuilder.div({ class: 'connection-saved-content' }, (noSavedConnectionContainer) => { - let noSavedConnectionLabel = localize('noSavedConnections', 'No saved connection'); - noSavedConnectionContainer.div({ class: 'no-saved-connections' }, (titleContainer) => { - titleContainer.text(noSavedConnectionLabel); - }); - }); + const noSavedConnectionContainer = DOM.append(this._noSavedConnection, DOM.$('.connection-saved-content')); + const noSavedConnectionLabel = localize('noSavedConnections', "No saved connection"); + DOM.append(noSavedConnectionContainer, DOM.$('.no-saved-connections')).innerText = noSavedConnectionLabel; } private onConnectionClick(event: any, element: IConnectionProfile) { - let isMouseOrigin = event.payload && (event.payload.origin === 'mouse'); - let isDoubleClick = isMouseOrigin && event.payload.originalEvent && event.payload.originalEvent.detail === 2; + const isMouseOrigin = event.payload && (event.payload.origin === 'mouse'); + const isDoubleClick = isMouseOrigin && event.payload.originalEvent && event.payload.originalEvent.detail === 2; if (isDoubleClick) { this.connect(element); } else { @@ -397,11 +374,11 @@ export class ConnectionDialogWidget extends Modal { this.show(); if (recentConnections) { - this._noRecentConnectionBuilder.hide(); - this._recentConnectionBuilder.show(); + DOM.hide(this._noRecentConnection); + DOM.show(this._recentConnection); } else { - this._recentConnectionBuilder.hide(); - this._noRecentConnectionBuilder.show(); + DOM.hide(this._recentConnection); + DOM.show(this._noRecentConnection); } await TreeUpdateUtils.structuralTreeUpdate(this._recentConnectionTree, 'recent', this._connectionManagementService, this._providers); diff --git a/src/sql/workbench/services/connection/browser/media/connectionDialog.css b/src/sql/workbench/services/connection/browser/media/connectionDialog.css index 5a2e2a322e..8baa9a1a11 100644 --- a/src/sql/workbench/services/connection/browser/media/connectionDialog.css +++ b/src/sql/workbench/services/connection/browser/media/connectionDialog.css @@ -90,6 +90,22 @@ margin: 0px 13px; } +.connection-recent-tab { + height: 100%; +} + +.connection-recent { + height: 100%; +} + +.connection-saved-tab { + height: 100%; +} + +.connection-saved { + height: 100%; +} + .vs-dark .connection-dialog .connection-history-actions .action-label.icon, .hc-black .connection-dialog .connection-history-actions .action-label.icon, .connection-dialog .connection-history-actions .action-label.icon {