Compare commits

...

62 Commits

Author SHA1 Message Date
Aditya Bist
8a3509e006 removed discontinued red bar from error detail (#1521) 2018-05-31 13:17:46 -07:00
Aditya Bist
1d3ead4031 fixed crash because of extra detect changes call (#1519) 2018-05-31 12:04:49 -07:00
Anthony Dresser
498bb47d7f Add progress indicator for dashboard scripting (#1511)
* add progress indicator for dashboard scripting

* formatting
2018-05-31 12:04:00 -07:00
Lance Klinger
f2df9f3917 Fix for double clicking column handle in results table where the column width would not update correctly when the longest row item is the top item in the viewPort (#1504) 2018-05-31 12:03:33 -07:00
Madeline MacDonald
0414ab6e6a Fixing launching new profiler from object explorer (#1514) 2018-05-30 16:39:11 -07:00
Matt Irvine
14a7a5534f Add API for extensions to get data protocol providers (#1518) 2018-05-30 16:37:11 -07:00
Karl Burtram
edc60e0ad1 Fix nullref exception showing query plan panel (#1516) 2018-05-30 14:30:14 -07:00
Abbie Petchtes
1a97e3de06 fix webview component css and add webview example (#1517) 2018-05-30 13:48:08 -07:00
Leila Lali
f5b1bd0bc2 fixed the issue with tab layout inside the dialog pane (#1515) 2018-05-30 13:02:19 -07:00
Aditya Bist
05d7e24e66 Agent UI fixes (#1510)
* added ellipses for long job names

* fixed resizing crash in jobs history page

* added some more ui fixes

* changed minWidths to widths

* code review comments
2018-05-30 10:53:36 -07:00
Leila Lali
83842ee9e1 fixed the path to fix the linux build error (#1512) 2018-05-30 09:53:30 -07:00
Leila Lali
a13039b14b added group container (#1508) 2018-05-29 13:08:13 -07:00
Leila Lali
8fce79f385 fixed the selector name for model view components (#1488) 2018-05-24 15:20:24 -07:00
Matt Irvine
2efea63000 Bump version to 0.30.3 2018-05-24 14:30:02 -07:00
Abbie Petchtes
c208abf0c5 Fix view model editor and webview component (#1483)
* destroy viewmodel when editor is closed and add example

* support retainContextWhenHidden option for webview component

* fix breaking change from master

* dispose html element during dispose

* add more comments
2018-05-24 13:54:41 -07:00
Anthony Dresser
1359354387 Angular Individual Service Injection - Decouple bootstrap service (#1457)
* change services to be individually injected into angular

* messing around with injection

* change angular bootstrapping to factory style

* formatting

* formatting

* fix imports

* fix build errors

* fix testsw

* fix tests

* fix compile errors
2018-05-23 16:51:02 -07:00
Abbie Petchtes
cd0f9b71c5 Fix view model editor layout (#1473)
* flex container should be as big as the parent container

* add example
2018-05-23 11:20:28 -07:00
Anthony Dresser
04ec9caad1 Remove Jquery references (#1461)
* modify key codes

* formatting

* change string event type

* code clean up
2018-05-23 10:59:28 -07:00
Leila Lali
259306a8db fixed the issue with setting form's width (#1472) 2018-05-23 10:23:03 -07:00
Abbie Petchtes
36a8991682 Feature/webview for model view (#1463)
* support webview for view model

* formatting

* remove unused imports
2018-05-23 09:51:44 -07:00
Leila Lali
1461929f86 added text component (#1462)
* added text component
2018-05-22 16:12:02 -07:00
Leila Lali
4bfc549927 model view drop down now support editable and not editable list (#1460)
* model view drop down now support editable and not editable list
2018-05-22 13:12:53 -07:00
Matt Irvine
40db0d6f6f Only allow model view components to be added once (#1458) 2018-05-22 13:06:00 -07:00
Karl Burtram
6aac0b6056 Initial Profiler extension scaffolding (#1451)
* Copy agent to profiler extension

* A few mote edits
2018-05-21 16:40:22 -07:00
Matt Irvine
8e234d9b2d Enable basic wizard API (#1450) 2018-05-21 15:19:21 -07:00
Abbie Petchtes
70819252a9 Add support for model view editor (#1442)
* Add proposed API for model view editors

* Initial working model view editor

* Add extension demo

* Revert "Add extension demo"

This reverts commit 10d3b720ad347919dd5668a339da8e96e26b2b82.

* view model editor and add the support for register content

* clean up the code

* fix editor issues where you register more than one content

* formating

* remove unused imports

* addressed comments

* address comments2

* address comment3
2018-05-21 12:46:13 -07:00
Leila Lali
ba264d8311 added radio button model view component (#1439)
* added radio button model view component
2018-05-21 11:45:27 -07:00
Karl Burtram
5de002e5c1 Change VS Code to SQL Ops Studio in screen reader dialog (#1448) 2018-05-21 10:45:39 -07:00
Karl Burtram
0b771abad2 Bump SQL Tools to 1.4.0-alpha.35 (#1447) 2018-05-18 16:27:04 -07:00
Anthony Dresser
00041c8ecd nump slickgrid (#1428) 2018-05-18 13:52:38 -07:00
Anthony Dresser
0225d6d9f9 adds tab accessibility (#1433) 2018-05-18 13:52:22 -07:00
Matt Irvine
fb4260d71c Bump tools service for recent fixes (#1434) 2018-05-17 09:55:01 -07:00
Karl Burtram
fa253158f4 Update SQL Ops to 0.30.2 (#1437) 2018-05-16 18:28:28 -07:00
Leila Lali
45e3c6ae49 added register content method to dialog and tab (#1415)
* added register content method to dialog and tab
2018-05-16 09:09:41 -07:00
Matt Irvine
d526fe0f7f Fire model view close event when destroyed (#1427) 2018-05-15 17:35:31 -07:00
Kevin Cunnane
5707b58fda Make Webview support (#1429)
This is needed to enable testing of webview-based experiences.

This was made an official API in the latest VSCode release, so on next merge this will be standard anyhow.
2018-05-15 16:37:52 -07:00
Matt Irvine
1a9f72dfe0 Rearrange done and cancel buttons and dispose dialogs correctly (#1420) 2018-05-15 15:39:27 -07:00
Karl Burtram
078f3a2b54 Add BETWEEN and REVERT to keyword colorization list (#1421) 2018-05-15 12:05:59 -07:00
Kevin Cunnane
5bcfb9ab32 Minor fix: callback data can be anything, shouldn't restrict to string (#1404) 2018-05-14 17:20:56 -07:00
Matt Irvine
9bd45cf66a Add default model view input types and validation (#1397) 2018-05-14 16:20:19 -07:00
Cory Rivera
89c48bbe75 Add option for using generic SQL queries to filter EditData rows via a query editor pane. (#1329) 2018-05-14 12:27:55 -07:00
Abbie Petchtes
6b549696c5 Bug/keyboard issue in manange linked account (#1400)
* add message and add account button when the linked account is empty

* fix account dialog tests

* address comment
2018-05-14 11:25:13 -07:00
Matt Irvine
3aaf8a24bf Fix form layout spacing (#1401) 2018-05-14 11:06:50 -07:00
Kevin Cunnane
41ffd6e8ae Add action list to cards with callback (#1392)
- Add the ActionDescriptor functionality. This is a table of information with actionable links
- Also add optional status indicator which shows a color. In the future, would like to extend to have icon in this space as an alternative.
- Fixed 1 issue with account management UI throwing an error on cancel
2018-05-11 10:59:42 -07:00
Abbie Petchtes
c0a6f3e012 fix theming issue in table widget (#1391) 2018-05-11 09:52:58 -07:00
Abbie Petchtes
eae8de0373 Add grid.viewAsChart and grid.goToNextGrid keyboard shortcuts for editor (#1390)
* adding shortcuts for view as chart and go to next grid

* small fix

* refactor query output functions out of gridParentComponents

* Revert "refactor query output functions out of gridParentComponents"

This reverts commit 51addcac76d2a21df150a8d95f54f061aab6ac7a.
2018-05-11 09:38:14 -07:00
Anthony Dresser
23ec6ac567 Change angular panel display behavior (#1344)
* got it working

* remove unneeded code

* formatting

* added scrollable, dashboard tabs don't scroll correctly though

* fix all bugs I could find

* address comments
2018-05-10 09:27:41 -07:00
Matt Irvine
f4cfb4a5ef Fire done/cancel click events when dialog is closed (#1379) 2018-05-09 13:17:02 -07:00
Abbie Petchtes
80a9c82813 Fix high contrast issues in task viewlet and panel (#1381)
* fix high contrast issues in task and panel

* change the panelTitle.inactiveForeground color in light theme

* remove opacity when the panel is active and inactive
2018-05-09 12:32:03 -07:00
Leila Lali
bcd6178d67 added properties to inputbox and form to be able to change style fro… (#1371)
* added properties to inputbox and form to be able to change style from extension
* moved registerModelViewProvider from dashboard to ui namespace
2018-05-09 10:58:23 -07:00
Matt Irvine
f10e281ffc Add validation to model view components (#1356) 2018-05-08 14:15:26 -07:00
Karl Burtram
c2b32fd64a Bump SQL Ops to 0.30.1 (#1369) 2018-05-08 13:02:14 -07:00
Karl Burtram
80f150dfb4 Update README for May release (#1359) 2018-05-07 09:27:38 -07:00
Aditya Bist
a5c5fcbde1 fixed tabbing for jobs history page (#1353) 2018-05-05 11:10:44 -07:00
Abbie Petchtes
0d76e845d5 update server reports extension screenshot (#1354) 2018-05-04 15:09:20 -07:00
Abbie Petchtes
979d50eb0e Add left nav bar for server reports extension (#1345)
* add left nav bar for server reports extension

* change monitor icon

* change performance icons
2018-05-04 14:57:01 -07:00
Karl Burtram
7099922c35 Bump SQL Ops to 0.29.3 (#1349) 2018-05-03 22:00:52 -07:00
Karl Burtram
b54b4a4445 Fix a null ref exception in dashboard layout (#1348) 2018-05-03 21:57:17 -07:00
Aditya Bist
03989a5af0 Fix scrolling in Jobs view page (#1346)
* resize when window resized

* fix scrolling issues
2018-05-03 21:39:22 -07:00
Leila Lali
1847c2e322 added checkbox component (#1330) 2018-05-03 17:11:55 -07:00
Karl Burtram
f7371e9ed5 Update SQL Agent extension readme and version (#1343) 2018-05-03 17:08:04 -07:00
Abbie Petchtes
f696274740 Add details for each chart and update README (#1341)
* add details for each chart and update readme

* update README
2018-05-03 13:19:16 -07:00
221 changed files with 10310 additions and 2209 deletions

View File

@@ -1,5 +1,20 @@
# Change Log
## Version 0.29.3
* Release date: May 7, 2018
* Release status: Public Preview
## What's new in this version
The May release is focused on stabilization and bug fixes leading up to the Build conference. This build contains the following highlights.
* Announcing **Redgate SQL Search** extension available in Extension Manager
* Community Localization available for 10 languages: **German, Spanish, French, Italian, Japanese, Korean, Portuguese, Russian, Simplified Chinese and Traditional Chinese!**
* **GDPR-compliant** build has reduced telemetry collection, improved [opt-out](https://github.com/Microsoft/sqlopsstudio/wiki/How-to-Disable-Telemetry-Reporting) experience and in-product links to [Privacy Statement](https://privacy.microsoft.com/en-us/privacystatement)
* Extension Manager has improved Marketplace experience to easily discover community extensions
* SQL Agent extension Jobs and Job History view improvement
* Updates for **whoisactive** and **Server Reports** extensions
* Continue to fix GitHub issues
## Version 0.28.6
* Release date: April 25, 2018
* Release status: Public Preview

View File

@@ -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.
**Download SQL Operations Studio March Public Preview**
**Download SQL Operations Studio May Public Preview**
Platform | Link
-- | --
Windows Setup Installer | https://go.microsoft.com/fwlink/?linkid=872717
Windows ZIP | https://go.microsoft.com/fwlink/?linkid=872718
macOS ZIP | https://go.microsoft.com/fwlink/?linkid=872719
Linux TAR.GZ | https://go.microsoft.com/fwlink/?linkid=872720
Linux DEB | https://go.microsoft.com/fwlink/?linkid=872722
Linux RPM | https://go.microsoft.com/fwlink/?linkid=872721
Windows Setup Installer | https://go.microsoft.com/fwlink/?linkid=873386
Windows ZIP | https://go.microsoft.com/fwlink/?linkid=873387
macOS ZIP | https://go.microsoft.com/fwlink/?linkid=873388
Linux TAR.GZ | https://go.microsoft.com/fwlink/?linkid=873389
Linux RPM | https://go.microsoft.com/fwlink/?linkid=873390
Linux DEB | https://go.microsoft.com/fwlink/?linkid=873391
Go to our [download page](https://aka.ms/sqlopsstudio) for more specific instructions.
@@ -74,7 +74,18 @@ We would like to thank all our users who raised issues, and in particular the fo
* SebastianPfliegel `Remove sqlExtensionHelp (#312)`
* olljanat for `Implemented npm version check (#314)`
* Adam Mechanic for helping with the `whoisactive` extension
* All community localization contributors *(will get list of individuals next month)*
* All community localization contributors
* French: Adrien Clerbois, ANAS BELABBES, Antoine Griffard, Arian Papillon, Eric Macarez, Eric Van Thorre, Jérémy LANDON, Matthias GROSPERRIN, Maxime COQUEREL, Olivier Guinart, thierry DEMAN-BARCELÒ, Thomas Potier
* Italian: Aldo Donetti, Alessandro Alpi, Andrea Dottor, Bruni Luca, Gianluca Hotz, Luca Nardi, Luigi Bruno, Marco Dal Pino, Mirco Vanini, Pasquale Ceglie, Riccardo Cappello, Sergio Govoni, Stefano Demiliani
* German: Anna Henke-Gunvaldson, Ben Weissman, David Ullmer, J.M. ., Kai Modo, Konstantin Staschill, Kostja Klein, Lennart Trunk, Markus Ehrenmüller-Jensen, Mascha Kroenlein, Matthias Knoll, Mourad Louha, Thomas Hütter, Wolfgang Straßer
* Spanish: Alberto Poblacion, Andy Gonzalez, Carlos Mendible, Christian Araujo, Daniel D, Eickhel Mendoza, Ernesto Cardenas, Ivan Toledo Ivanovic, Fran Diaz, JESUS GIL, Jorge Serrano Pérez, José Saturnino Pimentel Juárez, Mauricio Hidalgo, Pablo Iglesias, Rikhardo Estrada Rdez, Thierry DEMAN, YOLANDA CUESTA ALTIERI
* Japanese: Fujio Kojima, Kazushi KAMEGAWA, Masayoshi Yamada, Masayuki Ozawa , Seiji Momoto, Takashi Kanai, Takayoshi Tanaka, Yoshihisa Ozaki, 庄垣内治
* Chinese (simplified): DAN YE, Joel Yang, Lynne Dong, RyanYu Zhang, Sheng Jiang, Wei Zhang, Zhiliang Xu
* Chinese (Traditional): Bruce Chen, Chiayi Yen, Kevin Yang, Winnie Lin, 保哥 Will, 謝政廷
* Korean: Do-Kyun Kim, Evelyn Kim, Helen Jung, Hong Jmee, jeongwoo choi, Jun Hyoung Lee, Jungsun Kim정선, Justin Yoo, Kavrith mucha, Kiwoong Youm, MinGyu Ju, MVP_JUNO BEA, Sejun Kim, SOONMAN KWON, sung man ko, Yeongrak Choi, younggun kim, Youngjae Kim, 소영 이
* Russian: Andrey Veselov, Anton Fontanov, Anton Savin, Elena Ostrovskaia, Igor Babichev, Maxim Zelensky, Rodion Fedechkin, Tasha T, Vladimir Zyryanov
* Portuguese Brazil: Daniel de Sousa, Diogo Duarte, Douglas Correa, Douglas Eccker, José Emanuel Mendes, Marcelo Fernandes, Marcondes Alexandre, Roberto Fonseca, Rodrigo Crespi
And of course we'd like to thank the authors of all upstream dependencies. Please see a full list in the [ThirdPartyNotices.txt](https://raw.githubusercontent.com/Microsoft/sqlopsstudio/master/ThirdPartyNotices.txt)

View File

@@ -77,7 +77,8 @@ const vsce = require('vsce');
const sqlBuiltInExtensions = [
// Add SQL built-in extensions here.
// the extension will be excluded from SQLOps package and will have separate vsix packages
'agent'
'agent',
'profiler'
];
const vscodeEntryPoints = _.flatten([

View File

@@ -37,9 +37,8 @@ exports.defaultLanguages = [
// languages requested by the community to non-stable builds
exports.extraLanguages = [
{ id: 'pt-br', folderName: 'ptb' },
// {{SQL CARBON EDIT}}
// { id: 'hu', folderName: 'hun' },
// { id: 'tr', folderName: 'trk' }
{ id: 'hu', folderName: 'hun' },
{ id: 'tr', folderName: 'trk' }
];
// non built-in extensions also that are transifex and need to be part of the language packs
var externalExtensionsWithTranslations = {

View File

@@ -35,7 +35,8 @@ const extensions = [
'merge-conflict',
'insights-default',
'account-provider-azure',
'agent'
'agent',
'profiler'
];
extensions.forEach(extension => yarnInstall(`extensions/${extension}`));

View File

@@ -1,13 +1,15 @@
# Microsoft SQL Server Agent for SQL Operations Studio
Welcome to Microsoft SQL Server Agent for SQL Operations Studio! An extension for managing and troubleshooting
SQL Server Agent jobs and configuration. The current is a very early release of this extension that provides
SQL Server Agent jobs and configuration. The current is an early release of this extension that provides
basic functionality for the following.
* List SQL Server Agent Jobs configured on a SQL Server
* View Job History with job execution results
* Basic Job Control to start and stop jobs
<img src="https://user-images.githubusercontent.com/599935/39215738-d3a52580-47cd-11e8-9788-b290048c270e.png" alt="SQL Agent" style="width:800px;"/>
## 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.

View File

@@ -2,7 +2,7 @@
"name": "agent",
"displayName": "SQL Server Agent",
"description": "Manage and troubleshoot SQL Server Agent jobs (early preview)",
"version": "0.28.1",
"version": "0.29.0",
"publisher": "Microsoft",
"preview": true,
"license": "https://raw.githubusercontent.com/Microsoft/sqlopsstudio/master/LICENSE.txt",
@@ -22,6 +22,9 @@
"type": "git",
"url": "https://github.com/Microsoft/sqlopsstudio.git"
},
"extensionDependencies": [
"Microsoft.mssql"
],
"contributes": {
"outputChannels": [
"sqlagent"

View File

@@ -658,7 +658,7 @@
}
},
"dependencies": {
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#0.1.5",
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#0.1.7",
"opener": "^1.4.3",
"service-downloader": "github:anthonydresser/service-downloader#0.1.2",
"vscode-extension-telemetry": "^0.0.15"

View File

@@ -1,6 +1,6 @@
{
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
"version": "1.4.0-alpha.30",
"version": "1.4.0-alpha.35",
"downloadFileNames": {
"Windows_86": "win-x86-netcoreapp2.1.zip",
"Windows_64": "win-x64-netcoreapp2.1.zip",

View File

@@ -49,9 +49,9 @@ core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#0.1.5":
version "0.1.5"
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/21b0bacfc759689a6c280408528c6029a21b1abf"
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#0.1.7":
version "0.1.7"
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/d50285b03d0d5073c086362c5c96afb279320607"
dependencies:
vscode-languageclient "3.5.0"

View File

@@ -0,0 +1,2 @@
client/src/**
client/tsconfig.json

View File

@@ -0,0 +1,25 @@
# SQL Server Profiler for SQL Operations Studio
Welcome to the SQL Server Profiler for SQL Operations Studio! The SQL Server Profiler extension provides a simple SQL Server tracing solution similar to SSMS Profiler except built using XEvents. SSMS Profiler is very easy to use and has good default values for the most common tracing configurations. The UX is optimized for browsing through events and viewing the associated T-SQL text. The SQL Server Profiler for SQL Operations Studio also assumes good default values for collecting T-SQL execution activities with an easy to use UX.
Common SQL Profiler use-cases taken from https://docs.microsoft.com/en-us/sql/tools/sql-server-profiler/sql-server-profiler.
- Stepping through problem queries to find the cause of the problem.
- Finding and diagnosing slow-running queries.
- Capturing the series of Transact-SQL statements that lead to a problem.
- Monitoring the performance of SQL Server to tune workloads.
- Correlating performance counters to diagnose problems.
## 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.
## Privacy Statement
The [Microsoft Enterprise and Developer Privacy Statement](https://privacy.microsoft.com/en-us/privacystatement) describes the privacy statement of this software.
## License
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the [Source EULA](https://raw.githubusercontent.com/Microsoft/sqlopsstudio/master/LICENSE.txt).

View File

@@ -0,0 +1,63 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as vscode from 'vscode';
import * as data from 'sqlops';
/**
* Wrapper class to act as a facade over VSCode and Data APIs and allow us to test / mock callbacks into
* this API from our code
*
* @export
* @class ApiWrapper
*/
export class ApiWrapper {
// Data APIs
public registerWebviewProvider(widgetId: string, handler: (webview: data.DashboardWebview) => void): void {
return data.dashboard.registerWebviewProvider(widgetId, handler);
}
public registerControlHostProvider(widgetId: string, handler: (webview: data.DashboardWebview) => void): void {
return data.dashboard.registerWebviewProvider(widgetId, handler);
}
/**
* Get the configuration for a extensionName
* @param extensionName The string name of the extension to get the configuration for
* @param resource The optional URI, as a URI object or a string, to use to get resource-scoped configurations
*/
public getConfiguration(extensionName: string, resource?: vscode.Uri | string): vscode.WorkspaceConfiguration {
if (typeof resource === 'string') {
try {
resource = this.parseUri(resource);
} catch (e) {
resource = undefined;
}
}
return vscode.workspace.getConfiguration(extensionName, resource as vscode.Uri);
}
/**
* Parse uri
*/
public parseUri(uri: string): vscode.Uri {
return vscode.Uri.parse(uri);
}
public showOpenDialog(options: vscode.OpenDialogOptions): Thenable<vscode.Uri[] | undefined> {
return vscode.window.showOpenDialog(options);
}
public showErrorMessage(message: string, ...items: string[]): Thenable<string | undefined> {
return vscode.window.showErrorMessage(message, ...items);
}
public get workspaceRootPath(): string {
return vscode.workspace.rootPath;
}
}

View File

@@ -0,0 +1,23 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import vscode = require('vscode');
import { MainController } from './mainController';
import { ApiWrapper } from './apiWrapper';
export let controller: MainController;
export function activate(context: vscode.ExtensionContext) {
let apiWrapper = new ApiWrapper();
controller = new MainController(context, apiWrapper);
controller.activate();
}
// this method is called when your extension is deactivated
export function deactivate(): void {
if (controller) {
controller.deactivate();
}
}

View File

@@ -0,0 +1,32 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as vscode from 'vscode';
import * as data from 'sqlops';
import { ApiWrapper } from './apiWrapper';
/**
* The main controller class that initializes the extension
*/
export class MainController {
protected _apiWrapper: ApiWrapper;
protected _context: vscode.ExtensionContext;
// PUBLIC METHODS //////////////////////////////////////////////////////
public constructor(context: vscode.ExtensionContext, apiWrapper?: ApiWrapper) {
this._apiWrapper = apiWrapper || new ApiWrapper();
this._context = context;
}
/**
* Deactivates the extension
*/
public deactivate(): void {
}
public activate(): void {
}
}

View File

@@ -0,0 +1,8 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/// <reference path='../../../../../src/vs/vscode.d.ts'/>
/// <reference path='../../../../../src/sql/sqlops.d.ts'/>
/// <reference types='@types/node'/>

View File

@@ -0,0 +1,19 @@
{
"compileOnSave": true,
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"outDir": "./out",
"lib": [
"es6", "es2015.promise"
],
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"declaration": true
},
"exclude": [
"node_modules"
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View File

@@ -0,0 +1,44 @@
{
"name": "profiler",
"displayName": "SQL Server Profiler",
"description": "SQL Server Profiler for SQL Operations Studio",
"version": "0.30.0",
"publisher": "Microsoft",
"preview": true,
"license": "https://raw.githubusercontent.com/Microsoft/sqlopsstudio/master/LICENSE.txt",
"icon": "images/sqlserver.png",
"aiKey": "AIF-5574968e-856d-40d2-af67-c89a14e76412",
"engines": {
"vscode": "0.10.x"
},
"activationEvents": [
"*"
],
"main": "./client/out/main",
"scripts": {
"compile": "gulp compile-extension:profiler-client"
},
"repository": {
"type": "git",
"url": "https://github.com/Microsoft/sqlopsstudio.git"
},
"extensionDependencies": [
"Microsoft.mssql"
],
"contributes": {
"commands": [
{
"command": "profiler.newProfiler",
"title": "New Profiler",
"category": "Profiler"
}
],
"outputChannels": [
"sqlprofiler"
]
},
"devDependencies": {
"vscode": "1.0.1"
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -73,7 +73,7 @@
"panel.background": "#FFFFFE",
"panel.border": "#C8C8C8",
"panelTitle.activeForeground": "#212121",
"panelTitle.inactiveForeground": "#888888"
"panelTitle.inactiveForeground": "#757575"
},
"tokenColors": [
{

View File

@@ -1,6 +1,6 @@
{
"name": "sqlops",
"version": "0.29.2",
"version": "0.30.3",
"distro": "8c3e97e3425cc9814496472ab73e076de2ba99ee",
"author": {
"name": "Microsoft Corporation"
@@ -59,7 +59,7 @@
"reflect-metadata": "^0.1.8",
"rxjs": "5.4.0",
"semver": "4.3.6",
"slickgrid": "github:anthonydresser/SlickGrid#2.3.16",
"slickgrid": "github:anthonydresser/SlickGrid#2.3.17",
"spdlog": "0.6.0",
"svg.js": "^2.2.5",
"sudo-prompt": "^8.0.0",
@@ -162,4 +162,4 @@
"windows-mutex": "^0.2.0",
"windows-process-tree": "0.1.6"
}
}
}

View File

@@ -38,6 +38,9 @@ See [Paul Randal's wait types library] for more information about each wait type
We would like to thank all our users who raised issues, and in particular the following users who helped contribute fixes:
* flyfishingdba for Add square brackets for ms_foreachdb call (#1023)
## What's new in Server Reports v1.2?
* Created left nav bar and added 2 categories for insight widgets: monitor and performance
## What's new in Server Reports v1.1?
* Fixed DB Space Usage where it threw an error when database names contain special characters
* Changed DB Space Usage and DB Buffer Usage to show only top 10 data

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 52 KiB

View File

@@ -1,6 +1,6 @@
{
"name": "server-report",
"version": "0.1.0",
"version": "0.1.2",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@@ -2,7 +2,7 @@
"name": "server-report",
"displayName": "Server Reports",
"description": "Server Reports",
"version": "0.1.1",
"version": "0.1.2",
"publisher": "Microsoft",
"preview": true,
"engines": {
@@ -30,7 +30,30 @@
"title": "Server Reports",
"description": "This extension shows useful reports for a server.",
"container": {
"server-insights1": null
"nav-section": [
{
"id": "server-reports-monitoring",
"title": "Monitor",
"icon": {
"light": "./out/src/media/monitor.svg",
"dark": "./out/src/media/monitor_inverse.svg"
},
"container": {
"server-reports-monitoring-container": {}
}
},
{
"id": "server-reports-performance",
"title": "Performance",
"icon": {
"light": "./out/src/media/performance.svg",
"dark": "./out/src/media/performance_inverse.svg"
},
"container": {
"server-reports-performance-container": {}
}
}
]
}
}
],
@@ -122,7 +145,7 @@
],
"dashboard.containers": [
{
"id": "server-insights1",
"id": "server-reports-monitoring-container",
"container": {
"widgets-container": [
{
@@ -164,7 +187,14 @@
"widget": {
"extension-backup-growth-trend": {}
}
},
}
]
}
},
{
"id": "server-reports-performance-container",
"container": {
"widgets-container": [
{
"name": "Wait Counts by Paul Randal",
"gridItemConfig": {

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><title>usage</title><path d="M7,7H0A6.88,6.88,0,0,1,.25,5.14,7,7,0,0,1,5.14.25,6.92,6.92,0,0,1,7,0ZM6.75,8,1.88,12.87a6.91,6.91,0,0,1-1.4-2.26A7.33,7.33,0,0,1,0,8ZM6,1.08a6,6,0,0,0-1.77.6A6,6,0,0,0,1.68,4.23,6,6,0,0,0,1.08,6H6ZM1.08,9a6.63,6.63,0,0,0,.32,1.23A5.58,5.58,0,0,0,2,11.37L4.34,9ZM8,1l.89,0a8.52,8.52,0,0,1,.86.09,8.14,8.14,0,0,1,.84.18,6.66,6.66,0,0,1,.84.29,7.51,7.51,0,0,1,4.25,4.73,7.58,7.58,0,0,1,.06,4.18A7.51,7.51,0,0,1,15,12.29,7.49,7.49,0,0,1,12.29,15a7.5,7.5,0,0,1-1.79.75,7.63,7.63,0,0,1-4.87-.3A7.53,7.53,0,0,1,3.2,13.8l-.35-.35L8,8.29Zm.5,14a6.31,6.31,0,0,0,1.73-.23,6.66,6.66,0,0,0,1.55-.66,6.5,6.5,0,0,0,2.33-2.33,6.64,6.64,0,0,0,.66-1.55,6.47,6.47,0,0,0,0-3.36,6.69,6.69,0,0,0-.59-1.49,6.45,6.45,0,0,0-.93-1.29,6.63,6.63,0,0,0-1.21-1,6.49,6.49,0,0,0-1.44-.71A6.32,6.32,0,0,0,9,2v6.7L4.27,13.44a6.39,6.39,0,0,0,2,1.16A6.47,6.47,0,0,0,8.5,15Z"/></svg>

After

Width:  |  Height:  |  Size: 969 B

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.cls-1{fill:#fff;}</style></defs><title>usage_inverse</title><path class="cls-1" d="M7,7H0A6.88,6.88,0,0,1,.25,5.14,7,7,0,0,1,5.14.25,6.92,6.92,0,0,1,7,0ZM6.75,8,1.88,12.87a6.91,6.91,0,0,1-1.4-2.26A7.33,7.33,0,0,1,0,8ZM6,1.08a6,6,0,0,0-1.77.6A6,6,0,0,0,1.68,4.23,6,6,0,0,0,1.08,6H6ZM1.08,9a6.63,6.63,0,0,0,.32,1.23A5.58,5.58,0,0,0,2,11.37L4.34,9ZM8,1l.89,0a8.52,8.52,0,0,1,.86.09,8.14,8.14,0,0,1,.84.18,6.66,6.66,0,0,1,.84.29,7.51,7.51,0,0,1,4.25,4.73,7.58,7.58,0,0,1,.06,4.18A7.51,7.51,0,0,1,15,12.29,7.49,7.49,0,0,1,12.29,15a7.5,7.5,0,0,1-1.79.75,7.63,7.63,0,0,1-4.87-.3A7.53,7.53,0,0,1,3.2,13.8l-.35-.35L8,8.29Zm.5,14a6.31,6.31,0,0,0,1.73-.23,6.66,6.66,0,0,0,1.55-.66,6.5,6.5,0,0,0,2.33-2.33,6.64,6.64,0,0,0,.66-1.55,6.47,6.47,0,0,0,0-3.36,6.69,6.69,0,0,0-.59-1.49,6.45,6.45,0,0,0-.93-1.29,6.63,6.63,0,0,0-1.21-1,6.49,6.49,0,0,0-1.44-.71A6.32,6.32,0,0,0,9,2v6.7L4.27,13.44a6.39,6.39,0,0,0,2,1.16A6.47,6.47,0,0,0,8.5,15Z"/></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.cls-1{fill:#101e23;}.cls-2{fill:#4bb8d1;}.cls-3{fill:#0c1011;}</style></defs><title>health</title><path class="cls-1" d="M12.58,1.51A6.36,6.36,0,0,0,8,3.9,6.32,6.32,0,0,0,3.41,1.51,3.81,3.81,0,0,0,0,5.35,5.7,5.7,0,0,0,.64,7.88h.72l0-.08A5.18,5.18,0,0,1,.64,5.39c.07-1.25.87-3.14,2.8-3.23h.12A5.81,5.81,0,0,1,7.73,4.63L8,5.06l.27-.43a5.72,5.72,0,0,1,4.28-2.47c1.93.09,2.73,2,2.8,3.23a5.15,5.15,0,0,1-.64,2.34l0,0a2.38,2.38,0,0,1-.34.68,19.45,19.45,0,0,1-6.57,6.06,11.11,11.11,0,0,1-1.25-.81c-.34-.25-.66-.52-1-.8h0a22.83,22.83,0,0,1-2.76-3H2a18.68,18.68,0,0,0,5.76,5.29h0l0,0h0c3.49-1.63,7-5.73,7.49-7.18V8A5.85,5.85,0,0,0,16,5.35,3.81,3.81,0,0,0,12.58,1.51Z"/><path class="cls-1" d="M1.41,8l-.1-.15h0Z"/><path class="cls-1" d="M7.79,15.22v0h0Z"/><path class="cls-1" d="M7.76,15.23h0v0Z"/><path class="cls-1" d="M14.72,7.73l0,0a.13.13,0,0,0,0,0Z"/><path class="cls-2" d="M12.62,8.7v.12a.48.48,0,0,1-.48.48H8.66l0,.07L7.38,12.65h0A.72.72,0,0,1,6,12.53V9.44H6V6.6L5,9.05H5a.56.56,0,0,1-.52.37H.92V8.36H4.13l0-.07L5.41,5h0a.72.72,0,0,1,1.42.12V8.22h0v2.84L7.77,8.6h0a.56.56,0,0,1,.52-.37h3.84A.48.48,0,0,1,12.62,8.7Z"/><path class="cls-3" d="M12.62,8.7v.12a.48.48,0,0,1-.48.48H8.66l0,.07L7.38,12.65h0A.72.72,0,0,1,6,12.53V9.44H6V6.6L5,9.05H5a.56.56,0,0,1-.52.37H.92V8.36H4.13l0-.07L5.41,5h0a.72.72,0,0,1,1.42.12V8.22h0v2.84L7.77,8.6h0a.56.56,0,0,1,.52-.37h3.84A.48.48,0,0,1,12.62,8.7Z"/></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.cls-1{fill:#fff;}.cls-2{fill:#101e23;}.cls-3{fill:#4bb8d1;}</style></defs><title>health_inverse</title><path class="cls-1" d="M12.58,1.51A6.36,6.36,0,0,0,8,3.9,6.32,6.32,0,0,0,3.41,1.51,3.81,3.81,0,0,0,0,5.35,5.7,5.7,0,0,0,.64,7.88h.72l0-.08A5.18,5.18,0,0,1,.64,5.39c.07-1.25.87-3.14,2.8-3.23h.12A5.81,5.81,0,0,1,7.73,4.63L8,5.06l.27-.43a5.72,5.72,0,0,1,4.28-2.47c1.93.09,2.73,2,2.8,3.23a5.15,5.15,0,0,1-.64,2.34l0,0a2.38,2.38,0,0,1-.34.68,19.45,19.45,0,0,1-6.57,6.06,11.11,11.11,0,0,1-1.25-.81c-.34-.25-.66-.52-1-.8h0a22.83,22.83,0,0,1-2.76-3H2a18.68,18.68,0,0,0,5.76,5.29h0l0,0h0c3.49-1.63,7-5.73,7.49-7.18V8A5.85,5.85,0,0,0,16,5.35,3.81,3.81,0,0,0,12.58,1.51Z"/><path class="cls-2" d="M1.41,8l-.1-.15h0Z"/><path class="cls-2" d="M7.79,15.22v0h0Z"/><path class="cls-2" d="M7.76,15.23h0v0Z"/><path class="cls-2" d="M14.72,7.73l0,0a.13.13,0,0,0,0,0Z"/><path class="cls-3" d="M12.62,8.7v.12a.48.48,0,0,1-.48.48H8.66l0,.07L7.38,12.65h0A.72.72,0,0,1,6,12.53V9.44H6V6.6L5,9.05H5a.56.56,0,0,1-.52.37H.92V8.36H4.13l0-.07L5.41,5h0a.72.72,0,0,1,1.42.12V8.22h0v2.84L7.77,8.6h0a.56.56,0,0,1,.52-.37h3.84A.48.48,0,0,1,12.62,8.7Z"/><path class="cls-1" d="M12.62,8.7v.12a.48.48,0,0,1-.48.48H8.66l0,.07L7.38,12.65h0A.72.72,0,0,1,6,12.53V9.44H6V6.6L5,9.05H5a.56.56,0,0,1-.52.37H.92V8.36H4.13l0-.07L5.41,5h0a.72.72,0,0,1,1.42.12V8.22h0v2.84L7.77,8.6h0a.56.56,0,0,1,.52-.37h3.84A.48.48,0,0,1,12.62,8.7Z"/></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -6,6 +6,11 @@ Welcome to **sp_whoisactive** for SQL Operations Studio! Sp_whoisactive is a pro
<img src="https://github.com/Microsoft/sqlopsstudio/raw/master/samples/sp_whoIsActive/images/insights_section.png" alt="insights" style="width:480px;"/>
Details:
<img src="https://github.com/Microsoft/sqlopsstudio/raw/master/samples/sp_whoIsActive/images/insights_details_section.png" alt="insights" style="width:240px;"/>
## Why use sp_whoisactive?
Here are some quick facts on Who is Active from [Adam Machanics blog]:
@@ -15,9 +20,6 @@ Here are some quick facts on Who is Active from [Adam Machanics blog]:
* Who is Active is **compatible with all versions of SQL Server after SQL Server 2005 RTM**. It does require that the host database (generally master) is not set for SQL Server 2000 compatibility mode
## Documentation:
<img src="https://github.com/Microsoft/sqlopsstudio/raw/master/samples/sp_whoIsActive/images/documentation_section.png" alt="documentation" style="width:480px;"/>
If you haven't installed sp_whoisactive in your server, you can use the "Install sp_whoisactive" task to create the procedure.
See [sp_whoisactive Documentation] for more infomation.
@@ -34,3 +36,8 @@ See [sp_whoisactive extension project] in the SQL Operations Studio for the exte
## Contributions and "thank you"
Special thank to Adam Machanic for partnering with us and make this sp_whoisactive extension possible.
## What's new in Server Reports v1.1?
* Changed CPU usage, CPU delta, memory usage, memory delta to show only top 10 data
* Added details option on each chart to display details of data entries
* Improved "Get plans" and "Find leader of block" tasks. The tasks will open new editor, configure current dashboard connection, and run the query.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View File

@@ -78,10 +78,18 @@
"legendPosition": "none",
"labelFirstColumn": false,
"columnsAsLabels": true,
"showTopNData": 5
"showTopNData": 10
}
},
"queryFile": "./out/src/sql/cpuUsage.sql"
"queryFile": "./out/src/sql/cpuUsage.sql",
"details": {
"queryFile": "./out/src/sql/cpuUsage_details.sql",
"label": {
"column": "session_id",
"state": []
},
"value": "CPU"
}
}
},
{
@@ -94,10 +102,18 @@
"legendPosition": "none",
"labelFirstColumn": false,
"columnsAsLabels": true,
"showTopNData": 5
"showTopNData": 10
}
},
"queryFile": "./out/src/sql/cpuDelta.sql"
"queryFile": "./out/src/sql/cpuDelta.sql",
"details": {
"queryFile": "./out/src/sql/cpuDelta_details.sql",
"label": {
"column": "session_id",
"state": []
},
"value": "CPU_delta"
}
}
},
{
@@ -110,10 +126,18 @@
"legendPosition": "none",
"labelFirstColumn": false,
"columnsAsLabels": true,
"showTopNData": 5
"showTopNData": 10
}
},
"queryFile": "./out/src/sql/memoryUsage.sql"
"queryFile": "./out/src/sql/memoryUsage.sql",
"details": {
"queryFile": "./out/src/sql/memoryUsage_details.sql",
"label": {
"column": "session_id",
"state": []
},
"value": "used_memory"
}
}
},
{
@@ -126,10 +150,18 @@
"legendPosition": "none",
"labelFirstColumn": false,
"columnsAsLabels": true,
"showTopNData": 5
"showTopNData": 10
}
},
"queryFile": "./out/src/sql/memoryDelta.sql"
"queryFile": "./out/src/sql/memoryDelta.sql",
"details": {
"queryFile": "./out/src/sql/memoryDelta_details.sql",
"label": {
"column": "session_id",
"state": []
},
"value": "used_memory_delta"
}
}
},
{
@@ -159,7 +191,7 @@
}
},
{
"name": "Top 5 CPU Usage",
"name": "Top 10 CPU Usage",
"gridItemConfig": {
"sizex": 2,
"sizey": 1
@@ -169,7 +201,7 @@
}
},
{
"name": "Top 5 CPU Delta",
"name": "Top 10 CPU Delta",
"gridItemConfig": {
"sizex": 2,
"sizey": 1
@@ -179,7 +211,7 @@
}
},
{
"name": "Top 5 Memory Usage",
"name": "Top 10 Memory Usage",
"gridItemConfig": {
"sizex": 2,
"sizey": 1
@@ -189,7 +221,7 @@
}
},
{
"name": "Top 5 Memory Delta",
"name": "Top 10 Memory Delta",
"gridItemConfig": {
"sizex": 2,
"sizey": 1
@@ -197,16 +229,6 @@
"widget": {
"sp_whoisactive-memory-delta": {}
}
},
{
"name": "Blocking Sessions",
"gridItemConfig": {
"sizex": 2,
"sizey": 1
},
"widget": {
"sp_whoisactive-blocking_sessions": {}
}
}
]
}

View File

@@ -0,0 +1,8 @@
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME = 'sp_WhoIsActive')
EXEC sp_WhoIsActive
@delta_interval = 1,
@get_plans = 1,
@sort_order = '[CPU_delta] DESC'
ELSE
SELECT 0;
GO

View File

@@ -0,0 +1,7 @@
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME = 'sp_WhoIsActive')
EXEC sp_WhoIsActive
@get_plans = 1,
@sort_order = '[CPU] DESC'
ELSE
SELECT 0;
GO

View File

@@ -0,0 +1,8 @@
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME = 'sp_WhoIsActive')
EXEC sp_WhoIsActive
@delta_interval = 1,
@get_plans = 1,
@sort_order = '[used_memory_delta] DESC'
ELSE
SELECT 0;
GO

View File

@@ -0,0 +1,7 @@
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME = 'sp_WhoIsActive')
EXEC sp_WhoIsActive
@get_plans = 1,
@sort_order = '[used_memory] DESC'
ELSE
SELECT 0;
GO

View File

@@ -27,6 +27,12 @@
"through2": "2.0.3"
}
},
"@types/handlebars": {
"version": "4.0.37",
"resolved": "https://registry.npmjs.org/@types/handlebars/-/handlebars-4.0.37.tgz",
"integrity": "sha512-c/g99PQsJEFYdK3LT1qgPAZ61fu/oFOaEhov/6ZuUNMi1xQFbAOSThlX8fAQLf+QoGXtyv4S39OjIRXf3HkBtw==",
"dev": true
},
"@types/node": {
"version": "7.0.58",
"resolved": "https://registry.npmjs.org/@types/node/-/node-7.0.58.tgz",
@@ -51,11 +57,30 @@
"json-schema-traverse": "0.3.1"
}
},
"align-text": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
"integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
"requires": {
"kind-of": "3.2.2",
"longest": "1.0.1",
"repeat-string": "1.6.1"
},
"dependencies": {
"kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
"requires": {
"is-buffer": "1.1.6"
}
}
}
},
"amdefine": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
"integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
"dev": true
"integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU="
},
"ansi-colors": {
"version": "1.1.0",
@@ -136,6 +161,15 @@
"integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=",
"dev": true
},
"argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"dev": true,
"requires": {
"sprintf-js": "1.0.3"
}
},
"arr-diff": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
@@ -289,6 +323,11 @@
"integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
"dev": true
},
"async": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
"integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo="
},
"async-done": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/async-done/-/async-done-1.2.4.tgz",
@@ -420,6 +459,12 @@
"inherits": "2.0.3"
}
},
"boolbase": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
"dev": true
},
"boom": {
"version": "2.10.1",
"resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
@@ -538,6 +583,16 @@
"integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=",
"dev": true
},
"center-align": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
"integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
"optional": true,
"requires": {
"align-text": "0.1.4",
"lazy-cache": "1.0.4"
}
},
"chalk": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
@@ -551,6 +606,20 @@
"supports-color": "2.0.0"
}
},
"cheerio": {
"version": "1.0.0-rc.2",
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz",
"integrity": "sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs=",
"dev": true,
"requires": {
"css-select": "1.2.0",
"dom-serializer": "0.1.0",
"entities": "1.1.1",
"htmlparser2": "3.9.2",
"lodash": "4.17.10",
"parse5": "3.0.3"
}
},
"child-process-promise": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/child-process-promise/-/child-process-promise-2.2.1.tgz",
@@ -888,6 +957,24 @@
}
}
},
"css-select": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
"integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
"dev": true,
"requires": {
"boolbase": "1.0.0",
"css-what": "2.1.0",
"domutils": "1.5.1",
"nth-check": "1.0.1"
}
},
"css-what": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz",
"integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=",
"dev": true
},
"d": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz",
@@ -954,8 +1041,7 @@
"decamelize": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
"dev": true
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
},
"decode-uri-component": {
"version": "0.2.0",
@@ -1043,6 +1129,12 @@
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
"dev": true
},
"denodeify": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz",
"integrity": "sha1-OjYof1A05pnnV3kBBSwubJQlFjE=",
"dev": true
},
"detect-file": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz",
@@ -1061,6 +1153,49 @@
"integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==",
"dev": true
},
"dom-serializer": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
"integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=",
"dev": true,
"requires": {
"domelementtype": "1.1.3",
"entities": "1.1.1"
},
"dependencies": {
"domelementtype": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
"integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=",
"dev": true
}
}
},
"domelementtype": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz",
"integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=",
"dev": true
},
"domhandler": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
"integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
"dev": true,
"requires": {
"domelementtype": "1.3.0"
}
},
"domutils": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
"integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=",
"dev": true,
"requires": {
"dom-serializer": "0.1.0",
"domelementtype": "1.3.0"
}
},
"duplexer": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
@@ -1143,6 +1278,12 @@
"once": "1.4.0"
}
},
"entities": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz",
"integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=",
"dev": true
},
"error-ex": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz",
@@ -1630,6 +1771,16 @@
"integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=",
"dev": true
},
"fs-extra": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz",
"integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==",
"requires": {
"graceful-fs": "4.1.11",
"jsonfile": "4.0.0",
"universalify": "0.1.1"
}
},
"fs-mkdirp-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz",
@@ -2762,8 +2913,7 @@
"graceful-fs": {
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
"dev": true
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
},
"growl": {
"version": "1.10.3",
@@ -3928,6 +4078,27 @@
"glogg": "1.0.1"
}
},
"handlebars": {
"version": "4.0.11",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz",
"integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=",
"requires": {
"async": "1.5.2",
"optimist": "0.6.1",
"source-map": "0.4.4",
"uglify-js": "2.8.29"
},
"dependencies": {
"source-map": {
"version": "0.4.4",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
"integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
"requires": {
"amdefine": "1.0.1"
}
}
}
},
"har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
@@ -4047,6 +4218,20 @@
"integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==",
"dev": true
},
"htmlparser2": {
"version": "3.9.2",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz",
"integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=",
"dev": true,
"requires": {
"domelementtype": "1.3.0",
"domhandler": "2.4.2",
"domutils": "1.5.1",
"entities": "1.1.1",
"inherits": "2.0.3",
"readable-stream": "2.3.5"
}
},
"http-signature": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
@@ -4135,8 +4320,7 @@
"is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
"dev": true
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
},
"is-builtin-module": {
"version": "1.0.0",
@@ -4443,6 +4627,14 @@
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
"dev": true
},
"jsonfile": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
"requires": {
"graceful-fs": "4.1.11"
}
},
"jsonify": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
@@ -4497,6 +4689,12 @@
"es6-weak-map": "2.0.2"
}
},
"lazy-cache": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
"integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=",
"optional": true
},
"lazystream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz",
@@ -4540,6 +4738,15 @@
"resolve": "1.6.0"
}
},
"linkify-it": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.0.3.tgz",
"integrity": "sha1-2UpGSPmxwXnWT6lykSaL22zpQ08=",
"dev": true,
"requires": {
"uc.micro": "1.0.5"
}
},
"load-json-file": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
@@ -4553,6 +4760,12 @@
"strip-bom": "2.0.0"
}
},
"lodash": {
"version": "4.17.10",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
"integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==",
"dev": true
},
"lodash._basecopy": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz",
@@ -4678,6 +4891,11 @@
"lodash.escape": "3.2.0"
}
},
"longest": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
"integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc="
},
"lru-cache": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz",
@@ -4738,6 +4956,19 @@
"object-visit": "1.0.1"
}
},
"markdown-it": {
"version": "8.4.1",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.1.tgz",
"integrity": "sha512-CzzqSSNkFRUf9vlWvhK1awpJreMRqdCrBvZ8DIoDWTOkESMIF741UPAhuAmbyWmdiFPA6WARNhnu2M6Nrhwa+A==",
"dev": true,
"requires": {
"argparse": "1.0.10",
"entities": "1.1.1",
"linkify-it": "2.0.3",
"mdurl": "1.0.1",
"uc.micro": "1.0.5"
}
},
"matchdep": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz",
@@ -4750,6 +4981,12 @@
"stack-trace": "0.0.10"
}
},
"mdurl": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
"integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=",
"dev": true
},
"memoizee": {
"version": "0.4.12",
"resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.12.tgz",
@@ -4796,6 +5033,12 @@
"to-regex": "3.0.2"
}
},
"mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
"dev": true
},
"mime-db": {
"version": "1.33.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz",
@@ -4941,6 +5184,12 @@
"integrity": "sha1-WzLqB+tDyd7WEwQ0z5JvRrKn/U0=",
"dev": true
},
"mute-stream": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
"integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
"dev": true
},
"nan": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz",
@@ -5019,6 +5268,15 @@
"once": "1.4.0"
}
},
"nth-check": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz",
"integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=",
"dev": true,
"requires": {
"boolbase": "1.0.0"
}
},
"number-is-nan": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
@@ -5207,7 +5465,6 @@
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
"integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
"dev": true,
"requires": {
"minimist": "0.0.10",
"wordwrap": "0.0.3"
@@ -5216,8 +5473,7 @@
"minimist": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
"integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=",
"dev": true
"integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="
}
}
},
@@ -5230,6 +5486,12 @@
"readable-stream": "2.3.5"
}
},
"os-homedir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
"dev": true
},
"os-locale": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
@@ -5239,6 +5501,22 @@
"lcid": "1.0.0"
}
},
"os-tmpdir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
"dev": true
},
"osenv": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
"integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
"dev": true,
"requires": {
"os-homedir": "1.0.2",
"os-tmpdir": "1.0.2"
}
},
"p-map": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz",
@@ -5300,6 +5578,24 @@
"integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
"dev": true
},
"parse-semver": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz",
"integrity": "sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg=",
"dev": true,
"requires": {
"semver": "5.5.0"
}
},
"parse5": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz",
"integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==",
"dev": true,
"requires": {
"@types/node": "7.0.58"
}
},
"pascalcase": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
@@ -5564,6 +5860,15 @@
}
}
},
"read": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
"integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=",
"dev": true,
"requires": {
"mute-stream": "0.0.7"
}
},
"read-pkg": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
@@ -5684,8 +5989,7 @@
"repeat-string": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
"integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
"dev": true
"integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
},
"replace-ext": {
"version": "1.0.0",
@@ -5915,6 +6219,15 @@
"integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
"dev": true
},
"right-align": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
"integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
"optional": true,
"requires": {
"align-text": "0.1.4"
}
},
"rimraf": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
@@ -6136,8 +6449,7 @@
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
"dev": true
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
},
"source-map-resolve": {
"version": "0.5.1",
@@ -6536,6 +6848,15 @@
"next-tick": "1.0.0"
}
},
"tmp": {
"version": "0.0.29",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.29.tgz",
"integrity": "sha1-8lEl/w3Z2jzLDC3Tce4SiLuRKMA=",
"dev": true,
"requires": {
"os-tmpdir": "1.0.2"
}
},
"to-absolute-glob": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz",
@@ -6653,6 +6974,12 @@
}
}
},
"tunnel": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.4.tgz",
"integrity": "sha1-LTeFoVjBdMmhbcLARuxfxfF0IhM=",
"dev": true
},
"tunnel-agent": {
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz",
@@ -6666,6 +6993,16 @@
"dev": true,
"optional": true
},
"typed-rest-client": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-0.12.0.tgz",
"integrity": "sha1-Y3b1Un9CfaEh3K/f1+QeEyHgcgw=",
"dev": true,
"requires": {
"tunnel": "0.0.4",
"underscore": "1.8.3"
}
},
"typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
@@ -6678,12 +7015,78 @@
"integrity": "sha512-Ao/f6d/4EPLq0YwzsQz8iXflezpTkQzqAyenTiw4kCUGr1uPiFLC3+fZ+gMZz6eeI/qdRUqvC+HxIJzUAzEFdg==",
"dev": true
},
"uc.micro": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.5.tgz",
"integrity": "sha512-JoLI4g5zv5qNyT09f4YAvEZIIV1oOjqnewYg5D38dkQljIzpPT296dbIGvKro3digYI1bkb7W6EP1y4uDlmzLg==",
"dev": true
},
"uglify-js": {
"version": "2.8.29",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz",
"integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=",
"optional": true,
"requires": {
"source-map": "0.5.7",
"uglify-to-browserify": "1.0.2",
"yargs": "3.10.0"
},
"dependencies": {
"camelcase": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
"integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=",
"optional": true
},
"cliui": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
"integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
"optional": true,
"requires": {
"center-align": "0.1.3",
"right-align": "0.1.3",
"wordwrap": "0.0.2"
}
},
"wordwrap": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
"integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=",
"optional": true
},
"yargs": {
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
"integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
"optional": true,
"requires": {
"camelcase": "1.2.1",
"cliui": "2.1.0",
"decamelize": "1.2.0",
"window-size": "0.1.0"
}
}
}
},
"uglify-to-browserify": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
"integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=",
"optional": true
},
"unc-path-regex": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",
"integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=",
"dev": true
},
"underscore": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
"integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=",
"dev": true
},
"underscore.string": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.4.tgz",
@@ -6762,6 +7165,11 @@
"through2-filter": "2.0.0"
}
},
"universalify": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz",
"integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc="
},
"unset-value": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
@@ -6814,6 +7222,12 @@
"integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
"dev": true
},
"url-join": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz",
"integrity": "sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg=",
"dev": true
},
"url-parse": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.3.0.tgz",
@@ -6983,6 +7397,31 @@
"vinyl": "2.1.0"
}
},
"vsce": {
"version": "1.36.2",
"resolved": "https://registry.npmjs.org/vsce/-/vsce-1.36.2.tgz",
"integrity": "sha512-LiQjHdoaXOHKdk/PRN5OWWeEm/4w7tnFLf8EM+pzvlz/8uk7uJiqtMjVYAYawnU7c8KbMSz9nE9M6nCTV4ZSQA==",
"dev": true,
"requires": {
"cheerio": "1.0.0-rc.2",
"commander": "2.15.1",
"denodeify": "1.2.1",
"glob": "7.1.2",
"lodash": "4.17.10",
"markdown-it": "8.4.1",
"mime": "1.6.0",
"minimatch": "3.0.4",
"osenv": "0.1.5",
"parse-semver": "1.1.1",
"read": "1.0.7",
"semver": "5.5.0",
"tmp": "0.0.29",
"url-join": "1.1.0",
"vso-node-api": "6.5.0",
"yauzl": "2.9.1",
"yazl": "2.4.3"
}
},
"vscode": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.14.tgz",
@@ -7010,6 +7449,17 @@
"resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-3.2.2.tgz",
"integrity": "sha512-/Ur1+tgazwd51+ncRyoy0UIu4dvMdVXS9XMUULQlZIBoNGEwOhwEx9x+hHWoUjldMrOQ32t2CGKo0u6D4R6/hg=="
},
"vso-node-api": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/vso-node-api/-/vso-node-api-6.5.0.tgz",
"integrity": "sha512-hFjPLMJkq02zF8U+LhZ4airH0ivaiKzGdlNAQlYFB3lWuGH/UANUrl63DVPUQOyGw+7ZNQ+ufM44T6mWN92xyg==",
"dev": true,
"requires": {
"tunnel": "0.0.4",
"typed-rest-client": "0.12.0",
"underscore": "1.8.3"
}
},
"which": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz",
@@ -7025,11 +7475,16 @@
"integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=",
"dev": true
},
"window-size": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
"integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=",
"optional": true
},
"wordwrap": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
"integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=",
"dev": true
"integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="
},
"wrap-ansi": {
"version": "2.1.0",

View File

@@ -16,6 +16,24 @@
],
"main": "./out/src/extension",
"contributes": {
"commands": [
{
"command": "sqlservices.openDialog",
"title": "openDialog"
},
{
"command": "sqlservices.openEditor",
"title": "sqlservices.openEditor"
},
{
"command": "sqlservices.openEditorWithWebView",
"title": "sqlservices.openEditorWithWebView"
},
{
"command": "sqlservices.openEditorWithWebView2",
"title": "sqlservices.openEditorWithWebView2"
}
],
"dashboard.tabs": [
{
"id": "sqlservices.tab",
@@ -62,7 +80,9 @@
"postinstall": "node ./node_modules/vscode/bin/install && node ./node_modules/sqlops/bin/install && gulp copytypings"
},
"dependencies": {
"vscode-nls": "^3.2.2"
"vscode-nls": "^3.2.2",
"fs-extra": "^5.0.0",
"handlebars": "^4.0.11"
},
"devDependencies": {
"@types/node": "^7.0.43",
@@ -76,6 +96,8 @@
"sqlops": "github:anthonydresser/sqlops-extension-sqlops",
"tslint": "^3.14.0",
"typescript": "^2.6.1",
"vscode": "^1.1.14"
"vscode": "^1.1.14",
"@types/handlebars": "^4.0.11",
"vsce": "1.36.2"
}
}

View File

@@ -0,0 +1,18 @@
<!--
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-->
<html>
<header>
</header>
<body>
<button onclick="count()">Count</button>
<script>
function count() {
parent.postMessage('count', '*');
}
</script>
</body>
</html>

View File

@@ -0,0 +1,21 @@
<!--
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-->
<html>
<header>
</header>
<body>
<div id="output">Total Counts: 0</div>
<script>
let output = document.getElementById('output');
window.addEventListener("message", receiveMessage, false);
function receiveMessage(e) {
output.innerText = 'Total Counts: ' + e.data;
}
</script>
</body>
</html>

View File

@@ -9,6 +9,8 @@ import * as sqlops from 'sqlops';
import * as Utils from '../utils';
import * as vscode from 'vscode';
import SplitPropertiesPanel from './splitPropertiesPanel';
import * as fs from 'fs';
import * as path from 'path';
/**
* The main controller class that initializes the extension
@@ -33,6 +35,8 @@ export default class MainController implements vscode.Disposable {
}
public activate(): Promise<boolean> {
const buttonHtml = fs.readFileSync(path.join(__dirname, 'button.html')).toString();
const counterHtml = fs.readFileSync(path.join(__dirname, 'counter.html')).toString();
this.registerSqlServicesModelView();
this.registerSplitPanelModelView();
@@ -40,11 +44,247 @@ export default class MainController implements vscode.Disposable {
vscode.window.showInformationMessage(`Clicked from profile ${profile.serverName}.${profile.databaseName}`);
});
vscode.commands.registerCommand('sqlservices.openDialog', () => {
this.openDialog();
});
vscode.commands.registerCommand('sqlservices.openEditor', () => {
this.openEditor();
});
vscode.commands.registerCommand('sqlservices.openEditorWithWebView', () => {
this.openEditorWithWebview(buttonHtml, counterHtml);
});
vscode.commands.registerCommand('sqlservices.openEditorWithWebView2', () => {
this.openEditorWithWebview2();
});
return Promise.resolve(true);
}
private openDialog(): void {
let dialog = sqlops.window.modelviewdialog.createDialog('Test dialog');
let tab1 = sqlops.window.modelviewdialog.createTab('Test tab 1');
let tab2 = sqlops.window.modelviewdialog.createTab('Test tab 2');
tab2.content = 'sqlservices';
dialog.content = [tab1, tab2];
dialog.okButton.onClick(() => console.log('ok clicked!'));
dialog.cancelButton.onClick(() => console.log('cancel clicked!'));
dialog.okButton.label = 'ok';
dialog.cancelButton.label = 'no';
let customButton1 = sqlops.window.modelviewdialog.createButton('Test button 1');
customButton1.onClick(() => console.log('button 1 clicked!'));
let customButton2 = sqlops.window.modelviewdialog.createButton('Test button 2');
customButton2.onClick(() => console.log('button 2 clicked!'));
dialog.customButtons = [customButton1, customButton2];
tab1.registerContent(async (view) => {
let inputBox = view.modelBuilder.inputBox()
.withProperties({
//width: 300
}).component();
let inputBox2 = view.modelBuilder.inputBox().component();
let checkbox = view.modelBuilder.checkBox()
.withProperties({
label: 'Copy-only backup'
})
.component();
checkbox.onChanged(e => {
console.info("inputBox.enabled " + inputBox.enabled);
inputBox.enabled = !inputBox.enabled;
});
let button = view.modelBuilder.button()
.withProperties({
label: '+'
}).component();
let button3 = view.modelBuilder.button()
.withProperties({
label: '-'
}).component();
let button2 = view.modelBuilder.button()
.component();
button.onDidClick(e => {
inputBox2.value = 'Button clicked';
});
let dropdown = view.modelBuilder.dropDown()
.withProperties({
value: 'Full',
values: ['Full', 'Differential', 'Transaction Log']
})
.component();
let f = 0;
inputBox.onTextChanged((params) => {
vscode.window.showInformationMessage(inputBox.value);
f = f + 1;
inputBox2.value = f.toString();
});
dropdown.onValueChanged((params) => {
vscode.window.showInformationMessage(inputBox2.value);
inputBox.value = dropdown.value;
});
let radioButton = view.modelBuilder.radioButton()
.withProperties({
value: 'option1',
name: 'radioButtonOptions',
label: 'Option 1',
checked: true
//width: 300
}).component();
let radioButton2 = view.modelBuilder.radioButton()
.withProperties({
value: 'option2',
name: 'radioButtonOptions',
label: 'Option 2'
}).component();
let inputBox3 = view.modelBuilder.inputBox().component();
let inputBox4 = view.modelBuilder.inputBox().component();
let form2Model = view.modelBuilder.formContainer()
.withFormItems([{
component: inputBox3,
title: 'inputBox3'
}, {
component: inputBox4,
title: 'inputBox4'
}], {
horizontal: true
}).component();
let groupModel1 = view.modelBuilder.groupContainer()
.withLayout({
}).withItems([
form2Model
]).component();
radioButton.onDidClick(() => {
inputBox.value = radioButton.value;
groupModel1.enabled = true;
});
radioButton2.onDidClick(() => {
inputBox.value = radioButton.value;
groupModel1.enabled = false;
});
let flexRadioButtonsModel = view.modelBuilder.flexContainer()
.withLayout({
flexFlow: 'column',
alignItems: 'left',
height: 50
}).withItems([
radioButton, groupModel1, radioButton2]
, { flex: '1 1 50%' }).component();
let formModel = view.modelBuilder.formContainer()
.withFormItems([{
component: inputBox,
title: 'Backup name'
}, {
component: inputBox2,
title: 'Recovery model'
}, {
component: dropdown,
title: 'Backup type'
}, {
component: checkbox,
title: ''
}, {
component: inputBox2,
title: 'Backup files',
actions: [button, button3]
}, {
component: flexRadioButtonsModel,
title: 'Options'
}], {
horizontal: false,
componentWidth: 400
}).component();
await view.initializeModel(formModel);
});
sqlops.window.modelviewdialog.openDialog(dialog);
}
private openEditor(): void {
let editor = sqlops.workspace.createModelViewEditor('Test Model View');
editor.registerContent(async view => {
let inputBox = view.modelBuilder.inputBox()
.withValidation(component => component.value !== 'valid')
.component();
let formModel = view.modelBuilder.formContainer()
.withFormItems([{
component: inputBox,
title: 'Enter anything but "valid"'
}]).component();
view.onClosed((params) => {
vscode.window.showInformationMessage('The model view editor is closed.');
});
await view.initializeModel(formModel);
});
editor.openEditor();
}
private openEditorWithWebview(html1: string, html2: string): void {
let editor = sqlops.workspace.createModelViewEditor('Editor webview', { retainContextWhenHidden: true });
editor.registerContent(async view => {
let count = 0;
let webview1 = view.modelBuilder.webView()
.withProperties({
html: html1
})
.component();
let webview2 = view.modelBuilder.webView()
.withProperties({
html: html2
})
.component();
webview1.onMessage((params) => {
count++;
webview2.message = count;
});
let flexModel = view.modelBuilder.flexContainer()
.withLayout({
flexFlow: 'column',
alignItems: 'flex-start',
height: 500
}).withItems([
webview1, webview2
], { flex: '1 1 50%' })
.component();
await view.initializeModel(flexModel);
});
editor.openEditor();
}
private openEditorWithWebview2(): void {
let editor = sqlops.workspace.createModelViewEditor('Editor webview2', { retainContextWhenHidden: true });
editor.registerContent(async view => {
let webview = view.modelBuilder.webView()
.component();
let flexModel = view.modelBuilder.flexContainer()
.withLayout({
flexFlow: 'column',
alignItems: 'stretch',
height: '100%'
}).withItems([
webview
], { flex: '1 1 50%' })
.component();
let templateValues = {url: 'http://whoisactive.com/docs/'};
Utils.renderTemplateHtml(path.join(__dirname, '..'), 'templateTab.html', templateValues)
.then(html => {
webview.html = html;
});
await view.initializeModel(flexModel);
});
editor.openEditor();
}
private registerSqlServicesModelView(): void {
sqlops.dashboard.registerModelViewProvider('sqlservices', async (view) => {
sqlops.ui.registerModelViewProvider('sqlservices', async (view) => {
let flexModel = view.modelBuilder.flexContainer()
.withLayout({
flexFlow: 'row',
@@ -62,7 +302,7 @@ export default class MainController implements vscode.Disposable {
.withProperties<sqlops.CardProperties>({
label: 'label1',
value: 'value1',
actions: [{ label: 'action', taskId: 'sqlservices.clickTask' }]
actions: [{ label: 'action' }]
})
.component()
]).component(),
@@ -74,7 +314,7 @@ export default class MainController implements vscode.Disposable {
.withProperties<sqlops.CardProperties>({
label: 'label2',
value: 'value2',
actions: [{ label: 'action', taskId: 'sqlservices.clickTask' }]
actions: [{ label: 'action' }]
})
.component()
]).component()
@@ -85,7 +325,7 @@ export default class MainController implements vscode.Disposable {
}
private registerSplitPanelModelView(): void {
sqlops.dashboard.registerModelViewProvider('splitPanel', async (view) => {
sqlops.ui.registerModelViewProvider('splitPanel', async (view) => {
let numPanels = 3;
let splitPanel = new SplitPropertiesPanel(view, numPanels);
await view.initializeModel(splitPanel.modelBase);

View File

@@ -0,0 +1,36 @@
<!--
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script type="text/javascript">
window.onload = function() {
document.getElementById('frame').src = "{{{url}}}";
};
</script>
<style>
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
#frame {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
</style>
</head>
<body>
<iframe id="frame" width="100%" height="100%" frameborder="0"></iframe>
</body>
</html>

View File

@@ -19,6 +19,14 @@
normalize-path "^2.0.1"
through2 "^2.0.3"
"@types/handlebars@^4.0.11":
version "4.0.37"
resolved "https://registry.yarnpkg.com/@types/handlebars/-/handlebars-4.0.37.tgz#a3bc3eba0c0f03f753cac00841a5b21e26a02c03"
"@types/node@*":
version "10.1.3"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.1.3.tgz#5c16980936c4e3c83ce64e8ed71fb37bd7aea135"
"@types/node@^7.0.43":
version "7.0.58"
resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.58.tgz#ae852120137f40a29731a559e48003bd2d5d19f7"
@@ -47,6 +55,14 @@ ajv@^5.1.0:
fast-json-stable-stringify "^2.0.0"
json-schema-traverse "^0.3.0"
align-text@^0.1.1, align-text@^0.1.3:
version "0.1.4"
resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117"
dependencies:
kind-of "^3.0.2"
longest "^1.0.1"
repeat-string "^1.5.2"
amdefine@>=0.0.4:
version "1.0.1"
resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
@@ -115,6 +131,12 @@ are-we-there-yet@~1.1.2:
delegates "^1.0.0"
readable-stream "^2.0.6"
argparse@^1.0.7:
version "1.0.10"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
dependencies:
sprintf-js "~1.0.2"
arr-diff@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-1.1.0.tgz#687c32758163588fef7de7b36fabe495eb1a399a"
@@ -250,6 +272,10 @@ async-settle@^1.0.0:
dependencies:
async-done "^1.2.2"
async@^1.4.0:
version "1.5.2"
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
@@ -324,6 +350,10 @@ block-stream@*:
dependencies:
inherits "~2.0.0"
boolbase@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
boom@2.x.x:
version "2.10.1"
resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f"
@@ -408,6 +438,10 @@ cache-base@^1.0.1:
union-value "^1.0.0"
unset-value "^1.0.0"
camelcase@^1.0.2:
version "1.2.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39"
camelcase@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
@@ -420,6 +454,13 @@ caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
center-align@^0.1.1:
version "0.1.3"
resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad"
dependencies:
align-text "^0.1.3"
lazy-cache "^1.0.3"
chalk@^1.0.0, chalk@^1.1.1:
version "1.1.3"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
@@ -430,6 +471,17 @@ chalk@^1.0.0, chalk@^1.1.1:
strip-ansi "^3.0.0"
supports-color "^2.0.0"
cheerio@^1.0.0-rc.1:
version "1.0.0-rc.2"
resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.2.tgz#4b9f53a81b27e4d5dac31c0ffd0cfa03cc6830db"
dependencies:
css-select "~1.2.0"
dom-serializer "~0.1.0"
entities "~1.1.1"
htmlparser2 "^3.9.1"
lodash "^4.15.0"
parse5 "^3.0.1"
child-process-promise@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/child-process-promise/-/child-process-promise-2.2.1.tgz#4730a11ef610fad450b8f223c79d31d7bdad8074"
@@ -465,6 +517,14 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
cliui@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1"
dependencies:
center-align "^0.1.1"
right-align "^0.1.1"
wordwrap "0.0.2"
cliui@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
@@ -546,7 +606,7 @@ commander@2.11.0:
version "2.11.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563"
commander@^2.9.0:
commander@^2.8.1, commander@^2.9.0:
version "2.15.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
@@ -609,6 +669,19 @@ cryptiles@3.x.x:
dependencies:
boom "5.x.x"
css-select@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858"
dependencies:
boolbase "~1.0.0"
css-what "2.1"
domutils "1.5.1"
nth-check "~1.0.1"
css-what@2.1:
version "2.1.0"
resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd"
css@2.X, css@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/css/-/css-2.2.1.tgz#73a4c81de85db664d4ee674f7d47085e3b2d55dc"
@@ -654,7 +727,7 @@ debug@^2.2.0, debug@^2.3.3:
dependencies:
ms "2.0.0"
decamelize@^1.1.1:
decamelize@^1.0.0, decamelize@^1.1.1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
@@ -727,6 +800,10 @@ delegates@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
denodeify@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/denodeify/-/denodeify-1.2.1.tgz#3a36287f5034e699e7577901052c2e6c94251631"
detect-file@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
@@ -747,6 +824,41 @@ diff@^2.2.1:
version "2.2.3"
resolved "https://registry.yarnpkg.com/diff/-/diff-2.2.3.tgz#60eafd0d28ee906e4e8ff0a52c1229521033bf99"
dom-serializer@0, dom-serializer@~0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82"
dependencies:
domelementtype "~1.1.1"
entities "~1.1.1"
domelementtype@1, domelementtype@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2"
domelementtype@~1.1.1:
version "1.1.3"
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b"
domhandler@^2.3.0:
version "2.4.2"
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803"
dependencies:
domelementtype "1"
domutils@1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf"
dependencies:
dom-serializer "0"
domelementtype "1"
domutils@^1.5.1:
version "1.7.0"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
dependencies:
dom-serializer "0"
domelementtype "1"
duplexer2@0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db"
@@ -785,6 +897,10 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0:
dependencies:
once "^1.4.0"
entities@^1.1.1, entities@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0"
error-ex@^1.2.0:
version "1.3.1"
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc"
@@ -834,7 +950,7 @@ event-emitter@^0.3.5:
d "1"
es5-ext "~0.10.14"
event-stream@^3.3.1, event-stream@~3.3.4:
event-stream@^3.3.1, event-stream@^3.3.4, event-stream@~3.3.4:
version "3.3.4"
resolved "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571"
dependencies:
@@ -1068,6 +1184,14 @@ from@~0:
version "0.1.7"
resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe"
fs-extra@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd"
dependencies:
graceful-fs "^4.1.2"
jsonfile "^4.0.0"
universalify "^0.1.0"
fs-mkdirp-stream@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz#0b7815fc3201c6a69e14db98ce098c16935259eb"
@@ -1201,7 +1325,7 @@ glob-watcher@^5.0.0:
just-debounce "^1.0.0"
object.defaults "^1.1.0"
glob@7.1.2, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2:
glob@7.1.2, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1, glob@^7.1.2:
version "7.1.2"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
dependencies:
@@ -1314,6 +1438,16 @@ gulp-gunzip@1.0.0:
through2 "~0.6.5"
vinyl "~0.4.6"
gulp-remote-src-vscode@^0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/gulp-remote-src-vscode/-/gulp-remote-src-vscode-0.5.0.tgz#71785553bc491880088ad971f90910c4b2d80a99"
dependencies:
event-stream "^3.3.4"
node.extend "^1.1.2"
request "^2.79.0"
through2 "^2.0.3"
vinyl "^2.0.1"
gulp-remote-src@^0.4.3:
version "0.4.3"
resolved "https://registry.yarnpkg.com/gulp-remote-src/-/gulp-remote-src-0.4.3.tgz#5728cfd643433dd4845ddef0969f0f971a2ab4a1"
@@ -1386,6 +1520,16 @@ gulp-untar@^0.0.6:
tar "^2.2.1"
through2 "~2.0.3"
gulp-untar@^0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/gulp-untar/-/gulp-untar-0.0.7.tgz#92067d79e0fa1e92d60562a100233a44a5aa08b4"
dependencies:
event-stream "~3.3.4"
streamifier "~0.1.1"
tar "^2.2.1"
through2 "~2.0.3"
vinyl "^1.2.0"
gulp-util@~3.0.7, gulp-util@~3.0.8:
version "3.0.8"
resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f"
@@ -1436,6 +1580,16 @@ gulplog@^1.0.0:
dependencies:
glogg "^1.0.0"
handlebars@^4.0.11:
version "4.0.11"
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.11.tgz#630a35dfe0294bc281edae6ffc5d329fc7982dcc"
dependencies:
async "^1.4.0"
optimist "^0.6.1"
source-map "^0.4.4"
optionalDependencies:
uglify-js "^2.6"
har-schema@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e"
@@ -1558,6 +1712,17 @@ hosted-git-info@^2.1.4:
version "2.6.0"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.6.0.tgz#23235b29ab230c576aab0d4f13fc046b0b038222"
htmlparser2@^3.9.1:
version "3.9.2"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338"
dependencies:
domelementtype "^1.3.0"
domhandler "^2.3.0"
domutils "^1.5.1"
entities "^1.1.1"
inherits "^2.0.1"
readable-stream "^2.0.2"
http-signature@~1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf"
@@ -1886,6 +2051,12 @@ json-stringify-safe@~5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
jsonfile@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
optionalDependencies:
graceful-fs "^4.1.6"
jsonify@~0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
@@ -1938,6 +2109,10 @@ last-run@^1.1.0:
default-resolution "^2.0.0"
es6-weak-map "^2.0.1"
lazy-cache@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e"
lazystream@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4"
@@ -1969,6 +2144,12 @@ liftoff@^2.5.0:
rechoir "^0.6.2"
resolve "^1.1.7"
linkify-it@^2.0.0:
version "2.0.3"
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.0.3.tgz#d94a4648f9b1c179d64fa97291268bdb6ce9434f"
dependencies:
uc.micro "^1.0.1"
load-json-file@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
@@ -2066,6 +2247,14 @@ lodash.templatesettings@^3.0.0:
lodash._reinterpolate "^3.0.0"
lodash.escape "^3.0.0"
lodash@^4.15.0:
version "4.17.10"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7"
longest@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
lru-cache@^4.0.1:
version "4.1.2"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.2.tgz#45234b2e6e2f2b33da125624c4664929a0224c3f"
@@ -2099,6 +2288,16 @@ map-visit@^1.0.0:
dependencies:
object-visit "^1.0.0"
markdown-it@^8.3.1:
version "8.4.1"
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.1.tgz#206fe59b0e4e1b78a7c73250af9b34a4ad0aaf44"
dependencies:
argparse "^1.0.7"
entities "~1.1.1"
linkify-it "^2.0.0"
mdurl "^1.0.1"
uc.micro "^1.0.5"
matchdep@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/matchdep/-/matchdep-2.0.0.tgz#c6f34834a0d8dbc3b37c27ee8bbcb27c7775582e"
@@ -2108,6 +2307,10 @@ matchdep@^2.0.0:
resolve "^1.4.0"
stack-trace "0.0.10"
mdurl@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
memoizee@0.4.X:
version "0.4.12"
resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.12.tgz#780e99a219c50c549be6d0fc61765080975c58fb"
@@ -2173,7 +2376,11 @@ mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.7:
dependencies:
mime-db "~1.33.0"
"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4:
mime@^1.3.4:
version "1.6.0"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
dependencies:
@@ -2242,6 +2449,10 @@ mute-stdout@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/mute-stdout/-/mute-stdout-1.0.0.tgz#5b32ea07eb43c9ded6130434cf926f46b2a7fd4d"
mute-stream@~0.0.4:
version "0.0.7"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
nan@^2.3.0:
version "2.10.0"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f"
@@ -2287,7 +2498,7 @@ node-version@^1.0.0:
version "1.1.3"
resolved "https://registry.yarnpkg.com/node-version/-/node-version-1.1.3.tgz#1081c87cce6d2dbbd61d0e51e28c287782678496"
node.extend@~1.1.2:
node.extend@^1.1.2, node.extend@~1.1.2:
version "1.1.6"
resolved "https://registry.yarnpkg.com/node.extend/-/node.extend-1.1.6.tgz#a7b882c82d6c93a4863a5504bd5de8ec86258b96"
dependencies:
@@ -2330,6 +2541,12 @@ npmlog@^4.0.2:
gauge "~2.7.3"
set-blocking "~2.0.0"
nth-check@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.1.tgz#9929acdf628fc2c41098deab82ac580cf149aae4"
dependencies:
boolbase "~1.0.0"
number-is-nan@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
@@ -2415,7 +2632,7 @@ once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.3.3, once@^1.4.0:
dependencies:
wrappy "1"
optimist@~0.6.0:
optimist@^0.6.1, optimist@~0.6.0:
version "0.6.1"
resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
dependencies:
@@ -2445,11 +2662,11 @@ os-locale@^1.4.0:
dependencies:
lcid "^1.0.0"
os-tmpdir@^1.0.0:
os-tmpdir@^1.0.0, os-tmpdir@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
osenv@^0.1.4:
osenv@^0.1.3, osenv@^0.1.4:
version "0.1.5"
resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
dependencies:
@@ -2487,6 +2704,18 @@ parse-passwd@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
parse-semver@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/parse-semver/-/parse-semver-1.1.1.tgz#9a4afd6df063dc4826f93fba4a99cf223f666cb8"
dependencies:
semver "^5.1.0"
parse5@^3.0.1:
version "3.0.3"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c"
dependencies:
"@types/node" "*"
pascalcase@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
@@ -2683,6 +2912,12 @@ read-pkg@^1.0.0:
normalize-package-data "^2.3.2"
path-type "^1.0.0"
read@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4"
dependencies:
mute-stream "~0.0.4"
"readable-stream@>=1.0.33-1 <1.1.0-0":
version "1.0.34"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c"
@@ -2811,6 +3046,31 @@ request@2.81.0:
tunnel-agent "^0.6.0"
uuid "^3.0.0"
request@^2.79.0:
version "2.87.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e"
dependencies:
aws-sign2 "~0.7.0"
aws4 "^1.6.0"
caseless "~0.12.0"
combined-stream "~1.0.5"
extend "~3.0.1"
forever-agent "~0.6.1"
form-data "~2.3.1"
har-validator "~5.0.3"
http-signature "~1.2.0"
is-typedarray "~1.0.0"
isstream "~0.1.2"
json-stringify-safe "~5.0.1"
mime-types "~2.1.17"
oauth-sign "~0.8.2"
performance-now "^2.1.0"
qs "~6.5.1"
safe-buffer "^5.1.1"
tough-cookie "~2.3.3"
tunnel-agent "^0.6.0"
uuid "^3.1.0"
request@^2.83.0:
version "2.85.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.85.0.tgz#5a03615a47c61420b3eb99b7dba204f83603e1fa"
@@ -2902,6 +3162,12 @@ ret@~0.1.10:
version "0.1.15"
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
right-align@^0.1.1:
version "0.1.3"
resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef"
dependencies:
align-text "^0.1.1"
rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.6.1:
version "2.6.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
@@ -2924,7 +3190,7 @@ semver-greatest-satisfied-range@^1.1.0:
dependencies:
sver-compat "^1.5.0"
"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1:
"semver@2 || 3 || 4 || 5", semver@^5.1.0, semver@^5.3.0, semver@^5.4.1:
version "5.5.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
@@ -3036,7 +3302,13 @@ source-map@^0.1.38:
dependencies:
amdefine ">=0.0.4"
source-map@^0.5.6, source-map@~0.5.3:
source-map@^0.4.4:
version "0.4.4"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b"
dependencies:
amdefine ">=0.0.4"
source-map@^0.5.6, source-map@~0.5.1, source-map@~0.5.3:
version "0.5.7"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
@@ -3086,6 +3358,10 @@ sprintf-js@^1.0.3:
version "1.1.1"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c"
sprintf-js@~1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
"sqlops@github:anthonydresser/sqlops-extension-sqlops":
version "1.1.11"
resolved "https://codeload.github.com/anthonydresser/sqlops-extension-sqlops/tar.gz/dac501bbaa03a25239c060c6371dfdcf06707599"
@@ -3281,6 +3557,12 @@ timers-ext@^0.1.2:
es5-ext "~0.10.14"
next-tick "1"
tmp@0.0.29:
version "0.0.29"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.29.tgz#f25125ff0dd9da3ccb0c2dd371ee1288bb9128c0"
dependencies:
os-tmpdir "~1.0.1"
to-absolute-glob@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz#1cdfa472a9ef50c239ee66999b662ca0eb39937f"
@@ -3350,10 +3632,21 @@ tunnel-agent@~0.4.1:
version "0.4.3"
resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb"
tunnel@0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.4.tgz#2d3785a158c174c9a16dc2c046ec5fc5f1742213"
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
version "0.14.5"
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
typed-rest-client@^0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/typed-rest-client/-/typed-rest-client-0.12.0.tgz#6376f5527f427da121dcafdfd7e41e1321e0720c"
dependencies:
tunnel "0.0.4"
underscore "1.8.3"
typedarray@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
@@ -3362,6 +3655,23 @@ typescript@^2.6.1:
version "2.8.1"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.8.1.tgz#6160e4f8f195d5ba81d4876f9c0cc1fbc0820624"
uc.micro@^1.0.1, uc.micro@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.5.tgz#0c65f15f815aa08b560a61ce8b4db7ffc3f45376"
uglify-js@^2.6:
version "2.8.29"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"
dependencies:
source-map "~0.5.1"
yargs "~3.10.0"
optionalDependencies:
uglify-to-browserify "~1.0.0"
uglify-to-browserify@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
uid-number@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81"
@@ -3377,6 +3687,10 @@ underscore.string@^3.3.4:
sprintf-js "^1.0.3"
util-deprecate "^1.0.2"
underscore@1.8.3:
version "1.8.3"
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022"
undertaker-registry@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/undertaker-registry/-/undertaker-registry-1.0.1.tgz#5e4bda308e4a8a2ae584f9b9a4359a499825cc50"
@@ -3411,6 +3725,10 @@ unique-stream@^2.0.2:
json-stable-stringify "^1.0.0"
through2-filter "^2.0.0"
universalify@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7"
unset-value@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559"
@@ -3426,6 +3744,10 @@ urix@^0.1.0, urix@~0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
url-join@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/url-join/-/url-join-1.1.0.tgz#741c6c2f4596c4830d6718460920d0c92202dc78"
url-parse@^1.1.9:
version "1.2.0"
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.2.0.tgz#3a19e8aaa6d023ddd27dcc44cb4fc8f7fec23986"
@@ -3554,7 +3876,7 @@ vinyl@^0.5.0:
clone-stats "^0.0.1"
replace-ext "0.0.1"
vinyl@^1.0.0:
vinyl@^1.0.0, vinyl@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884"
dependencies:
@@ -3562,7 +3884,7 @@ vinyl@^1.0.0:
clone-stats "^0.0.1"
replace-ext "0.0.1"
vinyl@^2.0.0, vinyl@^2.0.2:
vinyl@^2.0.0, vinyl@^2.0.1, vinyl@^2.0.2:
version "2.1.0"
resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.1.0.tgz#021f9c2cf951d6b939943c89eb5ee5add4fd924c"
dependencies:
@@ -3585,21 +3907,43 @@ vinyl@~2.0.1:
remove-trailing-separator "^1.0.1"
replace-ext "^1.0.0"
vsce@1.36.2:
version "1.36.2"
resolved "https://registry.yarnpkg.com/vsce/-/vsce-1.36.2.tgz#dfcfca722bc6aa6bfcbffb1efd23176ba99b2944"
dependencies:
cheerio "^1.0.0-rc.1"
commander "^2.8.1"
denodeify "^1.2.1"
glob "^7.0.6"
lodash "^4.15.0"
markdown-it "^8.3.1"
mime "^1.3.4"
minimatch "^3.0.3"
osenv "^0.1.3"
parse-semver "^1.1.1"
read "^1.0.7"
semver "^5.1.0"
tmp "0.0.29"
url-join "^1.1.0"
vso-node-api "^6.1.2-preview"
yauzl "^2.3.1"
yazl "^2.2.2"
vscode-nls@^3.2.2:
version "3.2.2"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.2.tgz#3817eca5b985c2393de325197cf4e15eb2aa5350"
vscode@^1.1.6:
version "1.1.14"
resolved "https://registry.yarnpkg.com/vscode/-/vscode-1.1.14.tgz#f327f5fd45c085d12def616962af205b2bc75db5"
vscode@^1.1.14:
version "1.1.18"
resolved "https://registry.yarnpkg.com/vscode/-/vscode-1.1.18.tgz#e9227265dc72fc826bd6cd7bd21193f4e48fa671"
dependencies:
glob "^7.1.2"
gulp-chmod "^2.0.0"
gulp-filter "^5.0.1"
gulp-gunzip "1.0.0"
gulp-remote-src "^0.4.3"
gulp-remote-src-vscode "^0.5.0"
gulp-symdest "^1.1.0"
gulp-untar "^0.0.6"
gulp-untar "^0.0.7"
gulp-vinyl-zip "^2.1.0"
mocha "^4.0.1"
request "^2.83.0"
@@ -3608,6 +3952,14 @@ vscode@^1.1.6:
url-parse "^1.1.9"
vinyl-source-stream "^1.1.0"
vso-node-api@^6.1.2-preview:
version "6.5.0"
resolved "https://registry.yarnpkg.com/vso-node-api/-/vso-node-api-6.5.0.tgz#5f3453f27d211b0fd54423c4c73116c1e8fea0c6"
dependencies:
tunnel "0.0.4"
typed-rest-client "^0.12.0"
underscore "1.8.3"
which-module@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f"
@@ -3624,6 +3976,14 @@ wide-align@^1.1.0:
dependencies:
string-width "^1.0.2"
window-size@0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d"
wordwrap@0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f"
wordwrap@~0.0.2:
version "0.0.3"
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
@@ -3675,14 +4035,23 @@ yargs@^7.1.0:
y18n "^3.2.1"
yargs-parser "^5.0.0"
yauzl@^2.2.1:
yargs@~3.10.0:
version "3.10.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1"
dependencies:
camelcase "^1.0.2"
cliui "^2.1.0"
decamelize "^1.0.0"
window-size "0.1.0"
yauzl@^2.2.1, yauzl@^2.3.1:
version "2.9.1"
resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.9.1.tgz#a81981ea70a57946133883f029c5821a89359a7f"
dependencies:
buffer-crc32 "~0.2.3"
fd-slicer "~1.0.1"
yazl@^2.2.1:
yazl@^2.2.1, yazl@^2.2.2:
version "2.4.3"
resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.4.3.tgz#ec26e5cc87d5601b9df8432dbdd3cd2e5173a071"
dependencies:

View File

@@ -21,6 +21,12 @@ panel {
.tabbedPanel .composite.title {
display: flex;
flex: 0 0 auto;
position: relative;
}
.tabbedPanel .tabContainer {
flex: 1 1 auto;
overflow: hidden;
}
.tabbedPanel .tabList {
@@ -31,6 +37,7 @@ panel {
line-height: 35px;
white-space: nowrap;
flex: 1;
height: 100%;
}
.tabbedPanel .tabList .tab {
@@ -65,15 +72,6 @@ panel {
line-height: 45px;
}
.tabbedPanel .tabList .tab:hover .tabLabel,
.tabbedPanel .tabList .tab .tabLabel.active {
opacity: 1;
}
.tabbedPanel .tabList .tab .tabLabel {
opacity: 0.8;
}
.tabbedPanel .tabList .tab .tabLabel.icon {
background-repeat: no-repeat;
background-position: center center;
@@ -97,17 +95,13 @@ panel {
}
.composite.title .title-actions {
flex: 1 1 auto;
flex: 0 0 auto;
}
.tab > .tabLabel.active {
border-bottom: 1px solid;
}
.composite.title ~ tab.fullsize > :first-child {
height: calc(100% - 38px);
}
.tabbedPanel .title-actions .panel-actions .actions-container {
justify-content: flex-start;
}

View File

@@ -7,13 +7,13 @@ import { Component, ContentChildren, QueryList, AfterContentInit, Inject, forwar
import { TabComponent } from './tab.component';
import { TabHeaderComponent } from './tabHeader.component';
import { ScrollableDirective } from 'sql/base/browser/ui/scrollable/scrollable.directive';
import './panelStyles';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { Action } from 'vs/base/common/actions';
import * as types from 'vs/base/common/types';
import { mixin } from 'vs/base/common/objects';
import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
import { addDisposableListener, EventType } from 'vs/base/browser/dom';
import { Disposable } from 'vs/base/common/lifecycle';
@@ -46,12 +46,13 @@ let idPool = 0;
@Component({
selector: 'panel',
template: `
<div class="tabbedPanel fullsize" #tabbedPanel>
<div *ngIf="!options.showTabsWhenOne ? _tabs.length !== 1 : true" class="composite title" #titleContainer>
<div class="tabList" #tabList role="tablist">
<div *ngFor="let tab of _tabs">
<tab-header [tab]="tab" [showIcon]="options.showIcon" (onSelectTab)='selectTab($event)' (onCloseTab)='closeTab($event)'> </tab-header>
<div class="tabbedPanel fullsize" [ngClass]="options.layout === NavigationBarLayout.vertical ? 'vertical' : 'horizontal'">
<div *ngIf="!options.showTabsWhenOne ? _tabs.length !== 1 : true" class="composite title">
<div class="tabContainer">
<div class="tabList" role="tablist" scrollable [horizontalScroll]="ScrollbarVisibility.Auto" [verticalScroll]="ScrollbarVisibility.Hidden" [scrollYToX]="true">
<div role="presentation" *ngFor="let tab of _tabs">
<tab-header role="presentation" [active]="_activeTab === tab" [tab]="tab" [showIcon]="options.showIcon" (onSelectTab)='selectTab($event)' (onCloseTab)='closeTab($event)'></tab-header>
</div>
</div>
</div>
<div class="title-actions">
@@ -67,11 +68,12 @@ let idPool = 0;
</div>
`
})
export class PanelComponent extends Disposable implements AfterContentInit, OnInit, OnChanges, OnDestroy, AfterViewInit {
export class PanelComponent extends Disposable {
@Input() public options: IPanelOptions;
@Input() public actions: Array<Action>;
@ContentChildren(TabComponent) private _tabs: QueryList<TabComponent>;
@ViewChildren(TabHeaderComponent) private _headerTabs: QueryList<TabHeaderComponent>;
@ViewChild(ScrollableDirective) private scrollable: ScrollableDirective;
@Output() public onTabChange = new EventEmitter<TabComponent>();
@Output() public onTabClose = new EventEmitter<TabComponent>();
@@ -79,12 +81,11 @@ export class PanelComponent extends Disposable implements AfterContentInit, OnIn
private _activeTab: TabComponent;
private _actionbar: ActionBar;
private _mru: TabComponent[];
private _scrollableElement: ScrollableElement;
private ScrollbarVisibility = ScrollbarVisibility;
private NavigationBarLayout = NavigationBarLayout;
@ViewChild('panelActionbar', { read: ElementRef }) private _actionbarRef: ElementRef;
@ViewChild('tabbedPanel', { read: ElementRef }) private _tabbedPanelRef: ElementRef;
@ViewChild('titleContainer', { read: ElementRef }) private _titleContainer: ElementRef;
@ViewChild('tabList', { read: ElementRef }) private _tabList: ElementRef;
constructor( @Inject(forwardRef(() => NgZone)) private _zone: NgZone) {
super();
}
@@ -96,51 +97,14 @@ export class PanelComponent extends Disposable implements AfterContentInit, OnIn
ngAfterContentInit(): void {
if (this._tabs && this._tabs.length > 0) {
this._activeTab = this._tabs.first;
this._activeTab.active = true;
}
}
ngAfterViewInit(): void {
if (!this.options.showTabsWhenOne ? this._tabs.length !== 1 : true) {
let container = this._titleContainer.nativeElement as HTMLElement;
let tabList = this._tabList.nativeElement as HTMLElement;
container.removeChild(tabList);
this._scrollableElement = new ScrollableElement(tabList, {
horizontal: ScrollbarVisibility.Auto,
vertical: ScrollbarVisibility.Hidden,
scrollYToX: true,
useShadows: false,
horizontalScrollbarSize: 3
this.selectTab(this._tabs.first);
} else {
const sub = this._tabs.changes.subscribe(() => {
if (this._tabs && this._tabs.length > 0) {
this.selectTab(this._tabs.first);
sub.unsubscribe();
}
});
this._scrollableElement.onScroll(e => {
tabList.scrollLeft = e.scrollLeft;
});
container.insertBefore(this._scrollableElement.getDomNode(), container.firstChild);
this._scrollableElement.setScrollDimensions({
width: tabList.offsetWidth,
scrollWidth: tabList.scrollWidth
});
this._register(addDisposableListener(window, EventType.RESIZE, () => {
// Todo: Need to set timeout because we have to make sure that the grids have already rearraged before the getContentHeight gets called.
setTimeout(() => {
this._scrollableElement.setScrollDimensions({
width: tabList.offsetWidth,
scrollWidth: tabList.scrollWidth
});
}, 100);
}));
if (this.options.layout === NavigationBarLayout.horizontal) {
(<HTMLElement>this._tabbedPanelRef.nativeElement).classList.add(horizontalLayout);
} else {
(<HTMLElement>this._tabbedPanelRef.nativeElement).classList.add(verticalLayout);
}
}
}
@@ -154,6 +118,17 @@ export class PanelComponent extends Disposable implements AfterContentInit, OnIn
}
}
ngAfterViewInit(): void {
this._tabs.changes.subscribe(() => {
if (this.scrollable) {
this.scrollable.layout();
}
});
if (this.scrollable) {
this.scrollable.layout();
}
}
ngOnDestroy() {
if (this._actionbar) {
this._actionbar.dispose();
@@ -210,12 +185,6 @@ export class PanelComponent extends Disposable implements AfterContentInit, OnIn
this.setMostRecentlyUsed(tab);
this._activeTab.active = true;
// Make the tab header focus on the new selected tab
let activeTabHeader = this._headerTabs.find(i => i.tab === this._activeTab);
if (activeTabHeader) {
activeTabHeader.focusOnTabHeader();
}
this.onTabChange.emit(tab);
});
}

View File

@@ -9,9 +9,11 @@ import { TabComponent } from './tab.component';
import { TabHeaderComponent } from './tabHeader.component';
import { PanelComponent } from './panel.component';
import { ScrollableModule } from 'sql/base/browser/ui/scrollable/scrollable.module';
@NgModule({
imports: [CommonModule],
imports: [CommonModule, ScrollableModule],
exports: [TabComponent, PanelComponent],
declarations: [TabComponent, TabHeaderComponent, PanelComponent]
})
export class PanelModule { }
export class PanelModule { }

View File

@@ -66,6 +66,8 @@ export class TabbedPanel extends Disposable implements IThemable {
this.$header.append(actionbarcontainer);
this.$parent.append(this.$header);
this.$body = $('tabBody');
this.$body.attr('role', 'tabpanel');
this.$body.attr('tabindex', '0');
this.$parent.append(this.$body);
}
@@ -92,7 +94,7 @@ export class TabbedPanel extends Disposable implements IThemable {
tabHeaderElement.attr('tabindex', '0');
tabHeaderElement.attr('role', 'tab');
tabHeaderElement.attr('aria-selected', 'false');
tabHeaderElement.attr('aria-label', tab.title);
tabHeaderElement.attr('aria-controls', tab.identifier);
let tabElement = $('.tab');
tabHeaderElement.append(tabElement);
let tabLabel = $('a.tabLabel');
@@ -124,6 +126,7 @@ export class TabbedPanel extends Disposable implements IThemable {
this._shownTab = id;
this.$body.clearChildren();
let tab = this._tabMap.get(this._shownTab);
this.$body.attr('aria-labelledby', tab.identifier);
tab.label.addClass('active');
tab.header.addClass('active');
tab.header.attr('aria-selected', 'true');

View File

@@ -5,33 +5,33 @@
import 'vs/css!./media/panel';
import { registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
import { TAB_ACTIVE_FOREGROUND, TAB_INACTIVE_FOREGROUND, PANEL_ACTIVE_TITLE_BORDER } from 'vs/workbench/common/theme';
import { PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_INACTIVE_TITLE_FOREGROUND, PANEL_ACTIVE_TITLE_BORDER } from 'vs/workbench/common/theme';
import { activeContrastBorder, focusBorder } from 'vs/platform/theme/common/colorRegistry';
registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
// Title Active
const titleActive = theme.getColor(TAB_ACTIVE_FOREGROUND);
const titleActive = theme.getColor(PANEL_ACTIVE_TITLE_FOREGROUND);
const titleActiveBorder = theme.getColor(PANEL_ACTIVE_TITLE_BORDER);
if (titleActive || titleActiveBorder) {
collector.addRule(`
.tabbedPanel > .title > .tabList .tab:hover .tabLabel,
.tabbedPanel > .title > .tabList .tab .tabLabel.active {
.tabbedPanel > .title .tabList .tab:hover .tabLabel,
.tabbedPanel > .title .tabList .tab .tabLabel.active {
color: ${titleActive};
border-bottom-color: ${titleActiveBorder};
}
.tabbedPanel > .title > .tabList .tab-header.active {
.tabbedPanel > .title .tabList .tab-header.active {
outline: none;
}
`);
}
// Title Inactive
const titleInactive = theme.getColor(TAB_INACTIVE_FOREGROUND);
const titleInactive = theme.getColor(PANEL_INACTIVE_TITLE_FOREGROUND);
if (titleInactive) {
collector.addRule(`
.tabbedPanel > .title > .tabList .tab .tabLabel {
.tabbedPanel > .title .tabList .tab .tabLabel {
color: ${titleInactive};
}
`);
@@ -41,7 +41,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const focusBorderColor = theme.getColor(focusBorder);
if (focusBorderColor) {
collector.addRule(`
.tabbedPanel > .title > .tabList .tab .tabLabel:focus {
.tabbedPanel > .title .tabList .tab .tabLabel:focus {
color: ${titleActive};
border-bottom-color: ${focusBorderColor} !important;
border-bottom: 1px solid;
@@ -54,8 +54,8 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const outline = theme.getColor(activeContrastBorder);
if (outline) {
collector.addRule(`
.tabbedPanel > .title > .tabList .tab-header.active,
.tabbedPanel > .title > .tabList .tab-header:hover {
.tabbedPanel > .title .tabList .tab-header.active,
.tabbedPanel > .title .tabList .tab-header:hover {
outline-color: ${outline};
outline-width: 1px;
outline-style: solid;
@@ -63,7 +63,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
outline-offset: -5px;
}
.tabbedPanel > .title > .tabList .tab-header:hover:not(.active) {
.tabbedPanel > .title .tabList .tab-header:hover:not(.active) {
outline-style: dashed;
}
`);

View File

@@ -2,7 +2,7 @@
* 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, ContentChild, OnDestroy } from '@angular/core';
import { Component, Input, ContentChild, OnDestroy, TemplateRef, ChangeDetectorRef, forwardRef, Inject } from '@angular/core';
import { Action } from 'vs/base/common/actions';
@@ -13,13 +13,14 @@ export abstract class TabChild {
@Component({
selector: 'tab',
template: `
<div class="visibility" [class.hidden]="!active && visibilityType == 'visibility'" *ngIf="visibilityType == 'visibility' || active" class="fullsize">
<ng-content class="body fullsize"></ng-content>
<div role="tabpanel" [attr.aria-labelledby]="identifier" tabindex="0" class="visibility" [class.hidden]="shouldBeHidden()" *ngIf="shouldBeIfed()" class="fullsize">
<ng-container *ngTemplateOutlet="templateRef"></ng-container>
</div>
`
})
export class TabComponent implements OnDestroy {
@ContentChild(TabChild) private _child: TabChild;
@ContentChild(TemplateRef) templateRef;
@Input() public title: string;
@Input() public canClose: boolean;
@Input() public actions: Array<Action>;
@@ -27,9 +28,18 @@ export class TabComponent implements OnDestroy {
public _active = false;
@Input() public identifier: string;
@Input() private visibilityType: 'if' | 'visibility' = 'if';
private rendered = false;
constructor(
@Inject(forwardRef(() => ChangeDetectorRef)) private _cd: ChangeDetectorRef
) { }
public set active(val: boolean) {
this._active = val;
if (this.active) {
this.rendered = true;
}
this._cd.detectChanges();
if (this.active && this._child) {
this._child.layout();
}
@@ -45,4 +55,21 @@ export class TabComponent implements OnDestroy {
}
}
shouldBeIfed(): boolean {
if (this.active) {
return true;
} else if (this.visibilityType === 'visibility' && this.rendered) {
return true;
} else {
return false;
}
}
shouldBeHidden(): boolean {
if (this.visibilityType === 'visibility' && !this.active) {
return true;
} else {
return false;
}
}
}

View File

@@ -19,8 +19,8 @@ import { CloseTabAction } from './tabActions';
@Component({
selector: 'tab-header',
template: `
<div #actionHeader class="tab-header" style="flex: 0 0; flex-direction: row;" [class.active]="tab.active" tabindex="0" (keyup)="onKey($event)">
<span class="tab" (click)="selectTab(tab)" role="tab" [attr.aria-selected]="tab.active" [attr.aria-label]="tab.title">
<div #actionHeader role="presentation" class="tab-header" style="flex: 0 0; flex-direction: row; height: 100%" [class.active]="tab.active" tabindex="0" (keyup)="onKey($event)">
<span class="tab" (click)="selectTab(tab)" role="tab" [attr.aria-selected]="tab.active" [attr.aria-controls]="tab.title">
<a class="tabLabel" [class.active]="tab.active" #tabLabel>
</a>
</span>
@@ -31,6 +31,7 @@ import { CloseTabAction } from './tabActions';
export class TabHeaderComponent extends Disposable implements AfterContentInit, OnDestroy {
@Input() public tab: TabComponent;
@Input() public showIcon: boolean;
@Input() public active: boolean;
@Output() public onSelectTab: EventEmitter<TabComponent> = new EventEmitter<TabComponent>();
@Output() public onCloseTab: EventEmitter<TabComponent> = new EventEmitter<TabComponent>();

View File

@@ -0,0 +1,83 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as DOM from 'vs/base/browser/dom';
import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';
import { Color } from 'vs/base/common/color';
import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox';
import Event, { Emitter } from 'vs/base/common/event';
import { Widget } from 'vs/base/browser/ui/widget';
export interface IRadioButtonOptions {
label: string;
enabled?: boolean;
checked?: boolean;
}
export class RadioButton extends Widget {
private inputElement: HTMLInputElement;
private _onClicked = new Emitter<void>();
public readonly onClicked: Event<void> = this._onClicked.event;
private _label: HTMLSpanElement;
constructor(container: HTMLElement, opts: IRadioButtonOptions) {
super();
this.inputElement = document.createElement('input');
this.inputElement.type = 'radio';
this._label = document.createElement('span');
this.label = opts.label;
this.enabled = opts.enabled || true;
this.checked = opts.checked || false;
this.onclick(this.inputElement, () => this._onClicked.fire());
container.appendChild(this.inputElement);
container.appendChild(this._label);
}
public set name(value: string) {
this.inputElement.setAttribute('name', value);
}
public get name(): string {
return this.inputElement.getAttribute('name');
}
public set value(value: string) {
this.inputElement.setAttribute('value', value);
}
public get value(): string {
return this.inputElement.getAttribute('value');
}
public set checked(val: boolean) {
this.inputElement.checked = val;
}
public get checked(): boolean {
return this.inputElement.checked;
}
public set enabled(val: boolean) {
this.inputElement.disabled = !val;
}
public get enabled(): boolean {
return !this.inputElement.disabled;
}
public isEnabled(): boolean {
return !this.inputElement.hasAttribute('disabled');
}
public set label(val: string) {
this._label.innerText = val;
}
}

View File

@@ -3,11 +3,11 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Directive, Inject, forwardRef, ElementRef } from '@angular/core';
import { Directive, Inject, forwardRef, ElementRef, Input } from '@angular/core';
import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
import { getContentHeight, addDisposableListener, EventType } from 'vs/base/browser/dom';
import { getContentHeight, addDisposableListener, EventType, getContentWidth } from 'vs/base/browser/dom';
import { AngularDisposable } from 'sql/base/common/lifecycle';
@Directive({
@@ -17,33 +17,45 @@ export class ScrollableDirective extends AngularDisposable {
private scrollableElement: ScrollableElement;
private parent: HTMLElement;
private scrolled: HTMLElement;
@Input() horizontalScroll: ScrollbarVisibility;
@Input() verticalScroll: ScrollbarVisibility;
@Input() useShadow = false;
@Input() scrollYToX = false;
constructor(
@Inject(forwardRef(() => ElementRef)) private _el: ElementRef
) {
super();
}
ngOnInit() {
this.scrolled = this._el.nativeElement as HTMLElement;
this.parent = this.scrolled.parentElement;
const next = this.scrolled.nextSibling;
this.parent.removeChild(this.scrolled);
this.scrolled.style.position = 'relative';
this.scrollableElement = new ScrollableElement(this.scrolled, {
horizontal: ScrollbarVisibility.Hidden,
vertical: ScrollbarVisibility.Auto,
useShadows: false
horizontal: this.horizontalScroll,
vertical: this.verticalScroll,
useShadows: this.useShadow,
scrollYToX: this.scrollYToX,
horizontalScrollbarSize: 3
});
this.scrollableElement.onScroll(e => {
this.scrolled.style.bottom = e.scrollTop + 'px';
if (this.verticalScroll === ScrollbarVisibility.Auto) {
this.scrolled.style.bottom = e.scrollTop + 'px';
} else if (this.horizontalScroll === ScrollbarVisibility.Auto) {
this.scrolled.scrollLeft = e.scrollLeft;
}
});
this.parent.appendChild(this.scrollableElement.getDomNode());
this.parent.insertBefore(this.scrollableElement.getDomNode(), next);
const initialHeight = getContentHeight(this.scrolled);
this.scrollableElement.setScrollDimensions({
scrollHeight: getContentHeight(this.scrolled),
height: getContentHeight(this.parent)
});
const initalWidth = getContentWidth(this.scrolled);
this.resetScrollDimensions();
this._register(addDisposableListener(window, EventType.RESIZE, () => {
this.resetScrollDimensions();
@@ -52,24 +64,23 @@ export class ScrollableDirective extends AngularDisposable {
// unforunately because of angular rendering behavior we need to do a double check to make sure nothing changed after this point
setTimeout(() => {
let currentheight = getContentHeight(this.scrolled);
if (initialHeight !== currentheight) {
this.scrollableElement.setScrollDimensions({
scrollHeight: currentheight,
height: getContentHeight(this.parent)
});
let currentWidth = getContentWidth(this.scrolled);
if (initialHeight !== currentheight || initalWidth !== currentWidth) {
this.resetScrollDimensions();
}
}, 200);
}
private resetScrollDimensions() {
this.scrollableElement.setScrollDimensions({
scrollHeight: getContentHeight(this.scrolled),
height: getContentHeight(this.parent)
scrollHeight: this.verticalScroll === ScrollbarVisibility.Auto ? getContentHeight(this.scrolled) : undefined,
height: this.verticalScroll === ScrollbarVisibility.Auto ? getContentHeight(this.parent) : undefined,
scrollWidth: this.horizontalScroll === ScrollbarVisibility.Auto ? this.scrolled.scrollWidth : undefined,
width: this.horizontalScroll === ScrollbarVisibility.Auto ? this.scrolled.offsetWidth : undefined
});
}
public layout() {
this.resetScrollDimensions();
}
}

View File

@@ -0,0 +1,15 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ScrollableDirective } from './scrollable.directive';
@NgModule({
imports: [CommonModule],
exports: [ScrollableDirective],
declarations: [ScrollableDirective]
})
export class ScrollableModule { }

View File

@@ -67,7 +67,7 @@ export class AutoColumnSize<T> implements Slick.Plugin<T> {
let rowEl = this.createRow(columnDef);
let data = this._grid.getData();
let viewPort = this._grid.getViewport();
let start = Math.max(0, viewPort.top + 1);
let start = Math.max(0, viewPort.top);
let end = Math.min(data.getLength(), viewPort.bottom);
for (let i = start; i < end; i++) {
texts.push(data.getItem(i)[columnDef.field]);

View File

@@ -131,6 +131,14 @@
background: url("filter_inverse.svg") center center no-repeat !important;
}
.vs .icon.filterLabel {
background-image: url("filter.svg");
}
.vs-dark .icon.filterLabel,
.hc-black .icon.filterLabel {
background-image: url("filter_inverse.svg");
}
.vs .icon.warning-badge,
.vs-dark .icon.warning-badge,

View File

@@ -34,20 +34,28 @@ import { AccountProviderAddedEventParams, UpdateAccountListEventParams } from 's
import { FixedListView } from 'sql/platform/views/fixedListView';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
export interface IProviderViewUiComponent {
view: FixedListView<sqlops.Account>;
addAccountAction: AddAccountAction;
}
export class AccountDialog extends Modal {
public static ACCOUNTLIST_HEIGHT = 77;
public viewModel: AccountViewModel;
// MEMBER VARIABLES ////////////////////////////////////////////////////
private _providerViews: { [providerId: string]: FixedListView<sqlops.Account> } = {};
private _providerViews: { [providerId: string]: IProviderViewUiComponent } = {};
private _closeButton: Button;
private _addAccountButton: Button;
private _delegate: AccountListDelegate;
private _accountRenderer: AccountListRenderer;
private _actionRunner: ActionRunner;
private _splitView: SplitView;
private _container: HTMLElement;
private _splitViewContainer: HTMLElement;
private _noaccountViewContainer: HTMLElement;
// EVENTING ////////////////////////////////////////////////////////////
private _onAddAccountErrorEmitter: Emitter<string>;
@@ -89,6 +97,14 @@ export class AccountDialog extends Modal {
this.viewModel.addProviderEvent(arg => { self.addProvider(arg); });
this.viewModel.removeProviderEvent(arg => { self.removeProvider(arg); });
this.viewModel.updateAccountListEvent(arg => { self.updateProviderAccounts(arg); });
// Load the initial contents of the view model
this.viewModel.initialize()
.then(addedProviders => {
for (let addedProvider of addedProviders) {
self.addProvider(addedProvider);
}
});
}
// MODAL OVERRIDE METHODS //////////////////////////////////////////////
@@ -104,26 +120,35 @@ export class AccountDialog extends Modal {
attachModalDialogStyler(this, this._themeService);
this._closeButton = this.addFooterButton(localize('accountDialog.close', 'Close'), () => this.close());
this.registerListeners();
// Load the initial contents of the view model
this.viewModel.initialize()
.then(addedProviders => {
for (let addedProvider of addedProviders) {
self.addProvider(addedProvider);
}
});
}
protected renderBody(container: HTMLElement) {
this._container = container;
let viewBody = DOM.$('div.account-view');
DOM.append(container, viewBody);
this._splitView = new SplitView(viewBody);
this._splitViewContainer = DOM.$('div.account-view');
DOM.append(container, this._splitViewContainer);
this._splitView = new SplitView(this._splitViewContainer);
this._noaccountViewContainer = DOM.$('div.no-account-view');
let noAccountTitle = DOM.append(this._noaccountViewContainer, DOM.$('.no-account-view-label'));
let noAccountLabel = localize('accountDialog.noAccountLabel', 'There is no linked account. Please add an acount.');
noAccountTitle.innerHTML = noAccountLabel;
// Show the add account button for the first provider
// Todo: If we have more than 1 provider, need to show all add account buttons for all providers
let buttonSection = DOM.append(this._noaccountViewContainer, DOM.$('div.button-section'));
this._addAccountButton = new Button(buttonSection);
this._addAccountButton.label = localize('accountDialog.addConnection', 'Add an account');
this._register(this._addAccountButton.onDidClick(() => {
(<IProviderViewUiComponent>Object.values(this._providerViews)[0]).addAccountAction.run();
}));
DOM.append(container, this._noaccountViewContainer);
}
private registerListeners(): void {
// Theme styler
this._register(attachButtonStyler(this._closeButton, this._themeService));
this._register(attachButtonStyler(this._addAccountButton, this._themeService));
}
/* Overwrite escape key behavior */
@@ -143,12 +168,48 @@ export class AccountDialog extends Modal {
public open() {
this.show();
if (!this.isEmptyLinkedAccount()) {
this.showSplitView();
} else {
this._splitViewContainer.hidden = true;
this._noaccountViewContainer.hidden = false;
this._addAccountButton.focus();
}
}
private showSplitView() {
this._splitViewContainer.hidden = false;
this._noaccountViewContainer.hidden = true;
let views = this._splitView.getViews();
if (views && views.length > 0) {
let firstView = views[0];
if (firstView instanceof FixedListView) {
firstView.list.setSelection([0]);
firstView.list.domFocus();
}
}
}
private isEmptyLinkedAccount(): boolean {
for (var providerId in this._providerViews) {
var listView = this._providerViews[providerId].view;
if (listView && listView.list.length > 0) {
return false;
}
}
return true;
}
public dispose(): void {
super.dispose();
for (let key in this._providerViews) {
this._providerViews[key].dispose();
if (this._providerViews[key].addAccountAction) {
this._providerViews[key].addAccountAction.dispose();
}
if (this._providerViews[key].view) {
this._providerViews[key].view.dispose();
}
delete this._providerViews[key];
}
}
@@ -199,21 +260,26 @@ export class AccountDialog extends Modal {
// Set the initial items of the list
providerView.updateList(newProvider.initialAccounts);
if (newProvider.initialAccounts.length > 0 && this._splitViewContainer.hidden) {
this.showSplitView();
}
this.layout();
// Store the view for the provider
this._providerViews[newProvider.addedProvider.id] = providerView;
// Store the view for the provider and action
this._providerViews[newProvider.addedProvider.id] = { view: providerView, addAccountAction: addAccountAction };
}
private removeProvider(removedProvider: sqlops.AccountProviderMetadata) {
// Skip removing the provider if it doesn't exist
let providerView = this._providerViews[removedProvider.id];
if (!providerView) {
if (!providerView || !providerView.view) {
return;
}
// Remove the list view from the split view
this._splitView.removeView(providerView);
this._splitView.removeView(providerView.view);
this._splitView.layout(DOM.getContentHeight(this._container));
// Remove the list view from our internal map
@@ -223,10 +289,15 @@ export class AccountDialog extends Modal {
private updateProviderAccounts(args: UpdateAccountListEventParams) {
let providerMapping = this._providerViews[args.providerId];
if (!providerMapping) {
if (!providerMapping || !providerMapping.view) {
return;
}
providerMapping.updateList(args.accountList);
providerMapping.view.updateList(args.accountList);
if (args.accountList.length > 0 && this._splitViewContainer.hidden) {
this.showSplitView();
}
this.layout();
}
}

View File

@@ -2,9 +2,49 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.no-account-view {
font-size: 12px;
padding: 15px;
}
.account-view .monaco-split-view .split-view-view .header {
.no-account-view .no-account-view-label {
padding-bottom: 15px;
}
.account-view .header {
position: relative;
line-height: 22px;
font-size: 11px;
font-weight: bold;
text-transform: uppercase;
padding-left: 20px;
padding-right: 12px;
overflow: hidden;
display: flex;
}
.account-view .header .title {
display: flex;
justify-content: flex-start;
flex: 1 1 auto;
}
.account-view .header .actions {
display: flex;
justify-content: flex-end;
}
.account-view .header .actions .action-item .action-label {
width: 30px;
background-size: 16px;
background-position: center center;
background-repeat: no-repeat;
margin-right: 0;
height: 22px;
}
.account-view .header .count-badge-wrapper {
justify-content: flex-end;
}
.account-view .provider-view .list-row {
@@ -58,24 +98,4 @@
.account-view .provider-view .monaco-list .monaco-list-row.selected .list-row .actions-container,
.account-view .provider-view .monaco-list .monaco-list-row.focused .list-row .actions-container{
display: block;
}
.account-view .split-view-view .header .title {
display: flex;
justify-content: flex-start;
flex: 1 1 auto;
}
.account-view .split-view-view .header .actions {
display: flex;
justify-content: flex-end;
}
.account-view .split-view-view .header .actions .action-item .action-label {
width: 30px;
background-size: 16px;
background-position: center center;
background-repeat: no-repeat;
margin-right: 0;
height: 22px;
}

View File

@@ -205,11 +205,11 @@ export class FirewallRuleDialog extends Modal {
this._register(this._themeService.onDidColorThemeChange(e => this.updateTheme(e)));
this.updateTheme(this._themeService.getColorTheme());
jQuery(this._IPAddressInput).on('click', () => {
$(this._IPAddressInput).on(DOM.EventType.CLICK, () => {
this.onFirewallRuleOptionSelected(true);
});
jQuery(this._subnetIPRangeInput).on('click', () => {
$(this._subnetIPRangeInput).on(DOM.EventType.CLICK, () => {
this.onFirewallRuleOptionSelected(false);
});
}

View File

@@ -5,8 +5,8 @@
import { ChangeDetectorRef, ElementRef, Component, forwardRef, Inject } from '@angular/core';
import { NgForm } from '@angular/forms';
import { IBootstrapService, BOOTSTRAP_SERVICE_ID } from 'sql/services/bootstrap/bootstrapService';
import { TaskDialogComponentParams } from 'sql/services/bootstrap/bootstrapParams';
import { ITaskDialogComponentParams } from 'sql/services/bootstrap/bootstrapParams';
import { ConnectionManagementInfo } from 'sql/parts/connection/common/connectionManagementInfo';
import { IAdminService } from 'sql/parts/admin/common/adminService';
import { ITaskDialogComponent } from 'sql/parts/tasks/common/tasks';
@@ -31,8 +31,6 @@ export interface DatabaseFile {
})
export class CreateDatabaseComponent implements ITaskDialogComponent {
private _adminService: IAdminService;
public formSubmitted: boolean = false;
public ownerUri: string;
@@ -49,9 +47,8 @@ export class CreateDatabaseComponent implements ITaskDialogComponent {
constructor(
@Inject(forwardRef(() => ElementRef)) private _el: ElementRef,
@Inject(forwardRef(() => ChangeDetectorRef)) private _changeDetectorRef: ChangeDetectorRef,
@Inject(BOOTSTRAP_SERVICE_ID) private _bootstrapService: IBootstrapService
@Inject(IAdminService) private _adminService: IAdminService
) {
this._adminService = this._bootstrapService.adminService;
}
private getDatabaseInfo(form: NgForm): sqlops.DatabaseInfo {
@@ -77,7 +74,7 @@ export class CreateDatabaseComponent implements ITaskDialogComponent {
public onSelectOwner(): void { }
public injectBootstapper(parameters: TaskDialogComponentParams): void {
public injectBootstapper(parameters: ITaskDialogComponentParams): void {
let self = this;
this.ownerUri = parameters.ownerUri;
this._adminService.getDefaultDatabaseInfo(this.ownerUri).then(dbInfo => {

View File

@@ -4,8 +4,8 @@
*--------------------------------------------------------------------------------------------*/
import { ElementRef, Component, Inject, forwardRef } from '@angular/core';
import { IBootstrapService, BOOTSTRAP_SERVICE_ID } from 'sql/services/bootstrap/bootstrapService';
import { DashboardComponentParams } from 'sql/services/bootstrap/bootstrapParams';
import { IBootstrapParams } from 'sql/services/bootstrap/bootstrapService';
import { IDashboardComponentParams } from 'sql/services/bootstrap/bootstrapParams';
import { ConnectionManagementInfo } from 'sql/parts/connection/common/connectionManagementInfo';
export const CREATELOGIN_SELECTOR: string = 'createlogin-component';
@@ -22,9 +22,7 @@ export class CreateLoginComponent {
constructor(
@Inject(forwardRef(() => ElementRef)) private _el: ElementRef,
@Inject(BOOTSTRAP_SERVICE_ID) private _bootstrapService: IBootstrapService
@Inject(IBootstrapParams) private _params: IDashboardComponentParams
) {
let parameters: DashboardComponentParams = this._bootstrapService.getBootstrapParams(this._el.nativeElement.tagName);
}
}

View File

@@ -3,37 +3,43 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { NgModule, Inject, forwardRef, ApplicationRef, ComponentFactoryResolver } from '@angular/core';
import { NgModule, Inject, forwardRef, ApplicationRef, ComponentFactoryResolver, Type } from '@angular/core';
import { APP_BASE_HREF, CommonModule } from '@angular/common';
import { BrowserModule } from '@angular/platform-browser';
import { IBootstrapService, BOOTSTRAP_SERVICE_ID } from 'sql/services/bootstrap/bootstrapService';
import { IBootstrapParams } from 'sql/services/bootstrap/bootstrapService';
import { CreateLoginComponent, CREATELOGIN_SELECTOR } from 'sql/parts/admin/security/createLogin.component';
// Connection Dashboard main angular module
@NgModule({
declarations: [
CreateLoginComponent
],
entryComponents: [CreateLoginComponent],
imports: [
CommonModule,
BrowserModule
],
providers: [{ provide: APP_BASE_HREF, useValue: '/' }]
})
export class CreateLoginModule {
export const CreateLoginModule = (params: IBootstrapParams, selector: string): Type<any> => {
constructor(
@Inject(forwardRef(() => ComponentFactoryResolver)) private _resolver: ComponentFactoryResolver,
@Inject(BOOTSTRAP_SERVICE_ID) private _bootstrapService: IBootstrapService
) {
@NgModule({
declarations: [
CreateLoginComponent
],
entryComponents: [CreateLoginComponent],
imports: [
CommonModule,
BrowserModule
],
providers: [
{ provide: APP_BASE_HREF, useValue: '/' },
{ provide: IBootstrapParams, useValue: params }
]
})
class ModuleClass {
constructor(
@Inject(forwardRef(() => ComponentFactoryResolver)) private _resolver: ComponentFactoryResolver
) {
}
ngDoBootstrap(appRef: ApplicationRef) {
const factory = this._resolver.resolveComponentFactory(CreateLoginComponent);
(<any>factory).factory.selector = selector;
appRef.bootstrap(factory);
}
}
ngDoBootstrap(appRef: ApplicationRef) {
const factory = this._resolver.resolveComponentFactory(CreateLoginComponent);
const uniqueSelector: string = this._bootstrapService.getUniqueSelector(CREATELOGIN_SELECTOR);
(<any>factory).factory.selector = uniqueSelector;
appRef.bootstrap(factory);
}
}
return ModuleClass;
};

View File

@@ -17,8 +17,7 @@ import { IConnectionManagementService } from 'sql/parts/connection/common/connec
import { IMetadataService } from 'sql/services/metadata/metadataService';
import { IScriptingService } from 'sql/services/scripting/scriptingService';
import { IQueryEditorService } from 'sql/parts/query/common/queryEditorService';
import { IBootstrapService } from 'sql/services/bootstrap/bootstrapService';
import { BootstrapParams } from 'sql/services/bootstrap/bootstrapParams';
import { bootstrapAngular, IBootstrapParams } from 'sql/services/bootstrap/bootstrapService';
import { CREATELOGIN_SELECTOR } from 'sql/parts/admin/security/createLogin.component';
export class CreateLoginEditor extends BaseEditor {
@@ -32,8 +31,7 @@ export class CreateLoginEditor extends BaseEditor {
@IConnectionManagementService private _connectionService: IConnectionManagementService,
@IMetadataService private _metadataService: IMetadataService,
@IScriptingService private _scriptingService: IScriptingService,
@IQueryEditorService private _queryEditorService: IQueryEditorService,
@IBootstrapService private _bootstrapService: IBootstrapService
@IQueryEditorService private _queryEditorService: IQueryEditorService
) {
super(CreateLoginEditor.ID, telemetryService, themeService);
}
@@ -96,11 +94,11 @@ export class CreateLoginEditor extends BaseEditor {
private bootstrapAngular(input: CreateLoginInput): void {
// Get the bootstrap params and perform the bootstrap
let params: BootstrapParams = {
let params: IBootstrapParams = {
connection: input.getConnectionProfile(),
ownerUri: input.getUri()
};
let uniqueSelector = this._bootstrapService.bootstrap(
let uniqueSelector = this.instantiationService.invokeFunction(bootstrapAngular,
CreateLoginModule,
this.getContainer().getHTMLElement(),
CREATELOGIN_SELECTOR,

View File

@@ -5,8 +5,10 @@
import * as types from 'vs/base/common/types';
import { generateUuid } from 'vs/base/common/uuid';
import { Registry } from 'vs/platform/registry/common/platform';
import { error } from 'sql/base/common/log';
import * as nls from 'vs/nls';
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { error } from 'sql/base/common/log';
import { WidgetConfig } from 'sql/parts/dashboard/common/dashboardWidget';
import { Extensions, IInsightRegistry } from 'sql/platform/dashboard/common/insightRegistry';
import { ConnectionManagementInfo } from 'sql/parts/connection/common/connectionManagementInfo';
@@ -19,7 +21,7 @@ import { CONTROLHOST_CONTAINER } from 'sql/parts/dashboard/containers/dashboardC
import { NAV_SECTION } from 'sql/parts/dashboard/containers/dashboardNavSection.contribution';
import { IDashboardContainerRegistry, Extensions as DashboardContainerExtensions, IDashboardContainer, registerContainerType } from 'sql/platform/dashboard/common/dashboardContainerRegistry';
import { IDashboardTab } from 'sql/platform/dashboard/common/dashboardRegistry';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { SingleConnectionManagementService } from 'sql/services/common/commonServiceInterface.service';
const dashboardcontainerRegistry = Registry.as<IDashboardContainerRegistry>(DashboardContainerExtensions.dashboardContainerContributions);
const containerTypes = [
@@ -118,8 +120,8 @@ export function initExtensionConfigs(configurations: WidgetConfig[]): Array<Widg
* Add provider to the passed widgets and returns the new widgets
* @param widgets Array of widgets to add provider onto
*/
export function addProvider(config: WidgetConfig[], dashboardService: DashboardServiceInterface): Array<WidgetConfig> {
let provider = dashboardService.connectionManagementService.connectionInfo.providerId;
export function addProvider<T extends { connectionManagementService: SingleConnectionManagementService }>(config: WidgetConfig[], collection: T): Array<WidgetConfig> {
let provider = collection.connectionManagementService.connectionInfo.providerId;
return config.map((item) => {
if (item.provider === undefined) {
item.provider = provider;
@@ -132,8 +134,8 @@ export function addProvider(config: WidgetConfig[], dashboardService: DashboardS
* Adds the edition to the passed widgets and returns the new widgets
* @param widgets Array of widgets to add edition onto
*/
export function addEdition(config: WidgetConfig[], dashboardService: DashboardServiceInterface): Array<WidgetConfig> {
let connectionInfo: ConnectionManagementInfo = dashboardService.connectionManagementService.connectionInfo;
export function addEdition<T extends { connectionManagementService: SingleConnectionManagementService }>(config: WidgetConfig[], collection: DashboardServiceInterface): Array<WidgetConfig> {
let connectionInfo: ConnectionManagementInfo = collection.connectionManagementService.connectionInfo;
let edition = connectionInfo.serverInfo.engineEditionId;
return config.map((item) => {
if (item.edition === undefined) {
@@ -147,7 +149,7 @@ export function addEdition(config: WidgetConfig[], dashboardService: DashboardSe
* Adds the context to the passed widgets and returns the new widgets
* @param widgets Array of widgets to add context to
*/
export function addContext(config: WidgetConfig[], dashboardServer: DashboardServiceInterface, context: string): Array<WidgetConfig> {
export function addContext(config: WidgetConfig[], collection: any, context: string): Array<WidgetConfig> {
return config.map((item) => {
if (item.context === undefined) {
item.context = context;
@@ -160,12 +162,12 @@ export function addContext(config: WidgetConfig[], dashboardServer: DashboardSer
* Returns a filtered version of the widgets passed based on edition and provider
* @param config widgets to filter
*/
export function filterConfigs<T extends { when?: string }>(config: T[], dashboardService: DashboardServiceInterface): Array<T> {
export function filterConfigs<T extends { when?: string }, K extends { contextKeyService: IContextKeyService }>(config: T[], collection: K): Array<T> {
return config.filter((item) => {
if (!item.when) {
return true;
} else {
return dashboardService.contextKeyService.contextMatchesRules(ContextKeyExpr.deserialize(item.when));
return collection.contextKeyService.contextMatchesRules(ContextKeyExpr.deserialize(item.when));
}
});
}

View File

@@ -6,23 +6,25 @@
-->
<panel class="dashboard-panel" (onTabChange)="handleTabChange($event)" (onTabClose)="handleTabClose($event)" [actions]="panelActions">
<tab [visibilityType]="'visibility'" *ngFor="let tab of tabs" [title]="tab.title" class="fullsize" [identifier]="tab.id" [canClose]="tab.canClose" [actions]="tab.actions">
<dashboard-home-container *ngIf="tab.id === 'homeTab'; else not_home" [properties]="propertiesWidget" [tab]="tab">
</dashboard-home-container>
<ng-template #not_home>
<dashboard-webview-container *ngIf="getContentType(tab) === 'webview-container'" [tab]="tab">
</dashboard-webview-container>
<dashboard-widget-container *ngIf="getContentType(tab) === 'widgets-container'" [tab]="tab">
</dashboard-widget-container>
<dashboard-modelview-container *ngIf="getContentType(tab) === 'modelview-container'" [tab]="tab">
</dashboard-modelview-container>
<dashboard-controlhost-container *ngIf="getContentType(tab) === 'controlhost-container'" [tab]="tab">
</dashboard-controlhost-container>
<dashboard-nav-section *ngIf="getContentType(tab) === 'nav-section'" [tab]="tab">
</dashboard-nav-section>
<dashboard-grid-container *ngIf="getContentType(tab) === 'grid-container'" [tab]="tab">
</dashboard-grid-container>
<dashboard-error-container *ngIf="getContentType(tab) === 'error-container'" [tab]="tab">
</dashboard-error-container>
<ng-template>
<dashboard-home-container *ngIf="tab.id === 'homeTab'; else not_home" [properties]="propertiesWidget" [tab]="tab">
</dashboard-home-container>
<ng-template #not_home>
<dashboard-webview-container *ngIf="getContentType(tab) === 'webview-container'" [tab]="tab">
</dashboard-webview-container>
<dashboard-widget-container *ngIf="getContentType(tab) === 'widgets-container'" [tab]="tab">
</dashboard-widget-container>
<dashboard-modelview-container *ngIf="getContentType(tab) === 'modelview-container'" [tab]="tab">
</dashboard-modelview-container>
<dashboard-controlhost-container *ngIf="getContentType(tab) === 'controlhost-container'" [tab]="tab">
</dashboard-controlhost-container>
<dashboard-nav-section *ngIf="getContentType(tab) === 'nav-section'" [tab]="tab">
</dashboard-nav-section>
<dashboard-grid-container *ngIf="getContentType(tab) === 'grid-container'" [tab]="tab">
</dashboard-grid-container>
<dashboard-error-container *ngIf="getContentType(tab) === 'error-container'" [tab]="tab">
</dashboard-error-container>
</ng-template>
</ng-template>
</tab>
</panel>

View File

@@ -9,7 +9,7 @@ import 'sql/parts/dashboard/common/dashboardPanelStyles';
import { Component, Inject, forwardRef, ViewChild, ElementRef, ViewChildren, QueryList, OnDestroy, ChangeDetectorRef } from '@angular/core';
import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service';
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
import { CommonServiceInterface, SingleConnectionManagementService } from 'sql/services/common/commonServiceInterface.service';
import { WidgetConfig, TabConfig, TabSettingConfig } from 'sql/parts/dashboard/common/dashboardWidget';
import { Extensions, IInsightRegistry } from 'sql/platform/dashboard/common/insightRegistry';
import { DashboardWidgetWrapper } from 'sql/parts/dashboard/contents/dashboardWidgetWrapper.component';
@@ -17,9 +17,8 @@ import { IPropertiesConfig } from 'sql/parts/dashboard/pages/serverDashboardPage
import { PanelComponent } from 'sql/base/browser/ui/panel/panel.component';
import { IDashboardRegistry, Extensions as DashboardExtensions, IDashboardTab } from 'sql/platform/dashboard/common/dashboardRegistry';
import { PinUnpinTabAction, AddFeatureTabAction } from './actions';
import { TabComponent } from 'sql/base/browser/ui/panel/tab.component';
import { IBootstrapService, BOOTSTRAP_SERVICE_ID } from 'sql/services/bootstrap/bootstrapService';
import { AngularEventType } from 'sql/services/angularEventing/angularEventingService';
import { TabComponent, TabChild } from 'sql/base/browser/ui/panel/tab.component';
import { AngularEventType, IAngularEventingService } from 'sql/services/angularEventing/angularEventingService';
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
import * as dashboardHelper from 'sql/parts/dashboard/common/dashboardHelper';
import { WIDGETS_CONTAINER } from 'sql/parts/dashboard/containers/dashboardWidgetContainer.contribution';
@@ -40,9 +39,16 @@ import Event, { Emitter } from 'vs/base/common/event';
import { Action } from 'vs/base/common/actions';
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import Severity from 'vs/base/common/severity';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
const dashboardRegistry = Registry.as<IDashboardRegistry>(DashboardExtensions.DashboardContributions);
interface IConfigModifierCollection {
connectionManagementService: SingleConnectionManagementService;
contextKeyService: IContextKeyService;
}
@Component({
selector: 'dashboard-page',
@@ -61,7 +67,7 @@ export abstract class DashboardPage extends AngularDisposable {
private _tabsDispose: Array<IDisposable> = [];
private _tabSettingConfigs: Array<TabSettingConfig> = [];
@ViewChildren(DashboardTab) private _tabs: QueryList<DashboardTab>;
@ViewChildren(TabChild) private _tabs: QueryList<DashboardTab>;
@ViewChild(PanelComponent) private _panel: PanelComponent;
private _editEnabled = new Emitter<boolean>();
@@ -71,7 +77,7 @@ export abstract class DashboardPage extends AngularDisposable {
private readonly homeTabTitle: string = nls.localize('home', 'Home');
// a set of config modifiers
private readonly _configModifiers: Array<(item: Array<WidgetConfig>, dashboardServer: DashboardServiceInterface, context: string) => Array<WidgetConfig>> = [
private readonly _configModifiers: Array<(item: Array<WidgetConfig>, collection: IConfigModifierCollection, context: string) => Array<WidgetConfig>> = [
dashboardHelper.removeEmpty,
dashboardHelper.initExtensionConfigs,
dashboardHelper.addProvider,
@@ -80,27 +86,36 @@ export abstract class DashboardPage extends AngularDisposable {
dashboardHelper.filterConfigs
];
public get connectionManagementService(): SingleConnectionManagementService {
return this.dashboardService.connectionManagementService;
}
public get contextKeyService(): IContextKeyService {
return this.dashboardService.scopedContextKeyService;
}
private readonly _gridModifiers: Array<(item: Array<WidgetConfig>, originalConfig: Array<WidgetConfig>) => Array<WidgetConfig>> = [
dashboardHelper.validateGridConfig
];
protected abstract propertiesWidget: WidgetConfig;
protected abstract get context(): string;
protected dashboardService: DashboardServiceInterface;
constructor(
@Inject(forwardRef(() => CommonServiceInterface)) protected commonService: CommonServiceInterface,
@Inject(forwardRef(() => CommonServiceInterface)) protected dashboardService: DashboardServiceInterface,
@Inject(forwardRef(() => ElementRef)) protected _el: ElementRef,
@Inject(forwardRef(() => ChangeDetectorRef)) protected _cd: ChangeDetectorRef
@Inject(forwardRef(() => ChangeDetectorRef)) protected _cd: ChangeDetectorRef,
@Inject(IInstantiationService) private instantiationService: IInstantiationService,
@Inject(INotificationService) private notificationService: INotificationService,
@Inject(IAngularEventingService) private angularEventingService: IAngularEventingService
) {
super();
this.dashboardService = commonService as DashboardServiceInterface;
}
protected init() {
this.dashboardService.dashboardContextKey.set(this.context);
if (!this.dashboardService.connectionManagementService.connectionInfo) {
this.dashboardService.notificationService.notify({
this.notificationService.notify({
severity: Severity.Error,
message: nls.localize('missingConnectionInfo', 'No connection information could be found for this dashboard')
});
@@ -110,8 +125,8 @@ export abstract class DashboardPage extends AngularDisposable {
this._originalConfig = objects.deepClone(tempWidgets);
let properties = this.getProperties();
this._configModifiers.forEach((cb) => {
tempWidgets = cb.apply(this, [tempWidgets, this.dashboardService, this.context]);
properties = properties ? cb.apply(this, [properties, this.dashboardService, this.context]) : undefined;
tempWidgets = cb.apply(this, [tempWidgets, this, this.context]);
properties = properties ? cb.apply(this, [properties, this, this.context]) : undefined;
});
this._gridModifiers.forEach(cb => {
tempWidgets = cb.apply(this, [tempWidgets, this._originalConfig]);
@@ -142,9 +157,8 @@ export abstract class DashboardPage extends AngularDisposable {
actions: []
};
this.addNewTab(homeTab);
this._panel.selectTab(homeTab.id);
let allTabs = dashboardHelper.filterConfigs(dashboardRegistry.tabs, this.dashboardService);
let allTabs = dashboardHelper.filterConfigs(dashboardRegistry.tabs, this);
// Load tab setting configs
this._tabSettingConfigs = this.dashboardService.getSettings<Array<TabSettingConfig>>([this.context, 'tabs'].join('.'));
@@ -172,7 +186,7 @@ export abstract class DashboardPage extends AngularDisposable {
// Set panel actions
let openedTabs = [...pinnedDashboardTabs, ...alwaysShowTabs];
let addNewTabAction = this.dashboardService.instantiationService.createInstance(AddFeatureTabAction, allTabs, openedTabs, this.dashboardService.getUnderlyingUri());
let addNewTabAction = this.instantiationService.createInstance(AddFeatureTabAction, allTabs, openedTabs, this.dashboardService.getUnderlyingUri());
this._tabsDispose.push(addNewTabAction);
this.panelActions = [addNewTabAction];
this._cd.detectChanges();
@@ -233,7 +247,7 @@ export abstract class DashboardPage extends AngularDisposable {
} else if (v.alwaysShow) {
isPinned = true;
}
actions.push(this.dashboardService.instantiationService.createInstance(PinUnpinTabAction, v.id, this.dashboardService.getUnderlyingUri(), isPinned));
actions.push(this.instantiationService.createInstance(PinUnpinTabAction, v.id, this.dashboardService.getUnderlyingUri(), isPinned));
let config = v as TabConfig;
config.context = this.context;
@@ -254,7 +268,6 @@ export abstract class DashboardPage extends AngularDisposable {
}
}
private getContentType(tab: TabConfig): string {
return tab.container ? Object.keys(tab.container)[0] : '';
}
@@ -310,16 +323,15 @@ export abstract class DashboardPage extends AngularDisposable {
}
public handleTabChange(tab: TabComponent): void {
this._cd.detectChanges();
let localtab = this._tabs.find(i => i.id === tab.identifier);
this._editEnabled.fire(localtab.editable);
this._cd.detectChanges();
localtab.layout();
}
public handleTabClose(tab: TabComponent): void {
let index = this.tabs.findIndex(i => i.id === tab.identifier);
this.tabs.splice(index, 1);
this._cd.detectChanges();
this.dashboardService.angularEventingService.sendAngularEvent(this.dashboardService.getUnderlyingUri(), AngularEventType.CLOSE_TAB, { id: tab.identifier });
this.angularEventingService.sendAngularEvent(this.dashboardService.getUnderlyingUri(), AngularEventType.CLOSE_TAB, { id: tab.identifier });
}
}

View File

@@ -15,22 +15,22 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const tabActiveForeground = theme.getColor(TAB_ACTIVE_FOREGROUND);
if (tabActiveBackground || tabActiveForeground) {
collector.addRule(`
panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab:hover .tabLabel,
panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab .tabLabel.active {
panel.dashboard-panel > .tabbedPanel > .title .tabList .tab:hover .tabLabel,
panel.dashboard-panel > .tabbedPanel > .title .tabList .tab .tabLabel.active {
color: ${tabActiveForeground};
border-bottom: 0px solid;
}
panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab-header.active {
panel.dashboard-panel > .tabbedPanel > .title .tabList .tab-header.active {
background-color: ${tabActiveBackground};
outline-color: ${tabActiveBackground};
}
panel.dashboard-panel > .tabbedPanel.horizontal > .title > .monaco-scrollable-element > .tabList .tab-header.active {
panel.dashboard-panel > .tabbedPanel.horizontal > .title .tabList .tab-header.active {
border-bottom-color: transparent;
}
panel.dashboard-panel > .tabbedPanel.vertical > .title > .monaco-scrollable-element > .tabList .tab-header.active {
panel.dashboard-panel > .tabbedPanel.vertical > .title .tabList .tab-header.active {
border-right-color: transparent;
}
`);
@@ -39,7 +39,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const activeTabBorderColor = theme.getColor(TAB_ACTIVE_BORDER);
if (activeTabBorderColor) {
collector.addRule(`
panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab-header.active {
panel.dashboard-panel > .tabbedPanel > .title .tabList .tab-header.active {
box-shadow: ${activeTabBorderColor} 0 -1px inset;
}
`);
@@ -50,11 +50,11 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
const tabInactiveForeground = theme.getColor(TAB_INACTIVE_FOREGROUND);
if (tabInactiveBackground || tabInactiveForeground) {
collector.addRule(`
panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab .tabLabel {
panel.dashboard-panel > .tabbedPanel > .title .tabList .tab .tabLabel {
color: ${tabInactiveForeground};
}
panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab-header {
panel.dashboard-panel > .tabbedPanel > .title .tabList .tab-header {
background-color: ${tabInactiveBackground};
}
`);
@@ -71,12 +71,12 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
}
// Panel title background
const tabBoarder = theme.getColor(TAB_BORDER);
if (tabBoarder) {
const tabBorder = theme.getColor(TAB_BORDER);
if (tabBorder) {
collector.addRule(`
panel.dashboard-panel > .tabbedPanel > .title > .monaco-scrollable-element > .tabList .tab-header {
border-right-color: ${tabBoarder};
border-bottom-color: ${tabBoarder};
panel.dashboard-panel > .tabbedPanel > .title .tabList .tab-header {
border-right-color: ${tabBorder};
border-bottom-color: ${tabBorder};
}
`);
}
@@ -86,13 +86,13 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
if (outline) {
collector.addRule(`
panel.dashboard-panel > .tabbedPanel > .title {
border-bottom-color: ${tabBoarder};
border-bottom-color: ${tabBorder};
border-bottom-width: 1px;
border-bottom-style: solid;
}
panel.dashboard-panel > .tabbedPanel.vertical > .title {
border-right-color: ${tabBoarder};
border-right-color: ${tabBorder};
border-right-width: 1px;
border-right-style: solid;
}

View File

@@ -3,9 +3,13 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { OnDestroy } from '@angular/core';
import Event from 'vs/base/common/event';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { AngularDisposable } from 'sql/base/common/lifecycle';
import { TabChild } from 'sql/base/browser/ui/panel/tab.component';
export enum Conditional {
'equals',
@@ -17,7 +21,7 @@ export enum Conditional {
'always'
}
export abstract class DashboardTab extends AngularDisposable {
export abstract class DashboardTab extends TabChild implements OnDestroy {
public abstract layout(): void;
public abstract readonly id: string;
public abstract readonly editable: boolean;
@@ -26,4 +30,23 @@ export abstract class DashboardTab extends AngularDisposable {
public enableEdit(): void {
// no op
}
private _toDispose: IDisposable[] = [];
constructor() {
super();
}
public dispose(): void {
this._toDispose = dispose(this._toDispose);
}
protected _register<T extends IDisposable>(t: T): T {
this._toDispose.push(t);
return t;
}
ngOnDestroy() {
this.dispose();
}
}

View File

@@ -5,14 +5,17 @@
import 'vs/css!./dashboardControlHostContainer';
import { Component, forwardRef, Input, AfterContentInit, ViewChild, OnChanges } from '@angular/core';
import Event, { Emitter } from 'vs/base/common/event';
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
import { TabConfig } from 'sql/parts/dashboard/common/dashboardWidget';
import { ControlHostContent } from 'sql/parts/dashboard/contents/controlHostContent.component';
import { TabChild } from 'sql/base/browser/ui/panel/tab.component';
@Component({
selector: 'dashboard-controlhost-container',
providers: [{ provide: DashboardTab, useExisting: forwardRef(() => DashboardControlHostContainer) }],
providers: [{ provide: TabChild, useExisting: forwardRef(() => DashboardControlHostContainer) }],
template: `
<controlhost-content [webviewId]="tab.id">
</controlhost-content>

View File

@@ -9,13 +9,14 @@ import { Component, Inject, Input, forwardRef, ViewChild, ElementRef, ChangeDete
import { TabConfig } from 'sql/parts/dashboard/common/dashboardWidget';
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
import { TabChild } from 'sql/base/browser/ui/panel/tab.component';
import Event, { Emitter } from 'vs/base/common/event';
import * as nls from 'vs/nls';
@Component({
selector: 'dashboard-error-container',
providers: [{ provide: DashboardTab, useExisting: forwardRef(() => DashboardErrorContainer) }],
providers: [{ provide: TabChild, useExisting: forwardRef(() => DashboardErrorContainer) }],
template: `
<div class="error-container">
<div class="icon globalError">

View File

@@ -7,6 +7,7 @@ import 'vs/css!./dashboardGridContainer';
import { Component, Inject, Input, forwardRef, ViewChild, ElementRef, ViewChildren, QueryList, OnDestroy, ChangeDetectorRef, EventEmitter } from '@angular/core';
import { NgGridConfig, NgGrid, NgGridItem } from 'angular2-grid';
import { concat } from 'rxjs/operator/concat';
import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service';
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
@@ -14,13 +15,13 @@ import { TabConfig, WidgetConfig } from 'sql/parts/dashboard/common/dashboardWid
import { DashboardWidgetWrapper } from 'sql/parts/dashboard/contents/dashboardWidgetWrapper.component';
import { subscriptionToDisposable } from 'sql/base/common/lifecycle';
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
import { WebviewContent } from 'sql/parts/dashboard/contents/webviewContent.component';
import { TabChild } from 'sql/base/browser/ui/panel/tab.component';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import * as objects from 'vs/base/common/objects';
import Event, { Emitter } from 'vs/base/common/event';
import { concat } from 'rxjs/operator/concat';
import { WebviewContent } from 'sql/parts/dashboard/contents/webviewContent.component';
export interface GridCellConfig {
id?: string;
@@ -42,7 +43,7 @@ export interface GridWebviewConfig extends GridCellConfig {
@Component({
selector: 'dashboard-grid-container',
templateUrl: decodeURI(require.toUrl('sql/parts/dashboard/containers/dashboardGridContainer.component.html')),
providers: [{ provide: DashboardTab, useExisting: forwardRef(() => DashboardGridContainer) }]
providers: [{ provide: TabChild, useExisting: forwardRef(() => DashboardGridContainer) }]
})
export class DashboardGridContainer extends DashboardTab implements OnDestroy {
@Input() private tab: TabConfig;

View File

@@ -12,17 +12,20 @@ import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
import { WidgetConfig } from 'sql/parts/dashboard/common/dashboardWidget';
import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service';
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
import { AngularEventType } from 'sql/services/angularEventing/angularEventingService';
import { AngularEventType, IAngularEventingService } from 'sql/services/angularEventing/angularEventingService';
import { DashboardWidgetWrapper } from 'sql/parts/dashboard/contents/dashboardWidgetWrapper.component';
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import { ScrollableDirective } from 'sql/base/browser/ui/scrollable/scrollable.directive';
import { TabChild } from 'sql/base/browser/ui/panel/tab.component';
import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
@Component({
selector: 'dashboard-home-container',
providers: [{ provide: DashboardTab, useExisting: forwardRef(() => DashboardHomeContainer) }],
providers: [{ provide: TabChild, useExisting: forwardRef(() => DashboardHomeContainer) }],
template: `
<div class="fullsize" style="display: flex; flex-direction: column">
<div scrollable>
<div scrollable [horizontalScroll]="ScrollbarVisibility.Hidden" [verticalScroll]="ScrollbarVisibility.Auto">
<dashboard-widget-wrapper #propertiesClass *ngIf="properties" [collapsable]="true" [_config]="properties"
style="padding-left: 10px; padding-right: 10px; display: block; flex: 0" [style.height.px]="_propertiesClass?.collapsed ? '30' : '90'">
</dashboard-widget-wrapper>
@@ -37,9 +40,13 @@ export class DashboardHomeContainer extends DashboardWidgetContainer {
@ViewChild('propertiesClass') private _propertiesClass: DashboardWidgetWrapper;
@ContentChild(ScrollableDirective) private _scrollable;
private ScrollbarVisibility = ScrollbarVisibility;
constructor(
@Inject(forwardRef(() => ChangeDetectorRef)) _cd: ChangeDetectorRef,
@Inject(forwardRef(() => CommonServiceInterface)) protected dashboardService: DashboardServiceInterface
@Inject(forwardRef(() => CommonServiceInterface)) protected dashboardService: DashboardServiceInterface,
@Inject(IConfigurationService) private _configurationService: IConfigurationService,
@Inject(IAngularEventingService) private angularEventingService: IAngularEventingService
) {
super(_cd);
}
@@ -49,20 +56,20 @@ export class DashboardHomeContainer extends DashboardWidgetContainer {
if (collapsedVal === 'collapsed') {
this._propertiesClass.collapsed = true;
}
this.dashboardService.angularEventingService.onAngularEvent(this.dashboardService.getUnderlyingUri(), event => {
this.angularEventingService.onAngularEvent(this.dashboardService.getUnderlyingUri(), event => {
if (event.event === AngularEventType.COLLAPSE_WIDGET && this._propertiesClass && event.payload === this._propertiesClass.guid) {
this._propertiesClass.collapsed = !this._propertiesClass.collapsed;
this._cd.detectChanges();
this.dashboardService.configurationEditingService.writeConfiguration(ConfigurationTarget.USER, {
key: `dashboard.${this.properties.context}.properties`,
value: this._propertiesClass.collapsed ? 'collapsed' : true
});
this._configurationService.updateValue(`dashboard.${this.properties.context}.properties`,
this._propertiesClass.collapsed ? 'collapsed' : true, ConfigurationTarget.USER);
}
});
}
public layout() {
super.layout();
this._scrollable.layout();
if (this._scrollable) {
this._scrollable.layout();
}
}
}

View File

@@ -11,10 +11,11 @@ import Event, { Emitter } from 'vs/base/common/event';
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
import { TabConfig } from 'sql/parts/dashboard/common/dashboardWidget';
import { ModelViewContent } from 'sql/parts/modelComponents/modelViewContent.component';
import { TabChild } from 'sql/base/browser/ui/panel/tab.component';
@Component({
selector: 'dashboard-modelview-container',
providers: [{ provide: DashboardTab, useExisting: forwardRef(() => DashboardModelViewContainer) }],
providers: [{ provide: TabChild, useExisting: forwardRef(() => DashboardModelViewContainer) }],
template: `
<modelview-content [modelViewId]="tab.id">
</modelview-content>

View File

@@ -4,18 +4,20 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-->
<panel [options]="panelOpt" style="flex: 1 1 auto;" class="dashboard-panel" (onTabChange)="handleTabChange($event)">
<panel [options]="panelOpt" style="flex: 1 1 auto;" class="dashboard-panel">
<tab [visibilityType]="'visibility'" *ngFor="let tab of tabs" [title]="tab.title" class="fullsize"
[identifier]="tab.id" [canClose]="tab.canClose" [actions]="tab.actions" [iconClass]="tab.iconClass">
<dashboard-webview-container *ngIf="getContentType(tab) === 'webview-container'" [tab]="tab">
</dashboard-webview-container>
<dashboard-widget-container *ngIf="getContentType(tab) === 'widgets-container'" [tab]="tab">
</dashboard-widget-container>
<dashboard-modelview-container *ngIf="getContentType(tab) === 'modelview-container'" [tab]="tab">
</dashboard-modelview-container>
<dashboard-grid-container *ngIf="getContentType(tab) === 'grid-container'" [tab]="tab">
</dashboard-grid-container>
<dashboard-error-container *ngIf="getContentType(tab) === 'error-container'" [tab]="tab">
</dashboard-error-container>
<ng-template>
<dashboard-webview-container *ngIf="getContentType(tab) === 'webview-container'" [tab]="tab">
</dashboard-webview-container>
<dashboard-widget-container *ngIf="getContentType(tab) === 'widgets-container'" [tab]="tab">
</dashboard-widget-container>
<dashboard-modelview-container *ngIf="getContentType(tab) === 'modelview-container'" [tab]="tab">
</dashboard-modelview-container>
<dashboard-grid-container *ngIf="getContentType(tab) === 'grid-container'" [tab]="tab">
</dashboard-grid-container>
<dashboard-error-container *ngIf="getContentType(tab) === 'error-container'" [tab]="tab">
</dashboard-error-container>
</ng-template>
</tab>
</panel>

View File

@@ -11,7 +11,7 @@ import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboar
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
import { WidgetConfig, TabConfig, NavSectionConfig } from 'sql/parts/dashboard/common/dashboardWidget';
import { PanelComponent, IPanelOptions, NavigationBarLayout } from 'sql/base/browser/ui/panel/panel.component';
import { TabComponent } from 'sql/base/browser/ui/panel/tab.component';
import { TabComponent, TabChild } from 'sql/base/browser/ui/panel/tab.component';
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
import { WIDGETS_CONTAINER } from 'sql/parts/dashboard/containers/dashboardWidgetContainer.contribution';
import { GRID_CONTAINER } from 'sql/parts/dashboard/containers/dashboardGridContainer.contribution';
@@ -23,7 +23,7 @@ import * as nls from 'vs/nls';
@Component({
selector: 'dashboard-nav-section',
providers: [{ provide: DashboardTab, useExisting: forwardRef(() => DashboardNavSection) }],
providers: [{ provide: TabChild, useExisting: forwardRef(() => DashboardNavSection) }],
templateUrl: decodeURI(require.toUrl('sql/parts/dashboard/containers/dashboardNavSection.component.html'))
})
export class DashboardNavSection extends DashboardTab implements OnDestroy, OnChanges, AfterContentInit {
@@ -51,7 +51,7 @@ export class DashboardNavSection extends DashboardTab implements OnDestroy, OnCh
dashboardHelper.validateGridConfig
];
@ViewChildren(DashboardTab) private _tabs: QueryList<DashboardTab>;
@ViewChildren(TabChild) private _tabs: QueryList<DashboardTab>;
@ViewChild(PanelComponent) private _panel: PanelComponent;
constructor(
@Inject(forwardRef(() => CommonServiceInterface)) protected dashboardService: CommonServiceInterface,
@@ -124,11 +124,6 @@ export class DashboardNavSection extends DashboardTab implements OnDestroy, OnCh
this.addNewTab(config);
return config;
});
// put this immediately on the stack so that is ran *after* the tab is rendered
setTimeout(() => {
this._panel.selectTab(selectedTabs[0].id);
});
}
}
@@ -174,10 +169,4 @@ export class DashboardNavSection extends DashboardTab implements OnDestroy, OnCh
});
}
}
public handleTabChange(tab: TabComponent): void {
let localtab = this._tabs.find(i => i.id === tab.identifier);
this._cd.detectChanges();
localtab.layout();
}
}

View File

@@ -11,10 +11,11 @@ import Event, { Emitter } from 'vs/base/common/event';
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
import { TabConfig } from 'sql/parts/dashboard/common/dashboardWidget';
import { WebviewContent } from 'sql/parts/dashboard/contents/webviewContent.component';
import { TabChild } from 'sql/base/browser/ui/panel/tab.component';
@Component({
selector: 'dashboard-webview-container',
providers: [{ provide: DashboardTab, useExisting: forwardRef(() => DashboardWebviewContainer) }],
providers: [{ provide: TabChild, useExisting: forwardRef(() => DashboardWebviewContainer) }],
template: `
<webview-content [webviewId]="tab.id">
</webview-content>

View File

@@ -14,6 +14,7 @@ import { DashboardWidgetWrapper } from 'sql/parts/dashboard/contents/dashboardWi
import { subscriptionToDisposable } from 'sql/base/common/lifecycle';
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
import { WidgetContent } from 'sql/parts/dashboard/contents/widgetContent.component';
import { TabChild } from 'sql/base/browser/ui/panel/tab.component';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
@@ -22,7 +23,7 @@ import Event, { Emitter } from 'vs/base/common/event';
@Component({
selector: 'dashboard-widget-container',
providers: [{ provide: DashboardTab, useExisting: forwardRef(() => DashboardWidgetContainer) }],
providers: [{ provide: TabChild, useExisting: forwardRef(() => DashboardWidgetContainer) }],
template: `
<widget-content [widgets]="widgets" [originalConfig]="tab.originalConfig" [context]="tab.context">
</widget-content>

View File

@@ -10,7 +10,6 @@ import Event, { Emitter } from 'vs/base/common/event';
import { Parts } from 'vs/workbench/services/part/common/partService';
import { IDisposable } from 'vs/base/common/lifecycle';
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
import { TabConfig } from 'sql/parts/dashboard/common/dashboardWidget';
import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service';
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';

View File

@@ -28,7 +28,7 @@ import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboar
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
import { IDisposable } from 'vs/base/common/lifecycle';
import { IColorTheme } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { IColorTheme, IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import * as colors from 'vs/platform/theme/common/colorRegistry';
import * as themeColors from 'vs/workbench/common/theme';
import { Action } from 'vs/base/common/actions';
@@ -37,6 +37,7 @@ import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { memoize } from 'vs/base/common/decorators';
import { generateUuid } from 'vs/base/common/uuid';
import { Emitter } from 'vs/base/common/event';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
const componentMap: { [x: string]: Type<IDashboardWidget> } = {
'properties-widget': PropertiesWidgetComponent,
@@ -91,20 +92,22 @@ export class DashboardWidgetWrapper extends AngularDisposable implements OnInit
@Inject(forwardRef(() => ElementRef)) private _ref: ElementRef,
@Inject(forwardRef(() => CommonServiceInterface)) private _bootstrap: CommonServiceInterface,
@Inject(forwardRef(() => ChangeDetectorRef)) private _changeref: ChangeDetectorRef,
@Inject(forwardRef(() => Injector)) private _injector: Injector
@Inject(forwardRef(() => Injector)) private _injector: Injector,
@Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService,
@Inject(IInstantiationService) private instantiationService: IInstantiationService
) {
super();
}
ngOnInit() {
let self = this;
this._register(self._bootstrap.themeService.onDidColorThemeChange((event: IColorTheme) => {
this._register(self.themeService.onDidColorThemeChange((event: IColorTheme) => {
self.updateTheme(event);
}));
}
ngAfterViewInit() {
this.updateTheme(this._bootstrap.themeService.getColorTheme());
this.updateTheme(this.themeService.getColorTheme());
if (this.componentHost) {
this.loadWidget();
}
@@ -112,10 +115,10 @@ export class DashboardWidgetWrapper extends AngularDisposable implements OnInit
this._actionbar = new ActionBar(this._actionbarRef.nativeElement);
if (this._actions) {
if (this.collapsable) {
this._collapseAction = this._bootstrap.instantiationService.createInstance(CollapseWidgetAction, this._bootstrap.getUnderlyingUri(), this.guid, this.collapsed);
this._collapseAction = this.instantiationService.createInstance(CollapseWidgetAction, this._bootstrap.getUnderlyingUri(), this.guid, this.collapsed);
this._actionbar.push(this._collapseAction, { icon: true, label: false });
}
this._actionbar.push(this._bootstrap.instantiationService.createInstance(ToggleMoreWidgetAction, this._actions, this._component.actionsContext), { icon: true, label: false });
this._actionbar.push(this.instantiationService.createInstance(ToggleMoreWidgetAction, this._actions, this._component.actionsContext), { icon: true, label: false });
}
this.layout();
}
@@ -137,7 +140,7 @@ export class DashboardWidgetWrapper extends AngularDisposable implements OnInit
}
public enableEdit(): void {
this._actionbar.push(this._bootstrap.instantiationService.createInstance(DeleteWidgetAction, this._config.id, this._bootstrap.getUnderlyingUri()), { icon: true, label: false });
this._actionbar.push(this.instantiationService.createInstance(DeleteWidgetAction, this._config.id, this._bootstrap.getUnderlyingUri()), { icon: true, label: false });
}
public disableEdit(): void {

View File

@@ -8,16 +8,18 @@ import { Component, forwardRef, Input, OnInit, Inject, ChangeDetectorRef, Elemen
import Event, { Emitter } from 'vs/base/common/event';
import { Webview } from 'vs/workbench/parts/html/browser/webview';
import { Parts } from 'vs/workbench/services/part/common/partService';
import { Parts, IPartService } from 'vs/workbench/services/part/common/partService';
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
import { addDisposableListener, EventType } from 'vs/base/browser/dom';
import { memoize } from 'vs/base/common/decorators';
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { DashboardTab } from 'sql/parts/dashboard/common/interfaces';
import { TabConfig } from 'sql/parts/dashboard/common/dashboardWidget';
import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service';
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
import { IDashboardWebview } from 'sql/services/dashboard/common/dashboardViewService';
import { IDashboardWebview, IDashboardViewService } from 'sql/services/dashboard/common/dashboardViewService';
import { AngularDisposable } from 'sql/base/common/lifecycle';
import * as sqlops from 'sqlops';
@@ -37,19 +39,22 @@ export class WebviewContent extends AngularDisposable implements OnInit, IDashbo
private _onMessageDisposable: IDisposable;
private _webview: Webview;
private _html: string;
private _dashboardService: DashboardServiceInterface;
constructor(
@Inject(forwardRef(() => CommonServiceInterface)) private commonService: CommonServiceInterface,
@Inject(forwardRef(() => CommonServiceInterface)) private _dashboardService: DashboardServiceInterface,
@Inject(forwardRef(() => ChangeDetectorRef)) private _changeRef: ChangeDetectorRef,
@Inject(forwardRef(() => ElementRef)) private _el: ElementRef
@Inject(forwardRef(() => ElementRef)) private _el: ElementRef,
@Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService,
@Inject(IContextViewService) private contextViewService: IContextViewService,
@Inject(IDashboardViewService) private dashboardViewService: IDashboardViewService,
@Inject(IPartService) private partService: IPartService,
@Inject(IEnvironmentService) private environmentService: IEnvironmentService
) {
super();
this._dashboardService = commonService as DashboardServiceInterface;
}
ngOnInit() {
this._dashboardService.dashboardViewService.registerWebview(this);
this.dashboardViewService.registerWebview(this);
this._createWebview();
this._register(addDisposableListener(window, EventType.RESIZE, e => {
this.layout();
@@ -104,10 +109,10 @@ export class WebviewContent extends AngularDisposable implements OnInit, IDashbo
}
this._webview = new Webview(this._el.nativeElement,
this._dashboardService.partService.getContainer(Parts.EDITOR_PART),
this._dashboardService.themeService,
this._dashboardService.environmentService,
this._dashboardService.contextViewService,
this.partService.getContainer(Parts.EDITOR_PART),
this.themeService,
this.environmentService,
this.contextViewService,
undefined,
undefined,
{
@@ -120,7 +125,7 @@ export class WebviewContent extends AngularDisposable implements OnInit, IDashbo
this._onMessageDisposable = this._webview.onMessage(e => {
this._onMessage.fire(e);
});
this._webview.style(this._dashboardService.themeService.getTheme());
this._webview.style(this.themeService.getTheme());
if (this._html) {
this._webview.contents = this._html;
}

View File

@@ -16,7 +16,7 @@ import { RefreshWidgetAction, EditDashboardAction } from 'sql/parts/dashboard/co
import { DashboardPage } from 'sql/parts/dashboard/common/dashboardPage.component';
import { AngularDisposable } from 'sql/base/common/lifecycle';
import { IColorTheme } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { IColorTheme, IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { IDisposable } from 'vs/base/common/lifecycle';
import * as themeColors from 'vs/workbench/common/theme';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
@@ -39,14 +39,15 @@ export class DashboardComponent extends AngularDisposable implements OnInit {
constructor(
@Inject(forwardRef(() => CommonServiceInterface)) private _bootstrapService: CommonServiceInterface,
@Inject(forwardRef(() => Router)) private _router: Router,
@Inject(forwardRef(() => ChangeDetectorRef)) private _changeRef: ChangeDetectorRef
@Inject(forwardRef(() => ChangeDetectorRef)) private _changeRef: ChangeDetectorRef,
@Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService
) {
super();
}
ngOnInit() {
this._register(this._bootstrapService.themeService.onDidColorThemeChange(this.updateTheme, this));
this.updateTheme(this._bootstrapService.themeService.getColorTheme());
this._register(this.themeService.onDidColorThemeChange(this.updateTheme, this));
this.updateTheme(this.themeService.getColorTheme());
let profile: IConnectionProfile = this._bootstrapService.getOriginalConnectionProfile();
this.actionbar = new ActionBar(this.actionbarContainer.nativeElement);
this.actionbar.push(new RefreshWidgetAction(this.refresh, this), {

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Inject, NgModule, forwardRef, ApplicationRef, ComponentFactoryResolver } from '@angular/core';
import { Inject, NgModule, forwardRef, ApplicationRef, ComponentFactoryResolver, NgModuleRef, NgModuleFactory } from '@angular/core';
import { CommonModule, APP_BASE_HREF } from '@angular/common';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule, Routes, UrlSerializer, Router, NavigationEnd } from '@angular/router';
@@ -12,9 +12,9 @@ import { NgGridModule } from 'angular2-grid';
import { ChartsModule } from 'ng2-charts/ng2-charts';
import CustomUrlSerializer from 'sql/common/urlSerializer';
import { IBootstrapService, BOOTSTRAP_SERVICE_ID } from 'sql/services/bootstrap/bootstrapService';
import { Extensions, IInsightRegistry } from 'sql/platform/dashboard/common/insightRegistry';
import { Extensions as ComponentExtensions, IComponentRegistry } from 'sql/platform/dashboard/common/modelComponentRegistry';
import { IBootstrapParams } from 'sql/services/bootstrap/bootstrapService';
import { Registry } from 'vs/platform/registry/common/platform';
@@ -56,12 +56,13 @@ import { JobHistoryComponent } from 'sql/parts/jobManagement/views/jobHistory.co
let baseComponents = [DashboardHomeContainer, DashboardComponent, DashboardWidgetWrapper, DashboardWebviewContainer,
DashboardWidgetContainer, DashboardGridContainer, DashboardErrorContainer, DashboardNavSection, ModelViewContent, WebviewContent, WidgetContent,
ComponentHostDirective, BreadcrumbComponent, ControlHostContent, DashboardControlHostContainer,
JobsViewComponent, AgentViewComponent, JobHistoryComponent, JobStepsViewComponent, DashboardModelViewContainer, ModelComponentWrapper,
ScrollableDirective];
JobsViewComponent, AgentViewComponent, JobHistoryComponent, JobStepsViewComponent, DashboardModelViewContainer, ModelComponentWrapper];
/* Panel */
import { PanelModule } from 'sql/base/browser/ui/panel/panel.module';
import { ScrollableModule } from 'sql/base/browser/ui/scrollable/scrollable.module';
/* Pages */
import { ServerDashboardPage } from 'sql/parts/dashboard/pages/serverDashboardPage.component';
import { DatabaseDashboardPage } from 'sql/parts/dashboard/pages/databaseDashboardPage.component';
@@ -75,7 +76,6 @@ import { TasksWidget } from 'sql/parts/dashboard/widgets/tasks/tasksWidget.compo
import { InsightsWidget } from 'sql/parts/dashboard/widgets/insights/insightsWidget.component';
import { WebviewWidget } from 'sql/parts/dashboard/widgets/webview/webviewWidget.component';
import { JobStepsViewComponent } from '../jobManagement/views/jobStepsView.component';
import { ScrollableDirective } from 'sql/base/browser/ui/scrollable/scrollable.directive';
let widgetComponents = [
PropertiesWidgetComponent,
@@ -104,63 +104,68 @@ const appRoutes: Routes = [
];
// Connection Dashboard main angular module
@NgModule({
declarations: [
...baseComponents,
...pageComponents,
...widgetComponents,
...insightComponents,
...extensionComponents
],
// also for widgets
entryComponents: [
DashboardComponent,
...widgetComponents,
...insightComponents,
...extensionComponents
],
imports: [
CommonModule,
BrowserModule,
FormsModule,
NgGridModule,
ChartsModule,
RouterModule.forRoot(appRoutes),
PanelModule
],
providers: [
{ provide: APP_BASE_HREF, useValue: '/' },
{ provide: IBreadcrumbService, useClass: BreadcrumbService },
{ provide: CommonServiceInterface, useClass: DashboardServiceInterface },
{ provide: UrlSerializer, useClass: CustomUrlSerializer }
]
})
export class DashboardModule {
private _bootstrap: DashboardServiceInterface;
constructor(
@Inject(forwardRef(() => ComponentFactoryResolver)) private _resolver: ComponentFactoryResolver,
@Inject(BOOTSTRAP_SERVICE_ID) private _bootstrapService: IBootstrapService,
@Inject(forwardRef(() => CommonServiceInterface)) bootstrap: CommonServiceInterface,
@Inject(forwardRef(() => Router)) private _router: Router
) {
this._bootstrap = bootstrap as DashboardServiceInterface;
export const DashboardModule = (params, selector: string): any => {
@NgModule({
declarations: [
...baseComponents,
...pageComponents,
...widgetComponents,
...insightComponents,
...extensionComponents
],
// also for widgets
entryComponents: [
DashboardComponent,
...widgetComponents,
...insightComponents,
...extensionComponents
],
imports: [
CommonModule,
BrowserModule,
FormsModule,
NgGridModule,
ChartsModule,
RouterModule.forRoot(appRoutes),
PanelModule,
ScrollableModule
],
providers: [
{ provide: APP_BASE_HREF, useValue: '/' },
{ provide: IBreadcrumbService, useClass: BreadcrumbService },
{ provide: CommonServiceInterface, useClass: DashboardServiceInterface },
{ provide: UrlSerializer, useClass: CustomUrlSerializer },
{ provide: IBootstrapParams, useValue: params }
]
})
class ModuleClass {
private _bootstrap: DashboardServiceInterface;
constructor(
@Inject(forwardRef(() => ComponentFactoryResolver)) private _resolver: ComponentFactoryResolver,
@Inject(forwardRef(() => CommonServiceInterface)) bootstrap: CommonServiceInterface,
@Inject(forwardRef(() => Router)) private _router: Router,
@Inject(ITelemetryService) private telemetryService: ITelemetryService
) {
this._bootstrap = bootstrap as DashboardServiceInterface;
}
ngDoBootstrap(appRef: ApplicationRef) {
const factory = this._resolver.resolveComponentFactory(DashboardComponent);
this._bootstrap.selector = selector;
(<any>factory).factory.selector = selector;
appRef.bootstrap(factory);
this._router.events.subscribe(e => {
if (e instanceof NavigationEnd) {
this._bootstrap.handlePageNavigation();
TelemetryUtils.addTelemetry(this.telemetryService, TelemetryKeys.DashboardNavigated, {
numberOfNavigations: this._bootstrap.getNumberOfPageNavigations(),
routeUrl: e.url
});
}
});
}
}
ngDoBootstrap(appRef: ApplicationRef) {
const factory = this._resolver.resolveComponentFactory(DashboardComponent);
const uniqueSelector: string = this._bootstrapService.getUniqueSelector(DASHBOARD_SELECTOR);
this._bootstrap.selector = uniqueSelector;
(<any>factory).factory.selector = uniqueSelector;
appRef.bootstrap(factory);
this._router.events.subscribe(e => {
if (e instanceof NavigationEnd) {
this._bootstrap.handlePageNavigation();
TelemetryUtils.addTelemetry(this._bootstrapService.telemetryService, TelemetryKeys.DashboardNavigated, {
numberOfNavigations: this._bootstrap.getNumberOfPageNavigations(),
routeUrl: e.url
});
}
});
}
}
return ModuleClass;
};

View File

@@ -15,8 +15,8 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { DashboardInput } from './dashboardInput';
import { DashboardModule } from './dashboard.module';
import { IBootstrapService } from 'sql/services/bootstrap/bootstrapService';
import { DashboardComponentParams } from 'sql/services/bootstrap/bootstrapParams';
import { bootstrapAngular } from 'sql/services/bootstrap/bootstrapService';
import { IDashboardComponentParams } from 'sql/services/bootstrap/bootstrapParams';
import { DASHBOARD_SELECTOR } from 'sql/parts/dashboard/dashboard.component';
import { ConnectionContextkey } from 'sql/parts/connection/common/connectionContextKey';
import { IDashboardService } from 'sql/services/dashboard/common/dashboardService';
@@ -34,7 +34,6 @@ export class DashboardEditor extends BaseEditor {
@ITelemetryService telemetryService: ITelemetryService,
@IWorkbenchThemeService themeService: IWorkbenchThemeService,
@IInstantiationService private instantiationService: IInstantiationService,
@IBootstrapService private _bootstrapService: IBootstrapService,
@IContextKeyService private _contextKeyService: IContextKeyService,
@IDashboardService private _dashboardService: IDashboardService,
@IConnectionManagementService private _connMan: IConnectionManagementService
@@ -114,7 +113,7 @@ export class DashboardEditor extends BaseEditor {
let connectionContextKey = new ConnectionContextkey(scopedContextService);
connectionContextKey.set(input.connectionProfile);
let params: DashboardComponentParams = {
let params: IDashboardComponentParams = {
connection: input.connectionProfile,
ownerUri: input.uri,
scopedContextService,
@@ -123,7 +122,7 @@ export class DashboardEditor extends BaseEditor {
input.hasBootstrapped = true;
let uniqueSelector = this._bootstrapService.bootstrap(
let uniqueSelector = this.instantiationService.invokeFunction(bootstrapAngular,
DashboardModule,
this._dashboardContainer,
DASHBOARD_SELECTOR,

View File

@@ -10,11 +10,14 @@ import { BreadcrumbClass } from 'sql/parts/dashboard/services/breadcrumb.service
import { IBreadcrumbService } from 'sql/base/browser/ui/breadcrumb/interfaces';
import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service';
import { WidgetConfig } from 'sql/parts/dashboard/common/dashboardWidget';
import { IBootstrapService, BOOTSTRAP_SERVICE_ID } from 'sql/services/bootstrap/bootstrapService';
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
import { IAngularEventingService } from 'sql/services/angularEventing/angularEventingService';
import * as colors from 'vs/platform/theme/common/colorRegistry';
import * as nls from 'vs/nls';
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
export class DatabaseDashboardPage extends DashboardPage implements OnInit {
protected propertiesWidget: WidgetConfig = {
@@ -38,9 +41,12 @@ export class DatabaseDashboardPage extends DashboardPage implements OnInit {
@Inject(forwardRef(() => IBreadcrumbService)) private _breadcrumbService: IBreadcrumbService,
@Inject(forwardRef(() => CommonServiceInterface)) dashboardService: DashboardServiceInterface,
@Inject(forwardRef(() => ChangeDetectorRef)) _cd: ChangeDetectorRef,
@Inject(forwardRef(() => ElementRef)) el: ElementRef
@Inject(forwardRef(() => ElementRef)) el: ElementRef,
@Inject(IInstantiationService) instantiationService: IInstantiationService,
@Inject(INotificationService) notificationService: INotificationService,
@Inject(IAngularEventingService) angularEventingService: IAngularEventingService
) {
super(dashboardService, el, _cd);
super(dashboardService, el, _cd, instantiationService, notificationService, angularEventingService);
this._register(dashboardService.onUpdatePage(() => {
this.refresh(true);
this._cd.detectChanges();

View File

@@ -11,10 +11,13 @@ import { IBreadcrumbService } from 'sql/base/browser/ui/breadcrumb/interfaces';
import { WidgetConfig } from 'sql/parts/dashboard/common/dashboardWidget';
import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service';
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
import { IBootstrapService, BOOTSTRAP_SERVICE_ID } from 'sql/services/bootstrap/bootstrapService';
import { IAngularEventingService } from 'sql/services/angularEventing/angularEventingService';
import * as colors from 'vs/platform/theme/common/colorRegistry';
import * as nls from 'vs/nls';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
export class ServerDashboardPage extends DashboardPage implements OnInit {
protected propertiesWidget: WidgetConfig = {
@@ -37,11 +40,14 @@ export class ServerDashboardPage extends DashboardPage implements OnInit {
constructor(
@Inject(forwardRef(() => IBreadcrumbService)) private breadcrumbService: IBreadcrumbService,
@Inject(forwardRef(() => CommonServiceInterface)) dashboardService: CommonServiceInterface,
@Inject(forwardRef(() => CommonServiceInterface)) dashboardService: DashboardServiceInterface,
@Inject(forwardRef(() => ChangeDetectorRef)) _cd: ChangeDetectorRef,
@Inject(forwardRef(() => ElementRef)) el: ElementRef
@Inject(forwardRef(() => ElementRef)) el: ElementRef,
@Inject(IInstantiationService) instantiationService: IInstantiationService,
@Inject(INotificationService) notificationService: INotificationService,
@Inject(IAngularEventingService) angularEventingService: IAngularEventingService
) {
super(dashboardService, el, _cd);
super(dashboardService, el, _cd, instantiationService, notificationService, angularEventingService);
// revert back to default database
this._letDashboardPromise = this.dashboardService.connectionManagementService.changeDatabase('master');
}

View File

@@ -9,8 +9,8 @@ import { Router } from '@angular/router';
import { Observable } from 'rxjs/Observable';
/* SQL imports */
import { DashboardComponentParams } from 'sql/services/bootstrap/bootstrapParams';
import { IBootstrapService, BOOTSTRAP_SERVICE_ID } from 'sql/services/bootstrap/bootstrapService';
import { IDashboardComponentParams } from 'sql/services/bootstrap/bootstrapParams';
import { IBootstrapParams } from 'sql/services/bootstrap/bootstrapService';
import { IMetadataService } from 'sql/services/metadata/metadataService';
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
import { ConnectionManagementInfo } from 'sql/parts/connection/common/connectionManagementInfo';
@@ -64,9 +64,6 @@ export class DashboardServiceInterface extends CommonServiceInterface {
/* Static Services */
private _dashboardViewService = this._bootstrapService.dashboardViewService;
private _updatePage = new Emitter<void>();
public readonly onUpdatePage: Event<void> = this._updatePage.event;
@@ -88,14 +85,21 @@ export class DashboardServiceInterface extends CommonServiceInterface {
private _numberOfPageNavigations = 0;
constructor(
@Inject(BOOTSTRAP_SERVICE_ID) bootstrapService: IBootstrapService,
@Inject(forwardRef(() => Router)) private _router: Router,
@Inject(INotificationService) private _notificationService: INotificationService,
@Inject(IMetadataService) metadataService: IMetadataService,
@Inject(IConnectionManagementService) connectionManagementService: IConnectionManagementService,
@Inject(IAdminService) adminService: IAdminService,
@Inject(IQueryManagementService) queryManagementService: IQueryManagementService,
@Inject(IAngularEventingService) private angularEventingService: IAngularEventingService,
@Inject(IConfigurationService) private _configService: IConfigurationService,
@Inject(IBootstrapParams) _params: IDashboardComponentParams
) {
super(bootstrapService);
super(_params, metadataService, connectionManagementService, adminService, queryManagementService);
}
public get dashboardViewService(): IDashboardViewService {
return this._dashboardViewService;
private get params(): IDashboardComponentParams {
return this._params;
}
/**
@@ -107,11 +111,10 @@ export class DashboardServiceInterface extends CommonServiceInterface {
}
protected _getbootstrapParams(): void {
this._bootstrapParams = this._bootstrapService.getBootstrapParams<DashboardComponentParams>(this._uniqueSelector);
this._contextKeyService = this._bootstrapParams.scopedContextService;
this._connectionContextKey = this._bootstrapParams.connectionContextKey;
this.dashboardContextKey = this._dashboardContextKey.bindTo(this._contextKeyService);
this.uri = this._bootstrapParams.ownerUri;
this.scopedContextKeyService = this.params.scopedContextService;
this._connectionContextKey = this.params.connectionContextKey;
this.dashboardContextKey = this._dashboardContextKey.bindTo(this.scopedContextKeyService);
this.uri = this.params.ownerUri;
}
/**
@@ -120,7 +123,7 @@ export class DashboardServiceInterface extends CommonServiceInterface {
*/
protected set uri(uri: string) {
super.setUri(uri);
this._register(toDisposableSubscription(this._bootstrapService.angularEventingService.onAngularEvent(this._uri, (event) => this.handleDashboardEvent(event))));
this._register(toDisposableSubscription(this.angularEventingService.onAngularEvent(this._uri, (event) => this.handleDashboardEvent(event))));
}
/**
@@ -147,7 +150,7 @@ export class DashboardServiceInterface extends CommonServiceInterface {
}
public writeSettings(type: string, value: any, target: ConfigurationTarget) {
this._configurationEditingService.writeConfiguration(target, { key: [DASHBOARD_SETTINGS, type].join('.'), value });
this._configService.updateValue([DASHBOARD_SETTINGS, type].join('.'), value, target);
}
private handleDashboardEvent(event: IAngularEvent): void {

View File

@@ -6,7 +6,7 @@
import { Router } from '@angular/router';
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
import { MetadataType } from 'sql/parts/connection/common/connectionManagement';
import { MetadataType, IConnectionManagementService, IErrorMessageService } from 'sql/parts/connection/common/connectionManagement';
import { SingleConnectionManagementService } from 'sql/services/common/commonServiceInterface.service';
import {
NewQueryAction, ScriptSelectAction, EditDataAction, ScriptCreateAction, ScriptExecuteAction, ScriptAlterAction,
@@ -16,6 +16,8 @@ import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesServ
import { ConnectionManagementInfo } from 'sql/parts/connection/common/connectionManagementInfo';
import * as Constants from 'sql/parts/connection/common/constants';
import { OEAction } from 'sql/parts/objectExplorer/viewlet/objectExplorerActions';
import { IQueryEditorService } from 'sql/parts/query/common/queryEditorService';
import { IScriptingService } from 'sql/services/scripting/scriptingService';
import { ObjectMetadata } from 'sqlops';
@@ -30,6 +32,7 @@ import { generateUuid } from 'vs/base/common/uuid';
import { $ } from 'vs/base/browser/dom';
import { ExecuteCommandAction } from 'vs/platform/actions/common/actions';
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { IProgressService } from 'vs/platform/progress/common/progress';
export class ObjectMetadataWrapper implements ObjectMetadata {
public metadataType: MetadataType;
@@ -370,7 +373,7 @@ function GetExplorerActions(element: TreeResource, instantiationService: IInstan
if (element instanceof ObjectMetadataWrapper) {
if (element.metadataType === MetadataType.View || element.metadataType === MetadataType.Table) {
actions.push(instantiationService.createInstance(ScriptSelectAction, ScriptSelectAction.ID, ScriptSelectAction.LABEL));
actions.push(instantiationService.createInstance(ExplorerScriptSelectAction, ScriptSelectAction.ID, ScriptSelectAction.LABEL));
}
if (element.metadataType === MetadataType.Table) {
@@ -378,12 +381,12 @@ function GetExplorerActions(element: TreeResource, instantiationService: IInstan
}
if (element.metadataType === MetadataType.SProc && info.connectionProfile.providerName === Constants.mssqlProviderName) {
actions.push(instantiationService.createInstance(ScriptExecuteAction, ScriptExecuteAction.ID, ScriptExecuteAction.LABEL));
actions.push(instantiationService.createInstance(ExplorerScriptExecuteAction, ScriptExecuteAction.ID, ScriptExecuteAction.LABEL));
}
if ((element.metadataType === MetadataType.SProc || element.metadataType === MetadataType.Function || element.metadataType === MetadataType.View)
&& info.connectionProfile.providerName === Constants.mssqlProviderName) {
actions.push(instantiationService.createInstance(ScriptAlterAction, ScriptAlterAction.ID, ScriptAlterAction.LABEL));
actions.push(instantiationService.createInstance(ExplorerScriptAlterAction, ScriptAlterAction.ID, ScriptAlterAction.LABEL));
}
} else {
actions.push(instantiationService.createInstance(CustomExecuteCommandAction, NewQueryAction.ID, NewQueryAction.LABEL));
@@ -402,7 +405,7 @@ function GetExplorerActions(element: TreeResource, instantiationService: IInstan
return TPromise.as(actions);
}
actions.push(instantiationService.createInstance(ScriptCreateAction, ScriptCreateAction.ID, ScriptCreateAction.LABEL));
actions.push(instantiationService.createInstance(ExplorerScriptCreateAction, ScriptCreateAction.ID, ScriptCreateAction.LABEL));
return TPromise.as(actions);
}
@@ -412,3 +415,78 @@ class CustomExecuteCommandAction extends ExecuteCommandAction {
return super.run(context.profile);
}
}
class ExplorerScriptSelectAction extends ScriptSelectAction {
constructor(
id: string, label: string,
@IQueryEditorService queryEditorService: IQueryEditorService,
@IConnectionManagementService connectionManagementService: IConnectionManagementService,
@IScriptingService scriptingService: IScriptingService,
@IProgressService private progressService: IProgressService
) {
super(id, label, queryEditorService, connectionManagementService, scriptingService);
}
public run(actionContext: BaseActionContext): TPromise<boolean> {
let promise = super.run(actionContext);
this.progressService.showWhile(promise);
return promise;
}
}
class ExplorerScriptCreateAction extends ScriptCreateAction {
constructor(
id: string, label: string,
@IQueryEditorService queryEditorService: IQueryEditorService,
@IConnectionManagementService connectionManagementService: IConnectionManagementService,
@IScriptingService scriptingService: IScriptingService,
@IErrorMessageService errorMessageService: IErrorMessageService,
@IProgressService private progressService: IProgressService
) {
super(id, label, queryEditorService, connectionManagementService, scriptingService, errorMessageService);
}
public run(actionContext: BaseActionContext): TPromise<boolean> {
let promise = super.run(actionContext);
this.progressService.showWhile(promise);
return promise;
}
}
class ExplorerScriptAlterAction extends ScriptAlterAction {
constructor(
id: string, label: string,
@IQueryEditorService queryEditorService: IQueryEditorService,
@IConnectionManagementService connectionManagementService: IConnectionManagementService,
@IScriptingService scriptingService: IScriptingService,
@IErrorMessageService errorMessageService: IErrorMessageService,
@IProgressService private progressService: IProgressService
) {
super(id, label, queryEditorService, connectionManagementService, scriptingService, errorMessageService);
}
public run(actionContext: BaseActionContext): TPromise<boolean> {
let promise = super.run(actionContext);
this.progressService.showWhile(promise);
return promise;
}
}
class ExplorerScriptExecuteAction extends ScriptExecuteAction {
constructor(
id: string, label: string,
@IQueryEditorService queryEditorService: IQueryEditorService,
@IConnectionManagementService connectionManagementService: IConnectionManagementService,
@IScriptingService scriptingService: IScriptingService,
@IErrorMessageService errorMessageService: IErrorMessageService,
@IProgressService private progressService: IProgressService
) {
super(id, label, queryEditorService, connectionManagementService, scriptingService, errorMessageService);
}
public run(actionContext: BaseActionContext): TPromise<boolean> {
let promise = super.run(actionContext);
this.progressService.showWhile(promise);
return promise;
}
}

View File

@@ -16,6 +16,7 @@ import { CommonServiceInterface } from 'sql/services/common/commonServiceInterfa
import { toDisposableSubscription } from 'sql/parts/common/rxjsUtils';
import { ExplorerFilter, ExplorerRenderer, ExplorerDataSource, ExplorerController, ObjectMetadataWrapper, ExplorerModel } from './explorerTree';
import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
import { InputBox, IInputOptions } from 'vs/base/browser/ui/inputbox/inputBox';
import { attachInputBoxStyler, attachListStyler } from 'vs/platform/theme/common/styler';
@@ -23,6 +24,10 @@ import * as nls from 'vs/nls';
import { Tree } from 'vs/base/parts/tree/browser/treeImpl';
import { getContentHeight } from 'vs/base/browser/dom';
import { Delayer } from 'vs/base/common/async';
import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IProgressService } from 'vs/platform/progress/common/progress';
@Component({
selector: 'explorer-widget',
@@ -36,9 +41,9 @@ export class ExplorerWidget extends DashboardWidget implements IDashboardWidget,
this._bootstrap.getUnderlyingUri(),
this._bootstrap.connectionManagementService,
this._router,
this._bootstrap.contextMenuService,
this._bootstrap.capabilitiesService,
this._bootstrap.instantiationService
this.contextMenuService,
this.capabilitiesService,
this.instantiationService
);
private _treeRenderer = new ExplorerRenderer();
private _treeDataSource = new ExplorerDataSource();
@@ -54,7 +59,13 @@ export class ExplorerWidget extends DashboardWidget implements IDashboardWidget,
@Inject(forwardRef(() => Router)) private _router: Router,
@Inject(forwardRef(() => ChangeDetectorRef)) private _changeRef: ChangeDetectorRef,
@Inject(WIDGET_CONFIG) protected _config: WidgetConfig,
@Inject(forwardRef(() => ElementRef)) private _el: ElementRef
@Inject(forwardRef(() => ElementRef)) private _el: ElementRef,
@Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService,
@Inject(IContextViewService) private contextViewService: IContextViewService,
@Inject(IInstantiationService) private instantiationService: IInstantiationService,
@Inject(IContextMenuService) private contextMenuService: IContextMenuService,
@Inject(ICapabilitiesService) private capabilitiesService: ICapabilitiesService,
@Inject(IProgressService) private progressService: IProgressService
) {
super();
this.init();
@@ -69,7 +80,7 @@ export class ExplorerWidget extends DashboardWidget implements IDashboardWidget,
placeholder: placeholderLabel,
ariaLabel: placeholderLabel
};
this._input = new InputBox(this._inputContainer.nativeElement, this._bootstrap.contextViewService, inputOptions);
this._input = new InputBox(this._inputContainer.nativeElement, this.contextViewService, inputOptions);
this._register(this._input.onDidChange(e => {
this._filterDelayer.trigger(() => {
this._treeFilter.filterString = e;
@@ -84,9 +95,9 @@ export class ExplorerWidget extends DashboardWidget implements IDashboardWidget,
});
this._tree.layout(getContentHeight(this._tableContainer.nativeElement));
this._register(this._input);
this._register(attachInputBoxStyler(this._input, this._bootstrap.themeService));
this._register(attachInputBoxStyler(this._input, this.themeService));
this._register(this._tree);
this._register(attachListStyler(this._tree, this._bootstrap.themeService));
this._register(attachListStyler(this._tree, this.themeService));
}
private init(): void {
@@ -109,7 +120,7 @@ export class ExplorerWidget extends DashboardWidget implements IDashboardWidget,
this._register(toDisposableSubscription(this._bootstrap.metadataService.databaseNames.subscribe(
data => {
let profileData = data.map(d => {
let profile = new ConnectionProfile(this._bootstrap.capabilitiesService, currentProfile);
let profile = new ConnectionProfile(this.capabilitiesService, currentProfile);
profile.databaseName = d;
return profile;
});

View File

@@ -26,8 +26,10 @@ import * as types from 'vs/base/common/types';
import * as pfs from 'vs/base/node/pfs';
import * as nls from 'vs/nls';
import { Registry } from 'vs/platform/registry/common/platform';
import { WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { WorkbenchState, IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IntervalTimer } from 'vs/base/common/async';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IStorageService } from 'vs/platform/storage/common/storage';
const insightRegistry = Registry.as<IInsightRegistry>(Extensions.InsightContribution);
@@ -63,7 +65,11 @@ export class InsightsWidget extends DashboardWidget implements IDashboardWidget,
@Inject(forwardRef(() => CommonServiceInterface)) private dashboardService: CommonServiceInterface,
@Inject(WIDGET_CONFIG) protected _config: WidgetConfig,
@Inject(forwardRef(() => ViewContainerRef)) private viewContainerRef: ViewContainerRef,
@Inject(forwardRef(() => ChangeDetectorRef)) private _cd: ChangeDetectorRef
@Inject(forwardRef(() => ChangeDetectorRef)) private _cd: ChangeDetectorRef,
@Inject(IInstantiationService) private instantiationService: IInstantiationService,
@Inject(IStorageService) private storageService: IStorageService,
@Inject(IWorkspaceContextService) private workspaceContextService: IWorkspaceContextService,
) {
super();
this.insightConfig = <IInsightsConfig>this._config.widget['insights-widget'];
@@ -128,9 +134,9 @@ export class InsightsWidget extends DashboardWidget implements IDashboardWidget,
get actions(): Array<Action> {
let actions: Array<Action> = [];
if (this.insightConfig.details && (this.insightConfig.details.query || this.insightConfig.details.queryFile)) {
actions.push(this.dashboardService.instantiationService.createInstance(InsightAction, InsightAction.ID, InsightAction.LABEL));
actions.push(this.instantiationService.createInstance(InsightAction, InsightAction.ID, InsightAction.LABEL));
}
actions.push(this.dashboardService.instantiationService.createInstance(RunInsightQueryAction, RunInsightQueryAction.ID, RunInsightQueryAction.LABEL));
actions.push(this.instantiationService.createInstance(RunInsightQueryAction, RunInsightQueryAction.ID, RunInsightQueryAction.LABEL));
return actions;
}
@@ -150,14 +156,14 @@ export class InsightsWidget extends DashboardWidget implements IDashboardWidget,
};
this.lastUpdated = nls.localize('insights.lastUpdated', "Last Updated: {0} {1}", currentTime.toLocaleTimeString(), currentTime.toLocaleDateString());
this._cd.detectChanges();
this.dashboardService.storageService.store(this._getStorageKey(), JSON.stringify(store));
this.storageService.store(this._getStorageKey(), JSON.stringify(store));
}
return result;
}
private _checkStorage(): boolean {
if (this.insightConfig.cacheId) {
let storage = this.dashboardService.storageService.get(this._getStorageKey());
let storage = this.storageService.get(this._getStorageKey());
if (storage) {
let storedResult: IStorageResult = JSON.parse(storage);
let date = new Date(storedResult.date);
@@ -272,15 +278,15 @@ export class InsightsWidget extends DashboardWidget implements IDashboardWidget,
filePath = filePath.replace(match[0], '');
//filePath = this.dashboardService.workspaceContextService.toResource(filePath).fsPath;
switch (this.dashboardService.workspaceContextService.getWorkbenchState()) {
switch (this.workspaceContextService.getWorkbenchState()) {
case WorkbenchState.FOLDER:
filePath = this.dashboardService.workspaceContextService.getWorkspace().folders[0].toResource(filePath).fsPath;
filePath = this.workspaceContextService.getWorkspace().folders[0].toResource(filePath).fsPath;
break;
case WorkbenchState.WORKSPACE:
let filePathArray = filePath.split('/');
// filter out empty sections
filePathArray = filePathArray.filter(i => !!i);
let folder = this.dashboardService.workspaceContextService.getWorkspace().folders.find(i => i.name === filePathArray[0]);
let folder = this.workspaceContextService.getWorkspace().folders.find(i => i.name === filePathArray[0]);
if (!folder) {
return Promise.reject<void[]>(new Error(`Could not find workspace folder ${filePathArray[0]}`));
}

View File

@@ -5,22 +5,19 @@
import { Component, Input, Inject, ChangeDetectorRef, forwardRef, ElementRef, ViewChild } from '@angular/core';
import { BaseChartDirective } from 'ng2-charts/ng2-charts';
/* SQL Imports */
import { IBootstrapService, BOOTSTRAP_SERVICE_ID } from 'sql/services/bootstrap/bootstrapService';
import * as TelemetryKeys from 'sql/common/telemetryKeys';
import * as TelemetryUtils from 'sql/common/telemetryUtilities';
import { IInsightsView, IInsightData } from 'sql/parts/dashboard/widgets/insights/interfaces';
import { memoize, unmemoize } from 'sql/base/common/decorators';
/* VS Imports */
import * as colors from 'vs/platform/theme/common/colorRegistry';
import { mixin } from 'sql/base/common/objects';
import * as colors from 'vs/platform/theme/common/colorRegistry';
import { Color } from 'vs/base/common/color';
import * as types from 'vs/base/common/types';
import { Disposable } from 'vs/base/common/lifecycle';
import { IColorTheme } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { IColorTheme, IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import * as nls from 'vs/nls';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
export enum ChartType {
Bar = 'bar',
@@ -121,14 +118,15 @@ export abstract class ChartInsight extends Disposable implements IInsightsView {
constructor(
@Inject(forwardRef(() => ChangeDetectorRef)) private _changeRef: ChangeDetectorRef,
@Inject(forwardRef(() => ElementRef)) private _el: ElementRef,
@Inject(BOOTSTRAP_SERVICE_ID) protected _bootstrapService: IBootstrapService
@Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService,
@Inject(ITelemetryService) private telemetryService: ITelemetryService
) {
super();
}
init() {
this._register(this._bootstrapService.themeService.onDidColorThemeChange(e => this.updateTheme(e)));
this.updateTheme(this._bootstrapService.themeService.getColorTheme());
this._register(this.themeService.onDidColorThemeChange(e => this.updateTheme(e)));
this.updateTheme(this.themeService.getColorTheme());
// Note: must use a boolean to not render the canvas until all properties such as the labels and chart type are set.
// This is because chart.js doesn't auto-update anything other than dataset when re-rendering so defaults are used
// hence it's easier to not render until ready
@@ -142,7 +140,7 @@ export abstract class ChartInsight extends Disposable implements IInsightsView {
this._hasError = true;
this._changeRef.detectChanges();
}
TelemetryUtils.addTelemetry(this._bootstrapService.telemetryService, TelemetryKeys.ChartCreated, { type: this.chartType });
TelemetryUtils.addTelemetry(this.telemetryService, TelemetryKeys.ChartCreated, { type: this.chartType });
}
/**

View File

@@ -6,24 +6,31 @@ import { Component, Input, Inject, ChangeDetectorRef, forwardRef, ElementRef, On
import { getContentHeight, getContentWidth } from 'vs/base/browser/dom';
import { Dimension } from 'vs/base/browser/builder';
import { Disposable } from 'vs/base/common/lifecycle';
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { IInsightsView, IInsightData } from 'sql/parts/dashboard/widgets/insights/interfaces';
import { Table } from 'sql/base/browser/ui/table/table';
import { TableDataView } from 'sql/base/browser/ui/table/tableDataView';
import { DragCellSelectionModel } from '../../../../../base/browser/ui/table/plugins/dragCellSelectionModel.plugin';
import { DragCellSelectionModel } from 'sql/base/browser/ui/table/plugins/dragCellSelectionModel.plugin';
import { attachTableStyler} from 'sql/common/theme/styler';
@Component({
template: '<span></span>'
template: ''
})
export default class TableInsight implements IInsightsView, OnInit {
export default class TableInsight extends Disposable implements IInsightsView, OnInit {
private table: Table<any>;
private dataView: TableDataView<any>;
private columns: Slick.Column<any>[];
constructor(
@Inject(forwardRef(() => ChangeDetectorRef)) private _changeRef: ChangeDetectorRef,
@Inject(forwardRef(() => ElementRef)) private _elementRef: ElementRef
) { }
@Inject(forwardRef(() => ElementRef)) private _elementRef: ElementRef,
@Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService
) {
super();
this._elementRef.nativeElement.className = 'slickgridContainer';
}
ngOnInit() {
this.createTable();
@@ -58,13 +65,14 @@ export default class TableInsight implements IInsightsView, OnInit {
if (!this.table) {
this.table = new Table(this._elementRef.nativeElement, this.dataView, this.columns, { showRowNumber: true });
this.table.setSelectionModel(new DragCellSelectionModel());
this._register(attachTableStyler(this.table, this.themeService));
}
}
}
function transformData(rows: string[][], columns: string[]): {[key: string]: string}[] {
function transformData(rows: string[][], columns: string[]): { [key: string]: string }[] {
return rows.map(row => {
let object: {[key: string]: string} = {};
let object: { [key: string]: string } = {};
row.forEach((val, index) => {
object[columns[index]] = val;
});

View File

@@ -29,9 +29,9 @@ import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElemen
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
import { $, Builder } from 'vs/base/browser/builder';
import * as DOM from 'vs/base/browser/dom';
import { CommandsRegistry, ICommand } from 'vs/platform/commands/common/commands';
import { CommandsRegistry, ICommand, ICommandService } from 'vs/platform/commands/common/commands';
import { MenuRegistry, ICommandAction } from 'vs/platform/actions/common/actions';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode } from 'vs/base/common/keyCodes';
@@ -62,7 +62,9 @@ export class TasksWidget extends DashboardWidget implements IDashboardWidget, On
@Inject(forwardRef(() => CommonServiceInterface)) private _bootstrap: CommonServiceInterface,
@Inject(forwardRef(() => DomSanitizer)) private _sanitizer: DomSanitizer,
@Inject(forwardRef(() => ChangeDetectorRef)) private _changeref: ChangeDetectorRef,
@Inject(WIDGET_CONFIG) protected _config: WidgetConfig
@Inject(ICommandService) private commandService: ICommandService,
@Inject(WIDGET_CONFIG) protected _config: WidgetConfig,
@Inject(IContextKeyService) contextKeyService: IContextKeyService
) {
super();
this._profile = this._bootstrap.connectionManagementService.connectionInfo.connectionProfile;
@@ -76,7 +78,7 @@ export class TasksWidget extends DashboardWidget implements IDashboardWidget, On
return i;
}
} else {
if (tasks.includes(i.name) && _bootstrap.contextKeyService.contextMatchesRules(ContextKeyExpr.deserialize(i.when))) {
if (tasks.includes(i.name) && contextKeyService.contextMatchesRules(ContextKeyExpr.deserialize(i.when))) {
return i.name;
}
}
@@ -165,7 +167,7 @@ export class TasksWidget extends DashboardWidget implements IDashboardWidget, On
public runTask(task: ICommandAction) {
let serverInfo = this._bootstrap.connectionManagementService.connectionInfo.serverInfo;
this._bootstrap.commandService.executeCommand(task.id, this._profile);
this.commandService.executeCommand(task.id, this._profile);
}
public layout(): void {

View File

@@ -6,7 +6,7 @@
import { Component, Inject, forwardRef, ChangeDetectorRef, OnInit, ViewChild, ElementRef } from '@angular/core';
import { Webview } from 'vs/workbench/parts/html/browser/webview';
import { Parts } from 'vs/workbench/services/part/common/partService';
import { Parts, IPartService } from 'vs/workbench/services/part/common/partService';
import Event, { Emitter } from 'vs/base/common/event';
import { IDisposable } from 'vs/base/common/lifecycle';
import { memoize } from 'vs/base/common/decorators';
@@ -14,9 +14,12 @@ import { memoize } from 'vs/base/common/decorators';
import { DashboardWidget, IDashboardWidget, WidgetConfig, WIDGET_CONFIG } from 'sql/parts/dashboard/common/dashboardWidget';
import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service';
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
import { IDashboardWebview } from 'sql/services/dashboard/common/dashboardViewService';
import { IDashboardWebview, IDashboardViewService } from 'sql/services/dashboard/common/dashboardViewService';
import * as sqlops from 'sqlops';
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
interface IWebviewWidgetConfig {
id: string;
@@ -36,21 +39,24 @@ export class WebviewWidget extends DashboardWidget implements IDashboardWidget,
private _onMessage = new Emitter<string>();
public readonly onMessage: Event<string> = this._onMessage.event;
private _onMessageDisposable: IDisposable;
private _dashboardService: DashboardServiceInterface;
constructor(
@Inject(forwardRef(() => CommonServiceInterface)) private commonService: CommonServiceInterface,
@Inject(forwardRef(() => CommonServiceInterface)) private _dashboardService: DashboardServiceInterface,
@Inject(forwardRef(() => ChangeDetectorRef)) private _changeRef: ChangeDetectorRef,
@Inject(WIDGET_CONFIG) protected _config: WidgetConfig,
@Inject(forwardRef(() => ElementRef)) private _el: ElementRef
@Inject(forwardRef(() => ElementRef)) private _el: ElementRef,
@Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService,
@Inject(IContextViewService) private contextViewService: IContextViewService,
@Inject(IDashboardViewService) private dashboardViewService: IDashboardViewService,
@Inject(IPartService) private partService: IPartService,
@Inject(IEnvironmentService) private environmentService: IEnvironmentService
) {
super();
this._id = (_config.widget[selector] as IWebviewWidgetConfig).id;
this._dashboardService = commonService as DashboardServiceInterface;
}
ngOnInit() {
this._dashboardService.dashboardViewService.registerWebview(this);
this.dashboardViewService.registerWebview(this);
this._createWebview();
}
@@ -101,10 +107,10 @@ export class WebviewWidget extends DashboardWidget implements IDashboardWidget,
}
this._webview = new Webview(
this._el.nativeElement,
this._dashboardService.partService.getContainer(Parts.EDITOR_PART),
this._dashboardService.themeService,
this._dashboardService.environmentService,
this._dashboardService.contextViewService,
this.partService.getContainer(Parts.EDITOR_PART),
this.themeService,
this.environmentService,
this.contextViewService,
undefined,
undefined,
{
@@ -115,7 +121,7 @@ export class WebviewWidget extends DashboardWidget implements IDashboardWidget,
this._onMessageDisposable = this._webview.onMessage(e => {
this._onMessage.fire(e);
});
this._webview.style(this._dashboardService.themeService.getTheme());
this._webview.style(this.themeService.getTheme());
if (this._html) {
this._webview.contents = this._html;
}

View File

@@ -19,8 +19,9 @@ import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
import * as BackupConstants from 'sql/parts/disasterRecovery/backup/constants';
import { IBackupService, IBackupUiService, TaskExecutionMode } from 'sql/parts/disasterRecovery/backup/common/backupService';
import FileValidationConstants = require('sql/parts/fileBrowser/common/fileValidationServiceConstants');
import { DashboardComponentParams } from 'sql/services/bootstrap/bootstrapParams';
import { IBootstrapService, BOOTSTRAP_SERVICE_ID } from 'sql/services/bootstrap/bootstrapService';
import { IDashboardComponentParams } from 'sql/services/bootstrap/bootstrapParams';
import { IFileBrowserDialogController } from 'sql/parts/fileBrowser/common/interfaces';
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
import { MessageType } from 'vs/base/browser/ui/inputbox/inputBox';
import * as lifecycle from 'vs/base/common/lifecycle';
@@ -30,6 +31,9 @@ import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode } from 'vs/base/common/keyCodes';
import * as types from 'vs/base/common/types';
import * as strings from 'vs/base/common/strings';
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
export const BACKUP_SELECTOR: string = 'backup-component';
@@ -143,8 +147,6 @@ export class BackupComponent {
private localizedStrings = LocalizedStrings;
private _backupService: IBackupService;
private _backupUiService: IBackupUiService;
private _uri: string;
private _toDispose: lifecycle.IDisposable[] = [];
private _advancedHeaderSize = 32;
@@ -199,10 +201,14 @@ export class BackupComponent {
constructor(
@Inject(forwardRef(() => ElementRef)) private _el: ElementRef,
@Inject(forwardRef(() => ChangeDetectorRef)) private _changeDetectorRef: ChangeDetectorRef,
@Inject(BOOTSTRAP_SERVICE_ID) private _bootstrapService: IBootstrapService,
@Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService,
@Inject(IContextViewService) private contextViewService: IContextViewService,
@Inject(IFileBrowserDialogController) private fileBrowserDialogService: IFileBrowserDialogController,
@Inject(IBackupUiService) private _backupUiService: IBackupUiService,
@Inject(IBackupService) private _backupService: IBackupService,
@Inject(IClipboardService) private clipboardService: IClipboardService,
@Inject(IConnectionManagementService) private connectionManagementService: IConnectionManagementService
) {
this._backupService = _bootstrapService.backupService;
this._backupUiService = _bootstrapService.backupUiService;
this._backupUiService.onShowBackupEvent((param) => this.onGetBackupConfigInfo(param));
}
@@ -210,12 +216,12 @@ export class BackupComponent {
let self = this;
this.addFooterButtons();
this.recoveryBox = new InputBox(this.recoveryModelElement.nativeElement, this._bootstrapService.contextViewService, {
this.recoveryBox = new InputBox(this.recoveryModelElement.nativeElement, this.contextViewService, {
placeholder: this.recoveryModel,
ariaLabel: LocalizedStrings.RECOVERY_MODEL
});
// Set backup type
this.backupTypeSelectBox = new SelectBox([], '', this._bootstrapService.contextViewService);
this.backupTypeSelectBox = new SelectBox([], '', this.contextViewService);
this.backupTypeSelectBox.render(this.backupTypeElement.nativeElement);
// Set copy-only check box
@@ -259,12 +265,12 @@ export class BackupComponent {
});
// Set backup name
this.backupNameBox = new InputBox(this.backupNameElement.nativeElement, this._bootstrapService.contextViewService, {
this.backupNameBox = new InputBox(this.backupNameElement.nativeElement, this.contextViewService, {
ariaLabel: LocalizedStrings.BACKUP_NAME
});
// Set backup path list
this.pathListBox = new ListBox([], '', this._bootstrapService.contextViewService, this._bootstrapService.clipboardService);
this.pathListBox = new ListBox([], '', this.contextViewService, this.clipboardService);
this.pathListBox.render(this.pathElement.nativeElement);
// Set backup path add/remove buttons
@@ -277,18 +283,18 @@ export class BackupComponent {
this.removePathButton.title = localize('removeFile', 'Remove files');
// Set compression
this.compressionSelectBox = new SelectBox(this.compressionOptions, this.compressionOptions[0], this._bootstrapService.contextViewService);
this.compressionSelectBox = new SelectBox(this.compressionOptions, this.compressionOptions[0], this.contextViewService);
this.compressionSelectBox.render(this.compressionElement.nativeElement);
// Set encryption
this.algorithmSelectBox = new SelectBox(this.encryptionAlgorithms, this.encryptionAlgorithms[0], this._bootstrapService.contextViewService);
this.algorithmSelectBox = new SelectBox(this.encryptionAlgorithms, this.encryptionAlgorithms[0], this.contextViewService);
this.algorithmSelectBox.render(this.encryptionAlgorithmElement.nativeElement);
this.encryptorSelectBox = new SelectBox([], '', this._bootstrapService.contextViewService);
this.encryptorSelectBox = new SelectBox([], '', this.contextViewService);
this.encryptorSelectBox.render(this.encryptorElement.nativeElement);
// Set media
this.mediaNameBox = new InputBox(this.mediaNameElement.nativeElement,
this._bootstrapService.contextViewService,
this.contextViewService,
{
validationOptions: {
validation: (value: string) => !value ? ({ type: MessageType.ERROR, content: LocalizedStrings.MEDIA_NAME_REQUIRED_ERROR }) : null
@@ -297,14 +303,14 @@ export class BackupComponent {
}
);
this.mediaDescriptionBox = new InputBox(this.mediaDescriptionElement.nativeElement, this._bootstrapService.contextViewService, {
this.mediaDescriptionBox = new InputBox(this.mediaDescriptionElement.nativeElement, this.contextViewService, {
ariaLabel: LocalizedStrings.NEW_MEDIA_SET_DESCRIPTION
});
// Set backup retain days
let invalidInputMessage = localize('backupComponent.invalidInput', 'Invalid input. Value must be greater than or equal 0.');
this.backupRetainDaysBox = new InputBox(this.backupDaysElement.nativeElement,
this._bootstrapService.contextViewService,
this.contextViewService,
{
placeholder: '0',
type: 'number',
@@ -387,21 +393,21 @@ export class BackupComponent {
this.scriptButton = new Button(this.scriptButtonElement.nativeElement);
this.scriptButton.label = localize('backupComponent.script', 'Script');
this.addButtonClickHandler(this.scriptButton, () => this.onScript());
this._toDispose.push(attachButtonStyler(this.scriptButton, this._bootstrapService.themeService));
this._toDispose.push(attachButtonStyler(this.scriptButton, this.themeService));
this.scriptButton.enabled = false;
// Set backup footer button
this.backupButton = new Button(this.backupButtonElement.nativeElement);
this.backupButton.label = localize('backupComponent.backup', 'Backup');
this.addButtonClickHandler(this.backupButton, () => this.onOk());
this._toDispose.push(attachButtonStyler(this.backupButton, this._bootstrapService.themeService));
this._toDispose.push(attachButtonStyler(this.backupButton, this.themeService));
this.backupEnabled = false;
// Set cancel footer button
this.cancelButton = new Button(this.cancelButtonElement.nativeElement);
this.cancelButton.label = localize('backupComponent.cancel', 'Cancel');
this.addButtonClickHandler(this.cancelButton, () => this.onCancel());
this._toDispose.push(attachButtonStyler(this.cancelButton, this._bootstrapService.themeService));
this._toDispose.push(attachButtonStyler(this.cancelButton, this.themeService));
}
private initialize(isMetadataPopulated: boolean): void {
@@ -505,18 +511,18 @@ export class BackupComponent {
private registerListeners(): void {
// Theme styler
this._toDispose.push(attachInputBoxStyler(this.backupNameBox, this._bootstrapService.themeService));
this._toDispose.push(attachInputBoxStyler(this.recoveryBox, this._bootstrapService.themeService));
this._toDispose.push(attachSelectBoxStyler(this.backupTypeSelectBox, this._bootstrapService.themeService));
this._toDispose.push(attachListBoxStyler(this.pathListBox, this._bootstrapService.themeService));
this._toDispose.push(attachButtonStyler(this.addPathButton, this._bootstrapService.themeService));
this._toDispose.push(attachButtonStyler(this.removePathButton, this._bootstrapService.themeService));
this._toDispose.push(attachSelectBoxStyler(this.compressionSelectBox, this._bootstrapService.themeService));
this._toDispose.push(attachSelectBoxStyler(this.algorithmSelectBox, this._bootstrapService.themeService));
this._toDispose.push(attachSelectBoxStyler(this.encryptorSelectBox, this._bootstrapService.themeService));
this._toDispose.push(attachInputBoxStyler(this.mediaNameBox, this._bootstrapService.themeService));
this._toDispose.push(attachInputBoxStyler(this.mediaDescriptionBox, this._bootstrapService.themeService));
this._toDispose.push(attachInputBoxStyler(this.backupRetainDaysBox, this._bootstrapService.themeService));
this._toDispose.push(attachInputBoxStyler(this.backupNameBox, this.themeService));
this._toDispose.push(attachInputBoxStyler(this.recoveryBox, this.themeService));
this._toDispose.push(attachSelectBoxStyler(this.backupTypeSelectBox, this.themeService));
this._toDispose.push(attachListBoxStyler(this.pathListBox, this.themeService));
this._toDispose.push(attachButtonStyler(this.addPathButton, this.themeService));
this._toDispose.push(attachButtonStyler(this.removePathButton, this.themeService));
this._toDispose.push(attachSelectBoxStyler(this.compressionSelectBox, this.themeService));
this._toDispose.push(attachSelectBoxStyler(this.algorithmSelectBox, this.themeService));
this._toDispose.push(attachSelectBoxStyler(this.encryptorSelectBox, this.themeService));
this._toDispose.push(attachInputBoxStyler(this.mediaNameBox, this.themeService));
this._toDispose.push(attachInputBoxStyler(this.mediaDescriptionBox, this.themeService));
this._toDispose.push(attachInputBoxStyler(this.backupRetainDaysBox, this.themeService));
this._toDispose.push(this.backupTypeSelectBox.onDidSelect(selected => this.onBackupTypeChanged()));
this.addButtonClickHandler(this.addPathButton, () => this.onAddClick());
@@ -528,7 +534,7 @@ export class BackupComponent {
this.backupRetainDaysChanged(days);
}));
this._toDispose.push(this._bootstrapService.themeService.onDidColorThemeChange(e => this.updateTheme()));
this._toDispose.push(this.themeService.onDidColorThemeChange(e => this.updateTheme()));
}
// Update theming that is specific to backup dialog
@@ -566,7 +572,7 @@ export class BackupComponent {
private onCancel(): void {
this.close();
this._bootstrapService.connectionManagementService.disconnect(this._uri);
this.connectionManagementService.disconnect(this._uri);
}
private close(): void {
@@ -629,7 +635,7 @@ export class BackupComponent {
}
private onAddClick(): void {
this._bootstrapService.fileBrowserDialogService.showDialog(this._uri,
this.fileBrowserDialogService.showDialog(this._uri,
this.defaultNewBackupFolder,
BackupConstants.fileFiltersSet,
FileValidationConstants.backup,

View File

@@ -3,43 +3,50 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ApplicationRef, ComponentFactoryResolver, ModuleWithProviders, NgModule,
Inject, forwardRef } from '@angular/core';
import {
ApplicationRef, ComponentFactoryResolver, ModuleWithProviders, NgModule,
Inject, forwardRef, Type
} from '@angular/core';
import { APP_BASE_HREF, CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { IBootstrapService, BOOTSTRAP_SERVICE_ID } from 'sql/services/bootstrap/bootstrapService';
import { IBootstrapParams } from 'sql/services/bootstrap/bootstrapService';
import { BackupComponent, BACKUP_SELECTOR } from 'sql/parts/disasterRecovery/backup/backup.component';
// 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
@NgModule({
declarations: [
BackupComponent
],
entryComponents: [BackupComponent],
imports: [
FormsModule,
CommonModule,
BrowserModule,
BrowserAnimationsModule,
],
providers: [{ provide: APP_BASE_HREF, useValue: '/' }]
})
export class BackupModule {
export const BackupModule = (params: IBootstrapParams, selector: string): Type<any> => {
@NgModule({
declarations: [
BackupComponent
],
entryComponents: [BackupComponent],
imports: [
FormsModule,
CommonModule,
BrowserModule,
BrowserAnimationsModule,
],
providers: [
{ provide: APP_BASE_HREF, useValue: '/' },
{ provide: IBootstrapParams, useValue: params }
]
})
class ModuleClass {
constructor(
@Inject(forwardRef(() => ComponentFactoryResolver)) private _resolver: ComponentFactoryResolver,
@Inject(BOOTSTRAP_SERVICE_ID) private _bootstrapService: IBootstrapService
) {
constructor(
@Inject(forwardRef(() => ComponentFactoryResolver)) private _resolver: ComponentFactoryResolver
) {
}
ngDoBootstrap(appRef: ApplicationRef) {
const factory = this._resolver.resolveComponentFactory(BackupComponent);
(<any>factory).factory.selector = selector;
appRef.bootstrap(factory);
}
}
ngDoBootstrap(appRef: ApplicationRef) {
const factory = this._resolver.resolveComponentFactory(BackupComponent);
const uniqueSelector: string = this._bootstrapService.getUniqueSelector(BACKUP_SELECTOR);
(<any>factory).factory.selector = uniqueSelector;
appRef.bootstrap(factory);
}
}
return ModuleClass;
};

View File

@@ -7,7 +7,6 @@ import { Modal } from 'sql/base/browser/ui/modal/modal';
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
import { BackupModule } from 'sql/parts/disasterRecovery/backup/backup.module';
import { BACKUP_SELECTOR } from 'sql/parts/disasterRecovery/backup/backup.component';
import { IBootstrapService } from 'sql/services/bootstrap/bootstrapService';
import { attachModalDialogStyler } from 'sql/common/theme/styler';
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
import * as TelemetryKeys from 'sql/common/telemetryKeys';
@@ -17,6 +16,8 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IPartService } from 'vs/workbench/services/part/common/partService';
import { Builder } from 'vs/base/browser/builder';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { bootstrapAngular } from 'sql/services/bootstrap/bootstrapService';
export class BackupDialog extends Modal {
private _bodyBuilder: Builder;
@@ -25,12 +26,12 @@ export class BackupDialog extends Modal {
private _moduleRef: any;
constructor(
@IBootstrapService private _bootstrapService: IBootstrapService,
@IThemeService private _themeService: IThemeService,
@IPartService partService: IPartService,
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
@ITelemetryService telemetryService: ITelemetryService,
@IContextKeyService contextKeyService: IContextKeyService
@IContextKeyService contextKeyService: IContextKeyService,
@IInstantiationService private _instantiationService: IInstantiationService
) {
super('', TelemetryKeys.Backup, partService, telemetryService, contextKeyService, { isAngular: true, hasErrors: true });
}
@@ -53,7 +54,7 @@ export class BackupDialog extends Modal {
* Get the bootstrap params and perform the bootstrap
*/
private bootstrapAngular(bodyContainer: HTMLElement) {
this._uniqueSelector = this._bootstrapService.bootstrap(
this._uniqueSelector = this._instantiationService.invokeFunction(bootstrapAngular,
BackupModule,
bodyContainer,
BACKUP_SELECTOR,

View File

@@ -9,7 +9,7 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'
import Event from 'vs/base/common/event';
import * as sqlops from 'sqlops';
import { DashboardComponentParams } from 'sql/services/bootstrap/bootstrapParams';
import { IDashboardComponentParams } from 'sql/services/bootstrap/bootstrapParams';
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';

Some files were not shown because too many files have changed in this diff Show More