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": [
"--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": [

View File

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

View File

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

View File

@@ -94,6 +94,9 @@ export class JobDialog extends AgentDialog<JobData> {
private editStepButton: sqlops.ButtonComponent;
private deleteStepButton: sqlops.ButtonComponent;
// Schedule tab controls
private removeScheduleButton: sqlops.ButtonComponent;
// Notifications tab controls
private notificationsTabTopLabel: sqlops.TextComponent;
private emailCheckBox: sqlops.CheckBoxComponent;
@@ -302,6 +305,7 @@ export class JobDialog extends AgentDialog<JobData> {
this.stepsTable.data = this.convertStepsToData(this.steps);
this.steps[previousRow].id = previousStepId;
this.steps[rowNumber].id = currentStepId;
this.stepsTable.selectedRows = [previousRow];
});
this.moveStepDownButton.onDidClick(() => {
@@ -316,6 +320,7 @@ export class JobDialog extends AgentDialog<JobData> {
this.stepsTable.data = this.convertStepsToData(this.steps);
this.steps[nextRow].id = nextStepId;
this.steps[rowNumber].id = currentStepId;
this.stepsTable.selectedRows = [nextRow];
});
this.editStepButton.onDidClick(() => {
@@ -346,20 +351,30 @@ export class JobDialog extends AgentDialog<JobData> {
if (this.stepsTable.selectedRows.length === 1) {
let rowNumber = this.stepsTable.selectedRows[0];
AgentUtils.getAgentService().then((agentService) => {
let steps = this.model.jobSteps ? this.model.jobSteps : [];
let stepData = this.model.jobSteps[rowNumber];
agentService.deleteJobStep(this.ownerUri, stepData).then((result) => {
if (result && result.success) {
delete steps[rowNumber];
let data = this.convertStepsToData(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;
}
});
let stepData = this.steps[rowNumber];
if (stepData.jobId) {
agentService.deleteJobStep(this.ownerUri, stepData).then((result) => {
if (result && result.success) {
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;
}
});
} 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,
width: 80
}).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);
pickScheduleDialog.onSuccess((dialogModel) => {
let selectedSchedule = dialogModel.selectedSchedule;
@@ -483,12 +502,23 @@ export class JobDialog extends AgentDialog<JobData> {
});
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()
.withFormItems([{
component: this.schedulesTable,
title: this.SchedulesTopLabelString,
actions: [this.pickScheduleButton]
actions: [this.pickScheduleButton, this.removeScheduleButton]
}]).withLayout({ width: '100%' }).component();
await view.initializeModel(formModel);
@@ -499,10 +529,9 @@ export class JobDialog extends AgentDialog<JobData> {
private populateScheduleTable() {
let data = this.convertSchedulesToData(this.schedules);
if (data.length > 0) {
this.schedulesTable.data = data;
this.schedulesTable.height = 750;
}
this.schedulesTable.data = data;
this.schedulesTable.height = 750;
}
private initializeNotificationsTab() {
@@ -674,5 +703,6 @@ export class JobDialog extends AgentDialog<JobData> {
this.model.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 OpenCommandText: string = localize('jobStepDialog.open', 'Open...');
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 FailureParseText: string = localize('jobStepDialog.failParse', 'The command failed.');
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
private readonly StepNameLabelString: string = localize('jobStepDialog.stepNameLabel', 'Step Name');
@@ -62,6 +61,8 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
// Dropdown options
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 NextStep: string = localize('jobStepDialog.nextStep', 'Go to the next step');
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 fileBrowserNameBox: sqlops.InputBoxComponent;
private userInputBox: sqlops.InputBoxComponent;
private processExitCodeBox: sqlops.InputBoxComponent;
// Dropdowns
private typeDropdown: sqlops.DropDownComponent;
@@ -100,8 +102,6 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
// Buttons
private openButton: sqlops.ButtonComponent;
private parseButton: sqlops.ButtonComponent;
private nextButton: sqlops.ButtonComponent;
private previousButton: sqlops.ButtonComponent;
private outputFileBrowserButton: sqlops.ButtonComponent;
// Checkbox
@@ -179,18 +179,6 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
inputType: 'text'
})
.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) {
@@ -208,7 +196,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
this.typeDropdown = view.modelBuilder.dropDown()
.withProperties({
value: this.TSQLScript,
values: [this.TSQLScript]
values: [this.TSQLScript, this.CmdExec, this.Powershell]
})
.component();
this.runAsDropdown = view.modelBuilder.dropDown()
@@ -218,33 +206,20 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
})
.component();
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()
.withProperties({
value: databases[0],
values: databases
}).component();
this.processExitCodeBox = view.modelBuilder.inputBox()
.withProperties({
}).component();
this.processExitCodeBox.enabled = false;
// create the commands section
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()
.withFormItems([{
component: this.nameTextBox,
@@ -258,14 +233,52 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
}, {
component: this.databaseDropdown,
title: this.DatabaseLabelString
}, {
component: this.processExitCodeBox,
title: this.ProcessExitCodeText
}, {
component: this.commandTextBox,
title: this.CommandLabelString,
actions: [buttonContainer]
actions: [this.openButton, this.parseButton]
}], {
horizontal: false,
componentWidth: 420
}).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();
formWrapper.loading = false;
await view.initializeModel(formWrapper);
@@ -524,6 +537,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
this.model.outputFileName = this.outputFileNameBox.value;
this.model.appendToLogFile = this.appendToExistingFileCheckbox.checked;
this.model.command = this.commandTextBox.value ? this.commandTextBox.value : '';
this.model.commandExecutionSuccessCode = this.processExitCodeBox.value ? +this.processExitCodeBox.value : 0;
}
public async initializeDialog() {

View File

@@ -90,12 +90,9 @@ export class AzureResourceAccountTreeNode extends AzureResourceContainerTreeNode
}
} catch (error) {
if (error instanceof AzureResourceCredentialError) {
this.appContext.apiWrapper.showErrorMessage(error.message);
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);
}
if (!this.isSystemInitialized) {
if (!this.isSystemInitialized && !this._loadingTimer) {
this._loadingTimer = setInterval(async () => {
try {
// 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];
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 */
}
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 { registerAzureResourceDatabaseCommands } from '../azureResource/providers/database/commands';
import { equals } from '../azureResource/utils';
export default class AzureResourceController extends ControllerBase {
public activate(): Promise<boolean> {
@@ -37,7 +38,16 @@ export default class AzureResourceController extends ControllerBase {
const azureResourceTree = new AzureResourceTreeProvider(this.appContext);
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);

View File

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

View File

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

View File

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

View File

@@ -8,6 +8,7 @@ import * as nls from 'vscode-nls';
import * as sqlops from 'sqlops';
import { SelectOperationPage } from './pages/selectOperationpage';
import { DeployConfigPage } from './pages/deployConfigPage';
import { DeployActionPage } from './pages/deployActionPage';
import { DacFxSummaryPage } from './pages/dacFxSummaryPage';
import { ExportConfigPage } from './pages/exportConfigPage';
import { ExtractConfigPage } from './pages/extractConfigPage';
@@ -30,7 +31,33 @@ export enum Operation {
deploy,
extract,
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 {
@@ -60,6 +87,7 @@ export class DataTierApplicationWizard {
this.wizard = sqlops.window.modelviewdialog.createWizard('Data-tier Application Wizard');
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 deployActionWizardPage = sqlops.window.modelviewdialog.createWizardPage(localize('dacFx.deployActionPageName', 'Select Action'));
let summaryWizardPage = sqlops.window.modelviewdialog.createWizardPage(localize('dacFx.summaryPageName', 'Summary'));
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'));
@@ -67,6 +95,7 @@ export class DataTierApplicationWizard {
this.pages.set('selectOperation', new Page(selectOperationWizardPage));
this.pages.set('deployConfig', new Page(deployConfigWizardPage));
this.pages.set('deployAction', new Page(deployActionWizardPage));
this.pages.set('extractConfig', new Page(extractConfigWizardPage));
this.pages.set('importConfig', new Page(importConfigWizardPage));
this.pages.set('exportConfig', new Page(exportConfigWizardPage));
@@ -87,6 +116,12 @@ export class DataTierApplicationWizard {
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) => {
let extractConfigDacFxPage = new ExtractConfigPage(this, extractConfigWizardPage, this.model, view);
this.pages.get('extractConfig').dacFxPage = extractConfigDacFxPage;
@@ -113,39 +148,27 @@ export class DataTierApplicationWizard {
this.wizard.onPageChanged(async (event) => {
let idx = event.newPage;
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 (idx === 2) {
page = this.pages.get('summary');
}
let page = this.getPage(idx);
if (page !== undefined) {
page.dacFxPage.setupNavigationValidator();
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.onClick(async () => await this.generateDeployScript());
this.wizard.doneButton.onClick(async () => await this.executeOperation());
this.wizard.open();
@@ -177,6 +200,15 @@ export class DataTierApplicationWizard {
this.selectedOperation = Operation.export;
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();
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> {
let service = sqlops.dataprotocol.getProvider<sqlops.DacFxServicesProvider>(providerName, sqlops.DataProviderType.DacFxServicesProvider);
return service;

View File

@@ -49,6 +49,14 @@ export class DacFxSummaryPage extends BasePage {
async onPageEnter(): Promise<boolean> {
this.populateTable();
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;
}
@@ -68,6 +76,10 @@ export class DacFxSummaryPage extends BasePage {
let sourceServer = localize('dacfx.sourceServerName', 'Source Server');
let sourceDatabase = localize('dacfx.sourceDatabaseName', 'Source Database');
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) {
case Operation.deploy: {
@@ -75,6 +87,13 @@ export class DacFxSummaryPage extends BasePage {
[targetServer, this.model.serverName],
[fileLocation, this.model.filePath],
[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;
}
case Operation.extract: {
@@ -99,12 +118,21 @@ export class DacFxSummaryPage extends BasePage {
[fileLocation, this.model.filePath]];
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({
data: data,
columns: ['Setting', 'Value'],
width: 600,
width: 700,
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> {
let numPages = this.instance.wizard.pages.length;
for (let i = numPages - 1; i > 2; --i) {
await this.instance.wizard.removePage(i);
}
return true;
}
@@ -74,12 +69,14 @@ export class SelectOperationPage extends BasePage {
}).component();
this.deployRadioButton.onDidClick(() => {
// remove the previous page
this.instance.wizard.removePage(1);
this.removePages();
// add deploy page
let page = this.instance.pages.get('deployConfig');
this.instance.wizard.addPage(page.wizardPage, 1);
//add deploy pages
let configPage = this.instance.pages.get('deployConfig');
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
this.instance.setDoneButton(Operation.deploy);
@@ -99,12 +96,12 @@ export class SelectOperationPage extends BasePage {
}).component();
this.extractRadioButton.onDidClick(() => {
// remove the previous pages
this.instance.wizard.removePage(1);
this.removePages();
// add the extract page
let page = this.instance.pages.get('extractConfig');
this.instance.wizard.addPage(page.wizardPage, 1);
this.addSummaryPage(2);
// change button text and operation
this.instance.setDoneButton(Operation.extract);
@@ -124,12 +121,12 @@ export class SelectOperationPage extends BasePage {
}).component();
this.importRadioButton.onDidClick(() => {
// remove the previous page
this.instance.wizard.removePage(1);
this.removePages();
// add the import page
let page = this.instance.pages.get('importConfig');
this.instance.wizard.addPage(page.wizardPage, 1);
this.addSummaryPage(2);
// change button text and operation
this.instance.setDoneButton(Operation.import);
@@ -149,12 +146,12 @@ export class SelectOperationPage extends BasePage {
}).component();
this.exportRadioButton.onDidClick(() => {
// remove the 2 previous pages
this.instance.wizard.removePage(1);
this.removePages();
// add the export pages
let page = this.instance.pages.get('exportConfig');
this.instance.wizard.addPage(page.wizardPage, 1);
this.addSummaryPage(2);
// change button text and operation
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() {
this.instance.registerNavigationValidator(() => {
return true;

View File

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

View File

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

View File

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

View File

@@ -331,6 +331,14 @@ export interface DeployParams {
taskExecutionMode: TaskExecutionMode;
}
export interface GenerateDeployScriptParams {
packageFilePath: string;
databaseName: string;
scriptFilePath: string;
ownerUri: string;
taskExecutionMode: TaskExecutionMode;
}
export namespace ExportRequest {
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 namespace GenerateDeployScriptRequest {
export const type = new RequestType<GenerateDeployScriptParams, sqlops.DacFxResult, void, void>('dacfx/generateDeploymentScript');
}
// ------------------------------- < 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({
providerId: client.providerId,
exportBacpac,
importBacpac,
extractDacpac,
deployDacpac
deployDacpac,
generateDeployScript
});
}
}

View File

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

View File

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

View File

@@ -106,7 +106,7 @@ export class CreateSessionDialog {
private updateSessionName() {
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",
"version": "1.4.1",
"version": "1.4.3",
"distro": "8c3e97e3425cc9814496472ab73e076de2ba99ee",
"author": {
"name": "Microsoft Corporation"

View File

@@ -62,6 +62,12 @@
<trans-unit id="sql.saveAsCsv.encoding">
<source xml:lang="en">[Optional] File encoding used when saving results as CSV</source>
</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">
<source xml:lang="en">[Optional] Configuration options for copying results from the Results View</source>
</trans-unit>
@@ -596,6 +602,9 @@
<trans-unit id="saveAsExcel">
<source xml:lang="en">Save As Excel</source>
</trans-unit>
<trans-unit id="saveAsXml">
<source xml:lang="en">Save As XML</source>
</trans-unit>
<trans-unit id="copySelection">
<source xml:lang="en">Copy</source>
</trans-unit>
@@ -1142,6 +1151,9 @@
<trans-unit id="saveExcelLabel">
<source xml:lang="en">Save as Excel</source>
</trans-unit>
<trans-unit id="saveXMLLabel">
<source xml:lang="en">Save as XML</source>
</trans-unit>
<trans-unit id="viewChartLabel">
<source xml:lang="en">View as Chart</source>
</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 { Router } from '@angular/router';
import { toDisposableSubscription } from 'sql/parts/common/rxjsUtils';
import { toDisposableSubscription } from 'sql/base/node/rxjsUtils';
import { IBreadcrumbService, MenuItem } from './interfaces';
import { IDisposable } from 'vs/base/common/lifecycle';

View File

@@ -11,7 +11,7 @@ import {
} from '@angular/core';
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 { attachEditableDropdownStyler } from 'sql/common/theme/styler';

View File

@@ -11,7 +11,7 @@ import {
} from '@angular/core';
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 { 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.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 });
}
/**
* 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

View File

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

View File

@@ -12,7 +12,7 @@ import './panelStyles';
import { TabComponent } from './tab.component';
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 { 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 { ScrollbarVisibility } from 'vs/base/common/scrollable';
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({
selector: '[scrollable]'
@@ -74,7 +74,7 @@ export class ScrollableDirective extends AngularDisposable {
private resetScrollDimensions() {
this.scrollableElement.setScrollDimensions({
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,
width: this.horizontalScroll === ScrollbarVisibility.Auto ? this.scrolled.offsetWidth : undefined
});

View File

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

View File

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

View File

@@ -6,35 +6,49 @@
'use strict';
import 'vs/css!./scrollableSplitview';
import { HeightMap, IView as HeightIView, IViewItem as HeightIViewItem } from './heightMap';
import { IDisposable, combinedDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { mapEvent, Emitter, Event, debounceEvent } from 'vs/base/common/event';
import * as types from 'vs/base/common/types';
import * as dom from 'vs/base/browser/dom';
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 { 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 { mixin } from 'vs/base/common/objects';
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 interface ISplitViewOptions {
orientation?: Orientation; // default Orientation.VERTICAL
styles?: ISplitViewStyles;
orthogonalStartSash?: Sash;
orthogonalEndSash?: Sash;
inverseAltBehavior?: boolean;
enableResizing?: boolean;
scrollDebounce?: number;
verticalScrollbarVisibility?: ScrollbarVisibility;
}
const defaultStyles: ISplitViewStyles = {
separatorBorder: Color.transparent
};
const defaultOptions: ISplitViewOptions = {
enableResizing: true
};
export interface IView extends HeightIView {
readonly element: HTMLElement;
readonly minimumSize: number;
readonly maximumSize: number;
readonly onDidChange: Event<number | undefined>;
render(container: HTMLElement, orientation: Orientation): void;
layout(size: number, orientation: Orientation): void;
onAdd?(): void;
onRemove?(): void;
@@ -44,6 +58,7 @@ interface ISashEvent {
sash: Sash;
start: number;
current: number;
alt: boolean;
}
interface IViewItem extends HeightIViewItem {
@@ -64,7 +79,12 @@ interface ISashItem {
interface ISashDragState {
index: number;
start: number;
current: number;
sizes: number[];
minDelta: number;
maxDelta: number;
alt: boolean;
disposable: IDisposable;
}
enum State {
@@ -95,24 +115,28 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
private orientation: Orientation;
private el: HTMLElement;
private sashContainer: HTMLElement;
private viewContainer: HTMLElement;
private scrollable: ScrollableElement;
private size = 0;
private contentSize = 0;
private proportions: undefined | number[] = undefined;
private viewItems: IViewItem[] = [];
private sashItems: ISashItem[] = [];
private sashDragState: ISashDragState;
private state: State = State.Idle;
private scrollable: ScrollableElement;
private inverseAltBehavior: boolean;
private lastRenderHeight: number;
private lastRenderTop: number;
private options: ISplitViewOptions;
private dirtyState = false;
private lastRenderTop: number;
private lastRenderHeight: number;
private _onDidSashChange = new Emitter<void>();
private _onDidSashChange = new Emitter<number>();
readonly onDidSashChange = this._onDidSashChange.event;
private _onDidSashReset = new Emitter<void>();
private _onDidSashReset = new Emitter<number>();
readonly onDidSashReset = this._onDidSashReset.event;
private _onScroll = new Emitter<number>();
@@ -122,15 +146,48 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
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 = {}) {
super();
this.orientation = types.isUndefined(options.orientation) ? Orientation.VERTICAL : options.orientation;
this.inverseAltBehavior = !!options.inverseAltBehavior;
this.options = mixin(options, defaultOptions, false);
this.el = document.createElement('div');
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.relayout();
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, this.orientation === Orientation.VERTICAL ? 'vertical' : 'horizontal');
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) {
throw new Error('Cant modify splitview');
}
@@ -150,16 +222,23 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
this.state = State.Busy;
for (let i = 0; i < views.length; i++) {
let viewIndex = index + i;
let view = views[i], size = sizes[i];
let size: number | Sizing;
if (Array.isArray(sizes)) {
size = sizes[i];
} else {
size = sizes;
}
const view = views[i];
view.id = view.id || generateUuid();
// Add 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 containerDisposable = toDisposable(() => {
if (container.parentElement) {
this.el.removeChild(container);
this.viewContainer.removeChild(container);
}
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 layoutContainer = this.orientation === Orientation.VERTICAL
? size => item.container.style.height = `${item.size}px`
: size => item.container.style.width = `${item.size}px`;
? () => item.container.style.height = `${item.size}px`
: () => item.container.style.width = `${item.size}px`;
const layout = () => {
layoutContainer(item.size);
layoutContainer();
item.view.layout(item.size, this.orientation);
};
size = Math.round(size);
const item: IViewItem = { onRemove, onAdd, view, container, size, layout, disposable, height: size, top: 0, width: 0 };
this.viewItems.splice(viewIndex, 0, item);
let viewSize: number;
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
if (this.options.enableResizing && this.viewItems.length > 1) {
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 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
? (e: IBaseSashEvent) => ({ sash, start: e.startY, current: e.currentY })
: (e: IBaseSashEvent) => ({ sash, start: e.startX, current: e.currentX });
? (e: IBaseSashEvent) => ({ sash, start: e.startY, current: e.currentY, alt: e.altKey } as ISashEvent)
: (e: IBaseSashEvent) => ({ sash, start: e.startX, current: e.currentX, alt: e.altKey } as ISashEvent);
const onStart = mapEvent(sash.onDidStart, sashEventMapper);
const onStartDisposable = onStart(this.onSashStart, this);
const onChange = mapEvent(sash.onDidChange, sashEventMapper);
const onSashChangeDisposable = onChange(this.onSashChange, this);
const onEnd = mapEvent<void, void>(sash.onDidEnd, () => null);
const onEndDisposable = onEnd(() => this._onDidSashChange.fire());
const onDidReset = mapEvent<void, void>(sash.onDidReset, () => null);
const onDidResetDisposable = onDidReset(() => this._onDidSashReset.fire());
const onChangeDisposable = onChange(this.onSashChange, this);
const onEnd = mapEvent(sash.onDidEnd, () => firstIndex(this.sashItems, item => item.sash === sash));
const onEndDisposable = onEnd(this.onSashEnd, this);
const onDidResetDisposable = sash.onDidReset(() => this._onDidSashReset.fire(firstIndex(this.sashItems, item => item.sash === sash)));
const disposable = combinedDisposable([onStartDisposable, onSashChangeDisposable, onEndDisposable, onDidResetDisposable, sash]);
const disposable = combinedDisposable([onStartDisposable, onChangeDisposable, onEndDisposable, onDidResetDisposable, sash]);
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;
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) {
throw new Error('Cant modify splitview');
}
this.state = State.Busy;
view.id = view.id || generateUuid();
// Add 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 containerDisposable = toDisposable(() => {
if (container.parentElement) {
this.el.removeChild(container);
this.viewContainer.removeChild(container);
}
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 layoutContainer = this.orientation === Orientation.VERTICAL
? size => item.container.style.height = `${item.size}px`
: size => item.container.style.width = `${item.size}px`;
? () => item.container.style.height = `${item.size}px`
: () => item.container.style.width = `${item.size}px`;
const layout = () => {
layoutContainer(item.size);
layoutContainer();
item.view.layout(item.size, this.orientation);
};
size = Math.round(size);
const item: IViewItem = { onAdd, onRemove, view, container, size, layout, disposable, height: size, top: 0, width: 0 };
let viewSize: number;
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);
@@ -255,33 +369,47 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
if (this.options.enableResizing && this.viewItems.length > 1) {
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 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
? (e: IBaseSashEvent) => ({ sash, start: e.startY, current: e.currentY })
: (e: IBaseSashEvent) => ({ sash, start: e.startX, current: e.currentX });
? (e: IBaseSashEvent) => ({ sash, start: e.startY, current: e.currentY, alt: e.altKey } as ISashEvent)
: (e: IBaseSashEvent) => ({ sash, start: e.startX, current: e.currentX, alt: e.altKey } as ISashEvent);
const onStart = mapEvent(sash.onDidStart, sashEventMapper);
const onStartDisposable = onStart(this.onSashStart, this);
const onChange = mapEvent(sash.onDidChange, sashEventMapper);
const onSashChangeDisposable = onChange(this.onSashChange, this);
const onEnd = mapEvent<void, void>(sash.onDidEnd, () => null);
const onEndDisposable = onEnd(() => this._onDidSashChange.fire());
const onDidReset = mapEvent<void, void>(sash.onDidReset, () => null);
const onDidResetDisposable = onDidReset(() => this._onDidSashReset.fire());
const onChangeDisposable = onChange(this.onSashChange, this);
const onEnd = mapEvent(sash.onDidEnd, () => firstIndex(this.sashItems, item => item.sash === sash));
const onEndDisposable = onEnd(this.onSashEnd, this);
const onDidResetDisposable = sash.onDidReset(() => this._onDidSashReset.fire(firstIndex(this.sashItems, item => item.sash === sash)));
const disposable = combinedDisposable([onStartDisposable, onSashChangeDisposable, onEndDisposable, onDidResetDisposable, sash]);
const disposable = combinedDisposable([onStartDisposable, onChangeDisposable, onEndDisposable, onDidResetDisposable, sash]);
const sashItem: ISashItem = { sash, disposable };
sash.hide();
this.sashItems.splice(index - 1, 0, sashItem);
}
view.render(container, this.orientation);
this.relayout(index);
container.appendChild(view.element);
let highPriorityIndex: number | undefined;
if (typeof size !== 'number' && size.type === 'split') {
highPriorityIndex = size.index;
}
this.relayout(index, highPriorityIndex);
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) {
throw new Error('Cant modify splitview');
}
@@ -289,7 +417,7 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
this.state = State.Busy;
if (index < 0 || index >= this.viewItems.length) {
return;
throw new Error('Index out of bounds');
}
// Remove view
@@ -301,12 +429,16 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
const sashIndex = Math.max(index - 1, 0);
const sashItem = this.sashItems.splice(sashIndex, 1)[0];
sashItem.disposable.dispose();
} else {
this.lastRenderHeight = NaN, this.lastRenderTop = NaN;
}
this.relayout();
this.state = State.Idle;
if (sizing && sizing.type === 'distribute') {
this.distributeViewSizes();
}
return viewItem.view;
}
moveView(from: number, to: number): void {
@@ -314,36 +446,36 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
throw new Error('Cant modify splitview');
}
this.state = State.Busy;
if (from < 0 || from >= this.viewItems.length) {
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;
const size = this.getViewSize(from);
const view = this.removeView(from);
this.addView(view, size, to);
}
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);
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) {
@@ -351,14 +483,188 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
}
layout(size: number): void {
const previousSize = this.size;
const previousSize = Math.max(this.size, this.contentSize);
this.size = size;
this.contentSize = 0;
this.lastRenderHeight = 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 {
let i: number;
let stop: number;
@@ -398,96 +704,13 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
let topItem = this.itemAtIndex(this.indexAt(renderTop));
if (topItem) {
this.el.style.top = (topItem.top - renderTop) + 'px';
this.viewContainer.style.top = (topItem.top - renderTop) + 'px';
}
this.lastRenderTop = 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
private insertItemInDOM(item: IViewItem): boolean {
@@ -503,13 +726,13 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
}
if (elementAfter === null) {
this.el.appendChild(item.container);
this.viewContainer.appendChild(item.container);
} else {
try {
this.el.insertBefore(item.container, elementAfter);
this.viewContainer.insertBefore(item.container, elementAfter);
} catch (e) {
// 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;
}
this.el.removeChild(item.container);
this.viewContainer.removeChild(item.container);
item.onRemove();
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) {
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 {
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;
}
}
private distributeEmptySpace(): void {
let contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
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 size = clamp(item.size + emptyDelta, item.view.minimumSize, item.view.maximumSize);
const viewDelta = size - item.size;
emptyDelta -= viewDelta;
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 {
// Save new content size
this.contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
if (this.dirtyState) {
for (let i = this.indexAt(this.lastRenderTop); i <= this.indexAfter(this.lastRenderTop + this.lastRenderHeight) - 1; i++) {
this.viewItems[i].layout();
@@ -613,27 +845,10 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
this.dirtyState = false;
}
// Update sashes enablement
// let previous = false;
// const collapsesDown = this.viewItems.map(i => previous = (i.size - i.view.minimumSize > 0) || previous);
// 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();
// }
// });
this.scrollable.setScrollDimensions({
scrollHeight: this.contentSize,
height: this.size
});
}
private getSashPosition(sash: Sash): number {

View File

@@ -11,7 +11,7 @@ import {
} from '@angular/core';
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 { 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() {
this.onAsyncResponse.subscribe((e, args) => {
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
@@ -278,7 +278,7 @@ export class RowDetailView {
item._isPadding = false;
item._parent = parent;
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;
return item;
}
@@ -349,15 +349,13 @@ export class RowDetailView {
//slick-cell to escape the cell overflow clipping.
//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("style='height:", dataContext._height, "px;"); //set total height of padding
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='innerDetailView_", dataContext.id, "'>", escape(dataContext._detailContent), "</div></div>");
/* tslint:enable:no-unexternalized-strings */
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(`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='innerDetailView_${dataContext.id}'>${escape(dataContext._detailContent)}</div></div>`);
//&omit a final closing detail container </div> that would come next
return html.join('');
@@ -401,9 +399,9 @@ export class RowDetailView {
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) {
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);

View File

@@ -15,7 +15,6 @@ const sizePerDigit = 15;
export class RowNumberColumn<T> implements Slick.Plugin<T> {
private handler = new Slick.EventHandler();
private grid: Slick.Grid<T>;
private currentColumnWidth: number;
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> {
// 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 {
id: 'rowNumber',
name: '',
field: 'rowNumber',
width: this.currentColumnWidth,
resizable: false,
width: 22,
resizable: true,
cssClass: this.options.cssClass,
focusable: 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> {
//The data exposed publicly, when filter is enabled, _data holds the filtered data.
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 _findObs: Observable<IFindPosition>;
private _findIndex: number;
private _filterEnabled: boolean;
private _onRowCountChange = new Emitter<number>();
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>();
get onFindCountChange(): Event<number> { return this._onFindCountChange.event; }
private _onFilterStateChange = new Emitter<void>();
get onFilterStateChange(): Event<void> { return this._onFilterStateChange.event; }
constructor(
data?: Array<T>,
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) {
this._data = data;
@@ -65,6 +73,35 @@ export class TableDataView<T extends Slick.SlickData> implements IDisposableData
if (!_sortFn) {
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>) {
@@ -79,20 +116,39 @@ export class TableDataView<T extends Slick.SlickData> implements IDisposableData
return this._data[index];
}
getLengthNonFiltered(): number {
return this.filterEnabled ? this._allData.length : this._data.length;
}
push(items: Array<T>);
push(item: T);
push(input: T | Array<T>) {
let inputArray = new Array();
if (Array.isArray(input)) {
this._data.push(...input);
inputArray.push(...input);
} 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() {
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> {
@@ -180,6 +236,7 @@ export class TableDataView<T extends Slick.SlickData> implements IDisposableData
dispose() {
this._data = undefined;
this._allData = undefined;
this._findArray = 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
*/
export default class CustomUrlSerializer implements UrlSerializer {
private _defaultUrlSerializer: DefaultUrlSerializer = new DefaultUrlSerializer();
private _defaultUrlSerializer: DefaultUrlSerializer = new DefaultUrlSerializer();
parse(url: string): UrlTree {
// Encode parentheses
url = url.replace(/\(/g, '%28').replace(/\)/g, '%29');
// Use the default serializer from here on
return this._defaultUrlSerializer.parse(url);
}
parse(url: string): UrlTree {
// Encode parentheses
url = url.replace(/\(/g, '%28').replace(/\)/g, '%29');
// Use the default serializer from here on
return this._defaultUrlSerializer.parse(url);
}
serialize(tree: UrlTree): string {
// serialize parentheses after angular router
return this._defaultUrlSerializer.serialize(tree).replace(/%28/g, '(').replace(/%29/g, ')');
}
serialize(tree: UrlTree): string {
// serialize parentheses after angular router
return this._defaultUrlSerializer.serialize(tree).replace(/%28/g, '(').replace(/%29/g, ')');
}
}

View File

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

View File

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

View File

@@ -5,7 +5,7 @@
'use strict';
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';
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 { IThemable, attachStyler } from 'vs/platform/theme/common/styler';
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?:
{
@@ -262,3 +263,12 @@ export function attachCheckboxStyler(widget: IThemable, themeService: IThemeServ
disabledCheckboxForeground: (style && style.disabledCheckboxForeground) || sqlcolors.disabledCheckboxForeground
}, 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");
}
.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-dark .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!sql/parts/accountManagement/common/media/accountActions';
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 { IListService, ListService } from 'vs/platform/list/browser/listService';
import { IPartService } from 'vs/workbench/services/part/common/partService';
import { Event, Emitter } from 'vs/base/common/event';
import { localize } from 'vs/nls';
import { IThemeService } from 'vs/platform/theme/common/themeService';
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 { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
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 { Button } from 'sql/base/browser/ui/button/button';
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 { AddAccountAction } from 'sql/parts/accountManagement/common/accountActions';
import { AccountListRenderer, AccountListDelegate } from 'sql/parts/accountManagement/common/accountListRenderer';
import { AccountProviderAddedEventParams, UpdateAccountListEventParams } from 'sql/services/accountManagement/eventTypes';
import { FixedListView } from 'sql/platform/views/fixedListView';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { AccountProviderAddedEventParams, UpdateAccountListEventParams } from 'sql/platform/accountManagement/common/eventTypes';
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 {
view: FixedListView<sqlops.Account>;
view: AccountPanel;
addAccountAction: AddAccountAction;
}
@@ -46,13 +98,10 @@ export class AccountDialog extends Modal {
public viewModel: AccountViewModel;
// MEMBER VARIABLES ////////////////////////////////////////////////////
private _providerViews: { [providerId: string]: IProviderViewUiComponent } = {};
private _providerViewsMap = new Map<string, IProviderViewUiComponent>();
private _closeButton: Button;
private _addAccountButton: Button;
private _delegate: AccountListDelegate;
private _accountRenderer: AccountListRenderer;
private _actionRunner: ActionRunner;
private _splitView: SplitView;
private _container: HTMLElement;
private _splitViewContainer: HTMLElement;
@@ -68,10 +117,10 @@ export class AccountDialog extends Modal {
constructor(
@IPartService partService: IPartService,
@IThemeService themeService: IThemeService,
@IListService private _listService: IListService,
@IInstantiationService private _instantiationService: IInstantiationService,
@IContextMenuService private _contextMenuService: IContextMenuService,
@IKeybindingService private _keybindingService: IKeybindingService,
@IConfigurationService private _configurationService: IConfigurationService,
@ITelemetryService telemetryService: ITelemetryService,
@IContextKeyService contextKeyService: IContextKeyService,
@IClipboardService clipboardService: IClipboardService
@@ -86,11 +135,6 @@ export class AccountDialog extends Modal {
contextKeyService,
{ 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
this._onAddAccountErrorEmitter = new Emitter<string>();
@@ -98,28 +142,25 @@ export class AccountDialog extends Modal {
// Create the view model and wire up the events
this.viewModel = this._instantiationService.createInstance(AccountViewModel);
this.viewModel.addProviderEvent(arg => { self.addProvider(arg); });
this.viewModel.removeProviderEvent(arg => { self.removeProvider(arg); });
this.viewModel.updateAccountListEvent(arg => { self.updateProviderAccounts(arg); });
this.viewModel.addProviderEvent(arg => { this.addProvider(arg); });
this.viewModel.removeProviderEvent(arg => { this.removeProvider(arg); });
this.viewModel.updateAccountListEvent(arg => { this.updateProviderAccounts(arg); });
// Load the initial contents of the view model
this.viewModel.initialize()
.then(addedProviders => {
for (let addedProvider of addedProviders) {
self.addProvider(addedProvider);
this.addProvider(addedProvider);
}
});
}
// MODAL OVERRIDE METHODS //////////////////////////////////////////////
protected layout(height?: number): void {
// Ignore height as it's a subcomponent being laid out
this._splitView.layout(DOM.getContentHeight(this._container));
}
public render() {
let self = this;
super.render();
attachModalDialogStyler(this, this._themeService);
this._closeButton = this.addFooterButton(localize('accountDialog.close', 'Close'), () => this.close());
@@ -128,7 +169,7 @@ export class AccountDialog extends Modal {
protected renderBody(container: HTMLElement) {
this._container = container;
this._splitViewContainer = DOM.$('div.account-view');
this._splitViewContainer = DOM.$('div.account-view.monaco-panel-view');
DOM.append(container, this._splitViewContainer);
this._splitView = new SplitView(this._splitViewContainer);
@@ -143,7 +184,7 @@ export class AccountDialog extends Modal {
this._addAccountButton = new Button(buttonSection);
this._addAccountButton.label = localize('accountDialog.addConnection', 'Add an account');
this._register(this._addAccountButton.onDidClick(() => {
(<IProviderViewUiComponent>Object.values(this._providerViews)[0]).addAccountAction.run();
(<IProviderViewUiComponent>values(this._providerViewsMap)[0]).addAccountAction.run();
}));
DOM.append(container, this._noaccountViewContainer);
@@ -189,20 +230,19 @@ export class AccountDialog extends Modal {
private showSplitView() {
this._splitViewContainer.hidden = false;
this._noaccountViewContainer.hidden = true;
let views = this._splitView.getViews();
if (views && views.length > 0) {
let firstView = views[0];
if (firstView instanceof FixedListView) {
firstView.list.setSelection([0]);
firstView.list.domFocus();
if (values(this._providerViewsMap).length > 0) {
let firstView = values(this._providerViewsMap)[0];
if (firstView instanceof AccountPanel) {
firstView.setSelection([0]);
firstView.focus();
}
}
}
private isEmptyLinkedAccount(): boolean {
for (var providerId in this._providerViews) {
var listView = this._providerViews[providerId].view;
if (listView && listView.list.length > 0) {
for (let provider of values(this._providerViewsMap)) {
let listView = provider.view;
if (listView && listView.length > 0) {
return false;
}
}
@@ -211,23 +251,21 @@ export class AccountDialog extends Modal {
public dispose(): void {
super.dispose();
for (let key in this._providerViews) {
if (this._providerViews[key].addAccountAction) {
this._providerViews[key].addAccountAction.dispose();
for (let provider of values(this._providerViewsMap)) {
if (provider.addAccountAction) {
provider.addAccountAction.dispose();
}
if (this._providerViews[key].view) {
this._providerViews[key].view.dispose();
if (provider.view) {
provider.view.dispose();
}
delete this._providerViews[key];
}
}
// PRIVATE HELPERS /////////////////////////////////////////////////////
private addProvider(newProvider: AccountProviderAddedEventParams) {
let self = this;
// Skip adding the provider if it already exists
if (this._providerViews[newProvider.addedProvider.id]) {
if (this._providerViewsMap.get(newProvider.addedProvider.id)) {
return;
}
@@ -237,37 +275,35 @@ export class AccountDialog extends Modal {
AddAccountAction,
newProvider.addedProvider.id
);
addAccountAction.addAccountCompleteEvent(() => { self.hideSpinner(); });
addAccountAction.addAccountErrorEvent(msg => { self._onAddAccountErrorEmitter.fire(msg); });
addAccountAction.addAccountStartEvent(() => { self.showSpinner(); });
addAccountAction.addAccountCompleteEvent(() => { this.hideSpinner(); });
addAccountAction.addAccountErrorEvent(msg => { this._onAddAccountErrorEmitter.fire(msg); });
addAccountAction.addAccountStartEvent(() => { this.showSpinner(); });
// Create a fixed list view for the account provider
let providerViewContainer = DOM.$('.provider-view');
let accountList = new List<sqlops.Account>(providerViewContainer, this._delegate, [this._accountRenderer]);
let providerView = new FixedListView<sqlops.Account>(
undefined,
false,
newProvider.addedProvider.displayName,
accountList,
providerViewContainer,
22,
[addAccountAction],
this._actionRunner,
this._contextMenuService,
let providerView = new AccountPanel(
{
id: newProvider.addedProvider.id,
title: newProvider.addedProvider.displayName,
ariaHeaderLabel: newProvider.addedProvider.displayName
},
this._keybindingService,
this._contextMenuService,
this._configurationService,
this._instantiationService,
this._themeService
);
// Append the list view to the split view
this._splitView.addView(providerView);
this._register(attachListStyler(accountList, this._themeService));
attachPanelStyler(providerView, 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));
// Set the initial items of the list
providerView.updateList(newProvider.initialAccounts);
providerView.updateAccounts(newProvider.initialAccounts);
if (newProvider.initialAccounts.length > 0 && this._splitViewContainer.hidden) {
this.showSplitView();
@@ -276,31 +312,31 @@ export class AccountDialog extends Modal {
this.layout();
// 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) {
// 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) {
return;
}
// 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));
// Remove the list view from our internal map
delete this._providerViews[removedProvider.id];
this._providerViewsMap.delete(removedProvider.id);
this.layout();
}
private updateProviderAccounts(args: UpdateAccountListEventParams) {
let providerMapping = this._providerViews[args.providerId];
let providerMapping = this._providerViewsMap.get(args.providerId);
if (!providerMapping || !providerMapping.view) {
return;
}
providerMapping.view.updateList(args.accountList);
providerMapping.view.updateAccounts(args.accountList);
if (args.accountList.length > 0 && this._splitViewContainer.hidden) {
this.showSplitView();

View File

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

View File

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

View File

@@ -49,18 +49,18 @@
display: none;
}
.account-view .provider-view .list-row {
.account-view .list-row {
padding: 12px;
}
.account-view .provider-view .list-row .icon {
.account-view .list-row .icon {
flex: 0 0 50px;
height: 50px;
width: 50px;
background-size: 50px;
}
.account-view .provider-view .list-row .icon .badge {
.account-view .list-row .icon .badge {
position: absolute;
top: 43px;
left: 43px;
@@ -69,17 +69,17 @@
height: 22px;
}
.account-view .provider-view .list-row .icon .badge .badge-content {
.account-view .list-row .icon .badge .badge-content {
width: 22px;
height: 22px;
background-size: 22px;
}
.account-view .provider-view .list-row .actions-container {
.account-view .list-row .actions-container {
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;
margin-left: 20px;
margin-right: 10px;
@@ -88,16 +88,16 @@
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;
}
.account-view .provider-view .list-row .actions-container {
.account-view .list-row .actions-container {
display: none;
}
.account-view .provider-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 .provider-view .monaco-list .monaco-list-row.focused .list-row .actions-container{
.account-view .monaco-list .monaco-list-row:hover .list-row .actions-container,
.account-view .monaco-list .monaco-list-row.selected .list-row .actions-container,
.account-view .monaco-list .monaco-list-row.focused .list-row .actions-container{
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 { 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 {
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 { localize } from 'vs/nls';
import { IErrorMessageService } from 'sql/parts/connection/common/connectionManagement';
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 {
// MEMBER VARIABLES ////////////////////////////////////////////////////

View File

@@ -12,8 +12,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
import { Action } from 'vs/base/common/actions';
import { error } from 'sql/base/common/log';
import { IAccountManagementService } from 'sql/services/accountManagement/interfaces';
import { IErrorMessageService } from 'sql/parts/connection/common/connectionManagement';
import { IAccountManagementService } from 'sql/platform/accountManagement/common/interfaces';
import { IDialogService, IConfirmation } from 'vs/platform/dialogs/common/dialogs';
import { INotificationService } from 'vs/platform/notification/common/notification';
import Severity from 'vs/base/common/severity';
@@ -83,7 +82,6 @@ export class RemoveAccountAction extends Action {
private _account: sqlops.Account,
@IDialogService private _dialogService: IDialogService,
@INotificationService private _notificationService: INotificationService,
@IErrorMessageService private _errorMessageService: IErrorMessageService,
@IAccountManagementService private _accountManagementService: IAccountManagementService
) {
super(RemoveAccountAction.ID, RemoveAccountAction.LABEL, 'remove-account-action icon remove');
@@ -107,15 +105,15 @@ export class RemoveAccountAction extends Action {
return new TPromise((resolve, reject) => {
self._accountManagementService.removeAccount(self._account.key)
.then(
(result) => { resolve(result); },
(err) => {
// Must handle here as this is an independent action
self._notificationService.notify({
severity: Severity.Error,
message: localize('removeAccountFailed', 'Failed to remove account')
});
resolve(false);
}
(result) => { resolve(result); },
(err) => {
// Must handle here as this is an independent action
self._notificationService.notify({
severity: Severity.Error,
message: localize('removeAccountFailed', 'Failed to remove account')
});
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 { localize } from 'vs/nls';
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 { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
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 { 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 { attachModalDialogStyler, attachButtonStyler } from 'sql/common/theme/styler';
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 { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
// 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
@@ -65,7 +65,7 @@ export class FirewallRuleDialog extends Modal {
constructor(
@IAccountPickerService private _accountPickerService: IAccountPickerService,
@IPartService partService: IPartService,
@IWorkbenchThemeService private _workbenchThemeService: IWorkbenchThemeService,
@IThemeService themeService: IThemeService,
@IInstantiationService private _instantiationService: IInstantiationService,
@IContextViewService private _contextViewService: IContextViewService,
@ITelemetryService telemetryService: ITelemetryService,
@@ -79,7 +79,7 @@ export class FirewallRuleDialog extends Modal {
partService,
telemetryService,
clipboardService,
_workbenchThemeService,
themeService,
contextKeyService,
{
isFlyout: true,
@@ -206,8 +206,8 @@ export class FirewallRuleDialog extends Modal {
builder.append(firewallRuleSection);
});
this._register(this._workbenchThemeService.onDidColorThemeChange(e => this.updateTheme(e)));
this.updateTheme(this._workbenchThemeService.getColorTheme());
this._register(this._themeService.onThemeChange(e => this.updateTheme(e)));
this.updateTheme(this._themeService.getTheme());
$(this._IPAddressInput).on(DOM.EventType.CLICK, () => {
this.onFirewallRuleOptionSelected(true);
@@ -243,7 +243,7 @@ export class FirewallRuleDialog extends Modal {
}
// 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 link = linkColor ? linkColor.toString() : null;
if (this._helpLink) {

View File

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

View File

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

View File

@@ -6,7 +6,7 @@
import { ElementRef, Component, Inject, forwardRef } from '@angular/core';
import { IBootstrapParams } from 'sql/services/bootstrap/bootstrapService';
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';
@@ -21,8 +21,8 @@ export class CreateLoginComponent {
public connection: ConnectionManagementInfo;
constructor(
@Inject(forwardRef(() => ElementRef)) private _el: ElementRef,
@Inject(IBootstrapParams) private _params: IDashboardComponentParams
@Inject(forwardRef(() => ElementRef)) private _el: ElementRef,
@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 { IThemeService } from 'vs/platform/theme/common/themeService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { CreateLoginInput } from './createLoginInput';
import { CreateLoginModule } from './createLogin.module';
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
import { IMetadataService } from 'sql/services/metadata/metadataService';
import { IScriptingService } from 'sql/services/scripting/scriptingService';
import { CreateLoginInput } from 'sql/parts/admin/security/createLoginInput';
import { CreateLoginModule } from 'sql/parts/admin/security/createLogin.module';
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
import { IMetadataService } from 'sql/platform/metadata/common/metadataService';
import { IScriptingService } from 'sql/platform/scripting/common/scriptingService';
import { IQueryEditorService } from 'sql/parts/query/common/queryEditorService';
import { bootstrapAngular, IBootstrapParams } from 'sql/services/bootstrap/bootstrapService';
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 { EditorInput, EditorModel } from 'vs/workbench/common/editor';
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 {

View File

@@ -3,8 +3,6 @@
* 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 { IInstantiationService, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
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 { QueryPlanInput } from 'sql/parts/queryPlan/queryPlanInput';
import { NotebookInput, NotebookInputModel, NotebookInputValidator } from 'sql/parts/notebook/notebookInput';
import { DEFAULT_NOTEBOOK_PROVIDER, INotebookService } from 'sql/services/notebook/notebookService';
import { getProvidersForFileName } from 'sql/parts/notebook/notebookUtils';
import { DEFAULT_NOTEBOOK_PROVIDER, INotebookService } from 'sql/workbench/services/notebook/common/notebookService';
import { getProvidersForFileName, getStandardKernelsForProvider } from 'sql/parts/notebook/notebookUtils';
import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput';
const fs = require('fs');
@@ -71,6 +69,10 @@ export function convertEditorInput(input: EditorInput, options: IQueryEditorOpti
let notebookInputModel = new NotebookInputModel(uri, undefined, false, undefined);
notebookInputModel.providerId = providerIds.filter(provider => provider !== DEFAULT_NOTEBOOK_PROVIDER)[0];
notebookInputModel.providers = providerIds;
notebookInputModel.providers.forEach(provider => {
let standardKernels = getStandardKernelsForProvider(provider, notebookService);
notebookInputModel.standardKernels = standardKernels;
});
let notebookInput: NotebookInput = instantiationService.createInstance(NotebookInput, fileName, notebookInputModel);
return notebookInput;
});

View File

@@ -8,8 +8,8 @@ import { Action } from 'vs/base/common/actions';
import { TPromise } from 'vs/base/common/winjs.base';
import { Event, Emitter } from 'vs/base/common/event';
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
import { INotificationService, INotificationActions } from 'vs/platform/notification/common/notification';
import Severity from 'vs/base/common/severity';
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) => {
let activeInput = this._editorService.activeEditor;
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 connectionProfile = this._connectionManagementService.getConnectionProfile(activeInput.uri);
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 { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService';
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { IObjectExplorerService } from 'sql/parts/objectExplorer/common/objectExplorerService';
import * as TaskUtilities from 'sql/workbench/common/taskUtilities';
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';
export class AdvancedPropertiesController {
private _container: HTMLElement;
private _advancedDialog: OptionsDialog;
private _options: { [name: string]: any };
@@ -30,7 +28,6 @@ export class AdvancedPropertiesController {
public showDialog(providerOptions: sqlops.ConnectionOption[], container: HTMLElement, options: { [name: string]: any }): void {
this._options = options;
this._container = container;
var serviceOptions = providerOptions.map(option => AdvancedPropertiesController.connectionOptionToServiceOption(option));
this.advancedDialog.open(serviceOptions, this._options);
}
@@ -38,8 +35,7 @@ export class AdvancedPropertiesController {
public get advancedDialog() {
if (!this._advancedDialog) {
this._advancedDialog = this._instantiationService.createInstance(
OptionsDialog, localize('connectionAdvancedProperties', 'Advanced Properties'), TelemetryKeys.ConnectionAdvancedProperties, { hasBackButton: true });
this._advancedDialog.cancelLabel = localize('advancedProperties.discard', 'Discard');
OptionsDialog, localize('connectionAdvancedProperties', 'Advanced Properties'), TelemetryKeys.ConnectionAdvancedProperties, { hasBackButton: true, cancelLabel: localize('advancedProperties.discard', 'Discard') });
this._advancedDialog.onCloseEvent(() => this._onCloseAdvancedProperties());
this._advancedDialog.onOk(() => this.handleOnOk());
this._advancedDialog.render();

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