wizard for deploying bdc (#7183)

* wip

* wip2

* wip eod 820

* wip 822

* text component improvements and misc changes

* aria-label

* targetClusterPage wip

* target cluster page

* target cluster page

* wip 827

* wip deployment profile page

* profile page

* service settings page

* wip 0903

* 0909 wip

* 0910

* 0911

* sql instance and working directory

* notebooks

* docker version on windows

* EULA env var

* 917 updates

* address comments

* use async file access

* fix the summary page display issue for ad auth

* add save json file buttons

* use promise for private methds

* review feedbacks

* refactor

* pass json to notebooks

* fix no tool scenario

* bypass tool check if installed

* update hint text

* update notebooks

* workaround azdata first time use

* comments

* accept eula and some text update

* fix the error in package.json

* promise instead of thenable

* comments

* fix typo
This commit is contained in:
Alan Ren
2019-09-25 10:04:13 -07:00
committed by GitHub
parent 6a6048d40f
commit a0e31fc723
51 changed files with 4137 additions and 855 deletions

View File

@@ -1,5 +1,5 @@
<div *ngIf="label" [class]="getClass()" (click)="onCardClick()" (mouseover)="onCardHoverChanged($event)"
(mouseout)="onCardHoverChanged($event)" tabIndex="0">
(mouseout)="onCardHoverChanged($event)" tabIndex="0" [style.width]="width" [style.height]="height">
<ng-container *ngIf="isVerticalButton || isDetailsCard">
<span *ngIf="hasStatus" class="card-status">
<div class="status-content" [style.backgroundColor]="statusColor"></div>
@@ -13,8 +13,16 @@
<div [class]="iconClass" [style.maxWidth]="iconWidth" [style.maxHeight]="iconHeight"></div>
</div>
<h4 class="card-label">{{label}}</h4>
<div *ngFor="let desc of descriptions">
<div class="list-item-description">{{desc}}</div>
<hr />
<div *ngIf="descriptions.length > 0" class="model-card-description-container">
<div *ngFor="let desc of descriptions">
<div *ngIf="desc.label; else separator" [style.font-weight]="desc.fontWeight" class="model-card-list-item-description">
<span>{{desc.label}}</span><span class="model-card-list-item-description-value">{{desc.value}}</span>
</div>
<ng-template #separator>
<div style="height: 12px"></div>
</ng-template>
</div>
</div>
</div>
</ng-container>
@@ -50,4 +58,4 @@
</div>
</div>
</ng-container>
</div>
</div>

View File

@@ -15,7 +15,7 @@ import { IColorTheme, IWorkbenchThemeService } from 'vs/workbench/services/theme
import { ComponentWithIconBase } from 'sql/workbench/browser/modelComponents/componentWithIconBase';
import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType } from 'sql/workbench/browser/modelComponents/interfaces';
import { StatusIndicator, CardProperties, ActionDescriptor } from 'sql/workbench/api/common/sqlExtHostTypes';
import { StatusIndicator, CardProperties, ActionDescriptor, CardDescriptionItem } from 'sql/workbench/api/common/sqlExtHostTypes';
@Component({
templateUrl: decodeURI(require.toUrl('./card.component.html'))
@@ -145,8 +145,8 @@ export default class CardComponent extends ComponentWithIconBase implements ICom
return this.selectable && this.selected;
}
public get descriptions(): string[] {
return this.getPropertyOrDefault<CardProperties, string[]>((props) => props.descriptions, []);
public get descriptions(): CardDescriptionItem[] {
return this.getPropertyOrDefault<CardProperties, CardDescriptionItem[]>((props) => props.descriptions, []);
}
public get actions(): ActionDescriptor[] {

View File

@@ -23,7 +23,7 @@ class DivItem {
@Component({
template: `
<div #divContainer *ngIf="items" class="divContainer" [style.height]="height" [style.width]="width" (click)="onClick()" (keyup)="onKey($event)" [tabIndex]="tabIndex">
<div #divContainer *ngIf="items" class="divContainer" [style.height]="height" [style.width]="width" (click)="onClick()" (keyup)="onKey($event)">
<div *ngFor="let item of items" [style.order]="getItemOrder(item)" [ngStyle]="getItemStyles(item)">
<model-component-wrapper [descriptor]="item.descriptor" [modelStore]="modelStore">
</model-component-wrapper>
@@ -70,6 +70,7 @@ export default class DivContainer extends ContainerBase<azdata.DivItemLayout> im
this.updateOverflowY();
}
this.updateScroll();
this.updateClickable();
}
private updateOverflowY() {
@@ -86,6 +87,17 @@ export default class DivContainer extends ContainerBase<azdata.DivItemLayout> im
element.dispatchEvent(new Event('scroll'));
}
private updateClickable(): void {
const element = <HTMLElement>this.divContainer.nativeElement;
if (this.clickable) {
element.tabIndex = 0;
element.style.cursor = 'pointer';
} else {
element.removeAttribute('tabIndex');
element.style.cursor = 'default';
}
}
private onClick() {
this.fireEvent({
eventType: ComponentEventType.onDidClick,
@@ -121,10 +133,6 @@ export default class DivContainer extends ContainerBase<azdata.DivItemLayout> im
return this.getPropertyOrDefault<azdata.DivContainerProperties, boolean>((props) => props.clickable, false);
}
public get tabIndex(): number {
return this.clickable ? 0 : -1;
}
private onKey(e: KeyboardEvent) {
let event = new StandardKeyboardEvent(e);
if (event.equals(KeyCode.Enter) || event.equals(KeyCode.Space)) {

View File

@@ -21,7 +21,7 @@ export class FlexItem {
@Component({
template: `
<div *ngIf="items" class="flexContainer" [style.flexFlow]="flexFlow" [style.justifyContent]="justifyContent" [style.position]="position"
[style.alignItems]="alignItems" [style.alignContent]="alignContent" [style.height]="height" [style.width]="width">
[style.alignItems]="alignItems" [style.alignContent]="alignContent" [style.height]="height" [style.width]="width" [style.flex-wrap]="flexWrap">
<div *ngFor="let item of items" [style.flex]="getItemFlex(item)" [style.textAlign]="textAlign" [style.order]="getItemOrder(item)" [ngStyle]="getItemStyles(item)">
<model-component-wrapper [descriptor]="item.descriptor" [modelStore]="modelStore">
</model-component-wrapper>
@@ -40,6 +40,7 @@ export default class FlexContainer extends ContainerBase<FlexItemLayout> impleme
private _height: string;
private _width: string;
private _position: string;
private _flexWrap: string;
constructor(
@Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef,
@@ -70,6 +71,7 @@ export default class FlexContainer extends ContainerBase<FlexItemLayout> impleme
this._position = layout.position ? layout.position : '';
this._height = this.convertSize(layout.height);
this._width = this.convertSize(layout.width);
this._flexWrap = layout.flexWrap ? layout.flexWrap : '';
this.layout();
}
@@ -107,6 +109,10 @@ export default class FlexContainer extends ContainerBase<FlexItemLayout> impleme
return this._position;
}
public get flexWrap(): string {
return this._flexWrap;
}
private getItemFlex(item: FlexItem): string {
return item.config ? item.config.flex : '1 1 auto';
}

View File

@@ -15,19 +15,16 @@
vertical-align: top;
}
.model-card-list-item.selected,
.model-card.selected {
.model-card-list-item.selected, .model-card.selected {
border-color: rgb(0, 120, 215);
box-shadow: rgba(0, 120, 215, 0.75) 0px 0px 6px;
}
.model-card-list-item.unselected,
.model-card.unselected {
.model-card-list-item.unselected, .model-card.unselected {
border-color: rgb(214, 214, 214);
box-shadow: none;
}
.model-card .card-content {
position: relative;
display: inline-block;
@@ -103,8 +100,7 @@
text-align: center;
}
.model-card-list-item .selection-indicator-container,
.model-card .selection-indicator-container {
.model-card-list-item .selection-indicator-container, .model-card .selection-indicator-container {
position: absolute;
top: 5px;
right: 5px;
@@ -118,8 +114,7 @@
border-style: solid;
}
.model-card-list-item .selection-indicator-container,
.model-card .selection-indicator-container {
.model-card-list-item .selection-indicator-container, .model-card .selection-indicator-container {
position: absolute;
overflow: hidden;
width: 16px;
@@ -141,8 +136,7 @@
right: 5px;
}
.model-card-list-item .selection-indicator,
.model-card .selection-indicator {
.model-card-list-item .selection-indicator, .model-card .selection-indicator {
margin: 4px;
width: 8px;
height: 8px;
@@ -189,12 +183,27 @@
.model-card-list-item .list-item-icon {
background-position: 2px 2px;
padding-left:22px;
padding-left: 22px;
font-size: 15px;
background-repeat: no-repeat;
background-size: 16px 16px;
}
.model-card-list-item .list-item-description {
padding-left:22px;
}
padding-left: 22px;
}
.model-card-description-container {
border-top-width: 1px;
border-top-style: solid;
border-color: rgb(214, 214, 214);
padding: 5px;
}
.model-card-list-item-description {
text-align: left;
}
.model-card-list-item-description-value {
float: right;
}

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><title>info_notification</title><path d="M8,16a7.93,7.93,0,0,1-2.13-.28A8,8,0,0,1,4,14.91,8,8,0,0,1,0,8,7.94,7.94,0,0,1,.28,5.88,8,8,0,0,1,1.09,4,8,8,0,0,1,4,1.1,8.08,8.08,0,0,1,5.86.3a8.13,8.13,0,0,1,4.25,0,8,8,0,0,1,3.53,2.05A8,8,0,0,1,14.9,4a8,8,0,0,1,.8,1.91,8,8,0,0,1-2.05,7.78A7.93,7.93,0,0,1,12,14.91a8,8,0,0,1-1.91.8A7.93,7.93,0,0,1,8,16ZM8,1.08a6.72,6.72,0,0,0-1.84.25A7.09,7.09,0,0,0,4.5,2,6.92,6.92,0,0,0,2,4.52a7.09,7.09,0,0,0-.7,1.66,6.87,6.87,0,0,0,0,3.67A7.07,7.07,0,0,0,2,11.5,6.92,6.92,0,0,0,4.5,14a7.09,7.09,0,0,0,1.65.7,6.89,6.89,0,0,0,3.68,0,7.07,7.07,0,0,0,1.66-.7A6.92,6.92,0,0,0,14,11.5a7.08,7.08,0,0,0,.7-1.65,6.89,6.89,0,0,0,0-3.68A7.09,7.09,0,0,0,14,4.52,6.92,6.92,0,0,0,11.48,2a7.07,7.07,0,0,0-1.66-.7A6.74,6.74,0,0,0,8,1.08Zm-.53,3.2H8.52V5.34H7.46Zm0,2.13H8.52v5.33H7.46Z"/></svg>

After

Width:  |  Height:  |  Size: 902 B

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.cls-1{fill:#fff;}</style></defs><title>info_notification_inverse</title><path class="cls-1" d="M8,16a7.93,7.93,0,0,1-2.13-.28A8,8,0,0,1,4,14.91,8,8,0,0,1,0,8,7.94,7.94,0,0,1,.28,5.88,8,8,0,0,1,1.09,4,8,8,0,0,1,4,1.1,8.08,8.08,0,0,1,5.86.3a8.13,8.13,0,0,1,4.25,0,8,8,0,0,1,3.53,2.05A8,8,0,0,1,14.9,4a8,8,0,0,1,.8,1.91,8,8,0,0,1-2.05,7.78A7.93,7.93,0,0,1,12,14.91a8,8,0,0,1-1.91.8A7.93,7.93,0,0,1,8,16ZM8,1.08a6.72,6.72,0,0,0-1.84.25A7.09,7.09,0,0,0,4.5,2,6.92,6.92,0,0,0,2,4.52a7.09,7.09,0,0,0-.7,1.66,6.87,6.87,0,0,0,0,3.67A7.07,7.07,0,0,0,2,11.5,6.92,6.92,0,0,0,4.5,14a7.09,7.09,0,0,0,1.65.7,6.89,6.89,0,0,0,3.68,0,7.07,7.07,0,0,0,1.66-.7A6.92,6.92,0,0,0,14,11.5a7.08,7.08,0,0,0,.7-1.65,6.89,6.89,0,0,0,0-3.68A7.09,7.09,0,0,0,14,4.52,6.92,6.92,0,0,0,11.48,2a7.07,7.07,0,0,0-1.66-.7A6.74,6.74,0,0,0,8,1.08Zm-.53,3.2H8.52V5.34H7.46Zm0,2.13H8.52v5.33H7.46Z"/></svg>

After

Width:  |  Height:  |  Size: 970 B

View File

@@ -0,0 +1,48 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.modelview-text-tooltip {
background-size: 12px 12px;
background-repeat: no-repeat;
cursor: pointer;
width: 12px;
height: 12px;
margin-left: 5px;
}
.vs .modelview-text-tooltip {
background-image: url('info.svg')
}
.vs-dark .modelview-text-tooltip, .hc-black .modelview-text-tooltip {
background-image: url('info_inverse.svg')
}
.modelview-text-tooltip .modelview-text-tooltip-content {
visibility: hidden;
text-align: left;
border-radius: 5px;
width: 200px;
padding: 5px;
position: absolute;
z-index: 1;
margin-left: 14px;
}
.vs .modelview-text-tooltip .modelview-text-tooltip-content {
background-color: #f5f5f5;
}
.vs-dark .modelview-text-tooltip .modelview-text-tooltip-content, .hc-black .modelview-text-tooltip .modelview-text-tooltip-content {
background-color: #050505;
}
.modelview-text-tooltip:focus .modelview-text-tooltip-content, .modelview-text-tooltip:hover .modelview-text-tooltip-content {
visibility: visible;
}
.modelview-text-link {
text-decoration: underline !important;
}

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/radioButton';
import 'vs/css!./media/text';
import {
Component, Input, Inject, ChangeDetectorRef, forwardRef,
OnDestroy, AfterViewInit, ElementRef, SecurityContext
@@ -18,7 +18,13 @@ import { SafeHtml, DomSanitizer } from '@angular/platform-browser';
@Component({
selector: 'modelview-text',
template: `
<p [style.width]="getWidth()" [innerHTML]="getValue()" [ngStyle]="this.CSSStyles" (click)="onClick()"></p>`
<div style="display:flex;flex-flow:row;align-items:center;" [style.width]="getWidth()">
<p [innerHTML]="getValue()" [ngStyle]="this.CSSStyles"></p>
<p *ngIf="requiredIndicator" style="color:red;margin-left:5px;">*</p>
<div *ngIf="description" tabindex="0" class="modelview-text-tooltip" [attr.aria-label]="description">
<div class="modelview-text-tooltip-content" [innerHTML]="description"></div>
</div>
<div>`
})
export default class TextComponent extends ComponentBase implements IComponent, OnDestroy, AfterViewInit {
@Input() descriptor: IComponentDescriptor;
@@ -57,13 +63,29 @@ export default class TextComponent extends ComponentBase implements IComponent,
return this.getPropertyOrDefault<azdata.TextComponentProperties, string>((props) => props.value, '');
}
public set description(newValue: string) {
this.setPropertyFromUI<azdata.TextComponentProperties, string>((properties, value) => { properties.description = value; }, newValue);
}
public get description(): string {
return this.getPropertyOrDefault<azdata.TextComponentProperties, string>((props) => props.description, '');
}
public set requiredIndicator(newValue: boolean) {
this.setPropertyFromUI<azdata.TextComponentProperties, boolean>((properties, value) => { properties.requiredIndicator = value; }, newValue);
}
public get requiredIndicator(): boolean {
return this.getPropertyOrDefault<azdata.TextComponentProperties, boolean>((props) => props.requiredIndicator, false);
}
public getValue(): SafeHtml {
let links = this.getPropertyOrDefault<azdata.TextComponentProperties, azdata.LinkArea[]>((props) => props.links, []);
let text = this._domSanitizer.sanitize(SecurityContext.HTML, this.value);
if (links.length !== 0) {
for (let i: number = 0; i < links.length; i++) {
let link = links[i];
let linkTag = `<a href="${this._domSanitizer.sanitize(SecurityContext.URL, link.url)}" tabIndex="0" target="blank">${this._domSanitizer.sanitize(SecurityContext.HTML, link.text)}</a>`;
let linkTag = `<a class="modelview-text-link" href="${this._domSanitizer.sanitize(SecurityContext.URL, link.url)}" tabIndex="0" target="blank">${this._domSanitizer.sanitize(SecurityContext.HTML, link.text)}</a>`;
text = text.replace(`{${i}}`, linkTag);
}
}