mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-26 11:01:37 -05:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ca755365ce | ||
|
|
ea979de19f | ||
|
|
473ddfcdf1 | ||
|
|
a627285a4c | ||
|
|
322847469d | ||
|
|
6c5fac997f | ||
|
|
1871fd383e | ||
|
|
f5b147ca4b | ||
|
|
9d2b206156 | ||
|
|
a372c76e07 | ||
|
|
b1ce07d3ae |
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -38,5 +38,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"typescript.tsdk": "node_modules/typescript/lib"
|
"typescript.tsdk": "node_modules/typescript/lib",
|
||||||
|
"git.ignoreLimitWarning": true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,9 +49,9 @@ core-util-is@~1.0.0:
|
|||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||||
|
|
||||||
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#0.1.7":
|
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#0.1.9":
|
||||||
version "0.1.7"
|
version "0.1.9"
|
||||||
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/d50285b03d0d5073c086362c5c96afb279320607"
|
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/a1a79895cb79658b75d78aa5cfd745855019148d"
|
||||||
dependencies:
|
dependencies:
|
||||||
vscode-languageclient "3.5.0"
|
vscode-languageclient "3.5.0"
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "sqlops",
|
"name": "sqlops",
|
||||||
"version": "0.30.6",
|
"version": "0.31.1",
|
||||||
"distro": "8c3e97e3425cc9814496472ab73e076de2ba99ee",
|
"distro": "8c3e97e3425cc9814496472ab73e076de2ba99ee",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Microsoft Corporation"
|
"name": "Microsoft Corporation"
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export class ToggleDropdownAction extends Action {
|
|||||||
private static readonly ID = 'dropdownAction.toggle';
|
private static readonly ID = 'dropdownAction.toggle';
|
||||||
private static readonly ICON = 'dropdown-arrow';
|
private static readonly ICON = 'dropdown-arrow';
|
||||||
|
|
||||||
constructor(label, private _fn: () => any) {
|
constructor(private _fn: () => any, label: string) {
|
||||||
super(ToggleDropdownAction.ID, label, ToggleDropdownAction.ICON);
|
super(ToggleDropdownAction.ID, label, ToggleDropdownAction.ICON);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,10 @@ export interface IDropdownOptions extends IDropdownStyles {
|
|||||||
* Value to use as aria-label for the input box
|
* Value to use as aria-label for the input box
|
||||||
*/
|
*/
|
||||||
ariaLabel?: string;
|
ariaLabel?: string;
|
||||||
|
/**
|
||||||
|
* Label for the dropdown action
|
||||||
|
*/
|
||||||
|
actionLabel: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IDropdownStyles {
|
export interface IDropdownStyles {
|
||||||
@@ -66,7 +70,8 @@ const defaults: IDropdownOptions = {
|
|||||||
strictSelection: true,
|
strictSelection: true,
|
||||||
maxHeight: 300,
|
maxHeight: 300,
|
||||||
errorMessage: errorMessage,
|
errorMessage: errorMessage,
|
||||||
contextBorder: Color.fromHex('#696969')
|
contextBorder: Color.fromHex('#696969'),
|
||||||
|
actionLabel: nls.localize('dropdownAction.toggle', "Toggle dropdown")
|
||||||
};
|
};
|
||||||
|
|
||||||
interface ListResource {
|
interface ListResource {
|
||||||
@@ -115,11 +120,11 @@ export class Dropdown extends Disposable {
|
|||||||
this.$input = $('.dropdown-input').style('width', '100%').appendTo(this.$el);
|
this.$input = $('.dropdown-input').style('width', '100%').appendTo(this.$el);
|
||||||
this.$treeContainer = $('.dropdown-tree');
|
this.$treeContainer = $('.dropdown-tree');
|
||||||
|
|
||||||
this._toggleAction = new ToggleDropdownAction(nls.localize('dropdown.toggle', '{0} Toggle Dropdown', this._options.ariaLabel), () => {
|
this._toggleAction = new ToggleDropdownAction(() => {
|
||||||
this._showList();
|
this._showList();
|
||||||
this._tree.domFocus();
|
this._tree.domFocus();
|
||||||
this._tree.focusFirst();
|
this._tree.focusFirst();
|
||||||
});
|
}, opt.actionLabel);
|
||||||
|
|
||||||
this._input = new InputBox(this.$input.getHTMLElement(), contextViewService, {
|
this._input = new InputBox(this.$input.getHTMLElement(), contextViewService, {
|
||||||
validationOptions: {
|
validationOptions: {
|
||||||
|
|||||||
@@ -172,4 +172,22 @@
|
|||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal .modal-footer .dialogErrorMessage {
|
||||||
|
align-items: center;
|
||||||
|
max-height: 30px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal .dialogErrorMessage .icon {
|
||||||
|
float: left;
|
||||||
|
margin-right: 10px;
|
||||||
|
width: auto;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal .modal-footer .dialogErrorMessage .errorMessage {
|
||||||
|
max-height: 100%;
|
||||||
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
@@ -21,9 +21,13 @@ import { Button } from 'sql/base/browser/ui/button/button';
|
|||||||
import * as TelemetryUtils from 'sql/common/telemetryUtilities';
|
import * as TelemetryUtils from 'sql/common/telemetryUtilities';
|
||||||
import * as TelemetryKeys from 'sql/common/telemetryKeys';
|
import * as TelemetryKeys from 'sql/common/telemetryKeys';
|
||||||
import { localize } from 'vs/nls';
|
import { localize } from 'vs/nls';
|
||||||
|
import { MessageLevel } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||||
|
|
||||||
export const MODAL_SHOWING_KEY = 'modalShowing';
|
export const MODAL_SHOWING_KEY = 'modalShowing';
|
||||||
export const MODAL_SHOWING_CONTEXT = new RawContextKey<Array<string>>(MODAL_SHOWING_KEY, []);
|
export const MODAL_SHOWING_CONTEXT = new RawContextKey<Array<string>>(MODAL_SHOWING_KEY, []);
|
||||||
|
const INFO_ALT_TEXT = localize('infoAltText', 'Info');
|
||||||
|
const WARNING_ALT_TEXT = localize('warningAltText', 'Warning');
|
||||||
|
const ERROR_ALT_TEXT = localize('errorAltText', 'Error');
|
||||||
|
|
||||||
export interface IModalDialogStyles {
|
export interface IModalDialogStyles {
|
||||||
dialogForeground?: Color;
|
dialogForeground?: Color;
|
||||||
@@ -145,7 +149,7 @@ export abstract class Modal extends Disposable implements IThemable {
|
|||||||
/**
|
/**
|
||||||
* Build and render the modal, will call {@link Modal#renderBody}
|
* Build and render the modal, will call {@link Modal#renderBody}
|
||||||
*/
|
*/
|
||||||
public render() {
|
public render(errorMessagesInFooter: boolean = false) {
|
||||||
let modalBodyClass = (this._modalOptions.isAngular === false ? 'modal-body' : 'modal-body-and-footer');
|
let modalBodyClass = (this._modalOptions.isAngular === false ? 'modal-body' : 'modal-body-and-footer');
|
||||||
let parts: Array<HTMLElement> = [];
|
let parts: Array<HTMLElement> = [];
|
||||||
// This modal header section refers to the header of of the dialog
|
// This modal header section refers to the header of of the dialog
|
||||||
@@ -182,17 +186,6 @@ export abstract class Modal extends Disposable implements IThemable {
|
|||||||
|
|
||||||
this.renderBody(body.getHTMLElement());
|
this.renderBody(body.getHTMLElement());
|
||||||
|
|
||||||
if (this._modalOptions.isAngular === false && this._modalOptions.hasErrors) {
|
|
||||||
body.div({ class: 'dialogErrorMessage', id: 'dialogErrorMessage' }, (errorMessageContainer) => {
|
|
||||||
errorMessageContainer.div({ class: 'icon error' }, (iconContainer) => {
|
|
||||||
this._errorIconElement = iconContainer.getHTMLElement();
|
|
||||||
this._errorIconElement.style.visibility = 'hidden';
|
|
||||||
});
|
|
||||||
errorMessageContainer.div({ class: 'errorMessage' }, (messageContainer) => {
|
|
||||||
this._errorMessage = messageContainer;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// This modal footer section refers to the footer of of the dialog
|
// This modal footer section refers to the footer of of the dialog
|
||||||
if (this._modalOptions.isAngular === false) {
|
if (this._modalOptions.isAngular === false) {
|
||||||
this._modalFooterSection = $().div({ class: 'modal-footer' }, (modelFooter) => {
|
this._modalFooterSection = $().div({ class: 'modal-footer' }, (modelFooter) => {
|
||||||
@@ -221,6 +214,19 @@ export abstract class Modal extends Disposable implements IThemable {
|
|||||||
builderClass += ' wide';
|
builderClass += ' wide';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this._modalOptions.isAngular === false && this._modalOptions.hasErrors) {
|
||||||
|
let builder = errorMessagesInFooter ? this._leftFooter : body;
|
||||||
|
builder.div({ class: 'dialogErrorMessage', id: 'dialogErrorMessage' }, (errorMessageContainer) => {
|
||||||
|
errorMessageContainer.div({ class: 'icon error' }, (iconContainer) => {
|
||||||
|
this._errorIconElement = iconContainer.getHTMLElement();
|
||||||
|
this._errorIconElement.style.visibility = 'hidden';
|
||||||
|
});
|
||||||
|
errorMessageContainer.div({ class: 'errorMessage' }, (messageContainer) => {
|
||||||
|
this._errorMessage = messageContainer;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// The builder builds the dialog. It append header, body and footer sections.
|
// The builder builds the dialog. It append header, body and footer sections.
|
||||||
this._builder = $().div({ class: builderClass, 'role': 'dialog' }, (dialogContainer) => {
|
this._builder = $().div({ class: builderClass, 'role': 'dialog' }, (dialogContainer) => {
|
||||||
this._modalDialog = dialogContainer.div({ class: 'modal-dialog ', role: 'document' }, (modalDialog) => {
|
this._modalDialog = dialogContainer.div({ class: 'modal-dialog ', role: 'document' }, (modalDialog) => {
|
||||||
@@ -355,14 +361,33 @@ export abstract class Modal extends Disposable implements IThemable {
|
|||||||
* Show an error in the error message element
|
* Show an error in the error message element
|
||||||
* @param err Text to show in the error message
|
* @param err Text to show in the error message
|
||||||
*/
|
*/
|
||||||
protected setError(err: string) {
|
protected setError(err: string, level: MessageLevel = MessageLevel.Error) {
|
||||||
if (this._modalOptions.hasErrors) {
|
if (this._modalOptions.hasErrors) {
|
||||||
if (err === '') {
|
if (err === '') {
|
||||||
this._errorIconElement.style.visibility = 'hidden';
|
this._errorIconElement.style.visibility = 'hidden';
|
||||||
} else {
|
} else {
|
||||||
|
const levelClasses = ['info', 'warning', 'error'];
|
||||||
|
let selectedLevel = levelClasses[2];
|
||||||
|
let altText = ERROR_ALT_TEXT;
|
||||||
|
if (level === MessageLevel.Information) {
|
||||||
|
selectedLevel = levelClasses[0];
|
||||||
|
altText = INFO_ALT_TEXT;
|
||||||
|
} else if (level === MessageLevel.Warning) {
|
||||||
|
selectedLevel = levelClasses[1];
|
||||||
|
altText = WARNING_ALT_TEXT;
|
||||||
|
}
|
||||||
|
levelClasses.forEach(level => {
|
||||||
|
if (selectedLevel === level) {
|
||||||
|
this._errorIconElement.classList.add(level);
|
||||||
|
} else {
|
||||||
|
this._errorIconElement.classList.remove(level);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this._errorIconElement.title = altText;
|
||||||
this._errorIconElement.style.visibility = 'visible';
|
this._errorIconElement.style.visibility = 'visible';
|
||||||
}
|
}
|
||||||
this._errorMessage.innerHtml(err);
|
this._errorMessage.text(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><style type="text/css">.icon-canvas-transparent{opacity:0;fill:#F6F6F6;} .icon-vs-out{fill:#F6F6F6;} .icon-vs-blue{fill:#1BA1E2;} .icon-white{fill:#FFFFFF;}</style><path class="icon-canvas-transparent" d="M16 16h-16v-16h16v16z" id="canvas"/><path class="icon-vs-out" d="M0 8c0-4.418 3.582-8 8-8s8 3.582 8 8-3.582 8-8 8-8-3.582-8-8z" id="outline"/><path class="icon-vs-blue" d="M8 1c-3.865 0-7 3.135-7 7s3.135 7 7 7 7-3.135 7-7-3.135-7-7-7zm1 12h-2v-7h2v7zm0-8h-2v-2h2v2z" id="iconBg"/><path class="icon-white" d="M7 6h2v7h-2v-7zm0-1h2v-2h-2v2z" id="iconFg"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style type="text/css">.icon-canvas-transparent{opacity:0;fill:#F6F6F6;} .icon-vs-out{fill:#F6F6F6;} .icon-vs-blue{fill:#1BA1E2;} .icon-white{fill:#FFFFFF;}</style><path class="icon-canvas-transparent" d="M16 16h-16v-16h16v16z" id="canvas"/><path class="icon-vs-out" d="M0 8c0-4.418 3.582-8 8-8s8 3.582 8 8-3.582 8-8 8-8-3.582-8-8z" id="outline"/><path class="icon-vs-blue" d="M8 1c-3.865 0-7 3.135-7 7s3.135 7 7 7 7-3.135 7-7-3.135-7-7-7zm1 12h-2v-7h2v7zm0-8h-2v-2h2v2z" id="iconBg"/><path class="icon-white" d="M7 6h2v7h-2v-7zm0-1h2v-2h-2v2z" id="iconFg"/></svg>
|
||||||
|
Before Width: | Height: | Size: 627 B After Width: | Height: | Size: 624 B |
@@ -6,12 +6,14 @@
|
|||||||
import { NgModule, Inject, forwardRef, ApplicationRef, ComponentFactoryResolver, Type } from '@angular/core';
|
import { NgModule, Inject, forwardRef, ApplicationRef, ComponentFactoryResolver, Type } from '@angular/core';
|
||||||
import { APP_BASE_HREF, CommonModule } from '@angular/common';
|
import { APP_BASE_HREF, CommonModule } from '@angular/common';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { IBootstrapParams } from 'sql/services/bootstrap/bootstrapService';
|
|
||||||
|
|
||||||
import { CreateLoginComponent, CREATELOGIN_SELECTOR } from 'sql/parts/admin/security/createLogin.component';
|
import { IBootstrapParams, providerIterator } from 'sql/services/bootstrap/bootstrapService';
|
||||||
|
import { CreateLoginComponent } from 'sql/parts/admin/security/createLogin.component';
|
||||||
|
|
||||||
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
|
||||||
// Connection Dashboard main angular module
|
// Connection Dashboard main angular module
|
||||||
export const CreateLoginModule = (params: IBootstrapParams, selector: string): Type<any> => {
|
export const CreateLoginModule = (params: IBootstrapParams, selector: string, instantiationService: IInstantiationService): Type<any> => {
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@@ -24,7 +26,8 @@ export const CreateLoginModule = (params: IBootstrapParams, selector: string): T
|
|||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: APP_BASE_HREF, useValue: '/' },
|
{ provide: APP_BASE_HREF, useValue: '/' },
|
||||||
{ provide: IBootstrapParams, useValue: params }
|
{ provide: IBootstrapParams, useValue: params },
|
||||||
|
...providerIterator(instantiationService)
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
class ModuleClass {
|
class ModuleClass {
|
||||||
|
|||||||
@@ -172,7 +172,8 @@ export class ConnectionWidget {
|
|||||||
strictSelection: false,
|
strictSelection: false,
|
||||||
placeholder: this._defaultDatabaseName,
|
placeholder: this._defaultDatabaseName,
|
||||||
maxHeight: 125,
|
maxHeight: 125,
|
||||||
ariaLabel: databaseOption.displayName
|
ariaLabel: databaseOption.displayName,
|
||||||
|
actionLabel: localize('toggleDatabaseNameDropdown', 'Select Database Toggle Dropdown')
|
||||||
});
|
});
|
||||||
|
|
||||||
let serverGroupLabel = localize('serverGroup', 'Server group');
|
let serverGroupLabel = localize('serverGroup', 'Server group');
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { Inject, NgModule, forwardRef, ApplicationRef, ComponentFactoryResolver, NgModuleRef, NgModuleFactory } from '@angular/core';
|
import { Inject, NgModule, forwardRef, ApplicationRef, ComponentFactoryResolver } from '@angular/core';
|
||||||
import { CommonModule, APP_BASE_HREF } from '@angular/common';
|
import { CommonModule, APP_BASE_HREF } from '@angular/common';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { RouterModule, Routes, UrlSerializer, Router, NavigationEnd } from '@angular/router';
|
import { RouterModule, Routes, UrlSerializer, Router, NavigationEnd } from '@angular/router';
|
||||||
@@ -14,7 +14,7 @@ import { ChartsModule } from 'ng2-charts/ng2-charts';
|
|||||||
import CustomUrlSerializer from 'sql/common/urlSerializer';
|
import CustomUrlSerializer from 'sql/common/urlSerializer';
|
||||||
import { Extensions, IInsightRegistry } from 'sql/platform/dashboard/common/insightRegistry';
|
import { Extensions, IInsightRegistry } from 'sql/platform/dashboard/common/insightRegistry';
|
||||||
import { Extensions as ComponentExtensions, IComponentRegistry } from 'sql/platform/dashboard/common/modelComponentRegistry';
|
import { Extensions as ComponentExtensions, IComponentRegistry } from 'sql/platform/dashboard/common/modelComponentRegistry';
|
||||||
import { IBootstrapParams } from 'sql/services/bootstrap/bootstrapService';
|
import { IBootstrapParams, ISelector, providerIterator } from 'sql/services/bootstrap/bootstrapService';
|
||||||
|
|
||||||
import { Registry } from 'vs/platform/registry/common/platform';
|
import { Registry } from 'vs/platform/registry/common/platform';
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ import { CommonServiceInterface } from 'sql/services/common/commonServiceInterfa
|
|||||||
import { ComponentHostDirective } from 'sql/parts/dashboard/common/componentHost.directive';
|
import { ComponentHostDirective } from 'sql/parts/dashboard/common/componentHost.directive';
|
||||||
|
|
||||||
/* Base Components */
|
/* Base Components */
|
||||||
import { DashboardComponent, DASHBOARD_SELECTOR } from 'sql/parts/dashboard/dashboard.component';
|
import { DashboardComponent } from 'sql/parts/dashboard/dashboard.component';
|
||||||
import { DashboardWidgetWrapper } from 'sql/parts/dashboard/contents/dashboardWidgetWrapper.component';
|
import { DashboardWidgetWrapper } from 'sql/parts/dashboard/contents/dashboardWidgetWrapper.component';
|
||||||
import { DashboardWidgetContainer } from 'sql/parts/dashboard/containers/dashboardWidgetContainer.component';
|
import { DashboardWidgetContainer } from 'sql/parts/dashboard/containers/dashboardWidgetContainer.component';
|
||||||
import { DashboardGridContainer } from 'sql/parts/dashboard/containers/dashboardGridContainer.component';
|
import { DashboardGridContainer } from 'sql/parts/dashboard/containers/dashboardGridContainer.component';
|
||||||
@@ -80,7 +80,8 @@ import { ExplorerWidget } from 'sql/parts/dashboard/widgets/explorer/explorerWid
|
|||||||
import { TasksWidget } from 'sql/parts/dashboard/widgets/tasks/tasksWidget.component';
|
import { TasksWidget } from 'sql/parts/dashboard/widgets/tasks/tasksWidget.component';
|
||||||
import { InsightsWidget } from 'sql/parts/dashboard/widgets/insights/insightsWidget.component';
|
import { InsightsWidget } from 'sql/parts/dashboard/widgets/insights/insightsWidget.component';
|
||||||
import { WebviewWidget } from 'sql/parts/dashboard/widgets/webview/webviewWidget.component';
|
import { WebviewWidget } from 'sql/parts/dashboard/widgets/webview/webviewWidget.component';
|
||||||
import { JobStepsViewComponent } from '../jobManagement/views/jobStepsView.component';
|
import { JobStepsViewComponent } from 'sql/parts/jobManagement/views/jobStepsView.component';
|
||||||
|
import { IInstantiationService, _util } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
|
||||||
let widgetComponents = [
|
let widgetComponents = [
|
||||||
PropertiesWidgetComponent,
|
PropertiesWidgetComponent,
|
||||||
@@ -109,7 +110,7 @@ const appRoutes: Routes = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
// Connection Dashboard main angular module
|
// Connection Dashboard main angular module
|
||||||
export const DashboardModule = (params, selector: string): any => {
|
export const DashboardModule = (params, selector: string, instantiationService: IInstantiationService): any => {
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
...baseComponents,
|
...baseComponents,
|
||||||
@@ -140,31 +141,31 @@ export const DashboardModule = (params, selector: string): any => {
|
|||||||
{ provide: IBreadcrumbService, useClass: BreadcrumbService },
|
{ provide: IBreadcrumbService, useClass: BreadcrumbService },
|
||||||
{ provide: CommonServiceInterface, useClass: DashboardServiceInterface },
|
{ provide: CommonServiceInterface, useClass: DashboardServiceInterface },
|
||||||
{ provide: UrlSerializer, useClass: CustomUrlSerializer },
|
{ provide: UrlSerializer, useClass: CustomUrlSerializer },
|
||||||
{ provide: IBootstrapParams, useValue: params }
|
{ provide: IBootstrapParams, useValue: params },
|
||||||
|
{ provide: ISelector, useValue: selector },
|
||||||
|
...providerIterator(instantiationService)
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
class ModuleClass {
|
class ModuleClass {
|
||||||
private _bootstrap: DashboardServiceInterface;
|
private navigations = 0;
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(forwardRef(() => ComponentFactoryResolver)) private _resolver: ComponentFactoryResolver,
|
@Inject(forwardRef(() => ComponentFactoryResolver)) private _resolver: ComponentFactoryResolver,
|
||||||
@Inject(forwardRef(() => CommonServiceInterface)) bootstrap: CommonServiceInterface,
|
|
||||||
@Inject(forwardRef(() => Router)) private _router: Router,
|
@Inject(forwardRef(() => Router)) private _router: Router,
|
||||||
@Inject(ITelemetryService) private telemetryService: ITelemetryService
|
@Inject(ITelemetryService) private telemetryService: ITelemetryService,
|
||||||
|
@Inject(ISelector) private selector: string
|
||||||
) {
|
) {
|
||||||
this._bootstrap = bootstrap as DashboardServiceInterface;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngDoBootstrap(appRef: ApplicationRef) {
|
ngDoBootstrap(appRef: ApplicationRef) {
|
||||||
const factory = this._resolver.resolveComponentFactory(DashboardComponent);
|
const factory = this._resolver.resolveComponentFactory(DashboardComponent);
|
||||||
this._bootstrap.selector = selector;
|
(<any>factory).factory.selector = this.selector;
|
||||||
(<any>factory).factory.selector = selector;
|
|
||||||
appRef.bootstrap(factory);
|
appRef.bootstrap(factory);
|
||||||
|
|
||||||
this._router.events.subscribe(e => {
|
this._router.events.subscribe(e => {
|
||||||
if (e instanceof NavigationEnd) {
|
if (e instanceof NavigationEnd) {
|
||||||
this._bootstrap.handlePageNavigation();
|
this.navigations++;
|
||||||
TelemetryUtils.addTelemetry(this.telemetryService, TelemetryKeys.DashboardNavigated, {
|
TelemetryUtils.addTelemetry(this.telemetryService, TelemetryKeys.DashboardNavigated, {
|
||||||
numberOfNavigations: this._bootstrap.getNumberOfPageNavigations(),
|
numberOfNavigations: this.navigations,
|
||||||
routeUrl: e.url
|
routeUrl: e.url
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,50 +4,29 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/* Node Modules */
|
/* Node Modules */
|
||||||
import { Injectable, Inject, forwardRef, OnDestroy } from '@angular/core';
|
import { Injectable, Inject, forwardRef } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { Observable } from 'rxjs/Observable';
|
|
||||||
|
|
||||||
/* SQL imports */
|
/* SQL imports */
|
||||||
import { IDashboardComponentParams } from 'sql/services/bootstrap/bootstrapParams';
|
import { IDashboardComponentParams } from 'sql/services/bootstrap/bootstrapParams';
|
||||||
import { IBootstrapParams } from 'sql/services/bootstrap/bootstrapService';
|
import { IBootstrapParams } from 'sql/services/bootstrap/bootstrapService';
|
||||||
import { IMetadataService } from 'sql/services/metadata/metadataService';
|
import { IMetadataService } from 'sql/services/metadata/metadataService';
|
||||||
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
|
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
|
||||||
import { ConnectionManagementInfo } from 'sql/parts/connection/common/connectionManagementInfo';
|
|
||||||
import { IAdminService } from 'sql/parts/admin/common/adminService';
|
import { IAdminService } from 'sql/parts/admin/common/adminService';
|
||||||
import { IQueryManagementService } from 'sql/parts/query/common/queryManagement';
|
import { IQueryManagementService } from 'sql/parts/query/common/queryManagement';
|
||||||
import { toDisposableSubscription } from 'sql/parts/common/rxjsUtils';
|
import { toDisposableSubscription } from 'sql/parts/common/rxjsUtils';
|
||||||
import { IInsightsDialogService } from 'sql/parts/insights/common/interfaces';
|
|
||||||
import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
|
|
||||||
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
|
||||||
import { AngularEventType, IAngularEvent, IAngularEventingService } from 'sql/services/angularEventing/angularEventingService';
|
import { AngularEventType, IAngularEvent, IAngularEventingService } from 'sql/services/angularEventing/angularEventingService';
|
||||||
import { IDashboardTab } from 'sql/platform/dashboard/common/dashboardRegistry';
|
import { IDashboardTab } from 'sql/platform/dashboard/common/dashboardRegistry';
|
||||||
import { TabSettingConfig } from 'sql/parts/dashboard/common/dashboardWidget';
|
import { TabSettingConfig } from 'sql/parts/dashboard/common/dashboardWidget';
|
||||||
import { IDashboardViewService } from 'sql/services/dashboard/common/dashboardViewService';
|
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
|
||||||
import { AngularDisposable } from 'sql/base/common/lifecycle';
|
|
||||||
import { ConnectionContextkey } from 'sql/parts/connection/common/connectionContextKey';
|
|
||||||
import { SingleConnectionMetadataService, SingleConnectionManagementService, SingleAdminService, SingleQueryManagementService, CommonServiceInterface }
|
|
||||||
from 'sql/services/common/commonServiceInterface.service';
|
|
||||||
|
|
||||||
import { ProviderMetadata, DatabaseInfo, SimpleExecuteResult } from 'sqlops';
|
|
||||||
|
|
||||||
/* VS imports */
|
/* VS imports */
|
||||||
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
|
||||||
import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
|
||||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
|
||||||
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||||
import { ConfigurationEditingService, IConfigurationValue } from 'vs/workbench/services/configuration/node/configurationEditingService';
|
|
||||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
|
||||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
|
||||||
import { Event, Emitter } from 'vs/base/common/event';
|
import { Event, Emitter } from 'vs/base/common/event';
|
||||||
import Severity from 'vs/base/common/severity';
|
import Severity from 'vs/base/common/severity';
|
||||||
import * as nls from 'vs/nls';
|
import * as nls from 'vs/nls';
|
||||||
import { IPartService } from 'vs/workbench/services/part/common/partService';
|
|
||||||
import { deepClone } from 'vs/base/common/objects';
|
import { deepClone } from 'vs/base/common/objects';
|
||||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
import { RawContextKey, IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||||
import { IContextKeyService, RawContextKey, IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
|
||||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
|
||||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||||
|
|
||||||
const DASHBOARD_SETTINGS = 'dashboard';
|
const DASHBOARD_SETTINGS = 'dashboard';
|
||||||
@@ -85,45 +64,22 @@ export class DashboardServiceInterface extends CommonServiceInterface {
|
|||||||
private _numberOfPageNavigations = 0;
|
private _numberOfPageNavigations = 0;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(forwardRef(() => Router)) private _router: Router,
|
|
||||||
@Inject(INotificationService) private _notificationService: INotificationService,
|
|
||||||
@Inject(IMetadataService) metadataService: IMetadataService,
|
@Inject(IMetadataService) metadataService: IMetadataService,
|
||||||
@Inject(IConnectionManagementService) connectionManagementService: IConnectionManagementService,
|
@Inject(IConnectionManagementService) connectionManagementService: IConnectionManagementService,
|
||||||
@Inject(IAdminService) adminService: IAdminService,
|
@Inject(IAdminService) adminService: IAdminService,
|
||||||
@Inject(IQueryManagementService) queryManagementService: IQueryManagementService,
|
@Inject(IQueryManagementService) queryManagementService: IQueryManagementService,
|
||||||
|
@Inject(IBootstrapParams) params: IDashboardComponentParams,
|
||||||
|
@Inject(forwardRef(() => Router)) private _router: Router,
|
||||||
|
@Inject(INotificationService) private _notificationService: INotificationService,
|
||||||
@Inject(IAngularEventingService) private angularEventingService: IAngularEventingService,
|
@Inject(IAngularEventingService) private angularEventingService: IAngularEventingService,
|
||||||
@Inject(IConfigurationService) private _configService: IConfigurationService,
|
@Inject(IConfigurationService) private _configService: IConfigurationService
|
||||||
@Inject(IBootstrapParams) _params: IDashboardComponentParams
|
|
||||||
) {
|
) {
|
||||||
super(_params, metadataService, connectionManagementService, adminService, queryManagementService);
|
super(params, metadataService, connectionManagementService, adminService, queryManagementService);
|
||||||
}
|
// during testing there may not be params
|
||||||
|
if (this._params) {
|
||||||
private get params(): IDashboardComponentParams {
|
this.dashboardContextKey = this._dashboardContextKey.bindTo(this.scopedContextKeyService);
|
||||||
return this._params;
|
this._register(toDisposableSubscription(this.angularEventingService.onAngularEvent(this._uri, (event) => this.handleDashboardEvent(event))));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the selector for this dashboard instance, should only be set once
|
|
||||||
*/
|
|
||||||
public set selector(selector: string) {
|
|
||||||
this._uniqueSelector = selector;
|
|
||||||
this._getbootstrapParams();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected _getbootstrapParams(): void {
|
|
||||||
this.scopedContextKeyService = this.params.scopedContextService;
|
|
||||||
this._connectionContextKey = this.params.connectionContextKey;
|
|
||||||
this.dashboardContextKey = this._dashboardContextKey.bindTo(this.scopedContextKeyService);
|
|
||||||
this.uri = this.params.ownerUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the uri for this dashboard instance, should only be set once
|
|
||||||
* Inits all the services that depend on knowing a uri
|
|
||||||
*/
|
|
||||||
protected set uri(uri: string) {
|
|
||||||
super.setUri(uri);
|
|
||||||
this._register(toDisposableSubscription(this.angularEventingService.onAngularEvent(this._uri, (event) => this.handleDashboardEvent(event))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -4,20 +4,23 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ApplicationRef, ComponentFactoryResolver, ModuleWithProviders, NgModule,
|
ApplicationRef, ComponentFactoryResolver, NgModule,
|
||||||
Inject, forwardRef, Type
|
Inject, forwardRef, Type
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { APP_BASE_HREF, CommonModule } from '@angular/common';
|
import { APP_BASE_HREF, CommonModule } from '@angular/common';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { IBootstrapParams } from 'sql/services/bootstrap/bootstrapService';
|
|
||||||
import { BackupComponent, BACKUP_SELECTOR } from 'sql/parts/disasterRecovery/backup/backup.component';
|
import { IBootstrapParams, ISelector, providerIterator } from 'sql/services/bootstrap/bootstrapService';
|
||||||
|
import { BackupComponent } from 'sql/parts/disasterRecovery/backup/backup.component';
|
||||||
|
|
||||||
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
|
||||||
// work around
|
// work around
|
||||||
const BrowserAnimationsModule = (<any>require.__$__nodeRequire('@angular/platform-browser/animations')).BrowserAnimationsModule;
|
const BrowserAnimationsModule = (<any>require.__$__nodeRequire('@angular/platform-browser/animations')).BrowserAnimationsModule;
|
||||||
|
|
||||||
// Backup wizard main angular module
|
// Backup wizard main angular module
|
||||||
export const BackupModule = (params: IBootstrapParams, selector: string): Type<any> => {
|
export const BackupModule = (params: IBootstrapParams, selector: string, instantiationService: IInstantiationService): Type<any> => {
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
BackupComponent
|
BackupComponent
|
||||||
@@ -31,19 +34,22 @@ export const BackupModule = (params: IBootstrapParams, selector: string): Type<a
|
|||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: APP_BASE_HREF, useValue: '/' },
|
{ provide: APP_BASE_HREF, useValue: '/' },
|
||||||
{ provide: IBootstrapParams, useValue: params }
|
{ provide: IBootstrapParams, useValue: params },
|
||||||
|
{ provide: ISelector, useValue: selector },
|
||||||
|
...providerIterator(instantiationService)
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
class ModuleClass {
|
class ModuleClass {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(forwardRef(() => ComponentFactoryResolver)) private _resolver: ComponentFactoryResolver
|
@Inject(forwardRef(() => ComponentFactoryResolver)) private _resolver: ComponentFactoryResolver,
|
||||||
|
@Inject(ISelector) private selector: string
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngDoBootstrap(appRef: ApplicationRef) {
|
ngDoBootstrap(appRef: ApplicationRef) {
|
||||||
const factory = this._resolver.resolveComponentFactory(BackupComponent);
|
const factory = this._resolver.resolveComponentFactory(BackupComponent);
|
||||||
(<any>factory).factory.selector = selector;
|
(<any>factory).factory.selector = this.selector;
|
||||||
appRef.bootstrap(factory);
|
appRef.bootstrap(factory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -235,7 +235,8 @@ export class RestoreDialog extends Modal {
|
|||||||
this._databaseDropdown = new Dropdown(inputCellContainer.getHTMLElement(), this._contextViewService, this._themeService,
|
this._databaseDropdown = new Dropdown(inputCellContainer.getHTMLElement(), this._contextViewService, this._themeService,
|
||||||
{
|
{
|
||||||
strictSelection: false,
|
strictSelection: false,
|
||||||
ariaLabel: LocalizedStrings.TARGETDATABASE
|
ariaLabel: LocalizedStrings.TARGETDATABASE,
|
||||||
|
actionLabel: localize('toggleDatabaseNameDropdown', 'Select Database Toggle Dropdown')
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
this._databaseDropdown.onValueChange(s => {
|
this._databaseDropdown.onValueChange(s => {
|
||||||
|
|||||||
@@ -7,12 +7,14 @@
|
|||||||
import { ApplicationRef, ComponentFactoryResolver, NgModule, Inject, forwardRef, Type } from '@angular/core';
|
import { ApplicationRef, ComponentFactoryResolver, NgModule, Inject, forwardRef, Type } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
|
||||||
import { EditDataComponent, EDITDATA_SELECTOR } from 'sql/parts/grid/views/editData/editData.component';
|
|
||||||
import { SlickGrid } from 'angular2-slickgrid';
|
import { SlickGrid } from 'angular2-slickgrid';
|
||||||
import { IBootstrapParams } from 'sql/services/bootstrap/bootstrapService';
|
|
||||||
|
|
||||||
export const EditDataModule = (params: IBootstrapParams, selector: string): Type<any> => {
|
import { EditDataComponent } from 'sql/parts/grid/views/editData/editData.component';
|
||||||
|
import { IBootstrapParams, ISelector, providerIterator } from 'sql/services/bootstrap/bootstrapService';
|
||||||
|
|
||||||
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
|
||||||
|
export const EditDataModule = (params: IBootstrapParams, selector: string, instantiationService: IInstantiationService): Type<any> => {
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
|
||||||
@@ -30,19 +32,22 @@ export const EditDataModule = (params: IBootstrapParams, selector: string): Type
|
|||||||
EditDataComponent
|
EditDataComponent
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: IBootstrapParams, useValue: params }
|
{ provide: IBootstrapParams, useValue: params },
|
||||||
|
{ provide: ISelector, useValue: selector },
|
||||||
|
...providerIterator(instantiationService)
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
class ModuleClass {
|
class ModuleClass {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(forwardRef(() => ComponentFactoryResolver)) private _resolver: ComponentFactoryResolver
|
@Inject(forwardRef(() => ComponentFactoryResolver)) private _resolver: ComponentFactoryResolver,
|
||||||
|
@Inject(ISelector) private selector: string
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngDoBootstrap(appRef: ApplicationRef) {
|
ngDoBootstrap(appRef: ApplicationRef) {
|
||||||
const factory = this._resolver.resolveComponentFactory(EditDataComponent);
|
const factory = this._resolver.resolveComponentFactory(EditDataComponent);
|
||||||
(<any>factory).factory.selector = selector;
|
(<any>factory).factory.selector = this.selector;
|
||||||
appRef.bootstrap(factory);
|
appRef.bootstrap(factory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,21 +10,16 @@ import {
|
|||||||
|
|
||||||
import * as sqlops from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
|
|
||||||
import { ComponentBase } from 'sql/parts/modelComponents/componentBase';
|
import { ComponentWithIconBase } from 'sql/parts/modelComponents/componentWithIconBase';
|
||||||
import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType } from 'sql/parts/modelComponents/interfaces';
|
import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType } from 'sql/parts/modelComponents/interfaces';
|
||||||
import { attachButtonStyler } from 'sql/common/theme/styler';
|
import { attachButtonStyler } from 'sql/common/theme/styler';
|
||||||
import { Button } from 'sql/base/browser/ui/button/button';
|
import { Button } from 'sql/base/browser/ui/button/button';
|
||||||
|
|
||||||
import { SIDE_BAR_BACKGROUND, SIDE_BAR_TITLE_FOREGROUND } from 'vs/workbench/common/theme';
|
import { SIDE_BAR_BACKGROUND, SIDE_BAR_TITLE_FOREGROUND } from 'vs/workbench/common/theme';
|
||||||
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
||||||
import { attachListStyler } from 'vs/platform/theme/common/styler';
|
|
||||||
import URI from 'vs/base/common/uri';
|
|
||||||
import { IdGenerator } from 'vs/base/common/idGenerator';
|
|
||||||
import { createCSSRule, removeCSSRulesContainingSelector } from 'vs/base/browser/dom';
|
|
||||||
import { focusBorder, foreground } from 'vs/platform/theme/common/colorRegistry';
|
import { focusBorder, foreground } from 'vs/platform/theme/common/colorRegistry';
|
||||||
import { Color } from 'vs/base/common/color';
|
import { Color } from 'vs/base/common/color';
|
||||||
|
|
||||||
type IUserFriendlyIcon = string | URI | { light: string | URI; dark: string | URI };
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'modelview-button',
|
selector: 'modelview-button',
|
||||||
@@ -32,12 +27,10 @@ type IUserFriendlyIcon = string | URI | { light: string | URI; dark: string | UR
|
|||||||
<div #input style="width: 100%"></div>
|
<div #input style="width: 100%"></div>
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
export default class ButtonComponent extends ComponentBase implements IComponent, OnDestroy, AfterViewInit {
|
export default class ButtonComponent extends ComponentWithIconBase implements IComponent, OnDestroy, AfterViewInit {
|
||||||
@Input() descriptor: IComponentDescriptor;
|
@Input() descriptor: IComponentDescriptor;
|
||||||
@Input() modelStore: IModelStore;
|
@Input() modelStore: IModelStore;
|
||||||
private _button: Button;
|
private _button: Button;
|
||||||
private _iconClass: string;
|
|
||||||
private _iconPath: IUserFriendlyIcon;
|
|
||||||
|
|
||||||
@ViewChild('input', { read: ElementRef }) private _inputContainer: ElementRef;
|
@ViewChild('input', { read: ElementRef }) private _inputContainer: ElementRef;
|
||||||
constructor(
|
constructor(
|
||||||
@@ -71,9 +64,6 @@ export default class ButtonComponent extends ComponentBase implements IComponent
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
if (this._iconClass) {
|
|
||||||
removeCSSRulesContainingSelector(this._iconClass);
|
|
||||||
}
|
|
||||||
this.baseDestroy();
|
this.baseDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,14 +91,11 @@ export default class ButtonComponent extends ComponentBase implements IComponent
|
|||||||
this.updateIcon();
|
this.updateIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateIcon() {
|
protected updateIcon() {
|
||||||
if (this.iconPath && this.iconPath !== this._iconPath) {
|
if (this.iconPath) {
|
||||||
this._iconPath = this.iconPath;
|
|
||||||
if (!this._iconClass) {
|
if (!this._iconClass) {
|
||||||
const ids = new IdGenerator('button-component-icon-' + Math.round(Math.random() * 1000));
|
super.updateIcon();
|
||||||
this._iconClass = ids.nextId();
|
|
||||||
this._button.icon = this._iconClass + ' icon';
|
this._button.icon = this._iconClass + ' icon';
|
||||||
|
|
||||||
// Styling for icon button
|
// Styling for icon button
|
||||||
this._register(attachButtonStyler(this._button, this.themeService, {
|
this._register(attachButtonStyler(this._button, this.themeService, {
|
||||||
buttonBackground: Color.transparent.toString(),
|
buttonBackground: Color.transparent.toString(),
|
||||||
@@ -117,36 +104,6 @@ export default class ButtonComponent extends ComponentBase implements IComponent
|
|||||||
buttonForeground: foreground
|
buttonForeground: foreground
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
removeCSSRulesContainingSelector(this._iconClass);
|
|
||||||
const icon = this.getLightIconPath(this.iconPath);
|
|
||||||
const iconDark = this.getDarkIconPath(this.iconPath) || icon;
|
|
||||||
createCSSRule(`.icon.${this._iconClass}`, `background-image: url("${icon}")`);
|
|
||||||
createCSSRule(`.vs-dark .icon.${this._iconClass}, .hc-black .icon.${this._iconClass}`, `background-image: url("${iconDark}")`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private getLightIconPath(iconPath: IUserFriendlyIcon): string {
|
|
||||||
if (iconPath && iconPath['light']) {
|
|
||||||
return this.getIconPath(iconPath['light']);
|
|
||||||
} else {
|
|
||||||
return this.getIconPath(<string | URI>iconPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private getDarkIconPath(iconPath: IUserFriendlyIcon): string {
|
|
||||||
if (iconPath && iconPath['dark']) {
|
|
||||||
return this.getIconPath(iconPath['dark']);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private getIconPath(iconPath: string | URI): string {
|
|
||||||
if (typeof iconPath === 'string') {
|
|
||||||
return URI.file(iconPath).toString();
|
|
||||||
} else {
|
|
||||||
let uri = URI.revive(iconPath);
|
|
||||||
return uri.toString();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,13 +117,7 @@ export default class ButtonComponent extends ComponentBase implements IComponent
|
|||||||
this.setPropertyFromUI<sqlops.ButtonProperties, string>(this.setValueProperties, newValue);
|
this.setPropertyFromUI<sqlops.ButtonProperties, string>(this.setValueProperties, newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public get iconPath(): string | URI | { light: string | URI; dark: string | URI } {
|
|
||||||
return this.getPropertyOrDefault<sqlops.ButtonProperties, IUserFriendlyIcon>((props) => props.iconPath, undefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
public set iconPath(newValue: string | URI | { light: string | URI; dark: string | URI }) {
|
|
||||||
this.setPropertyFromUI<sqlops.ButtonProperties, IUserFriendlyIcon>((properties, iconPath) => { properties.iconPath = iconPath; }, newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
private setValueProperties(properties: sqlops.ButtonProperties, label: string): void {
|
private setValueProperties(properties: sqlops.ButtonProperties, label: string): void {
|
||||||
properties.label = label;
|
properties.label = label;
|
||||||
|
|||||||
@@ -1,19 +1,32 @@
|
|||||||
<div *ngIf="label" class="model-card">
|
<div *ngIf="label" [class]="getClass()" (click)="onCardClick()" (mouseover)="onCardHoverChanged($event)" (mouseout)="onCardHoverChanged($event)">
|
||||||
<span *ngIf="hasStatus" class="card-status">
|
<span *ngIf="hasStatus" class="card-status">
|
||||||
<div class="status-content" [style.backgroundColor]="statusColor"></div>
|
<div class="status-content" [style.backgroundColor]="statusColor"></div>
|
||||||
</span>
|
</span>
|
||||||
<div class="card-content">
|
|
||||||
<h4 class="card-label">{{label}}</h4>
|
<ng-container *ngIf="isVerticalButton">
|
||||||
<p class="card-value">{{value}}</p>
|
<div class="card-vertical-button">
|
||||||
<span *ngIf="actions">
|
<div *ngIf="iconPath" class="iconContainer"><div [class]="iconClass" [style.width]="iconWidth" [style.height]="iconHeight"></div>
|
||||||
<table class="model-table">
|
<hr/>
|
||||||
<tr *ngFor="let action of actions">
|
<h4 class="card-label">{{label}}</h4>
|
||||||
<td class="table-row">{{action.label}}</td>
|
</div>
|
||||||
<td *ngIf="action.actionTitle" class="table-row">
|
</div>
|
||||||
<a class="pointer prominent" (click)="onDidActionClick(action)">{{action.actionTitle}}</a>
|
</ng-container>
|
||||||
</td>
|
|
||||||
</tr>
|
<ng-container *ngIf="isDetailsCard">
|
||||||
</table>
|
<div class="card-content">
|
||||||
</span>
|
<h4 class="card-label">{{label}}</h4>
|
||||||
</div>
|
<p class="card-value">{{value}}</p>
|
||||||
|
<span *ngIf="actions">
|
||||||
|
<table class="model-table">
|
||||||
|
<tr *ngFor="let action of actions">
|
||||||
|
<td class="table-row">{{action.label}}</td>
|
||||||
|
<td *ngIf="action.actionTitle" class="table-row">
|
||||||
|
<a class="pointer prominent" (click)="onDidActionClick(action)">{{action.actionTitle}}</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -15,14 +15,14 @@ import * as colors from 'vs/platform/theme/common/colorRegistry';
|
|||||||
import { IColorTheme, IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
import { IColorTheme, IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
||||||
|
|
||||||
import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service';
|
import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service';
|
||||||
import { ComponentBase } from 'sql/parts/modelComponents/componentBase';
|
import { ComponentWithIconBase } from 'sql/parts/modelComponents/componentWithIconBase';
|
||||||
import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType } from 'sql/parts/modelComponents/interfaces';
|
import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType } from 'sql/parts/modelComponents/interfaces';
|
||||||
import { StatusIndicator, CardProperties, ActionDescriptor } from 'sql/workbench/api/common/sqlExtHostTypes';
|
import { StatusIndicator, CardProperties, ActionDescriptor } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: decodeURI(require.toUrl('sql/parts/modelComponents/card.component.html'))
|
templateUrl: decodeURI(require.toUrl('sql/parts/modelComponents/card.component.html'))
|
||||||
})
|
})
|
||||||
export default class CardComponent extends ComponentBase implements IComponent, OnDestroy {
|
export default class CardComponent extends ComponentWithIconBase implements IComponent, OnDestroy {
|
||||||
@Input() descriptor: IComponentDescriptor;
|
@Input() descriptor: IComponentDescriptor;
|
||||||
@Input() modelStore: IModelStore;
|
@Input() modelStore: IModelStore;
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ export default class CardComponent extends ComponentBase implements IComponent,
|
|||||||
|
|
||||||
constructor(@Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef,
|
constructor(@Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef,
|
||||||
@Inject(forwardRef(() => ElementRef)) private _el: ElementRef,
|
@Inject(forwardRef(() => ElementRef)) private _el: ElementRef,
|
||||||
@Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService
|
@Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService,
|
||||||
) {
|
) {
|
||||||
super(changeRef);
|
super(changeRef);
|
||||||
}
|
}
|
||||||
@@ -46,6 +46,39 @@ export default class CardComponent extends ComponentBase implements IComponent,
|
|||||||
this.baseDestroy();
|
this.baseDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _defaultBorderColor = 'rgb(214, 214, 214)';
|
||||||
|
private _hasFocus: boolean;
|
||||||
|
|
||||||
|
public onCardClick() {
|
||||||
|
if (this.selectable) {
|
||||||
|
this.selected = !this.selected;
|
||||||
|
this._changeRef.detectChanges();
|
||||||
|
this._onEventEmitter.fire({
|
||||||
|
eventType: ComponentEventType.onDidClick,
|
||||||
|
args: this.selected
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public getBorderColor() {
|
||||||
|
if (this.selectable && this.selected || this._hasFocus) {
|
||||||
|
return 'Blue';
|
||||||
|
} else {
|
||||||
|
return this._defaultBorderColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public getClass(): string {
|
||||||
|
return (this.selectable && this.selected || this._hasFocus) ? 'model-card selected' :
|
||||||
|
'model-card unselected';
|
||||||
|
}
|
||||||
|
|
||||||
|
public onCardHoverChanged(event: any) {
|
||||||
|
if (this.selectable) {
|
||||||
|
this._hasFocus = event.type === 'mouseover';
|
||||||
|
this._changeRef.detectChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
/// IComponent implementation
|
/// IComponent implementation
|
||||||
|
|
||||||
public layout(): void {
|
public layout(): void {
|
||||||
@@ -57,6 +90,19 @@ export default class CardComponent extends ComponentBase implements IComponent,
|
|||||||
this.layout();
|
this.layout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setProperties(properties: { [key: string]: any; }): void {
|
||||||
|
super.setProperties(properties);
|
||||||
|
this.updateIcon();
|
||||||
|
}
|
||||||
|
|
||||||
|
public get iconClass(): string {
|
||||||
|
return this._iconClass + ' icon' + ' cardIcon';
|
||||||
|
}
|
||||||
|
|
||||||
|
private get selectable(): boolean {
|
||||||
|
return this.cardType === 'VerticalButton';
|
||||||
|
}
|
||||||
|
|
||||||
// CSS-bound properties
|
// CSS-bound properties
|
||||||
|
|
||||||
public get label(): string {
|
public get label(): string {
|
||||||
@@ -67,6 +113,27 @@ export default class CardComponent extends ComponentBase implements IComponent,
|
|||||||
return this.getPropertyOrDefault<CardProperties, string>((props) => props.value, '');
|
return this.getPropertyOrDefault<CardProperties, string>((props) => props.value, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get cardType(): string {
|
||||||
|
return this.getPropertyOrDefault<CardProperties, string>((props) => props.cardType, 'Details');
|
||||||
|
}
|
||||||
|
|
||||||
|
public get selected(): boolean {
|
||||||
|
return this.getPropertyOrDefault<sqlops.CardProperties, boolean>((props) => props.selected, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public set selected(newValue: boolean) {
|
||||||
|
this.setPropertyFromUI<sqlops.CardProperties, boolean>((props, value) => props.selected = value, newValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public get isDetailsCard(): boolean {
|
||||||
|
return !this.cardType || this.cardType === 'Details';
|
||||||
|
}
|
||||||
|
|
||||||
|
public get isVerticalButton(): boolean {
|
||||||
|
return this.cardType === 'VerticalButton';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public get actions(): ActionDescriptor[] {
|
public get actions(): ActionDescriptor[] {
|
||||||
return this.getPropertyOrDefault<CardProperties, ActionDescriptor[]>((props) => props.actions, []);
|
return this.getPropertyOrDefault<CardProperties, ActionDescriptor[]>((props) => props.actions, []);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,26 @@
|
|||||||
margin: 15px;
|
margin: 15px;
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-color: rgb(214, 214, 214);
|
|
||||||
text-align: left;
|
text-align: left;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
box-shadow: rgba(120, 120, 120, 0.75) 0px 0px 6px;
|
box-shadow: rgba(120, 120, 120, 0.75) 0px 0px 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.model-card.selected {
|
||||||
|
border-color: darkblue
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs-dark .monaco-workbench .model-card.selected,
|
||||||
|
.hc-black .monaco-workbench .model-card.selected {
|
||||||
|
border-color: darkblue
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-card.unselected {
|
||||||
|
border-color: rgb(214, 214, 214);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.model-card .card-content {
|
.model-card .card-content {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@@ -23,6 +37,16 @@
|
|||||||
min-width: 30px;
|
min-width: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.model-card .card-vertical-button {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
height: auto;
|
||||||
|
width: auto;
|
||||||
|
padding: 5px 5px 5px 5px;
|
||||||
|
min-height: 130px;
|
||||||
|
min-width: 130px;
|
||||||
|
}
|
||||||
|
|
||||||
.model-card .card-label {
|
.model-card .card-label {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
@@ -33,6 +57,19 @@
|
|||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.model-card .iconContainer {
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
text-align: center;
|
||||||
|
padding: 10px 0px 10px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-card .cardIcon {
|
||||||
|
display: inline-block;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
.model-card .card-status {
|
.model-card .card-status {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 7px;
|
top: 7px;
|
||||||
|
|||||||
@@ -18,6 +18,12 @@ import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboar
|
|||||||
import { Event, Emitter } from 'vs/base/common/event';
|
import { Event, Emitter } from 'vs/base/common/event';
|
||||||
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||||
import { ModelComponentWrapper } from 'sql/parts/modelComponents/modelComponentWrapper.component';
|
import { ModelComponentWrapper } from 'sql/parts/modelComponents/modelComponentWrapper.component';
|
||||||
|
import URI from 'vs/base/common/uri';
|
||||||
|
import { IdGenerator } from 'vs/base/common/idGenerator';
|
||||||
|
import { createCSSRule, removeCSSRulesContainingSelector } from 'vs/base/browser/dom';
|
||||||
|
|
||||||
|
|
||||||
|
export type IUserFriendlyIcon = string | URI | { light: string | URI; dark: string | URI };
|
||||||
|
|
||||||
export class ItemDescriptor<T> {
|
export class ItemDescriptor<T> {
|
||||||
constructor(public descriptor: IComponentDescriptor, public config: T) { }
|
constructor(public descriptor: IComponentDescriptor, public config: T) { }
|
||||||
@@ -98,10 +104,6 @@ export abstract class ComponentBase extends Disposable implements IComponent, On
|
|||||||
if (enabled === undefined) {
|
if (enabled === undefined) {
|
||||||
enabled = true;
|
enabled = true;
|
||||||
properties['enabled'] = enabled;
|
properties['enabled'] = enabled;
|
||||||
this.fireEvent({
|
|
||||||
eventType: ComponentEventType.PropertiesChanged,
|
|
||||||
args: this.getProperties()
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return <boolean>enabled;
|
return <boolean>enabled;
|
||||||
}
|
}
|
||||||
|
|||||||
107
src/sql/parts/modelComponents/componentWithIconBase.ts
Normal file
107
src/sql/parts/modelComponents/componentWithIconBase.ts
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
Component, Input, Inject, ChangeDetectorRef, forwardRef, ComponentFactoryResolver,
|
||||||
|
ViewChild, ViewChildren, ElementRef, Injector, OnDestroy, OnInit, QueryList
|
||||||
|
} from '@angular/core';
|
||||||
|
|
||||||
|
import { IComponent, IComponentDescriptor, IModelStore, IComponentEventArgs, ComponentEventType } from 'sql/parts/modelComponents/interfaces';
|
||||||
|
import * as sqlops from 'sqlops';
|
||||||
|
import URI from 'vs/base/common/uri';
|
||||||
|
import { IdGenerator } from 'vs/base/common/idGenerator';
|
||||||
|
import { createCSSRule, removeCSSRulesContainingSelector } from 'vs/base/browser/dom';
|
||||||
|
import { ComponentBase } from 'sql/parts/modelComponents/componentBase';
|
||||||
|
|
||||||
|
|
||||||
|
export type IUserFriendlyIcon = string | URI | { light: string | URI; dark: string | URI };
|
||||||
|
|
||||||
|
export class ItemDescriptor<T> {
|
||||||
|
constructor(public descriptor: IComponentDescriptor, public config: T) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class ComponentWithIconBase extends ComponentBase {
|
||||||
|
|
||||||
|
protected _iconClass: string;
|
||||||
|
protected _iconPath: IUserFriendlyIcon;
|
||||||
|
constructor(
|
||||||
|
changeRef: ChangeDetectorRef) {
|
||||||
|
super(changeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// IComponent implementation
|
||||||
|
|
||||||
|
public get iconClass(): string {
|
||||||
|
return this._iconClass + ' icon';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected updateIcon() {
|
||||||
|
if (this.iconPath && this.iconPath !== this._iconPath) {
|
||||||
|
this._iconPath = this.iconPath;
|
||||||
|
if (!this._iconClass) {
|
||||||
|
const ids = new IdGenerator('model-view-component-icon-' + Math.round(Math.random() * 1000));
|
||||||
|
this._iconClass = ids.nextId();
|
||||||
|
}
|
||||||
|
|
||||||
|
removeCSSRulesContainingSelector(this._iconClass);
|
||||||
|
const icon = this.getLightIconPath(this.iconPath);
|
||||||
|
const iconDark = this.getDarkIconPath(this.iconPath) || icon;
|
||||||
|
createCSSRule(`.icon.${this._iconClass}`, `background-image: url("${icon}")`);
|
||||||
|
createCSSRule(`.vs-dark .icon.${this._iconClass}, .hc-black .icon.${this._iconClass}`, `background-image: url("${iconDark}")`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getLightIconPath(iconPath: IUserFriendlyIcon): string {
|
||||||
|
if (iconPath && iconPath['light']) {
|
||||||
|
return this.getIconPath(iconPath['light']);
|
||||||
|
} else {
|
||||||
|
return this.getIconPath(<string | URI>iconPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getDarkIconPath(iconPath: IUserFriendlyIcon): string {
|
||||||
|
if (iconPath && iconPath['dark']) {
|
||||||
|
return this.getIconPath(iconPath['dark']);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getIconPath(iconPath: string | URI): string {
|
||||||
|
if (typeof iconPath === 'string') {
|
||||||
|
return URI.file(iconPath).toString();
|
||||||
|
} else {
|
||||||
|
let uri = URI.revive(iconPath);
|
||||||
|
return uri.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public getIconWidth(): string {
|
||||||
|
return this.convertSize(this.iconWidth, '40px');
|
||||||
|
}
|
||||||
|
|
||||||
|
public getIconHeight(): string {
|
||||||
|
return this.convertSize(this.iconHeight, '40px');
|
||||||
|
}
|
||||||
|
|
||||||
|
public get iconPath(): string | URI | { light: string | URI; dark: string | URI } {
|
||||||
|
return this.getPropertyOrDefault<sqlops.ComponentWithIcon, IUserFriendlyIcon>((props) => props.iconPath, undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
public get iconHeight(): number | string {
|
||||||
|
return this.getPropertyOrDefault<sqlops.ComponentWithIcon, number | string>((props) => props.iconHeight, '40px');
|
||||||
|
}
|
||||||
|
|
||||||
|
public get iconWidth(): number | string {
|
||||||
|
return this.getPropertyOrDefault<sqlops.ComponentWithIcon, number | string>((props) => props.iconWidth, '40px');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
if (this._iconClass) {
|
||||||
|
removeCSSRulesContainingSelector(this._iconClass);
|
||||||
|
}
|
||||||
|
super.ngOnDestroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,8 +4,8 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Component, Input, Inject, ChangeDetectorRef, forwardRef, ComponentFactoryResolver,
|
Component, Input, Inject, ChangeDetectorRef, forwardRef,
|
||||||
ViewChild, ViewChildren, ElementRef, Injector, OnDestroy, QueryList, AfterViewInit
|
ViewChild, ElementRef, OnDestroy, AfterViewInit
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
|
|
||||||
import * as sqlops from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
@@ -14,14 +14,11 @@ import { ComponentBase } from 'sql/parts/modelComponents/componentBase';
|
|||||||
import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType } from 'sql/parts/modelComponents/interfaces';
|
import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType } from 'sql/parts/modelComponents/interfaces';
|
||||||
import { Dropdown, IDropdownOptions } from 'sql/base/browser/ui/editableDropdown/dropdown';
|
import { Dropdown, IDropdownOptions } from 'sql/base/browser/ui/editableDropdown/dropdown';
|
||||||
import { SelectBox } from 'sql/base/browser/ui/selectBox/selectBox';
|
import { SelectBox } from 'sql/base/browser/ui/selectBox/selectBox';
|
||||||
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
|
|
||||||
import { attachEditableDropdownStyler } from 'sql/common/theme/styler';
|
import { attachEditableDropdownStyler } from 'sql/common/theme/styler';
|
||||||
import { attachSelectBoxStyler } from 'vs/platform/theme/common/styler';
|
import { attachSelectBoxStyler } from 'vs/platform/theme/common/styler';
|
||||||
|
|
||||||
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
||||||
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
||||||
import { Event, Emitter } from 'vs/base/common/event';
|
|
||||||
import { attachListStyler } from 'vs/platform/theme/common/styler';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'modelview-dropdown',
|
selector: 'modelview-dropdown',
|
||||||
@@ -60,7 +57,8 @@ export default class DropDownComponent extends ComponentBase implements ICompone
|
|||||||
strictSelection: false,
|
strictSelection: false,
|
||||||
placeholder: '',
|
placeholder: '',
|
||||||
maxHeight: 125,
|
maxHeight: 125,
|
||||||
ariaLabel: ''
|
ariaLabel: '',
|
||||||
|
actionLabel: ''
|
||||||
};
|
};
|
||||||
this._editableDropdown = new Dropdown(this._editableDropDownContainer.nativeElement, this.contextViewService, this.themeService,
|
this._editableDropdown = new Dropdown(this._editableDropDownContainer.nativeElement, this.contextViewService, this.themeService,
|
||||||
dropdownOptions);
|
dropdownOptions);
|
||||||
@@ -147,15 +145,11 @@ export default class DropDownComponent extends ComponentBase implements ICompone
|
|||||||
private getSelectedValue(): string {
|
private getSelectedValue(): string {
|
||||||
if (this.values && this.values.length > 0 && this.valuesHaveDisplayName()) {
|
if (this.values && this.values.length > 0 && this.valuesHaveDisplayName()) {
|
||||||
let selectedValue = <sqlops.CategoryValue>this.value || <sqlops.CategoryValue>this.values[0];
|
let selectedValue = <sqlops.CategoryValue>this.value || <sqlops.CategoryValue>this.values[0];
|
||||||
if (!this.value) {
|
|
||||||
this.value = selectedValue;
|
|
||||||
}
|
|
||||||
let valueCategory = (<sqlops.CategoryValue[]>this.values).find(v => v.name === selectedValue.name);
|
let valueCategory = (<sqlops.CategoryValue[]>this.values).find(v => v.name === selectedValue.name);
|
||||||
|
|
||||||
return valueCategory && valueCategory.displayName;
|
return valueCategory && valueCategory.displayName;
|
||||||
} else {
|
} else {
|
||||||
if (!this.value && this.values && this.values.length > 0) {
|
if (!this.value && this.values && this.values.length > 0) {
|
||||||
this.value = <string>this.values[0];
|
return <string>this.values[0];
|
||||||
}
|
}
|
||||||
return <string>this.value;
|
return <string>this.value;
|
||||||
}
|
}
|
||||||
@@ -200,11 +194,11 @@ export default class DropDownComponent extends ComponentBase implements ICompone
|
|||||||
this.setPropertyFromUI<sqlops.DropDownProperties, string[] | sqlops.CategoryValue[]>(this.setValuesProperties, newValue);
|
this.setPropertyFromUI<sqlops.DropDownProperties, string[] | sqlops.CategoryValue[]>(this.setValuesProperties, newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private setValueProperties(properties: sqlops.DropDownProperties, value: string): void {
|
private setValueProperties(properties: sqlops.DropDownProperties, value: string | sqlops.CategoryValue): void {
|
||||||
properties.value = value;
|
properties.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private setValuesProperties(properties: sqlops.DropDownProperties, values: string[]): void {
|
private setValuesProperties(properties: sqlops.DropDownProperties, values: string[] | sqlops.CategoryValue[]): void {
|
||||||
properties.values = values;
|
properties.values = values;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
import 'vs/css!./formLayout';
|
import 'vs/css!./formLayout';
|
||||||
|
import 'vs/css!sql/media/icons/common-icons';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Component, Input, Inject, ChangeDetectorRef, forwardRef, ComponentFactoryResolver,
|
Component, Input, Inject, ChangeDetectorRef, forwardRef, ComponentFactoryResolver,
|
||||||
@@ -25,6 +26,9 @@ export interface TitledFormItemLayout {
|
|||||||
horizontal: boolean;
|
horizontal: boolean;
|
||||||
componentWidth?: number | string;
|
componentWidth?: number | string;
|
||||||
componentHeight?: number | string;
|
componentHeight?: number | string;
|
||||||
|
titleFontSize?: number | string;
|
||||||
|
required?: boolean;
|
||||||
|
info?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FormLayout {
|
export interface FormLayout {
|
||||||
@@ -37,12 +41,15 @@ class FormItem {
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
template: `
|
template: `
|
||||||
<div #container *ngIf="items" class="form-table" [style.width]="getFormWidth()" [style.height]="getFormHeight()">
|
<div #container *ngIf="items" class="form-table" [style.padding]="getFormPadding()" [style.width]="getFormWidth()" [style.height]="getFormHeight()">
|
||||||
<ng-container *ngFor="let item of items">
|
<ng-container *ngFor="let item of items">
|
||||||
<div class="form-row" *ngIf="isFormComponent(item)" [style.height]="getRowHeight(item)">
|
<div class="form-row" *ngIf="isFormComponent(item)" [style.height]="getRowHeight(item)">
|
||||||
|
|
||||||
<ng-container *ngIf="isHorizontal(item)">
|
<ng-container *ngIf="isHorizontal(item)">
|
||||||
<div class="form-cell">{{getItemTitle(item)}}</div>
|
<div class="form-cell" [style.font-size]="getItemTitleFontSize(item)">
|
||||||
|
{{getItemTitle(item)}}<span class="form-required" *ngIf="isItemRequired(item)">*</span>
|
||||||
|
<span class="icon info form-info" *ngIf="itemHasInfo(item)" [title]="getItemInfo(item)"></span>
|
||||||
|
</div>
|
||||||
<div class="form-cell">
|
<div class="form-cell">
|
||||||
<div class="form-component-container">
|
<div class="form-component-container">
|
||||||
<div [style.width]="getComponentWidth(item)" [ngClass]="{'form-input-flex': !getComponentWidth(item)}">
|
<div [style.width]="getComponentWidth(item)" [ngClass]="{'form-input-flex': !getComponentWidth(item)}">
|
||||||
@@ -59,7 +66,10 @@ class FormItem {
|
|||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<div class="form-vertical-container" *ngIf="isVertical(item)" [style.height]="getRowHeight(item)">
|
<div class="form-vertical-container" *ngIf="isVertical(item)" [style.height]="getRowHeight(item)">
|
||||||
<div class="form-item-row">{{getItemTitle(item)}}</div>
|
<div class="form-item-row" [style.font-size]="getItemTitleFontSize(item)">
|
||||||
|
{{getItemTitle(item)}}<span class="form-required" *ngIf="isItemRequired(item)">*</span>
|
||||||
|
<span class="icon info form-info" *ngIf="itemHasInfo(item)" [title]="getItemInfo(item)"></span>
|
||||||
|
</div>
|
||||||
<div class="form-item-row" [style.width]="getComponentWidth(item)" [style.height]="getRowHeight(item)">
|
<div class="form-item-row" [style.width]="getComponentWidth(item)" [style.height]="getRowHeight(item)">
|
||||||
<model-component-wrapper [descriptor]="item.descriptor" [modelStore]="modelStore" [style.width]="getComponentWidth(item)" [style.height]="getRowHeight(item)">
|
<model-component-wrapper [descriptor]="item.descriptor" [modelStore]="modelStore" [style.width]="getComponentWidth(item)" [style.height]="getRowHeight(item)">
|
||||||
</model-component-wrapper>
|
</model-component-wrapper>
|
||||||
@@ -121,6 +131,10 @@ export default class FormContainer extends ContainerBase<FormItemLayout> impleme
|
|||||||
return this.convertSize(this._formLayout && this._formLayout.width, '');
|
return this.convertSize(this._formLayout && this._formLayout.width, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getFormPadding(): string {
|
||||||
|
return this._formLayout && this._formLayout.padding ? this._formLayout.padding : '10px 30px 0px 30px';
|
||||||
|
}
|
||||||
|
|
||||||
private getFormHeight(): string {
|
private getFormHeight(): string {
|
||||||
return this.convertSize(this._formLayout && this._formLayout.height, '');
|
return this.convertSize(this._formLayout && this._formLayout.height, '');
|
||||||
}
|
}
|
||||||
@@ -135,11 +149,32 @@ export default class FormContainer extends ContainerBase<FormItemLayout> impleme
|
|||||||
return (itemConfig && itemConfig.componentHeight) ? this.convertSize(itemConfig.componentHeight, '') : '';
|
return (itemConfig && itemConfig.componentHeight) ? this.convertSize(itemConfig.componentHeight, '') : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private isItemRequired(item: FormItem): boolean {
|
||||||
|
let itemConfig = item.config;
|
||||||
|
return itemConfig && itemConfig.required;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getItemInfo(item: FormItem): string {
|
||||||
|
let itemConfig = item.config;
|
||||||
|
return itemConfig && itemConfig.info;
|
||||||
|
}
|
||||||
|
|
||||||
|
private itemHasInfo(item: FormItem): boolean {
|
||||||
|
let itemConfig = item.config;
|
||||||
|
return itemConfig && itemConfig.info !== undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private getItemTitle(item: FormItem): string {
|
private getItemTitle(item: FormItem): string {
|
||||||
let itemConfig = item.config;
|
let itemConfig = item.config;
|
||||||
return itemConfig ? itemConfig.title : '';
|
return itemConfig ? itemConfig.title : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getItemTitleFontSize(item: FormItem): string {
|
||||||
|
let itemConfig = item.config;
|
||||||
|
return itemConfig && itemConfig.titleFontSize ? this.convertSize(itemConfig.titleFontSize, '11px') : '11px';
|
||||||
|
}
|
||||||
|
|
||||||
private getActionComponents(item: FormItem): FormItem[] {
|
private getActionComponents(item: FormItem): FormItem[] {
|
||||||
let items = this.items;
|
let items = this.items;
|
||||||
let itemConfig = item.config;
|
let itemConfig = item.config;
|
||||||
|
|||||||
@@ -37,6 +37,16 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.form-required {
|
||||||
|
color: red;
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-info {
|
||||||
|
width: 15px;
|
||||||
|
height: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
.form-component-actions {
|
.form-component-actions {
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ export class ModelViewContent extends ViewBase implements OnInit, IModelView {
|
|||||||
|
|
||||||
@memoize
|
@memoize
|
||||||
public get connection(): sqlops.connection.Connection {
|
public get connection(): sqlops.connection.Connection {
|
||||||
if (!this._commonService.connectionManagementService) {
|
if (!this._commonService.connectionManagementService || !this._commonService.connectionManagementService.connectionInfo) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ export class ModelViewContent extends ViewBase implements OnInit, IModelView {
|
|||||||
|
|
||||||
@memoize
|
@memoize
|
||||||
public get serverInfo(): sqlops.ServerInfo {
|
public get serverInfo(): sqlops.ServerInfo {
|
||||||
if (!this._commonService.connectionManagementService) {
|
if (!this._commonService.connectionManagementService || !this._commonService.connectionManagementService.connectionInfo) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -448,7 +448,8 @@ export class ListDatabasesActionItem extends EventEmitter implements IActionItem
|
|||||||
this._dropdown = new Dropdown(this.$databaseListDropdown.getHTMLElement(), contextViewProvider, themeService, {
|
this._dropdown = new Dropdown(this.$databaseListDropdown.getHTMLElement(), contextViewProvider, themeService, {
|
||||||
strictSelection: true,
|
strictSelection: true,
|
||||||
placeholder: selectString,
|
placeholder: selectString,
|
||||||
ariaLabel: selectString
|
ariaLabel: selectString,
|
||||||
|
actionLabel: nls.localize('toggleDatabaseNameDropdown', 'Select Database Toggle Dropdown')
|
||||||
});
|
});
|
||||||
this._dropdown.onValueChange(s => this.databaseSelected(s));
|
this._dropdown.onValueChange(s => this.databaseSelected(s));
|
||||||
|
|
||||||
|
|||||||
@@ -13,13 +13,14 @@ import { ChartsModule } from 'ng2-charts/ng2-charts';
|
|||||||
|
|
||||||
const BrowserAnimationsModule = (<any>require.__$__nodeRequire('@angular/platform-browser/animations')).BrowserAnimationsModule;
|
const BrowserAnimationsModule = (<any>require.__$__nodeRequire('@angular/platform-browser/animations')).BrowserAnimationsModule;
|
||||||
|
|
||||||
import { IBootstrapParams } from 'sql/services/bootstrap/bootstrapService';
|
import { IBootstrapParams, ISelector, providerIterator } from 'sql/services/bootstrap/bootstrapService';
|
||||||
import { Extensions, IInsightRegistry } from 'sql/platform/dashboard/common/insightRegistry';
|
import { Extensions, IInsightRegistry } from 'sql/platform/dashboard/common/insightRegistry';
|
||||||
|
|
||||||
import { Registry } from 'vs/platform/registry/common/platform';
|
import { Registry } from 'vs/platform/registry/common/platform';
|
||||||
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
|
||||||
|
|
||||||
import { QueryOutputComponent, QUERY_OUTPUT_SELECTOR } from 'sql/parts/query/views/queryOutput.component';
|
import { QueryOutputComponent } from 'sql/parts/query/views/queryOutput.component';
|
||||||
import { QueryPlanComponent, } from 'sql/parts/queryPlan/queryPlan.component';
|
import { QueryPlanComponent, } from 'sql/parts/queryPlan/queryPlan.component';
|
||||||
import { QueryComponent } from 'sql/parts/grid/views/query/query.component';
|
import { QueryComponent } from 'sql/parts/grid/views/query/query.component';
|
||||||
import { TopOperationsComponent } from 'sql/parts/queryPlan/topOperations.component';
|
import { TopOperationsComponent } from 'sql/parts/queryPlan/topOperations.component';
|
||||||
@@ -41,7 +42,7 @@ let baseComponents = [QueryComponent, ComponentHostDirective, QueryOutputCompone
|
|||||||
/* Insights */
|
/* Insights */
|
||||||
let insightComponents = Registry.as<IInsightRegistry>(Extensions.InsightContribution).getAllCtors();
|
let insightComponents = Registry.as<IInsightRegistry>(Extensions.InsightContribution).getAllCtors();
|
||||||
|
|
||||||
export const QueryOutputModule = (params: IBootstrapParams, selector: string): Type<any> => {
|
export const QueryOutputModule = (params: IBootstrapParams, selector: string, instantiationService: IInstantiationService): Type<any> => {
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -67,19 +68,22 @@ export const QueryOutputModule = (params: IBootstrapParams, selector: string): T
|
|||||||
...insightComponents
|
...insightComponents
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: IBootstrapParams, useValue: params }
|
{ provide: IBootstrapParams, useValue: params },
|
||||||
|
{ provide: ISelector, useValue: selector },
|
||||||
|
...providerIterator(instantiationService)
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
class ModuleClass {
|
class ModuleClass {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(forwardRef(() => ComponentFactoryResolver)) private _resolver: ComponentFactoryResolver
|
@Inject(forwardRef(() => ComponentFactoryResolver)) private _resolver: ComponentFactoryResolver,
|
||||||
|
@Inject(ISelector) private selector: string
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngDoBootstrap(appRef: ApplicationRef) {
|
ngDoBootstrap(appRef: ApplicationRef) {
|
||||||
const factory = this._resolver.resolveComponentFactory(QueryOutputComponent);
|
const factory = this._resolver.resolveComponentFactory(QueryOutputComponent);
|
||||||
(<any>factory).factory.selector = selector;
|
(<any>factory).factory.selector = this.selector;
|
||||||
appRef.bootstrap(factory);
|
appRef.bootstrap(factory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,14 @@
|
|||||||
import { NgModule, Inject, forwardRef, ApplicationRef, ComponentFactoryResolver, Type } from '@angular/core';
|
import { NgModule, Inject, forwardRef, ApplicationRef, ComponentFactoryResolver, Type } from '@angular/core';
|
||||||
import { APP_BASE_HREF, CommonModule } from '@angular/common';
|
import { APP_BASE_HREF, CommonModule } from '@angular/common';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { IBootstrapParams } from 'sql/services/bootstrap/bootstrapService';
|
|
||||||
import { QueryPlanComponent, QUERYPLAN_SELECTOR } from 'sql/parts/queryPlan/queryPlan.component';
|
import { IBootstrapParams, ISelector, providerIterator } from 'sql/services/bootstrap/bootstrapService';
|
||||||
|
import { QueryPlanComponent } from 'sql/parts/queryPlan/queryPlan.component';
|
||||||
|
|
||||||
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
|
||||||
// Connection Dashboard main angular module
|
// Connection Dashboard main angular module
|
||||||
export const QueryPlanModule = (params: IBootstrapParams, selector: string): Type<any> => {
|
export const QueryPlanModule = (params: IBootstrapParams, selector: string, instantiationService: IInstantiationService): Type<any> => {
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@@ -23,19 +26,22 @@ export const QueryPlanModule = (params: IBootstrapParams, selector: string): Typ
|
|||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: APP_BASE_HREF, useValue: '/' },
|
{ provide: APP_BASE_HREF, useValue: '/' },
|
||||||
{ provide: IBootstrapParams, useValue: params }
|
{ provide: IBootstrapParams, useValue: params },
|
||||||
|
{ provide: ISelector, useValue: selector },
|
||||||
|
...providerIterator(instantiationService)
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
class ModuleClass {
|
class ModuleClass {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(forwardRef(() => ComponentFactoryResolver)) private _resolver: ComponentFactoryResolver
|
@Inject(forwardRef(() => ComponentFactoryResolver)) private _resolver: ComponentFactoryResolver,
|
||||||
|
@Inject(ISelector) private selector: string
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngDoBootstrap(appRef: ApplicationRef) {
|
ngDoBootstrap(appRef: ApplicationRef) {
|
||||||
const factory = this._resolver.resolveComponentFactory(QueryPlanComponent);
|
const factory = this._resolver.resolveComponentFactory(QueryPlanComponent);
|
||||||
(<any>factory).factory.selector = selector;
|
(<any>factory).factory.selector = this.selector;
|
||||||
appRef.bootstrap(factory);
|
appRef.bootstrap(factory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,11 @@ import { APP_BASE_HREF, CommonModule } from '@angular/common';
|
|||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
|
||||||
import { TaskDialogComponent, TASKDIALOG_SELECTOR } from 'sql/parts/tasks/dialog/taskDialog.component';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
|
||||||
|
import { TaskDialogComponent } from 'sql/parts/tasks/dialog/taskDialog.component';
|
||||||
import { CreateDatabaseComponent } from 'sql/parts/admin/database/create/createDatabase.component';
|
import { CreateDatabaseComponent } from 'sql/parts/admin/database/create/createDatabase.component';
|
||||||
import { IBootstrapParams } from 'sql/services/bootstrap/bootstrapService';
|
import { IBootstrapParams, ISelector, providerIterator } from 'sql/services/bootstrap/bootstrapService';
|
||||||
|
|
||||||
// Setup routes for various child components
|
// Setup routes for various child components
|
||||||
const appRoutes: Routes = [
|
const appRoutes: Routes = [
|
||||||
@@ -27,7 +29,7 @@ const appRoutes: Routes = [
|
|||||||
{ path: '**', component: CreateDatabaseComponent }
|
{ path: '**', component: CreateDatabaseComponent }
|
||||||
];
|
];
|
||||||
|
|
||||||
export const TaskDialogModule = (params: IBootstrapParams, selector: string): Type<any> => {
|
export const TaskDialogModule = (params: IBootstrapParams, selector: string, instantiationService: IInstantiationService): Type<any> => {
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
TaskDialogComponent,
|
TaskDialogComponent,
|
||||||
@@ -42,19 +44,22 @@ export const TaskDialogModule = (params: IBootstrapParams, selector: string): Ty
|
|||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: APP_BASE_HREF, useValue: '/' },
|
{ provide: APP_BASE_HREF, useValue: '/' },
|
||||||
{ provide: IBootstrapParams, useValue: params }
|
{ provide: IBootstrapParams, useValue: params },
|
||||||
|
{ provide: ISelector, useValue: selector },
|
||||||
|
...providerIterator(instantiationService)
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
class ModuleClass {
|
class ModuleClass {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(forwardRef(() => ComponentFactoryResolver)) private _resolver: ComponentFactoryResolver
|
@Inject(forwardRef(() => ComponentFactoryResolver)) private _resolver: ComponentFactoryResolver,
|
||||||
|
@Inject(ISelector) private selector: string
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngDoBootstrap(appRef: ApplicationRef) {
|
ngDoBootstrap(appRef: ApplicationRef) {
|
||||||
const factory = this._resolver.resolveComponentFactory(TaskDialogComponent);
|
const factory = this._resolver.resolveComponentFactory(TaskDialogComponent);
|
||||||
(<any>factory).factory.selector = selector;
|
(<any>factory).factory.selector = this.selector;
|
||||||
appRef.bootstrap(factory);
|
appRef.bootstrap(factory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ import { Dialog, Wizard, DialogTab } from 'sql/platform/dialog/dialogTypes';
|
|||||||
import { IModalOptions } from 'sql/base/browser/ui/modal/modal';
|
import { IModalOptions } from 'sql/base/browser/ui/modal/modal';
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
|
||||||
const defaultOptions: IModalOptions = { hasBackButton: false, isWide: false };
|
const defaultOptions: IModalOptions = { hasBackButton: false, isWide: false, hasErrors: true };
|
||||||
const defaultWizardOptions: IModalOptions = { hasBackButton: false, isWide: true };
|
const defaultWizardOptions: IModalOptions = { hasBackButton: false, isWide: true, hasErrors: true };
|
||||||
|
|
||||||
export class CustomDialogService {
|
export class CustomDialogService {
|
||||||
private _dialogModals = new Map<Dialog, DialogModal>();
|
private _dialogModals = new Map<Dialog, DialogModal>();
|
||||||
|
|||||||
@@ -11,22 +11,25 @@ import { forwardRef, NgModule, ComponentFactoryResolver, Inject, ApplicationRef
|
|||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { CommonModule, APP_BASE_HREF } from '@angular/common';
|
import { CommonModule, APP_BASE_HREF } from '@angular/common';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
|
||||||
import { DialogContainer } from 'sql/platform/dialog/dialogContainer.component';
|
import { DialogContainer } from 'sql/platform/dialog/dialogContainer.component';
|
||||||
import { Extensions, IComponentRegistry } from 'sql/platform/dashboard/common/modelComponentRegistry';
|
import { Extensions, IComponentRegistry } from 'sql/platform/dashboard/common/modelComponentRegistry';
|
||||||
import { ModelViewContent } from 'sql/parts/modelComponents/modelViewContent.component';
|
import { ModelViewContent } from 'sql/parts/modelComponents/modelViewContent.component';
|
||||||
import { ModelComponentWrapper } from 'sql/parts/modelComponents/modelComponentWrapper.component';
|
import { ModelComponentWrapper } from 'sql/parts/modelComponents/modelComponentWrapper.component';
|
||||||
import { ComponentHostDirective } from 'sql/parts/dashboard/common/componentHost.directive';
|
import { ComponentHostDirective } from 'sql/parts/dashboard/common/componentHost.directive';
|
||||||
import { IBootstrapParams } from 'sql/services/bootstrap/bootstrapService';
|
import { IBootstrapParams, ISelector, providerIterator } from 'sql/services/bootstrap/bootstrapService';
|
||||||
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
|
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
|
||||||
import { Registry } from 'vs/platform/registry/common/platform';
|
|
||||||
import { Checkbox } from 'sql/base/browser/ui/checkbox/checkbox.component';
|
import { Checkbox } from 'sql/base/browser/ui/checkbox/checkbox.component';
|
||||||
import { SelectBox } from 'sql/base/browser/ui/selectBox/selectBox.component';
|
import { SelectBox } from 'sql/base/browser/ui/selectBox/selectBox.component';
|
||||||
import { InputBox } from 'sql/base/browser/ui/inputBox/inputBox.component';
|
import { InputBox } from 'sql/base/browser/ui/inputBox/inputBox.component';
|
||||||
|
|
||||||
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
import { Registry } from 'vs/platform/registry/common/platform';
|
||||||
|
|
||||||
/* Model-backed components */
|
/* Model-backed components */
|
||||||
let extensionComponents = Registry.as<IComponentRegistry>(Extensions.ComponentContribution).getAllCtors();
|
let extensionComponents = Registry.as<IComponentRegistry>(Extensions.ComponentContribution).getAllCtors();
|
||||||
|
|
||||||
export const DialogModule = (params, selector: string): any => {
|
export const DialogModule = (params, selector: string, instantiationService: IInstantiationService): any => {
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
Checkbox,
|
Checkbox,
|
||||||
@@ -47,20 +50,22 @@ export const DialogModule = (params, selector: string): any => {
|
|||||||
providers: [
|
providers: [
|
||||||
{ provide: APP_BASE_HREF, useValue: '/' },
|
{ provide: APP_BASE_HREF, useValue: '/' },
|
||||||
CommonServiceInterface,
|
CommonServiceInterface,
|
||||||
{ provide: IBootstrapParams, useValue: params }
|
{ provide: IBootstrapParams, useValue: params },
|
||||||
|
{ provide: ISelector, useValue: selector },
|
||||||
|
...providerIterator(instantiationService)
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
class ModuleClass {
|
class ModuleClass {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(forwardRef(() => ComponentFactoryResolver)) private _resolver: ComponentFactoryResolver,
|
@Inject(forwardRef(() => ComponentFactoryResolver)) private _resolver: ComponentFactoryResolver,
|
||||||
@Inject(forwardRef(() => CommonServiceInterface)) bootstrap: CommonServiceInterface,
|
@Inject(ISelector) private selector: string
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngDoBootstrap(appRef: ApplicationRef) {
|
ngDoBootstrap(appRef: ApplicationRef) {
|
||||||
const factoryWrapper: any = this._resolver.resolveComponentFactory(DialogContainer);
|
const factoryWrapper: any = this._resolver.resolveComponentFactory(DialogContainer);
|
||||||
factoryWrapper.factory.selector = selector;
|
factoryWrapper.factory.selector = this.selector;
|
||||||
appRef.bootstrap(factoryWrapper);
|
appRef.bootstrap(factoryWrapper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import { localize } from 'vs/nls';
|
|||||||
import { Emitter } from 'vs/base/common/event';
|
import { Emitter } from 'vs/base/common/event';
|
||||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
import { DialogMessage, MessageLevel } from '../../workbench/api/common/sqlExtHostTypes';
|
||||||
|
|
||||||
export class DialogModal extends Modal {
|
export class DialogModal extends Modal {
|
||||||
private _dialogPane: DialogPane;
|
private _dialogPane: DialogPane;
|
||||||
@@ -52,7 +53,7 @@ export class DialogModal extends Modal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
super.render();
|
super.render(true);
|
||||||
attachModalDialogStyler(this, this._themeService);
|
attachModalDialogStyler(this, this._themeService);
|
||||||
|
|
||||||
if (this.backButton) {
|
if (this.backButton) {
|
||||||
@@ -67,29 +68,43 @@ export class DialogModal extends Modal {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this._doneButton = this.addDialogButton(this._dialog.okButton, () => this.done(), false);
|
this._doneButton = this.addDialogButton(this._dialog.okButton, () => this.done(), false, true);
|
||||||
this._dialog.okButton.registerClickEvent(this._onDone.event);
|
this._dialog.okButton.registerClickEvent(this._onDone.event);
|
||||||
|
this._dialog.onValidityChanged(valid => {
|
||||||
|
this._doneButton.enabled = valid && this._dialog.okButton.enabled;
|
||||||
|
});
|
||||||
this._cancelButton = this.addDialogButton(this._dialog.cancelButton, () => this.cancel(), false);
|
this._cancelButton = this.addDialogButton(this._dialog.cancelButton, () => this.cancel(), false);
|
||||||
this._dialog.cancelButton.registerClickEvent(this._onCancel.event);
|
this._dialog.cancelButton.registerClickEvent(this._onCancel.event);
|
||||||
|
|
||||||
|
let messageChangeHandler = (message: DialogMessage) => {
|
||||||
|
if (message && message.text) {
|
||||||
|
this.setError(message.text, message.level);
|
||||||
|
} else {
|
||||||
|
this.setError('');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
messageChangeHandler(this._dialog.message);
|
||||||
|
this._dialog.onMessageChange(message => messageChangeHandler(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
private addDialogButton(button: DialogButton, onSelect: () => void = () => undefined, registerClickEvent: boolean = true): Button {
|
private addDialogButton(button: DialogButton, onSelect: () => void = () => undefined, registerClickEvent: boolean = true, requireDialogValid: boolean = false): Button {
|
||||||
let buttonElement = this.addFooterButton(button.label, onSelect);
|
let buttonElement = this.addFooterButton(button.label, onSelect);
|
||||||
buttonElement.enabled = button.enabled;
|
buttonElement.enabled = button.enabled;
|
||||||
if (registerClickEvent) {
|
if (registerClickEvent) {
|
||||||
button.registerClickEvent(buttonElement.onDidClick);
|
button.registerClickEvent(buttonElement.onDidClick);
|
||||||
}
|
}
|
||||||
button.onUpdate(() => {
|
button.onUpdate(() => {
|
||||||
this.updateButtonElement(buttonElement, button);
|
this.updateButtonElement(buttonElement, button, requireDialogValid);
|
||||||
});
|
});
|
||||||
attachButtonStyler(buttonElement, this._themeService);
|
attachButtonStyler(buttonElement, this._themeService);
|
||||||
this.updateButtonElement(buttonElement, button);
|
this.updateButtonElement(buttonElement, button, requireDialogValid);
|
||||||
return buttonElement;
|
return buttonElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateButtonElement(buttonElement: Button, dialogButton: DialogButton) {
|
private updateButtonElement(buttonElement: Button, dialogButton: DialogButton, requireDialogValid: boolean = false) {
|
||||||
buttonElement.label = dialogButton.label;
|
buttonElement.label = dialogButton.label;
|
||||||
buttonElement.enabled = dialogButton.enabled;
|
buttonElement.enabled = requireDialogValid ? dialogButton.enabled && this._dialog.valid : dialogButton.enabled;
|
||||||
dialogButton.hidden ? buttonElement.element.classList.add('dialogModal-hidden') : buttonElement.element.classList.remove('dialogModal-hidden');
|
dialogButton.hidden ? buttonElement.element.classList.add('dialogModal-hidden') : buttonElement.element.classList.remove('dialogModal-hidden');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,11 +123,13 @@ export class DialogModal extends Modal {
|
|||||||
this.show();
|
this.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
public done(): void {
|
public async done(): Promise<void> {
|
||||||
if (this._dialog.okButton.enabled) {
|
if (this._dialog.okButton.enabled) {
|
||||||
this._onDone.fire();
|
if (await this._dialog.validateClose()) {
|
||||||
this.dispose();
|
this._onDone.fire();
|
||||||
this.hide();
|
this.dispose();
|
||||||
|
this.hide();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { TabbedPanel, IPanelTab, IPanelView } from 'sql/base/browser/ui/panel/pa
|
|||||||
import { bootstrapAngular } from 'sql/services/bootstrap/bootstrapService';
|
import { bootstrapAngular } from 'sql/services/bootstrap/bootstrapService';
|
||||||
import { DialogModule } from 'sql/platform/dialog/dialog.module';
|
import { DialogModule } from 'sql/platform/dialog/dialog.module';
|
||||||
import { DialogComponentParams } from 'sql/platform/dialog/dialogContainer.component';
|
import { DialogComponentParams } from 'sql/platform/dialog/dialogContainer.component';
|
||||||
|
import { DialogMessage } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||||
|
|
||||||
import * as DOM from 'vs/base/browser/dom';
|
import * as DOM from 'vs/base/browser/dom';
|
||||||
import { Builder } from 'vs/base/browser/builder';
|
import { Builder } from 'vs/base/browser/builder';
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
import * as sqlops from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
import { localize } from 'vs/nls';
|
import { localize } from 'vs/nls';
|
||||||
import { Event, Emitter } from 'vs/base/common/event';
|
import { Event, Emitter } from 'vs/base/common/event';
|
||||||
|
import { DialogMessage } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||||
|
|
||||||
export class ModelViewPane {
|
export class ModelViewPane {
|
||||||
private _valid: boolean = true;
|
private _valid: boolean = true;
|
||||||
@@ -45,6 +46,10 @@ export class Dialog extends ModelViewPane {
|
|||||||
public okButton: DialogButton = new DialogButton(Dialog.DONE_BUTTON_LABEL, true);
|
public okButton: DialogButton = new DialogButton(Dialog.DONE_BUTTON_LABEL, true);
|
||||||
public cancelButton: DialogButton = new DialogButton(Dialog.CANCEL_BUTTON_LABEL, true);
|
public cancelButton: DialogButton = new DialogButton(Dialog.CANCEL_BUTTON_LABEL, true);
|
||||||
public customButtons: DialogButton[];
|
public customButtons: DialogButton[];
|
||||||
|
private _onMessageChange = new Emitter<DialogMessage>();
|
||||||
|
public readonly onMessageChange = this._onMessageChange.event;
|
||||||
|
private _message: DialogMessage;
|
||||||
|
private _closeValidator: () => boolean | Thenable<boolean>;
|
||||||
|
|
||||||
constructor(public title: string, content?: string | DialogTab[]) {
|
constructor(public title: string, content?: string | DialogTab[]) {
|
||||||
super();
|
super();
|
||||||
@@ -52,6 +57,29 @@ export class Dialog extends ModelViewPane {
|
|||||||
this.content = content;
|
this.content = content;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get message(): DialogMessage {
|
||||||
|
return this._message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public set message(value: DialogMessage) {
|
||||||
|
if (this._message && !value || !this._message && value || this._message && value && (this._message.level !== value.level || this._message.text !== value.text)) {
|
||||||
|
this._message = value;
|
||||||
|
this._onMessageChange.fire(this._message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public registerCloseValidator(validator: () => boolean | Thenable<boolean>): void {
|
||||||
|
this._closeValidator = validator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public validateClose(): Thenable<boolean> {
|
||||||
|
if (this._closeValidator) {
|
||||||
|
return Promise.resolve(this._closeValidator());
|
||||||
|
} else {
|
||||||
|
return Promise.resolve(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DialogButton implements sqlops.window.modelviewdialog.Button {
|
export class DialogButton implements sqlops.window.modelviewdialog.Button {
|
||||||
@@ -140,6 +168,9 @@ export class Wizard {
|
|||||||
private _pageRemovedEmitter = new Emitter<WizardPage>();
|
private _pageRemovedEmitter = new Emitter<WizardPage>();
|
||||||
public readonly onPageRemoved = this._pageRemovedEmitter.event;
|
public readonly onPageRemoved = this._pageRemovedEmitter.event;
|
||||||
private _navigationValidator: (pageChangeInfo: sqlops.window.modelviewdialog.WizardPageChangeInfo) => boolean | Thenable<boolean>;
|
private _navigationValidator: (pageChangeInfo: sqlops.window.modelviewdialog.WizardPageChangeInfo) => boolean | Thenable<boolean>;
|
||||||
|
private _onMessageChange = new Emitter<DialogMessage>();
|
||||||
|
public readonly onMessageChange = this._onMessageChange.event;
|
||||||
|
private _message: DialogMessage;
|
||||||
|
|
||||||
constructor(public title: string) { }
|
constructor(public title: string) { }
|
||||||
|
|
||||||
@@ -207,4 +238,15 @@ export class Wizard {
|
|||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get message(): DialogMessage {
|
||||||
|
return this._message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public set message(value: DialogMessage) {
|
||||||
|
if (this._message && !value || !this._message && value || this._message && value && (this._message.level !== value.level || this._message.text !== value.text)) {
|
||||||
|
this._message = value;
|
||||||
|
this._onMessageChange.fire(this._message);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
.dialogModal-body {
|
.dialogModal-body {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-width: 500px;
|
min-width: 500px;
|
||||||
@@ -29,4 +29,4 @@
|
|||||||
|
|
||||||
.footer-button.dialogModal-hidden {
|
.footer-button.dialogModal-hidden {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import { localize } from 'vs/nls';
|
|||||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||||
import { Emitter } from 'vs/base/common/event';
|
import { Emitter } from 'vs/base/common/event';
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
import { DialogMessage, MessageLevel } from '../../workbench/api/common/sqlExtHostTypes';
|
||||||
|
|
||||||
export class WizardModal extends Modal {
|
export class WizardModal extends Modal {
|
||||||
private _dialogPanes = new Map<WizardPage, DialogPane>();
|
private _dialogPanes = new Map<WizardPage, DialogPane>();
|
||||||
@@ -58,7 +59,7 @@ export class WizardModal extends Modal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
super.render();
|
super.render(true);
|
||||||
attachModalDialogStyler(this, this._themeService);
|
attachModalDialogStyler(this, this._themeService);
|
||||||
|
|
||||||
if (this.backButton) {
|
if (this.backButton) {
|
||||||
@@ -66,32 +67,59 @@ export class WizardModal extends Modal {
|
|||||||
attachButtonStyler(this.backButton, this._themeService, { buttonBackground: SIDE_BAR_BACKGROUND, buttonHoverBackground: SIDE_BAR_BACKGROUND });
|
attachButtonStyler(this.backButton, this._themeService, { buttonBackground: SIDE_BAR_BACKGROUND, buttonHoverBackground: SIDE_BAR_BACKGROUND });
|
||||||
}
|
}
|
||||||
|
|
||||||
this._previousButton = this.addDialogButton(this._wizard.backButton, () => this.showPage(this.getCurrentPage() - 1));
|
if (this._wizard.customButtons) {
|
||||||
this._nextButton = this.addDialogButton(this._wizard.nextButton, () => this.showPage(this.getCurrentPage() + 1));
|
this._wizard.customButtons.forEach(button => {
|
||||||
|
let buttonElement = this.addDialogButton(button);
|
||||||
|
this.updateButtonElement(buttonElement, button);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this._previousButton = this.addDialogButton(this._wizard.backButton, () => this.showPage(this._wizard.currentPage - 1));
|
||||||
|
this._nextButton = this.addDialogButton(this._wizard.nextButton, () => this.showPage(this._wizard.currentPage + 1), true, true);
|
||||||
this._generateScriptButton = this.addDialogButton(this._wizard.generateScriptButton, () => undefined);
|
this._generateScriptButton = this.addDialogButton(this._wizard.generateScriptButton, () => undefined);
|
||||||
this._doneButton = this.addDialogButton(this._wizard.doneButton, () => this.done(), false);
|
this._doneButton = this.addDialogButton(this._wizard.doneButton, () => this.done(), false, true);
|
||||||
this._wizard.doneButton.registerClickEvent(this._onDone.event);
|
this._wizard.doneButton.registerClickEvent(this._onDone.event);
|
||||||
this._cancelButton = this.addDialogButton(this._wizard.cancelButton, () => this.cancel(), false);
|
this._cancelButton = this.addDialogButton(this._wizard.cancelButton, () => this.cancel(), false);
|
||||||
this._wizard.cancelButton.registerClickEvent(this._onCancel.event);
|
this._wizard.cancelButton.registerClickEvent(this._onCancel.event);
|
||||||
|
|
||||||
|
let messageChangeHandler = (message: DialogMessage) => {
|
||||||
|
if (message && message.text) {
|
||||||
|
this.setError(message.text, message.level);
|
||||||
|
} else {
|
||||||
|
this.setError('');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
messageChangeHandler(this._wizard.message);
|
||||||
|
this._wizard.onMessageChange(message => messageChangeHandler(message));
|
||||||
|
|
||||||
|
this._wizard.pages.forEach((page, index) => {
|
||||||
|
page.onValidityChanged(valid => {
|
||||||
|
if (index === this._wizard.currentPage) {
|
||||||
|
this._nextButton.enabled = this._wizard.nextButton.enabled && page.valid;
|
||||||
|
this._doneButton.enabled = this._wizard.doneButton.enabled && page.valid;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private addDialogButton(button: DialogButton, onSelect: () => void = () => undefined, registerClickEvent: boolean = true): Button {
|
private addDialogButton(button: DialogButton, onSelect: () => void = () => undefined, registerClickEvent: boolean = true, requirePageValid: boolean = false): Button {
|
||||||
let buttonElement = this.addFooterButton(button.label, onSelect);
|
let buttonElement = this.addFooterButton(button.label, onSelect);
|
||||||
buttonElement.enabled = button.enabled;
|
buttonElement.enabled = button.enabled;
|
||||||
if (registerClickEvent) {
|
if (registerClickEvent) {
|
||||||
button.registerClickEvent(buttonElement.onDidClick);
|
button.registerClickEvent(buttonElement.onDidClick);
|
||||||
}
|
}
|
||||||
button.onUpdate(() => {
|
button.onUpdate(() => {
|
||||||
this.updateButtonElement(buttonElement, button);
|
this.updateButtonElement(buttonElement, button, requirePageValid);
|
||||||
});
|
});
|
||||||
attachButtonStyler(buttonElement, this._themeService);
|
attachButtonStyler(buttonElement, this._themeService);
|
||||||
this.updateButtonElement(buttonElement, button);
|
this.updateButtonElement(buttonElement, button, requirePageValid);
|
||||||
return buttonElement;
|
return buttonElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateButtonElement(buttonElement: Button, dialogButton: DialogButton) {
|
private updateButtonElement(buttonElement: Button, dialogButton: DialogButton, requirePageValid: boolean = false) {
|
||||||
buttonElement.label = dialogButton.label;
|
buttonElement.label = dialogButton.label;
|
||||||
buttonElement.enabled = dialogButton.enabled;
|
buttonElement.enabled = requirePageValid ? dialogButton.enabled && this._wizard.pages[this._wizard.currentPage].valid : dialogButton.enabled;
|
||||||
dialogButton.hidden ? buttonElement.element.classList.add('dialogModal-hidden') : buttonElement.element.classList.remove('dialogModal-hidden');
|
dialogButton.hidden ? buttonElement.element.classList.add('dialogModal-hidden') : buttonElement.element.classList.remove('dialogModal-hidden');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,18 +128,17 @@ export class WizardModal extends Modal {
|
|||||||
this._body = bodyBuilder.getHTMLElement();
|
this._body = bodyBuilder.getHTMLElement();
|
||||||
});
|
});
|
||||||
|
|
||||||
let builder = new Builder(this._body);
|
|
||||||
this._wizard.pages.forEach(page => {
|
this._wizard.pages.forEach(page => {
|
||||||
this.registerPage(page);
|
this.registerPage(page);
|
||||||
});
|
});
|
||||||
this._wizard.onPageAdded(page => {
|
this._wizard.onPageAdded(page => {
|
||||||
this.registerPage(page);
|
this.registerPage(page);
|
||||||
this.showPage(this.getCurrentPage(), false);
|
this.showPage(this._wizard.currentPage, false);
|
||||||
});
|
});
|
||||||
this._wizard.onPageRemoved(page => {
|
this._wizard.onPageRemoved(page => {
|
||||||
let dialogPane = this._dialogPanes.get(page);
|
let dialogPane = this._dialogPanes.get(page);
|
||||||
this._dialogPanes.delete(page);
|
this._dialogPanes.delete(page);
|
||||||
this.showPage(this.getCurrentPage(), false);
|
this.showPage(this._wizard.currentPage, false);
|
||||||
dialogPane.dispose();
|
dialogPane.dispose();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -141,6 +168,9 @@ export class WizardModal extends Modal {
|
|||||||
});
|
});
|
||||||
this.setButtonsForPage(index);
|
this.setButtonsForPage(index);
|
||||||
this._wizard.setCurrentPage(index);
|
this._wizard.setCurrentPage(index);
|
||||||
|
let currentPageValid = this._wizard.pages[this._wizard.currentPage].valid;
|
||||||
|
this._nextButton.enabled = this._wizard.nextButton.enabled && currentPageValid;
|
||||||
|
this._doneButton.enabled = this._wizard.doneButton.enabled && currentPageValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
private setButtonsForPage(index: number) {
|
private setButtonsForPage(index: number) {
|
||||||
@@ -161,10 +191,6 @@ export class WizardModal extends Modal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getCurrentPage(): number {
|
|
||||||
return this._wizard.currentPage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public open(): void {
|
public open(): void {
|
||||||
this.showPage(0, false);
|
this.showPage(0, false);
|
||||||
this.show();
|
this.show();
|
||||||
|
|||||||
@@ -3,20 +3,31 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { NgModuleRef, enableProdMode, InjectionToken, ReflectiveInjector, Type, PlatformRef, Provider } from '@angular/core';
|
import { NgModuleRef, enableProdMode, InjectionToken, Type, PlatformRef, Provider, Injector, Optional, Inject, ComponentFactoryResolver } from '@angular/core';
|
||||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
|
||||||
import { IEditorInput } from 'vs/platform/editor/common/editor';
|
import { IEditorInput } from 'vs/platform/editor/common/editor';
|
||||||
import { IInstantiationService, _util } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService, _util } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
|
||||||
const selectorCounter = new Map<string, number>();
|
const selectorCounter = new Map<string, number>();
|
||||||
const serviceMap = new Map<string, IInstantiationService>();
|
|
||||||
|
|
||||||
export const IBootstrapParams = new InjectionToken('bootstrap_params');
|
export function providerIterator(service: IInstantiationService): Provider[] {
|
||||||
|
return Array.from(_util.serviceIds.values()).map(v => {
|
||||||
|
return {
|
||||||
|
provide: v, useFactory: () => {
|
||||||
|
return (<any>service)._getOrCreateServiceInstance(v);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ISelector = new InjectionToken<string>('selector');
|
||||||
|
|
||||||
|
export const IBootstrapParams = new InjectionToken<IBootstrapParams>('bootstrap_params');
|
||||||
export interface IBootstrapParams {
|
export interface IBootstrapParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IModuleFactory<T> = (params: IBootstrapParams, selector: string) => Type<T>;
|
export type IModuleFactory<T> = (params: IBootstrapParams, selector: string, service: IInstantiationService) => Type<T>;
|
||||||
|
|
||||||
function createUniqueSelector(selector: string): string {
|
function createUniqueSelector(selector: string): string {
|
||||||
let num: number;
|
let num: number;
|
||||||
@@ -37,31 +48,13 @@ export function bootstrapAngular<T>(service: IInstantiationService, moduleType:
|
|||||||
let selector = document.createElement(uniqueSelectorString);
|
let selector = document.createElement(uniqueSelectorString);
|
||||||
container.appendChild(selector);
|
container.appendChild(selector);
|
||||||
|
|
||||||
serviceMap.set(uniqueSelectorString, service);
|
|
||||||
|
|
||||||
if (!platform) {
|
if (!platform) {
|
||||||
// Perform the bootsrap
|
platform = platformBrowserDynamic();
|
||||||
|
|
||||||
const providers: Provider = [];
|
|
||||||
|
|
||||||
_util.serviceIds.forEach(id => {
|
|
||||||
providers.push({
|
|
||||||
provide: id, useFactory: () => {
|
|
||||||
return (<any>serviceMap.get(uniqueSelectorString))._getOrCreateServiceInstance(id);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
platform = platformBrowserDynamic(providers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
platform.bootstrapModule(moduleType(params, uniqueSelectorString)).then(moduleRef => {
|
platform.bootstrapModule(moduleType(params, uniqueSelectorString, service)).then(moduleRef => {
|
||||||
if (input) {
|
if (input) {
|
||||||
input.onDispose(() => {
|
input.onDispose(() => {
|
||||||
serviceMap.delete(uniqueSelectorString);
|
|
||||||
moduleRef.onDestroy(() => {
|
|
||||||
serviceMap.delete(uniqueSelectorString);
|
|
||||||
});
|
|
||||||
moduleRef.destroy();
|
moduleRef.destroy();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,7 +95,6 @@ export class SingleQueryManagementService {
|
|||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CommonServiceInterface extends AngularDisposable {
|
export class CommonServiceInterface extends AngularDisposable {
|
||||||
protected _uniqueSelector: string;
|
|
||||||
protected _uri: string;
|
protected _uri: string;
|
||||||
|
|
||||||
/* Special Services */
|
/* Special Services */
|
||||||
@@ -115,6 +114,12 @@ export class CommonServiceInterface extends AngularDisposable {
|
|||||||
@Inject(IQueryManagementService) protected _queryManagementService: IQueryManagementService
|
@Inject(IQueryManagementService) protected _queryManagementService: IQueryManagementService
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
// during testing there may not be params
|
||||||
|
if (this._params) {
|
||||||
|
this.scopedContextKeyService = this._params.scopedContextService;
|
||||||
|
this._connectionContextKey = this._params.connectionContextKey;
|
||||||
|
this.uri = this._params.ownerUri;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public get metadataService(): SingleConnectionMetadataService {
|
public get metadataService(): SingleConnectionMetadataService {
|
||||||
@@ -133,20 +138,6 @@ export class CommonServiceInterface extends AngularDisposable {
|
|||||||
return this._singleQueryManagementService;
|
return this._singleQueryManagementService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the selector for this instance, should only be set once
|
|
||||||
*/
|
|
||||||
public set selector(selector: string) {
|
|
||||||
this._uniqueSelector = selector;
|
|
||||||
this._getbootstrapParams();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected _getbootstrapParams(): void {
|
|
||||||
this.scopedContextKeyService = this._params.scopedContextService;
|
|
||||||
this._connectionContextKey = this._params.connectionContextKey;
|
|
||||||
this.uri = this._params.ownerUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected setUri(uri: string) {
|
protected setUri(uri: string) {
|
||||||
this._uri = uri;
|
this._uri = uri;
|
||||||
this._singleMetadataService = new SingleConnectionMetadataService(this._metadataService, this._uri);
|
this._singleMetadataService = new SingleConnectionMetadataService(this._metadataService, this._uri);
|
||||||
|
|||||||
67
src/sql/sqlops.proposed.d.ts
vendored
67
src/sql/sqlops.proposed.d.ts
vendored
@@ -239,11 +239,15 @@ declare module 'sqlops' {
|
|||||||
horizontal?: boolean;
|
horizontal?: boolean;
|
||||||
componentWidth?: number | string;
|
componentWidth?: number | string;
|
||||||
componentHeight?: number | string;
|
componentHeight?: number | string;
|
||||||
|
titleFontSize?: number | string;
|
||||||
|
required?: boolean;
|
||||||
|
info?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FormLayout {
|
export interface FormLayout {
|
||||||
width?: number | string;
|
width?: number | string;
|
||||||
height?: number | string;
|
height?: number | string;
|
||||||
|
padding?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GroupLayout {
|
export interface GroupLayout {
|
||||||
@@ -296,15 +300,22 @@ declare module 'sqlops' {
|
|||||||
Error = 3
|
Error = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum CardType {
|
||||||
|
VerticalButton = 'VerticalButton',
|
||||||
|
Details = 'Details'
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Properties representing the card component, can be used
|
* Properties representing the card component, can be used
|
||||||
* when using ModelBuilder to create the component
|
* when using ModelBuilder to create the component
|
||||||
*/
|
*/
|
||||||
export interface CardProperties {
|
export interface CardProperties extends ComponentWithIcon {
|
||||||
label: string;
|
label: string;
|
||||||
value?: string;
|
value?: string;
|
||||||
actions?: ActionDescriptor[];
|
actions?: ActionDescriptor[];
|
||||||
status?: StatusIndicator;
|
status?: StatusIndicator;
|
||||||
|
selected?: boolean;
|
||||||
|
cardType: CardType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type InputBoxInputType = 'color' | 'date' | 'datetime-local' | 'email' | 'month' | 'number' | 'password' | 'range' | 'search' | 'text' | 'time' | 'url' | 'week';
|
export type InputBoxInputType = 'color' | 'date' | 'datetime-local' | 'email' | 'month' | 'number' | 'password' | 'range' | 'search' | 'text' | 'time' | 'url' | 'week';
|
||||||
@@ -314,6 +325,12 @@ declare module 'sqlops' {
|
|||||||
width?: number | string;
|
width?: number | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ComponentWithIcon {
|
||||||
|
iconPath?: string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri };
|
||||||
|
iconHeight?: number | string;
|
||||||
|
iconWidth?: number | string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface InputBoxProperties extends ComponentProperties {
|
export interface InputBoxProperties extends ComponentProperties {
|
||||||
value?: string;
|
value?: string;
|
||||||
ariaLabel?: string;
|
ariaLabel?: string;
|
||||||
@@ -389,20 +406,17 @@ declare module 'sqlops' {
|
|||||||
html?: string;
|
html?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ButtonProperties extends ComponentProperties {
|
export interface ButtonProperties extends ComponentProperties, ComponentWithIcon {
|
||||||
label?: string;
|
label?: string;
|
||||||
iconPath?: string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LoadingComponentProperties {
|
export interface LoadingComponentProperties {
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CardComponent extends Component {
|
export interface CardComponent extends Component, CardProperties {
|
||||||
label: string;
|
|
||||||
value: string;
|
|
||||||
actions?: ActionDescriptor[];
|
|
||||||
onDidActionClick: vscode.Event<ActionDescriptor>;
|
onDidActionClick: vscode.Event<ActionDescriptor>;
|
||||||
|
onCardSelectedChanged: vscode.Event<any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TextComponent extends Component {
|
export interface TextComponent extends Component {
|
||||||
@@ -582,6 +596,24 @@ declare module 'sqlops' {
|
|||||||
*/
|
*/
|
||||||
export function createWizard(title: string): Wizard;
|
export function createWizard(title: string): Wizard;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to control whether a message in a dialog/wizard is displayed as an error,
|
||||||
|
* warning, or informational message. Default is error.
|
||||||
|
*/
|
||||||
|
export enum MessageLevel {
|
||||||
|
Error = 0,
|
||||||
|
Warning = 1,
|
||||||
|
Information = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A message shown in a dialog. If the level is not set it defaults to error.
|
||||||
|
*/
|
||||||
|
export type DialogMessage = {
|
||||||
|
readonly text: string,
|
||||||
|
readonly level?: MessageLevel
|
||||||
|
};
|
||||||
|
|
||||||
export interface ModelViewPanel {
|
export interface ModelViewPanel {
|
||||||
/**
|
/**
|
||||||
* Register model view content for the dialog.
|
* Register model view content for the dialog.
|
||||||
@@ -632,6 +664,21 @@ declare module 'sqlops' {
|
|||||||
* Any additional buttons that should be displayed
|
* Any additional buttons that should be displayed
|
||||||
*/
|
*/
|
||||||
customButtons: Button[];
|
customButtons: Button[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the informational message shown in the dialog. Hidden when the message is
|
||||||
|
* undefined or the text is empty or undefined. The default level is error.
|
||||||
|
*/
|
||||||
|
message: DialogMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a callback that will be called when the user tries to click done. Only
|
||||||
|
* one callback can be registered at once, so each registration call will clear
|
||||||
|
* the previous registration.
|
||||||
|
* @param validator The callback that gets executed when the user tries to click
|
||||||
|
* done. Return true to allow the dialog to close or false to block it from closing
|
||||||
|
*/
|
||||||
|
registerCloseValidator(validator: () => boolean | Thenable<boolean>): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DialogTab extends ModelViewPanel {
|
export interface DialogTab extends ModelViewPanel {
|
||||||
@@ -798,6 +845,12 @@ declare module 'sqlops' {
|
|||||||
* cancel it.
|
* cancel it.
|
||||||
*/
|
*/
|
||||||
registerNavigationValidator(validator: (pageChangeInfo: WizardPageChangeInfo) => boolean | Thenable<boolean>): void;
|
registerNavigationValidator(validator: (pageChangeInfo: WizardPageChangeInfo) => boolean | Thenable<boolean>): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the informational message shown in the wizard. Hidden when the message is
|
||||||
|
* undefined or the text is empty or undefined. The default level is error.
|
||||||
|
*/
|
||||||
|
message: DialogMessage
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,6 +149,7 @@ export interface IModelViewDialogDetails {
|
|||||||
okButton: number;
|
okButton: number;
|
||||||
cancelButton: number;
|
cancelButton: number;
|
||||||
customButtons: number[];
|
customButtons: number[];
|
||||||
|
message: DialogMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IModelViewTabDetails {
|
export interface IModelViewTabDetails {
|
||||||
@@ -179,6 +180,18 @@ export interface IModelViewWizardDetails {
|
|||||||
nextButton: number;
|
nextButton: number;
|
||||||
backButton: number;
|
backButton: number;
|
||||||
customButtons: number[];
|
customButtons: number[];
|
||||||
|
message: DialogMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum MessageLevel {
|
||||||
|
Error = 0,
|
||||||
|
Warning = 1,
|
||||||
|
Information = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DialogMessage {
|
||||||
|
text: string;
|
||||||
|
level?: MessageLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Card-related APIs that need to be here to avoid early load issues
|
/// Card-related APIs that need to be here to avoid early load issues
|
||||||
@@ -195,6 +208,8 @@ export interface CardProperties {
|
|||||||
value?: string;
|
value?: string;
|
||||||
actions?: ActionDescriptor[];
|
actions?: ActionDescriptor[];
|
||||||
status?: StatusIndicator;
|
status?: StatusIndicator;
|
||||||
|
selected?: boolean;
|
||||||
|
cardType: CardType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ActionDescriptor {
|
export interface ActionDescriptor {
|
||||||
@@ -223,4 +238,9 @@ export enum DeclarativeDataType {
|
|||||||
string = 'string',
|
string = 'string',
|
||||||
category = 'category',
|
category = 'category',
|
||||||
boolean = 'boolean'
|
boolean = 'boolean'
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum CardType {
|
||||||
|
VerticalButton = 'VerticalButton',
|
||||||
|
Details = 'Details'
|
||||||
}
|
}
|
||||||
@@ -15,7 +15,7 @@ import * as vscode from 'vscode';
|
|||||||
import * as sqlops from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
|
|
||||||
import { SqlMainContext, ExtHostModelViewShape, MainThreadModelViewShape } from 'sql/workbench/api/node/sqlExtHost.protocol';
|
import { SqlMainContext, ExtHostModelViewShape, MainThreadModelViewShape } from 'sql/workbench/api/node/sqlExtHost.protocol';
|
||||||
import { IItemConfig, ModelComponentTypes, IComponentShape, IComponentEventArgs, ComponentEventType } from 'sql/workbench/api/common/sqlExtHostTypes';
|
import { IItemConfig, ModelComponentTypes, IComponentShape, IComponentEventArgs, ComponentEventType, CardType } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||||
|
|
||||||
class ModelBuilderImpl implements sqlops.ModelBuilder {
|
class ModelBuilderImpl implements sqlops.ModelBuilder {
|
||||||
private nextComponentId: number;
|
private nextComponentId: number;
|
||||||
@@ -255,6 +255,9 @@ class FormContainerBuilder extends ContainerBuilderImpl<sqlops.FormContainer, sq
|
|||||||
|
|
||||||
private convertToItemConfig(formComponent: sqlops.FormComponent, itemLayout?: sqlops.FormItemLayout): InternalItemConfig {
|
private convertToItemConfig(formComponent: sqlops.FormComponent, itemLayout?: sqlops.FormItemLayout): InternalItemConfig {
|
||||||
let componentWrapper = formComponent.component as ComponentWrapper;
|
let componentWrapper = formComponent.component as ComponentWrapper;
|
||||||
|
if (itemLayout && itemLayout.required && componentWrapper) {
|
||||||
|
componentWrapper.required = true;
|
||||||
|
}
|
||||||
let actions: string[] = undefined;
|
let actions: string[] = undefined;
|
||||||
if (formComponent.actions) {
|
if (formComponent.actions) {
|
||||||
actions = formComponent.actions.map(action => {
|
actions = formComponent.actions.map(action => {
|
||||||
@@ -377,7 +380,8 @@ class ComponentWrapper implements sqlops.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public get enabled(): boolean {
|
public get enabled(): boolean {
|
||||||
return this.properties['enabled'];
|
let isEnabled = this.properties['enabled'];
|
||||||
|
return (isEnabled === undefined) ? true : isEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public set enabled(value: boolean) {
|
public set enabled(value: boolean) {
|
||||||
@@ -400,6 +404,13 @@ class ComponentWrapper implements sqlops.Component {
|
|||||||
this.setProperty('width', v);
|
this.setProperty('width', v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get required(): boolean {
|
||||||
|
return this.properties['required'];
|
||||||
|
}
|
||||||
|
public set required(v: boolean) {
|
||||||
|
this.setProperty('required', v);
|
||||||
|
}
|
||||||
|
|
||||||
public toComponentShape(): IComponentShape {
|
public toComponentShape(): IComponentShape {
|
||||||
return <IComponentShape>{
|
return <IComponentShape>{
|
||||||
id: this.id,
|
id: this.id,
|
||||||
@@ -512,6 +523,7 @@ class CardWrapper extends ComponentWrapper implements sqlops.CardComponent {
|
|||||||
super(proxy, handle, ModelComponentTypes.Card, id);
|
super(proxy, handle, ModelComponentTypes.Card, id);
|
||||||
this.properties = {};
|
this.properties = {};
|
||||||
this._emitterMap.set(ComponentEventType.onDidClick, new Emitter<any>());
|
this._emitterMap.set(ComponentEventType.onDidClick, new Emitter<any>());
|
||||||
|
this._emitterMap.set(ComponentEventType.onDidClick, new Emitter<any>());
|
||||||
}
|
}
|
||||||
|
|
||||||
public get label(): string {
|
public get label(): string {
|
||||||
@@ -526,17 +538,53 @@ class CardWrapper extends ComponentWrapper implements sqlops.CardComponent {
|
|||||||
public set value(v: string) {
|
public set value(v: string) {
|
||||||
this.setProperty('value', v);
|
this.setProperty('value', v);
|
||||||
}
|
}
|
||||||
|
public get selected(): boolean {
|
||||||
|
return this.properties['selected'];
|
||||||
|
}
|
||||||
|
public set selected(v: boolean) {
|
||||||
|
this.setProperty('selected', v);
|
||||||
|
}
|
||||||
|
public get cardType(): sqlops.CardType {
|
||||||
|
return this.properties['cardType'];
|
||||||
|
}
|
||||||
|
public set cardType(v: sqlops.CardType) {
|
||||||
|
this.setProperty('cardType', v);
|
||||||
|
}
|
||||||
public get actions(): sqlops.ActionDescriptor[] {
|
public get actions(): sqlops.ActionDescriptor[] {
|
||||||
return this.properties['actions'];
|
return this.properties['actions'];
|
||||||
}
|
}
|
||||||
public set actions(a: sqlops.ActionDescriptor[]) {
|
public set actions(a: sqlops.ActionDescriptor[]) {
|
||||||
this.setProperty('actions', a);
|
this.setProperty('actions', a);
|
||||||
}
|
}
|
||||||
|
public get iconPath(): string | URI | { light: string | URI; dark: string | URI } {
|
||||||
|
return this.properties['iconPath'];
|
||||||
|
}
|
||||||
|
public set iconPath(v: string | URI | { light: string | URI; dark: string | URI }) {
|
||||||
|
this.setProperty('iconPath', v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public get iconHeight(): number | string {
|
||||||
|
return this.properties['iconHeight'];
|
||||||
|
}
|
||||||
|
public set iconHeight(v: number | string) {
|
||||||
|
this.setProperty('iconHeight', v);
|
||||||
|
}
|
||||||
|
public get iconWidth(): number | string {
|
||||||
|
return this.properties['iconWidth'];
|
||||||
|
}
|
||||||
|
public set iconWidth(v: number | string) {
|
||||||
|
this.setProperty('iconWidth', v);
|
||||||
|
}
|
||||||
|
|
||||||
public get onDidActionClick(): vscode.Event<sqlops.ActionDescriptor> {
|
public get onDidActionClick(): vscode.Event<sqlops.ActionDescriptor> {
|
||||||
let emitter = this._emitterMap.get(ComponentEventType.onDidClick);
|
let emitter = this._emitterMap.get(ComponentEventType.onDidClick);
|
||||||
return emitter && emitter.event;
|
return emitter && emitter.event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get onCardSelectedChanged(): vscode.Event<any> {
|
||||||
|
let emitter = this._emitterMap.get(ComponentEventType.onDidClick);
|
||||||
|
return emitter && emitter.event;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class InputBoxWrapper extends ComponentWrapper implements sqlops.InputBoxComponent {
|
class InputBoxWrapper extends ComponentWrapper implements sqlops.InputBoxComponent {
|
||||||
@@ -772,7 +820,11 @@ class DropDownWrapper extends ComponentWrapper implements sqlops.DropDownCompone
|
|||||||
}
|
}
|
||||||
|
|
||||||
public get value(): string | sqlops.CategoryValue {
|
public get value(): string | sqlops.CategoryValue {
|
||||||
return this.properties['value'];
|
let val = this.properties['value'];
|
||||||
|
if (!val && this.values && this.values.length > 0) {
|
||||||
|
val = this.values[0];
|
||||||
|
}
|
||||||
|
return val;
|
||||||
}
|
}
|
||||||
public set value(v: string | sqlops.CategoryValue) {
|
public set value(v: string | sqlops.CategoryValue) {
|
||||||
this.setProperty('value', v);
|
this.setProperty('value', v);
|
||||||
|
|||||||
@@ -93,6 +93,8 @@ class DialogImpl extends ModelViewPanelImpl implements sqlops.window.modelviewdi
|
|||||||
public okButton: sqlops.window.modelviewdialog.Button;
|
public okButton: sqlops.window.modelviewdialog.Button;
|
||||||
public cancelButton: sqlops.window.modelviewdialog.Button;
|
public cancelButton: sqlops.window.modelviewdialog.Button;
|
||||||
public customButtons: sqlops.window.modelviewdialog.Button[];
|
public customButtons: sqlops.window.modelviewdialog.Button[];
|
||||||
|
private _message: sqlops.window.modelviewdialog.DialogMessage;
|
||||||
|
private _closeValidator: () => boolean | Thenable<boolean>;
|
||||||
|
|
||||||
constructor(extHostModelViewDialog: ExtHostModelViewDialog,
|
constructor(extHostModelViewDialog: ExtHostModelViewDialog,
|
||||||
extHostModelView: ExtHostModelViewShape) {
|
extHostModelView: ExtHostModelViewShape) {
|
||||||
@@ -105,6 +107,27 @@ class DialogImpl extends ModelViewPanelImpl implements sqlops.window.modelviewdi
|
|||||||
super.setModelViewId(value);
|
super.setModelViewId(value);
|
||||||
this.content = value;
|
this.content = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get message(): sqlops.window.modelviewdialog.DialogMessage {
|
||||||
|
return this._message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public set message(value: sqlops.window.modelviewdialog.DialogMessage) {
|
||||||
|
this._message = value;
|
||||||
|
this._extHostModelViewDialog.updateDialogContent(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public registerCloseValidator(validator: () => boolean | Thenable<boolean>): void {
|
||||||
|
this._closeValidator = validator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public validateClose(): Thenable<boolean> {
|
||||||
|
if (this._closeValidator) {
|
||||||
|
return Promise.resolve(this._closeValidator());
|
||||||
|
} else {
|
||||||
|
return Promise.resolve(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TabImpl extends ModelViewPanelImpl implements sqlops.window.modelviewdialog.DialogTab {
|
class TabImpl extends ModelViewPanelImpl implements sqlops.window.modelviewdialog.DialogTab {
|
||||||
@@ -218,6 +241,7 @@ class WizardImpl implements sqlops.window.modelviewdialog.Wizard {
|
|||||||
private _pageChangedEmitter = new Emitter<sqlops.window.modelviewdialog.WizardPageChangeInfo>();
|
private _pageChangedEmitter = new Emitter<sqlops.window.modelviewdialog.WizardPageChangeInfo>();
|
||||||
public readonly onPageChanged = this._pageChangedEmitter.event;
|
public readonly onPageChanged = this._pageChangedEmitter.event;
|
||||||
private _navigationValidator: (info: sqlops.window.modelviewdialog.WizardPageChangeInfo) => boolean | Thenable<boolean>;
|
private _navigationValidator: (info: sqlops.window.modelviewdialog.WizardPageChangeInfo) => boolean | Thenable<boolean>;
|
||||||
|
private _message: sqlops.window.modelviewdialog.DialogMessage;
|
||||||
|
|
||||||
constructor(public title: string, private _extHostModelViewDialog: ExtHostModelViewDialog) {
|
constructor(public title: string, private _extHostModelViewDialog: ExtHostModelViewDialog) {
|
||||||
this.doneButton = this._extHostModelViewDialog.createButton(DONE_LABEL);
|
this.doneButton = this._extHostModelViewDialog.createButton(DONE_LABEL);
|
||||||
@@ -234,6 +258,15 @@ class WizardImpl implements sqlops.window.modelviewdialog.Wizard {
|
|||||||
return this._currentPage;
|
return this._currentPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get message(): sqlops.window.modelviewdialog.DialogMessage {
|
||||||
|
return this._message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public set message(value: sqlops.window.modelviewdialog.DialogMessage) {
|
||||||
|
this._message = value;
|
||||||
|
this._extHostModelViewDialog.updateWizard(this);
|
||||||
|
}
|
||||||
|
|
||||||
public addPage(page: sqlops.window.modelviewdialog.WizardPage, index?: number): Thenable<void> {
|
public addPage(page: sqlops.window.modelviewdialog.WizardPage, index?: number): Thenable<void> {
|
||||||
return this._extHostModelViewDialog.updateWizardPage(page).then(() => {
|
return this._extHostModelViewDialog.updateWizardPage(page).then(() => {
|
||||||
this._extHostModelViewDialog.addPage(this, page, index);
|
this._extHostModelViewDialog.addPage(this, page, index);
|
||||||
@@ -354,6 +387,11 @@ export class ExtHostModelViewDialog implements ExtHostModelViewDialogShape {
|
|||||||
return wizard.validateNavigation(info);
|
return wizard.validateNavigation(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public $validateDialogClose(handle: number): Thenable<boolean> {
|
||||||
|
let dialog = this._objectsByHandle.get(handle) as DialogImpl;
|
||||||
|
return dialog.validateClose();
|
||||||
|
}
|
||||||
|
|
||||||
public openDialog(dialog: sqlops.window.modelviewdialog.Dialog): void {
|
public openDialog(dialog: sqlops.window.modelviewdialog.Dialog): void {
|
||||||
let handle = this.getHandle(dialog);
|
let handle = this.getHandle(dialog);
|
||||||
this.updateDialogContent(dialog);
|
this.updateDialogContent(dialog);
|
||||||
@@ -387,7 +425,8 @@ export class ExtHostModelViewDialog implements ExtHostModelViewDialogShape {
|
|||||||
okButton: this.getHandle(dialog.okButton),
|
okButton: this.getHandle(dialog.okButton),
|
||||||
cancelButton: this.getHandle(dialog.cancelButton),
|
cancelButton: this.getHandle(dialog.cancelButton),
|
||||||
content: dialog.content && typeof dialog.content !== 'string' ? dialog.content.map(tab => this.getHandle(tab)) : dialog.content as string,
|
content: dialog.content && typeof dialog.content !== 'string' ? dialog.content.map(tab => this.getHandle(tab)) : dialog.content as string,
|
||||||
customButtons: dialog.customButtons ? dialog.customButtons.map(button => this.getHandle(button)) : undefined
|
customButtons: dialog.customButtons ? dialog.customButtons.map(button => this.getHandle(button)) : undefined,
|
||||||
|
message: dialog.message
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -495,7 +534,8 @@ export class ExtHostModelViewDialog implements ExtHostModelViewDialogShape {
|
|||||||
generateScriptButton: this.getHandle(wizard.generateScriptButton),
|
generateScriptButton: this.getHandle(wizard.generateScriptButton),
|
||||||
doneButton: this.getHandle(wizard.doneButton),
|
doneButton: this.getHandle(wizard.doneButton),
|
||||||
nextButton: this.getHandle(wizard.nextButton),
|
nextButton: this.getHandle(wizard.nextButton),
|
||||||
customButtons: wizard.customButtons ? wizard.customButtons.map(button => this.getHandle(button)) : undefined
|
customButtons: wizard.customButtons ? wizard.customButtons.map(button => this.getHandle(button)) : undefined,
|
||||||
|
message: wizard.message
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ export class MainThreadModelViewDialog implements MainThreadModelViewDialogShape
|
|||||||
dialog.okButton = okButton;
|
dialog.okButton = okButton;
|
||||||
dialog.cancelButton = cancelButton;
|
dialog.cancelButton = cancelButton;
|
||||||
dialog.onValidityChanged(valid => this._proxy.$onPanelValidityChanged(handle, valid));
|
dialog.onValidityChanged(valid => this._proxy.$onPanelValidityChanged(handle, valid));
|
||||||
|
dialog.registerCloseValidator(() => this.validateDialogClose(handle));
|
||||||
this._dialogs.set(handle, dialog);
|
this._dialogs.set(handle, dialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,6 +95,8 @@ export class MainThreadModelViewDialog implements MainThreadModelViewDialogShape
|
|||||||
dialog.customButtons = details.customButtons.map(buttonHandle => this.getButton(buttonHandle));
|
dialog.customButtons = details.customButtons.map(buttonHandle => this.getButton(buttonHandle));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dialog.message = details.message;
|
||||||
|
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,6 +172,7 @@ export class MainThreadModelViewDialog implements MainThreadModelViewDialogShape
|
|||||||
if (details.customButtons !== undefined) {
|
if (details.customButtons !== undefined) {
|
||||||
wizard.customButtons = details.customButtons.map(buttonHandle => this.getButton(buttonHandle));
|
wizard.customButtons = details.customButtons.map(buttonHandle => this.getButton(buttonHandle));
|
||||||
}
|
}
|
||||||
|
wizard.message = details.message;
|
||||||
|
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
@@ -259,4 +263,8 @@ export class MainThreadModelViewDialog implements MainThreadModelViewDialogShape
|
|||||||
private validateNavigation(handle: number, info: sqlops.window.modelviewdialog.WizardPageChangeInfo): Thenable<boolean> {
|
private validateNavigation(handle: number, info: sqlops.window.modelviewdialog.WizardPageChangeInfo): Thenable<boolean> {
|
||||||
return this._proxy.$validateNavigation(handle, info);
|
return this._proxy.$validateNavigation(handle, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private validateDialogClose(handle: number): Thenable<boolean> {
|
||||||
|
return this._proxy.$validateDialogClose(handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -315,7 +315,8 @@ export function createApiFactory(
|
|||||||
},
|
},
|
||||||
createWizard(title: string): sqlops.window.modelviewdialog.Wizard {
|
createWizard(title: string): sqlops.window.modelviewdialog.Wizard {
|
||||||
return extHostModelViewDialog.createWizard(title);
|
return extHostModelViewDialog.createWizard(title);
|
||||||
}
|
},
|
||||||
|
MessageLevel: sqlExtHostTypes.MessageLevel
|
||||||
};
|
};
|
||||||
|
|
||||||
const window: typeof sqlops.window = {
|
const window: typeof sqlops.window = {
|
||||||
@@ -390,7 +391,8 @@ export function createApiFactory(
|
|||||||
workspace,
|
workspace,
|
||||||
queryeditor: queryEditor,
|
queryeditor: queryEditor,
|
||||||
ui: ui,
|
ui: ui,
|
||||||
StatusIndicator: sqlExtHostTypes.StatusIndicator
|
StatusIndicator: sqlExtHostTypes.StatusIndicator,
|
||||||
|
CardType: sqlExtHostTypes.CardType
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -563,6 +563,7 @@ export interface ExtHostModelViewDialogShape {
|
|||||||
$onWizardPageChanged(handle: number, info: sqlops.window.modelviewdialog.WizardPageChangeInfo): void;
|
$onWizardPageChanged(handle: number, info: sqlops.window.modelviewdialog.WizardPageChangeInfo): void;
|
||||||
$updateWizardPageInfo(handle: number, pageHandles: number[], currentPageIndex: number): void;
|
$updateWizardPageInfo(handle: number, pageHandles: number[], currentPageIndex: number): void;
|
||||||
$validateNavigation(handle: number, info: sqlops.window.modelviewdialog.WizardPageChangeInfo): Thenable<boolean>;
|
$validateNavigation(handle: number, info: sqlops.window.modelviewdialog.WizardPageChangeInfo): Thenable<boolean>;
|
||||||
|
$validateDialogClose(handle: number): Thenable<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MainThreadModelViewDialogShape extends IDisposable {
|
export interface MainThreadModelViewDialogShape extends IDisposable {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { Mock, It, Times } from 'typemoq';
|
|||||||
import { ExtHostModelViewDialog } from 'sql/workbench/api/node/extHostModelViewDialog';
|
import { ExtHostModelViewDialog } from 'sql/workbench/api/node/extHostModelViewDialog';
|
||||||
import { MainThreadModelViewDialogShape, ExtHostModelViewShape } from 'sql/workbench/api/node/sqlExtHost.protocol';
|
import { MainThreadModelViewDialogShape, ExtHostModelViewShape } from 'sql/workbench/api/node/sqlExtHost.protocol';
|
||||||
import { IMainContext } from 'vs/workbench/api/node/extHost.protocol';
|
import { IMainContext } from 'vs/workbench/api/node/extHost.protocol';
|
||||||
|
import { MessageLevel } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
@@ -290,4 +291,39 @@ suite('ExtHostModelViewDialog Tests', () => {
|
|||||||
assert.equal(validationInfo.lastPage, lastPage);
|
assert.equal(validationInfo.lastPage, lastPage);
|
||||||
assert.equal(validationInfo.newPage, newPage);
|
assert.equal(validationInfo.newPage, newPage);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Changing the wizard message sends the new message to the main thread', () => {
|
||||||
|
// Set up the main thread mock to record the call
|
||||||
|
mockProxy.setup(x => x.$setWizardDetails(It.isAny(), It.isAny()));
|
||||||
|
let wizard = extHostModelViewDialog.createWizard('wizard_1');
|
||||||
|
|
||||||
|
// If I update the wizard's message
|
||||||
|
let newMessage = {
|
||||||
|
level: MessageLevel.Error,
|
||||||
|
text: 'test message'
|
||||||
|
};
|
||||||
|
wizard.message = newMessage;
|
||||||
|
|
||||||
|
// Then the main thread gets notified of the new details
|
||||||
|
mockProxy.verify(x => x.$setWizardDetails(It.isAny(), It.is(x => x.message === newMessage)), Times.once());
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Main thread can execute dialog close validation', () => {
|
||||||
|
// Set up the main thread mock to record the dialog handle
|
||||||
|
let dialogHandle: number;
|
||||||
|
mockProxy.setup(x => x.$setDialogDetails(It.isAny(), It.isAny())).callback((handle, details) => dialogHandle = handle);
|
||||||
|
|
||||||
|
// Create the dialog and add a validation that records that it has been called
|
||||||
|
let dialog = extHostModelViewDialog.createDialog('dialog_1');
|
||||||
|
extHostModelViewDialog.updateDialogContent(dialog);
|
||||||
|
let callCount = 0;
|
||||||
|
dialog.registerCloseValidator(() => {
|
||||||
|
callCount++;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// If I call the validation from the main thread then it should run
|
||||||
|
extHostModelViewDialog.$validateDialogClose(dialogHandle);
|
||||||
|
assert.equal(callCount, 1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
@@ -7,7 +7,7 @@ import * as assert from 'assert';
|
|||||||
import { Mock, It, Times } from 'typemoq';
|
import { Mock, It, Times } from 'typemoq';
|
||||||
import { MainThreadModelViewDialog } from 'sql/workbench/api/node/mainThreadModelViewDialog';
|
import { MainThreadModelViewDialog } from 'sql/workbench/api/node/mainThreadModelViewDialog';
|
||||||
import { IExtHostContext } from 'vs/workbench/api/node/extHost.protocol';
|
import { IExtHostContext } from 'vs/workbench/api/node/extHost.protocol';
|
||||||
import { IModelViewButtonDetails, IModelViewTabDetails, IModelViewDialogDetails, IModelViewWizardPageDetails, IModelViewWizardDetails } from 'sql/workbench/api/common/sqlExtHostTypes';
|
import { IModelViewButtonDetails, IModelViewTabDetails, IModelViewDialogDetails, IModelViewWizardPageDetails, IModelViewWizardDetails, DialogMessage, MessageLevel } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||||
import { CustomDialogService } from 'sql/platform/dialog/customDialogService';
|
import { CustomDialogService } from 'sql/platform/dialog/customDialogService';
|
||||||
import { Dialog, DialogTab, Wizard } from 'sql/platform/dialog/dialogTypes';
|
import { Dialog, DialogTab, Wizard } from 'sql/platform/dialog/dialogTypes';
|
||||||
import { ExtHostModelViewDialogShape } from 'sql/workbench/api/node/sqlExtHost.protocol';
|
import { ExtHostModelViewDialogShape } from 'sql/workbench/api/node/sqlExtHost.protocol';
|
||||||
@@ -60,7 +60,8 @@ suite('MainThreadModelViewDialog Tests', () => {
|
|||||||
$onPanelValidityChanged: (handle, valid) => undefined,
|
$onPanelValidityChanged: (handle, valid) => undefined,
|
||||||
$onWizardPageChanged: (handle, info) => undefined,
|
$onWizardPageChanged: (handle, info) => undefined,
|
||||||
$updateWizardPageInfo: (wizardHandle, pageHandles, currentPageIndex) => undefined,
|
$updateWizardPageInfo: (wizardHandle, pageHandles, currentPageIndex) => undefined,
|
||||||
$validateNavigation: (handle, info) => undefined
|
$validateNavigation: (handle, info) => undefined,
|
||||||
|
$validateDialogClose: handle => undefined
|
||||||
});
|
});
|
||||||
let extHostContext = <IExtHostContext>{
|
let extHostContext = <IExtHostContext>{
|
||||||
getProxy: proxyType => mockExtHostModelViewDialog.object
|
getProxy: proxyType => mockExtHostModelViewDialog.object
|
||||||
@@ -112,7 +113,8 @@ suite('MainThreadModelViewDialog Tests', () => {
|
|||||||
content: [tab1Handle, tab2Handle],
|
content: [tab1Handle, tab2Handle],
|
||||||
okButton: okButtonHandle,
|
okButton: okButtonHandle,
|
||||||
cancelButton: cancelButtonHandle,
|
cancelButton: cancelButtonHandle,
|
||||||
customButtons: [button1Handle, button2Handle]
|
customButtons: [button1Handle, button2Handle],
|
||||||
|
message: undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set up the wizard details
|
// Set up the wizard details
|
||||||
@@ -152,7 +154,8 @@ suite('MainThreadModelViewDialog Tests', () => {
|
|||||||
currentPage: undefined,
|
currentPage: undefined,
|
||||||
title: 'wizard_title',
|
title: 'wizard_title',
|
||||||
customButtons: [],
|
customButtons: [],
|
||||||
pages: [page1Handle, page2Handle]
|
pages: [page1Handle, page2Handle],
|
||||||
|
message: undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
// Register the buttons, tabs, and dialog
|
// Register the buttons, tabs, and dialog
|
||||||
@@ -322,10 +325,38 @@ suite('MainThreadModelViewDialog Tests', () => {
|
|||||||
mockExtHostModelViewDialog.setup(x => x.$validateNavigation(It.isAny(), It.isAny()));
|
mockExtHostModelViewDialog.setup(x => x.$validateNavigation(It.isAny(), It.isAny()));
|
||||||
|
|
||||||
// If I call validateNavigation on the wizard that gets created
|
// If I call validateNavigation on the wizard that gets created
|
||||||
let wizard: Wizard = (mainThreadModelViewDialog as any).getWizard(wizardHandle);
|
mainThreadModelViewDialog.$openWizard(wizardHandle);
|
||||||
wizard.validateNavigation(1);
|
openedWizard.validateNavigation(1);
|
||||||
|
|
||||||
// Then the call gets forwarded to the extension host
|
// Then the call gets forwarded to the extension host
|
||||||
mockExtHostModelViewDialog.verify(x => x.$validateNavigation(It.is(handle => handle === wizardHandle), It.is(info => info.newPage === 1)), Times.once());
|
mockExtHostModelViewDialog.verify(x => x.$validateNavigation(It.is(handle => handle === wizardHandle), It.is(info => info.newPage === 1)), Times.once());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Adding a message to a wizard fires events on the created wizard', () => {
|
||||||
|
mainThreadModelViewDialog.$openWizard(wizardHandle);
|
||||||
|
let newMessage: DialogMessage;
|
||||||
|
openedWizard.onMessageChange(message => newMessage = message);
|
||||||
|
|
||||||
|
// If I change the wizard's message
|
||||||
|
wizardDetails.message = {
|
||||||
|
level: MessageLevel.Error,
|
||||||
|
text: 'test message'
|
||||||
|
};
|
||||||
|
mainThreadModelViewDialog.$setWizardDetails(wizardHandle, wizardDetails);
|
||||||
|
|
||||||
|
// Then the message gets changed on the wizard
|
||||||
|
assert.equal(newMessage, wizardDetails.message, 'New message was not included in the fired event');
|
||||||
|
assert.equal(openedWizard.message, wizardDetails.message, 'New message was not set on the wizard');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Creating a dialog adds a close validation that calls the extension host', () => {
|
||||||
|
mockExtHostModelViewDialog.setup(x => x.$validateDialogClose(It.isAny()));
|
||||||
|
|
||||||
|
// If I call validateClose on the dialog that gets created
|
||||||
|
mainThreadModelViewDialog.$openDialog(dialogHandle);
|
||||||
|
openedDialog.validateClose();
|
||||||
|
|
||||||
|
// Then the call gets forwarded to the extension host
|
||||||
|
mockExtHostModelViewDialog.verify(x => x.$validateDialogClose(It.is(handle => handle === dialogHandle)), Times.once());
|
||||||
|
});
|
||||||
});
|
});
|
||||||
@@ -52,6 +52,7 @@ export interface IProductConfiguration {
|
|||||||
};
|
};
|
||||||
documentationUrl: string;
|
documentationUrl: string;
|
||||||
releaseNotesUrl: string;
|
releaseNotesUrl: string;
|
||||||
|
// {SQL CARBON EDIT}
|
||||||
gettingStartedUrl: string;
|
gettingStartedUrl: string;
|
||||||
keyboardShortcutsUrlMac: string;
|
keyboardShortcutsUrlMac: string;
|
||||||
keyboardShortcutsUrlLinux: string;
|
keyboardShortcutsUrlLinux: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user