Compare commits

..

41 Commits
1.4.1 ... 1.4.3

Author SHA1 Message Date
Chris LaFreniere
e8eb7bec1b Fix notebook selection issues including from placeholder (#3836) 2019-01-28 14:02:23 -08:00
kisantia
565b7404f9 Add generate script option to DacFx wizard (#3789)
* Add generate script option to deploy scenario

* add action to summary page and fixed page adding/removing so that summary page will have the correct step number

* updating contract based on change in sqltoolsservice

* added enums to make index checks more clear

* cleaned up onPageChanged()

* bump sqltoolsservice version to 68
2019-01-28 10:48:36 -08:00
Chris LaFreniere
9cffe4d476 Allow for "when" clause filtering for Notebook Toolbar Given ProviderId Changes (#3712)
* Integrate first SQL Notebooks Bits into Master (#3679)

* First crack tsql notebook (no output rendered yet)

* getting messages back

* intellisense working first cell, no connection errors

* sql notebook cell output functioning

* Latest SQL noteobook changes

* Undo change to launch.json

* Plumbing providers through

* Kernels shown from multiple providers, can switch between them. No mementos yet

* Ensure we have a feature flag for SQL notebooks, ensure existing functionality still works

* Fix tslint duplicate imports issue

* Addressing PR comments

* second round of PR feedback to cleanup notebook service manager code

* merge latest from master

* Enable notebook toolbar actions to disable themselves on provider change

* Undo changes to taskbar/actionbar

* very minor change due to latest merge
2019-01-26 11:01:40 -08:00
Chris LaFreniere
43be88a37c SQL Kernel Improvements/Removing Spark Code from Core/Attach to Changes (#3790)
* Scenarios work besides loading saved kernel

* Fix compilation issue

* Save and load functional

* Fix loading kernesl issue when sql kernel is not enabled

* Fix language mapping to not be hardcoded any longer

* Remove unnecessary comment

* PR Comments vol. 1

* Code cleanup, use ConnectionProfile instead of IConnectionProfile when accessing serverName

* PR changes vol. 2

* One final comment for PR

* Fix linting issue
2019-01-25 18:54:04 -08:00
Anthony Dresser
ea67859de7 Initial Code Layering (#3788)
* working on formatting

* fixed basic lint errors; starting moving things to their appropriate location

* formatting

* update tslint to match the version of vscode we have

* remove unused code

* work in progress fixing layering

* formatting

* moved connection management service to platform

* formatting

* add missing file

* moving more servies

* formatting

* moving more services

* formatting

* wip

* moving more services

* formatting

* revert back tslint rules

* move css file

* add missing svgs
2019-01-25 14:52:35 -08:00
Aditya Bist
c8986464ec fixed arrows disappearing after tab change (#3829) 2019-01-25 13:29:39 -08:00
Aditya Bist
7804f94d8b Copy all messages when selecting all (#3818)
* copy all messages when selecting all

* added functionality for keyboard shortcuts

* fixed bug when select all then selection made

* made output similar to debug console
2019-01-25 12:10:00 -08:00
Alan Ren
bfa77aebfc add clear filter icon and update filter icon from Smitha (#3828) 2019-01-25 11:34:58 -08:00
Yurong He
487fb02313 Bump sqltoolservice version to 67 for unified connection support (#3827) 2019-01-25 11:24:26 -08:00
Aditya Bist
ef64038107 Added horizontal scrolling for explorer (#3819)
* added horizontal scrolling for explorer

* made horizontal scrolling auto
2019-01-24 13:31:19 -08:00
udeeshagautam
5d336accbc adding hover text for dashboard serach grid items (#3816)
Fix for issue : Search widget in Manage dashboard truncates long names with no hovertext to show full name (Ref issue: #3075)
2019-01-24 13:17:37 -08:00
Karl Burtram
99047b2866 Remove Ctrl-Alt keyboard shortcuts (#3810) 2019-01-23 17:23:59 -08:00
Aditya Bist
f611cf3b5a Improve Agent performance (#3804)
* pause and resume job history retrieval when opening dialogs

* review comments

* removed boolean for tab change
2019-01-23 14:25:54 -08:00
Karl Burtram
4ad059605c Update Azure account picker styles based on splitview change (#3791) 2019-01-23 10:50:41 -08:00
Karl Burtram
dc2ff97dd8 Bump Azure Data Studio to 1.4.3 2019-01-22 16:54:51 -08:00
Karl Burtram
2b5265c103 Fix infinite callbacks in Azure Resource Explorer (#3780) 2019-01-22 15:22:45 -08:00
Aditya Bist
2e98fde053 fixed resizing in agent because of slickgrid change (#3786) 2019-01-22 14:38:20 -08:00
Anthony Dresser
d5176e0eb7 remove updating row number column size (#3756) 2019-01-22 14:37:59 -08:00
Anthony Dresser
eb0b2a847b change stating to handle magnify state (#3746)
* change stating to handle magnify state

* fix magnify during state setup
2019-01-22 14:37:33 -08:00
Aditya Bist
cff5482f69 Show Azure Data Studio instead of azuredatastudio when updating (#3787)
* show Azure Data Studio instead of azuredatastudio when updating

* added sql carbon tag
2019-01-22 10:58:40 -08:00
Alan Ren
afc37973d0 Update readme.md 2019-01-22 10:53:26 -08:00
Alan Ren
3eada6c6ab Create readme.md 2019-01-22 10:21:18 -08:00
Aditya Bist
7c39268fe5 Agent - bug fixes and mini features (#3637)
* fixed scrollbar in jobs

* show steps tree when job history is opened

* cleaned and added edit job to job history

* scrollbars on step details

* steps scrolling done

* fixed styling

* fixed keyboard selection, navigation and UI

* fixed tabbing accessibility

* added refresh action to job history

* fixed focus on move step

* added remove schedule button

* fixed various bugs

* added errors for all actions

* review comments
2019-01-22 10:01:13 -08:00
Alan Ren
eb67b299de Alanren/integration test (#3657)
* add an extension for integration tests

* setup ads before running test

* test setup

* test cases

* bash script

* shorter temp folder name

* code cleanup

* add commented out original code

* fix test error

* test result path

* rename results file

* change file path

* report smoke test results

* test stablize

* test stablization and configurable test servers

* fix smoke test error

* connection provider

* simplify the integration test script

* add comment

* fix tslint error

* address PR comments

* add temp log to check whether the environment variable is already set

* remove temp log

* move api definition to testapi typing file

* exclude integration tests extension

* address comments
2019-01-18 17:00:30 -08:00
Alan Ren
3e7a09c1e3 Alanren/profiler filter (#3760)
* profiler filter

* add test cases

* perf improvement with bulk insert

* update dependency version and address comments
2019-01-18 16:25:18 -08:00
Karl Burtram
637dc9b9b2 Bump Azure Data Studio to 1.4.2 2019-01-18 09:48:44 -08:00
Karl Burtram
1de16d4715 Reset query messages for each execution (#3772) 2019-01-17 17:53:05 -08:00
Kevin Cunnane
49090d774d Null ref occurred when doing some UI interactions before the notebook model was set (#3769) 2019-01-17 14:41:56 -08:00
Karl Burtram
9a695b5cdd Reenable results stream by default (#3752) 2019-01-17 10:28:48 -08:00
Raj
e0339b50c0 #3753: User settings configuration - python installation path (#3754)
* #3753: User settings configuration - python installation path

* Text change

* #3753: Text change

* Message change
2019-01-16 16:29:06 -08:00
Karl Burtram
d0c584672f Fix Top Operations tab title (#3751) 2019-01-15 16:06:51 -08:00
Anthony Dresser
27816acaeb Remove custom splitview (#3467)
* working on options dialog

* working through options dialog

* trying to work through modifying options dialog

* working on converting scrollablesplitview

* fixed options working through profiler

* fix profiler

* fix account dialog

* trying to fix problems with splitpanel

* fix insights dialog

* moving through

* fix last list, need to verify looks and functionality

* fix look of account dialog

* formatting

* formatting

* working through scrollable bugs

* working on problem with view size

* fix margin issues

* fix styler for dialogs

* add panel styles to insights

* create instantiation issues

* fix test

* fix test

* remove unused code

* formatting

* working through insight dialog issues

* fix table updating

* remove console logs
2019-01-15 15:00:34 -08:00
Mustafa Sadedil
4de3cc8a09 Completed: Missing feature request: Save as XML (#3729)
* Save as XML feature added to grid

* Unrelated code removed
2019-01-15 14:36:42 -08:00
Karl Burtram
5c16ceb2fa Bump SQL Tools Service to pick up https://github.com/Microsoft/sqltoolsservice/pull/763 (#3748) 2019-01-15 14:12:20 -08:00
Raj
9db3f73413 Notebook Doesn't Prompt for Save even when isDirty #3568 (#3656)
This is temp fix until native save is implemented.
2019-01-15 11:41:05 -08:00
Chris LaFreniere
e0ceddce09 Notebooks: Add Placeholder Cell, Fix Link Styling (#3728)
* Placeholder cell to add new real cells

* Fix links in notebooks to show correct color, rely on angular ngif for placeholder

* Fix failing test where one cell was expected by default

* Remove unnecessary TODO
2019-01-14 17:29:06 -08:00
Chris LaFreniere
6dc4096299 Editor focus based on activeCell, create text in edit, scroll to active (#3725) 2019-01-14 16:39:36 -08:00
Chris LaFreniere
1fa03b5c74 Ensure we always get all providers (#3724) 2019-01-14 16:38:57 -08:00
Kevin Cunnane
f8f57a93c3 Fix #3736 Notebook: cannot connect to SQL big data cluster due to empty config.json file (#3738)
- Writing the config file in the core for now, will look to move to the extension in Feb release
2019-01-14 14:14:32 -08:00
Karl Burtram
960fe63312 Bump Data Protocol client to 0.2.11 (#3739) 2019-01-14 14:04:35 -08:00
Karl Burtram
7545b94128 Turn off "something went wrong" message (#3606) 2019-01-11 17:39:13 -08:00
472 changed files with 11217 additions and 10630 deletions

10
.vscode/launch.json vendored
View File

@@ -152,6 +152,16 @@
"args": [ "args": [
"--extensionDevelopmentPath=${workspaceRoot}/extensions/debug-auto-launch" "--extensionDevelopmentPath=${workspaceRoot}/extensions/debug-auto-launch"
] ]
},
{
"type": "node",
"request": "launch",
"name": "Launch Smoke Test",
"program": "${workspaceFolder}/test/smoke/test/index.js",
"cwd": "${workspaceFolder}/test/smoke",
"env": {
"BUILD_ARTIFACTSTAGINGDIRECTORY": "${workspaceFolder}"
}
} }
], ],
"compounds": [ "compounds": [

View File

@@ -65,6 +65,8 @@ const excludedExtensions = [
'vscode-colorize-tests', 'vscode-colorize-tests',
'ms-vscode.node-debug', 'ms-vscode.node-debug',
'ms-vscode.node-debug2', 'ms-vscode.node-debug2',
// {{SQL CARBON EDIT}}
'integration-tests',
]; ];
// {{SQL CARBON EDIT}} // {{SQL CARBON EDIT}}

View File

@@ -26,6 +26,7 @@ export class JobData implements IAgentDialogData {
private _operators: string[]; private _operators: string[];
private _defaultOwner: string; private _defaultOwner: string;
private _jobCompletionActionConditions: sqlops.CategoryValue[]; private _jobCompletionActionConditions: sqlops.CategoryValue[];
private _jobCategoryIdsMap: sqlops.AgentJobCategory[];
public dialogMode: AgentDialogMode = AgentDialogMode.CREATE; public dialogMode: AgentDialogMode = AgentDialogMode.CREATE;
public name: string; public name: string;
@@ -46,6 +47,7 @@ export class JobData implements IAgentDialogData {
public alerts: sqlops.AgentAlertInfo[]; public alerts: sqlops.AgentAlertInfo[];
public jobId: string; public jobId: string;
public startStepId: number; public startStepId: number;
public categoryType: number;
constructor( constructor(
ownerUri: string, ownerUri: string,
@@ -66,6 +68,8 @@ export class JobData implements IAgentDialogData {
this.alerts = jobInfo.alerts; this.alerts = jobInfo.alerts;
this.jobId = jobInfo.jobId; this.jobId = jobInfo.jobId;
this.startStepId = jobInfo.startStepId; this.startStepId = jobInfo.startStepId;
this.categoryId = jobInfo.categoryId;
this.categoryType = jobInfo.categoryType;
} }
} }
@@ -73,6 +77,10 @@ export class JobData implements IAgentDialogData {
return this._jobCategories; return this._jobCategories;
} }
public get jobCategoryIdsMap(): sqlops.AgentJobCategory[] {
return this._jobCategoryIdsMap;
}
public get operators(): string[] { public get operators(): string[] {
return this._operators; return this._operators;
} }
@@ -96,7 +104,7 @@ export class JobData implements IAgentDialogData {
this._jobCategories = jobDefaults.categories.map((cat) => { this._jobCategories = jobDefaults.categories.map((cat) => {
return cat.name; return cat.name;
}); });
this._jobCategoryIdsMap = jobDefaults.categories;
this._defaultOwner = jobDefaults.owner; this._defaultOwner = jobDefaults.owner;
this._operators = ['', this._defaultOwner]; this._operators = ['', this._defaultOwner];
@@ -164,8 +172,8 @@ export class JobData implements IAgentDialogData {
hasSchedule: false, hasSchedule: false,
hasStep: false, hasStep: false,
runnable: true, runnable: true,
categoryId: 0, categoryId: this.categoryId,
categoryType: 1, // LocalJob, hard-coding the value, corresponds to the target tab in SSMS categoryType: this.categoryType,
lastRun: '', lastRun: '',
nextRun: '', nextRun: '',
jobId: this.jobId, jobId: this.jobId,

View File

@@ -94,6 +94,9 @@ export class JobDialog extends AgentDialog<JobData> {
private editStepButton: sqlops.ButtonComponent; private editStepButton: sqlops.ButtonComponent;
private deleteStepButton: sqlops.ButtonComponent; private deleteStepButton: sqlops.ButtonComponent;
// Schedule tab controls
private removeScheduleButton: sqlops.ButtonComponent;
// Notifications tab controls // Notifications tab controls
private notificationsTabTopLabel: sqlops.TextComponent; private notificationsTabTopLabel: sqlops.TextComponent;
private emailCheckBox: sqlops.CheckBoxComponent; private emailCheckBox: sqlops.CheckBoxComponent;
@@ -302,6 +305,7 @@ export class JobDialog extends AgentDialog<JobData> {
this.stepsTable.data = this.convertStepsToData(this.steps); this.stepsTable.data = this.convertStepsToData(this.steps);
this.steps[previousRow].id = previousStepId; this.steps[previousRow].id = previousStepId;
this.steps[rowNumber].id = currentStepId; this.steps[rowNumber].id = currentStepId;
this.stepsTable.selectedRows = [previousRow];
}); });
this.moveStepDownButton.onDidClick(() => { this.moveStepDownButton.onDidClick(() => {
@@ -316,6 +320,7 @@ export class JobDialog extends AgentDialog<JobData> {
this.stepsTable.data = this.convertStepsToData(this.steps); this.stepsTable.data = this.convertStepsToData(this.steps);
this.steps[nextRow].id = nextStepId; this.steps[nextRow].id = nextStepId;
this.steps[rowNumber].id = currentStepId; this.steps[rowNumber].id = currentStepId;
this.stepsTable.selectedRows = [nextRow];
}); });
this.editStepButton.onDidClick(() => { this.editStepButton.onDidClick(() => {
@@ -346,20 +351,30 @@ export class JobDialog extends AgentDialog<JobData> {
if (this.stepsTable.selectedRows.length === 1) { if (this.stepsTable.selectedRows.length === 1) {
let rowNumber = this.stepsTable.selectedRows[0]; let rowNumber = this.stepsTable.selectedRows[0];
AgentUtils.getAgentService().then((agentService) => { AgentUtils.getAgentService().then((agentService) => {
let steps = this.model.jobSteps ? this.model.jobSteps : []; let stepData = this.steps[rowNumber];
let stepData = this.model.jobSteps[rowNumber]; if (stepData.jobId) {
agentService.deleteJobStep(this.ownerUri, stepData).then((result) => { agentService.deleteJobStep(this.ownerUri, stepData).then((result) => {
if (result && result.success) { if (result && result.success) {
delete steps[rowNumber]; this.steps.splice(rowNumber, 1);
let data = this.convertStepsToData(steps); let data = this.convertStepsToData(this.steps);
this.stepsTable.data = data; this.stepsTable.data = data;
this.startStepDropdownValues = []; this.startStepDropdownValues = [];
this.steps.forEach((step) => { this.steps.forEach((step) => {
this.startStepDropdownValues.push({ displayName: step.id + ': ' + step.stepName, name: step.id.toString() }); this.startStepDropdownValues.push({ displayName: step.id + ': ' + step.stepName, name: step.id.toString() });
}); });
this.startStepDropdown.values = this.startStepDropdownValues; this.startStepDropdown.values = this.startStepDropdownValues;
} }
}); });
} else {
this.steps.splice(rowNumber, 1);
let data = this.convertStepsToData(this.steps);
this.stepsTable.data = data;
this.startStepDropdownValues = [];
this.steps.forEach((step) => {
this.startStepDropdownValues.push({ displayName: step.id + ': ' + step.stepName, name: step.id.toString() });
});
this.startStepDropdown.values = this.startStepDropdownValues;
}
}); });
} }
}); });
@@ -468,7 +483,11 @@ export class JobDialog extends AgentDialog<JobData> {
label: this.PickScheduleButtonString, label: this.PickScheduleButtonString,
width: 80 width: 80
}).component(); }).component();
this.pickScheduleButton.onDidClick((e)=>{ this.removeScheduleButton = view.modelBuilder.button().withProperties({
label: 'Remove schedule',
width: 100
}).component();
this.pickScheduleButton.onDidClick(()=>{
let pickScheduleDialog = new PickScheduleDialog(this.model.ownerUri, this.model.name); let pickScheduleDialog = new PickScheduleDialog(this.model.ownerUri, this.model.name);
pickScheduleDialog.onSuccess((dialogModel) => { pickScheduleDialog.onSuccess((dialogModel) => {
let selectedSchedule = dialogModel.selectedSchedule; let selectedSchedule = dialogModel.selectedSchedule;
@@ -483,12 +502,23 @@ export class JobDialog extends AgentDialog<JobData> {
}); });
pickScheduleDialog.showDialog(); pickScheduleDialog.showDialog();
}); });
this.removeScheduleButton.onDidClick(() => {
if (this.schedulesTable.selectedRows.length === 1) {
let selectedRow = this.schedulesTable.selectedRows[0];
let selectedScheduleName = this.schedulesTable.data[selectedRow][1];
for (let i = 0; i < this.schedules.length; i++) {
if (this.schedules[i].name === selectedScheduleName) {
this.schedules.splice(i, 1);
}
}
this.populateScheduleTable();
}
});
let formModel = view.modelBuilder.formContainer() let formModel = view.modelBuilder.formContainer()
.withFormItems([{ .withFormItems([{
component: this.schedulesTable, component: this.schedulesTable,
title: this.SchedulesTopLabelString, title: this.SchedulesTopLabelString,
actions: [this.pickScheduleButton] actions: [this.pickScheduleButton, this.removeScheduleButton]
}]).withLayout({ width: '100%' }).component(); }]).withLayout({ width: '100%' }).component();
await view.initializeModel(formModel); await view.initializeModel(formModel);
@@ -499,10 +529,9 @@ export class JobDialog extends AgentDialog<JobData> {
private populateScheduleTable() { private populateScheduleTable() {
let data = this.convertSchedulesToData(this.schedules); let data = this.convertSchedulesToData(this.schedules);
if (data.length > 0) { this.schedulesTable.data = data;
this.schedulesTable.data = data; this.schedulesTable.height = 750;
this.schedulesTable.height = 750;
}
} }
private initializeNotificationsTab() { private initializeNotificationsTab() {
@@ -674,5 +703,6 @@ export class JobDialog extends AgentDialog<JobData> {
this.model.alerts = []; this.model.alerts = [];
} }
this.model.alerts = this.alerts; this.model.alerts = this.alerts;
this.model.categoryId = +this.model.jobCategoryIdsMap.find(cat => cat.name === this.model.category).id;
} }
} }

View File

@@ -29,11 +29,10 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
private readonly AdvancedTabText: string = localize('jobStepDialog.advanced', 'Advanced'); private readonly AdvancedTabText: string = localize('jobStepDialog.advanced', 'Advanced');
private readonly OpenCommandText: string = localize('jobStepDialog.open', 'Open...'); private readonly OpenCommandText: string = localize('jobStepDialog.open', 'Open...');
private readonly ParseCommandText: string = localize('jobStepDialog.parse','Parse'); private readonly ParseCommandText: string = localize('jobStepDialog.parse','Parse');
private readonly NextButtonText: string = localize('jobStepDialog.next', 'Next');
private readonly PreviousButtonText: string = localize('jobStepDialog.previous','Previous');
private readonly SuccessfulParseText: string = localize('jobStepDialog.successParse', 'The command was successfully parsed.'); private readonly SuccessfulParseText: string = localize('jobStepDialog.successParse', 'The command was successfully parsed.');
private readonly FailureParseText: string = localize('jobStepDialog.failParse', 'The command failed.'); private readonly FailureParseText: string = localize('jobStepDialog.failParse', 'The command failed.');
private readonly BlankStepNameErrorText: string = localize('jobStepDialog.blankStepName', 'The step name cannot be left blank'); private readonly BlankStepNameErrorText: string = localize('jobStepDialog.blankStepName', 'The step name cannot be left blank');
private readonly ProcessExitCodeText: string = localize('jobStepDialog.processExitCode', 'Process exit code of a successful command:');
// General Control Titles // General Control Titles
private readonly StepNameLabelString: string = localize('jobStepDialog.stepNameLabel', 'Step Name'); private readonly StepNameLabelString: string = localize('jobStepDialog.stepNameLabel', 'Step Name');
@@ -62,6 +61,8 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
// Dropdown options // Dropdown options
private readonly TSQLScript: string = localize('jobStepDialog.TSQL', 'Transact-SQL script (T-SQL)'); private readonly TSQLScript: string = localize('jobStepDialog.TSQL', 'Transact-SQL script (T-SQL)');
private readonly Powershell: string = localize('jobStepDialog.powershell', 'PowerShell');
private readonly CmdExec: string = localize('jobStepDialog.CmdExec', 'Operating system (CmdExec)');
private readonly AgentServiceAccount: string = localize('jobStepDialog.agentServiceAccount', 'SQL Server Agent Service Account'); private readonly AgentServiceAccount: string = localize('jobStepDialog.agentServiceAccount', 'SQL Server Agent Service Account');
private readonly NextStep: string = localize('jobStepDialog.nextStep', 'Go to the next step'); private readonly NextStep: string = localize('jobStepDialog.nextStep', 'Go to the next step');
private readonly QuitJobReportingSuccess: string = localize('jobStepDialog.quitJobSuccess', 'Quit the job reporting success'); private readonly QuitJobReportingSuccess: string = localize('jobStepDialog.quitJobSuccess', 'Quit the job reporting success');
@@ -88,6 +89,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
private outputFileNameBox: sqlops.InputBoxComponent; private outputFileNameBox: sqlops.InputBoxComponent;
private fileBrowserNameBox: sqlops.InputBoxComponent; private fileBrowserNameBox: sqlops.InputBoxComponent;
private userInputBox: sqlops.InputBoxComponent; private userInputBox: sqlops.InputBoxComponent;
private processExitCodeBox: sqlops.InputBoxComponent;
// Dropdowns // Dropdowns
private typeDropdown: sqlops.DropDownComponent; private typeDropdown: sqlops.DropDownComponent;
@@ -100,8 +102,6 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
// Buttons // Buttons
private openButton: sqlops.ButtonComponent; private openButton: sqlops.ButtonComponent;
private parseButton: sqlops.ButtonComponent; private parseButton: sqlops.ButtonComponent;
private nextButton: sqlops.ButtonComponent;
private previousButton: sqlops.ButtonComponent;
private outputFileBrowserButton: sqlops.ButtonComponent; private outputFileBrowserButton: sqlops.ButtonComponent;
// Checkbox // Checkbox
@@ -179,18 +179,6 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
inputType: 'text' inputType: 'text'
}) })
.component(); .component();
this.nextButton = view.modelBuilder.button()
.withProperties({
label: this.NextButtonText,
enabled: false,
width: '80px'
}).component();
this.previousButton = view.modelBuilder.button()
.withProperties({
label: this.PreviousButtonText,
enabled: false,
width: '80px'
}).component();
} }
private createGeneralTab(databases: string[], queryProvider: sqlops.QueryProvider) { private createGeneralTab(databases: string[], queryProvider: sqlops.QueryProvider) {
@@ -208,7 +196,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
this.typeDropdown = view.modelBuilder.dropDown() this.typeDropdown = view.modelBuilder.dropDown()
.withProperties({ .withProperties({
value: this.TSQLScript, value: this.TSQLScript,
values: [this.TSQLScript] values: [this.TSQLScript, this.CmdExec, this.Powershell]
}) })
.component(); .component();
this.runAsDropdown = view.modelBuilder.dropDown() this.runAsDropdown = view.modelBuilder.dropDown()
@@ -218,33 +206,20 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
}) })
.component(); .component();
this.runAsDropdown.enabled = false; this.runAsDropdown.enabled = false;
this.typeDropdown.onValueChanged((type) => {
if (type.selected !== this.TSQLScript) {
this.runAsDropdown.value = this.AgentServiceAccount;
this.runAsDropdown.values = [this.runAsDropdown.value];
} else {
this.runAsDropdown.value = '';
this.runAsDropdown.values = [''];
}
});
this.databaseDropdown = view.modelBuilder.dropDown() this.databaseDropdown = view.modelBuilder.dropDown()
.withProperties({ .withProperties({
value: databases[0], value: databases[0],
values: databases values: databases
}).component(); }).component();
this.processExitCodeBox = view.modelBuilder.inputBox()
.withProperties({
}).component();
this.processExitCodeBox.enabled = false;
// create the commands section // create the commands section
this.createCommands(view, queryProvider); this.createCommands(view, queryProvider);
let buttonContainer = view.modelBuilder.flexContainer()
.withLayout({
flexFlow: 'row',
justifyContent: 'space-between',
width: 420
}).withItems([this.openButton, this.parseButton, this.previousButton, this.nextButton], {
flex: '1 1 50%'
}).component();
let formModel = view.modelBuilder.formContainer() let formModel = view.modelBuilder.formContainer()
.withFormItems([{ .withFormItems([{
component: this.nameTextBox, component: this.nameTextBox,
@@ -258,14 +233,52 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
}, { }, {
component: this.databaseDropdown, component: this.databaseDropdown,
title: this.DatabaseLabelString title: this.DatabaseLabelString
}, {
component: this.processExitCodeBox,
title: this.ProcessExitCodeText
}, { }, {
component: this.commandTextBox, component: this.commandTextBox,
title: this.CommandLabelString, title: this.CommandLabelString,
actions: [buttonContainer] actions: [this.openButton, this.parseButton]
}], { }], {
horizontal: false, horizontal: false,
componentWidth: 420 componentWidth: 420
}).component(); }).component();
this.typeDropdown.onValueChanged((type) => {
switch (type.selected) {
case(this.TSQLScript):
this.runAsDropdown.value = '';
this.runAsDropdown.values = [''];
this.runAsDropdown.enabled = false;
this.databaseDropdown.enabled = true;
this.databaseDropdown.values = databases;
this.databaseDropdown.value = databases[0];
this.processExitCodeBox.value = '';
this.processExitCodeBox.enabled = false;
break;
case(this.Powershell):
this.runAsDropdown.value = this.AgentServiceAccount;
this.runAsDropdown.values = [this.runAsDropdown.value];
this.runAsDropdown.enabled = true;
this.databaseDropdown.enabled = false;
this.databaseDropdown.values = [''];
this.databaseDropdown.value = '';
this.processExitCodeBox.value = '';
this.processExitCodeBox.enabled = false;
break;
case(this.CmdExec):
this.databaseDropdown.enabled = false;
this.databaseDropdown.values = [''];
this.databaseDropdown.value = '';
this.runAsDropdown.value = this.AgentServiceAccount;
this.runAsDropdown.values = [this.runAsDropdown.value];
this.runAsDropdown.enabled = true;
this.processExitCodeBox.enabled = true;
this.processExitCodeBox.value = '0';
break;
}
});
let formWrapper = view.modelBuilder.loadingComponent().withItem(formModel).component(); let formWrapper = view.modelBuilder.loadingComponent().withItem(formModel).component();
formWrapper.loading = false; formWrapper.loading = false;
await view.initializeModel(formWrapper); await view.initializeModel(formWrapper);
@@ -524,6 +537,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
this.model.outputFileName = this.outputFileNameBox.value; this.model.outputFileName = this.outputFileNameBox.value;
this.model.appendToLogFile = this.appendToExistingFileCheckbox.checked; this.model.appendToLogFile = this.appendToExistingFileCheckbox.checked;
this.model.command = this.commandTextBox.value ? this.commandTextBox.value : ''; this.model.command = this.commandTextBox.value ? this.commandTextBox.value : '';
this.model.commandExecutionSuccessCode = this.processExitCodeBox.value ? +this.processExitCodeBox.value : 0;
} }
public async initializeDialog() { public async initializeDialog() {

View File

@@ -90,12 +90,9 @@ export class AzureResourceAccountTreeNode extends AzureResourceContainerTreeNode
} }
} catch (error) { } catch (error) {
if (error instanceof AzureResourceCredentialError) { if (error instanceof AzureResourceCredentialError) {
this.appContext.apiWrapper.showErrorMessage(error.message);
this.appContext.apiWrapper.executeCommand('azure.resource.signin'); this.appContext.apiWrapper.executeCommand('azure.resource.signin');
} else {
return [AzureResourceMessageTreeNode.create(AzureResourceErrorMessageUtil.getErrorMessage(error), this)];
} }
return [AzureResourceMessageTreeNode.create(AzureResourceErrorMessageUtil.getErrorMessage(error), this)];
} }
} }

View File

@@ -32,7 +32,7 @@ export class AzureResourceTreeProvider implements TreeDataProvider<TreeNode>, IA
return element.getChildren(true); return element.getChildren(true);
} }
if (!this.isSystemInitialized) { if (!this.isSystemInitialized && !this._loadingTimer) {
this._loadingTimer = setInterval(async () => { this._loadingTimer = setInterval(async () => {
try { try {
// Call sqlops.accounts.getAllAccounts() to determine whether the system has been initialized. // Call sqlops.accounts.getAllAccounts() to determine whether the system has been initialized.

View File

@@ -40,4 +40,57 @@ export function generateGuid(): string {
let clockSequenceHi: string = hexValues[8 + (Math.random() * 4) | 0]; let clockSequenceHi: string = hexValues[8 + (Math.random() * 4) | 0];
return oct.substr(0, 8) + '-' + oct.substr(9, 4) + '-4' + oct.substr(13, 3) + '-' + clockSequenceHi + oct.substr(16, 3) + '-' + oct.substr(19, 12); return oct.substr(0, 8) + '-' + oct.substr(9, 4) + '-4' + oct.substr(13, 3) + '-' + clockSequenceHi + oct.substr(16, 3) + '-' + oct.substr(19, 12);
/* tslint:enable:no-bitwise */ /* tslint:enable:no-bitwise */
}
export function equals(one: any, other: any): boolean {
if (one === other) {
return true;
}
if (one === null || one === undefined || other === null || other === undefined) {
return false;
}
if (typeof one !== typeof other) {
return false;
}
if (typeof one !== 'object') {
return false;
}
if ((Array.isArray(one)) !== (Array.isArray(other))) {
return false;
}
let i: number;
let key: string;
if (Array.isArray(one)) {
if (one.length !== other.length) {
return false;
}
for (i = 0; i < one.length; i++) {
if (!equals(one[i], other[i])) {
return false;
}
}
} else {
const oneKeys: string[] = [];
for (key in one) {
oneKeys.push(key);
}
oneKeys.sort();
const otherKeys: string[] = [];
for (key in other) {
otherKeys.push(key);
}
otherKeys.sort();
if (!equals(oneKeys, otherKeys)) {
return false;
}
for (i = 0; i < oneKeys.length; i++) {
if (!equals(one[oneKeys[i]], other[oneKeys[i]])) {
return false;
}
}
}
return true;
} }

View File

@@ -25,6 +25,7 @@ import { AzureResourceTenantService } from '../azureResource/services/tenantServ
import { registerAzureResourceDatabaseServerCommands } from '../azureResource/providers/databaseServer/commands'; import { registerAzureResourceDatabaseServerCommands } from '../azureResource/providers/databaseServer/commands';
import { registerAzureResourceDatabaseCommands } from '../azureResource/providers/database/commands'; import { registerAzureResourceDatabaseCommands } from '../azureResource/providers/database/commands';
import { equals } from '../azureResource/utils';
export default class AzureResourceController extends ControllerBase { export default class AzureResourceController extends ControllerBase {
public activate(): Promise<boolean> { public activate(): Promise<boolean> {
@@ -37,7 +38,16 @@ export default class AzureResourceController extends ControllerBase {
const azureResourceTree = new AzureResourceTreeProvider(this.appContext); const azureResourceTree = new AzureResourceTreeProvider(this.appContext);
this.extensionContext.subscriptions.push(this.apiWrapper.registerTreeDataProvider('azureResourceExplorer', azureResourceTree)); this.extensionContext.subscriptions.push(this.apiWrapper.registerTreeDataProvider('azureResourceExplorer', azureResourceTree));
this.appContext.getService<IAzureResourceAccountService>(AzureResourceServiceNames.accountService).onDidChangeAccounts((e: DidChangeAccountsParams) => { azureResourceTree.notifyNodeChanged(undefined); }); let previousAccounts = undefined;
this.appContext.getService<IAzureResourceAccountService>(AzureResourceServiceNames.accountService).onDidChangeAccounts((e: DidChangeAccountsParams) => {
// the onDidChangeAccounts event will trigger in many cases where the accounts didn't actually change
// the notifyNodeChanged event triggers a refresh which triggers a getChildren which can trigger this callback
// this below check short-circuits the infinite callback loop
if (!equals(e.accounts, previousAccounts)) {
azureResourceTree.notifyNodeChanged(undefined);
}
previousAccounts = e.accounts;
});
registerAzureResourceCommands(this.appContext, azureResourceTree); registerAzureResourceCommands(this.appContext, azureResourceTree);

View File

@@ -14,7 +14,7 @@
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"experimentalDecorators": true, "experimentalDecorators": true,
"moduleResolution": "node", "moduleResolution": "node",
"declaration": true "declaration": false
}, },
"exclude": [ "exclude": [
"node_modules" "node_modules"

View File

@@ -67,7 +67,7 @@
} }
}, },
"dependencies": { "dependencies": {
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#0.2.10", "dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#0.2.15",
"opener": "^1.4.3", "opener": "^1.4.3",
"service-downloader": "github:anthonydresser/service-downloader#0.1.5", "service-downloader": "github:anthonydresser/service-downloader#0.1.5",
"vscode-extension-telemetry": "0.0.18", "vscode-extension-telemetry": "0.0.18",

View File

@@ -45,4 +45,6 @@ export interface DacFxDataModel extends BaseDataModel {
filePath: string; filePath: string;
version: string; version: string;
upgradeExisting: boolean; upgradeExisting: boolean;
scriptFilePath: string;
generateScriptAndDeploy: boolean;
} }

View File

@@ -8,6 +8,7 @@ import * as nls from 'vscode-nls';
import * as sqlops from 'sqlops'; import * as sqlops from 'sqlops';
import { SelectOperationPage } from './pages/selectOperationpage'; import { SelectOperationPage } from './pages/selectOperationpage';
import { DeployConfigPage } from './pages/deployConfigPage'; import { DeployConfigPage } from './pages/deployConfigPage';
import { DeployActionPage } from './pages/deployActionPage';
import { DacFxSummaryPage } from './pages/dacFxSummaryPage'; import { DacFxSummaryPage } from './pages/dacFxSummaryPage';
import { ExportConfigPage } from './pages/exportConfigPage'; import { ExportConfigPage } from './pages/exportConfigPage';
import { ExtractConfigPage } from './pages/extractConfigPage'; import { ExtractConfigPage } from './pages/extractConfigPage';
@@ -30,7 +31,33 @@ export enum Operation {
deploy, deploy,
extract, extract,
import, import,
export export,
generateDeployScript
}
export enum DeployOperationPath {
selectOperation,
deployOptions,
deployAction,
summary
}
export enum ExtractOperationPath {
selectOperation,
options,
summary
}
export enum ImportOperationPath {
selectOperation,
options,
summary
}
export enum ExportOperationPath {
selectOperation,
options,
summary
} }
export class DataTierApplicationWizard { export class DataTierApplicationWizard {
@@ -60,6 +87,7 @@ export class DataTierApplicationWizard {
this.wizard = sqlops.window.modelviewdialog.createWizard('Data-tier Application Wizard'); this.wizard = sqlops.window.modelviewdialog.createWizard('Data-tier Application Wizard');
let selectOperationWizardPage = sqlops.window.modelviewdialog.createWizardPage(localize('dacFx.selectOperationPageName', 'Select an Operation')); let selectOperationWizardPage = sqlops.window.modelviewdialog.createWizardPage(localize('dacFx.selectOperationPageName', 'Select an Operation'));
let deployConfigWizardPage = sqlops.window.modelviewdialog.createWizardPage(localize('dacFx.deployConfigPageName', 'Select Deploy Dacpac Settings')); let deployConfigWizardPage = sqlops.window.modelviewdialog.createWizardPage(localize('dacFx.deployConfigPageName', 'Select Deploy Dacpac Settings'));
let deployActionWizardPage = sqlops.window.modelviewdialog.createWizardPage(localize('dacFx.deployActionPageName', 'Select Action'));
let summaryWizardPage = sqlops.window.modelviewdialog.createWizardPage(localize('dacFx.summaryPageName', 'Summary')); let summaryWizardPage = sqlops.window.modelviewdialog.createWizardPage(localize('dacFx.summaryPageName', 'Summary'));
let extractConfigWizardPage = sqlops.window.modelviewdialog.createWizardPage(localize('dacFx.extractConfigPageName', 'Select Extract Dacpac Settings')); let extractConfigWizardPage = sqlops.window.modelviewdialog.createWizardPage(localize('dacFx.extractConfigPageName', 'Select Extract Dacpac Settings'));
let importConfigWizardPage = sqlops.window.modelviewdialog.createWizardPage(localize('dacFx.importConfigPageName', 'Select Import Bacpac Settings')); let importConfigWizardPage = sqlops.window.modelviewdialog.createWizardPage(localize('dacFx.importConfigPageName', 'Select Import Bacpac Settings'));
@@ -67,6 +95,7 @@ export class DataTierApplicationWizard {
this.pages.set('selectOperation', new Page(selectOperationWizardPage)); this.pages.set('selectOperation', new Page(selectOperationWizardPage));
this.pages.set('deployConfig', new Page(deployConfigWizardPage)); this.pages.set('deployConfig', new Page(deployConfigWizardPage));
this.pages.set('deployAction', new Page(deployActionWizardPage));
this.pages.set('extractConfig', new Page(extractConfigWizardPage)); this.pages.set('extractConfig', new Page(extractConfigWizardPage));
this.pages.set('importConfig', new Page(importConfigWizardPage)); this.pages.set('importConfig', new Page(importConfigWizardPage));
this.pages.set('exportConfig', new Page(exportConfigWizardPage)); this.pages.set('exportConfig', new Page(exportConfigWizardPage));
@@ -87,6 +116,12 @@ export class DataTierApplicationWizard {
await deployConfigDacFxPage.start(); await deployConfigDacFxPage.start();
}); });
deployActionWizardPage.registerContent(async (view) => {
let deployActionDacFxPage = new DeployActionPage(this, deployActionWizardPage, this.model, view);
this.pages.get('deployAction').dacFxPage = deployActionDacFxPage;
await deployActionDacFxPage.start();
});
extractConfigWizardPage.registerContent(async (view) => { extractConfigWizardPage.registerContent(async (view) => {
let extractConfigDacFxPage = new ExtractConfigPage(this, extractConfigWizardPage, this.model, view); let extractConfigDacFxPage = new ExtractConfigPage(this, extractConfigWizardPage, this.model, view);
this.pages.get('extractConfig').dacFxPage = extractConfigDacFxPage; this.pages.get('extractConfig').dacFxPage = extractConfigDacFxPage;
@@ -113,39 +148,27 @@ export class DataTierApplicationWizard {
this.wizard.onPageChanged(async (event) => { this.wizard.onPageChanged(async (event) => {
let idx = event.newPage; let idx = event.newPage;
let page: Page; let page = this.getPage(idx);
if (idx === 1) {
switch (this.selectedOperation) {
case Operation.deploy: {
page = this.pages.get('deployConfig');
break;
}
case Operation.extract: {
page = this.pages.get('extractConfig');
break;
}
case Operation.import: {
page = this.pages.get('importConfig');
break;
}
case Operation.export: {
page = this.pages.get('exportConfig');
break;
}
}
} else if (idx === 2) {
page = this.pages.get('summary');
}
if (page !== undefined) { if (page !== undefined) {
page.dacFxPage.setupNavigationValidator(); page.dacFxPage.setupNavigationValidator();
page.dacFxPage.onPageEnter(); page.dacFxPage.onPageEnter();
} }
//do onPageLeave for summary page so that GenerateScript button only shows up if upgrading database
let idxLast = event.lastPage;
if (this.isSummaryPage(idxLast)) {
let lastPage = this.pages.get('summary');
if (lastPage) {
lastPage.dacFxPage.onPageLeave();
}
}
}); });
this.wizard.pages = [selectOperationWizardPage, deployConfigWizardPage, summaryWizardPage]; this.wizard.pages = [selectOperationWizardPage, deployConfigWizardPage, deployActionWizardPage, summaryWizardPage];
this.wizard.generateScriptButton.hidden = true; this.wizard.generateScriptButton.hidden = true;
this.wizard.generateScriptButton.onClick(async () => await this.generateDeployScript());
this.wizard.doneButton.onClick(async () => await this.executeOperation()); this.wizard.doneButton.onClick(async () => await this.executeOperation());
this.wizard.open(); this.wizard.open();
@@ -177,6 +200,15 @@ export class DataTierApplicationWizard {
this.selectedOperation = Operation.export; this.selectedOperation = Operation.export;
break; break;
} }
case Operation.generateDeployScript: {
this.wizard.doneButton.label = localize('dacFx.generateScriptButton', 'Generate Script');
this.selectedOperation = Operation.generateDeployScript;
break;
}
}
if (operation !== Operation.deploy && operation !== Operation.generateDeployScript) {
this.model.upgradeExisting = false;
} }
} }
@@ -198,6 +230,10 @@ export class DataTierApplicationWizard {
await this.export(); await this.export();
break; break;
} }
case Operation.generateDeployScript: {
await this.generateDeployScript();
break;
}
} }
} }
@@ -245,6 +281,64 @@ export class DataTierApplicationWizard {
} }
} }
private async generateDeployScript() {
if (!this.model.scriptFilePath) {
return;
}
let service = await DataTierApplicationWizard.getService(this.model.server.providerName);
let ownerUri = await sqlops.connection.getUriForConnection(this.model.server.connectionId);
this.wizard.message = {
text: localize('dacfx.scriptGeneratingMessage', 'You can view the status of script generation in the Task History once the wizard is closed'),
level: sqlops.window.modelviewdialog.MessageLevel.Information,
description: ''
};
let result = await service.generateDeployScript(this.model.filePath, this.model.database, this.model.scriptFilePath, ownerUri, sqlops.TaskExecutionMode.execute);
if (!result || !result.success) {
vscode.window.showErrorMessage(
localize('alertData.deployErrorMessage', "Deploy failed '{0}'", result.errorMessage ? result.errorMessage : 'Unknown'));
}
}
private getPage(idx: number): Page {
let page: Page;
if (idx === 1) {
switch (this.selectedOperation) {
case Operation.deploy: {
page = this.pages.get('deployConfig');
break;
}
case Operation.extract: {
page = this.pages.get('extractConfig');
break;
}
case Operation.import: {
page = this.pages.get('importConfig');
break;
}
case Operation.export: {
page = this.pages.get('exportConfig');
break;
}
}
} else if ((this.selectedOperation === Operation.deploy || this.selectedOperation === Operation.generateDeployScript) && idx === DeployOperationPath.deployAction) {
page = this.pages.get('deployAction');
} else if (this.isSummaryPage(idx)) {
page = this.pages.get('summary');
}
return page;
}
private isSummaryPage(idx: number): boolean {
return this.selectedOperation === Operation.import && idx === ImportOperationPath.summary
|| this.selectedOperation === Operation.export && idx === ExportOperationPath.summary
|| this.selectedOperation === Operation.extract && idx === ExtractOperationPath.summary
|| (this.selectedOperation === Operation.deploy || this.selectedOperation === Operation.generateDeployScript) && idx === DeployOperationPath.summary;
}
private static async getService(providerName: string): Promise<sqlops.DacFxServicesProvider> { private static async getService(providerName: string): Promise<sqlops.DacFxServicesProvider> {
let service = sqlops.dataprotocol.getProvider<sqlops.DacFxServicesProvider>(providerName, sqlops.DataProviderType.DacFxServicesProvider); let service = sqlops.dataprotocol.getProvider<sqlops.DacFxServicesProvider>(providerName, sqlops.DataProviderType.DacFxServicesProvider);
return service; return service;

View File

@@ -49,6 +49,14 @@ export class DacFxSummaryPage extends BasePage {
async onPageEnter(): Promise<boolean> { async onPageEnter(): Promise<boolean> {
this.populateTable(); this.populateTable();
this.loader.loading = false; this.loader.loading = false;
if (this.model.upgradeExisting && this.model.generateScriptAndDeploy) {
this.instance.wizard.generateScriptButton.hidden = false;
}
return true;
}
async onPageLeave(): Promise<boolean> {
this.instance.wizard.generateScriptButton.hidden = true;
return true; return true;
} }
@@ -68,6 +76,10 @@ export class DacFxSummaryPage extends BasePage {
let sourceServer = localize('dacfx.sourceServerName', 'Source Server'); let sourceServer = localize('dacfx.sourceServerName', 'Source Server');
let sourceDatabase = localize('dacfx.sourceDatabaseName', 'Source Database'); let sourceDatabase = localize('dacfx.sourceDatabaseName', 'Source Database');
let fileLocation = localize('dacfx.fileLocation', 'File Location'); let fileLocation = localize('dacfx.fileLocation', 'File Location');
let scriptLocation = localize('dacfx.scriptLocation', 'Deployment Script Location');
let action = localize('dacfx.action', 'Action');
let deploy = localize('dacfx.deploy', 'Deploy');
let generateScript = localize('dacfx.generateScript', 'Generate Deployment Script');
switch (this.instance.selectedOperation) { switch (this.instance.selectedOperation) {
case Operation.deploy: { case Operation.deploy: {
@@ -75,6 +87,13 @@ export class DacFxSummaryPage extends BasePage {
[targetServer, this.model.serverName], [targetServer, this.model.serverName],
[fileLocation, this.model.filePath], [fileLocation, this.model.filePath],
[targetDatabase, this.model.database]]; [targetDatabase, this.model.database]];
if (this.model.generateScriptAndDeploy) {
data[3] = [scriptLocation, this.model.scriptFilePath];
data[4] = [action, generateScript + ', ' + deploy];
}
else {
data[3] = [action, deploy];
}
break; break;
} }
case Operation.extract: { case Operation.extract: {
@@ -99,12 +118,21 @@ export class DacFxSummaryPage extends BasePage {
[fileLocation, this.model.filePath]]; [fileLocation, this.model.filePath]];
break; break;
} }
case Operation.generateDeployScript: {
data = [
[targetServer, this.model.serverName],
[fileLocation, this.model.filePath],
[targetDatabase, this.model.database],
[scriptLocation, this.model.scriptFilePath],
[action, generateScript]];
break;
}
} }
this.table.updateProperties({ this.table.updateProperties({
data: data, data: data,
columns: ['Setting', 'Value'], columns: ['Setting', 'Value'],
width: 600, width: 700,
height: 200 height: 200
}); });
} }

View File

@@ -0,0 +1,176 @@
/*---------------------------------------------------------------------------------------------
* 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 sqlops from 'sqlops';
import * as nls from 'vscode-nls';
import * as vscode from 'vscode';
import * as path from 'path';
import * as os from 'os';
import { DacFxDataModel } from '../api/models';
import { DataTierApplicationWizard, Operation } from '../dataTierApplicationWizard';
import { DacFxConfigPage } from '../api/dacFxConfigPage';
const localize = nls.loadMessageBundle();
export class DeployActionPage extends DacFxConfigPage {
protected readonly wizardPage: sqlops.window.modelviewdialog.WizardPage;
protected readonly instance: DataTierApplicationWizard;
protected readonly model: DacFxDataModel;
protected readonly view: sqlops.ModelView;
private deployRadioButton: sqlops.RadioButtonComponent;
private deployScriptRadioButton: sqlops.RadioButtonComponent;
private scriptRadioButton: sqlops.RadioButtonComponent;
private form: sqlops.FormContainer;
public constructor(instance: DataTierApplicationWizard, wizardPage: sqlops.window.modelviewdialog.WizardPage, model: DacFxDataModel, view: sqlops.ModelView) {
super(instance, wizardPage, model, view);
}
async start(): Promise<boolean> {
let deployComponent = await this.createDeployRadioButton();
let deployScriptComponent = await this.createDeployScriptRadioButton();
let scriptComponent = await this.createScriptRadioButton();
let fileBrowserComponent = await this.createFileBrowser();
this.form = this.view.modelBuilder.formContainer()
.withFormItems(
[
deployComponent,
scriptComponent,
deployScriptComponent,
fileBrowserComponent
]).component();
await this.view.initializeModel(this.form);
//default have the first radio button checked
this.deployRadioButton.checked = true;
this.toggleFileBrowser(false);
return true;
}
async onPageEnter(): Promise<boolean> {
return true;
}
private async createDeployRadioButton(): Promise<sqlops.FormComponent> {
this.deployRadioButton = this.view.modelBuilder.radioButton()
.withProperties({
name: 'selectedDeployAction',
label: localize('dacFx.deployRadioButtonLabel', 'Deploy'),
}).component();
this.deployRadioButton.onDidClick(() => {
this.model.generateScriptAndDeploy = false;
this.instance.setDoneButton(Operation.deploy);
this.toggleFileBrowser(false);
});
return {
component: this.deployRadioButton,
title: ''
};
}
private async createDeployScriptRadioButton(): Promise<sqlops.FormComponent> {
this.deployScriptRadioButton = this.view.modelBuilder.radioButton()
.withProperties({
name: 'selectedDeployAction',
label: localize('dacFx.deployScriptRadioButtonLabel', 'Generate Deployment Script and Deploy'),
}).component();
this.deployScriptRadioButton.onDidClick(() => {
this.model.generateScriptAndDeploy = true;
this.instance.setDoneButton(Operation.deploy);
this.toggleFileBrowser(true);
});
return {
component: this.deployScriptRadioButton,
title: ''
};
}
private async createScriptRadioButton(): Promise<sqlops.FormComponent> {
this.scriptRadioButton = this.view.modelBuilder.radioButton()
.withProperties({
name: 'selectedDeployAction',
label: localize('dacFx.scriptRadioButtonLabel', 'Generate Deployment Script'),
}).component();
this.scriptRadioButton.onDidClick(() => {
this.model.generateScriptAndDeploy = false;
this.toggleFileBrowser(true);
//change button text and operation
this.instance.setDoneButton(Operation.generateDeployScript);
});
return {
component: this.scriptRadioButton,
title: ''
};
}
private async createFileBrowser(): Promise<sqlops.FormComponentGroup> {
this.createFileBrowserParts();
//default filepath
let now = new Date();
let datetime = now.getFullYear() + '-' + (now.getMonth() + 1) + '-' + now.getDate() + '-' + now.getHours() + '-' + now.getMinutes();
this.fileTextBox.value= path.join(os.homedir(), this.model.database + '_UpgradeDACScript_' + datetime + '.sql');
this.model.scriptFilePath = this.fileTextBox.value;
this.fileButton.onDidClick(async (click) => {
let fileUri = await vscode.window.showSaveDialog(
{
defaultUri: vscode.Uri.file(this.fileTextBox.value),
saveLabel: localize('dacfxDeployScript.saveFile', 'Save'),
filters: {
'SQL Files': ['sql'],
}
}
);
if (!fileUri) {
return;
}
this.fileTextBox.value = fileUri.fsPath;
this.model.scriptFilePath = fileUri.fsPath;
});
this.fileTextBox.onTextChanged(async () => {
this.model.scriptFilePath = this.fileTextBox.value;
});
return {
title: '',
components: [
{
title: localize('dacfx.generatedScriptLocation','Deployment Script Location'),
component: this.fileTextBox,
layout: {
horizontal: true,
componentWidth: 400
},
actions: [this.fileButton]
},],
};
}
private toggleFileBrowser(enable: boolean): void {
this.fileTextBox.enabled = enable;
this.fileButton.enabled = enable;
}
public setupNavigationValidator() {
this.instance.registerNavigationValidator(() => {
return true;
});
}
}

View File

@@ -58,11 +58,6 @@ export class SelectOperationPage extends BasePage {
} }
async onPageEnter(): Promise<boolean> { async onPageEnter(): Promise<boolean> {
let numPages = this.instance.wizard.pages.length;
for (let i = numPages - 1; i > 2; --i) {
await this.instance.wizard.removePage(i);
}
return true; return true;
} }
@@ -74,12 +69,14 @@ export class SelectOperationPage extends BasePage {
}).component(); }).component();
this.deployRadioButton.onDidClick(() => { this.deployRadioButton.onDidClick(() => {
// remove the previous page this.removePages();
this.instance.wizard.removePage(1);
// add deploy page //add deploy pages
let page = this.instance.pages.get('deployConfig'); let configPage = this.instance.pages.get('deployConfig');
this.instance.wizard.addPage(page.wizardPage, 1); this.instance.wizard.addPage(configPage.wizardPage, 1);
let actionPage = this.instance.pages.get('deployAction');
this.instance.wizard.addPage(actionPage.wizardPage, 2);
this.addSummaryPage(3);
// change button text and operation // change button text and operation
this.instance.setDoneButton(Operation.deploy); this.instance.setDoneButton(Operation.deploy);
@@ -99,12 +96,12 @@ export class SelectOperationPage extends BasePage {
}).component(); }).component();
this.extractRadioButton.onDidClick(() => { this.extractRadioButton.onDidClick(() => {
// remove the previous pages this.removePages();
this.instance.wizard.removePage(1);
// add the extract page // add the extract page
let page = this.instance.pages.get('extractConfig'); let page = this.instance.pages.get('extractConfig');
this.instance.wizard.addPage(page.wizardPage, 1); this.instance.wizard.addPage(page.wizardPage, 1);
this.addSummaryPage(2);
// change button text and operation // change button text and operation
this.instance.setDoneButton(Operation.extract); this.instance.setDoneButton(Operation.extract);
@@ -124,12 +121,12 @@ export class SelectOperationPage extends BasePage {
}).component(); }).component();
this.importRadioButton.onDidClick(() => { this.importRadioButton.onDidClick(() => {
// remove the previous page this.removePages();
this.instance.wizard.removePage(1);
// add the import page // add the import page
let page = this.instance.pages.get('importConfig'); let page = this.instance.pages.get('importConfig');
this.instance.wizard.addPage(page.wizardPage, 1); this.instance.wizard.addPage(page.wizardPage, 1);
this.addSummaryPage(2);
// change button text and operation // change button text and operation
this.instance.setDoneButton(Operation.import); this.instance.setDoneButton(Operation.import);
@@ -149,12 +146,12 @@ export class SelectOperationPage extends BasePage {
}).component(); }).component();
this.exportRadioButton.onDidClick(() => { this.exportRadioButton.onDidClick(() => {
// remove the 2 previous pages this.removePages();
this.instance.wizard.removePage(1);
// add the export pages // add the export pages
let page = this.instance.pages.get('exportConfig'); let page = this.instance.pages.get('exportConfig');
this.instance.wizard.addPage(page.wizardPage, 1); this.instance.wizard.addPage(page.wizardPage, 1);
this.addSummaryPage(2);
// change button text and operation // change button text and operation
this.instance.setDoneButton(Operation.export); this.instance.setDoneButton(Operation.export);
@@ -166,6 +163,18 @@ export class SelectOperationPage extends BasePage {
}; };
} }
private removePages() {
let numPages = this.instance.wizard.pages.length;
for (let i = numPages - 1; i > 0; --i) {
this.instance.wizard.removePage(i);
}
}
private addSummaryPage(index: number) {
let summaryPage = this.instance.pages.get('summary');
this.instance.wizard.addPage(summaryPage.wizardPage, index);
}
public setupNavigationValidator() { public setupNavigationValidator() {
this.instance.registerNavigationValidator(() => { this.instance.registerNavigationValidator(() => {
return true; return true;

View File

@@ -11,7 +11,7 @@
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"experimentalDecorators": true, "experimentalDecorators": true,
"moduleResolution": "node", "moduleResolution": "node",
"declaration": true "declaration": false
}, },
"exclude": [ "exclude": [
"node_modules" "node_modules"

View File

@@ -5,14 +5,12 @@
agent-base@4, agent-base@^4.1.0: agent-base@4, agent-base@^4.1.0:
version "4.2.1" version "4.2.1"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9"
integrity sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==
dependencies: dependencies:
es6-promisify "^5.0.0" es6-promisify "^5.0.0"
applicationinsights@1.0.1: applicationinsights@1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.1.tgz#53446b830fe8d5d619eee2a278b31d3d25030927" resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.1.tgz#53446b830fe8d5d619eee2a278b31d3d25030927"
integrity sha1-U0Rrgw/o1dYZ7uKieLMdPSUDCSc=
dependencies: dependencies:
diagnostic-channel "0.2.0" diagnostic-channel "0.2.0"
diagnostic-channel-publishers "0.2.1" diagnostic-channel-publishers "0.2.1"
@@ -21,12 +19,10 @@ applicationinsights@1.0.1:
base64-js@0.0.8: base64-js@0.0.8:
version "0.0.8" version "0.0.8"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.8.tgz#1101e9544f4a76b1bc3b26d452ca96d7a35e7978" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.8.tgz#1101e9544f4a76b1bc3b26d452ca96d7a35e7978"
integrity sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=
bl@^1.0.0: bl@^1.0.0:
version "1.2.2" version "1.2.2"
resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c"
integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==
dependencies: dependencies:
readable-stream "^2.3.5" readable-stream "^2.3.5"
safe-buffer "^5.1.1" safe-buffer "^5.1.1"
@@ -34,12 +30,10 @@ bl@^1.0.0:
buffer-alloc-unsafe@^1.1.0: buffer-alloc-unsafe@^1.1.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==
buffer-alloc@^1.2.0: buffer-alloc@^1.2.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec"
integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==
dependencies: dependencies:
buffer-alloc-unsafe "^1.1.0" buffer-alloc-unsafe "^1.1.0"
buffer-fill "^1.0.0" buffer-fill "^1.0.0"
@@ -47,17 +41,14 @@ buffer-alloc@^1.2.0:
buffer-crc32@~0.2.3: buffer-crc32@~0.2.3:
version "0.2.13" version "0.2.13"
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
buffer-fill@^1.0.0: buffer-fill@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c"
integrity sha1-+PeLdniYiO858gXNY39o5wISKyw=
buffer@^3.0.1: buffer@^3.0.1:
version "3.6.0" version "3.6.0"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-3.6.0.tgz#a72c936f77b96bf52f5f7e7b467180628551defb" resolved "https://registry.yarnpkg.com/buffer/-/buffer-3.6.0.tgz#a72c936f77b96bf52f5f7e7b467180628551defb"
integrity sha1-pyyTb3e5a/UvX357RnGAYoVR3vs=
dependencies: dependencies:
base64-js "0.0.8" base64-js "0.0.8"
ieee754 "^1.1.4" ieee754 "^1.1.4"
@@ -66,39 +57,34 @@ buffer@^3.0.1:
commander@~2.8.1: commander@~2.8.1:
version "2.8.1" version "2.8.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4"
integrity sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=
dependencies: dependencies:
graceful-readlink ">= 1.0.0" graceful-readlink ">= 1.0.0"
core-util-is@~1.0.0: core-util-is@~1.0.0:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#0.2.10": "dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#0.2.15":
version "0.2.10" version "0.2.15"
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/4de3f7caf0eba54159911b977ddb4f5d7c0a9ca8" resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/a2cd2db109de882f0959f7b6421c86afa585f460"
dependencies: dependencies:
vscode-languageclient "3.5.1" vscode-languageclient "3.5.1"
debug@3.1.0: debug@3.1.0:
version "3.1.0" version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
dependencies: dependencies:
ms "2.0.0" ms "2.0.0"
debug@^3.1.0: debug@^3.1.0:
version "3.2.6" version "3.2.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
dependencies: dependencies:
ms "^2.1.1" ms "^2.1.1"
decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1:
version "4.1.1" version "4.1.1"
resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1"
integrity sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==
dependencies: dependencies:
file-type "^5.2.0" file-type "^5.2.0"
is-stream "^1.1.0" is-stream "^1.1.0"
@@ -107,7 +93,6 @@ decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1:
decompress-tarbz2@^4.0.0: decompress-tarbz2@^4.0.0:
version "4.1.1" version "4.1.1"
resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b"
integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==
dependencies: dependencies:
decompress-tar "^4.1.0" decompress-tar "^4.1.0"
file-type "^6.1.0" file-type "^6.1.0"
@@ -118,7 +103,6 @@ decompress-tarbz2@^4.0.0:
decompress-targz@^4.0.0: decompress-targz@^4.0.0:
version "4.1.1" version "4.1.1"
resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee"
integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==
dependencies: dependencies:
decompress-tar "^4.1.1" decompress-tar "^4.1.1"
file-type "^5.2.0" file-type "^5.2.0"
@@ -127,7 +111,6 @@ decompress-targz@^4.0.0:
decompress-unzip@^4.0.1: decompress-unzip@^4.0.1:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69"
integrity sha1-3qrM39FK6vhVePczroIQ+bSEj2k=
dependencies: dependencies:
file-type "^3.8.0" file-type "^3.8.0"
get-stream "^2.2.0" get-stream "^2.2.0"
@@ -137,7 +120,6 @@ decompress-unzip@^4.0.1:
decompress@^4.2.0: decompress@^4.2.0:
version "4.2.0" version "4.2.0"
resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d" resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d"
integrity sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=
dependencies: dependencies:
decompress-tar "^4.0.0" decompress-tar "^4.0.0"
decompress-tarbz2 "^4.0.0" decompress-tarbz2 "^4.0.0"
@@ -151,70 +133,58 @@ decompress@^4.2.0:
diagnostic-channel-publishers@0.2.1: diagnostic-channel-publishers@0.2.1:
version "0.2.1" version "0.2.1"
resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3" resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3"
integrity sha1-ji1geottef6IC1SLxYzGvrKIxPM=
diagnostic-channel@0.2.0: diagnostic-channel@0.2.0:
version "0.2.0" version "0.2.0"
resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-0.2.0.tgz#cc99af9612c23fb1fff13612c72f2cbfaa8d5a17" resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-0.2.0.tgz#cc99af9612c23fb1fff13612c72f2cbfaa8d5a17"
integrity sha1-zJmvlhLCP7H/8TYSxy8sv6qNWhc=
dependencies: dependencies:
semver "^5.3.0" semver "^5.3.0"
end-of-stream@^1.0.0: end-of-stream@^1.0.0:
version "1.4.1" version "1.4.1"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43"
integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==
dependencies: dependencies:
once "^1.4.0" once "^1.4.0"
es6-promise@^4.0.3: es6-promise@^4.0.3:
version "4.2.5" version "4.2.5"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.5.tgz#da6d0d5692efb461e082c14817fe2427d8f5d054" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.5.tgz#da6d0d5692efb461e082c14817fe2427d8f5d054"
integrity sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==
es6-promisify@^5.0.0: es6-promisify@^5.0.0:
version "5.0.0" version "5.0.0"
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=
dependencies: dependencies:
es6-promise "^4.0.3" es6-promise "^4.0.3"
eventemitter2@^5.0.1: eventemitter2@^5.0.1:
version "5.0.1" version "5.0.1"
resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-5.0.1.tgz#6197a095d5fb6b57e8942f6fd7eaad63a09c9452" resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-5.0.1.tgz#6197a095d5fb6b57e8942f6fd7eaad63a09c9452"
integrity sha1-YZegldX7a1folC9v1+qtY6CclFI=
fd-slicer@~1.1.0: fd-slicer@~1.1.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=
dependencies: dependencies:
pend "~1.2.0" pend "~1.2.0"
file-type@^3.8.0: file-type@^3.8.0:
version "3.9.0" version "3.9.0"
resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9"
integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek=
file-type@^5.2.0: file-type@^5.2.0:
version "5.2.0" version "5.2.0"
resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6"
integrity sha1-LdvqfHP/42No365J3DOMBYwritY=
file-type@^6.1.0: file-type@^6.1.0:
version "6.2.0" version "6.2.0"
resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919"
integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==
fs-constants@^1.0.0: fs-constants@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
get-stream@^2.2.0: get-stream@^2.2.0:
version "2.3.1" version "2.3.1"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de"
integrity sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=
dependencies: dependencies:
object-assign "^4.0.1" object-assign "^4.0.1"
pinkie-promise "^2.0.0" pinkie-promise "^2.0.0"
@@ -222,17 +192,14 @@ get-stream@^2.2.0:
graceful-fs@^4.1.10: graceful-fs@^4.1.10:
version "4.1.15" version "4.1.15"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==
"graceful-readlink@>= 1.0.0": "graceful-readlink@>= 1.0.0":
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=
http-proxy-agent@^2.1.0: http-proxy-agent@^2.1.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405"
integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==
dependencies: dependencies:
agent-base "4" agent-base "4"
debug "3.1.0" debug "3.1.0"
@@ -240,7 +207,6 @@ http-proxy-agent@^2.1.0:
https-proxy-agent@^2.2.1: https-proxy-agent@^2.2.1:
version "2.2.1" version "2.2.1"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0"
integrity sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==
dependencies: dependencies:
agent-base "^4.1.0" agent-base "^4.1.0"
debug "^3.1.0" debug "^3.1.0"
@@ -248,115 +214,94 @@ https-proxy-agent@^2.2.1:
ieee754@^1.1.4: ieee754@^1.1.4:
version "1.1.12" version "1.1.12"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b"
integrity sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==
inherits@~2.0.3: inherits@~2.0.3:
version "2.0.3" version "2.0.3"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
is-natural-number@^4.0.1: is-natural-number@^4.0.1:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8"
integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=
is-stream@^1.1.0: is-stream@^1.1.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
isarray@^1.0.0, isarray@~1.0.0: isarray@^1.0.0, isarray@~1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
make-dir@^1.0.0: make-dir@^1.0.0:
version "1.3.0" version "1.3.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==
dependencies: dependencies:
pify "^3.0.0" pify "^3.0.0"
minimist@0.0.8: minimist@0.0.8:
version "0.0.8" version "0.0.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
mkdirp@^0.5.1: mkdirp@^0.5.1:
version "0.5.1" version "0.5.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
dependencies: dependencies:
minimist "0.0.8" minimist "0.0.8"
ms@2.0.0: ms@2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
ms@^2.1.1: ms@^2.1.1:
version "2.1.1" version "2.1.1"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
object-assign@^4.0.1: object-assign@^4.0.1:
version "4.1.1" version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
once@^1.4.0: once@^1.4.0:
version "1.4.0" version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
dependencies: dependencies:
wrappy "1" wrappy "1"
opener@^1.4.3: opener@^1.4.3:
version "1.5.1" version "1.5.1"
resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed" resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed"
integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==
os-tmpdir@~1.0.2: os-tmpdir@~1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
pend@~1.2.0: pend@~1.2.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA=
pify@^2.3.0: pify@^2.3.0:
version "2.3.0" version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
pify@^3.0.0: pify@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=
pinkie-promise@^2.0.0: pinkie-promise@^2.0.0:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o=
dependencies: dependencies:
pinkie "^2.0.0" pinkie "^2.0.0"
pinkie@^2.0.0: pinkie@^2.0.0:
version "2.0.4" version "2.0.4"
resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
process-nextick-args@~2.0.0: process-nextick-args@~2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa"
integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==
readable-stream@^2.3.0, readable-stream@^2.3.5: readable-stream@^2.3.0, readable-stream@^2.3.5:
version "2.3.6" version "2.3.6"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==
dependencies: dependencies:
core-util-is "~1.0.0" core-util-is "~1.0.0"
inherits "~2.0.3" inherits "~2.0.3"
@@ -369,19 +314,16 @@ readable-stream@^2.3.0, readable-stream@^2.3.5:
safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2" version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
seek-bzip@^1.0.5: seek-bzip@^1.0.5:
version "1.0.5" version "1.0.5"
resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc"
integrity sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=
dependencies: dependencies:
commander "~2.8.1" commander "~2.8.1"
semver@^5.3.0: semver@^5.3.0:
version "5.6.0" version "5.6.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
"service-downloader@github:anthonydresser/service-downloader#0.1.5": "service-downloader@github:anthonydresser/service-downloader#0.1.5":
version "0.1.5" version "0.1.5"
@@ -397,21 +339,18 @@ semver@^5.3.0:
string_decoder@~1.1.1: string_decoder@~1.1.1:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
dependencies: dependencies:
safe-buffer "~5.1.0" safe-buffer "~5.1.0"
strip-dirs@^2.0.0: strip-dirs@^2.0.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5"
integrity sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==
dependencies: dependencies:
is-natural-number "^4.0.1" is-natural-number "^4.0.1"
tar-stream@^1.5.2: tar-stream@^1.5.2:
version "1.6.2" version "1.6.2"
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555"
integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==
dependencies: dependencies:
bl "^1.0.0" bl "^1.0.0"
buffer-alloc "^1.2.0" buffer-alloc "^1.2.0"
@@ -424,24 +363,20 @@ tar-stream@^1.5.2:
through@^2.3.6: through@^2.3.6:
version "2.3.8" version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
tmp@^0.0.33: tmp@^0.0.33:
version "0.0.33" version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
dependencies: dependencies:
os-tmpdir "~1.0.2" os-tmpdir "~1.0.2"
to-buffer@^1.1.1: to-buffer@^1.1.1:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80"
integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==
unbzip2-stream@^1.0.9: unbzip2-stream@^1.0.9:
version "1.3.1" version "1.3.1"
resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.1.tgz#7854da51622a7e63624221196357803b552966a1" resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.1.tgz#7854da51622a7e63624221196357803b552966a1"
integrity sha512-fIZnvdjblYs7Cru/xC6tCPVhz7JkYcVQQkePwMLyQELzYTds2Xn8QefPVnvdVhhZqubxNA1cASXEH5wcK0Bucw==
dependencies: dependencies:
buffer "^3.0.1" buffer "^3.0.1"
through "^2.3.6" through "^2.3.6"
@@ -449,31 +384,26 @@ unbzip2-stream@^1.0.9:
util-deprecate@~1.0.1: util-deprecate@~1.0.1:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
vscode-extension-telemetry@0.0.18: vscode-extension-telemetry@0.0.18:
version "0.0.18" version "0.0.18"
resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.18.tgz#602ba20d8c71453aa34533a291e7638f6e5c0327" resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.18.tgz#602ba20d8c71453aa34533a291e7638f6e5c0327"
integrity sha512-Vw3Sr+dZwl+c6PlsUwrTtCOJkgrmvS3OUVDQGcmpXWAgq9xGq6as0K4pUx+aGqTjzLAESmWSrs6HlJm6J6Khcg==
dependencies: dependencies:
applicationinsights "1.0.1" applicationinsights "1.0.1"
vscode-jsonrpc@3.5.0: vscode-jsonrpc@3.5.0:
version "3.5.0" version "3.5.0"
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-3.5.0.tgz#87239d9e166b2d7352245b8a813597804c1d63aa" resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-3.5.0.tgz#87239d9e166b2d7352245b8a813597804c1d63aa"
integrity sha1-hyOdnhZrLXNSJFuKgTWXgEwdY6o=
vscode-languageclient@3.5.1: vscode-languageclient@3.5.1:
version "3.5.1" version "3.5.1"
resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-3.5.1.tgz#c78e582459c24e58f88020dfa34065e976186a98" resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-3.5.1.tgz#c78e582459c24e58f88020dfa34065e976186a98"
integrity sha512-GTQ+hSq/o4c/y6GYmyP9XNrVoIu0NFZ67KltSkqN+tO0eUNDIlrVNX+3DJzzyLhSsrctuGzuYWm3t87mNAcBmQ==
dependencies: dependencies:
vscode-languageserver-protocol "3.5.1" vscode-languageserver-protocol "3.5.1"
vscode-languageserver-protocol@3.5.1: vscode-languageserver-protocol@3.5.1:
version "3.5.1" version "3.5.1"
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.5.1.tgz#5144a3a9eeccbd83fe2745bd4ed75fad6cc45f0d" resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.5.1.tgz#5144a3a9eeccbd83fe2745bd4ed75fad6cc45f0d"
integrity sha512-1fPDIwsAv1difCV+8daOrJEGunClNJWqnUHq/ncWrjhitKWXgGmRCjlwZ3gDUTt54yRcvXz1PXJDaRNvNH6pYA==
dependencies: dependencies:
vscode-jsonrpc "3.5.0" vscode-jsonrpc "3.5.0"
vscode-languageserver-types "3.5.0" vscode-languageserver-types "3.5.0"
@@ -481,27 +411,22 @@ vscode-languageserver-protocol@3.5.1:
vscode-languageserver-types@3.5.0: vscode-languageserver-types@3.5.0:
version "3.5.0" version "3.5.0"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.5.0.tgz#e48d79962f0b8e02de955e3f524908e2b19c0374" resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.5.0.tgz#e48d79962f0b8e02de955e3f524908e2b19c0374"
integrity sha1-5I15li8LjgLelV4/UkkI4rGcA3Q=
vscode-nls@^3.2.1: vscode-nls@^3.2.1:
version "3.2.5" version "3.2.5"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.5.tgz#25520c1955108036dec607c85e00a522f247f1a4" resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.5.tgz#25520c1955108036dec607c85e00a522f247f1a4"
integrity sha512-ITtoh3V4AkWXMmp3TB97vsMaHRgHhsSFPsUdzlueSL+dRZbSNTZeOmdQv60kjCV306ghPxhDeoNUEm3+EZMuyw==
wrappy@1: wrappy@1:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
xtend@^4.0.0: xtend@^4.0.0:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68=
yauzl@^2.4.2: yauzl@^2.4.2:
version "2.10.0" version "2.10.0"
resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=
dependencies: dependencies:
buffer-crc32 "~0.2.3" buffer-crc32 "~0.2.3"
fd-slicer "~1.1.0" fd-slicer "~1.1.0"
@@ -509,4 +434,3 @@ yauzl@^2.4.2:
zone.js@0.7.6: zone.js@0.7.6:
version "0.7.6" version "0.7.6"
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009" resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009"
integrity sha1-+7w50+AmHQmG8boGMG6zrrDSIAk=

View File

@@ -0,0 +1,17 @@
// A launch configuration that compiles the extension and then opens it inside a new window
{
"version": "0.1.0",
"configurations": [
{
"name": "Launch Tests",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": ["${workspaceFolder}/../../", "${workspaceFolder}/test", "--extensionDevelopmentPath=${workspaceFolder}", "--extensionTestsPath=${workspaceFolder}/out" ],
"stopOnEntry": false,
"sourceMaps": true,
"outDir": "${workspaceFolder}/out",
"preLaunchTask": "npm"
}
]
}

View File

@@ -0,0 +1,31 @@
// Available variables which can be used inside of strings.
// ${workspaceFolder}: the root folder of the team
// ${file}: the current opened file
// ${relativeFile}: the current opened file relative to cwd
// ${fileBasename}: the current opened file's basename
// ${fileDirname}: the current opened file's dirname
// ${fileExtname}: the current opened file's extension
// ${cwd}: the current working directory of the spawned process
// A task runner that calls a custom npm script that compiles the extension.
{
"version": "0.1.0",
// we want to run npm
"command": "npm",
// the command is a shell script
"isShellCommand": true,
// show the output window only if unrecognized errors occur.
"showOutput": "silent",
// we run the custom script "compile" as defined in package.json
"args": ["run", "compile", "--loglevel", "silent"],
// The tsc compiler is started in watching mode
"isWatching": true,
// use the standard tsc in watch mode problem matcher to find compile problems in the output.
"problemMatcher": "$tsc-watch"
}

View File

@@ -0,0 +1 @@
copy the extension installers to this folder

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,58 @@
{
"name": "integration-tests",
"description": "Integration Tests",
"version": "0.0.1",
"publisher": "Microsoft",
"private": true,
"engines": {
"vscode": "*",
"sqlops": "*"
},
"activationEvents": [
"*"
],
"main": "./out/main",
"extensionDependencies": [
"Microsoft.agent",
"Microsoft.import",
"Microsoft.profiler",
"Microsoft.mssql",
"Microsoft.notebook"
],
"contributes": {
"configuration": {
"type": "object",
"title": "ADS Integration Test Configuration",
"properties": {
"test.testSetupCompleted": {
"type": "boolean",
"default": false,
"description": ""
}
}
},
"commands": [{
"command": "test.setupIntegrationTest",
"title": "Setup Integration Test",
"category": "Test"
},
{
"command": "test.waitForExtensionsToLoad",
"title": "Wait For Extensions To Load",
"category": "Test"
}
]
},
"scripts": {
"vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:vscode-colorize-tests ./tsconfig.json",
"postinstall": "node ./node_modules/vscode/bin/install"
},
"devDependencies": {
"@types/node": "7.0.43",
"@types/chai": "3.4.34",
"mocha-junit-reporter": "^1.17.0",
"mocha-multi-reporters": "^1.1.7",
"vscode": "1.1.5",
"chai": "3.5.0"
}
}

View File

@@ -0,0 +1,32 @@
This integration-tests suite is based on the extension testing feature provided by VS Code, We can use this for:
a. Commands for setting up the environment for feature testing.
b. Adding test cases that do not need UI interaction or the test scenarios not supported by the UI automation framework (e.g. object explorer context menu not html based)
extensionInstallers folder: copy the VISX installers for the extensions we would like to run the tests with.
src folder: this is where the test file for features should be added, name the file like this: feature.test.ts. e.g. objectExplorer.test.ts
UI automation testing:
the ADS UI automation test cases should be added under $root/test/smoke/src/sql folder. Each feature should create its own folder and add 2 files, one for accessing the feature and the other for the test cases. For example: objectExplorer.ts and objectExplorer.test.ts.
Setup step:
1. Launch ADS
2. Install extensions from /extensions/integration-tests/extensionInstallers by calling the test command in the integration-tests extension
3. Set configuration values. E.g. Enable preview features by calling the test command in the integration-tests extension
For now this has only been tested for Windows platform
How to run the test:
1. In the build pipeline:
The integration tests and UI automation tests have been added to ADS windows pipeline to run the test and report the results, you can find the test result under the test tab.
2. Local environment:
Integration tests:
test-integration.bat or test-integration.sh under scripts folder
UI automation tests:
navigate to test/smoke folder and run: node test/index.js
You can also run UI automation from VSCode by selecting the launch option: Launch Smoke Test.
ADS will be launched using new temp folders: extension folder and data folder so that your local dev environment won't be changed.

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.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import { context } from './testContext';
const path = require('path');
const testRunner = require('vscode/lib/testrunner');
const suite = 'Integration Tests';
const options: any = {
ui: 'tdd',
useColors: true,
timeout: 600000
};
if (process.env.BUILD_ARTIFACTSTAGINGDIRECTORY) {
options.reporter = 'mocha-multi-reporters';
options.reporterOptions = {
reporterEnabled: 'spec, mocha-junit-reporter',
mochaJunitReporterReporterOptions: {
testsuitesTitle: `${suite} ${process.platform}`,
mochaFile: path.join(process.env.BUILD_ARTIFACTSTAGINGDIRECTORY, `test-results/${process.platform}-${suite.toLowerCase().replace(/[^\w]/g, '-')}-results.xml`)
}
};
}
if (!vscode.workspace.getConfiguration('test')['testSetupCompleted']) {
context.RunTest = false;
}
testRunner.configure(options);
export = testRunner;

View File

@@ -0,0 +1,77 @@
/*---------------------------------------------------------------------------------------------
* 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 sqlops from 'sqlops';
import { normalize, join } from 'path';
import * as fs from 'fs';
const TEST_SETUP_COMPLETED_TEXT: string = 'Test Setup Completed';
const EXTENSION_LOADED_TEXT: string = 'Test Extension Loaded';
const ALL_EXTENSION_LOADED_TEXT: string = 'All Extensions Loaded';
var statusBarItemTimer: NodeJS.Timer;
export function activate(context: vscode.ExtensionContext) {
var statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
vscode.commands.registerCommand('test.setupIntegrationTest', async () => {
let extensionInstallersFolder = normalize(join(__dirname, '../extensionInstallers'));
let installers = fs.readdirSync(extensionInstallersFolder);
for (let i = 0; i < installers.length; i++) {
if (installers[i].endsWith('.vsix')) {
let installerFullPath = join(extensionInstallersFolder, installers[i]);
await sqlops.extensions.install(installerFullPath);
}
}
await setConfiguration('workbench.enablePreviewFeatures', true);
await setConfiguration('workbench.showConnectDialogOnStartup', false);
await setConfiguration('test.testSetupCompleted', true);
showStatusBarItem(statusBarItem, TEST_SETUP_COMPLETED_TEXT);
});
vscode.commands.registerCommand('test.waitForExtensionsToLoad', async () => {
let expectedExtensions = ['Microsoft.agent', 'Microsoft.import', 'Microsoft.mssql', 'Microsoft.profiler'];
do {
let extensions = vscode.extensions.all.filter(ext => { return expectedExtensions.indexOf(ext.id) !== -1; });
let isReady = true;
for (let i = 0; i < extensions.length; i++) {
let extension = extensions[i];
isReady = isReady && extension.isActive;
if (!isReady) {
break;
}
}
if (isReady) {
showStatusBarItem(statusBarItem, ALL_EXTENSION_LOADED_TEXT);
break;
} else {
await new Promise(resolve => { setTimeout(resolve, 1000); });
}
}
while (true);
});
showStatusBarItem(statusBarItem, EXTENSION_LOADED_TEXT);
}
function showStatusBarItem(statusBarItem: vscode.StatusBarItem, text: string) {
statusBarItem.text = text;
statusBarItem.tooltip = text;
statusBarItem.show();
clearTimeout(statusBarItemTimer);
statusBarItemTimer = setTimeout(function () {
statusBarItem.hide();
}, 5000);
}
// this method is called when your extension is deactivated
export function deactivate(): void {
}
async function setConfiguration(name: string, value: any) {
await vscode.workspace.getConfiguration().update(name, value, true);
}

View File

@@ -0,0 +1,29 @@
/*---------------------------------------------------------------------------------------------
* 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 'mocha';
import * as sqlops from 'sqlops';
import { context } from './testContext';
import { getDefaultTestingServer } from './testConfig';
import { connectToServer } from './utils';
import assert = require('assert');
if (context.RunTest) {
suite('Object Explorer integration test suite', () => {
test('context menu test', async function () {
await connectToServer(await getDefaultTestingServer());
let nodes = <sqlops.objectexplorer.ObjectExplorerNode[]>await sqlops.objectexplorer.getActiveConnectionNodes();
assert(nodes.length === 1, `expecting 1 active connection, actual: ${nodes.length}`);
let actions = await sqlops.objectexplorer.getNodeActions(nodes[0].connectionId, nodes[0].nodePath);
const expectedActions = ['Manage', 'New Query', 'Disconnect', 'Delete Connection', 'Refresh', 'Launch Profiler'];
const expectedString = expectedActions.join(',');
const actualString = actions.join(',');
assert(expectedActions.length === actions.length && expectedString === actualString, `Expected actions: "${expectedString}", Actual actions: "${actualString}"`);
});
});
}

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.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'mocha';
import * as vscode from 'vscode';
import { context } from './testContext';
if (!context.RunTest) {
suite('integration test setup', () => {
test('test setup', async function () {
//Prepare the environment and make it ready for testing
await vscode.commands.executeCommand('test.setupIntegrationTest');
//Reload the window, this is required for some changes made by the 'test.setupIntegrationTest' to work
await vscode.commands.executeCommand('workbench.action.reloadWindow');
});
});
}

View File

@@ -0,0 +1,92 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/*
TODO: Due to a runtime error, I duplicated this file at these 2 locations:
$/extensions/integration-test/src/testConfig.ts
$/test/smoke/src/sql/testConfig.ts
for now, make sure to keep both files in sync.
*/
interface ITestServerProfile {
serverName: string;
userName: string;
password: string;
authenticationType: AuthenticationType;
database: string;
provider: ConnectionProvider;
version: string;
}
interface INameDisplayNamePair {
name: string;
displayName: string;
}
export enum AuthenticationType {
Windows,
SqlLogin
}
export enum ConnectionProvider {
SQLServer
}
var connectionProviderMapping = {};
var authenticationTypeMapping = {};
connectionProviderMapping[ConnectionProvider.SQLServer] = { name: 'MSSQL', displayName: 'Microsoft SQL Server' };
authenticationTypeMapping[AuthenticationType.SqlLogin] = { name: 'SqlLogin', displayName: 'SQL Login' };
authenticationTypeMapping[AuthenticationType.Windows] = { name: 'Integrated', displayName: 'Windows Authentication' };
export class TestServerProfile {
constructor(private _profile: ITestServerProfile) { }
public get serverName(): string { return this._profile.serverName; }
public get userName(): string { return this._profile.userName; }
public get password(): string { return this._profile.password; }
public get database(): string { return this._profile.database; }
public get version(): string { return this._profile.version; }
public get provider(): ConnectionProvider { return this._profile.provider; }
public get providerName(): string { return getEnumMappingEntry(connectionProviderMapping, this.provider).name; }
public get providerDisplayName(): string { return getEnumMappingEntry(connectionProviderMapping, this.provider).displayName; }
public get authenticationType(): AuthenticationType { return this._profile.authenticationType; }
public get authenticationTypeName(): string { return getEnumMappingEntry(authenticationTypeMapping, this.authenticationType).name; }
public get authenticationTypeDisplayName(): string { return getEnumMappingEntry(authenticationTypeMapping, this.authenticationType).displayName; }
}
var TestingServers: TestServerProfile[] = [
new TestServerProfile(
{
serverName: 'SQLTOOLS2017-3',
userName: '',
password: '',
authenticationType: AuthenticationType.Windows,
database: 'master',
provider: ConnectionProvider.SQLServer,
version: '2017'
})
];
function getEnumMappingEntry(mapping: any, enumValue: any): INameDisplayNamePair {
let entry = mapping[enumValue];
if (entry) {
return entry;
} else {
throw `Unknown enum type: ${enumValue.toString()}`;
}
}
export async function getDefaultTestingServer(): Promise<TestServerProfile> {
let servers = await getTestingServers();
return servers[0];
}
export async function getTestingServers(): Promise<TestServerProfile[]> {
let promise = new Promise<TestServerProfile[]>(resolve => {
resolve(TestingServers);
});
await promise;
return promise;
}

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.
*--------------------------------------------------------------------------------------------*/
export var context = {
RunTest: true
};

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/sql/sqlops.d.ts'/>
/// <reference path='../../../../src/sql/sqlops.proposed.d.ts'/>
/// <reference path='../../../../src/sql/sqlops.test.d.ts'/>
/// <reference types='@types/node'/>

View File

@@ -0,0 +1,38 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import assert = require('assert');
import * as sqlops from 'sqlops';
import * as vscode from 'vscode';
import { TestServerProfile } from './testConfig';
export async function connectToServer(server: TestServerProfile) {
let connectionProfile: sqlops.IConnectionProfile = {
serverName: server.serverName,
databaseName: server.database,
authenticationType: server.authenticationTypeName,
providerName: server.providerName,
connectionName: '',
userName: server.userName,
password: server.password,
savePassword: false,
groupFullName: undefined,
saveProfile: true,
id: undefined,
groupId: undefined,
options: {}
};
await ensureConnectionViewOpened();
let result = <sqlops.ConnectionResult>await sqlops.connection.connect(connectionProfile);
assert(result.connected, `Failed to connect to "${connectionProfile.serverName}", error code: ${result.errorCode}, error message: ${result.errorMessage}`);
//workaround
//wait for OE to load
await new Promise(c => setTimeout(c, 3000));
}
export async function ensureConnectionViewOpened() {
await vscode.commands.executeCommand('workbench.view.connections');
}

View File

@@ -0,0 +1,15 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "ES5",
"outDir": "out",
"noUnusedLocals": true,
"lib": [
"es2015"
],
"sourceMap": true
},
"include": [
"src/**/*"
]
}

File diff suppressed because it is too large Load Diff

View File

@@ -18,7 +18,7 @@
"update-grammar": "node ../../build/npm/update-grammar.js Microsoft/vscode-mssql syntaxes/SQL.plist ./syntaxes/sql.tmLanguage.json" "update-grammar": "node ../../build/npm/update-grammar.js Microsoft/vscode-mssql syntaxes/SQL.plist ./syntaxes/sql.tmLanguage.json"
}, },
"dependencies": { "dependencies": {
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#0.2.10", "dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#0.2.15",
"opener": "^1.4.3", "opener": "^1.4.3",
"service-downloader": "github:anthonydresser/service-downloader#0.1.5", "service-downloader": "github:anthonydresser/service-downloader#0.1.5",
"vscode-extension-telemetry": "^0.0.15" "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#}", "downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
"version": "1.5.0-alpha.63", "version": "1.5.0-alpha.68",
"downloadFileNames": { "downloadFileNames": {
"Windows_86": "win-x86-netcoreapp2.2.zip", "Windows_86": "win-x86-netcoreapp2.2.zip",
"Windows_64": "win-x64-netcoreapp2.2.zip", "Windows_64": "win-x64-netcoreapp2.2.zip",

View File

@@ -331,6 +331,14 @@ export interface DeployParams {
taskExecutionMode: TaskExecutionMode; taskExecutionMode: TaskExecutionMode;
} }
export interface GenerateDeployScriptParams {
packageFilePath: string;
databaseName: string;
scriptFilePath: string;
ownerUri: string;
taskExecutionMode: TaskExecutionMode;
}
export namespace ExportRequest { export namespace ExportRequest {
export const type = new RequestType<ExportParams, sqlops.DacFxResult, void, void>('dacfx/export'); export const type = new RequestType<ExportParams, sqlops.DacFxResult, void, void>('dacfx/export');
} }
@@ -347,4 +355,8 @@ export namespace DeployRequest {
export const type = new RequestType<DeployParams, sqlops.DacFxResult, void, void>('dacfx/deploy'); export const type = new RequestType<DeployParams, sqlops.DacFxResult, void, void>('dacfx/deploy');
} }
export namespace GenerateDeployScriptRequest {
export const type = new RequestType<GenerateDeployScriptParams, sqlops.DacFxResult, void, void>('dacfx/generateDeploymentScript');
}
// ------------------------------- < DacFx > ------------------------------------ // ------------------------------- < DacFx > ------------------------------------

View File

@@ -106,12 +106,26 @@ export class DacFxServicesFeature extends SqlOpsFeature<undefined> {
); );
}; };
let generateDeployScript = (packageFilePath: string, targetDatabaseName: string, scriptFilePath: string, ownerUri: string, taskExecutionMode: sqlops.TaskExecutionMode): Thenable<sqlops.DacFxResult> => {
let params: contracts.GenerateDeployScriptParams = { packageFilePath: packageFilePath, databaseName: targetDatabaseName, scriptFilePath: scriptFilePath, ownerUri: ownerUri, taskExecutionMode: taskExecutionMode };
return client.sendRequest(contracts.GenerateDeployScriptRequest.type, params).then(
r => {
return r;
},
e => {
client.logFailedRequest(contracts.DeployRequest.type, e);
return Promise.resolve(undefined);
}
);
};
return sqlops.dataprotocol.registerDacFxServicesProvider({ return sqlops.dataprotocol.registerDacFxServicesProvider({
providerId: client.providerId, providerId: client.providerId,
exportBacpac, exportBacpac,
importBacpac, importBacpac,
extractDacpac, extractDacpac,
deployDacpac deployDacpac,
generateDeployScript
}); });
} }
} }

View File

@@ -11,7 +11,7 @@
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"experimentalDecorators": true, "experimentalDecorators": true,
"moduleResolution": "node", "moduleResolution": "node",
"declaration": true "declaration": false
}, },
"exclude": [ "exclude": [
"node_modules" "node_modules"

View File

@@ -5,14 +5,12 @@
agent-base@4, agent-base@^4.1.0: agent-base@4, agent-base@^4.1.0:
version "4.2.1" version "4.2.1"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9"
integrity sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==
dependencies: dependencies:
es6-promisify "^5.0.0" es6-promisify "^5.0.0"
applicationinsights@1.0.1: applicationinsights@1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.1.tgz#53446b830fe8d5d619eee2a278b31d3d25030927" resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.1.tgz#53446b830fe8d5d619eee2a278b31d3d25030927"
integrity sha1-U0Rrgw/o1dYZ7uKieLMdPSUDCSc=
dependencies: dependencies:
diagnostic-channel "0.2.0" diagnostic-channel "0.2.0"
diagnostic-channel-publishers "0.2.1" diagnostic-channel-publishers "0.2.1"
@@ -21,12 +19,10 @@ applicationinsights@1.0.1:
base64-js@0.0.8: base64-js@0.0.8:
version "0.0.8" version "0.0.8"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.8.tgz#1101e9544f4a76b1bc3b26d452ca96d7a35e7978" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.8.tgz#1101e9544f4a76b1bc3b26d452ca96d7a35e7978"
integrity sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=
bl@^1.0.0: bl@^1.0.0:
version "1.2.2" version "1.2.2"
resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c"
integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==
dependencies: dependencies:
readable-stream "^2.3.5" readable-stream "^2.3.5"
safe-buffer "^5.1.1" safe-buffer "^5.1.1"
@@ -34,12 +30,10 @@ bl@^1.0.0:
buffer-alloc-unsafe@^1.1.0: buffer-alloc-unsafe@^1.1.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==
buffer-alloc@^1.2.0: buffer-alloc@^1.2.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec"
integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==
dependencies: dependencies:
buffer-alloc-unsafe "^1.1.0" buffer-alloc-unsafe "^1.1.0"
buffer-fill "^1.0.0" buffer-fill "^1.0.0"
@@ -47,17 +41,14 @@ buffer-alloc@^1.2.0:
buffer-crc32@~0.2.3: buffer-crc32@~0.2.3:
version "0.2.13" version "0.2.13"
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
buffer-fill@^1.0.0: buffer-fill@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c"
integrity sha1-+PeLdniYiO858gXNY39o5wISKyw=
buffer@^3.0.1: buffer@^3.0.1:
version "3.6.0" version "3.6.0"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-3.6.0.tgz#a72c936f77b96bf52f5f7e7b467180628551defb" resolved "https://registry.yarnpkg.com/buffer/-/buffer-3.6.0.tgz#a72c936f77b96bf52f5f7e7b467180628551defb"
integrity sha1-pyyTb3e5a/UvX357RnGAYoVR3vs=
dependencies: dependencies:
base64-js "0.0.8" base64-js "0.0.8"
ieee754 "^1.1.4" ieee754 "^1.1.4"
@@ -66,39 +57,34 @@ buffer@^3.0.1:
commander@~2.8.1: commander@~2.8.1:
version "2.8.1" version "2.8.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4"
integrity sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=
dependencies: dependencies:
graceful-readlink ">= 1.0.0" graceful-readlink ">= 1.0.0"
core-util-is@~1.0.0: core-util-is@~1.0.0:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#0.2.10": "dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#0.2.15":
version "0.2.10" version "0.2.15"
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/4de3f7caf0eba54159911b977ddb4f5d7c0a9ca8" resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/a2cd2db109de882f0959f7b6421c86afa585f460"
dependencies: dependencies:
vscode-languageclient "3.5.1" vscode-languageclient "3.5.1"
debug@3.1.0: debug@3.1.0:
version "3.1.0" version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
dependencies: dependencies:
ms "2.0.0" ms "2.0.0"
debug@^3.1.0: debug@^3.1.0:
version "3.2.6" version "3.2.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
dependencies: dependencies:
ms "^2.1.1" ms "^2.1.1"
decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1:
version "4.1.1" version "4.1.1"
resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1"
integrity sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==
dependencies: dependencies:
file-type "^5.2.0" file-type "^5.2.0"
is-stream "^1.1.0" is-stream "^1.1.0"
@@ -107,7 +93,6 @@ decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1:
decompress-tarbz2@^4.0.0: decompress-tarbz2@^4.0.0:
version "4.1.1" version "4.1.1"
resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b"
integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==
dependencies: dependencies:
decompress-tar "^4.1.0" decompress-tar "^4.1.0"
file-type "^6.1.0" file-type "^6.1.0"
@@ -118,7 +103,6 @@ decompress-tarbz2@^4.0.0:
decompress-targz@^4.0.0: decompress-targz@^4.0.0:
version "4.1.1" version "4.1.1"
resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee"
integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==
dependencies: dependencies:
decompress-tar "^4.1.1" decompress-tar "^4.1.1"
file-type "^5.2.0" file-type "^5.2.0"
@@ -127,7 +111,6 @@ decompress-targz@^4.0.0:
decompress-unzip@^4.0.1: decompress-unzip@^4.0.1:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69"
integrity sha1-3qrM39FK6vhVePczroIQ+bSEj2k=
dependencies: dependencies:
file-type "^3.8.0" file-type "^3.8.0"
get-stream "^2.2.0" get-stream "^2.2.0"
@@ -137,7 +120,6 @@ decompress-unzip@^4.0.1:
decompress@^4.2.0: decompress@^4.2.0:
version "4.2.0" version "4.2.0"
resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d" resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d"
integrity sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=
dependencies: dependencies:
decompress-tar "^4.0.0" decompress-tar "^4.0.0"
decompress-tarbz2 "^4.0.0" decompress-tarbz2 "^4.0.0"
@@ -151,70 +133,58 @@ decompress@^4.2.0:
diagnostic-channel-publishers@0.2.1: diagnostic-channel-publishers@0.2.1:
version "0.2.1" version "0.2.1"
resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3" resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3"
integrity sha1-ji1geottef6IC1SLxYzGvrKIxPM=
diagnostic-channel@0.2.0: diagnostic-channel@0.2.0:
version "0.2.0" version "0.2.0"
resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-0.2.0.tgz#cc99af9612c23fb1fff13612c72f2cbfaa8d5a17" resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-0.2.0.tgz#cc99af9612c23fb1fff13612c72f2cbfaa8d5a17"
integrity sha1-zJmvlhLCP7H/8TYSxy8sv6qNWhc=
dependencies: dependencies:
semver "^5.3.0" semver "^5.3.0"
end-of-stream@^1.0.0: end-of-stream@^1.0.0:
version "1.4.1" version "1.4.1"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43"
integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==
dependencies: dependencies:
once "^1.4.0" once "^1.4.0"
es6-promise@^4.0.3: es6-promise@^4.0.3:
version "4.2.5" version "4.2.5"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.5.tgz#da6d0d5692efb461e082c14817fe2427d8f5d054" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.5.tgz#da6d0d5692efb461e082c14817fe2427d8f5d054"
integrity sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==
es6-promisify@^5.0.0: es6-promisify@^5.0.0:
version "5.0.0" version "5.0.0"
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=
dependencies: dependencies:
es6-promise "^4.0.3" es6-promise "^4.0.3"
eventemitter2@^5.0.1: eventemitter2@^5.0.1:
version "5.0.1" version "5.0.1"
resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-5.0.1.tgz#6197a095d5fb6b57e8942f6fd7eaad63a09c9452" resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-5.0.1.tgz#6197a095d5fb6b57e8942f6fd7eaad63a09c9452"
integrity sha1-YZegldX7a1folC9v1+qtY6CclFI=
fd-slicer@~1.1.0: fd-slicer@~1.1.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=
dependencies: dependencies:
pend "~1.2.0" pend "~1.2.0"
file-type@^3.8.0: file-type@^3.8.0:
version "3.9.0" version "3.9.0"
resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9"
integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek=
file-type@^5.2.0: file-type@^5.2.0:
version "5.2.0" version "5.2.0"
resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6"
integrity sha1-LdvqfHP/42No365J3DOMBYwritY=
file-type@^6.1.0: file-type@^6.1.0:
version "6.2.0" version "6.2.0"
resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919"
integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==
fs-constants@^1.0.0: fs-constants@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
get-stream@^2.2.0: get-stream@^2.2.0:
version "2.3.1" version "2.3.1"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de"
integrity sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=
dependencies: dependencies:
object-assign "^4.0.1" object-assign "^4.0.1"
pinkie-promise "^2.0.0" pinkie-promise "^2.0.0"
@@ -222,17 +192,14 @@ get-stream@^2.2.0:
graceful-fs@^4.1.10: graceful-fs@^4.1.10:
version "4.1.15" version "4.1.15"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==
"graceful-readlink@>= 1.0.0": "graceful-readlink@>= 1.0.0":
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=
http-proxy-agent@^2.1.0: http-proxy-agent@^2.1.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405"
integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==
dependencies: dependencies:
agent-base "4" agent-base "4"
debug "3.1.0" debug "3.1.0"
@@ -240,7 +207,6 @@ http-proxy-agent@^2.1.0:
https-proxy-agent@^2.2.1: https-proxy-agent@^2.2.1:
version "2.2.1" version "2.2.1"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0"
integrity sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==
dependencies: dependencies:
agent-base "^4.1.0" agent-base "^4.1.0"
debug "^3.1.0" debug "^3.1.0"
@@ -248,115 +214,94 @@ https-proxy-agent@^2.2.1:
ieee754@^1.1.4: ieee754@^1.1.4:
version "1.1.12" version "1.1.12"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b"
integrity sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==
inherits@~2.0.3: inherits@~2.0.3:
version "2.0.3" version "2.0.3"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
is-natural-number@^4.0.1: is-natural-number@^4.0.1:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8"
integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=
is-stream@^1.1.0: is-stream@^1.1.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
isarray@^1.0.0, isarray@~1.0.0: isarray@^1.0.0, isarray@~1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
make-dir@^1.0.0: make-dir@^1.0.0:
version "1.3.0" version "1.3.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==
dependencies: dependencies:
pify "^3.0.0" pify "^3.0.0"
minimist@0.0.8: minimist@0.0.8:
version "0.0.8" version "0.0.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
mkdirp@^0.5.1: mkdirp@^0.5.1:
version "0.5.1" version "0.5.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
dependencies: dependencies:
minimist "0.0.8" minimist "0.0.8"
ms@2.0.0: ms@2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
ms@^2.1.1: ms@^2.1.1:
version "2.1.1" version "2.1.1"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
object-assign@^4.0.1: object-assign@^4.0.1:
version "4.1.1" version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
once@^1.4.0: once@^1.4.0:
version "1.4.0" version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
dependencies: dependencies:
wrappy "1" wrappy "1"
opener@^1.4.3: opener@^1.4.3:
version "1.5.1" version "1.5.1"
resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed" resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed"
integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==
os-tmpdir@~1.0.2: os-tmpdir@~1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
pend@~1.2.0: pend@~1.2.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA=
pify@^2.3.0: pify@^2.3.0:
version "2.3.0" version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
pify@^3.0.0: pify@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=
pinkie-promise@^2.0.0: pinkie-promise@^2.0.0:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o=
dependencies: dependencies:
pinkie "^2.0.0" pinkie "^2.0.0"
pinkie@^2.0.0: pinkie@^2.0.0:
version "2.0.4" version "2.0.4"
resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
process-nextick-args@~2.0.0: process-nextick-args@~2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa"
integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==
readable-stream@^2.3.0, readable-stream@^2.3.5: readable-stream@^2.3.0, readable-stream@^2.3.5:
version "2.3.6" version "2.3.6"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==
dependencies: dependencies:
core-util-is "~1.0.0" core-util-is "~1.0.0"
inherits "~2.0.3" inherits "~2.0.3"
@@ -369,19 +314,16 @@ readable-stream@^2.3.0, readable-stream@^2.3.5:
safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2" version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
seek-bzip@^1.0.5: seek-bzip@^1.0.5:
version "1.0.5" version "1.0.5"
resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc"
integrity sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=
dependencies: dependencies:
commander "~2.8.1" commander "~2.8.1"
semver@^5.3.0: semver@^5.3.0:
version "5.6.0" version "5.6.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
"service-downloader@github:anthonydresser/service-downloader#0.1.5": "service-downloader@github:anthonydresser/service-downloader#0.1.5":
version "0.1.5" version "0.1.5"
@@ -397,21 +339,18 @@ semver@^5.3.0:
string_decoder@~1.1.1: string_decoder@~1.1.1:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
dependencies: dependencies:
safe-buffer "~5.1.0" safe-buffer "~5.1.0"
strip-dirs@^2.0.0: strip-dirs@^2.0.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5"
integrity sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==
dependencies: dependencies:
is-natural-number "^4.0.1" is-natural-number "^4.0.1"
tar-stream@^1.5.2: tar-stream@^1.5.2:
version "1.6.2" version "1.6.2"
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555"
integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==
dependencies: dependencies:
bl "^1.0.0" bl "^1.0.0"
buffer-alloc "^1.2.0" buffer-alloc "^1.2.0"
@@ -424,24 +363,20 @@ tar-stream@^1.5.2:
through@^2.3.6: through@^2.3.6:
version "2.3.8" version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
tmp@^0.0.33: tmp@^0.0.33:
version "0.0.33" version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
dependencies: dependencies:
os-tmpdir "~1.0.2" os-tmpdir "~1.0.2"
to-buffer@^1.1.1: to-buffer@^1.1.1:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80"
integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==
unbzip2-stream@^1.0.9: unbzip2-stream@^1.0.9:
version "1.3.1" version "1.3.1"
resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.1.tgz#7854da51622a7e63624221196357803b552966a1" resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.1.tgz#7854da51622a7e63624221196357803b552966a1"
integrity sha512-fIZnvdjblYs7Cru/xC6tCPVhz7JkYcVQQkePwMLyQELzYTds2Xn8QefPVnvdVhhZqubxNA1cASXEH5wcK0Bucw==
dependencies: dependencies:
buffer "^3.0.1" buffer "^3.0.1"
through "^2.3.6" through "^2.3.6"
@@ -449,31 +384,26 @@ unbzip2-stream@^1.0.9:
util-deprecate@~1.0.1: util-deprecate@~1.0.1:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
vscode-extension-telemetry@^0.0.15: vscode-extension-telemetry@^0.0.15:
version "0.0.15" version "0.0.15"
resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.15.tgz#685c32f3b67e8fb85ba689c1d7f88ff90ff87856" resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.15.tgz#685c32f3b67e8fb85ba689c1d7f88ff90ff87856"
integrity sha512-Yf6dL9r2x2GISI1xh22XsAaydSTQG/4aBitu8sGBwGr42n2TyOsIXGtXSDgqQBNZgYD6+P1EHqrrzetn9ekWTQ==
dependencies: dependencies:
applicationinsights "1.0.1" applicationinsights "1.0.1"
vscode-jsonrpc@3.5.0: vscode-jsonrpc@3.5.0:
version "3.5.0" version "3.5.0"
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-3.5.0.tgz#87239d9e166b2d7352245b8a813597804c1d63aa" resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-3.5.0.tgz#87239d9e166b2d7352245b8a813597804c1d63aa"
integrity sha1-hyOdnhZrLXNSJFuKgTWXgEwdY6o=
vscode-languageclient@3.5.1: vscode-languageclient@3.5.1:
version "3.5.1" version "3.5.1"
resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-3.5.1.tgz#c78e582459c24e58f88020dfa34065e976186a98" resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-3.5.1.tgz#c78e582459c24e58f88020dfa34065e976186a98"
integrity sha512-GTQ+hSq/o4c/y6GYmyP9XNrVoIu0NFZ67KltSkqN+tO0eUNDIlrVNX+3DJzzyLhSsrctuGzuYWm3t87mNAcBmQ==
dependencies: dependencies:
vscode-languageserver-protocol "3.5.1" vscode-languageserver-protocol "3.5.1"
vscode-languageserver-protocol@3.5.1: vscode-languageserver-protocol@3.5.1:
version "3.5.1" version "3.5.1"
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.5.1.tgz#5144a3a9eeccbd83fe2745bd4ed75fad6cc45f0d" resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.5.1.tgz#5144a3a9eeccbd83fe2745bd4ed75fad6cc45f0d"
integrity sha512-1fPDIwsAv1difCV+8daOrJEGunClNJWqnUHq/ncWrjhitKWXgGmRCjlwZ3gDUTt54yRcvXz1PXJDaRNvNH6pYA==
dependencies: dependencies:
vscode-jsonrpc "3.5.0" vscode-jsonrpc "3.5.0"
vscode-languageserver-types "3.5.0" vscode-languageserver-types "3.5.0"
@@ -481,22 +411,18 @@ vscode-languageserver-protocol@3.5.1:
vscode-languageserver-types@3.5.0: vscode-languageserver-types@3.5.0:
version "3.5.0" version "3.5.0"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.5.0.tgz#e48d79962f0b8e02de955e3f524908e2b19c0374" resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.5.0.tgz#e48d79962f0b8e02de955e3f524908e2b19c0374"
integrity sha1-5I15li8LjgLelV4/UkkI4rGcA3Q=
wrappy@1: wrappy@1:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
xtend@^4.0.0: xtend@^4.0.0:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68=
yauzl@^2.4.2: yauzl@^2.4.2:
version "2.10.0" version "2.10.0"
resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=
dependencies: dependencies:
buffer-crc32 "~0.2.3" buffer-crc32 "~0.2.3"
fd-slicer "~1.1.0" fd-slicer "~1.1.0"
@@ -504,4 +430,3 @@ yauzl@^2.4.2:
zone.js@0.7.6: zone.js@0.7.6:
version "0.7.6" version "0.7.6"
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009" resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009"
integrity sha1-+7w50+AmHQmG8boGMG6zrrDSIAk=

View File

@@ -21,6 +21,11 @@
"type": "boolean", "type": "boolean",
"default": true, "default": true,
"description": "%notebook.enabled.description%" "description": "%notebook.enabled.description%"
},
"notebook.pythonPath": {
"type": "string",
"default": "",
"description": "%notebook.pythonPath.description%"
} }
} }
}, },

