mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-25 18:47:14 -05:00
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ca755365ce | ||
|
|
ea979de19f | ||
|
|
473ddfcdf1 | ||
|
|
a627285a4c | ||
|
|
322847469d | ||
|
|
6c5fac997f | ||
|
|
1871fd383e | ||
|
|
f5b147ca4b | ||
|
|
9d2b206156 | ||
|
|
a372c76e07 | ||
|
|
b1ce07d3ae | ||
|
|
bc09fb30d8 | ||
|
|
c13f219318 | ||
|
|
6b018c5d06 | ||
|
|
e69158d9b2 | ||
|
|
520cfb780a | ||
|
|
e686fed209 | ||
|
|
80ab19ac23 | ||
|
|
25228fa58e | ||
|
|
676d35090f | ||
|
|
e1a36a356c | ||
|
|
3274c0b734 | ||
|
|
9c95e1289f |
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
|
||||||
}
|
}
|
||||||
|
|||||||
13
CHANGELOG.md
13
CHANGELOG.md
@@ -1,5 +1,18 @@
|
|||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## Version 0.30.6
|
||||||
|
* Release date: June 20, 2018
|
||||||
|
* Release status: Public Preview
|
||||||
|
|
||||||
|
## What's new in this version
|
||||||
|
* **SQL Server Profiler for SQL Operations Studio *Preview*** extension initial release
|
||||||
|
* The new **SQL Data Warehouse** extension includes rich customizable dashboard widgets surfacing insights to your data warehouse. This unlocks key scenarios around managing and tuning your data warehouse to ensure it is optimized for consistent performance.
|
||||||
|
* **Edit Data "Filtering and Sorting"** support
|
||||||
|
* **SQL Server Agent for SQL Operations Studio *Preview*** extension enhancements for Jobs and Job History views
|
||||||
|
* Improved **Wizard & Dialog UI Builder Framework** extensibility APIs
|
||||||
|
* Update VS Code Platform source code integrating [March 2018 (1.22)](https://code.visualstudio.com/updates/v1_22) and [April 2018 (1.23)](https://code.visualstudio.com/updates/v1_23) releases
|
||||||
|
* Fix GitHub Issues
|
||||||
|
|
||||||
## Version 0.29.3
|
## Version 0.29.3
|
||||||
* Release date: May 7, 2018
|
* Release date: May 7, 2018
|
||||||
* Release status: Public Preview
|
* Release status: Public Preview
|
||||||
|
|||||||
15
README.md
15
README.md
@@ -4,16 +4,16 @@
|
|||||||
|
|
||||||
SQL Operations Studio is a data management tool that enables you to work with SQL Server, Azure SQL DB and SQL DW from Windows, macOS and Linux.
|
SQL Operations Studio is a data management tool that enables you to work with SQL Server, Azure SQL DB and SQL DW from Windows, macOS and Linux.
|
||||||
|
|
||||||
**Download SQL Operations Studio May Public Preview**
|
**Download SQL Operations Studio June Public Preview**
|
||||||
|
|
||||||
Platform | Link
|
Platform | Link
|
||||||
-- | --
|
-- | --
|
||||||
Windows Setup Installer | https://go.microsoft.com/fwlink/?linkid=873386
|
Windows Setup Installer | https://go.microsoft.com/fwlink/?linkid=875602
|
||||||
Windows ZIP | https://go.microsoft.com/fwlink/?linkid=873387
|
Windows ZIP | https://go.microsoft.com/fwlink/?linkid=875603
|
||||||
macOS ZIP | https://go.microsoft.com/fwlink/?linkid=873388
|
macOS ZIP | https://go.microsoft.com/fwlink/?linkid=875604
|
||||||
Linux TAR.GZ | https://go.microsoft.com/fwlink/?linkid=873389
|
Linux TAR.GZ | https://go.microsoft.com/fwlink/?linkid=875605
|
||||||
Linux RPM | https://go.microsoft.com/fwlink/?linkid=873390
|
Linux RPM | https://go.microsoft.com/fwlink/?linkid=875606
|
||||||
Linux DEB | https://go.microsoft.com/fwlink/?linkid=873391
|
Linux DEB | https://go.microsoft.com/fwlink/?linkid=875607
|
||||||
|
|
||||||
Go to our [download page](https://aka.ms/sqlopsstudio) for more specific instructions.
|
Go to our [download page](https://aka.ms/sqlopsstudio) for more specific instructions.
|
||||||
|
|
||||||
@@ -61,6 +61,7 @@ The [Microsoft Enterprise and Developer Privacy Statement](https://privacy.micro
|
|||||||
## Contributions and "thank you"
|
## Contributions and "thank you"
|
||||||
We would like to thank all our users who raised issues, and in particular the following users who helped contribute fixes:
|
We would like to thank all our users who raised issues, and in particular the following users who helped contribute fixes:
|
||||||
|
|
||||||
|
* lanceklinger `Fix for double clicking column handle in results table #1504`
|
||||||
* westerncj for `Removed duplicate contribution from README.md (#753)`
|
* westerncj for `Removed duplicate contribution from README.md (#753)`
|
||||||
* ntovas for `Fix for duplicate extensions shown in "Save File" dialog. (#779)`
|
* ntovas for `Fix for duplicate extensions shown in "Save File" dialog. (#779)`
|
||||||
* SebastianPfliegel for `Add cursor snippet (#475)`
|
* SebastianPfliegel for `Add cursor snippet (#475)`
|
||||||
|
|||||||
@@ -658,7 +658,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#0.1.8.2",
|
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#0.1.9",
|
||||||
"opener": "^1.4.3",
|
"opener": "^1.4.3",
|
||||||
"service-downloader": "github:anthonydresser/service-downloader#0.1.2",
|
"service-downloader": "github:anthonydresser/service-downloader#0.1.2",
|
||||||
"vscode-extension-telemetry": "^0.0.15"
|
"vscode-extension-telemetry": "^0.0.15"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
|
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
|
||||||
"version": "1.4.0-alpha.45",
|
"version": "1.4.0-alpha.46",
|
||||||
"downloadFileNames": {
|
"downloadFileNames": {
|
||||||
"Windows_86": "win-x86-netcoreapp2.1.zip",
|
"Windows_86": "win-x86-netcoreapp2.1.zip",
|
||||||
"Windows_64": "win-x64-netcoreapp2.1.zip",
|
"Windows_64": "win-x64-netcoreapp2.1.zip",
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,13 @@ Common SQL Profiler use-cases taken from https://docs.microsoft.com/en-us/sql/to
|
|||||||
- Monitoring the performance of SQL Server to tune workloads.
|
- Monitoring the performance of SQL Server to tune workloads.
|
||||||
- Correlating performance counters to diagnose problems.
|
- Correlating performance counters to diagnose problems.
|
||||||
|
|
||||||
|
## SQL Server Profiler 0.1.1 Release
|
||||||
|
The SQL Server Profiler for SQL Operations Studio *Preview* extension is now available. This is the initial preview release for a new lightweight XEvent-based profiler. The SQL Server Profiler extension tries to make it simple to quickly trace server activity for troubleshooting and monitoring.
|
||||||
|
|
||||||
|
We'll continue to enhance this extension over the next couple releases. Take a look at the below screenshot to see what's currently available.
|
||||||
|
|
||||||
|
<img width="850" src="https://user-images.githubusercontent.com/599935/41578613-fa10e8bc-7347-11e8-8b97-9fb7d186c9f6.png">
|
||||||
|
|
||||||
## Code of Conduct
|
## Code of Conduct
|
||||||
|
|
||||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "profiler",
|
"name": "profiler",
|
||||||
"displayName": "SQL Server Profiler",
|
"displayName": "SQL Server Profiler",
|
||||||
"description": "SQL Server Profiler for SQL Operations Studio",
|
"description": "SQL Server Profiler for SQL Operations Studio",
|
||||||
"version": "0.30.0",
|
"version": "0.1.1",
|
||||||
"publisher": "Microsoft",
|
"publisher": "Microsoft",
|
||||||
"preview": true,
|
"preview": true,
|
||||||
"license": "https://raw.githubusercontent.com/Microsoft/sqlopsstudio/master/LICENSE.txt",
|
"license": "https://raw.githubusercontent.com/Microsoft/sqlopsstudio/master/LICENSE.txt",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "sqlops",
|
"name": "sqlops",
|
||||||
"version": "0.30.5",
|
"version": "0.31.1",
|
||||||
"distro": "8c3e97e3425cc9814496472ab73e076de2ba99ee",
|
"distro": "8c3e97e3425cc9814496472ab73e076de2ba99ee",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Microsoft Corporation"
|
"name": "Microsoft Corporation"
|
||||||
|
|||||||
@@ -27,14 +27,16 @@
|
|||||||
"reportIssueUrl": "https://github.com/Microsoft/sqlopsstudio/issues/new?labels=customer%20reported%20issue",
|
"reportIssueUrl": "https://github.com/Microsoft/sqlopsstudio/issues/new?labels=customer%20reported%20issue",
|
||||||
"requestFeatureUrl": "https://github.com/Microsoft/sqlopsstudio/issues/new?labels=feature-request"
|
"requestFeatureUrl": "https://github.com/Microsoft/sqlopsstudio/issues/new?labels=feature-request"
|
||||||
},
|
},
|
||||||
"releaseNotesUrl": "https://go.microsoft.com/fwlink/?linkid=862039",
|
"gettingStartedUrl": "https://go.microsoft.com/fwlink/?linkid=862039",
|
||||||
|
"releaseNotesUrl": "https://go.microsoft.com/fwlink/?linkid=875578",
|
||||||
"documentationUrl": "https://go.microsoft.com/fwlink/?linkid=862277",
|
"documentationUrl": "https://go.microsoft.com/fwlink/?linkid=862277",
|
||||||
"commit": "9ca6200018fc206d67a47229f991901a8a453781",
|
"commit": "9ca6200018fc206d67a47229f991901a8a453781",
|
||||||
"date": "2017-12-15T12:00:00.000Z",
|
"date": "2017-12-15T12:00:00.000Z",
|
||||||
"recommendedExtensions": [
|
"recommendedExtensions": [
|
||||||
"Microsoft.agent",
|
"Microsoft.agent",
|
||||||
"Microsoft.whoisactive",
|
"Microsoft.profiler",
|
||||||
"Microsoft.server-report",
|
"Microsoft.server-report",
|
||||||
|
"Microsoft.whoisactive",
|
||||||
"Redgate.sql-search"
|
"Redgate.sql-search"
|
||||||
],
|
],
|
||||||
"extensionsGallery": {
|
"extensionsGallery": {
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,4 +5,9 @@
|
|||||||
|
|
||||||
.editdata-component * {
|
.editdata-component * {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
#workbench\.editor\.editDataEditor .monaco-toolbar .monaco-select-box {
|
||||||
|
margin-top: 4px;
|
||||||
|
margin-bottom: 4px;
|
||||||
}
|
}
|
||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,22 +83,19 @@ export default class ButtonComponent extends ComponentBase implements IComponent
|
|||||||
this._button.enabled = this.enabled;
|
this._button.enabled = this.enabled;
|
||||||
this._button.label = this.label;
|
this._button.label = this.label;
|
||||||
if (this.width) {
|
if (this.width) {
|
||||||
this._button.setWidth(this.width.toString());
|
this._button.setWidth(this.convertSize(this.width.toString()));
|
||||||
}
|
}
|
||||||
if (this.height) {
|
if (this.height) {
|
||||||
this._button.setWidth(this.height.toString());
|
this._button.setWidth(this.convertSize(this.height.toString()));
|
||||||
}
|
}
|
||||||
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;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import { attachInputBoxStyler, attachListStyler } from 'vs/platform/theme/common
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'modelview-checkbox',
|
selector: 'modelview-checkbox',
|
||||||
template: `
|
template: `
|
||||||
<div #input style="width: 100%"></div>
|
<div #input [style.width]="getWidth()"></div>
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
export default class CheckBoxComponent extends ComponentBase implements IComponent, OnDestroy, AfterViewInit {
|
export default class CheckBoxComponent extends ComponentBase implements IComponent, OnDestroy, AfterViewInit {
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -146,11 +148,12 @@ export abstract class ComponentBase extends Disposable implements IComponent, On
|
|||||||
return this.height ? this.convertSize(this.height) : '';
|
return this.height ? this.convertSize(this.height) : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected convertSize(size: number | string): string {
|
protected convertSize(size: number | string, defaultValue?: string): string {
|
||||||
|
defaultValue = defaultValue || '';
|
||||||
if (types.isUndefinedOrNull(size)) {
|
if (types.isUndefinedOrNull(size)) {
|
||||||
return '100%';
|
return defaultValue;
|
||||||
}
|
}
|
||||||
let convertedSize: string = size ? size.toString() : '100%';
|
let convertedSize: string = size ? size.toString() : defaultValue;
|
||||||
if (!convertedSize.toLowerCase().endsWith('px') && !convertedSize.toLowerCase().endsWith('%')) {
|
if (!convertedSize.toLowerCase().endsWith('px') && !convertedSize.toLowerCase().endsWith('%')) {
|
||||||
convertedSize = convertedSize + 'px';
|
convertedSize = convertedSize + 'px';
|
||||||
}
|
}
|
||||||
|
|||||||
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);
|
||||||
@@ -145,18 +143,22 @@ export default class DropDownComponent extends ComponentBase implements ICompone
|
|||||||
}
|
}
|
||||||
|
|
||||||
private getSelectedValue(): string {
|
private getSelectedValue(): string {
|
||||||
if (this.values && this.valuesHaveDisplayName()) {
|
if (this.values && this.values.length > 0 && this.valuesHaveDisplayName()) {
|
||||||
let valueCategory = (<sqlops.CategoryValue[]>this.values).find(v => v.name === this.value);
|
let selectedValue = <sqlops.CategoryValue>this.value || <sqlops.CategoryValue>this.values[0];
|
||||||
|
let valueCategory = (<sqlops.CategoryValue[]>this.values).find(v => v.name === selectedValue.name);
|
||||||
return valueCategory && valueCategory.displayName;
|
return valueCategory && valueCategory.displayName;
|
||||||
} else {
|
} else {
|
||||||
return this.value;
|
if (!this.value && this.values && this.values.length > 0) {
|
||||||
|
return <string>this.values[0];
|
||||||
|
}
|
||||||
|
return <string>this.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private setSelectedValue(newValue: string): void {
|
private setSelectedValue(newValue: string): void {
|
||||||
if (this.values && this.valuesHaveDisplayName()) {
|
if (this.values && this.valuesHaveDisplayName()) {
|
||||||
let valueCategory = (<sqlops.CategoryValue[]>this.values).find(v => v.displayName === newValue);
|
let valueCategory = (<sqlops.CategoryValue[]>this.values).find(v => v.displayName === newValue);
|
||||||
this.value = valueCategory && valueCategory.name;
|
this.value = valueCategory;
|
||||||
} else {
|
} else {
|
||||||
this.value = newValue;
|
this.value = newValue;
|
||||||
}
|
}
|
||||||
@@ -164,8 +166,8 @@ export default class DropDownComponent extends ComponentBase implements ICompone
|
|||||||
|
|
||||||
// CSS-bound properties
|
// CSS-bound properties
|
||||||
|
|
||||||
private get value(): string {
|
private get value(): string | sqlops.CategoryValue {
|
||||||
return this.getPropertyOrDefault<sqlops.DropDownProperties, string>((props) => props.value, '');
|
return this.getPropertyOrDefault<sqlops.DropDownProperties, string | sqlops.CategoryValue>((props) => props.value, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
private get editable(): boolean {
|
private get editable(): boolean {
|
||||||
@@ -180,8 +182,8 @@ export default class DropDownComponent extends ComponentBase implements ICompone
|
|||||||
return !this.editable ? '' : 'none';
|
return !this.editable ? '' : 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
private set value(newValue: string) {
|
private set value(newValue: string | sqlops.CategoryValue) {
|
||||||
this.setPropertyFromUI<sqlops.DropDownProperties, string>(this.setValueProperties, newValue);
|
this.setPropertyFromUI<sqlops.DropDownProperties, string | sqlops.CategoryValue>(this.setValueProperties, newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private get values(): string[] | sqlops.CategoryValue[] {
|
private get values(): string[] | sqlops.CategoryValue[] {
|
||||||
@@ -192,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class FlexItem {
|
|||||||
template: `
|
template: `
|
||||||
<div *ngIf="items" class="flexContainer" [style.flexFlow]="flexFlow" [style.justifyContent]="justifyContent"
|
<div *ngIf="items" class="flexContainer" [style.flexFlow]="flexFlow" [style.justifyContent]="justifyContent"
|
||||||
[style.alignItems]="alignItems" [style.alignContent]="alignContent" [style.height]="height" [style.width]="width">
|
[style.alignItems]="alignItems" [style.alignContent]="alignContent" [style.height]="height" [style.width]="width">
|
||||||
<div *ngFor="let item of items" [style.flex]="getItemFlex(item)" [style.order]="getItemOrder(item)" >
|
<div *ngFor="let item of items" [style.flex]="getItemFlex(item)" [style.textAlign]="textAlign" [style.order]="getItemOrder(item)" >
|
||||||
<model-component-wrapper [descriptor]="item.descriptor" [modelStore]="modelStore">
|
<model-component-wrapper [descriptor]="item.descriptor" [modelStore]="modelStore">
|
||||||
</model-component-wrapper>
|
</model-component-wrapper>
|
||||||
</div>
|
</div>
|
||||||
@@ -40,6 +40,7 @@ export default class FlexContainer extends ContainerBase<FlexItemLayout> impleme
|
|||||||
private _justifyContent: string;
|
private _justifyContent: string;
|
||||||
private _alignItems: string;
|
private _alignItems: string;
|
||||||
private _alignContent: string;
|
private _alignContent: string;
|
||||||
|
private _textAlign: string;
|
||||||
private _height: string;
|
private _height: string;
|
||||||
private _width: string;
|
private _width: string;
|
||||||
|
|
||||||
@@ -65,6 +66,7 @@ export default class FlexContainer extends ContainerBase<FlexItemLayout> impleme
|
|||||||
this._justifyContent = layout.justifyContent ? layout.justifyContent : '';
|
this._justifyContent = layout.justifyContent ? layout.justifyContent : '';
|
||||||
this._alignItems = layout.alignItems ? layout.alignItems : '';
|
this._alignItems = layout.alignItems ? layout.alignItems : '';
|
||||||
this._alignContent = layout.alignContent ? layout.alignContent : '';
|
this._alignContent = layout.alignContent ? layout.alignContent : '';
|
||||||
|
this._textAlign = layout.textAlign ? layout.textAlign : '';
|
||||||
this._height = this.convertSize(layout.height);
|
this._height = this.convertSize(layout.height);
|
||||||
this._width = this.convertSize(layout.width);
|
this._width = this.convertSize(layout.width);
|
||||||
|
|
||||||
@@ -96,6 +98,10 @@ export default class FlexContainer extends ContainerBase<FlexItemLayout> impleme
|
|||||||
return this._alignContent;
|
return this._alignContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get textAlign(): string {
|
||||||
|
return this._textAlign;
|
||||||
|
}
|
||||||
|
|
||||||
private getItemFlex(item: FlexItem): string {
|
private getItemFlex(item: FlexItem): string {
|
||||||
return item.config ? item.config.flex : '1 1 auto';
|
return item.config ? item.config.flex : '1 1 auto';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
@@ -16,13 +17,18 @@ import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboar
|
|||||||
import { ContainerBase } from 'sql/parts/modelComponents/componentBase';
|
import { ContainerBase } from 'sql/parts/modelComponents/componentBase';
|
||||||
import { ModelComponentWrapper } from 'sql/parts/modelComponents/modelComponentWrapper.component';
|
import { ModelComponentWrapper } from 'sql/parts/modelComponents/modelComponentWrapper.component';
|
||||||
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
|
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
|
||||||
|
import { getContentHeight, getContentWidth, Dimension } from 'vs/base/browser/dom';
|
||||||
|
|
||||||
export interface TitledFormItemLayout {
|
export interface TitledFormItemLayout {
|
||||||
title: string;
|
title: string;
|
||||||
actions?: string[];
|
actions?: string[];
|
||||||
isFormComponent: Boolean;
|
isFormComponent: Boolean;
|
||||||
horizontal: boolean;
|
horizontal: boolean;
|
||||||
componentWidth: number;
|
componentWidth?: number | string;
|
||||||
|
componentHeight?: number | string;
|
||||||
|
titleFontSize?: number | string;
|
||||||
|
required?: boolean;
|
||||||
|
info?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FormLayout {
|
export interface FormLayout {
|
||||||
@@ -35,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)">
|
<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)}">
|
||||||
@@ -56,10 +65,13 @@ class FormItem {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<div class="form-vertical-container" *ngIf="isVertical(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)">
|
||||||
<div class="form-item-row" [style.width]="getComponentWidth(item)">
|
{{getItemTitle(item)}}<span class="form-required" *ngIf="isItemRequired(item)">*</span>
|
||||||
<model-component-wrapper [descriptor]="item.descriptor" [modelStore]="modelStore" [style.width]="getComponentWidth(item)">
|
<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)">
|
||||||
|
<model-component-wrapper [descriptor]="item.descriptor" [modelStore]="modelStore" [style.width]="getComponentWidth(item)" [style.height]="getRowHeight(item)">
|
||||||
</model-component-wrapper>
|
</model-component-wrapper>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="itemHasActions(item)" class="form-item-row form-actions-table form-item-last-row">
|
<div *ngIf="itemHasActions(item)" class="form-item-row form-actions-table form-item-last-row">
|
||||||
@@ -101,6 +113,10 @@ export default class FormContainer extends ContainerBase<FormItemLayout> impleme
|
|||||||
ngAfterViewInit(): void {
|
ngAfterViewInit(): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public layout(): void {
|
||||||
|
super.layout();
|
||||||
|
}
|
||||||
|
|
||||||
/// IComponent implementation
|
/// IComponent implementation
|
||||||
|
|
||||||
public get alignItems(): string {
|
public get alignItems(): string {
|
||||||
@@ -112,23 +128,53 @@ export default class FormContainer extends ContainerBase<FormItemLayout> impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
private getFormWidth(): string {
|
private getFormWidth(): string {
|
||||||
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, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
private getComponentWidth(item: FormItem): string {
|
private getComponentWidth(item: FormItem): string {
|
||||||
let itemConfig = item.config;
|
let itemConfig = item.config;
|
||||||
return (itemConfig && itemConfig.componentWidth) ? itemConfig.componentWidth + 'px' : '';
|
return (itemConfig && itemConfig.componentWidth) ? this.convertSize(itemConfig.componentWidth, '') : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getRowHeight(item: FormItem): string {
|
||||||
|
let itemConfig = item.config;
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import { RowSelectionModel } from 'sql/base/browser/ui/table/plugins/rowSelectio
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'modelview-table',
|
selector: 'modelview-table',
|
||||||
template: `
|
template: `
|
||||||
<div #table style="width: 100%"></div>
|
<div #table style="width: 100%;height:100%"></div>
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
export default class TableComponent extends ComponentBase implements IComponent, OnDestroy, AfterViewInit {
|
export default class TableComponent extends ComponentBase implements IComponent, OnDestroy, AfterViewInit {
|
||||||
@@ -92,9 +92,8 @@ export default class TableComponent extends ComponentBase implements IComponent,
|
|||||||
let options = <Slick.GridOptions<any>>{
|
let options = <Slick.GridOptions<any>>{
|
||||||
syncColumnCellResize: true,
|
syncColumnCellResize: true,
|
||||||
enableColumnReorder: false,
|
enableColumnReorder: false,
|
||||||
rowHeight: 45,
|
|
||||||
enableCellNavigation: true,
|
enableCellNavigation: true,
|
||||||
forceFitColumns: true
|
forceFitColumns: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
this._table = new Table<Slick.SlickData>(this._inputContainer.nativeElement, this._tableData, this._tableColumns, options);
|
this._table = new Table<Slick.SlickData>(this._inputContainer.nativeElement, this._tableData, this._tableColumns, options);
|
||||||
|
|||||||
@@ -19,8 +19,10 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
|||||||
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
|
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||||
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
|
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
|
||||||
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
||||||
|
import { IObjectExplorerService } from '../../objectExplorer/common/objectExplorerService';
|
||||||
import { ProfilerInput } from 'sql/parts/profiler/editor/profilerInput';
|
import { ProfilerInput } from 'sql/parts/profiler/editor/profilerInput';
|
||||||
import { TPromise } from 'vs/base/common/winjs.base';
|
import { TPromise } from 'vs/base/common/winjs.base';
|
||||||
|
import * as TaskUtilities from 'sql/workbench/common/taskUtilities';
|
||||||
|
|
||||||
// Contribute Global Actions
|
// Contribute Global Actions
|
||||||
const category = nls.localize('profilerCategory', "Profiler");
|
const category = nls.localize('profilerCategory', "Profiler");
|
||||||
@@ -37,20 +39,9 @@ CommandsRegistry.registerCommand({
|
|||||||
let editorService: IWorkbenchEditorService = accessor.get(IWorkbenchEditorService);
|
let editorService: IWorkbenchEditorService = accessor.get(IWorkbenchEditorService);
|
||||||
let instantiationService: IInstantiationService = accessor.get(IInstantiationService);
|
let instantiationService: IInstantiationService = accessor.get(IInstantiationService);
|
||||||
let connectionService: IConnectionManagementService = accessor.get(IConnectionManagementService);
|
let connectionService: IConnectionManagementService = accessor.get(IConnectionManagementService);
|
||||||
|
let objectExplorerService: IObjectExplorerService = accessor.get(IObjectExplorerService);
|
||||||
|
|
||||||
// TODO: for test-only, grab the first MSSQL active connection for the profiler session
|
let connectionProfile = TaskUtilities.getCurrentGlobalConnection(objectExplorerService, connectionService, editorService);
|
||||||
// TODO: when finishing the feature the connection should come from the launch context
|
|
||||||
let connectionProfile: IConnectionProfile;
|
|
||||||
let activeConnections = connectionService.getActiveConnections();
|
|
||||||
if (activeConnections) {
|
|
||||||
for (let i = 0; i < activeConnections.length; ++i) {
|
|
||||||
if (activeConnections[i].providerName === 'MSSQL') {
|
|
||||||
connectionProfile = activeConnections[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let profilerInput = instantiationService.createInstance(ProfilerInput, connectionProfile);
|
let profilerInput = instantiationService.createInstance(ProfilerInput, connectionProfile);
|
||||||
return editorService.openEditor(profilerInput, { pinned: true }, false).then(() => TPromise.as(true));
|
return editorService.openEditor(profilerInput, { pinned: true }, false).then(() => TPromise.as(true));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -202,8 +202,6 @@ export class ProfilerEditor extends BaseEditor {
|
|||||||
this._register(attachSelectBoxStyler(this._sessionTemplateSelector, this.themeService));
|
this._register(attachSelectBoxStyler(this._sessionTemplateSelector, this.themeService));
|
||||||
|
|
||||||
this._actionBar.setContent([
|
this._actionBar.setContent([
|
||||||
{ action: this._connectAction },
|
|
||||||
{ element: Taskbar.createTaskbarSeparator() },
|
|
||||||
{ action: this._startAction },
|
{ action: this._startAction },
|
||||||
{ action: this._stopAction },
|
{ action: this._stopAction },
|
||||||
{ element: dropdownContainer },
|
{ element: dropdownContainer },
|
||||||
@@ -386,21 +384,20 @@ export class ProfilerEditor extends BaseEditor {
|
|||||||
|
|
||||||
if (e.isConnected) {
|
if (e.isConnected) {
|
||||||
this._connectAction.connected = this.input.state.isConnected;
|
this._connectAction.connected = this.input.state.isConnected;
|
||||||
this._startAction.enabled = this.input.state.isConnected;
|
|
||||||
this._stopAction.enabled = false;
|
|
||||||
this._pauseAction.enabled = false;
|
|
||||||
|
|
||||||
if (this.input.state.isConnected) {
|
if (this.input.state.isConnected) {
|
||||||
this._sessionTemplateSelector.disable();
|
this._sessionTemplateSelector.disable();
|
||||||
} else {
|
} else {
|
||||||
this._sessionTemplateSelector.enable();
|
this._sessionTemplateSelector.enable();
|
||||||
|
this._startAction.enabled = this.input.state.isConnected;
|
||||||
|
this._stopAction.enabled = false;
|
||||||
|
this._pauseAction.enabled = false;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.isPaused){
|
if (e.isPaused){
|
||||||
this._pauseAction.paused = this.input.state.isPaused;
|
this._pauseAction.paused = this.input.state.isPaused;
|
||||||
|
this._pauseAction.enabled = !this.input.state.isStopped && (this.input.state.isRunning || this.input.state.isPaused);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.isStopped || e.isRunning) {
|
if (e.isStopped || e.isRunning) {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
|
|||||||
import { EditorInput } from 'vs/workbench/common/editor';
|
import { EditorInput } from 'vs/workbench/common/editor';
|
||||||
import { IEditorModel } from 'vs/platform/editor/common/editor';
|
import { IEditorModel } from 'vs/platform/editor/common/editor';
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||||
import { Event, Emitter } from 'vs/base/common/event';
|
import { Event, Emitter } from 'vs/base/common/event';
|
||||||
import { generateUuid } from 'vs/base/common/uuid';
|
import { generateUuid } from 'vs/base/common/uuid';
|
||||||
|
|
||||||
@@ -35,14 +36,15 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
|||||||
constructor(
|
constructor(
|
||||||
private _connection: IConnectionProfile,
|
private _connection: IConnectionProfile,
|
||||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||||
@IProfilerService private _profilerService: IProfilerService
|
@IProfilerService private _profilerService: IProfilerService,
|
||||||
|
@INotificationService private _notificationService: INotificationService
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this._state = new ProfilerState();
|
this._state = new ProfilerState();
|
||||||
// set inital state
|
// set inital state
|
||||||
this.state.change({
|
this.state.change({
|
||||||
isConnected: true,
|
isConnected: true,
|
||||||
isStopped: false,
|
isStopped: true,
|
||||||
isPaused: false,
|
isPaused: false,
|
||||||
isRunning: false,
|
isRunning: false,
|
||||||
autoscroll: true
|
autoscroll: true
|
||||||
@@ -123,7 +125,21 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
|||||||
return this._state;
|
return this._state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public onSessionStopped(notification: sqlops.ProfilerSessionStoppedParams) {
|
||||||
|
this._notificationService.error(nls.localize("profiler.sessionStopped", "XEvent Profiler Session stopped unexpectedly on the server {0}.", this._connection.serverName));
|
||||||
|
|
||||||
|
this.state.change({
|
||||||
|
isStopped: true,
|
||||||
|
isPaused: false,
|
||||||
|
isRunning: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public onMoreRows(eventMessage: sqlops.ProfilerSessionEvents) {
|
public onMoreRows(eventMessage: sqlops.ProfilerSessionEvents) {
|
||||||
|
if (eventMessage.eventsLost){
|
||||||
|
this._notificationService.warn(nls.localize("profiler.eventsLost", "The XEvent Profiler session for {0} has lost events.", this._connection.serverName));
|
||||||
|
}
|
||||||
|
|
||||||
for (let i: number = 0; i < eventMessage.events.length && i < 500; ++i) {
|
for (let i: number = 0; i < eventMessage.events.length && i < 500; ++i) {
|
||||||
let e: sqlops.ProfilerEvent = eventMessage.events[i];
|
let e: sqlops.ProfilerEvent = eventMessage.events[i];
|
||||||
let data = {};
|
let data = {};
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ export interface IProfilerSession {
|
|||||||
* Called by the service when more rows are available to render
|
* Called by the service when more rows are available to render
|
||||||
*/
|
*/
|
||||||
onMoreRows(events: sqlops.ProfilerSessionEvents);
|
onMoreRows(events: sqlops.ProfilerSessionEvents);
|
||||||
|
/**
|
||||||
|
* Called by the service when the session is closed unexpectedly
|
||||||
|
*/
|
||||||
|
onSessionStopped(events: sqlops.ProfilerSessionStoppedParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,6 +69,10 @@ export interface IProfilerService {
|
|||||||
* The method called by the service provider for when more rows are available to render
|
* The method called by the service provider for when more rows are available to render
|
||||||
*/
|
*/
|
||||||
onMoreRows(params: sqlops.ProfilerSessionEvents): void;
|
onMoreRows(params: sqlops.ProfilerSessionEvents): void;
|
||||||
|
/**
|
||||||
|
* The method called by the service provider for when more rows are available to render
|
||||||
|
*/
|
||||||
|
onSessionStopped(params: sqlops.ProfilerSessionStoppedParams): void;
|
||||||
/**
|
/**
|
||||||
* Gets a list of the session templates that are specified in the settings
|
* Gets a list of the session templates that are specified in the settings
|
||||||
* @param provider An optional string to limit the session template to a specific
|
* @param provider An optional string to limit the session template to a specific
|
||||||
|
|||||||
@@ -82,6 +82,11 @@ export class ProfilerService implements IProfilerService {
|
|||||||
this._sessionMap.get(this._idMap.reverseGet(params.sessionId)).onMoreRows(params);
|
this._sessionMap.get(this._idMap.reverseGet(params.sessionId)).onMoreRows(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public onSessionStopped(params: sqlops.ProfilerSessionStoppedParams): void {
|
||||||
|
|
||||||
|
this._sessionMap.get(this._idMap.reverseGet(params.ownerUri)).onSessionStopped(params);
|
||||||
|
}
|
||||||
|
|
||||||
public connectSession(id: ProfilerSessionID): Thenable<boolean> {
|
public connectSession(id: ProfilerSessionID): Thenable<boolean> {
|
||||||
return this._runAction(id, provider => provider.connectSession(this._idMap.get(id)));
|
return this._runAction(id, provider => provider.connectSession(this._idMap.get(id)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,10 @@ export class ProfilerTestBackend implements sqlops.ProfilerProvider {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
registerOnSessionStopped(handler: (response: sqlops.ProfilerSessionStoppedParams) => any) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
private intervalFn(guid: string): number {
|
private intervalFn(guid: string): number {
|
||||||
return setTimeout(() => {
|
return setTimeout(() => {
|
||||||
let data = this.testData[this.index++];
|
let data = this.testData[this.index++];
|
||||||
|
|||||||
@@ -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';
|
||||||
@@ -67,6 +68,7 @@ export class DialogPane extends Disposable implements IThemable {
|
|||||||
this._body.appendChild(tabContainer);
|
this._body.appendChild(tabContainer);
|
||||||
this.initializeModelViewContainer(tabContainer, tab.content, tab);
|
this.initializeModelViewContainer(tabContainer, tab.content, tab);
|
||||||
this._tabbedPanel.onTabChange(e => {
|
this._tabbedPanel.onTabChange(e => {
|
||||||
|
tabContainer.style.height = (this.getTabDimension().height - this._tabbedPanel.headersize) + 'px';
|
||||||
this._onTabChange.fire(tab.content);
|
this._onTabChange.fire(tab.content);
|
||||||
});
|
});
|
||||||
this._tabbedPanel.pushTab({
|
this._tabbedPanel.pushTab({
|
||||||
@@ -91,7 +93,7 @@ export class DialogPane extends Disposable implements IThemable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private getTabDimension(): DOM.Dimension {
|
private getTabDimension(): DOM.Dimension {
|
||||||
return new DOM.Dimension(DOM.getContentWidth(this._body), DOM.getContentHeight(this._body))
|
return new DOM.Dimension(DOM.getContentWidth(this._body), DOM.getContentHeight(this._body));
|
||||||
}
|
}
|
||||||
|
|
||||||
public layout(): void {
|
public layout(): void {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
10
src/sql/sqlops.d.ts
vendored
10
src/sql/sqlops.d.ts
vendored
@@ -1409,6 +1409,7 @@ declare module 'sqlops' {
|
|||||||
disconnectSession(sessionId: string): Thenable<boolean>;
|
disconnectSession(sessionId: string): Thenable<boolean>;
|
||||||
|
|
||||||
registerOnSessionEventsAvailable(handler: (response: ProfilerSessionEvents) => any): void;
|
registerOnSessionEventsAvailable(handler: (response: ProfilerSessionEvents) => any): void;
|
||||||
|
registerOnSessionStopped(handler: (response: ProfilerSessionStoppedParams) => any): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IProfilerTableRow {
|
export interface IProfilerTableRow {
|
||||||
@@ -1449,6 +1450,15 @@ declare module 'sqlops' {
|
|||||||
sessionId: string;
|
sessionId: string;
|
||||||
|
|
||||||
events: ProfilerEvent[];
|
events: ProfilerEvent[];
|
||||||
|
|
||||||
|
eventsLost: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProfilerSessionStoppedParams {
|
||||||
|
|
||||||
|
ownerUri: string;
|
||||||
|
|
||||||
|
sessionId: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// File browser interfaces -----------------------------------------------------------------------
|
// File browser interfaces -----------------------------------------------------------------------
|
||||||
|
|||||||
83
src/sql/sqlops.proposed.d.ts
vendored
83
src/sql/sqlops.proposed.d.ts
vendored
@@ -216,6 +216,11 @@ declare module 'sqlops' {
|
|||||||
* Container Width
|
* Container Width
|
||||||
*/
|
*/
|
||||||
width?: number | string;
|
width?: number | string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
textAlign?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FlexItemLayout {
|
export interface FlexItemLayout {
|
||||||
@@ -232,12 +237,17 @@ declare module 'sqlops' {
|
|||||||
|
|
||||||
export interface FormItemLayout {
|
export interface FormItemLayout {
|
||||||
horizontal?: boolean;
|
horizontal?: boolean;
|
||||||
componentWidth?: number;
|
componentWidth?: 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 {
|
||||||
@@ -290,22 +300,35 @@ 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';
|
||||||
|
|
||||||
export interface ComponentProperties {
|
export interface ComponentProperties {
|
||||||
height: number | string;
|
height?: number | string;
|
||||||
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 {
|
||||||
@@ -354,7 +377,7 @@ declare module 'sqlops' {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface DropDownProperties extends ComponentProperties {
|
export interface DropDownProperties extends ComponentProperties {
|
||||||
value?: string;
|
value?: string | CategoryValue;
|
||||||
values?: string[] | CategoryValue[];
|
values?: string[] | CategoryValue[];
|
||||||
editable?: boolean;
|
editable?: boolean;
|
||||||
}
|
}
|
||||||
@@ -383,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 {
|
||||||
@@ -418,7 +438,7 @@ declare module 'sqlops' {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface DropDownComponent extends Component, DropDownProperties {
|
export interface DropDownComponent extends Component, DropDownProperties {
|
||||||
value: string;
|
value: string | CategoryValue;
|
||||||
values: string[] | CategoryValue[];
|
values: string[] | CategoryValue[];
|
||||||
onValueChanged: vscode.Event<any>;
|
onValueChanged: vscode.Event<any>;
|
||||||
}
|
}
|
||||||
@@ -576,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.
|
||||||
@@ -626,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 {
|
||||||
@@ -792,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'
|
||||||
}
|
}
|
||||||
@@ -518,6 +518,13 @@ export class ExtHostDataProtocol extends ExtHostDataProtocolShape {
|
|||||||
this._proxy.$onSessionEventsAvailable(handle, response);
|
this._proxy.$onSessionEventsAvailable(handle, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Profiler session stopped unexpectedly notification
|
||||||
|
*/
|
||||||
|
public $onSessionStopped(handle: number, response: sqlops.ProfilerSessionStoppedParams): void {
|
||||||
|
this._proxy.$onSessionStopped(handle, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Agent Job Provider methods
|
* Agent Job Provider methods
|
||||||
|
|||||||
@@ -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 {
|
||||||
@@ -771,10 +819,14 @@ class DropDownWrapper extends ComponentWrapper implements sqlops.DropDownCompone
|
|||||||
this._emitterMap.set(ComponentEventType.onDidChange, new Emitter<any>());
|
this._emitterMap.set(ComponentEventType.onDidChange, new Emitter<any>());
|
||||||
}
|
}
|
||||||
|
|
||||||
public get value(): string {
|
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) {
|
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
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -432,6 +432,10 @@ export class MainThreadDataProtocol implements MainThreadDataProtocolShape {
|
|||||||
this._profilerService.onMoreRows(response);
|
this._profilerService.onMoreRows(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public $onSessionStopped(handle: number, response: sqlops.ProfilerSessionStoppedParams): void {
|
||||||
|
this._profilerService.onSessionStopped(response);
|
||||||
|
}
|
||||||
|
|
||||||
public $unregisterProvider(handle: number): TPromise<any> {
|
public $unregisterProvider(handle: number): TPromise<any> {
|
||||||
let capabilitiesRegistration = this._capabilitiesRegistrations[handle];
|
let capabilitiesRegistration = this._capabilitiesRegistrations[handle];
|
||||||
if (capabilitiesRegistration) {
|
if (capabilitiesRegistration) {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -237,6 +237,10 @@ export function createApiFactory(
|
|||||||
extHostDataProvider.$onSessionEventsAvailable(provider.handle, response);
|
extHostDataProvider.$onSessionEventsAvailable(provider.handle, response);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
provider.registerOnSessionStopped((response: sqlops.ProfilerSessionStoppedParams) => {
|
||||||
|
extHostDataProvider.$onSessionStopped(provider.handle, response);
|
||||||
|
});
|
||||||
|
|
||||||
return extHostDataProvider.$registerProfilerProvider(provider);
|
return extHostDataProvider.$registerProfilerProvider(provider);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -311,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 = {
|
||||||
@@ -386,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
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -416,6 +416,7 @@ export interface MainThreadDataProtocolShape extends IDisposable {
|
|||||||
$onFilePathsValidated(handle: number, response: sqlops.FileBrowserValidatedParams): void;
|
$onFilePathsValidated(handle: number, response: sqlops.FileBrowserValidatedParams): void;
|
||||||
$onScriptingComplete(handle: number, message: sqlops.ScriptingCompleteResult): void;
|
$onScriptingComplete(handle: number, message: sqlops.ScriptingCompleteResult): void;
|
||||||
$onSessionEventsAvailable(handle: number, response: sqlops.ProfilerSessionEvents): void;
|
$onSessionEventsAvailable(handle: number, response: sqlops.ProfilerSessionEvents): void;
|
||||||
|
$onSessionStopped(handle: number, response: sqlops.ProfilerSessionStoppedParams): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback when a session has completed initialization
|
* Callback when a session has completed initialization
|
||||||
@@ -562,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 {
|
||||||
|
|||||||
@@ -29,14 +29,14 @@ export class OpenGettingStartedInBrowserAction extends Action {
|
|||||||
}
|
}
|
||||||
|
|
||||||
run(): TPromise<any> {
|
run(): TPromise<any> {
|
||||||
const uri = URI.parse(product.releaseNotesUrl);
|
const uri = URI.parse(product.gettingStartedUrl);
|
||||||
return this.openerService.open(uri);
|
return this.openerService.open(uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ShowCurrentReleaseNotesAction extends AbstractShowReleaseNotesAction {
|
export class ShowCurrentReleaseNotesAction extends AbstractShowReleaseNotesAction {
|
||||||
|
|
||||||
static ID = 'update.showCurrentCarbonReleaseNotes';
|
static ID = 'update.showGettingStarted';
|
||||||
static LABEL = nls.localize('showReleaseNotes', "Show Getting Started");
|
static LABEL = nls.localize('showReleaseNotes', "Show Getting Started");
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
|||||||
@@ -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());
|
||||||
|
});
|
||||||
});
|
});
|
||||||
@@ -397,8 +397,16 @@ export class SelectBoxList implements ISelectBoxDelegate, IDelegate<ISelectOptio
|
|||||||
container.appendChild(this.selectDropDownContainer);
|
container.appendChild(this.selectDropDownContainer);
|
||||||
|
|
||||||
this.layoutSelectDropDown();
|
this.layoutSelectDropDown();
|
||||||
|
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
return {
|
return {
|
||||||
dispose: () => container.removeChild(this.selectDropDownContainer) // remove to take out the CSS rules we add
|
dispose: () => {
|
||||||
|
try {
|
||||||
|
container.removeChild(this.selectDropDownContainer); // remove to take out the CSS rules we add
|
||||||
|
} catch(e) {
|
||||||
|
// if this fails it means it is already removed
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -999,8 +999,8 @@ export class CodeMenu {
|
|||||||
arrays.coalesce([
|
arrays.coalesce([
|
||||||
// new MenuItem({ label: mnemonicLabel(nls.localize({ key: 'miWelcome', comment: ['&& denotes a mnemonic'] }, "&&Welcome")), click: () => this.windowsService.sendToFocused('vscode:runAction', 'workbench.action.showWelcomePage') }),
|
// new MenuItem({ label: mnemonicLabel(nls.localize({ key: 'miWelcome', comment: ['&& denotes a mnemonic'] }, "&&Welcome")), click: () => this.windowsService.sendToFocused('vscode:runAction', 'workbench.action.showWelcomePage') }),
|
||||||
// {{SQL CARBON EDIT}}
|
// {{SQL CARBON EDIT}}
|
||||||
product.releaseNotesUrl ?
|
product.gettingStartedUrl ?
|
||||||
this.createMenuItem(nls.localize({ key: 'miReleaseNotes', comment: ['&& denotes a mnemonic'] }, "Getting &&Started"), 'update.showCurrentCarbonReleaseNotes')
|
this.createMenuItem(nls.localize({ key: 'miGettingStarted', comment: ['&& denotes a mnemonic'] }, "Getting &&Started"), 'update.showGettingStarted')
|
||||||
: null,
|
: null,
|
||||||
product.documentationUrl ?
|
product.documentationUrl ?
|
||||||
this.createMenuItem(nls.localize({ key: 'miDocumentation', comment: ['&& denotes a mnemonic'] }, "&&Documentation"), 'workbench.action.openDocumentationUrl')
|
this.createMenuItem(nls.localize({ key: 'miDocumentation', comment: ['&& denotes a mnemonic'] }, "&&Documentation"), 'workbench.action.openDocumentationUrl')
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ export interface IProductConfiguration {
|
|||||||
};
|
};
|
||||||
documentationUrl: string;
|
documentationUrl: string;
|
||||||
releaseNotesUrl: string;
|
releaseNotesUrl: string;
|
||||||
|
// {SQL CARBON EDIT}
|
||||||
|
gettingStartedUrl: string;
|
||||||
keyboardShortcutsUrlMac: string;
|
keyboardShortcutsUrlMac: string;
|
||||||
keyboardShortcutsUrlLinux: string;
|
keyboardShortcutsUrlLinux: string;
|
||||||
keyboardShortcutsUrlWin: string;
|
keyboardShortcutsUrlWin: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user