View File

@@ -3,6 +3,7 @@
"description": "Defines the Data-procotol based Notebook contribution and many Notebook commands and contributions.", "description": "Defines the Data-procotol based Notebook contribution and many Notebook commands and contributions.",
"notebook.configuration.title": "Notebook configuration", "notebook.configuration.title": "Notebook configuration",
"notebook.enabled.description": "Enable viewing notebook files using built-in notebook editor.", "notebook.enabled.description": "Enable viewing notebook files using built-in notebook editor.",
"notebook.pythonPath.description": "Local path to python installation used by Notebooks.",
"notebook.command.new": "New Notebook", "notebook.command.new": "New Notebook",
"notebook.command.open": "Open Notebook" "notebook.command.open": "Open Notebook"
} }

View File

@@ -106,7 +106,7 @@ export class CreateSessionDialog {
private updateSessionName() { private updateSessionName() {
if (this.templatesBox.value) { if (this.templatesBox.value) {
this.sessionNameBox.value = `ADS_${this.templatesBox.value.toString()}` this.sessionNameBox.value = `ADS_${this.templatesBox.value.toString()}`;
} }
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "azuredatastudio", "name": "azuredatastudio",
"version": "1.4.1", "version": "1.4.3",
"distro": "8c3e97e3425cc9814496472ab73e076de2ba99ee", "distro": "8c3e97e3425cc9814496472ab73e076de2ba99ee",
"author": { "author": {
"name": "Microsoft Corporation" "name": "Microsoft Corporation"

View File

@@ -62,6 +62,12 @@
<trans-unit id="sql.saveAsCsv.encoding"> <trans-unit id="sql.saveAsCsv.encoding">
<source xml:lang="en">[Optional] File encoding used when saving results as CSV</source> <source xml:lang="en">[Optional] File encoding used when saving results as CSV</source>
</trans-unit> </trans-unit>
<trans-unit id="sql.saveAsXml.formatted">
<source xml:lang="en">[Optional] When true, XML output will be formatted when saving results as XML</source>
</trans-unit>
<trans-unit id="sql.saveAsXml.encoding">
<source xml:lang="en">[Optional] File encoding used when saving results as XML</source>
</trans-unit>
<trans-unit id="sql.copyIncludeHeaders"> <trans-unit id="sql.copyIncludeHeaders">
<source xml:lang="en">[Optional] Configuration options for copying results from the Results View</source> <source xml:lang="en">[Optional] Configuration options for copying results from the Results View</source>
</trans-unit> </trans-unit>
@@ -596,6 +602,9 @@
<trans-unit id="saveAsExcel"> <trans-unit id="saveAsExcel">
<source xml:lang="en">Save As Excel</source> <source xml:lang="en">Save As Excel</source>
</trans-unit> </trans-unit>
<trans-unit id="saveAsXml">
<source xml:lang="en">Save As XML</source>
</trans-unit>
<trans-unit id="copySelection"> <trans-unit id="copySelection">
<source xml:lang="en">Copy</source> <source xml:lang="en">Copy</source>
</trans-unit> </trans-unit>
@@ -1142,6 +1151,9 @@
<trans-unit id="saveExcelLabel"> <trans-unit id="saveExcelLabel">
<source xml:lang="en">Save as Excel</source> <source xml:lang="en">Save as Excel</source>
</trans-unit> </trans-unit>
<trans-unit id="saveXMLLabel">
<source xml:lang="en">Save as XML</source>
</trans-unit>
<trans-unit id="viewChartLabel"> <trans-unit id="viewChartLabel">
<source xml:lang="en">View as Chart</source> <source xml:lang="en">View as Chart</source>
</trans-unit> </trans-unit>

View File

@@ -0,0 +1,20 @@
setlocal
pushd %~dp0\..
set VSCODEUSERDATADIR=%TMP%\adsuser-%RANDOM%-%TIME:~6,5%
set VSCODEEXTENSIONSDIR=%TMP%\adsext-%RANDOM%-%TIME:~6,5%
echo %VSCODEUSERDATADIR%
echo %VSCODEEXTENSIONSDIR%
@echo OFF
call .\scripts\code.bat --extensionDevelopmentPath=%~dp0\..\extensions\integration-tests --extensionTestsPath=%~dp0\..\extensions\integration-tests\out --user-data-dir=%VSCODEUSERDATADIR% --extensions-dir=%VSCODEEXTENSIONSDIR%
if %errorlevel% neq 0 exit /b %errorlevel%
rmdir /s /q %VSCODEUSERDATADIR%
rmdir /s /q %VSCODEEXTENSIONSDIR%
popd
endlocal

View File

@@ -0,0 +1,23 @@
#!/bin/bash
set -e
if [[ "$OSTYPE" == "darwin"* ]]; then
realpath() { [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"; }
ROOT=$(dirname $(dirname $(realpath "$0")))
VSCODEUSERDATADIR=`mktemp -d -t 'myuserdatadir'`
VSCODEEXTDIR=`mktemp -d -t 'myextdir'`
else
ROOT=$(dirname $(dirname $(readlink -f $0)))
VSCODEUSERDATADIR=`mktemp -d 2>/dev/null`
VSCODEEXTDIR=`mktemp -d 2>/dev/null`
fi
cd $ROOT
echo $VSCODEUSERDATADIR
echo $VSCODEEXTDIR
./scripts/code.sh --extensionDevelopmentPath=$ROOT/extensions/integration-tests --extensionTestsPath=$ROOT/extensions/integration-tests/out --user-data-dir=$VSCODEUSERDATADIR --extensions-dir=$VSCODEEXTDIR
rm -r $VSCODEUSERDATADIR
rm -r $VSCODEEXTDIR

View File

@@ -8,7 +8,7 @@ import 'vs/css!./media/breadcrumb';
import { Component, Inject, forwardRef, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core'; import { Component, Inject, forwardRef, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { toDisposableSubscription } from 'sql/parts/common/rxjsUtils'; import { toDisposableSubscription } from 'sql/base/node/rxjsUtils';
import { IBreadcrumbService, MenuItem } from './interfaces'; import { IBreadcrumbService, MenuItem } from './interfaces';
import { IDisposable } from 'vs/base/common/lifecycle'; import { IDisposable } from 'vs/base/common/lifecycle';

View File

@@ -11,7 +11,7 @@ import {
} from '@angular/core'; } from '@angular/core';
import { Dropdown, IDropdownOptions } from 'sql/base/browser/ui/editableDropdown/dropdown'; import { Dropdown, IDropdownOptions } from 'sql/base/browser/ui/editableDropdown/dropdown';
import { AngularDisposable } from 'sql/base/common/lifecycle'; import { AngularDisposable } from 'sql/base/node/lifecycle';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { attachEditableDropdownStyler } from 'sql/common/theme/styler'; import { attachEditableDropdownStyler } from 'sql/common/theme/styler';

View File

@@ -11,7 +11,7 @@ import {
} from '@angular/core'; } from '@angular/core';
import { InputBox as vsInputBox } from 'sql/base/browser/ui/inputBox/inputBox'; import { InputBox as vsInputBox } from 'sql/base/browser/ui/inputBox/inputBox';
import { AngularDisposable } from 'sql/base/common/lifecycle'; import { AngularDisposable } from 'sql/base/node/lifecycle';
import { attachInputBoxStyler } from 'vs/platform/theme/common/styler'; import { attachInputBoxStyler } from 'vs/platform/theme/common/styler';
import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IThemeService } from 'vs/platform/theme/common/themeService';

View File

@@ -414,17 +414,17 @@ export abstract class Modal extends Disposable implements IThemable {
} }
}); });
this._resizeListener = DOM.addDisposableListener(window, DOM.EventType.RESIZE, (e: Event) => { this._resizeListener = DOM.addDisposableListener(window, DOM.EventType.RESIZE, (e: Event) => {
this.layout(DOM.getTotalHeight(this._builder.getHTMLElement())); this.layout(DOM.getTotalHeight(this._modalBodySection));
}); });
this.layout(DOM.getTotalHeight(this._builder.getHTMLElement())); this.layout(DOM.getTotalHeight(this._modalBodySection));
TelemetryUtils.addTelemetry(this._telemetryService, TelemetryKeys.ModalDialogOpened, { name: this._name }); TelemetryUtils.addTelemetry(this._telemetryService, TelemetryKeys.ModalDialogOpened, { name: this._name });
} }
/** /**
* Required to be implemented so that scrolling and other functions operate correctly. Should re-layout controls in the modal * Required to be implemented so that scrolling and other functions operate correctly. Should re-layout controls in the modal
*/ */
protected abstract layout(height?: number): void; protected abstract layout(height: number): void;
/** /**
* Hides the modal and removes key listeners * Hides the modal and removes key listeners

View File

@@ -6,19 +6,20 @@
'use strict'; 'use strict';
import 'vs/css!./media/optionsDialog'; import 'vs/css!./media/optionsDialog';
import { Button } from 'sql/base/browser/ui/button/button';
import { FixedCollapsibleView } from 'sql/platform/views/fixedCollapsibleView';
import * as DialogHelper from './dialogHelper'; import * as DialogHelper from './dialogHelper';
import { SelectBox } from 'sql/base/browser/ui/selectBox/selectBox'; import { SelectBox } from 'sql/base/browser/ui/selectBox/selectBox';
import { IModalOptions, Modal } from './modal'; import { IModalOptions, Modal } from './modal';
import * as OptionsDialogHelper from './optionsDialogHelper'; import * as OptionsDialogHelper from './optionsDialogHelper';
import { attachButtonStyler, attachModalDialogStyler } from 'sql/common/theme/styler'; import { attachButtonStyler, attachModalDialogStyler, attachPanelStyler } from 'sql/common/theme/styler';
import { ServiceOptionType } from 'sql/workbench/api/common/sqlExtHostTypes';
import { ScrollableSplitView } from 'sql/base/browser/ui/scrollableSplitview/scrollableSplitview';
import * as sqlops from 'sqlops'; import * as sqlops from 'sqlops';
import { IPartService } from 'vs/workbench/services/part/common/partService'; import { IPartService } from 'vs/workbench/services/part/common/partService';
import { Event, Emitter } from 'vs/base/common/event'; import { Event, Emitter } from 'vs/base/common/event';
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { localize } from 'vs/nls'; import { localize } from 'vs/nls';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
@@ -26,58 +27,56 @@ import { IWorkbenchThemeService, IColorTheme } from 'vs/workbench/services/theme
import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { contrastBorder } from 'vs/platform/theme/common/colorRegistry';
import * as styler from 'vs/platform/theme/common/styler'; import * as styler from 'vs/platform/theme/common/styler';
import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox'; import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox';
import { SplitView, CollapsibleState } from 'sql/base/browser/ui/splitview/splitview';
import { Builder, $ } from 'vs/base/browser/builder'; import { Builder, $ } from 'vs/base/browser/builder';
import { Widget } from 'vs/base/browser/ui/widget'; import { Widget } from 'vs/base/browser/ui/widget';
import { ServiceOptionType } from 'sql/workbench/api/common/sqlExtHostTypes';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { IViewletPanelOptions, ViewletPanel } from 'vs/workbench/browser/parts/views/panelViewlet';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
export class CategoryView extends FixedCollapsibleView { export class CategoryView extends ViewletPanel {
private _treecontainer: HTMLElement;
private _collapsed: CollapsibleState;
constructor(private viewTitle: string, private _bodyContainer: HTMLElement, collapsed: boolean, initialBodySize: number, headerSize: number) { constructor(
super( private contentElement: HTMLElement,
initialBodySize, private size: number,
{ options: IViewletPanelOptions,
expandedBodySize: initialBodySize, @IKeybindingService keybindingService: IKeybindingService,
sizing: headerSize, @IContextMenuService contextMenuService: IContextMenuService,
initialState: collapsed ? CollapsibleState.COLLAPSED : CollapsibleState.EXPANDED, @IConfigurationService configurationService: IConfigurationService
ariaHeaderLabel: viewTitle ) {
}); super(options, keybindingService, contextMenuService, configurationService);
this._collapsed = collapsed ? CollapsibleState.COLLAPSED : CollapsibleState.EXPANDED;
} }
public renderHeader(container: HTMLElement): void { // we want a fixed size, so when we render to will measure our content and set that to be our
const titleDiv = $('div.title').appendTo(container); // minimum and max size
$('span').text(this.viewTitle).appendTo(titleDiv); protected renderBody(container: HTMLElement): void {
container.appendChild(this.contentElement);
this.maximumBodySize = this.size;
this.minimumBodySize = this.size;
} }
public renderBody(container: HTMLElement): void { protected layoutBody(size: number): void {
this._treecontainer = document.createElement('div'); //
container.appendChild(this._treecontainer);
this._treecontainer.appendChild(this._bodyContainer);
this.changeState(this._collapsed);
} }
}
public layoutBody(size: number): void { export interface IOptionsDialogOptions extends IModalOptions {
this._treecontainer.style.height = size + 'px'; cancelLabel?: string;
}
} }
export class OptionsDialog extends Modal { export class OptionsDialog extends Modal {
private _body: HTMLElement; private _body: HTMLElement;
private _optionGroups: HTMLElement; private _optionGroups: HTMLElement;
private _dividerBuilder: Builder; private _dividerBuilder: Builder;
private _okButton: Button;
private _closeButton: Button;
private _optionTitle: Builder; private _optionTitle: Builder;
private _optionDescription: Builder; private _optionDescription: Builder;
private _optionElements: { [optionName: string]: OptionsDialogHelper.IOptionElement } = {}; private _optionElements: { [optionName: string]: OptionsDialogHelper.IOptionElement } = {};
private _optionValues: { [optionName: string]: string }; private _optionValues: { [optionName: string]: string };
private _optionRowSize = 31; private _optionRowSize = 31;
private _optionCategoryPadding = 30; private _optionCategoryPadding = 30;
private _categoryHeaderSize = 22; private height: number;
private splitview: ScrollableSplitView;
private _onOk = new Emitter<void>(); private _onOk = new Emitter<void>();
public onOk: Event<void> = this._onOk.event; public onOk: Event<void> = this._onOk.event;
@@ -85,16 +84,14 @@ export class OptionsDialog extends Modal {
private _onCloseEvent = new Emitter<void>(); private _onCloseEvent = new Emitter<void>();
public onCloseEvent: Event<void> = this._onCloseEvent.event; public onCloseEvent: Event<void> = this._onCloseEvent.event;
public okLabel: string = localize('optionsDialog.ok', 'OK');
public cancelLabel: string = localize('optionsDialog.cancel', 'Cancel');
constructor( constructor(
title: string, title: string,
name: string, name: string,
options: IModalOptions, private options: IOptionsDialogOptions,
@IPartService partService: IPartService, @IPartService partService: IPartService,
@IWorkbenchThemeService private _workbenchThemeService: IWorkbenchThemeService, @IWorkbenchThemeService private _workbenchThemeService: IWorkbenchThemeService,
@IContextViewService private _contextViewService: IContextViewService, @IContextViewService private _contextViewService: IContextViewService,
@IInstantiationService private _instantiationService: IInstantiationService,
@ITelemetryService telemetryService: ITelemetryService, @ITelemetryService telemetryService: ITelemetryService,
@IContextKeyService contextKeyService: IContextKeyService, @IContextKeyService contextKeyService: IContextKeyService,
@IClipboardService clipboardService: IClipboardService @IClipboardService clipboardService: IClipboardService
@@ -109,14 +106,13 @@ export class OptionsDialog extends Modal {
this.backButton.onDidClick(() => this.cancel()); this.backButton.onDidClick(() => this.cancel());
attachButtonStyler(this.backButton, this._themeService, { buttonBackground: SIDE_BAR_BACKGROUND, buttonHoverBackground: SIDE_BAR_BACKGROUND }); attachButtonStyler(this.backButton, this._themeService, { buttonBackground: SIDE_BAR_BACKGROUND, buttonHoverBackground: SIDE_BAR_BACKGROUND });
} }
this._okButton = this.addFooterButton(this.okLabel, () => this.ok()); let okButton = this.addFooterButton(localize('optionsDialog.ok', 'OK'), () => this.ok());
this._closeButton = this.addFooterButton(this.cancelLabel, () => this.cancel()); let closeButton = this.addFooterButton(this.options.cancelLabel || localize('optionsDialog.cancel', 'Cancel'), () => this.cancel());
// Theme styler // Theme styler
attachButtonStyler(this._okButton, this._themeService); attachButtonStyler(okButton, this._themeService);
attachButtonStyler(this._closeButton, this._themeService); attachButtonStyler(closeButton, this._themeService);
let self = this; this._register(this._workbenchThemeService.onDidColorThemeChange(e => this.updateTheme(e)));
this._register(self._workbenchThemeService.onDidColorThemeChange(e => self.updateTheme(e))); this.updateTheme(this._workbenchThemeService.getColorTheme());
self.updateTheme(self._workbenchThemeService.getColorTheme());
} }
protected renderBody(container: HTMLElement) { protected renderBody(container: HTMLElement) {
@@ -151,24 +147,24 @@ export class OptionsDialog extends Modal {
} }
private onOptionLinkClicked(optionName: string): void { private onOptionLinkClicked(optionName: string): void {
var option = this._optionElements[optionName].option; let option = this._optionElements[optionName].option;
this._optionTitle.text(option.displayName); this._optionTitle.text(option.displayName);
this._optionDescription.text(option.description); this._optionDescription.text(option.description);
} }
private fillInOptions(container: Builder, options: sqlops.ServiceOption[]): void { private fillInOptions(container: Builder, options: sqlops.ServiceOption[]): void {
for (var i = 0; i < options.length; i++) { for (let i = 0; i < options.length; i++) {
var option: sqlops.ServiceOption = options[i]; let option: sqlops.ServiceOption = options[i];
var rowContainer = DialogHelper.appendRow(container, option.displayName, 'optionsDialog-label', 'optionsDialog-input'); let rowContainer = DialogHelper.appendRow(container, option.displayName, 'optionsDialog-label', 'optionsDialog-input');
OptionsDialogHelper.createOptionElement(option, rowContainer, this._optionValues, this._optionElements, this._contextViewService, (name) => this.onOptionLinkClicked(name)); OptionsDialogHelper.createOptionElement(option, rowContainer, this._optionValues, this._optionElements, this._contextViewService, (name) => this.onOptionLinkClicked(name));
} }
} }
private registerStyling(): void { private registerStyling(): void {
// Theme styler // Theme styler
for (var optionName in this._optionElements) { for (let optionName in this._optionElements) {
var widget: Widget = this._optionElements[optionName].optionWidget; let widget: Widget = this._optionElements[optionName].optionWidget;
var option = this._optionElements[optionName].option; let option = this._optionElements[optionName].option;
switch (option.valueType) { switch (option.valueType) {
case ServiceOptionType.category: case ServiceOptionType.category:
case ServiceOptionType.boolean: case ServiceOptionType.boolean:
@@ -225,47 +221,51 @@ export class OptionsDialog extends Modal {
public open(options: sqlops.ServiceOption[], optionValues: { [name: string]: any }) { public open(options: sqlops.ServiceOption[], optionValues: { [name: string]: any }) {
this._optionValues = optionValues; this._optionValues = optionValues;
var firstOption: string; let firstOption: string;
var containerGroup: Builder; let containerGroup: Builder;
var layoutSize = 0; let optionsContentBuilder: Builder = $().div({ class: 'optionsDialog-options-groups monaco-panel-view' }, (container) => {
var optionsContentBuilder: Builder = $().div({ class: 'optionsDialog-options-groups' }, (container) => {
containerGroup = container; containerGroup = container;
this._optionGroups = container.getHTMLElement(); this._optionGroups = container.getHTMLElement();
}); });
var splitview = new SplitView(containerGroup.getHTMLElement()); this.splitview = new ScrollableSplitView(containerGroup.getHTMLElement(), { enableResizing: false, scrollDebounce: 0 });
let categoryMap = OptionsDialogHelper.groupOptionsByCategory(options); let categoryMap = OptionsDialogHelper.groupOptionsByCategory(options);
for (var category in categoryMap) { for (let category in categoryMap) {
var serviceOptions: sqlops.ServiceOption[] = categoryMap[category]; let serviceOptions: sqlops.ServiceOption[] = categoryMap[category];
var bodyContainer = $().element('table', { class: 'optionsDialog-table' }, (tableContainer: Builder) => { let bodyContainer = $().element('table', { class: 'optionsDialog-table' }, (tableContainer: Builder) => {
this.fillInOptions(tableContainer, serviceOptions); this.fillInOptions(tableContainer, serviceOptions);
}); });
var viewSize = this._optionCategoryPadding + serviceOptions.length * this._optionRowSize; let viewSize = this._optionCategoryPadding + serviceOptions.length * this._optionRowSize;
layoutSize += (viewSize + this._categoryHeaderSize); let categoryView = this._instantiationService.createInstance(CategoryView, bodyContainer.getHTMLElement(), viewSize, { title: category, ariaHeaderLabel: category, id: category });
var categoryView = new CategoryView(category, bodyContainer.getHTMLElement(), false, viewSize, this._categoryHeaderSize); this.splitview.addView(categoryView, viewSize);
splitview.addView(categoryView); categoryView.render();
attachPanelStyler(categoryView, this._themeService);
if (!firstOption) { if (!firstOption) {
firstOption = serviceOptions[0].name; firstOption = serviceOptions[0].name;
} }
} }
splitview.layout(layoutSize); if (this.height) {
this.splitview.layout(this.height - 120);
}
let body = new Builder(this._body); let body = new Builder(this._body);
body.append(optionsContentBuilder.getHTMLElement(), 0); body.append(optionsContentBuilder.getHTMLElement(), 0);
this.show(); this.show();
var firstOptionWidget = this._optionElements[firstOption].optionWidget; let firstOptionWidget = this._optionElements[firstOption].optionWidget;
this.registerStyling(); this.registerStyling();
firstOptionWidget.focus(); firstOptionWidget.focus();
} }
protected layout(height?: number): void { protected layout(height?: number): void {
// Nothing currently laid out in this class this.height = height;
// account for padding and the details view
this.splitview.layout(this.height - 120 - 20);
} }
public dispose(): void { public dispose(): void {
super.dispose(); super.dispose();
for (var optionName in this._optionElements) { for (let optionName in this._optionElements) {
var widget: Widget = this._optionElements[optionName].optionWidget; let widget: Widget = this._optionElements[optionName].optionWidget;
widget.dispose(); widget.dispose();
delete this._optionElements[optionName]; delete this._optionElements[optionName];
} }

View File

@@ -12,7 +12,7 @@ import './panelStyles';
import { TabComponent } from './tab.component'; import { TabComponent } from './tab.component';
import { ScrollableDirective } from 'sql/base/browser/ui/scrollable/scrollable.directive'; import { ScrollableDirective } from 'sql/base/browser/ui/scrollable/scrollable.directive';
import { subscriptionToDisposable } from 'sql/base/common/lifecycle'; import { subscriptionToDisposable } from 'sql/base/node/lifecycle';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { Action } from 'vs/base/common/actions'; import { Action } from 'vs/base/common/actions';

View File

@@ -8,7 +8,7 @@ import { Directive, Inject, forwardRef, ElementRef, Input } from '@angular/core'
import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { ScrollbarVisibility } from 'vs/base/common/scrollable';
import { getContentHeight, addDisposableListener, EventType, getContentWidth } from 'vs/base/browser/dom'; import { getContentHeight, addDisposableListener, EventType, getContentWidth } from 'vs/base/browser/dom';
import { AngularDisposable } from 'sql/base/common/lifecycle'; import { AngularDisposable } from 'sql/base/node/lifecycle';
@Directive({ @Directive({
selector: '[scrollable]' selector: '[scrollable]'
@@ -74,7 +74,7 @@ export class ScrollableDirective extends AngularDisposable {
private resetScrollDimensions() { private resetScrollDimensions() {
this.scrollableElement.setScrollDimensions({ this.scrollableElement.setScrollDimensions({
scrollHeight: this.verticalScroll === ScrollbarVisibility.Auto ? getContentHeight(this.scrolled) : undefined, scrollHeight: this.verticalScroll === ScrollbarVisibility.Auto ? getContentHeight(this.scrolled) : undefined,
height: this.verticalScroll === ScrollbarVisibility.Auto ? getContentHeight(this.parent) : undefined, height: this.verticalScroll === ScrollbarVisibility.Auto ? getContentHeight(this.parent) : undefined,
scrollWidth: this.horizontalScroll === ScrollbarVisibility.Auto ? this.scrolled.scrollWidth : undefined, scrollWidth: this.horizontalScroll === ScrollbarVisibility.Auto ? this.scrolled.scrollWidth : undefined,
width: this.horizontalScroll === ScrollbarVisibility.Auto ? this.scrolled.offsetWidth : undefined width: this.horizontalScroll === ScrollbarVisibility.Auto ? this.scrolled.offsetWidth : undefined
}); });

View File

@@ -6,7 +6,7 @@
import { INextIterator } from 'vs/base/common/iterator'; import { INextIterator } from 'vs/base/common/iterator';
export interface IView { export interface IView {
id: string; id?: string;
} }
export interface IViewItem { export interface IViewItem {

View File

@@ -3,6 +3,11 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
.monaco-scroll-split-view { .split-view-container {
position: relative; position: relative;
} }
.monaco-scroll-split-view {
height: 100%;
width: 100%;
}

View File

@@ -6,35 +6,49 @@
'use strict'; 'use strict';
import 'vs/css!./scrollableSplitview'; import 'vs/css!./scrollableSplitview';
import { HeightMap, IView as HeightIView, IViewItem as HeightIViewItem } from './heightMap';
import { IDisposable, combinedDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { IDisposable, combinedDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { mapEvent, Emitter, Event, debounceEvent } from 'vs/base/common/event'; import { mapEvent, Emitter, Event, debounceEvent } from 'vs/base/common/event';
import * as types from 'vs/base/common/types'; import * as types from 'vs/base/common/types';
import * as dom from 'vs/base/browser/dom'; import * as dom from 'vs/base/browser/dom';
import { clamp } from 'vs/base/common/numbers'; import { clamp } from 'vs/base/common/numbers';
import { range, firstIndex } from 'vs/base/common/arrays'; import { range, firstIndex, pushToStart } from 'vs/base/common/arrays';
import { Sash, Orientation, ISashEvent as IBaseSashEvent } from 'vs/base/browser/ui/sash/sash'; import { Sash, Orientation, ISashEvent as IBaseSashEvent } from 'vs/base/browser/ui/sash/sash';
import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
import { HeightMap, IView as HeightIView, IViewItem as HeightIViewItem } from './heightMap';
import { ArrayIterator } from 'vs/base/common/iterator'; import { ArrayIterator } from 'vs/base/common/iterator';
import { mixin } from 'vs/base/common/objects'; import { mixin } from 'vs/base/common/objects';
import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { ScrollbarVisibility } from 'vs/base/common/scrollable';
import { ISplitViewStyles, Sizing } from 'vs/base/browser/ui/splitview/splitview';
import { Color } from 'vs/base/common/color';
import { domEvent } from 'vs/base/browser/event';
import { generateUuid } from 'vs/base/common/uuid';
export { Orientation } from 'vs/base/browser/ui/sash/sash'; export { Orientation } from 'vs/base/browser/ui/sash/sash';
export interface ISplitViewOptions { export interface ISplitViewOptions {
orientation?: Orientation; // default Orientation.VERTICAL orientation?: Orientation; // default Orientation.VERTICAL
styles?: ISplitViewStyles;
orthogonalStartSash?: Sash;
orthogonalEndSash?: Sash;
inverseAltBehavior?: boolean;
enableResizing?: boolean; enableResizing?: boolean;
scrollDebounce?: number;
verticalScrollbarVisibility?: ScrollbarVisibility; verticalScrollbarVisibility?: ScrollbarVisibility;
} }
const defaultStyles: ISplitViewStyles = {
separatorBorder: Color.transparent
};
const defaultOptions: ISplitViewOptions = { const defaultOptions: ISplitViewOptions = {
enableResizing: true enableResizing: true
}; };
export interface IView extends HeightIView { export interface IView extends HeightIView {
readonly element: HTMLElement;
readonly minimumSize: number; readonly minimumSize: number;
readonly maximumSize: number; readonly maximumSize: number;
readonly onDidChange: Event<number | undefined>; readonly onDidChange: Event<number | undefined>;
render(container: HTMLElement, orientation: Orientation): void;
layout(size: number, orientation: Orientation): void; layout(size: number, orientation: Orientation): void;
onAdd?(): void; onAdd?(): void;
onRemove?(): void; onRemove?(): void;
@@ -44,6 +58,7 @@ interface ISashEvent {
sash: Sash; sash: Sash;
start: number; start: number;
current: number; current: number;
alt: boolean;
} }
interface IViewItem extends HeightIViewItem { interface IViewItem extends HeightIViewItem {
@@ -64,7 +79,12 @@ interface ISashItem {
interface ISashDragState { interface ISashDragState {
index: number; index: number;
start: number; start: number;
current: number;
sizes: number[]; sizes: number[];
minDelta: number;
maxDelta: number;
alt: boolean;
disposable: IDisposable;
} }
enum State { enum State {
@@ -95,24 +115,28 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
private orientation: Orientation; private orientation: Orientation;
private el: HTMLElement; private el: HTMLElement;
private sashContainer: HTMLElement;
private viewContainer: HTMLElement;
private scrollable: ScrollableElement;
private size = 0; private size = 0;
private contentSize = 0; private contentSize = 0;
private proportions: undefined | number[] = undefined;
private viewItems: IViewItem[] = []; private viewItems: IViewItem[] = [];
private sashItems: ISashItem[] = []; private sashItems: ISashItem[] = [];
private sashDragState: ISashDragState; private sashDragState: ISashDragState;
private state: State = State.Idle; private state: State = State.Idle;
private scrollable: ScrollableElement; private inverseAltBehavior: boolean;
private lastRenderHeight: number;
private lastRenderTop: number;
private options: ISplitViewOptions; private options: ISplitViewOptions;
private dirtyState = false; private dirtyState = false;
private lastRenderTop: number; private _onDidSashChange = new Emitter<number>();
private lastRenderHeight: number;
private _onDidSashChange = new Emitter<void>();
readonly onDidSashChange = this._onDidSashChange.event; readonly onDidSashChange = this._onDidSashChange.event;
private _onDidSashReset = new Emitter<void>(); private _onDidSashReset = new Emitter<number>();
readonly onDidSashReset = this._onDidSashReset.event; readonly onDidSashReset = this._onDidSashReset.event;
private _onScroll = new Emitter<number>(); private _onScroll = new Emitter<number>();
@@ -122,15 +146,48 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
return this.viewItems.length; return this.viewItems.length;
} }
get minimumSize(): number {
return this.viewItems.reduce((r, item) => r + item.view.minimumSize, 0);
}
get maximumSize(): number {
return this.length === 0 ? Number.POSITIVE_INFINITY : this.viewItems.reduce((r, item) => r + item.view.maximumSize, 0);
}
private _orthogonalStartSash: Sash | undefined;
get orthogonalStartSash(): Sash | undefined { return this._orthogonalStartSash; }
set orthogonalStartSash(sash: Sash | undefined) {
for (const sashItem of this.sashItems) {
sashItem.sash.orthogonalStartSash = sash;
}
this._orthogonalStartSash = sash;
}
private _orthogonalEndSash: Sash | undefined;
get orthogonalEndSash(): Sash | undefined { return this._orthogonalEndSash; }
set orthogonalEndSash(sash: Sash | undefined) {
for (const sashItem of this.sashItems) {
sashItem.sash.orthogonalEndSash = sash;
}
this._orthogonalEndSash = sash;
}
get sashes(): Sash[] {
return this.sashItems.map(s => s.sash);
}
constructor(container: HTMLElement, options: ISplitViewOptions = {}) { constructor(container: HTMLElement, options: ISplitViewOptions = {}) {
super(); super();
this.orientation = types.isUndefined(options.orientation) ? Orientation.VERTICAL : options.orientation; this.orientation = types.isUndefined(options.orientation) ? Orientation.VERTICAL : options.orientation;
this.inverseAltBehavior = !!options.inverseAltBehavior;
this.options = mixin(options, defaultOptions, false); this.options = mixin(options, defaultOptions, false);
this.el = document.createElement('div'); this.el = document.createElement('div');
this.scrollable = new ScrollableElement(this.el, { vertical: options.verticalScrollbarVisibility }); this.scrollable = new ScrollableElement(this.el, { vertical: options.verticalScrollbarVisibility });
debounceEvent(this.scrollable.onScroll, (l, e) => e, 25)(e => { debounceEvent(this.scrollable.onScroll, (l, e) => e, types.isNumber(this.options.scrollDebounce) ? this.options.scrollDebounce : 25)(e => {
this.render(e.scrollTop, e.height); this.render(e.scrollTop, e.height);
this.relayout(); this.relayout();
this._onScroll.fire(e.scrollTop); this._onScroll.fire(e.scrollTop);
@@ -140,9 +197,24 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
dom.addClass(domNode, 'monaco-split-view2'); dom.addClass(domNode, 'monaco-split-view2');
dom.addClass(domNode, this.orientation === Orientation.VERTICAL ? 'vertical' : 'horizontal'); dom.addClass(domNode, this.orientation === Orientation.VERTICAL ? 'vertical' : 'horizontal');
container.appendChild(domNode); container.appendChild(domNode);
this.sashContainer = dom.append(this.el, dom.$('.sash-container'));
this.viewContainer = dom.append(this.el, dom.$('.split-view-container'));
this.style(options.styles || defaultStyles);
} }
addViews(views: IView[], sizes: number[], index = this.viewItems.length): void { style(styles: ISplitViewStyles): void {
if (styles.separatorBorder.isTransparent()) {
dom.removeClass(this.el, 'separator-border');
this.el.style.removeProperty('--separator-border');
} else {
dom.addClass(this.el, 'separator-border');
this.el.style.setProperty('--separator-border', styles.separatorBorder.toString());
}
}
addViews(views: IView[], sizes: number[] | Sizing, index = this.viewItems.length): void {
if (this.state !== State.Idle) { if (this.state !== State.Idle) {
throw new Error('Cant modify splitview'); throw new Error('Cant modify splitview');
} }
@@ -150,16 +222,23 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
this.state = State.Busy; this.state = State.Busy;
for (let i = 0; i < views.length; i++) { for (let i = 0; i < views.length; i++) {
let viewIndex = index + i; let size: number | Sizing;
let view = views[i], size = sizes[i]; if (Array.isArray(sizes)) {
size = sizes[i];
} else {
size = sizes;
}
const view = views[i];
view.id = view.id || generateUuid();
// Add view // Add view
const container = dom.$('.split-view-view'); const container = dom.$('.split-view-view');
// removed default adding of the view directly to the container
const onChangeDisposable = view.onDidChange(size => this.onViewChange(item, size)); const onChangeDisposable = view.onDidChange(size => this.onViewChange(item, size));
const containerDisposable = toDisposable(() => { const containerDisposable = toDisposable(() => {
if (container.parentElement) { if (container.parentElement) {
this.el.removeChild(container); this.viewContainer.removeChild(container);
} }
this.onRemoveItems(new ArrayIterator([item.view.id])); this.onRemoveItems(new ArrayIterator([item.view.id]));
}); });
@@ -169,65 +248,91 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
const onRemove = view.onRemove ? () => view.onRemove() : () => { }; const onRemove = view.onRemove ? () => view.onRemove() : () => { };
const layoutContainer = this.orientation === Orientation.VERTICAL const layoutContainer = this.orientation === Orientation.VERTICAL
? size => item.container.style.height = `${item.size}px` ? () => item.container.style.height = `${item.size}px`
: size => item.container.style.width = `${item.size}px`; : () => item.container.style.width = `${item.size}px`;
const layout = () => { const layout = () => {
layoutContainer(item.size); layoutContainer();
item.view.layout(item.size, this.orientation); item.view.layout(item.size, this.orientation);
}; };
size = Math.round(size); let viewSize: number;
const item: IViewItem = { onRemove, onAdd, view, container, size, layout, disposable, height: size, top: 0, width: 0 };
this.viewItems.splice(viewIndex, 0, item);
this.onInsertItems(new ArrayIterator([item]), viewIndex > 0 ? this.viewItems[viewIndex - 1].view.id : undefined); if (typeof size === 'number') {
viewSize = size;
} else if (size.type === 'split') {
viewSize = this.getViewSize(size.index) / 2;
} else {
viewSize = view.minimumSize;
}
const item: IViewItem = { onAdd, onRemove, view, container, size: viewSize, layout, disposable, height: viewSize, top: 0, width: 0 };
this.viewItems.splice(index, 0, item);
this.onInsertItems(new ArrayIterator([item]), index > 0 ? this.viewItems[index - 1].view.id : undefined);
// Add sash // Add sash
if (this.options.enableResizing && this.viewItems.length > 1) { if (this.options.enableResizing && this.viewItems.length > 1) {
const orientation = this.orientation === Orientation.VERTICAL ? Orientation.HORIZONTAL : Orientation.VERTICAL; const orientation = this.orientation === Orientation.VERTICAL ? Orientation.HORIZONTAL : Orientation.VERTICAL;
const layoutProvider = this.orientation === Orientation.VERTICAL ? { getHorizontalSashTop: sash => this.getSashPosition(sash) } : { getVerticalSashLeft: sash => this.getSashPosition(sash) }; const layoutProvider = this.orientation === Orientation.VERTICAL ? { getHorizontalSashTop: sash => this.getSashPosition(sash) } : { getVerticalSashLeft: sash => this.getSashPosition(sash) };
const sash = new Sash(this.el, layoutProvider, { orientation }); const sash = new Sash(this.sashContainer, layoutProvider, {
orientation,
orthogonalStartSash: this.orthogonalStartSash,
orthogonalEndSash: this.orthogonalEndSash
});
const sashEventMapper = this.orientation === Orientation.VERTICAL const sashEventMapper = this.orientation === Orientation.VERTICAL
? (e: IBaseSashEvent) => ({ sash, start: e.startY, current: e.currentY }) ? (e: IBaseSashEvent) => ({ sash, start: e.startY, current: e.currentY, alt: e.altKey } as ISashEvent)
: (e: IBaseSashEvent) => ({ sash, start: e.startX, current: e.currentX }); : (e: IBaseSashEvent) => ({ sash, start: e.startX, current: e.currentX, alt: e.altKey } as ISashEvent);
const onStart = mapEvent(sash.onDidStart, sashEventMapper); const onStart = mapEvent(sash.onDidStart, sashEventMapper);
const onStartDisposable = onStart(this.onSashStart, this); const onStartDisposable = onStart(this.onSashStart, this);
const onChange = mapEvent(sash.onDidChange, sashEventMapper); const onChange = mapEvent(sash.onDidChange, sashEventMapper);
const onSashChangeDisposable = onChange(this.onSashChange, this); const onChangeDisposable = onChange(this.onSashChange, this);
const onEnd = mapEvent<void, void>(sash.onDidEnd, () => null); const onEnd = mapEvent(sash.onDidEnd, () => firstIndex(this.sashItems, item => item.sash === sash));
const onEndDisposable = onEnd(() => this._onDidSashChange.fire()); const onEndDisposable = onEnd(this.onSashEnd, this);
const onDidReset = mapEvent<void, void>(sash.onDidReset, () => null); const onDidResetDisposable = sash.onDidReset(() => this._onDidSashReset.fire(firstIndex(this.sashItems, item => item.sash === sash)));
const onDidResetDisposable = onDidReset(() => this._onDidSashReset.fire());
const disposable = combinedDisposable([onStartDisposable, onSashChangeDisposable, onEndDisposable, onDidResetDisposable, sash]); const disposable = combinedDisposable([onStartDisposable, onChangeDisposable, onEndDisposable, onDidResetDisposable, sash]);
const sashItem: ISashItem = { sash, disposable }; const sashItem: ISashItem = { sash, disposable };
this.sashItems.splice(viewIndex - 1, 0, sashItem); this.sashItems.splice(index - 1, 0, sashItem);
} }
view.render(container, this.orientation); container.appendChild(view.element);
} }
this.relayout(); let highPriorityIndex: number | undefined;
if (!types.isArray(sizes) && sizes.type === 'split') {
highPriorityIndex = sizes.index;
}
this.relayout(index, highPriorityIndex);
this.state = State.Idle; this.state = State.Idle;
if (!types.isArray(sizes) && sizes.type === 'distribute') {
this.distributeViewSizes();
}
} }
addView(view: IView, size: number, index = this.viewItems.length): void { addView(view: IView, size: number | Sizing, index = this.viewItems.length): void {
if (this.state !== State.Idle) { if (this.state !== State.Idle) {
throw new Error('Cant modify splitview'); throw new Error('Cant modify splitview');
} }
this.state = State.Busy; this.state = State.Busy;
view.id = view.id || generateUuid();
// Add view // Add view
const container = dom.$('.split-view-view'); const container = dom.$('.split-view-view');
// removed default adding of the view directly to the container
const onChangeDisposable = view.onDidChange(size => this.onViewChange(item, size)); const onChangeDisposable = view.onDidChange(size => this.onViewChange(item, size));
const containerDisposable = toDisposable(() => { const containerDisposable = toDisposable(() => {
if (container.parentElement) { if (container.parentElement) {
this.el.removeChild(container); this.viewContainer.removeChild(container);
} }
this.onRemoveItems(new ArrayIterator([item.view.id])); this.onRemoveItems(new ArrayIterator([item.view.id]));
}); });
@@ -237,16 +342,25 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
const onRemove = view.onRemove ? () => view.onRemove() : () => { }; const onRemove = view.onRemove ? () => view.onRemove() : () => { };
const layoutContainer = this.orientation === Orientation.VERTICAL const layoutContainer = this.orientation === Orientation.VERTICAL
? size => item.container.style.height = `${item.size}px` ? () => item.container.style.height = `${item.size}px`
: size => item.container.style.width = `${item.size}px`; : () => item.container.style.width = `${item.size}px`;
const layout = () => { const layout = () => {
layoutContainer(item.size); layoutContainer();
item.view.layout(item.size, this.orientation); item.view.layout(item.size, this.orientation);
}; };
size = Math.round(size); let viewSize: number;
const item: IViewItem = { onAdd, onRemove, view, container, size, layout, disposable, height: size, top: 0, width: 0 };
if (typeof size === 'number') {
viewSize = size;
} else if (size.type === 'split') {
viewSize = this.getViewSize(size.index) / 2;
} else {
viewSize = view.minimumSize;
}
const item: IViewItem = { onAdd, onRemove, view, container, size: viewSize, layout, disposable, height: viewSize, top: 0, width: 0 };
this.viewItems.splice(index, 0, item); this.viewItems.splice(index, 0, item);
this.onInsertItems(new ArrayIterator([item]), index > 0 ? this.viewItems[index - 1].view.id : undefined); this.onInsertItems(new ArrayIterator([item]), index > 0 ? this.viewItems[index - 1].view.id : undefined);
@@ -255,33 +369,47 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
if (this.options.enableResizing && this.viewItems.length > 1) { if (this.options.enableResizing && this.viewItems.length > 1) {
const orientation = this.orientation === Orientation.VERTICAL ? Orientation.HORIZONTAL : Orientation.VERTICAL; const orientation = this.orientation === Orientation.VERTICAL ? Orientation.HORIZONTAL : Orientation.VERTICAL;
const layoutProvider = this.orientation === Orientation.VERTICAL ? { getHorizontalSashTop: sash => this.getSashPosition(sash) } : { getVerticalSashLeft: sash => this.getSashPosition(sash) }; const layoutProvider = this.orientation === Orientation.VERTICAL ? { getHorizontalSashTop: sash => this.getSashPosition(sash) } : { getVerticalSashLeft: sash => this.getSashPosition(sash) };
const sash = new Sash(this.el, layoutProvider, { orientation }); const sash = new Sash(this.sashContainer, layoutProvider, {
orientation,
orthogonalStartSash: this.orthogonalStartSash,
orthogonalEndSash: this.orthogonalEndSash
});
const sashEventMapper = this.orientation === Orientation.VERTICAL const sashEventMapper = this.orientation === Orientation.VERTICAL
? (e: IBaseSashEvent) => ({ sash, start: e.startY, current: e.currentY }) ? (e: IBaseSashEvent) => ({ sash, start: e.startY, current: e.currentY, alt: e.altKey } as ISashEvent)
: (e: IBaseSashEvent) => ({ sash, start: e.startX, current: e.currentX }); : (e: IBaseSashEvent) => ({ sash, start: e.startX, current: e.currentX, alt: e.altKey } as ISashEvent);
const onStart = mapEvent(sash.onDidStart, sashEventMapper); const onStart = mapEvent(sash.onDidStart, sashEventMapper);
const onStartDisposable = onStart(this.onSashStart, this); const onStartDisposable = onStart(this.onSashStart, this);
const onChange = mapEvent(sash.onDidChange, sashEventMapper); const onChange = mapEvent(sash.onDidChange, sashEventMapper);
const onSashChangeDisposable = onChange(this.onSashChange, this); const onChangeDisposable = onChange(this.onSashChange, this);
const onEnd = mapEvent<void, void>(sash.onDidEnd, () => null); const onEnd = mapEvent(sash.onDidEnd, () => firstIndex(this.sashItems, item => item.sash === sash));
const onEndDisposable = onEnd(() => this._onDidSashChange.fire()); const onEndDisposable = onEnd(this.onSashEnd, this);
const onDidReset = mapEvent<void, void>(sash.onDidReset, () => null); const onDidResetDisposable = sash.onDidReset(() => this._onDidSashReset.fire(firstIndex(this.sashItems, item => item.sash === sash)));
const onDidResetDisposable = onDidReset(() => this._onDidSashReset.fire());
const disposable = combinedDisposable([onStartDisposable, onSashChangeDisposable, onEndDisposable, onDidResetDisposable, sash]); const disposable = combinedDisposable([onStartDisposable, onChangeDisposable, onEndDisposable, onDidResetDisposable, sash]);
const sashItem: ISashItem = { sash, disposable }; const sashItem: ISashItem = { sash, disposable };
sash.hide();
this.sashItems.splice(index - 1, 0, sashItem); this.sashItems.splice(index - 1, 0, sashItem);
} }
view.render(container, this.orientation); container.appendChild(view.element);
this.relayout(index);
let highPriorityIndex: number | undefined;
if (typeof size !== 'number' && size.type === 'split') {
highPriorityIndex = size.index;
}
this.relayout(index, highPriorityIndex);
this.state = State.Idle; this.state = State.Idle;
if (typeof size !== 'number' && size.type === 'distribute') {
this.distributeViewSizes();
}
} }
removeView(index: number): void { removeView(index: number, sizing?: Sizing): IView {
if (this.state !== State.Idle) { if (this.state !== State.Idle) {
throw new Error('Cant modify splitview'); throw new Error('Cant modify splitview');
} }
@@ -289,7 +417,7 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
this.state = State.Busy; this.state = State.Busy;
if (index < 0 || index >= this.viewItems.length) { if (index < 0 || index >= this.viewItems.length) {
return; throw new Error('Index out of bounds');
} }
// Remove view // Remove view
@@ -301,12 +429,16 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
const sashIndex = Math.max(index - 1, 0); const sashIndex = Math.max(index - 1, 0);
const sashItem = this.sashItems.splice(sashIndex, 1)[0]; const sashItem = this.sashItems.splice(sashIndex, 1)[0];
sashItem.disposable.dispose(); sashItem.disposable.dispose();
} else {
this.lastRenderHeight = NaN, this.lastRenderTop = NaN;
} }
this.relayout(); this.relayout();
this.state = State.Idle; this.state = State.Idle;
if (sizing && sizing.type === 'distribute') {
this.distributeViewSizes();
}
return viewItem.view;
} }
moveView(from: number, to: number): void { moveView(from: number, to: number): void {
@@ -314,36 +446,36 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
throw new Error('Cant modify splitview'); throw new Error('Cant modify splitview');
} }
this.state = State.Busy; const size = this.getViewSize(from);
const view = this.removeView(from);
if (from < 0 || from >= this.viewItems.length) { this.addView(view, size, to);
return;
}
if (to < 0 || to >= this.viewItems.length) {
return;
}
if (from === to) {
return;
}
const viewItem = this.viewItems.splice(from, 1)[0];
this.viewItems.splice(to, 0, viewItem);
if (to + 1 < this.viewItems.length) {
this.el.insertBefore(viewItem.container, this.viewItems[to + 1].container);
} else {
this.el.appendChild(viewItem.container);
}
this.layoutViews();
this.state = State.Idle;
} }
private relayout(lowPriorityIndex?: number): void { swapViews(from: number, to: number): void {
if (this.state !== State.Idle) {
throw new Error('Cant modify splitview');
}
if (from > to) {
return this.swapViews(to, from);
}
const fromSize = this.getViewSize(from);
const toSize = this.getViewSize(to);
const toView = this.removeView(to);
const fromView = this.removeView(from);
this.addView(toView, fromSize, from);
this.addView(fromView, toSize, to);
}
private relayout(lowPriorityIndex?: number, highPriorityIndex?: number): void {
const contentSize = this.viewItems.reduce((r, i) => r + i.size, 0); const contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
this.resize(this.viewItems.length - 1, this.size - contentSize, undefined, lowPriorityIndex);
this.resize(this.viewItems.length - 1, this.size - contentSize, undefined, lowPriorityIndex, highPriorityIndex);
this.distributeEmptySpace();
this.layoutViews();
this.saveProportions();
} }
public setScrollPosition(position: number) { public setScrollPosition(position: number) {
@@ -351,14 +483,188 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
} }
layout(size: number): void { layout(size: number): void {
const previousSize = this.size; const previousSize = Math.max(this.size, this.contentSize);
this.size = size; this.size = size;
this.contentSize = 0; this.contentSize = 0;
this.lastRenderHeight = undefined; this.lastRenderHeight = undefined;
this.lastRenderTop = undefined; this.lastRenderTop = undefined;
this.resize(this.viewItems.length - 1, size - previousSize);
if (!this.proportions) {
this.resize(this.viewItems.length - 1, size - previousSize);
} else {
for (let i = 0; i < this.viewItems.length; i++) {
const item = this.viewItems[i];
item.size = clamp(Math.round(this.proportions[i] * size), item.view.minimumSize, item.view.maximumSize);
}
}
this.distributeEmptySpace();
this.layoutViews();
} }
private saveProportions(): void {
if (this.contentSize > 0) {
this.proportions = this.viewItems.map(i => i.size / this.contentSize);
}
}
private onSashStart({ sash, start, alt }: ISashEvent): void {
const index = firstIndex(this.sashItems, item => item.sash === sash);
// This way, we can press Alt while we resize a sash, macOS style!
const disposable = combinedDisposable([
domEvent(document.body, 'keydown')(e => resetSashDragState(this.sashDragState.current, e.altKey)),
domEvent(document.body, 'keyup')(() => resetSashDragState(this.sashDragState.current, false))
]);
const resetSashDragState = (start: number, alt: boolean) => {
const sizes = this.viewItems.map(i => i.size);
let minDelta = Number.NEGATIVE_INFINITY;
let maxDelta = Number.POSITIVE_INFINITY;
if (this.inverseAltBehavior) {
alt = !alt;
}
if (alt) {
// When we're using the last sash with Alt, we're resizing
// the view to the left/up, instead of right/down as usual
// Thus, we must do the inverse of the usual
const isLastSash = index === this.sashItems.length - 1;
if (isLastSash) {
const viewItem = this.viewItems[index];
minDelta = (viewItem.view.minimumSize - viewItem.size) / 2;
maxDelta = (viewItem.view.maximumSize - viewItem.size) / 2;
} else {
const viewItem = this.viewItems[index + 1];
minDelta = (viewItem.size - viewItem.view.maximumSize) / 2;
maxDelta = (viewItem.size - viewItem.view.minimumSize) / 2;
}
}
this.sashDragState = { start, current: start, index, sizes, minDelta, maxDelta, alt, disposable };
};
resetSashDragState(start, alt);
}
private onSashChange({ current }: ISashEvent): void {
const { index, start, sizes, alt, minDelta, maxDelta } = this.sashDragState;
this.sashDragState.current = current;
const delta = current - start;
const newDelta = this.resize(index, delta, sizes, undefined, undefined, minDelta, maxDelta);
if (alt) {
const isLastSash = index === this.sashItems.length - 1;
const newSizes = this.viewItems.map(i => i.size);
const viewItemIndex = isLastSash ? index : index + 1;
const viewItem = this.viewItems[viewItemIndex];
const newMinDelta = viewItem.size - viewItem.view.maximumSize;
const newMaxDelta = viewItem.size - viewItem.view.minimumSize;
const resizeIndex = isLastSash ? index - 1 : index + 1;
this.resize(resizeIndex, -newDelta, newSizes, undefined, undefined, newMinDelta, newMaxDelta);
}
this.distributeEmptySpace();
this.layoutViews();
}
private onSashEnd(index: number): void {
this._onDidSashChange.fire(index);
this.sashDragState.disposable.dispose();
this.saveProportions();
}
private onViewChange(item: IViewItem, size: number | undefined): void {
const index = this.viewItems.indexOf(item);
if (index < 0 || index >= this.viewItems.length) {
return;
}
size = typeof size === 'number' ? size : item.size;
size = clamp(size, item.view.minimumSize, item.view.maximumSize);
if (this.inverseAltBehavior && index > 0) {
// In this case, we want the view to grow or shrink both sides equally
// so we just resize the "left" side by half and let `resize` do the clamping magic
this.resize(index - 1, Math.floor((item.size - size) / 2));
this.distributeEmptySpace();
this.layoutViews();
} else {
item.size = size;
this.updateSize(item.view.id, size);
let top = item.top + item.size;
for (let i = index + 1; i < this.viewItems.length; i++) {
let currentItem = this.viewItems[i];
this.updateTop(currentItem.view.id, top);
top += currentItem.size;
}
this.relayout(index);
}
}
resizeView(index: number, size: number): void {
if (this.state !== State.Idle) {
throw new Error('Cant modify splitview');
}
this.state = State.Busy;
if (index < 0 || index >= this.viewItems.length) {
return;
}
const item = this.viewItems[index];
size = Math.round(size);
size = clamp(size, item.view.minimumSize, item.view.maximumSize);
let delta = size - item.size;
if (delta !== 0 && index < this.viewItems.length - 1) {
const downIndexes = range(index + 1, this.viewItems.length);
const collapseDown = downIndexes.reduce((r, i) => r + (this.viewItems[i].size - this.viewItems[i].view.minimumSize), 0);
const expandDown = downIndexes.reduce((r, i) => r + (this.viewItems[i].view.maximumSize - this.viewItems[i].size), 0);
const deltaDown = clamp(delta, -expandDown, collapseDown);
this.resize(index, deltaDown);
delta -= deltaDown;
}
if (delta !== 0 && index > 0) {
const upIndexes = range(index - 1, -1);
const collapseUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].size - this.viewItems[i].view.minimumSize), 0);
const expandUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].view.maximumSize - this.viewItems[i].size), 0);
const deltaUp = clamp(-delta, -collapseUp, expandUp);
this.resize(index - 1, deltaUp);
}
this.distributeEmptySpace();
this.layoutViews();
this.saveProportions();
this.state = State.Idle;
}
distributeViewSizes(): void {
const size = Math.floor(this.size / this.viewItems.length);
for (let i = 0; i < this.viewItems.length - 1; i++) {
this.resizeView(i, size);
}
}
getViewSize(index: number): number {
if (index < 0 || index >= this.viewItems.length) {
return -1;
}
return this.viewItems[index].size;
}
private render(scrollTop: number, viewHeight: number): void { private render(scrollTop: number, viewHeight: number): void {
let i: number; let i: number;
let stop: number; let stop: number;
@@ -398,96 +704,13 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
let topItem = this.itemAtIndex(this.indexAt(renderTop)); let topItem = this.itemAtIndex(this.indexAt(renderTop));
if (topItem) { if (topItem) {
this.el.style.top = (topItem.top - renderTop) + 'px'; this.viewContainer.style.top = (topItem.top - renderTop) + 'px';
} }
this.lastRenderTop = renderTop; this.lastRenderTop = renderTop;
this.lastRenderHeight = renderBottom - renderTop; this.lastRenderHeight = renderBottom - renderTop;
} }
private onSashStart({ sash, start }: ISashEvent): void {
const index = firstIndex(this.sashItems, item => item.sash === sash);
const sizes = this.viewItems.map(i => i.size);
// const upIndexes = range(index, -1);
// const collapseUp = upIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].view.minimumSize), 0);
// const expandUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].view.maximumSize - sizes[i]), 0);
// const downIndexes = range(index + 1, this.viewItems.length);
// const collapseDown = downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].view.minimumSize), 0);
// const expandDown = downIndexes.reduce((r, i) => r + (this.viewItems[i].view.maximumSize - sizes[i]), 0);
// const minDelta = -Math.min(collapseUp, expandDown);
// const maxDelta = Math.min(collapseDown, expandUp);
this.sashDragState = { start, index, sizes };
}
private onSashChange({ sash, current }: ISashEvent): void {
const { index, start, sizes } = this.sashDragState;
const delta = current - start;
this.resize(index, delta, sizes);
}
private onViewChange(item: IViewItem, size: number | undefined): void {
const index = this.viewItems.indexOf(item);
if (index < 0 || index >= this.viewItems.length) {
return;
}
size = typeof size === 'number' ? size : item.size;
size = clamp(size, item.view.minimumSize, item.view.maximumSize);
item.size = size;
this.updateSize(item.view.id, size);
let top = item.top + item.size;
for (let i = index + 1; i < this.viewItems.length; i++) {
let currentItem = this.viewItems[i];
this.updateTop(currentItem.view.id, top);
top += currentItem.size;
}
this.relayout(index);
}
resizeView(index: number, size: number): void {
if (this.state !== State.Idle) {
throw new Error('Cant modify splitview');
}
this.state = State.Busy;
if (index < 0 || index >= this.viewItems.length) {
return;
}
const item = this.viewItems[index];
size = Math.round(size);
size = clamp(size, item.view.minimumSize, item.view.maximumSize);
let delta = size - item.size;
if (delta !== 0 && index < this.viewItems.length - 1) {
const downIndexes = range(index + 1, this.viewItems.length);
const collapseDown = downIndexes.reduce((r, i) => r + (this.viewItems[i].size - this.viewItems[i].view.minimumSize), 0);
const expandDown = downIndexes.reduce((r, i) => r + (this.viewItems[i].view.maximumSize - this.viewItems[i].size), 0);
const deltaDown = clamp(delta, -expandDown, collapseDown);
this.resize(index, deltaDown);
delta -= deltaDown;
}
if (delta !== 0 && index > 0) {
const upIndexes = range(index - 1, -1);
const collapseUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].size - this.viewItems[i].view.minimumSize), 0);
const expandUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].view.maximumSize - this.viewItems[i].size), 0);
const deltaUp = clamp(-delta, -collapseUp, expandUp);
this.resize(index - 1, deltaUp);
}
this.state = State.Idle;
}
// DOM changes // DOM changes
private insertItemInDOM(item: IViewItem): boolean { private insertItemInDOM(item: IViewItem): boolean {
@@ -503,13 +726,13 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
} }
if (elementAfter === null) { if (elementAfter === null) {
this.el.appendChild(item.container); this.viewContainer.appendChild(item.container);
} else { } else {
try { try {
this.el.insertBefore(item.container, elementAfter); this.viewContainer.insertBefore(item.container, elementAfter);
} catch (e) { } catch (e) {
// console.warn('Failed to locate previous tree element'); // console.warn('Failed to locate previous tree element');
this.el.appendChild(item.container); this.viewContainer.appendChild(item.container);
} }
} }
@@ -524,85 +747,94 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
return false; return false;
} }
this.el.removeChild(item.container); this.viewContainer.removeChild(item.container);
item.onRemove(); item.onRemove();
return true; return true;
} }
getViewSize(index: number): number { private resize(
index: number,
delta: number,
sizes = this.viewItems.map(i => i.size),
lowPriorityIndex?: number,
highPriorityIndex?: number,
overloadMinDelta: number = Number.NEGATIVE_INFINITY,
overloadMaxDelta: number = Number.POSITIVE_INFINITY
): number {
if (index < 0 || index >= this.viewItems.length) { if (index < 0 || index >= this.viewItems.length) {
return -1; return 0;
} }
return this.viewItems[index].size; const upIndexes = range(index, -1);
const downIndexes = range(index + 1, this.viewItems.length);
if (typeof highPriorityIndex === 'number') {
pushToStart(upIndexes, highPriorityIndex);
pushToStart(downIndexes, highPriorityIndex);
}
if (typeof lowPriorityIndex === 'number') {
pushToEnd(upIndexes, lowPriorityIndex);
pushToEnd(downIndexes, lowPriorityIndex);
}
const upItems = upIndexes.map(i => this.viewItems[i]);
const upSizes = upIndexes.map(i => sizes[i]);
const downItems = downIndexes.map(i => this.viewItems[i]);
const downSizes = downIndexes.map(i => sizes[i]);
const minDeltaUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].view.minimumSize - sizes[i]), 0);
const maxDeltaUp = upIndexes.reduce((r, i) => r + (this.viewItems[i].view.maximumSize - sizes[i]), 0);
const maxDeltaDown = downIndexes.length === 0 ? Number.POSITIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].view.minimumSize), 0);
const minDeltaDown = downIndexes.length === 0 ? Number.NEGATIVE_INFINITY : downIndexes.reduce((r, i) => r + (sizes[i] - this.viewItems[i].view.maximumSize), 0);
const minDelta = Math.max(minDeltaUp, minDeltaDown, overloadMinDelta);
const maxDelta = Math.min(maxDeltaDown, maxDeltaUp, overloadMaxDelta);
delta = clamp(delta, minDelta, maxDelta);
for (let i = 0, deltaUp = delta; i < upItems.length; i++) {
const item = upItems[i];
const size = clamp(upSizes[i] + deltaUp, item.view.minimumSize, item.view.maximumSize);
const viewDelta = size - upSizes[i];
deltaUp -= viewDelta;
item.size = size;
this.dirtyState = true;
}
for (let i = 0, deltaDown = delta; i < downItems.length; i++) {
const item = downItems[i];
const size = clamp(downSizes[i] - deltaDown, item.view.minimumSize, item.view.maximumSize);
const viewDelta = size - downSizes[i];
deltaDown += viewDelta;
item.size = size;
this.dirtyState = true;
}
return delta;
} }
private resize(index: number, delta: number, sizes = this.viewItems.map(i => i.size), lowPriorityIndex?: number): void { private distributeEmptySpace(): void {
if (index < 0 || index >= this.viewItems.length) {
return;
}
if (delta !== 0) {
let upIndexes = range(index, -1);
let downIndexes = range(index + 1, this.viewItems.length);
if (typeof lowPriorityIndex === 'number') {
upIndexes = pushToEnd(upIndexes, lowPriorityIndex);
downIndexes = pushToEnd(downIndexes, lowPriorityIndex);
}
const upItems = upIndexes.map(i => this.viewItems[i]);
const upSizes = upIndexes.map(i => sizes[i]);
const downItems = downIndexes.map(i => this.viewItems[i]);
const downSizes = downIndexes.map(i => sizes[i]);
for (let i = 0, deltaUp = delta; deltaUp !== 0 && i < upItems.length; i++) {
const item = upItems[i];
const size = clamp(upSizes[i] + deltaUp, item.view.minimumSize, item.view.maximumSize);
const viewDelta = size - upSizes[i];
deltaUp -= viewDelta;
item.size = size;
this.dirtyState = true;
}
for (let i = 0, deltaDown = delta; deltaDown !== 0 && i < downItems.length; i++) {
const item = downItems[i];
const size = clamp(downSizes[i] - deltaDown, item.view.minimumSize, item.view.maximumSize);
const viewDelta = size - downSizes[i];
deltaDown += viewDelta;
item.size = size;
this.dirtyState = true;
}
}
let contentSize = this.viewItems.reduce((r, i) => r + i.size, 0); let contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
let emptyDelta = this.size - contentSize; let emptyDelta = this.size - contentSize;
for (let i = this.viewItems.length - 1; emptyDelta > 0 && i >= 0; i--) { for (let i = this.viewItems.length - 1; emptyDelta !== 0 && i >= 0; i--) {
const item = this.viewItems[i]; const item = this.viewItems[i];
const size = clamp(item.size + emptyDelta, item.view.minimumSize, item.view.maximumSize); const size = clamp(item.size + emptyDelta, item.view.minimumSize, item.view.maximumSize);
const viewDelta = size - item.size; const viewDelta = size - item.size;
emptyDelta -= viewDelta; emptyDelta -= viewDelta;
item.size = size; item.size = size;
this.dirtyState = true;
} }
this.contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
this.scrollable.setScrollDimensions({
scrollHeight: this.contentSize,
height: this.size
});
this.layoutViews();
} }
private layoutViews(): void { private layoutViews(): void {
// Save new content size
this.contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
if (this.dirtyState) { if (this.dirtyState) {
for (let i = this.indexAt(this.lastRenderTop); i <= this.indexAfter(this.lastRenderTop + this.lastRenderHeight) - 1; i++) { for (let i = this.indexAt(this.lastRenderTop); i <= this.indexAfter(this.lastRenderTop + this.lastRenderHeight) - 1; i++) {
this.viewItems[i].layout(); this.viewItems[i].layout();
@@ -613,27 +845,10 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
this.dirtyState = false; this.dirtyState = false;
} }
// Update sashes enablement this.scrollable.setScrollDimensions({
// let previous = false; scrollHeight: this.contentSize,
// const collapsesDown = this.viewItems.map(i => previous = (i.size - i.view.minimumSize > 0) || previous); height: this.size
});
// previous = false;
// const expandsDown = this.viewItems.map(i => previous = (i.view.maximumSize - i.size > 0) || previous);
// const reverseViews = [...this.viewItems].reverse();
// previous = false;
// const collapsesUp = reverseViews.map(i => previous = (i.size - i.view.minimumSize > 0) || previous).reverse();
// previous = false;
// const expandsUp = reverseViews.map(i => previous = (i.view.maximumSize - i.size > 0) || previous).reverse();
// this.sashItems.forEach((s, i) => {
// if ((collapsesDown[i] && expandsUp[i + 1]) || (expandsDown[i] && collapsesUp[i + 1])) {
// s.sash.enable();
// } else {
// s.sash.disable();
// }
// });
} }
private getSashPosition(sash: Sash): number { private getSashPosition(sash: Sash): number {

View File

@@ -11,7 +11,7 @@ import {
} from '@angular/core'; } from '@angular/core';
import { SelectBox as vsSelectBox } from 'sql/base/browser/ui/selectBox/selectBox'; import { SelectBox as vsSelectBox } from 'sql/base/browser/ui/selectBox/selectBox';
import { AngularDisposable } from 'sql/base/common/lifecycle'; import { AngularDisposable } from 'sql/base/node/lifecycle';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { ISelectData } from 'vs/base/browser/ui/selectBox/selectBox'; import { ISelectData } from 'vs/base/browser/ui/selectBox/selectBox';

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#e8e8e8" d="M6 4v8l4-4-4-4zm1 2.414l1.586 1.586-1.586 1.586v-3.172z"/></svg>

Before

Width:  |  Height:  |  Size: 151 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#646465" d="M6 4v8l4-4-4-4zm1 2.414l1.586 1.586-1.586 1.586v-3.172z"/></svg>

Before

Width:  |  Height:  |  Size: 151 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#e8e8e8" d="M11 10.07h-5.656l5.656-5.656v5.656z"/></svg>

Before

Width:  |  Height:  |  Size: 131 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#646465" d="M11 10.07h-5.656l5.656-5.656v5.656z"/></svg>

Before

Width:  |  Height:  |  Size: 131 B

View File

@@ -1,94 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-split-view {
position: relative;
}
.monaco-split-view > .split-view-view {
overflow: hidden;
}
.monaco-split-view.vertical > .split-view-view {
width: 100%;
}
.monaco-split-view.horizontal > .split-view-view {
height: 100%;
}
.monaco-split-view > .split-view-view > .header {
position: relative;
line-height: 22px;
font-size: 11px;
font-weight: bold;
text-transform: uppercase;
padding-left: 20px;
overflow: hidden;
display: flex;
}
.monaco-split-view > .split-view-view > .header.hide {
display: none;
}
/* Bold font style does not go well with CJK fonts */
.monaco-split-view:lang(zh-Hans) > .split-view-view > .header,
.monaco-split-view:lang(zh-Hant) > .split-view-view > .header,
.monaco-split-view:lang(ja) > .split-view-view > .header,
.monaco-split-view:lang(ko) > .split-view-view > .header { font-weight: normal; }
.monaco-split-view > .split-view-view > .header.collapsible {
cursor: pointer;
}
.monaco-split-view > .split-view-view > .header.collapsible {
background-image: url('arrow-collapse.svg');
background-position: 2px center;
background-repeat: no-repeat;
}
.monaco-split-view > .split-view-view > .header.collapsible:not(.collapsed) {
background-image: url('arrow-expand.svg');
background-position: 2px center;
background-repeat: no-repeat;
}
.vs-dark .monaco-split-view > .split-view-view > .header.collapsible {
background-image: url('arrow-collapse-dark.svg');
}
.vs-dark .monaco-split-view > .split-view-view > .header.collapsible:not(.collapsed) {
background-image: url('arrow-expand-dark.svg');
background-position: 2px center;
background-repeat: no-repeat;
}
/* Animation */
.monaco-split-view.animated > .split-view-view {
transition-duration: 0.15s;
-webkit-transition-duration: 0.15s;
-moz-transition-duration: 0.15s;
transition-timing-function: ease-out;
-webkit-transition-timing-function: ease-out;
-moz-transition-timing-function: ease-out;
}
.monaco-split-view.vertical.animated > .split-view-view {
transition-property: height;
-webkit-transition-property: height;
-moz-transition-property: height;
}
.monaco-split-view.horizontal.animated > .split-view-view {
transition-property: width;
-webkit-transition-property: width;
-moz-transition-property: width;
}
.hc-black .split-view-view > .header .action-label:before {
top: 4px !important;
}

File diff suppressed because it is too large Load Diff

View File

@@ -219,7 +219,7 @@ export class RowDetailView {
public subscribeToOnAsyncResponse() { public subscribeToOnAsyncResponse() {
this.onAsyncResponse.subscribe((e, args) => { this.onAsyncResponse.subscribe((e, args) => {
if (!args || !args.itemDetail) { if (!args || !args.itemDetail) {
throw 'Slick.RowDetailView plugin requires the onAsyncResponse() to supply "args.itemDetail" property.'; throw new Error('Slick.RowDetailView plugin requires the onAsyncResponse() to supply "args.itemDetail" property.');
} }
// If we just want to load in a view directly we can use detailView property to do so // If we just want to load in a view directly we can use detailView property to do so
@@ -278,7 +278,7 @@ export class RowDetailView {
item._isPadding = false; item._isPadding = false;
item._parent = parent; item._parent = parent;
item._offset = offset; item._offset = offset;
item.name = parent.message ? parent.message : nls.localize('rowDetailView.loadError','Loading Error...'); item.name = parent.message ? parent.message : nls.localize('rowDetailView.loadError', 'Loading Error...');
parent._child = item; parent._child = item;
return item; return item;
} }
@@ -349,15 +349,13 @@ export class RowDetailView {
//slick-cell to escape the cell overflow clipping. //slick-cell to escape the cell overflow clipping.
//sneaky extra </div> inserted here-----------------v //sneaky extra </div> inserted here-----------------v
/* tslint:disable:no-unexternalized-strings */ html.push('<div class="detailView-toggle collapse"></div></div>');
html.push("<div class='detailView-toggle collapse'></div></div>");
html.push("<div id='cellDetailView_", dataContext.id, "' class='dynamic-cell-detail' "); //apply custom css to detail html.push(`<div id='cellDetailView_${dataContext.id}' class='dynamic-cell-detail' `); //apply custom css to detail
html.push("style='height:", dataContext._height, "px;"); //set total height of padding html.push(`style=\'height:${dataContext._height}px;`); //set total height of padding
html.push("top:", rowHeight, "px'>"); //shift detail below 1st row html.push(`top:${rowHeight}px'>`); //shift detail below 1st row
html.push("<div id='detailViewContainer_", dataContext.id, "' class='detail-container' style='max-height:" + (dataContext._height - rowHeight + bottomMargin) + "px'>"); //sub ctr for custom styling html.push(`<div id='detailViewContainer_${dataContext.id}"' class='detail-container' style='max-height:${(dataContext._height - rowHeight + bottomMargin)}px'>`); //sub ctr for custom styling
html.push("<div id='innerDetailView_", dataContext.id, "'>", escape(dataContext._detailContent), "</div></div>"); html.push(`<div id='innerDetailView_${dataContext.id}'>${escape(dataContext._detailContent)}</div></div>`);
/* tslint:enable:no-unexternalized-strings */
//&omit a final closing detail container </div> that would come next //&omit a final closing detail container </div> that would come next
return html.join(''); return html.join('');
@@ -401,9 +399,9 @@ export class RowDetailView {
this._grid.getOptions().minRowBuffer = item._sizePadding + 3; this._grid.getOptions().minRowBuffer = item._sizePadding + 3;
} }
mainContainer.setAttribute('style', 'max-height: ' + item._height + 'px'); mainContainer.setAttribute('style', `max-height: ${item._height}px`);
if (cellItem) { if (cellItem) {
cellItem.setAttribute('style', 'height: ' + item._height + 'px;top:' + rowHeight + 'px'); cellItem.setAttribute('style', `height: ${item._height}px;top:${rowHeight}px`);
} }
let idxParent = this._dataView.getIdxById(item.id); let idxParent = this._dataView.getIdxById(item.id);

View File

@@ -15,7 +15,6 @@ const sizePerDigit = 15;
export class RowNumberColumn<T> implements Slick.Plugin<T> { export class RowNumberColumn<T> implements Slick.Plugin<T> {
private handler = new Slick.EventHandler(); private handler = new Slick.EventHandler();
private grid: Slick.Grid<T>; private grid: Slick.Grid<T>;
private currentColumnWidth: number;
constructor(private options: IRowNumberColumnOptions) { constructor(private options: IRowNumberColumnOptions) {
} }
@@ -50,23 +49,14 @@ export class RowNumberColumn<T> implements Slick.Plugin<T> {
} }
} }
public updateRowCount(rowNum: number) {
this.options.numberOfRows = rowNum;
let columnWidth = Math.max(this.options.numberOfRows.toString().length * sizePerDigit, 22);
if (columnWidth !== this.currentColumnWidth) {
this.grid.setColumnWidths([this.getColumnDefinition()]);
}
}
public getColumnDefinition(): Slick.Column<T> { public getColumnDefinition(): Slick.Column<T> {
// that smallest we can make it is 22 due to padding and margins in the cells // that smallest we can make it is 22 due to padding and margins in the cells
this.currentColumnWidth = Math.max(this.options.numberOfRows.toString().length * sizePerDigit, 22);
return { return {
id: 'rowNumber', id: 'rowNumber',
name: '', name: '',
field: 'rowNumber', field: 'rowNumber',
width: this.currentColumnWidth, width: 22,
resizable: false, resizable: true,
cssClass: this.options.cssClass, cssClass: this.options.cssClass,
focusable: false, focusable: false,
selectable: false, selectable: false,

View File

@@ -40,10 +40,14 @@ function defaultSort<T>(args: Slick.OnSortEventArgs<T>, data: Array<T>): Array<T
} }
export class TableDataView<T extends Slick.SlickData> implements IDisposableDataProvider<T> { export class TableDataView<T extends Slick.SlickData> implements IDisposableDataProvider<T> {
//The data exposed publicly, when filter is enabled, _data holds the filtered data.
private _data: Array<T>; private _data: Array<T>;
//Used when filtering is enabled, _allData holds the complete set of data.
private _allData: Array<T>;
private _findArray: Array<IFindPosition>; private _findArray: Array<IFindPosition>;
private _findObs: Observable<IFindPosition>; private _findObs: Observable<IFindPosition>;
private _findIndex: number; private _findIndex: number;
private _filterEnabled: boolean;
private _onRowCountChange = new Emitter<number>(); private _onRowCountChange = new Emitter<number>();
get onRowCountChange(): Event<number> { return this._onRowCountChange.event; } get onRowCountChange(): Event<number> { return this._onRowCountChange.event; }
@@ -51,10 +55,14 @@ export class TableDataView<T extends Slick.SlickData> implements IDisposableData
private _onFindCountChange = new Emitter<number>(); private _onFindCountChange = new Emitter<number>();
get onFindCountChange(): Event<number> { return this._onFindCountChange.event; } get onFindCountChange(): Event<number> { return this._onFindCountChange.event; }
private _onFilterStateChange = new Emitter<void>();
get onFilterStateChange(): Event<void> { return this._onFilterStateChange.event; }
constructor( constructor(
data?: Array<T>, data?: Array<T>,
private _findFn?: (val: T, exp: string) => Array<number>, private _findFn?: (val: T, exp: string) => Array<number>,
private _sortFn?: (args: Slick.OnSortEventArgs<T>, data: Array<T>) => Array<T> private _sortFn?: (args: Slick.OnSortEventArgs<T>, data: Array<T>) => Array<T>,
private _filterFn?: (data: Array<T>) => Array<T>
) { ) {
if (data) { if (data) {
this._data = data; this._data = data;
@@ -65,6 +73,35 @@ export class TableDataView<T extends Slick.SlickData> implements IDisposableData
if (!_sortFn) { if (!_sortFn) {
this._sortFn = defaultSort; this._sortFn = defaultSort;
} }
if (!_filterFn) {
this._filterFn = (dataToFilter) => dataToFilter;
}
this._filterEnabled = false;
}
public get filterEnabled(): boolean {
return this._filterEnabled;
}
public filter() {
if (!this.filterEnabled) {
this._allData = new Array(...this._data);
this._data = this._filterFn(this._allData);
this._filterEnabled = true;
}
this._data = this._filterFn(this._allData);
this._onFilterStateChange.fire();
}
public clearFilter() {
if (this._filterEnabled) {
this._data = this._allData;
this._allData = [];
this._filterEnabled = false;
this._onFilterStateChange.fire();
}
} }
sort(args: Slick.OnSortEventArgs<T>) { sort(args: Slick.OnSortEventArgs<T>) {
@@ -79,20 +116,39 @@ export class TableDataView<T extends Slick.SlickData> implements IDisposableData
return this._data[index]; return this._data[index];
} }
getLengthNonFiltered(): number {
return this.filterEnabled ? this._allData.length : this._data.length;
}
push(items: Array<T>); push(items: Array<T>);
push(item: T); push(item: T);
push(input: T | Array<T>) { push(input: T | Array<T>) {
let inputArray = new Array();
if (Array.isArray(input)) { if (Array.isArray(input)) {
this._data.push(...input); inputArray.push(...input);
} else { } else {
this._data.push(input); inputArray.push(input);
} }
this._onRowCountChange.fire();
if (this._filterEnabled) {
this._allData.push(...inputArray);
let filteredArray = this._filterFn(inputArray);
if (filteredArray.length !== 0) {
this._data.push(...filteredArray);
}
} else {
this._data.push(...inputArray);
}
this._onRowCountChange.fire(this.getLength());
} }
clear() { clear() {
this._data = new Array<T>(); this._data = new Array<T>();
this._onRowCountChange.fire(); if (this._filterEnabled) {
this._allData = new Array<T>();
}
this._onRowCountChange.fire(this.getLength());
} }
find(exp: string, maxMatches: number = 0): Thenable<IFindPosition> { find(exp: string, maxMatches: number = 0): Thenable<IFindPosition> {
@@ -180,6 +236,7 @@ export class TableDataView<T extends Slick.SlickData> implements IDisposableData
dispose() { dispose() {
this._data = undefined; this._data = undefined;
this._allData = undefined;
this._findArray = undefined; this._findArray = undefined;
this._findObs = undefined; this._findObs = undefined;
} }

View File

@@ -1,148 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Table } from './table';
import { TableDataView } from './tableDataView';
import { View, Orientation, AbstractCollapsibleView, HeaderView, ICollapsibleViewOptions, IViewOptions, CollapsibleState } from 'sql/base/browser/ui/splitview/splitview';
import { $ } from 'vs/base/browser/builder';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode } from 'vs/base/common/keyCodes';
import * as DOM from 'vs/base/browser/dom';
import * as lifecycle from 'vs/base/common/lifecycle';
export class TableBasicView<T> extends View {
private _table: Table<T>;
private _container: HTMLElement;
constructor(
viewOpts: IViewOptions,
data?: Array<T> | TableDataView<T>,
columns?: Slick.Column<T>[],
tableOpts?: Slick.GridOptions<T>
) {
super(undefined, viewOpts);
this._container = document.createElement('div');
this._container.className = 'table-view';
this._table = new Table<T>(this._container, { dataProvider: data, columns }, tableOpts);
}
public get table(): Table<T> {
return this._table;
}
render(container: HTMLElement, orientation: Orientation): void {
container.appendChild(this._container);
}
focus(): void {
this._table.focus();
}
layout(size: number, orientation: Orientation): void {
this._table.layout(size, orientation);
}
}
export class TableHeaderView<T> extends HeaderView {
private _table: Table<T>;
private _container: HTMLElement;
constructor(
private _viewTitle: string,
viewOpts: IViewOptions,
data?: Array<T> | TableDataView<T>,
columns?: Slick.Column<T>[],
tableOpts?: Slick.GridOptions<T>
) {
super(undefined, viewOpts);
this._container = document.createElement('div');
this._container.className = 'table-view';
this._table = new Table<T>(this._container, { dataProvider: data, columns }, tableOpts);
}
public get table(): Table<T> {
return this._table;
}
protected renderHeader(container: HTMLElement): void {
const titleDiv = $('div.title').appendTo(container);
$('span').text(this._viewTitle).appendTo(titleDiv);
}
protected renderBody(container: HTMLElement): void {
container.appendChild(this._container);
}
protected layoutBody(size: number): void {
this._table.layout(size, Orientation.VERTICAL);
}
focus(): void {
this._table.focus();
}
}
export class TableCollapsibleView<T> extends AbstractCollapsibleView {
private _table: Table<T>;
private _container: HTMLElement;
private _headerTabListener: lifecycle.IDisposable;
constructor(
private _viewTitle: string,
viewOpts: ICollapsibleViewOptions,
data?: Array<T> | TableDataView<T>,
columns?: Slick.Column<T>[],
tableOpts?: Slick.GridOptions<T>
) {
super(undefined, viewOpts);
this._container = document.createElement('div');
this._container.className = 'table-view';
this._table = new Table<T>(this._container, { dataProvider: data, columns }, tableOpts);
}
public render(container: HTMLElement, orientation: Orientation): void {
super.render(container, orientation);
this._headerTabListener = DOM.addDisposableListener(this.header, DOM.EventType.KEY_DOWN, (e) => {
let event = new StandardKeyboardEvent(e);
if (event.equals(KeyCode.Tab) && this.state === CollapsibleState.EXPANDED) {
let element = this._table.getSelectedRows();
if (!element || element.length === 0) {
this._table.setSelectedRows([0]);
this._table.setActiveCell(0, 1);
e.stopImmediatePropagation();
}
}
});
}
public dispose(): void {
if (this._headerTabListener) {
this._headerTabListener.dispose();
this._headerTabListener = null;
}
super.dispose();
}
public addContainerClass(className: string) {
this._container.classList.add(className);
}
public get table(): Table<T> {
return this._table;
}
protected renderHeader(container: HTMLElement): void {
const titleDiv = $('div.title').appendTo(container);
$('span').text(this._viewTitle).appendTo(titleDiv);
}
protected renderBody(container: HTMLElement): void {
container.appendChild(this._container);
}
protected layoutBody(size: number): void {
this._table.layout(size, Orientation.VERTICAL);
}
}

View File

@@ -1,26 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.custom-view-tree-node-item {
display: flex;
height: 22px;
line-height: 22px;
}
.custom-view-tree-node-item > .custom-view-tree-node-item-icon {
background-size: 16px;
background-position: left center;
background-repeat: no-repeat;
padding-right: 6px;
width: 16px;
height: 22px;
-webkit-font-smoothing: antialiased;
}
.custom-view-tree-node-item > .custom-view-tree-node-item-label {
flex: 1;
text-overflow: ellipsis;
overflow: hidden;
}

View File

@@ -1,303 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import { TPromise } from 'vs/base/common/winjs.base';
import { IThemable } from 'vs/platform/theme/common/styler';
import * as errors from 'vs/base/common/errors';
import { $ } from 'vs/base/browser/builder';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { IAction, IActionRunner } from 'vs/base/common/actions';
import { IActionItem, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
import { prepareActions } from 'vs/workbench/browser/actions';
import { ITree } from 'vs/base/parts/tree/browser/tree';
import { DelayedDragHandler } from 'vs/base/browser/dnd';
import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { AbstractCollapsibleView, CollapsibleState, IView as IBaseView, SplitView, ViewSizing } from 'sql/base/browser/ui/splitview/splitview';
export interface IViewOptions {
id: string;
name: string;
actionRunner: IActionRunner;
collapsed: boolean;
}
export interface IViewConstructorSignature {
new(initialSize: number, options: IViewOptions, ...services: { _serviceBrand: any; }[]): IView;
}
export interface IView extends IBaseView, IThemable {
id: string;
name: string;
getHeaderElement(): HTMLElement;
create(): TPromise<void>;
setVisible(visible: boolean): TPromise<void>;
isVisible(): boolean;
getActions(): IAction[];
getSecondaryActions(): IAction[];
getActionItem(action: IAction): IActionItem;
getActionsContext(): any;
showHeader(): boolean;
hideHeader(): boolean;
focusBody(): void;
isExpanded(): boolean;
expand(): void;
collapse(): void;
getOptimalWidth(): number;
shutdown(): void;
}
export interface ICollapsibleViewOptions extends IViewOptions {
ariaHeaderLabel?: string;
sizing: ViewSizing;
initialBodySize?: number;
}
export abstract class CollapsibleView extends AbstractCollapsibleView implements IView {
readonly id: string;
readonly name: string;
protected treeContainer: HTMLElement;
protected tree: ITree;
protected toDispose: IDisposable[];
protected toolBar: ToolBar;
protected actionRunner: IActionRunner;
protected isDisposed: boolean;
private _isVisible: boolean;
private dragHandler: DelayedDragHandler;
constructor(
initialSize: number,
options: ICollapsibleViewOptions,
protected keybindingService: IKeybindingService,
protected contextMenuService: IContextMenuService
) {
super(initialSize, {
ariaHeaderLabel: options.ariaHeaderLabel,
sizing: options.sizing,
bodySize: options.initialBodySize ? options.initialBodySize : 4 * 22,
initialState: options.collapsed ? CollapsibleState.COLLAPSED : CollapsibleState.EXPANDED,
});
this.id = options.id;
this.name = options.name;
this.actionRunner = options.actionRunner;
this.toDispose = [];
}
protected changeState(state: CollapsibleState): void {
this.updateTreeVisibility(this.tree, state === CollapsibleState.EXPANDED);
super.changeState(state);
}
get draggableLabel(): string { return this.name; }
public create(): TPromise<void> {
return TPromise.as(null);
}
getHeaderElement(): HTMLElement {
return this.header;
}
public renderHeader(container: HTMLElement): void {
// Tool bar
this.toolBar = new ToolBar($('div.actions').appendTo(container).getHTMLElement(), this.contextMenuService, {
orientation: ActionsOrientation.HORIZONTAL,
actionItemProvider: (action) => this.getActionItem(action),
ariaLabel: nls.localize('viewToolbarAriaLabel', "{0} actions", this.name),
getKeyBinding: (action) => this.keybindingService.lookupKeybinding(action.id)
});
this.toolBar.actionRunner = this.actionRunner;
this.updateActions();
// Expand on drag over
this.dragHandler = new DelayedDragHandler(container, () => {
if (!this.isExpanded()) {
this.expand();
}
});
}
protected updateActions(): void {
this.toolBar.setActions(prepareActions(this.getActions()), prepareActions(this.getSecondaryActions()))();
this.toolBar.context = this.getActionsContext();
}
protected renderViewTree(container: HTMLElement): HTMLElement {
const treeContainer = document.createElement('div');
container.appendChild(treeContainer);
return treeContainer;
}
public getViewer(): ITree {
return this.tree;
}
public isVisible(): boolean {
return this._isVisible;
}
public setVisible(visible: boolean): TPromise<void> {
if (this._isVisible !== visible) {
this._isVisible = visible;
this.updateTreeVisibility(this.tree, visible && this.state === CollapsibleState.EXPANDED);
}
return TPromise.as(null);
}
public focusBody(): void {
this.focusTree();
}
protected reveal(element: any, relativeTop?: number): TPromise<void> {
if (!this.tree) {
return TPromise.as(null); // return early if viewlet has not yet been created
}
return this.tree.reveal(element, relativeTop);
}
public layoutBody(size: number): void {
if (this.tree) {
this.treeContainer.style.height = size + 'px';
this.tree.layout(size);
}
}
public getActions(): IAction[] {
return [];
}
public getSecondaryActions(): IAction[] {
return [];
}
public getActionItem(action: IAction): IActionItem {
return null;
}
public getActionsContext(): any {
return undefined;
}
public shutdown(): void {
// Subclass to implement
}
public getOptimalWidth(): number {
return 0;
}
public dispose(): void {
this.isDisposed = true;
this.treeContainer = null;
if (this.tree) {
this.tree.dispose();
}
if (this.dragHandler) {
this.dragHandler.dispose();
}
this.toDispose = dispose(this.toDispose);
if (this.toolBar) {
this.toolBar.dispose();
}
super.dispose();
}
private updateTreeVisibility(tree: ITree, isVisible: boolean): void {
if (!tree) {
return;
}
if (isVisible) {
$(tree.getHTMLElement()).show();
} else {
$(tree.getHTMLElement()).hide(); // make sure the tree goes out of the tabindex world by hiding it
}
if (isVisible) {
tree.onVisible();
} else {
tree.onHidden();
}
}
private focusTree(): void {
if (!this.tree) {
return; // return early if viewlet has not yet been created
}
// Make sure the current selected element is revealed
const selection = this.tree.getSelection();
if (selection.length > 0) {
this.reveal(selection[0], 0.5).done(null, errors.onUnexpectedError);
}
// Pass Focus to Viewer
this.tree.domFocus();
}
}
export interface IViewletViewOptions extends IViewOptions {
viewletSettings: object;
}
export interface IViewState {
collapsed: boolean;
size: number | undefined;
isHidden: boolean;
order: number;
}

View File

@@ -1,50 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { TPromise } from 'vs/base/common/winjs.base';
import { Event } from 'vs/base/common/event';
import { Command } from 'vs/editor/common/modes';
export type TreeViewItemHandleArg = {
$treeViewId: string,
$treeItemHandle: number
};
export enum TreeItemCollapsibleState {
None = 0,
Collapsed = 1,
Expanded = 2
}
export interface ITreeItem {
handle: number;
label: string;
icon?: string;
iconDark?: string;
contextValue?: string;
command?: Command;
children?: ITreeItem[];
collapsibleState?: TreeItemCollapsibleState;
}
export interface ITreeViewDataProvider {
onDidChange: Event<ITreeItem[] | undefined | null>;
onDispose: Event<void>;
getElements(): TPromise<ITreeItem[]>;
getChildren(element: ITreeItem): TPromise<ITreeItem[]>;
}

View File

@@ -11,17 +11,17 @@ import { DefaultUrlSerializer, UrlSerializer, UrlTree } from '@angular/router';
* encode and decode the parentheses. Github issue angular/angular#10280, microsoft/carbon#1116 * encode and decode the parentheses. Github issue angular/angular#10280, microsoft/carbon#1116
*/ */
export default class CustomUrlSerializer implements UrlSerializer { export default class CustomUrlSerializer implements UrlSerializer {
private _defaultUrlSerializer: DefaultUrlSerializer = new DefaultUrlSerializer(); private _defaultUrlSerializer: DefaultUrlSerializer = new DefaultUrlSerializer();
parse(url: string): UrlTree { parse(url: string): UrlTree {
// Encode parentheses // Encode parentheses
url = url.replace(/\(/g, '%28').replace(/\)/g, '%29'); url = url.replace(/\(/g, '%28').replace(/\)/g, '%29');
// Use the default serializer from here on // Use the default serializer from here on
return this._defaultUrlSerializer.parse(url); return this._defaultUrlSerializer.parse(url);
} }
serialize(tree: UrlTree): string { serialize(tree: UrlTree): string {
// serialize parentheses after angular router // serialize parentheses after angular router
return this._defaultUrlSerializer.serialize(tree).replace(/%28/g, '(').replace(/%29/g, ')'); return this._defaultUrlSerializer.serialize(tree).replace(/%28/g, '(').replace(/%29/g, ')');
} }
} }

View File

@@ -6,7 +6,6 @@
// localizable strings // localizable strings
export const InvalidProvider = 'Provider is invalid'; export const InvalidProvider = 'Provider is invalid';
export const SerializationDisabled = 'Saving results into different format disabled for this data provider.';
/** /**
* Feature names * Feature names

View File

@@ -41,6 +41,7 @@ export const Accounts = 'Accounts';
export const FireWallRule = 'FirewallRule'; export const FireWallRule = 'FirewallRule';
export const AutoOAuth = 'AutoOAuth'; export const AutoOAuth = 'AutoOAuth';
export const AddNewDashboardTab = 'AddNewDashboardTab'; export const AddNewDashboardTab = 'AddNewDashboardTab';
export const ProfilerFilter = 'ProfilerFilter';
// SQL Agent Events: // SQL Agent Events:

View File

@@ -5,7 +5,7 @@
'use strict'; 'use strict';
import { ITelemetryService, ITelemetryData } from 'vs/platform/telemetry/common/telemetry'; import { ITelemetryService, ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces'; import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { warn } from 'sql/base/common/log'; import { warn } from 'sql/base/common/log';
export interface IConnectionTelemetryData extends ITelemetryData { export interface IConnectionTelemetryData extends ITelemetryData {

View File

@@ -11,7 +11,8 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
import * as cr from 'vs/platform/theme/common/colorRegistry'; import * as cr from 'vs/platform/theme/common/colorRegistry';
import { IThemable, attachStyler } from 'vs/platform/theme/common/styler'; import { IThemable, attachStyler } from 'vs/platform/theme/common/styler';
import { IDisposable } from 'vs/base/common/lifecycle'; import { IDisposable } from 'vs/base/common/lifecycle';
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; import { SIDE_BAR_BACKGROUND, SIDE_BAR_SECTION_HEADER_FOREGROUND, SIDE_BAR_SECTION_HEADER_BACKGROUND, SIDE_BAR_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme';
import { IPanelColors } from 'vs/workbench/browser/parts/views/panelViewlet';
export function attachModalDialogStyler(widget: IThemable, themeService: IThemeService, style?: export function attachModalDialogStyler(widget: IThemable, themeService: IThemeService, style?:
{ {
@@ -262,3 +263,12 @@ export function attachCheckboxStyler(widget: IThemable, themeService: IThemeServ
disabledCheckboxForeground: (style && style.disabledCheckboxForeground) || sqlcolors.disabledCheckboxForeground disabledCheckboxForeground: (style && style.disabledCheckboxForeground) || sqlcolors.disabledCheckboxForeground
}, widget); }, widget);
} }
export function attachPanelStyler(widget: IThemable, themeService: IThemeService) {
return attachStyler<IPanelColors>(themeService, {
headerForeground: SIDE_BAR_SECTION_HEADER_FOREGROUND,
headerBackground: SIDE_BAR_SECTION_HEADER_BACKGROUND,
// headerHighContrastBorder: index === 0 ? null : contrastBorder,
dropBackground: SIDE_BAR_DRAG_AND_DROP_BACKGROUND
}, widget);
}

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>clearfilter</title><path d="M0,1H16V2.71l-6,6V15H6V8.71l-6-6ZM15,2.29V2H1v.29l6,6V14H9V8.29ZM15.29,10l.71.71L14.2,12.5,16,14.29l-.71.71L13.5,13.2,11.71,15,11,14.29l1.8-1.79L11,10.71l.71-.71,1.79,1.8Z"/></svg>

After

Width:  |  Height:  |  Size: 308 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>clearfilter_inverse</title><path class="cls-1" d="M0,1H16V2.71l-6,6V15H6V8.71l-6-6ZM15,2.29V2H1v.29l6,6V14H9V8.29ZM15.29,10l.71.71L14.2,12.5,16,14.29l-.71.71L13.5,13.2,11.71,15,11,14.29l1.8-1.79L11,10.71l.71-.71,1.79,1.8Z"/></svg>

After

Width:  |  Height:  |  Size: 376 B

View File

@@ -149,6 +149,15 @@
background-image: url("filter_inverse.svg"); background-image: url("filter_inverse.svg");
} }
.vs .icon.clear-filter {
background-image: url("clearfilter.svg");
}
.vs-dark .icon.clear-filter,
.hc-black .icon.clear-filter {
background-image: url("clearfilter_inverse.svg");
}
.vs .icon.warning-badge, .vs .icon.warning-badge,
.vs-dark .icon.warning-badge, .vs-dark .icon.warning-badge,
.hc-black .icon.warning-badge { .hc-black .icon.warning-badge {

View File

@@ -1 +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{font-size:12px;font-family:FullMDL2Assets, Full MDL2 Assets;}</style></defs><title>filter_16x16</title><text class="cls-1" transform="translate(0 12)"> </text><path d="M0,1.53H16V3.24l-6,6v6.27H6V9.22l-6-6ZM15,2.82V2.53H1v.29l6,6v5.69H9V8.8Z"/></svg> <svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><title>filter</title><path d="M0,1H16V2.68l-6,6v6.27H6V8.67l-6-6ZM15,2.26V2H1v.29l6,6v5.69H9V8.24Z"/></svg>

Before

Width:  |  Height:  |  Size: 363 B

After

Width:  |  Height:  |  Size: 200 B

View File

@@ -1 +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{font-size:12px;font-family:FullMDL2Assets, Full MDL2 Assets;}.cls-1,.cls-2{fill:#fff;}</style></defs><title>filter_inverse_16x16</title><text class="cls-1" transform="translate(0.03 12.1)"> </text><path class="cls-2" d="M.05,1.63H16V3.33l-6,6v6.27H6V9.31l-6-6ZM15,2.91V2.62H1v.29l6,6v5.69H9V8.89Z"/></svg> <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>filter_inverse</title><path class="cls-1" d="M0,1H16V2.68l-6,6v6.27H6V8.67l-6-6ZM15,2.26V2H1v.29l6,6v5.69H9V8.24Z"/></svg>

Before

Width:  |  Height:  |  Size: 418 B

After

Width:  |  Height:  |  Size: 268 B

View File

@@ -8,35 +8,87 @@
import 'vs/css!./media/accountDialog'; import 'vs/css!./media/accountDialog';
import 'vs/css!sql/parts/accountManagement/common/media/accountActions'; import 'vs/css!sql/parts/accountManagement/common/media/accountActions';
import * as DOM from 'vs/base/browser/dom'; import * as DOM from 'vs/base/browser/dom';
import { SplitView } from 'sql/base/browser/ui/splitview/splitview';
import { List } from 'vs/base/browser/ui/list/listWidget'; import { List } from 'vs/base/browser/ui/list/listWidget';
import { IListService, ListService } from 'vs/platform/list/browser/listService';
import { IPartService } from 'vs/workbench/services/part/common/partService'; import { IPartService } from 'vs/workbench/services/part/common/partService';
import { Event, Emitter } from 'vs/base/common/event'; import { Event, Emitter } from 'vs/base/common/event';
import { localize } from 'vs/nls'; import { localize } from 'vs/nls';
import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IThemeService } from 'vs/platform/theme/common/themeService';
import { attachListStyler } from 'vs/platform/theme/common/styler'; import { attachListStyler } from 'vs/platform/theme/common/styler';
import { ActionRunner } from 'vs/base/common/actions'; import { IAction } from 'vs/base/common/actions';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import * as TelemetryKeys from 'sql/common/telemetryKeys'; import { SplitView, Sizing } from 'vs/base/browser/ui/splitview/splitview';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ViewletPanel, IViewletPanelOptions } from 'vs/workbench/browser/parts/views/panelViewlet';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { values } from 'vs/base/common/map';
import * as sqlops from 'sqlops'; import * as sqlops from 'sqlops';
import { Button } from 'sql/base/browser/ui/button/button'; import { Button } from 'sql/base/browser/ui/button/button';
import { Modal } from 'sql/base/browser/ui/modal/modal'; import { Modal } from 'sql/base/browser/ui/modal/modal';
import { attachModalDialogStyler, attachButtonStyler } from 'sql/common/theme/styler'; import { attachModalDialogStyler, attachButtonStyler, attachPanelStyler } from 'sql/common/theme/styler';
import { AccountViewModel } from 'sql/parts/accountManagement/accountDialog/accountViewModel'; import { AccountViewModel } from 'sql/parts/accountManagement/accountDialog/accountViewModel';
import { AddAccountAction } from 'sql/parts/accountManagement/common/accountActions'; import { AddAccountAction } from 'sql/parts/accountManagement/common/accountActions';
import { AccountListRenderer, AccountListDelegate } from 'sql/parts/accountManagement/common/accountListRenderer'; import { AccountListRenderer, AccountListDelegate } from 'sql/parts/accountManagement/common/accountListRenderer';
import { AccountProviderAddedEventParams, UpdateAccountListEventParams } from 'sql/services/accountManagement/eventTypes'; import { AccountProviderAddedEventParams, UpdateAccountListEventParams } from 'sql/platform/accountManagement/common/eventTypes';
import { FixedListView } from 'sql/platform/views/fixedListView';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IClipboardService } from 'sql/platform/clipboard/common/clipboardService'; import { IClipboardService } from 'sql/platform/clipboard/common/clipboardService';
import * as TelemetryKeys from 'sql/common/telemetryKeys';
class AccountPanel extends ViewletPanel {
public index: number;
private accountList: List<sqlops.Account>;
constructor(
private options: IViewletPanelOptions,
@IKeybindingService keybindingService: IKeybindingService,
@IContextMenuService contextMenuService: IContextMenuService,
@IConfigurationService configurationService: IConfigurationService,
@IInstantiationService private instantiationService: IInstantiationService,
@IThemeService private themeService: IThemeService
) {
super(options, keybindingService, contextMenuService, configurationService);
}
protected renderBody(container: HTMLElement): void {
this.accountList = new List<sqlops.Account>(container, new AccountListDelegate(AccountDialog.ACCOUNTLIST_HEIGHT), [this.instantiationService.createInstance(AccountListRenderer)]);
this.disposables.push(attachListStyler(this.accountList, this.themeService));
}
protected layoutBody(size: number): void {
if (this.accountList) {
this.accountList.layout(size);
}
}
public get length(): number {
return this.accountList.length;
}
public focus() {
this.accountList.domFocus();
}
public updateAccounts(accounts: sqlops.Account[]) {
this.accountList.splice(0, this.accountList.length, accounts);
}
public setSelection(indexes: number[]) {
this.accountList.setSelection(indexes);
}
public getActions(): IAction[] {
return [this.instantiationService.createInstance(
AddAccountAction,
this.options.id
)];
}
}
export interface IProviderViewUiComponent { export interface IProviderViewUiComponent {
view: FixedListView<sqlops.Account>; view: AccountPanel;
addAccountAction: AddAccountAction; addAccountAction: AddAccountAction;
} }
@@ -46,13 +98,10 @@ export class AccountDialog extends Modal {
public viewModel: AccountViewModel; public viewModel: AccountViewModel;
// MEMBER VARIABLES //////////////////////////////////////////////////// // MEMBER VARIABLES ////////////////////////////////////////////////////
private _providerViews: { [providerId: string]: IProviderViewUiComponent } = {}; private _providerViewsMap = new Map<string, IProviderViewUiComponent>();
private _closeButton: Button; private _closeButton: Button;
private _addAccountButton: Button; private _addAccountButton: Button;
private _delegate: AccountListDelegate;
private _accountRenderer: AccountListRenderer;
private _actionRunner: ActionRunner;
private _splitView: SplitView; private _splitView: SplitView;
private _container: HTMLElement; private _container: HTMLElement;
private _splitViewContainer: HTMLElement; private _splitViewContainer: HTMLElement;
@@ -68,10 +117,10 @@ export class AccountDialog extends Modal {
constructor( constructor(
@IPartService partService: IPartService, @IPartService partService: IPartService,
@IThemeService themeService: IThemeService, @IThemeService themeService: IThemeService,
@IListService private _listService: IListService,
@IInstantiationService private _instantiationService: IInstantiationService, @IInstantiationService private _instantiationService: IInstantiationService,
@IContextMenuService private _contextMenuService: IContextMenuService, @IContextMenuService private _contextMenuService: IContextMenuService,
@IKeybindingService private _keybindingService: IKeybindingService, @IKeybindingService private _keybindingService: IKeybindingService,
@IConfigurationService private _configurationService: IConfigurationService,
@ITelemetryService telemetryService: ITelemetryService, @ITelemetryService telemetryService: ITelemetryService,
@IContextKeyService contextKeyService: IContextKeyService, @IContextKeyService contextKeyService: IContextKeyService,
@IClipboardService clipboardService: IClipboardService @IClipboardService clipboardService: IClipboardService
@@ -86,11 +135,6 @@ export class AccountDialog extends Modal {
contextKeyService, contextKeyService,
{ hasSpinner: true } { hasSpinner: true }
); );
let self = this;
this._delegate = new AccountListDelegate(AccountDialog.ACCOUNTLIST_HEIGHT);
this._accountRenderer = this._instantiationService.createInstance(AccountListRenderer);
this._actionRunner = new ActionRunner();
// Setup the event emitters // Setup the event emitters
this._onAddAccountErrorEmitter = new Emitter<string>(); this._onAddAccountErrorEmitter = new Emitter<string>();
@@ -98,28 +142,25 @@ export class AccountDialog extends Modal {
// Create the view model and wire up the events // Create the view model and wire up the events
this.viewModel = this._instantiationService.createInstance(AccountViewModel); this.viewModel = this._instantiationService.createInstance(AccountViewModel);
this.viewModel.addProviderEvent(arg => { self.addProvider(arg); }); this.viewModel.addProviderEvent(arg => { this.addProvider(arg); });
this.viewModel.removeProviderEvent(arg => { self.removeProvider(arg); }); this.viewModel.removeProviderEvent(arg => { this.removeProvider(arg); });
this.viewModel.updateAccountListEvent(arg => { self.updateProviderAccounts(arg); }); this.viewModel.updateAccountListEvent(arg => { this.updateProviderAccounts(arg); });
// Load the initial contents of the view model // Load the initial contents of the view model
this.viewModel.initialize() this.viewModel.initialize()
.then(addedProviders => { .then(addedProviders => {
for (let addedProvider of addedProviders) { for (let addedProvider of addedProviders) {
self.addProvider(addedProvider); this.addProvider(addedProvider);
} }
}); });
} }
// MODAL OVERRIDE METHODS ////////////////////////////////////////////// // MODAL OVERRIDE METHODS //////////////////////////////////////////////
protected layout(height?: number): void { protected layout(height?: number): void {
// Ignore height as it's a subcomponent being laid out
this._splitView.layout(DOM.getContentHeight(this._container)); this._splitView.layout(DOM.getContentHeight(this._container));
} }
public render() { public render() {
let self = this;
super.render(); super.render();
attachModalDialogStyler(this, this._themeService); attachModalDialogStyler(this, this._themeService);
this._closeButton = this.addFooterButton(localize('accountDialog.close', 'Close'), () => this.close()); this._closeButton = this.addFooterButton(localize('accountDialog.close', 'Close'), () => this.close());
@@ -128,7 +169,7 @@ export class AccountDialog extends Modal {
protected renderBody(container: HTMLElement) { protected renderBody(container: HTMLElement) {
this._container = container; this._container = container;
this._splitViewContainer = DOM.$('div.account-view'); this._splitViewContainer = DOM.$('div.account-view.monaco-panel-view');
DOM.append(container, this._splitViewContainer); DOM.append(container, this._splitViewContainer);
this._splitView = new SplitView(this._splitViewContainer); this._splitView = new SplitView(this._splitViewContainer);
@@ -143,7 +184,7 @@ export class AccountDialog extends Modal {
this._addAccountButton = new Button(buttonSection); this._addAccountButton = new Button(buttonSection);
this._addAccountButton.label = localize('accountDialog.addConnection', 'Add an account'); this._addAccountButton.label = localize('accountDialog.addConnection', 'Add an account');
this._register(this._addAccountButton.onDidClick(() => { this._register(this._addAccountButton.onDidClick(() => {
(<IProviderViewUiComponent>Object.values(this._providerViews)[0]).addAccountAction.run(); (<IProviderViewUiComponent>values(this._providerViewsMap)[0]).addAccountAction.run();
})); }));
DOM.append(container, this._noaccountViewContainer); DOM.append(container, this._noaccountViewContainer);
@@ -189,20 +230,19 @@ export class AccountDialog extends Modal {
private showSplitView() { private showSplitView() {
this._splitViewContainer.hidden = false; this._splitViewContainer.hidden = false;
this._noaccountViewContainer.hidden = true; this._noaccountViewContainer.hidden = true;
let views = this._splitView.getViews(); if (values(this._providerViewsMap).length > 0) {
if (views && views.length > 0) { let firstView = values(this._providerViewsMap)[0];
let firstView = views[0]; if (firstView instanceof AccountPanel) {
if (firstView instanceof FixedListView) { firstView.setSelection([0]);
firstView.list.setSelection([0]); firstView.focus();
firstView.list.domFocus();
} }
} }
} }
private isEmptyLinkedAccount(): boolean { private isEmptyLinkedAccount(): boolean {
for (var providerId in this._providerViews) { for (let provider of values(this._providerViewsMap)) {
var listView = this._providerViews[providerId].view; let listView = provider.view;
if (listView && listView.list.length > 0) { if (listView && listView.length > 0) {
return false; return false;
} }
} }
@@ -211,23 +251,21 @@ export class AccountDialog extends Modal {
public dispose(): void { public dispose(): void {
super.dispose(); super.dispose();
for (let key in this._providerViews) { for (let provider of values(this._providerViewsMap)) {
if (this._providerViews[key].addAccountAction) { if (provider.addAccountAction) {
this._providerViews[key].addAccountAction.dispose(); provider.addAccountAction.dispose();
} }
if (this._providerViews[key].view) { if (provider.view) {
this._providerViews[key].view.dispose(); provider.view.dispose();
} }
delete this._providerViews[key];
} }
} }
// PRIVATE HELPERS ///////////////////////////////////////////////////// // PRIVATE HELPERS /////////////////////////////////////////////////////
private addProvider(newProvider: AccountProviderAddedEventParams) { private addProvider(newProvider: AccountProviderAddedEventParams) {
let self = this;
// Skip adding the provider if it already exists // Skip adding the provider if it already exists
if (this._providerViews[newProvider.addedProvider.id]) { if (this._providerViewsMap.get(newProvider.addedProvider.id)) {
return; return;
} }
@@ -237,37 +275,35 @@ export class AccountDialog extends Modal {
AddAccountAction, AddAccountAction,
newProvider.addedProvider.id newProvider.addedProvider.id
); );
addAccountAction.addAccountCompleteEvent(() => { self.hideSpinner(); }); addAccountAction.addAccountCompleteEvent(() => { this.hideSpinner(); });
addAccountAction.addAccountErrorEvent(msg => { self._onAddAccountErrorEmitter.fire(msg); }); addAccountAction.addAccountErrorEvent(msg => { this._onAddAccountErrorEmitter.fire(msg); });
addAccountAction.addAccountStartEvent(() => { self.showSpinner(); }); addAccountAction.addAccountStartEvent(() => { this.showSpinner(); });
// Create a fixed list view for the account provider let providerView = new AccountPanel(
let providerViewContainer = DOM.$('.provider-view'); {
let accountList = new List<sqlops.Account>(providerViewContainer, this._delegate, [this._accountRenderer]); id: newProvider.addedProvider.id,
let providerView = new FixedListView<sqlops.Account>( title: newProvider.addedProvider.displayName,
undefined, ariaHeaderLabel: newProvider.addedProvider.displayName
false, },
newProvider.addedProvider.displayName,
accountList,
providerViewContainer,
22,
[addAccountAction],
this._actionRunner,
this._contextMenuService,
this._keybindingService, this._keybindingService,
this._contextMenuService,
this._configurationService,
this._instantiationService,
this._themeService this._themeService
); );
// Append the list view to the split view attachPanelStyler(providerView, this._themeService);
this._splitView.addView(providerView);
this._register(attachListStyler(accountList, this._themeService)); const insertIndex = this._splitView.length;
// Append the list view to the split view
this._splitView.addView(providerView, Sizing.Distribute, insertIndex);
providerView.render();
providerView.index = insertIndex;
let listService = <ListService>this._listService;
this._register(listService.register(accountList));
this._splitView.layout(DOM.getContentHeight(this._container)); this._splitView.layout(DOM.getContentHeight(this._container));
// Set the initial items of the list // Set the initial items of the list
providerView.updateList(newProvider.initialAccounts); providerView.updateAccounts(newProvider.initialAccounts);
if (newProvider.initialAccounts.length > 0 && this._splitViewContainer.hidden) { if (newProvider.initialAccounts.length > 0 && this._splitViewContainer.hidden) {
this.showSplitView(); this.showSplitView();
@@ -276,31 +312,31 @@ export class AccountDialog extends Modal {
this.layout(); this.layout();
// Store the view for the provider and action // Store the view for the provider and action
this._providerViews[newProvider.addedProvider.id] = { view: providerView, addAccountAction: addAccountAction }; this._providerViewsMap.set(newProvider.addedProvider.id, { view: providerView, addAccountAction: addAccountAction });
} }
private removeProvider(removedProvider: sqlops.AccountProviderMetadata) { private removeProvider(removedProvider: sqlops.AccountProviderMetadata) {
// Skip removing the provider if it doesn't exist // Skip removing the provider if it doesn't exist
let providerView = this._providerViews[removedProvider.id]; let providerView = this._providerViewsMap.get(removedProvider.id);
if (!providerView || !providerView.view) { if (!providerView || !providerView.view) {
return; return;
} }
// Remove the list view from the split view // Remove the list view from the split view
this._splitView.removeView(providerView.view); this._splitView.removeView(providerView.view.index);
this._splitView.layout(DOM.getContentHeight(this._container)); this._splitView.layout(DOM.getContentHeight(this._container));
// Remove the list view from our internal map // Remove the list view from our internal map
delete this._providerViews[removedProvider.id]; this._providerViewsMap.delete(removedProvider.id);
this.layout(); this.layout();
} }
private updateProviderAccounts(args: UpdateAccountListEventParams) { private updateProviderAccounts(args: UpdateAccountListEventParams) {
let providerMapping = this._providerViews[args.providerId]; let providerMapping = this._providerViewsMap.get(args.providerId);
if (!providerMapping || !providerMapping.view) { if (!providerMapping || !providerMapping.view) {
return; return;
} }
providerMapping.view.updateList(args.accountList); providerMapping.view.updateAccounts(args.accountList);
if (args.accountList.length > 0 && this._splitViewContainer.hidden) { if (args.accountList.length > 0 && this._splitViewContainer.hidden) {
this.showSplitView(); this.showSplitView();

View File

@@ -7,9 +7,9 @@
import Severity from 'vs/base/common/severity'; import Severity from 'vs/base/common/severity';
import { AccountDialog } from 'sql/parts/accountManagement/accountDialog/accountDialog'; import { AccountDialog } from 'sql/parts/accountManagement/accountDialog/accountDialog';
import { IErrorMessageService } from 'sql/parts/connection/common/connectionManagement';
import { localize } from 'vs/nls'; import { localize } from 'vs/nls';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IErrorMessageService } from 'sql/platform/errorMessage/common/errorMessageService';
export class AccountDialogController { export class AccountDialogController {

View File

@@ -7,8 +7,8 @@
import * as sqlops from 'sqlops'; import * as sqlops from 'sqlops';
import { Event, Emitter } from 'vs/base/common/event'; import { Event, Emitter } from 'vs/base/common/event';
import { IAccountManagementService } from 'sql/services/accountManagement/interfaces'; import { IAccountManagementService } from 'sql/platform/accountManagement/common/interfaces';
import { AccountProviderAddedEventParams, UpdateAccountListEventParams } from 'sql/services/accountManagement/eventTypes'; import { AccountProviderAddedEventParams, UpdateAccountListEventParams } from 'sql/platform/accountManagement/common/eventTypes';
/** /**
* View model for account dialog * View model for account dialog

View File

@@ -49,18 +49,18 @@
display: none; display: none;
} }
.account-view .provider-view .list-row { .account-view .list-row {
padding: 12px; padding: 12px;
} }
.account-view .provider-view .list-row .icon { .account-view .list-row .icon {
flex: 0 0 50px; flex: 0 0 50px;
height: 50px; height: 50px;
width: 50px; width: 50px;
background-size: 50px; background-size: 50px;
} }
.account-view .provider-view .list-row .icon .badge { .account-view .list-row .icon .badge {
position: absolute; position: absolute;
top: 43px; top: 43px;
left: 43px; left: 43px;
@@ -69,17 +69,17 @@
height: 22px; height: 22px;
} }
.account-view .provider-view .list-row .icon .badge .badge-content { .account-view .list-row .icon .badge .badge-content {
width: 22px; width: 22px;
height: 22px; height: 22px;
background-size: 22px; background-size: 22px;
} }
.account-view .provider-view .list-row .actions-container { .account-view .list-row .actions-container {
flex: 0 0 50px; flex: 0 0 50px;
} }
.account-view .provider-view .list-row .actions-container .action-item .action-label { .account-view .list-row .actions-container .action-item .action-label {
width: 16px; width: 16px;
margin-left: 20px; margin-left: 20px;
margin-right: 10px; margin-right: 10px;
@@ -88,16 +88,16 @@
background-repeat: no-repeat; background-repeat: no-repeat;
} }
.account-view .provider-view .list-row .actions-container .action-item .action-label.icon.remove { .account-view .list-row .actions-container .action-item .action-label.icon.remove {
background-size: 14px !important; background-size: 14px !important;
} }
.account-view .provider-view .list-row .actions-container { .account-view .list-row .actions-container {
display: none; display: none;
} }
.account-view .provider-view .monaco-list .monaco-list-row:hover .list-row .actions-container, .account-view .monaco-list .monaco-list-row:hover .list-row .actions-container,
.account-view .provider-view .monaco-list .monaco-list-row.selected .list-row .actions-container, .account-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{ .account-view .monaco-list .monaco-list-row.focused .list-row .actions-container{
display: block; display: block;
} }

View File

@@ -17,7 +17,7 @@ import { IStatusbarItem } from 'vs/workbench/browser/parts/statusbar/statusbar';
import { Themable, STATUS_BAR_FOREGROUND } from 'vs/workbench/common/theme'; import { Themable, STATUS_BAR_FOREGROUND } from 'vs/workbench/common/theme';
import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IAccountManagementService } from 'sql/services/accountManagement/interfaces'; import { IAccountManagementService } from 'sql/platform/accountManagement/common/interfaces';
export class AccountListStatusbarItem extends Themable implements IStatusbarItem { export class AccountListStatusbarItem extends Themable implements IStatusbarItem {
private _manageLinkedAccountAction: IAction; private _manageLinkedAccountAction: IAction;

View File

@@ -8,9 +8,9 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import Severity from 'vs/base/common/severity'; import Severity from 'vs/base/common/severity';
import { localize } from 'vs/nls'; import { localize } from 'vs/nls';
import { IErrorMessageService } from 'sql/parts/connection/common/connectionManagement';
import { AutoOAuthDialog } from 'sql/parts/accountManagement/autoOAuthDialog/autoOAuthDialog'; import { AutoOAuthDialog } from 'sql/parts/accountManagement/autoOAuthDialog/autoOAuthDialog';
import { IAccountManagementService } from 'sql/services/accountManagement/interfaces'; import { IAccountManagementService } from 'sql/platform/accountManagement/common/interfaces';
import { IErrorMessageService } from 'sql/platform/errorMessage/common/errorMessageService';
export class AutoOAuthDialogController { export class AutoOAuthDialogController {
// MEMBER VARIABLES //////////////////////////////////////////////////// // MEMBER VARIABLES ////////////////////////////////////////////////////

View File

@@ -12,8 +12,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
import { Action } from 'vs/base/common/actions'; import { Action } from 'vs/base/common/actions';
import { error } from 'sql/base/common/log'; import { error } from 'sql/base/common/log';
import { IAccountManagementService } from 'sql/services/accountManagement/interfaces'; import { IAccountManagementService } from 'sql/platform/accountManagement/common/interfaces';
import { IErrorMessageService } from 'sql/parts/connection/common/connectionManagement';
import { IDialogService, IConfirmation } from 'vs/platform/dialogs/common/dialogs'; import { IDialogService, IConfirmation } from 'vs/platform/dialogs/common/dialogs';
import { INotificationService } from 'vs/platform/notification/common/notification'; import { INotificationService } from 'vs/platform/notification/common/notification';
import Severity from 'vs/base/common/severity'; import Severity from 'vs/base/common/severity';
@@ -83,7 +82,6 @@ export class RemoveAccountAction extends Action {
private _account: sqlops.Account, private _account: sqlops.Account,
@IDialogService private _dialogService: IDialogService, @IDialogService private _dialogService: IDialogService,
@INotificationService private _notificationService: INotificationService, @INotificationService private _notificationService: INotificationService,
@IErrorMessageService private _errorMessageService: IErrorMessageService,
@IAccountManagementService private _accountManagementService: IAccountManagementService @IAccountManagementService private _accountManagementService: IAccountManagementService
) { ) {
super(RemoveAccountAction.ID, RemoveAccountAction.LABEL, 'remove-account-action icon remove'); super(RemoveAccountAction.ID, RemoveAccountAction.LABEL, 'remove-account-action icon remove');
@@ -107,15 +105,15 @@ export class RemoveAccountAction extends Action {
return new TPromise((resolve, reject) => { return new TPromise((resolve, reject) => {
self._accountManagementService.removeAccount(self._account.key) self._accountManagementService.removeAccount(self._account.key)
.then( .then(
(result) => { resolve(result); }, (result) => { resolve(result); },
(err) => { (err) => {
// Must handle here as this is an independent action // Must handle here as this is an independent action
self._notificationService.notify({ self._notificationService.notify({
severity: Severity.Error, severity: Severity.Error,
message: localize('removeAccountFailed', 'Failed to remove account') message: localize('removeAccountFailed', 'Failed to remove account')
}); });
resolve(false); resolve(false);
} }
); );
}); });
} }

View File

@@ -13,13 +13,14 @@ import { Event, Emitter } from 'vs/base/common/event';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { localize } from 'vs/nls'; import { localize } from 'vs/nls';
import { buttonBackground } from 'vs/platform/theme/common/colorRegistry'; import { buttonBackground } from 'vs/platform/theme/common/colorRegistry';
import { IWorkbenchThemeService, IColorTheme } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { attachInputBoxStyler } from 'vs/platform/theme/common/styler'; import { attachInputBoxStyler } from 'vs/platform/theme/common/styler';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IWindowsService } from 'vs/platform/windows/common/windows'; import { IWindowsService } from 'vs/platform/windows/common/windows';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
import * as sqlops from 'sqlops'; import * as sqlops from 'sqlops';
import { Button } from 'sql/base/browser/ui/button/button'; import { Button } from 'sql/base/browser/ui/button/button';
@@ -27,9 +28,8 @@ import { Modal } from 'sql/base/browser/ui/modal/modal';
import { FirewallRuleViewModel } from 'sql/parts/accountManagement/firewallRuleDialog/firewallRuleViewModel'; import { FirewallRuleViewModel } from 'sql/parts/accountManagement/firewallRuleDialog/firewallRuleViewModel';
import { attachModalDialogStyler, attachButtonStyler } from 'sql/common/theme/styler'; import { attachModalDialogStyler, attachButtonStyler } from 'sql/common/theme/styler';
import { InputBox } from 'sql/base/browser/ui/inputBox/inputBox'; import { InputBox } from 'sql/base/browser/ui/inputBox/inputBox';
import { IAccountPickerService } from 'sql/parts/accountManagement/common/interfaces'; import { IAccountPickerService } from 'sql/platform/accountManagement/common/accountPicker';
import * as TelemetryKeys from 'sql/common/telemetryKeys'; import * as TelemetryKeys from 'sql/common/telemetryKeys';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
// TODO: Make the help link 1) extensible (01/08/2018, https://github.com/Microsoft/azuredatastudio/issues/450) // TODO: Make the help link 1) extensible (01/08/2018, https://github.com/Microsoft/azuredatastudio/issues/450)
// in case that other non-Azure sign in is to be used // in case that other non-Azure sign in is to be used
@@ -65,7 +65,7 @@ export class FirewallRuleDialog extends Modal {
constructor( constructor(
@IAccountPickerService private _accountPickerService: IAccountPickerService, @IAccountPickerService private _accountPickerService: IAccountPickerService,
@IPartService partService: IPartService, @IPartService partService: IPartService,
@IWorkbenchThemeService private _workbenchThemeService: IWorkbenchThemeService, @IThemeService themeService: IThemeService,
@IInstantiationService private _instantiationService: IInstantiationService, @IInstantiationService private _instantiationService: IInstantiationService,
@IContextViewService private _contextViewService: IContextViewService, @IContextViewService private _contextViewService: IContextViewService,
@ITelemetryService telemetryService: ITelemetryService, @ITelemetryService telemetryService: ITelemetryService,
@@ -79,7 +79,7 @@ export class FirewallRuleDialog extends Modal {
partService, partService,
telemetryService, telemetryService,
clipboardService, clipboardService,
_workbenchThemeService, themeService,
contextKeyService, contextKeyService,
{ {
isFlyout: true, isFlyout: true,
@@ -206,8 +206,8 @@ export class FirewallRuleDialog extends Modal {
builder.append(firewallRuleSection); builder.append(firewallRuleSection);
}); });
this._register(this._workbenchThemeService.onDidColorThemeChange(e => this.updateTheme(e))); this._register(this._themeService.onThemeChange(e => this.updateTheme(e)));
this.updateTheme(this._workbenchThemeService.getColorTheme()); this.updateTheme(this._themeService.getTheme());
$(this._IPAddressInput).on(DOM.EventType.CLICK, () => { $(this._IPAddressInput).on(DOM.EventType.CLICK, () => {
this.onFirewallRuleOptionSelected(true); this.onFirewallRuleOptionSelected(true);
@@ -243,7 +243,7 @@ export class FirewallRuleDialog extends Modal {
} }
// Update theming that is specific to firewall rule flyout body // Update theming that is specific to firewall rule flyout body
private updateTheme(theme: IColorTheme): void { private updateTheme(theme: ITheme): void {
let linkColor = theme.getColor(buttonBackground); let linkColor = theme.getColor(buttonBackground);
let link = linkColor ? linkColor.toString() : null; let link = linkColor ? linkColor.toString() : null;
if (this._helpLink) { if (this._helpLink) {

View File

@@ -9,12 +9,12 @@ import Severity from 'vs/base/common/severity';
import { localize } from 'vs/nls'; import { localize } from 'vs/nls';
import * as sqlops from 'sqlops'; import * as sqlops from 'sqlops';
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces'; import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { IErrorMessageService } from 'sql/parts/connection/common/connectionManagement';
import { FirewallRuleDialog } from 'sql/parts/accountManagement/firewallRuleDialog/firewallRuleDialog'; import { FirewallRuleDialog } from 'sql/parts/accountManagement/firewallRuleDialog/firewallRuleDialog';
import { IAccountManagementService, AzureResource } from 'sql/services/accountManagement/interfaces'; import { IAccountManagementService, AzureResource } from 'sql/platform/accountManagement/common/interfaces';
import { IResourceProviderService } from 'sql/parts/accountManagement/common/interfaces'; import { IResourceProviderService } from 'sql/workbench/services/resourceProvider/common/resourceProviderService';
import { Deferred } from 'sql/base/common/promise'; import { Deferred } from 'sql/base/common/promise';
import { IErrorMessageService } from 'sql/platform/errorMessage/common/errorMessageService';
export class FirewallRuleDialogController { export class FirewallRuleDialogController {

View File

@@ -7,8 +7,8 @@ import { ChangeDetectorRef, ElementRef, Component, forwardRef, Inject } from '@a
import { NgForm } from '@angular/forms'; import { NgForm } from '@angular/forms';
import { ITaskDialogComponentParams } from 'sql/services/bootstrap/bootstrapParams'; import { ITaskDialogComponentParams } from 'sql/services/bootstrap/bootstrapParams';
import { ConnectionManagementInfo } from 'sql/parts/connection/common/connectionManagementInfo'; import { ConnectionManagementInfo } from 'sql/platform/connection/common/connectionManagementInfo';
import { IAdminService } from 'sql/parts/admin/common/adminService'; import { IAdminService } from 'sql/workbench/services/admin/common/adminService';
import { ITaskDialogComponent } from 'sql/parts/tasks/common/tasks'; import { ITaskDialogComponent } from 'sql/parts/tasks/common/tasks';
import * as sqlops from 'sqlops'; import * as sqlops from 'sqlops';

View File

@@ -6,7 +6,7 @@
import { ElementRef, Component, Inject, forwardRef } from '@angular/core'; import { ElementRef, Component, Inject, forwardRef } from '@angular/core';
import { IBootstrapParams } from 'sql/services/bootstrap/bootstrapService'; import { IBootstrapParams } from 'sql/services/bootstrap/bootstrapService';
import { IDashboardComponentParams } from 'sql/services/bootstrap/bootstrapParams'; import { IDashboardComponentParams } from 'sql/services/bootstrap/bootstrapParams';
import { ConnectionManagementInfo } from 'sql/parts/connection/common/connectionManagementInfo'; import { ConnectionManagementInfo } from 'sql/platform/connection/common/connectionManagementInfo';
export const CREATELOGIN_SELECTOR: string = 'createlogin-component'; export const CREATELOGIN_SELECTOR: string = 'createlogin-component';
@@ -21,8 +21,8 @@ export class CreateLoginComponent {
public connection: ConnectionManagementInfo; public connection: ConnectionManagementInfo;
constructor( constructor(
@Inject(forwardRef(() => ElementRef)) private _el: ElementRef, @Inject(forwardRef(() => ElementRef)) private _el: ElementRef,
@Inject(IBootstrapParams) private _params: IDashboardComponentParams @Inject(IBootstrapParams) private _params: IDashboardComponentParams
) { ) {
} }
} }

View File

@@ -11,11 +11,11 @@ import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { CreateLoginInput } from './createLoginInput'; import { CreateLoginInput } from 'sql/parts/admin/security/createLoginInput';
import { CreateLoginModule } from './createLogin.module'; import { CreateLoginModule } from 'sql/parts/admin/security/createLogin.module';
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement'; import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
import { IMetadataService } from 'sql/services/metadata/metadataService'; import { IMetadataService } from 'sql/platform/metadata/common/metadataService';
import { IScriptingService } from 'sql/services/scripting/scriptingService'; import { IScriptingService } from 'sql/platform/scripting/common/scriptingService';
import { IQueryEditorService } from 'sql/parts/query/common/queryEditorService'; import { IQueryEditorService } from 'sql/parts/query/common/queryEditorService';
import { bootstrapAngular, IBootstrapParams } from 'sql/services/bootstrap/bootstrapService'; import { bootstrapAngular, IBootstrapParams } from 'sql/services/bootstrap/bootstrapService';
import { CREATELOGIN_SELECTOR } from 'sql/parts/admin/security/createLogin.component'; import { CREATELOGIN_SELECTOR } from 'sql/parts/admin/security/createLogin.component';

View File

@@ -6,7 +6,7 @@
import { TPromise } from 'vs/base/common/winjs.base'; import { TPromise } from 'vs/base/common/winjs.base';
import { EditorInput, EditorModel } from 'vs/workbench/common/editor'; import { EditorInput, EditorModel } from 'vs/workbench/common/editor';
import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput'; import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput';
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces'; import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
export class CreateLoginInput extends EditorInput { export class CreateLoginInput extends EditorInput {

View File

@@ -3,8 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as path from 'path';
import { EditorInput, IEditorInput } from 'vs/workbench/common/editor'; import { EditorInput, IEditorInput } from 'vs/workbench/common/editor';
import { IInstantiationService, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput'; import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput';
@@ -16,8 +14,8 @@ import { QueryInput } from 'sql/parts/query/common/queryInput';
import { IQueryEditorOptions } from 'sql/parts/query/common/queryEditorService'; import { IQueryEditorOptions } from 'sql/parts/query/common/queryEditorService';
import { QueryPlanInput } from 'sql/parts/queryPlan/queryPlanInput'; import { QueryPlanInput } from 'sql/parts/queryPlan/queryPlanInput';
import { NotebookInput, NotebookInputModel, NotebookInputValidator } from 'sql/parts/notebook/notebookInput'; import { NotebookInput, NotebookInputModel, NotebookInputValidator } from 'sql/parts/notebook/notebookInput';
import { DEFAULT_NOTEBOOK_PROVIDER, INotebookService } from 'sql/services/notebook/notebookService'; import { DEFAULT_NOTEBOOK_PROVIDER, INotebookService } from 'sql/workbench/services/notebook/common/notebookService';
import { getProvidersForFileName } from 'sql/parts/notebook/notebookUtils'; import { getProvidersForFileName, getStandardKernelsForProvider } from 'sql/parts/notebook/notebookUtils';
import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput'; import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput';
const fs = require('fs'); const fs = require('fs');
@@ -71,6 +69,10 @@ export function convertEditorInput(input: EditorInput, options: IQueryEditorOpti
let notebookInputModel = new NotebookInputModel(uri, undefined, false, undefined); let notebookInputModel = new NotebookInputModel(uri, undefined, false, undefined);
notebookInputModel.providerId = providerIds.filter(provider => provider !== DEFAULT_NOTEBOOK_PROVIDER)[0]; notebookInputModel.providerId = providerIds.filter(provider => provider !== DEFAULT_NOTEBOOK_PROVIDER)[0];
notebookInputModel.providers = providerIds; notebookInputModel.providers = providerIds;
notebookInputModel.providers.forEach(provider => {
let standardKernels = getStandardKernelsForProvider(provider, notebookService);
notebookInputModel.standardKernels = standardKernels;
});
let notebookInput: NotebookInput = instantiationService.createInstance(NotebookInput, fileName, notebookInputModel); let notebookInput: NotebookInput = instantiationService.createInstance(NotebookInput, fileName, notebookInputModel);
return notebookInput; return notebookInput;
}); });

View File

@@ -8,8 +8,8 @@ import { Action } from 'vs/base/common/actions';
import { TPromise } from 'vs/base/common/winjs.base'; import { TPromise } from 'vs/base/common/winjs.base';
import { Event, Emitter } from 'vs/base/common/event'; import { Event, Emitter } from 'vs/base/common/event';
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces'; import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement'; import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
import { INotificationService, INotificationActions } from 'vs/platform/notification/common/notification'; import { INotificationService, INotificationActions } from 'vs/platform/notification/common/notification';
import Severity from 'vs/base/common/severity'; import Severity from 'vs/base/common/severity';
import { IDialogService, IConfirmation, IConfirmationResult } from 'vs/platform/dialogs/common/dialogs'; import { IDialogService, IConfirmation, IConfirmationResult } from 'vs/platform/dialogs/common/dialogs';
@@ -159,7 +159,7 @@ export class GetCurrentConnectionStringAction extends Action {
return new TPromise<void>((resolve, reject) => { return new TPromise<void>((resolve, reject) => {
let activeInput = this._editorService.activeEditor; let activeInput = this._editorService.activeEditor;
if (activeInput && (activeInput instanceof QueryInput || activeInput instanceof EditDataInput || activeInput instanceof DashboardInput) if (activeInput && (activeInput instanceof QueryInput || activeInput instanceof EditDataInput || activeInput instanceof DashboardInput)
&& this._connectionManagementService.isConnected(activeInput.uri)) { && this._connectionManagementService.isConnected(activeInput.uri)) {
let includePassword = false; let includePassword = false;
let connectionProfile = this._connectionManagementService.getConnectionProfile(activeInput.uri); let connectionProfile = this._connectionManagementService.getConnectionProfile(activeInput.uri);
this._connectionManagementService.getConnectionString(connectionProfile.id, includePassword).then(result => { this._connectionManagementService.getConnectionString(connectionProfile.id, includePassword).then(result => {

View File

@@ -7,9 +7,9 @@ import { IDisposable, combinedDisposable } from 'vs/base/common/lifecycle';
import { IStatusbarItem } from 'vs/workbench/browser/parts/statusbar/statusbar'; import { IStatusbarItem } from 'vs/workbench/browser/parts/statusbar/statusbar';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService'; import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement'; import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService'; import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService';
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces'; import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { IObjectExplorerService } from 'sql/parts/objectExplorer/common/objectExplorerService'; import { IObjectExplorerService } from 'sql/parts/objectExplorer/common/objectExplorerService';
import * as TaskUtilities from 'sql/workbench/common/taskUtilities'; import * as TaskUtilities from 'sql/workbench/common/taskUtilities';
import { EditorServiceImpl } from 'vs/workbench/browser/parts/editor/editor'; import { EditorServiceImpl } from 'vs/workbench/browser/parts/editor/editor';

View File

@@ -13,8 +13,6 @@ import { localize } from 'vs/nls';
import * as TelemetryKeys from 'sql/common/telemetryKeys'; import * as TelemetryKeys from 'sql/common/telemetryKeys';
export class AdvancedPropertiesController { export class AdvancedPropertiesController {
private _container: HTMLElement;
private _advancedDialog: OptionsDialog; private _advancedDialog: OptionsDialog;
private _options: { [name: string]: any }; private _options: { [name: string]: any };
@@ -30,7 +28,6 @@ export class AdvancedPropertiesController {
public showDialog(providerOptions: sqlops.ConnectionOption[], container: HTMLElement, options: { [name: string]: any }): void { public showDialog(providerOptions: sqlops.ConnectionOption[], container: HTMLElement, options: { [name: string]: any }): void {
this._options = options; this._options = options;
this._container = container;
var serviceOptions = providerOptions.map(option => AdvancedPropertiesController.connectionOptionToServiceOption(option)); var serviceOptions = providerOptions.map(option => AdvancedPropertiesController.connectionOptionToServiceOption(option));
this.advancedDialog.open(serviceOptions, this._options); this.advancedDialog.open(serviceOptions, this._options);
} }
@@ -38,8 +35,7 @@ export class AdvancedPropertiesController {
public get advancedDialog() { public get advancedDialog() {
if (!this._advancedDialog) { if (!this._advancedDialog) {
this._advancedDialog = this._instantiationService.createInstance( this._advancedDialog = this._instantiationService.createInstance(
OptionsDialog, localize('connectionAdvancedProperties', 'Advanced Properties'), TelemetryKeys.ConnectionAdvancedProperties, { hasBackButton: true }); OptionsDialog, localize('connectionAdvancedProperties', 'Advanced Properties'), TelemetryKeys.ConnectionAdvancedProperties, { hasBackButton: true, cancelLabel: localize('advancedProperties.discard', 'Discard') });
this._advancedDialog.cancelLabel = localize('advancedProperties.discard', 'Discard');
this._advancedDialog.onCloseEvent(() => this._onCloseAdvancedProperties()); this._advancedDialog.onCloseEvent(() => this._onCloseAdvancedProperties());
this._advancedDialog.onOk(() => this.handleOnOk()); this._advancedDialog.onOk(() => this.handleOnOk());
this._advancedDialog.render(); this._advancedDialog.render();

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