mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-03-18 11:03:18 -04:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b931ccfabf | ||
|
|
eeab048f46 | ||
|
|
e2b446be1c | ||
|
|
5f2e17a738 | ||
|
|
399d6d0045 | ||
|
|
f36f3ffd21 | ||
|
|
00cd772cbc | ||
|
|
b6c9a3bb89 | ||
|
|
cbf6c06e4b | ||
|
|
cff21124da | ||
|
|
ce7893c2e5 | ||
|
|
f7dcaa38ff | ||
|
|
8ce1013a26 | ||
|
|
114d67b408 | ||
|
|
56c2d16560 | ||
|
|
2238c42432 | ||
|
|
64f6cf6747 | ||
|
|
c0e9f1ca43 | ||
|
|
7f66087d8c | ||
|
|
18671b7cca | ||
|
|
233156c744 | ||
|
|
5e964d2105 | ||
|
|
59e7a5fa4b | ||
|
|
8452f577d2 | ||
|
|
726eb8d0e1 | ||
|
|
2c0d6b93ee |
16
README.md
16
README.md
@@ -34,9 +34,9 @@ See the [change log](https://github.com/Microsoft/azuredatastudio/blob/master/CH
|
|||||||
- Task History window to view current task execution status, completion results with error messages and task T-SQL scripting
|
- Task History window to view current task execution status, completion results with error messages and task T-SQL scripting
|
||||||
- Scripting support to generate CREATE, SELECT, ALTER and DROP statements for database objects
|
- Scripting support to generate CREATE, SELECT, ALTER and DROP statements for database objects
|
||||||
- Workspaces with full Git integration and Find In Files support to managing T-SQL script libraries
|
- Workspaces with full Git integration and Find In Files support to managing T-SQL script libraries
|
||||||
- Modern light-weight shell with theming, user settings, full screen support, integrated terminal and numerous other features
|
- Modern light-weight shell with theming, user settings, full-screen support, integrated terminal and numerous other features
|
||||||
|
|
||||||
Here's some of these features in action.
|
Here are some of these features in action.
|
||||||
|
|
||||||
<img src='https://github.com/Microsoft/azuredatastudio/blob/master/docs/overview_screen.jpg' width='800px'>
|
<img src='https://github.com/Microsoft/azuredatastudio/blob/master/docs/overview_screen.jpg' width='800px'>
|
||||||
|
|
||||||
@@ -69,25 +69,25 @@ We would like to thank all our users who raised issues, and in particular the fo
|
|||||||
* AlexFsmn `Disabled connection name input when connecting to a server. #2566`
|
* AlexFsmn `Disabled connection name input when connecting to a server. #2566`
|
||||||
* SebastianPfliegel `Added more saveAsCsv options #2099`
|
* SebastianPfliegel `Added more saveAsCsv options #2099`
|
||||||
* ianychoi `Fixes a typo: Mimunum -> Minimum #1994`
|
* ianychoi `Fixes a typo: Mimunum -> Minimum #1994`
|
||||||
* AlexFsmn `Fixed bug where proper file extension wasn't appended to filename. #2151`
|
* AlexFsmn `Fixed bug where proper file extension wasn't appended to the filename. #2151`
|
||||||
* AlexFsmn `Added functionality for adding any file to import wizard #2329`
|
* AlexFsmn `Added functionality for adding any file to import wizard #2329`
|
||||||
* AlexFsmn `Fixed background issue when copying a chart to clipboard #2215`
|
* AlexFsmn `Fixed background issue when copying a chart to clipboard #2215`
|
||||||
* AlexFsmn `Fixed problem where vertical charts didn't display labels correctly. #2263`
|
* AlexFsmn `Fixed problem where vertical charts didn't display labels correctly. #2263`
|
||||||
* AlexFsmn `Fixed Initial values for charts to match visuals #2266`
|
* AlexFsmn `Fixed Initial values for charts to match visuals #2266`
|
||||||
* AlexFsmn `Renamed chart option labels #2264`
|
* AlexFsmn `Renamed chart option labels #2264`
|
||||||
* AlexFsmn `Added feature for opening file after exporting to CSV/XLS/JSON & query files #2216`
|
* AlexFsmn `Added feature for the opening file after exporting to CSV/XLS/JSON & query files #2216`
|
||||||
* AlexFsmm `Get Connection String should copy to clipboard #2175`
|
* AlexFsmm `Get Connection String should copy to clipboard #2175`
|
||||||
* lanceklinger `Fix for double clicking column handle in results table #1504`
|
* lanceklinger `Fix for double-clicking column handle in results table #1504`
|
||||||
* westerncj for `Removed duplicate contribution from README.md (#753)`
|
* westerncj for `Removed duplicate contribution from README.md (#753)`
|
||||||
* ntovas for `Fix for duplicate extensions shown in "Save File" dialog. (#779)`
|
* ntovas for `Fix for duplicate extensions shown in "Save File" dialog. (#779)`
|
||||||
* SebastianPfliegel for `Add cursor snippet (#475)`
|
* SebastianPfliegel for `Add cursor snippet (#475)`
|
||||||
* mikaoelitiana for fix: `revert README and CONTRIBUTING after last VSCode merge (#574)`
|
* mikaoelitiana for the fix: `revert README and CONTRIBUTING after last VSCode merge (#574)`
|
||||||
* alextercete for `Reinstate menu item to install from VSIX (#682)`
|
* alextercete for `Reinstate menu item to install from VSIX (#682)`
|
||||||
* alextercete for `Fix "No extension gallery service configured" error (#427)`
|
* alextercete for `Fix "No extension gallery service configured" error (#427)`
|
||||||
* mwiedemeyer for `Fix #58: Default sort order for DB size widget (#111)`
|
* mwiedemeyer for `Fix #58: Default sort order for DB size widget (#111)`
|
||||||
* AlexTroshkin for `Show disconnect in context menu only when connectionProfile connected (#150)`
|
* AlexTroshkin for `Show disconnect in context menu only when connectionProfile connected (#150)`
|
||||||
* AlexTroshkin for `Fix #138: Invalid syntax color highlighting (identity not highlighting) (#140))`
|
* AlexTroshkin for `Fix #138: Invalid syntax color highlighting (identity not highlighting) (#140))`
|
||||||
* stebet for `Fix #153: Fixing sql snippets that failed on a DB with case-sensitive collation. (#152)`
|
* stebet for `Fix #153: Fixing sql snippets that failed on a DB with a case-sensitive collation. (#152)`
|
||||||
* SebastianPfliegel `Remove sqlExtensionHelp (#312)`
|
* SebastianPfliegel `Remove sqlExtensionHelp (#312)`
|
||||||
* olljanat for `Implemented npm version check (#314)`
|
* olljanat for `Implemented npm version check (#314)`
|
||||||
* Adam Machanic for helping with the `whoisactive` extension
|
* Adam Machanic for helping with the `whoisactive` extension
|
||||||
@@ -104,7 +104,7 @@ We would like to thank all our users who raised issues, and in particular the fo
|
|||||||
* Portuguese Brazil: Daniel de Sousa, Diogo Duarte, Douglas Correa, Douglas Eccker, José Emanuel Mendes, Marcelo Fernandes, Marcondes Alexandre, Roberto Fonseca, Rodrigo Crespi
|
* Portuguese Brazil: Daniel de Sousa, Diogo Duarte, Douglas Correa, Douglas Eccker, José Emanuel Mendes, Marcelo Fernandes, Marcondes Alexandre, Roberto Fonseca, Rodrigo Crespi
|
||||||
|
|
||||||
|
|
||||||
And of course we'd like to thank the authors of all upstream dependencies. Please see a full list in the [ThirdPartyNotices.txt](https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/ThirdPartyNotices.txt)
|
And of course, we'd like to thank the authors of all upstream dependencies. Please see a full list in the [ThirdPartyNotices.txt](https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/ThirdPartyNotices.txt)
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "agent",
|
"name": "agent",
|
||||||
"displayName": "SQL Server Agent",
|
"displayName": "SQL Server Agent",
|
||||||
"description": "Manage and troubleshoot SQL Server Agent jobs",
|
"description": "Manage and troubleshoot SQL Server Agent jobs",
|
||||||
"version": "0.34.0",
|
"version": "0.35.0",
|
||||||
"publisher": "Microsoft",
|
"publisher": "Microsoft",
|
||||||
"preview": true,
|
"preview": true,
|
||||||
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/LICENSE.txt",
|
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/LICENSE.txt",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import * as vscode from 'vscode';
|
|||||||
import * as sqlops from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
import { AgentUtils } from '../agentUtils';
|
import { AgentUtils } from '../agentUtils';
|
||||||
import { IAgentDialogData, AgentDialogMode } from '../interfaces';
|
import { IAgentDialogData, AgentDialogMode } from '../interfaces';
|
||||||
|
import { JobData } from './jobData';
|
||||||
|
|
||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
@@ -45,8 +46,19 @@ export class AlertData implements IAgentDialogData {
|
|||||||
wmiEventNamespace: string;
|
wmiEventNamespace: string;
|
||||||
wmiEventQuery: string;
|
wmiEventQuery: string;
|
||||||
|
|
||||||
constructor(ownerUri:string, alertInfo: sqlops.AgentAlertInfo) {
|
private viaJobDialog: boolean;
|
||||||
|
private jobModel: JobData;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
ownerUri:string,
|
||||||
|
alertInfo: sqlops.AgentAlertInfo,
|
||||||
|
jobModel?: JobData,
|
||||||
|
viaJobDialog: boolean = false
|
||||||
|
) {
|
||||||
this.ownerUri = ownerUri;
|
this.ownerUri = ownerUri;
|
||||||
|
this.viaJobDialog = viaJobDialog;
|
||||||
|
this.jobModel = jobModel;
|
||||||
|
this.jobName = this.jobName ? this.jobName : this.jobModel.name;
|
||||||
|
|
||||||
if (alertInfo) {
|
if (alertInfo) {
|
||||||
this.dialogMode = AgentDialogMode.EDIT;
|
this.dialogMode = AgentDialogMode.EDIT;
|
||||||
@@ -60,7 +72,6 @@ export class AlertData implements IAgentDialogData {
|
|||||||
this.includeEventDescription = alertInfo.includeEventDescription.toString();
|
this.includeEventDescription = alertInfo.includeEventDescription.toString();
|
||||||
this.isEnabled = alertInfo.isEnabled;
|
this.isEnabled = alertInfo.isEnabled;
|
||||||
this.jobId = alertInfo.jobId;
|
this.jobId = alertInfo.jobId;
|
||||||
this.jobName = alertInfo.jobName;
|
|
||||||
this.lastOccurrenceDate = alertInfo.lastOccurrenceDate;
|
this.lastOccurrenceDate = alertInfo.lastOccurrenceDate;
|
||||||
this.lastResponseDate = alertInfo.lastResponseDate;
|
this.lastResponseDate = alertInfo.lastResponseDate;
|
||||||
this.messageId = alertInfo.messageId;
|
this.messageId = alertInfo.messageId;
|
||||||
@@ -82,10 +93,18 @@ export class AlertData implements IAgentDialogData {
|
|||||||
|
|
||||||
public async save() {
|
public async save() {
|
||||||
let agentService = await AgentUtils.getAgentService();
|
let agentService = await AgentUtils.getAgentService();
|
||||||
let result = this.dialogMode === AgentDialogMode.CREATE
|
let result: any;
|
||||||
? await agentService.createAlert(this.ownerUri, this.toAgentAlertInfo())
|
// if it's called via the job dialog, add it to the
|
||||||
: await agentService.updateAlert(this.ownerUri, this.originalName, this.toAgentAlertInfo());
|
// job model
|
||||||
|
if (this.viaJobDialog) {
|
||||||
|
if (this.jobModel) {
|
||||||
|
Promise.resolve(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// has to be a create alert
|
||||||
|
result = await agentService.createAlert(this.ownerUri, this.toAgentAlertInfo());
|
||||||
|
}
|
||||||
if (!result || !result.success) {
|
if (!result || !result.success) {
|
||||||
vscode.window.showErrorMessage(
|
vscode.window.showErrorMessage(
|
||||||
localize('alertData.saveErrorMessage', "Alert update failed '{0}'", result.errorMessage ? result.errorMessage : 'Unknown'));
|
localize('alertData.saveErrorMessage', "Alert update failed '{0}'", result.errorMessage ? result.errorMessage : 'Unknown'));
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ export class JobData implements IAgentDialogData {
|
|||||||
public jobSteps: sqlops.AgentJobStepInfo[];
|
public jobSteps: sqlops.AgentJobStepInfo[];
|
||||||
public jobSchedules: sqlops.AgentJobScheduleInfo[];
|
public jobSchedules: sqlops.AgentJobScheduleInfo[];
|
||||||
public alerts: sqlops.AgentAlertInfo[];
|
public alerts: sqlops.AgentAlertInfo[];
|
||||||
|
public jobId: string;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
ownerUri: string,
|
ownerUri: string,
|
||||||
@@ -62,6 +63,7 @@ export class JobData implements IAgentDialogData {
|
|||||||
this.jobSteps = jobInfo.JobSteps;
|
this.jobSteps = jobInfo.JobSteps;
|
||||||
this.jobSchedules = jobInfo.JobSchedules;
|
this.jobSchedules = jobInfo.JobSchedules;
|
||||||
this.alerts = jobInfo.Alerts;
|
this.alerts = jobInfo.Alerts;
|
||||||
|
this.jobId = jobInfo.jobId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +117,6 @@ export class JobData implements IAgentDialogData {
|
|||||||
let result = this.dialogMode === AgentDialogMode.CREATE
|
let result = this.dialogMode === AgentDialogMode.CREATE
|
||||||
? await this._agentService.createJob(this.ownerUri, jobInfo)
|
? await this._agentService.createJob(this.ownerUri, jobInfo)
|
||||||
: await this._agentService.updateJob(this.ownerUri, this.originalName, jobInfo);
|
: await this._agentService.updateJob(this.ownerUri, this.originalName, jobInfo);
|
||||||
|
|
||||||
if (!result || !result.success) {
|
if (!result || !result.success) {
|
||||||
vscode.window.showErrorMessage(
|
vscode.window.showErrorMessage(
|
||||||
localize('jobData.saveErrorMessage', "Job update failed '{0}'", result.errorMessage ? result.errorMessage : 'Unknown'));
|
localize('jobData.saveErrorMessage', "Job update failed '{0}'", result.errorMessage ? result.errorMessage : 'Unknown'));
|
||||||
@@ -135,18 +136,6 @@ export class JobData implements IAgentDialogData {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public addJobSchedule(schedule: sqlops.AgentJobScheduleInfo) {
|
|
||||||
if (this.jobSchedules) {
|
|
||||||
let existingSchedule = this.jobSchedules.find(item => item.name === schedule.name);
|
|
||||||
if (!existingSchedule) {
|
|
||||||
this.jobSchedules.push(schedule);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.jobSchedules = [];
|
|
||||||
this.jobSchedules.push(schedule);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public toAgentJobInfo(): sqlops.AgentJobInfo {
|
public toAgentJobInfo(): sqlops.AgentJobInfo {
|
||||||
return {
|
return {
|
||||||
name: this.name,
|
name: this.name,
|
||||||
@@ -177,7 +166,7 @@ export class JobData implements IAgentDialogData {
|
|||||||
categoryType: 1, // LocalJob, hard-coding the value, corresponds to the target tab in SSMS
|
categoryType: 1, // LocalJob, hard-coding the value, corresponds to the target tab in SSMS
|
||||||
lastRun: '',
|
lastRun: '',
|
||||||
nextRun: '',
|
nextRun: '',
|
||||||
jobId: ''
|
jobId: this.jobId
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,11 +46,13 @@ export class JobStepData implements IAgentDialogData {
|
|||||||
public retryInterval: number;
|
public retryInterval: number;
|
||||||
public proxyName: string;
|
public proxyName: string;
|
||||||
private jobModel: JobData;
|
private jobModel: JobData;
|
||||||
|
private viaJobDialog: boolean;
|
||||||
|
|
||||||
constructor(ownerUri:string, jobModel?: JobData) {
|
constructor(ownerUri:string, jobModel?: JobData, viaJobDialog: boolean = false) {
|
||||||
this.ownerUri = ownerUri;
|
this.ownerUri = ownerUri;
|
||||||
this.jobName = jobModel.name;
|
this.jobName = jobModel.name;
|
||||||
this.jobModel = jobModel;
|
this.jobModel = jobModel;
|
||||||
|
this.viaJobDialog = viaJobDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async initialize() {
|
public async initialize() {
|
||||||
@@ -59,18 +61,16 @@ export class JobStepData implements IAgentDialogData {
|
|||||||
public async save() {
|
public async save() {
|
||||||
let agentService = await AgentUtils.getAgentService();
|
let agentService = await AgentUtils.getAgentService();
|
||||||
let result: any;
|
let result: any;
|
||||||
if (this.dialogMode === AgentDialogMode.CREATE) {
|
// if it's called via the job dialog, add it to the
|
||||||
if (this.jobModel && this.jobModel.dialogMode === AgentDialogMode.CREATE) {
|
// job model
|
||||||
// create job -> create step
|
if (this.viaJobDialog) {
|
||||||
|
if (this.jobModel) {
|
||||||
Promise.resolve(this);
|
Promise.resolve(this);
|
||||||
return;
|
return;
|
||||||
} else {
|
|
||||||
// edit job -> create step
|
|
||||||
result = await agentService.createJobStep(this.ownerUri, JobStepData.convertToAgentJobStepInfo(this));
|
|
||||||
}
|
}
|
||||||
} else if (this.jobModel && this.jobModel.dialogMode === AgentDialogMode.EDIT) {
|
} else {
|
||||||
// edit job -> edit step
|
// has to be a create step
|
||||||
result = await agentService.updateJobStep(this.ownerUri, this.stepName, JobStepData.convertToAgentJobStepInfo(this));
|
result = await agentService.createJobStep(this.ownerUri, JobStepData.convertToAgentJobStepInfo(this));
|
||||||
}
|
}
|
||||||
if (!result || !result.success) {
|
if (!result || !result.success) {
|
||||||
vscode.window.showErrorMessage(
|
vscode.window.showErrorMessage(
|
||||||
|
|||||||
@@ -29,8 +29,6 @@ export class PickScheduleData implements IAgentDialogData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async save() {
|
public async save() {
|
||||||
let agentService = await AgentUtils.getAgentService();
|
|
||||||
this.selectedSchedule.jobName = this.jobName;
|
this.selectedSchedule.jobName = this.jobName;
|
||||||
let result = await agentService.createJobSchedule(this.ownerUri, this.selectedSchedule);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { AgentUtils } from '../agentUtils';
|
|||||||
import { AlertData } from '../data/alertData';
|
import { AlertData } from '../data/alertData';
|
||||||
import { OperatorDialog } from './operatorDialog';
|
import { OperatorDialog } from './operatorDialog';
|
||||||
import { JobDialog } from './jobDialog';
|
import { JobDialog } from './jobDialog';
|
||||||
|
import { JobData } from '../data/jobData';
|
||||||
|
|
||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
@@ -148,14 +149,23 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
private delayMinutesTextBox: sqlops.InputBoxComponent;
|
private delayMinutesTextBox: sqlops.InputBoxComponent;
|
||||||
private delaySecondsTextBox: sqlops.InputBoxComponent;
|
private delaySecondsTextBox: sqlops.InputBoxComponent;
|
||||||
|
|
||||||
private jobs: string[];
|
|
||||||
private databases: string[];
|
private databases: string[];
|
||||||
|
private jobModel: JobData;
|
||||||
|
public jobId: string;
|
||||||
|
public jobName: string;
|
||||||
|
|
||||||
constructor(ownerUri: string, alertInfo: sqlops.AgentAlertInfo = undefined, jobs: string[]) {
|
constructor(
|
||||||
|
ownerUri: string,
|
||||||
|
jobModel: JobData,
|
||||||
|
alertInfo: sqlops.AgentAlertInfo = undefined,
|
||||||
|
viaJobDialog: boolean = false
|
||||||
|
) {
|
||||||
super(ownerUri,
|
super(ownerUri,
|
||||||
new AlertData(ownerUri, alertInfo),
|
new AlertData(ownerUri, alertInfo, jobModel, viaJobDialog),
|
||||||
alertInfo ? AlertDialog.EditDialogTitle : AlertDialog.CreateDialogTitle);
|
alertInfo ? AlertDialog.EditDialogTitle : AlertDialog.CreateDialogTitle);
|
||||||
this.jobs = jobs;
|
this.jobModel = jobModel;
|
||||||
|
this.jobId = this.jobId ? this.jobId : this.jobModel.jobId;
|
||||||
|
this.jobName = this.jobName ? this.jobName : this.jobModel.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async initializeDialog(dialog: sqlops.window.modelviewdialog.Dialog) {
|
protected async initializeDialog(dialog: sqlops.window.modelviewdialog.Dialog) {
|
||||||
@@ -512,7 +522,8 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
protected updateModel() {
|
protected updateModel() {
|
||||||
this.model.name = this.nameTextBox.value;
|
this.model.name = this.nameTextBox.value;
|
||||||
this.model.isEnabled = this.enabledCheckBox.checked;
|
this.model.isEnabled = this.enabledCheckBox.checked;
|
||||||
|
this.model.jobId = this.jobId;
|
||||||
|
this.model.jobName = this.jobName;
|
||||||
this.model.alertType = this.getDropdownValue(this.typeDropDown);
|
this.model.alertType = this.getDropdownValue(this.typeDropDown);
|
||||||
let databaseName = this.getDropdownValue(this.databaseDropDown);
|
let databaseName = this.getDropdownValue(this.databaseDropDown);
|
||||||
this.model.databaseName = (databaseName !== AlertDialog.AllDatabases) ? databaseName : undefined;
|
this.model.databaseName = (databaseName !== AlertDialog.AllDatabases) ? databaseName : undefined;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { PickScheduleDialog } from './pickScheduleDialog';
|
|||||||
import { AlertDialog } from './alertDialog';
|
import { AlertDialog } from './alertDialog';
|
||||||
import { AgentDialog } from './agentDialog';
|
import { AgentDialog } from './agentDialog';
|
||||||
import { AgentUtils } from '../agentUtils';
|
import { AgentUtils } from '../agentUtils';
|
||||||
|
import { JobStepData } from '../data/jobStepData';
|
||||||
|
|
||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
@@ -110,11 +111,19 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
private newAlertButton: sqlops.ButtonComponent;
|
private newAlertButton: sqlops.ButtonComponent;
|
||||||
private isEdit: boolean = false;
|
private isEdit: boolean = false;
|
||||||
|
|
||||||
|
// Job objects
|
||||||
|
private steps: sqlops.AgentJobStepInfo[];
|
||||||
|
private schedules: sqlops.AgentJobScheduleInfo[];
|
||||||
|
private alerts: sqlops.AgentAlertInfo[] = [];
|
||||||
|
|
||||||
constructor(ownerUri: string, jobInfo: sqlops.AgentJobInfo = undefined) {
|
constructor(ownerUri: string, jobInfo: sqlops.AgentJobInfo = undefined) {
|
||||||
super(
|
super(
|
||||||
ownerUri,
|
ownerUri,
|
||||||
new JobData(ownerUri, jobInfo),
|
new JobData(ownerUri, jobInfo),
|
||||||
jobInfo ? JobDialog.EditDialogTitle : JobDialog.CreateDialogTitle);
|
jobInfo ? JobDialog.EditDialogTitle : JobDialog.CreateDialogTitle);
|
||||||
|
this.steps = this.model.jobSteps ? this.model.jobSteps : [];
|
||||||
|
this.schedules = this.model.jobSchedules ? this.model.jobSchedules : [];
|
||||||
|
this.alerts = this.model.alerts ? this.model.alerts : [];
|
||||||
this.isEdit = jobInfo ? true : false;
|
this.isEdit = jobInfo ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,12 +207,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
|
|
||||||
private initializeStepsTab() {
|
private initializeStepsTab() {
|
||||||
this.stepsTab.registerContent(async view => {
|
this.stepsTab.registerContent(async view => {
|
||||||
let previewTag = view.modelBuilder.text()
|
let data = this.steps ? this.convertStepsToData(this.steps) : [];
|
||||||
.withProperties({
|
|
||||||
value: 'Feature Preview'
|
|
||||||
}).component();
|
|
||||||
let steps = this.model.jobSteps ? this.model.jobSteps : [];
|
|
||||||
let data = this.convertStepsToData(steps);
|
|
||||||
this.stepsTable = view.modelBuilder.table()
|
this.stepsTable = view.modelBuilder.table()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
columns: [
|
columns: [
|
||||||
@@ -237,13 +241,11 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
width: 80
|
width: 80
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
let stepDialog = new JobStepDialog(this.model.ownerUri, '' , this.model);
|
let stepDialog = new JobStepDialog(this.model.ownerUri, '' , this.model, null, true);
|
||||||
stepDialog.onSuccess((step) => {
|
stepDialog.onSuccess((step) => {
|
||||||
if (!this.model.jobSteps) {
|
let stepInfo = JobStepData.convertToAgentJobStepInfo(step);
|
||||||
this.model.jobSteps = [];
|
this.steps.push(stepInfo);
|
||||||
}
|
this.stepsTable.data = this.convertStepsToData(this.steps);
|
||||||
this.model.jobSteps.push(step);
|
|
||||||
this.stepsTable.data = this.convertStepsToData(this.model.jobSteps);
|
|
||||||
});
|
});
|
||||||
this.newStepButton.onDidClick((e)=>{
|
this.newStepButton.onDidClick((e)=>{
|
||||||
if (this.nameTextBox.value && this.nameTextBox.value.length > 0) {
|
if (this.nameTextBox.value && this.nameTextBox.value.length > 0) {
|
||||||
@@ -277,7 +279,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
this.deleteStepButton.enabled = true;
|
this.deleteStepButton.enabled = true;
|
||||||
this.editStepButton.enabled = true;
|
this.editStepButton.enabled = true;
|
||||||
this.editStepButton.onDidClick(() => {
|
this.editStepButton.onDidClick(() => {
|
||||||
let stepDialog = new JobStepDialog(this.model.ownerUri, '' , this.model, stepData);
|
let stepDialog = new JobStepDialog(this.model.ownerUri, '' , this.model, stepData, true);
|
||||||
stepDialog.openDialog();
|
stepDialog.openDialog();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -287,7 +289,6 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
agentService.deleteJobStep(this.ownerUri, stepData).then((result) => {
|
agentService.deleteJobStep(this.ownerUri, stepData).then((result) => {
|
||||||
if (result && result.success) {
|
if (result && result.success) {
|
||||||
delete steps[rowNumber];
|
delete steps[rowNumber];
|
||||||
this.model.jobSteps = steps;
|
|
||||||
let data = this.convertStepsToData(steps);
|
let data = this.convertStepsToData(steps);
|
||||||
this.stepsTable.data = data;
|
this.stepsTable.data = data;
|
||||||
}
|
}
|
||||||
@@ -299,10 +300,6 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
|
|
||||||
let formModel = view.modelBuilder.formContainer()
|
let formModel = view.modelBuilder.formContainer()
|
||||||
.withFormItems([{
|
.withFormItems([{
|
||||||
component: previewTag,
|
|
||||||
title: ''
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: this.stepsTable,
|
component: this.stepsTable,
|
||||||
title: this.JobStepsTopLabelString,
|
title: this.JobStepsTopLabelString,
|
||||||
actions: [this.moveStepUpButton, this.moveStepDownButton, this.newStepButton, this.editStepButton, this.deleteStepButton]
|
actions: [this.moveStepUpButton, this.moveStepDownButton, this.newStepButton, this.editStepButton, this.deleteStepButton]
|
||||||
@@ -313,10 +310,6 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
|
|
||||||
private initializeAlertsTab() {
|
private initializeAlertsTab() {
|
||||||
this.alertsTab.registerContent(async view => {
|
this.alertsTab.registerContent(async view => {
|
||||||
let previewTag = view.modelBuilder.text()
|
|
||||||
.withProperties({
|
|
||||||
value: 'Feature Preview'
|
|
||||||
}).component();
|
|
||||||
let alerts = this.model.alerts ? this.model.alerts : [];
|
let alerts = this.model.alerts ? this.model.alerts : [];
|
||||||
let data = this.convertAlertsToData(alerts);
|
let data = this.convertAlertsToData(alerts);
|
||||||
this.alertsTable = view.modelBuilder.table()
|
this.alertsTable = view.modelBuilder.table()
|
||||||
@@ -327,7 +320,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
this.AlertTypeLabelString
|
this.AlertTypeLabelString
|
||||||
],
|
],
|
||||||
data: data,
|
data: data,
|
||||||
height: 430,
|
height: 750,
|
||||||
width: 400
|
width: 400
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
@@ -336,18 +329,24 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
width: 80
|
width: 80
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
this.newAlertButton.onDidClick((e)=>{
|
let alertDialog = new AlertDialog(this.model.ownerUri, this.model, null, true);
|
||||||
let alertDialog = new AlertDialog(this.model.ownerUri, null, []);
|
alertDialog.onSuccess((alert) => {
|
||||||
alertDialog.onSuccess((dialogModel) => {
|
let alertInfo = alert.toAgentAlertInfo();
|
||||||
|
this.alerts.push(alertInfo);
|
||||||
|
this.alertsTable.data = this.convertAlertsToData(this.alerts);
|
||||||
});
|
});
|
||||||
|
this.newAlertButton.onDidClick(()=>{
|
||||||
|
if (this.nameTextBox.value && this.nameTextBox.value.length > 0) {
|
||||||
|
alertDialog.jobId = this.model.jobId;
|
||||||
|
alertDialog.jobName = this.model.name ? this.model.name : this.nameTextBox.value;
|
||||||
alertDialog.openDialog();
|
alertDialog.openDialog();
|
||||||
|
} else {
|
||||||
|
this.dialog.message = { text: this.BlankJobNameErrorText };
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let formModel = view.modelBuilder.formContainer()
|
let formModel = view.modelBuilder.formContainer()
|
||||||
.withFormItems([{
|
.withFormItems([{
|
||||||
component: previewTag,
|
|
||||||
title: ''
|
|
||||||
}, {
|
|
||||||
component: this.alertsTable,
|
component: this.alertsTable,
|
||||||
title: this.AlertsTopLabelString,
|
title: this.AlertsTopLabelString,
|
||||||
actions: [this.newAlertButton]
|
actions: [this.newAlertButton]
|
||||||
@@ -380,8 +379,11 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
pickScheduleDialog.onSuccess((dialogModel) => {
|
pickScheduleDialog.onSuccess((dialogModel) => {
|
||||||
let selectedSchedule = dialogModel.selectedSchedule;
|
let selectedSchedule = dialogModel.selectedSchedule;
|
||||||
if (selectedSchedule) {
|
if (selectedSchedule) {
|
||||||
selectedSchedule.jobName = this.model.name;
|
let existingSchedule = this.schedules.find(item => item.name === selectedSchedule.name);
|
||||||
this.model.addJobSchedule(selectedSchedule);
|
if (!existingSchedule) {
|
||||||
|
selectedSchedule.jobName = this.model.name ? this.model.name : this.nameTextBox.value;
|
||||||
|
this.schedules.push(selectedSchedule);
|
||||||
|
}
|
||||||
this.populateScheduleTable();
|
this.populateScheduleTable();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -402,8 +404,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private populateScheduleTable() {
|
private populateScheduleTable() {
|
||||||
let schedules = this.model.jobSchedules ? this.model.jobSchedules : [];
|
let data = this.convertSchedulesToData(this.schedules);
|
||||||
let data = this.convertSchedulesToData(schedules);
|
|
||||||
if (data.length > 0) {
|
if (data.length > 0) {
|
||||||
this.schedulesTable.data = data;
|
this.schedulesTable.data = data;
|
||||||
this.schedulesTable.height = 750;
|
this.schedulesTable.height = 750;
|
||||||
@@ -566,5 +567,17 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
this.model.pageLevel = this.getActualConditionValue(this.pagerCheckBox, this.pagerConditionDropdown);
|
this.model.pageLevel = this.getActualConditionValue(this.pagerCheckBox, this.pagerConditionDropdown);
|
||||||
this.model.eventLogLevel = this.getActualConditionValue(this.eventLogCheckBox, this.eventLogConditionDropdown);
|
this.model.eventLogLevel = this.getActualConditionValue(this.eventLogCheckBox, this.eventLogConditionDropdown);
|
||||||
this.model.deleteLevel = this.getActualConditionValue(this.deleteJobCheckBox, this.deleteJobConditionDropdown);
|
this.model.deleteLevel = this.getActualConditionValue(this.deleteJobCheckBox, this.deleteJobConditionDropdown);
|
||||||
|
if (!this.model.jobSteps) {
|
||||||
|
this.model.jobSteps = [];
|
||||||
|
}
|
||||||
|
this.model.jobSteps = this.steps;
|
||||||
|
if (!this.model.jobSchedules) {
|
||||||
|
this.model.jobSchedules = [];
|
||||||
|
}
|
||||||
|
this.model.jobSchedules = this.schedules;
|
||||||
|
if (!this.model.alerts) {
|
||||||
|
this.model.alerts = [];
|
||||||
|
}
|
||||||
|
this.model.alerts = this.alerts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,9 +118,10 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
|
|||||||
server: string,
|
server: string,
|
||||||
jobModel: JobData,
|
jobModel: JobData,
|
||||||
jobStepInfo?: sqlops.AgentJobStepInfo,
|
jobStepInfo?: sqlops.AgentJobStepInfo,
|
||||||
|
viaJobDialog: boolean = false
|
||||||
) {
|
) {
|
||||||
super(ownerUri,
|
super(ownerUri,
|
||||||
jobStepInfo ? JobStepData.convertToJobStepData(jobStepInfo, jobModel) : new JobStepData(ownerUri, jobModel),
|
jobStepInfo ? JobStepData.convertToJobStepData(jobStepInfo, jobModel) : new JobStepData(ownerUri, jobModel, viaJobDialog),
|
||||||
jobStepInfo ? JobStepDialog.EditDialogTitle : JobStepDialog.NewDialogTitle);
|
jobStepInfo ? JobStepDialog.EditDialogTitle : JobStepDialog.NewDialogTitle);
|
||||||
this.stepId = jobStepInfo ?
|
this.stepId = jobStepInfo ?
|
||||||
jobStepInfo.id : jobModel.jobSteps ?
|
jobStepInfo.id : jobModel.jobSteps ?
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
|
|||||||
private static readonly PagerSundayCheckBoxLabel: string = localize('createOperator.PagerSundayCheckBox', 'Sunday');
|
private static readonly PagerSundayCheckBoxLabel: string = localize('createOperator.PagerSundayCheckBox', 'Sunday');
|
||||||
private static readonly WorkdayBeginLabel: string = localize('createOperator.workdayBegin', 'Workday begin');
|
private static readonly WorkdayBeginLabel: string = localize('createOperator.workdayBegin', 'Workday begin');
|
||||||
private static readonly WorkdayEndLabel: string = localize('createOperator.workdayEnd', 'Workday end');
|
private static readonly WorkdayEndLabel: string = localize('createOperator.workdayEnd', 'Workday end');
|
||||||
private static readonly PagerDutyScheduleLabel: string = localize('createOperator.PagerDutySchedule', 'Pager on duty schdule');
|
private static readonly PagerDutyScheduleLabel: string = localize('createOperator.PagerDutySchedule', 'Pager on duty schedule');
|
||||||
|
|
||||||
// Notifications tab strings
|
// Notifications tab strings
|
||||||
private static readonly AlertsTableLabel: string = localize('createOperator.AlertListHeading', 'Alert list');
|
private static readonly AlertsTableLabel: string = localize('createOperator.AlertListHeading', 'Alert list');
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import { ProxyDialog } from './dialogs/proxyDialog';
|
|||||||
import { JobStepDialog } from './dialogs/jobStepDialog';
|
import { JobStepDialog } from './dialogs/jobStepDialog';
|
||||||
import { PickScheduleDialog } from './dialogs/pickScheduleDialog';
|
import { PickScheduleDialog } from './dialogs/pickScheduleDialog';
|
||||||
import { JobData } from './data/jobData';
|
import { JobData } from './data/jobData';
|
||||||
|
import { AgentUtils } from './agentUtils';
|
||||||
|
|
||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
@@ -41,18 +42,24 @@ export class MainController {
|
|||||||
let dialog = new JobDialog(ownerUri, jobInfo);
|
let dialog = new JobDialog(ownerUri, jobInfo);
|
||||||
dialog.openDialog();
|
dialog.openDialog();
|
||||||
});
|
});
|
||||||
vscode.commands.registerCommand('agent.openNewStepDialog', (ownerUri: string, server: string, jobData: JobData, jobStepInfo: sqlops.AgentJobStepInfo) => {
|
vscode.commands.registerCommand('agent.openNewStepDialog', (ownerUri: string, server: string, jobInfo: sqlops.AgentJobInfo, jobStepInfo: sqlops.AgentJobStepInfo) => {
|
||||||
let dialog = new JobStepDialog(ownerUri, server, jobData, jobStepInfo);
|
AgentUtils.getAgentService().then((agentService) => {
|
||||||
|
let jobData: JobData = new JobData(ownerUri, jobInfo, agentService);
|
||||||
|
let dialog = new JobStepDialog(ownerUri, server, jobData, jobStepInfo, false);
|
||||||
dialog.openDialog();
|
dialog.openDialog();
|
||||||
});
|
});
|
||||||
|
});
|
||||||
vscode.commands.registerCommand('agent.openPickScheduleDialog', (ownerUri: string, jobName: string) => {
|
vscode.commands.registerCommand('agent.openPickScheduleDialog', (ownerUri: string, jobName: string) => {
|
||||||
let dialog = new PickScheduleDialog(ownerUri, jobName);
|
let dialog = new PickScheduleDialog(ownerUri, jobName);
|
||||||
dialog.showDialog();
|
dialog.showDialog();
|
||||||
});
|
});
|
||||||
vscode.commands.registerCommand('agent.openAlertDialog', (ownerUri: string, alertInfo: sqlops.AgentAlertInfo, jobs: string[]) => {
|
vscode.commands.registerCommand('agent.openAlertDialog', (ownerUri: string, jobInfo: sqlops.AgentJobInfo, alertInfo: sqlops.AgentAlertInfo) => {
|
||||||
let dialog = new AlertDialog(ownerUri, alertInfo, jobs);
|
AgentUtils.getAgentService().then((agentService) => {
|
||||||
|
let jobData: JobData = new JobData(ownerUri, jobInfo, agentService);
|
||||||
|
let dialog = new AlertDialog(ownerUri, jobData, alertInfo, false);
|
||||||
dialog.openDialog();
|
dialog.openDialog();
|
||||||
});
|
});
|
||||||
|
});
|
||||||
vscode.commands.registerCommand('agent.openOperatorDialog', (ownerUri: string, operatorInfo: sqlops.AgentOperatorInfo) => {
|
vscode.commands.registerCommand('agent.openOperatorDialog', (ownerUri: string, operatorInfo: sqlops.AgentOperatorInfo) => {
|
||||||
let dialog = new OperatorDialog(ownerUri, operatorInfo);
|
let dialog = new OperatorDialog(ownerUri, operatorInfo);
|
||||||
dialog.openDialog();
|
dialog.openDialog();
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "import",
|
"name": "import",
|
||||||
"displayName": "SQL Server Import",
|
"displayName": "SQL Server Import",
|
||||||
"description": "SQL Server Import for Azure Data Studio supports importing CSV or JSON files into SQL Server.",
|
"description": "SQL Server Import for Azure Data Studio supports importing CSV or JSON files into SQL Server.",
|
||||||
"version": "0.3.0",
|
"version": "0.4.0",
|
||||||
"publisher": "Microsoft",
|
"publisher": "Microsoft",
|
||||||
"preview": true,
|
"preview": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -42,33 +42,6 @@
|
|||||||
"mac": "ctrl+i"
|
"mac": "ctrl+i"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dashboard.tabs": [
|
|
||||||
{
|
|
||||||
"id": "flat-file-import",
|
|
||||||
"title": "Flat File Import",
|
|
||||||
"description": "The flat file importer.",
|
|
||||||
"container": {
|
|
||||||
"flat-file-import-container": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"dashboard.containers": [
|
|
||||||
{
|
|
||||||
"id": "flat-file-import-container",
|
|
||||||
"container": {
|
|
||||||
"widgets-container": [
|
|
||||||
{
|
|
||||||
"name": "Tasks",
|
|
||||||
"widget": {
|
|
||||||
"tasks-widget": [
|
|
||||||
"flatFileImport.start"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"menus": {
|
"menus": {
|
||||||
"objectExplorer/item/context": [
|
"objectExplorer/item/context": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export class FlatFileWizard {
|
|||||||
public async start(p: any, ...args: any[]) {
|
public async start(p: any, ...args: any[]) {
|
||||||
let model = <ImportDataModel>{};
|
let model = <ImportDataModel>{};
|
||||||
|
|
||||||
let profile = <sqlops.IConnectionProfile>p.connectionProfile;
|
let profile = p ? <sqlops.IConnectionProfile>p.connectionProfile : null;
|
||||||
if (profile) {
|
if (profile) {
|
||||||
model.serverId = profile.id;
|
model.serverId = profile.id;
|
||||||
model.database = profile.databaseName;
|
model.database = profile.databaseName;
|
||||||
|
|||||||
@@ -345,7 +345,7 @@
|
|||||||
"specialValueType": null,
|
"specialValueType": null,
|
||||||
"isIdentity": false,
|
"isIdentity": false,
|
||||||
"name": "asynchronousProcessing",
|
"name": "asynchronousProcessing",
|
||||||
"displayName": "Asynchronous processing enabled",
|
"displayName": "Asynchronous processing",
|
||||||
"description": "When true, enables usage of the Asynchronous functionality in the .Net Framework Data Provider",
|
"description": "When true, enables usage of the Asynchronous functionality in the .Net Framework Data Provider",
|
||||||
"groupName": "Initialization",
|
"groupName": "Initialization",
|
||||||
"valueType": "boolean",
|
"valueType": "boolean",
|
||||||
@@ -387,7 +387,7 @@
|
|||||||
"specialValueType": null,
|
"specialValueType": null,
|
||||||
"isIdentity": false,
|
"isIdentity": false,
|
||||||
"name": "columnEncryptionSetting",
|
"name": "columnEncryptionSetting",
|
||||||
"displayName": "Column encryption setting",
|
"displayName": "Column encryption",
|
||||||
"description": "Default column encryption setting for all the commands on the connection",
|
"description": "Default column encryption setting for all the commands on the connection",
|
||||||
"groupName": "Security",
|
"groupName": "Security",
|
||||||
"valueType": "category",
|
"valueType": "category",
|
||||||
|
|||||||
@@ -42,18 +42,18 @@
|
|||||||
"Create a new Table": {
|
"Create a new Table": {
|
||||||
"prefix": "sqlCreateTable",
|
"prefix": "sqlCreateTable",
|
||||||
"body": [
|
"body": [
|
||||||
"-- Create a new table called '[${1:TableName}]' in schema '[${2:SchemaName}]' in database '[${3:DatabaseName}]'",
|
"-- Create a new table called '[${1:TableName}]' in schema '[${2:dbo}]'",
|
||||||
"-- Drop the table if it already exists",
|
"-- Drop the table if it already exists",
|
||||||
"IF OBJECT_ID('[${3:DatabaseName}].[${2:SchemaName}].[${1:TableName}]', 'U') IS NOT NULL",
|
"IF OBJECT_ID('[${2:dbo}].[${1:TableName}]', 'U') IS NOT NULL",
|
||||||
"DROP TABLE [${3:DatabaseName}].[${2:SchemaName}].[${1:TableName}]",
|
"DROP TABLE [${2:dbo}].[${1:TableName}]",
|
||||||
"GO",
|
"GO",
|
||||||
"-- Create the table in the specified database and schema",
|
"-- Create the table in the specified schema",
|
||||||
"CREATE TABLE [${3:DatabaseName}].[${2:SchemaName}].[${1:TableName}]",
|
"CREATE TABLE [${2:dbo}].[${1:TableName}]",
|
||||||
"(",
|
"(",
|
||||||
"\t[${4:ColumnName}]Id INT NOT NULL PRIMARY KEY, -- Primary Key column",
|
"\t[${3:Id}] INT NOT NULL PRIMARY KEY, -- Primary Key column",
|
||||||
"\t[${5:ColumnName1}] [NVARCHAR](50) NOT NULL,",
|
"\t[${4:ColumnName2}] ${5:NVARCHAR(50)} NOT NULL,",
|
||||||
"\t[${6:ColumnName2}] [NVARCHAR](50) NOT NULL",
|
"\t[${6:ColumnName3}] ${7:NVARCHAR(50)} NOT NULL",
|
||||||
"\t-- Specify more columns here",
|
"\t$0-- Specify more columns here",
|
||||||
");",
|
");",
|
||||||
"GO"
|
"GO"
|
||||||
],
|
],
|
||||||
@@ -64,10 +64,10 @@
|
|||||||
"Drop a Table": {
|
"Drop a Table": {
|
||||||
"prefix": "sqlDropTable",
|
"prefix": "sqlDropTable",
|
||||||
"body": [
|
"body": [
|
||||||
"-- Drop a table called '${3:TableName}' in schema '${2:SchemaName}' in Database '${1:DatabaseName}'",
|
"-- Drop a table called '${1:TableName}' in schema '${2:dbo}'",
|
||||||
"-- Drop the table if it already exists",
|
"-- Drop the table if it already exists",
|
||||||
"IF OBJECT_ID('[${1:DatabaseName}].[${2:SchemaName}].[${3:TableName}]', 'U') IS NOT NULL",
|
"IF OBJECT_ID('[${2:dbo}].[${1:TableName}]', 'U') IS NOT NULL",
|
||||||
"DROP TABLE [${1:DatabaseName}].[${2:SchemaName}].[${3:TableName}]",
|
"DROP TABLE [${2:dbo}].[${1:TableName}]",
|
||||||
"GO"
|
"GO"
|
||||||
],
|
],
|
||||||
"description": "Drop a Table"
|
"description": "Drop a Table"
|
||||||
@@ -76,9 +76,9 @@
|
|||||||
"Add a new column to a Table": {
|
"Add a new column to a Table": {
|
||||||
"prefix": "sqlAddColumn",
|
"prefix": "sqlAddColumn",
|
||||||
"body": [
|
"body": [
|
||||||
"-- Add a new column '[${1:NewColumnName}]' to table '[${2:TableName}]' in schema '[${3:SchemaName}]' in database '[${4:DatabaseName}]'",
|
"-- Add a new column '[${1:NewColumnName}]' to table '[${2:TableName}]' in schema '[${3:dbo}]'",
|
||||||
"ALTER TABLE [${4:DatabaseName}].[${3:SchemaName}].[${2:TableName}]",
|
"ALTER TABLE [${3:dbo}].[${2:TableName}]",
|
||||||
"\tADD [${1:NewColumnName}] /*new_column_name*/ ${5:int} /*new_column_datatype*/ ${6:NULL} /*new_column_nullability*/",
|
"\tADD [${1:NewColumnName}] /*new_column_name*/ ${4:int} /*new_column_datatype*/ ${5:NULL} /*new_column_nullability*/",
|
||||||
"GO"
|
"GO"
|
||||||
],
|
],
|
||||||
"description": "Add a new column to a Table"
|
"description": "Add a new column to a Table"
|
||||||
@@ -87,8 +87,8 @@
|
|||||||
"Drop a column from a Table": {
|
"Drop a column from a Table": {
|
||||||
"prefix": "sqlDropColumn",
|
"prefix": "sqlDropColumn",
|
||||||
"body": [
|
"body": [
|
||||||
"-- Drop '[${1:ColumnName}]' from table '[${2:TableName}]' in schema '[${3:SchemaName}]' in database '[${4:DatabaseName}]'",
|
"-- Drop '[${1:ColumnName}]' from table '[${2:TableName}]' in schema '[${3:dbo}]'",
|
||||||
"ALTER TABLE [${4:DatabaseName}].[${3:SchemaName}].[${2:TableName}]",
|
"ALTER TABLE [${3:dbo}].[${2:TableName}]",
|
||||||
"\tDROP COLUMN [${1:ColumnName}]",
|
"\tDROP COLUMN [${1:ColumnName}]",
|
||||||
"GO"
|
"GO"
|
||||||
],
|
],
|
||||||
@@ -98,9 +98,9 @@
|
|||||||
"Select rows from a Table or a View": {
|
"Select rows from a Table or a View": {
|
||||||
"prefix": "sqlSelect",
|
"prefix": "sqlSelect",
|
||||||
"body": [
|
"body": [
|
||||||
"-- Select rows from a Table or View '[${1:TableOrViewName}]' in schema '[${2:SchemaName}]' in database '[${3:DatabaseName}]'",
|
"-- Select rows from a Table or View '[${1:TableOrViewName}]' in schema '[${2:dbo}]'",
|
||||||
"SELECT * FROM [${3:DatabaseName}].[${2:SchemaName}].[${1:TableOrViewName}]",
|
"SELECT * FROM [${2:dbo}].[${1:TableOrViewName}]",
|
||||||
"WHERE ${4:/* add search conditions here */}",
|
"WHERE ${3:/* add search conditions here */}",
|
||||||
"GO"
|
"GO"
|
||||||
],
|
],
|
||||||
"description": "Select rows from a Table or a View"
|
"description": "Select rows from a Table or a View"
|
||||||
@@ -109,17 +109,17 @@
|
|||||||
"Insert rows into a Table": {
|
"Insert rows into a Table": {
|
||||||
"prefix": "sqlInsertRows",
|
"prefix": "sqlInsertRows",
|
||||||
"body": [
|
"body": [
|
||||||
"-- Insert rows into table '${1:TableName}' in schema '[${2:SchemaName}]' in database '[${3:DatabaseName}]'",
|
"-- Insert rows into table '${1:TableName}' in schema '[${2:dbo}]'",
|
||||||
"INSERT INTO [${3:DatabaseName}].[${2:SchemaName}].[${1:TableName}]",
|
"INSERT INTO [${2:dbo}].[${1:TableName}]",
|
||||||
"( -- Columns to insert data into",
|
"( -- Columns to insert data into",
|
||||||
" ${4:[ColumnName1], [ColumnName2], [ColumnName3]}",
|
" ${3:[ColumnName1], [ColumnName2], [ColumnName3]}",
|
||||||
")",
|
")",
|
||||||
"VALUES",
|
"VALUES",
|
||||||
"( -- First row: values for the columns in the list above",
|
"( -- First row: values for the columns in the list above",
|
||||||
" ${5:ColumnValue1, ColumnValue2, ColumnValue3}",
|
" ${4:ColumnValue1, ColumnValue2, ColumnValue3}",
|
||||||
"),",
|
"),",
|
||||||
"( -- Second row: values for the columns in the list above",
|
"( -- Second row: values for the columns in the list above",
|
||||||
" ${6:ColumnValue1, ColumnValue2, ColumnValue3}",
|
" ${5:ColumnValue1, ColumnValue2, ColumnValue3}",
|
||||||
")",
|
")",
|
||||||
"-- Add more rows here",
|
"-- Add more rows here",
|
||||||
"GO"
|
"GO"
|
||||||
@@ -130,9 +130,9 @@
|
|||||||
"Delete rows from a Table": {
|
"Delete rows from a Table": {
|
||||||
"prefix": "sqlDeleteRows",
|
"prefix": "sqlDeleteRows",
|
||||||
"body": [
|
"body": [
|
||||||
"-- Delete rows from table '[${1:TableName}]' in schema '[${2:SchemaName}]' in database '[${3:DatabaseName}]'",
|
"-- Delete rows from table '[${1:TableName}]' in schema '[${2:dbo}]'",
|
||||||
"DELETE FROM [${3:DatabaseName}].[${2:SchemaName}].[${1:TableName}]",
|
"DELETE FROM [${2:dbo}].[${1:TableName}]",
|
||||||
"WHERE ${4:/* add search conditions here */}",
|
"WHERE ${3:/* add search conditions here */}",
|
||||||
"GO"
|
"GO"
|
||||||
],
|
],
|
||||||
"description": "Delete rows from a Table"
|
"description": "Delete rows from a Table"
|
||||||
@@ -141,13 +141,13 @@
|
|||||||
"Update rows in a Table": {
|
"Update rows in a Table": {
|
||||||
"prefix": "sqlUpdateRows",
|
"prefix": "sqlUpdateRows",
|
||||||
"body": [
|
"body": [
|
||||||
"-- Update rows in table '[${1:TableName}]' in schema '[${2:SchemaName}]' in database '[${3:DatabaseName}]'",
|
"-- Update rows in table '[${1:TableName}]' in schema '[${2:dbo}]'",
|
||||||
"UPDATE [${3:DatabaseName}].[${2:SchemaName}].[${1:TableName}]",
|
"UPDATE [${2:dbo}].[${1:TableName}]",
|
||||||
"SET",
|
"SET",
|
||||||
"\t[${4:ColumnName1}] = ${5:ColumnValue1},",
|
"\t[${3:ColumnName1}] = ${4:ColumnValue1},",
|
||||||
"\t[${6:ColumnName2}] = ${7:ColumnValue2}",
|
"\t[${5:ColumnName2}] = ${6:ColumnValue2}",
|
||||||
"\t-- Add more columns and values here",
|
"\t-- Add more columns and values here",
|
||||||
"WHERE ${8:/* add search conditions here */}",
|
"WHERE ${7:/* add search conditions here */}",
|
||||||
"GO"
|
"GO"
|
||||||
],
|
],
|
||||||
"description": "Update rows in a Table"
|
"description": "Update rows in a Table"
|
||||||
@@ -156,27 +156,27 @@
|
|||||||
"Create a stored procedure": {
|
"Create a stored procedure": {
|
||||||
"prefix": "sqlCreateStoredProc",
|
"prefix": "sqlCreateStoredProc",
|
||||||
"body": [
|
"body": [
|
||||||
"-- Create a new stored procedure called '${1:StoredProcedureName}' in schema '${2:SchemaName}'",
|
"-- Create a new stored procedure called '${1:StoredProcedureName}' in schema '${2:dbo}'",
|
||||||
"-- Drop the stored procedure if it already exists",
|
"-- Drop the stored procedure if it already exists",
|
||||||
"IF EXISTS (",
|
"IF EXISTS (",
|
||||||
"SELECT *",
|
"SELECT *",
|
||||||
"\tFROM INFORMATION_SCHEMA.ROUTINES",
|
"\tFROM INFORMATION_SCHEMA.ROUTINES",
|
||||||
"WHERE SPECIFIC_SCHEMA = N'${2:SchemaName}'",
|
"WHERE SPECIFIC_SCHEMA = N'${2:dbo}'",
|
||||||
"\tAND SPECIFIC_NAME = N'${1:StoredProcedureName}'",
|
"\tAND SPECIFIC_NAME = N'${1:StoredProcedureName}'",
|
||||||
")",
|
")",
|
||||||
"DROP PROCEDURE ${2:SchemaName}.${1:StoredProcedureName}",
|
"DROP PROCEDURE ${2:dbo}.${1:StoredProcedureName}",
|
||||||
"GO",
|
"GO",
|
||||||
"-- Create the stored procedure in the specified schema",
|
"-- Create the stored procedure in the specified schema",
|
||||||
"CREATE PROCEDURE ${2:SchemaName}.${1:StoredProcedureName}",
|
"CREATE PROCEDURE ${2:dbo}.${1:StoredProcedureName}",
|
||||||
"\t$3@param1 /*parameter name*/ int /*datatype_for_param1*/ = 0, /*default_value_for_param1*/",
|
"\t$3@param1 /*parameter name*/ $4int /*datatype_for_param1*/ = 0, /*default_value_for_param1*/",
|
||||||
"\t$4@param2 /*parameter name*/ int /*datatype_for_param1*/ = 0 /*default_value_for_param2*/",
|
"\t$5@param2 /*parameter name*/ $6int /*datatype_for_param1*/ = 0 /*default_value_for_param2*/",
|
||||||
"-- add more stored procedure parameters here",
|
"-- add more stored procedure parameters here",
|
||||||
"AS",
|
"AS",
|
||||||
"\t-- body of the stored procedure",
|
"\t-- body of the stored procedure",
|
||||||
"\tSELECT @param1, @param2",
|
"\tSELECT @param1, @param2",
|
||||||
"GO",
|
"GO",
|
||||||
"-- example to execute the stored procedure we just created",
|
"-- example to execute the stored procedure we just created",
|
||||||
"EXECUTE ${2:SchemaName}.${1:StoredProcedureName} 1 /*value_for_param1*/, 2 /*value_for_param2*/",
|
"EXECUTE ${2:dbo}.${1:StoredProcedureName} 1 /*value_for_param1*/, 2 /*value_for_param2*/",
|
||||||
"GO"
|
"GO"
|
||||||
],
|
],
|
||||||
"description": "Create a stored procedure"
|
"description": "Create a stored procedure"
|
||||||
@@ -185,14 +185,14 @@
|
|||||||
"Drop a stored procedure": {
|
"Drop a stored procedure": {
|
||||||
"prefix": "sqlDropStoredProc",
|
"prefix": "sqlDropStoredProc",
|
||||||
"body": [
|
"body": [
|
||||||
"-- Drop the stored procedure called '${1:StoredProcedureName}' in schema '${2:SchemaName}'",
|
"-- Drop the stored procedure called '${1:StoredProcedureName}' in schema '${2:dbo}'",
|
||||||
"IF EXISTS (",
|
"IF EXISTS (",
|
||||||
"SELECT *",
|
"SELECT *",
|
||||||
"\tFROM INFORMATION_SCHEMA.ROUTINES",
|
"\tFROM INFORMATION_SCHEMA.ROUTINES",
|
||||||
"WHERE SPECIFIC_SCHEMA = N'${2:SchemaName}'",
|
"WHERE SPECIFIC_SCHEMA = N'${2:dbo}'",
|
||||||
"\tAND SPECIFIC_NAME = N'${1:StoredProcedureName}'",
|
"\tAND SPECIFIC_NAME = N'${1:StoredProcedureName}'",
|
||||||
")",
|
")",
|
||||||
"DROP PROCEDURE ${2:SchemaName}.${1:StoredProcedureName}",
|
"DROP PROCEDURE ${2:dbo}.${1:StoredProcedureName}",
|
||||||
"GO"
|
"GO"
|
||||||
],
|
],
|
||||||
"description": "Drop a stored procedure"
|
"description": "Drop a stored procedure"
|
||||||
@@ -241,7 +241,7 @@
|
|||||||
"Declare a cursor": {
|
"Declare a cursor": {
|
||||||
"prefix": "sqlCursor",
|
"prefix": "sqlCursor",
|
||||||
"body": [
|
"body": [
|
||||||
"-- Declare a cursor for a Table or a View '${1:TableOrViewName}' in schema '${2:SchemaName}'",
|
"-- Declare a cursor for a Table or a View '${1:TableOrViewName}' in schema '${2:dbo}'",
|
||||||
"DECLARE @ColumnName1 NVARCHAR(50), @ColumnName2 NVARCHAR(50)",
|
"DECLARE @ColumnName1 NVARCHAR(50), @ColumnName2 NVARCHAR(50)",
|
||||||
"",
|
"",
|
||||||
"DECLARE db_cursor CURSOR FOR",
|
"DECLARE db_cursor CURSOR FOR",
|
||||||
@@ -304,8 +304,8 @@
|
|||||||
"prefix": "sqlCreateIndex",
|
"prefix": "sqlCreateIndex",
|
||||||
"body": [
|
"body": [
|
||||||
"-- Create a nonclustered index with or without a unique constraint",
|
"-- Create a nonclustered index with or without a unique constraint",
|
||||||
"-- Or create a clustered index on table '[${1:TableName}]' in schema '[${2:SchemaName}]' in database '[${3:DatabaseName}]'",
|
"-- Or create a clustered index on table '[${1:TableName}]' in schema '[${2:dbo}]' in database '[${3:DatabaseName}]'",
|
||||||
"CREATE ${5:/*UNIQUE or CLUSTERED*/} INDEX IX_${4:IndexName} ON [${3:DatabaseName}].[${2:SchemaName}].[${1:TableName}] ([${6:ColumnName1}] DESC /*Change sort order as needed*/",
|
"CREATE ${5:/*UNIQUE or CLUSTERED*/} INDEX IX_${4:IndexName} ON [${3:DatabaseName}].[${2:dbo}].[${1:TableName}] ([${6:ColumnName1}] DESC /*Change sort order as needed*/",
|
||||||
"GO"
|
"GO"
|
||||||
],
|
],
|
||||||
"description": "Create a new Index"
|
"description": "Create a new Index"
|
||||||
@@ -319,13 +319,13 @@
|
|||||||
"IF OBJECT_ID('tempDB..#${1:TableName}', 'U') IS NOT NULL",
|
"IF OBJECT_ID('tempDB..#${1:TableName}', 'U') IS NOT NULL",
|
||||||
"DROP TABLE #${1:TableName}",
|
"DROP TABLE #${1:TableName}",
|
||||||
"GO",
|
"GO",
|
||||||
"-- Create the temporary table from a physical table called '${4:TableName}' in schema '${3:SchemaName}' in database '${2:DatabaseName}'",
|
"-- Create the temporary table from a physical table called '${4:TableName}' in schema '${3:dbo}' in database '${2:DatabaseName}'",
|
||||||
"SELECT *",
|
"SELECT *",
|
||||||
"INTO #${1:TableName}",
|
"INTO #${1:TableName}",
|
||||||
"FROM [${2:DatabaseName}].[${3:[SchemaName}].[${4:TableName}]",
|
"FROM [${2:DatabaseName}].[${3:[dbo}].[${4:TableName}]",
|
||||||
"WHERE ${5:/* add search conditions here */}"
|
"WHERE ${5:/* add search conditions here */}"
|
||||||
],
|
],
|
||||||
"description": "Create a new Temporary Table"
|
"description": "Create a new Temporary Table"
|
||||||
},
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
|
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
|
||||||
"version": "1.5.0-alpha.48",
|
"version": "1.5.0-alpha.52",
|
||||||
"downloadFileNames": {
|
"downloadFileNames": {
|
||||||
"Windows_86": "win-x86-netcoreapp2.2.zip",
|
"Windows_86": "win-x86-netcoreapp2.2.zip",
|
||||||
"Windows_64": "win-x64-netcoreapp2.2.zip",
|
"Windows_64": "win-x64-netcoreapp2.2.zip",
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { CreateSessionData } from '../data/createSessionData';
|
|||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
export class CreateSessionDialog {
|
export class CreateSessionDialog {
|
||||||
|
private readonly _providerType: string;
|
||||||
|
|
||||||
// Top level
|
// Top level
|
||||||
private readonly DialogTitle: string = localize('createSessionDialog.newSession', 'New Session');
|
private readonly DialogTitle: string = localize('createSessionDialog.newSession', 'New Session');
|
||||||
@@ -30,13 +31,17 @@ export class CreateSessionDialog {
|
|||||||
public readonly onSuccess: vscode.Event<CreateSessionData> = this._onSuccess.event;
|
public readonly onSuccess: vscode.Event<CreateSessionData> = this._onSuccess.event;
|
||||||
|
|
||||||
|
|
||||||
constructor(ownerUri: string, templates: Array<sqlops.ProfilerSessionTemplate>) {
|
constructor(ownerUri: string, providerType: string, templates: Array<sqlops.ProfilerSessionTemplate>) {
|
||||||
if (typeof (templates) === 'undefined' || templates === null) {
|
if (typeof (templates) === 'undefined' || templates === null) {
|
||||||
throw new Error(localize('createSessionDialog.templatesInvalid', "Invalid templates list, cannot open dialog"));
|
throw new Error(localize('createSessionDialog.templatesInvalid', "Invalid templates list, cannot open dialog"));
|
||||||
}
|
}
|
||||||
if (typeof (ownerUri) === 'undefined' || ownerUri === null) {
|
if (typeof (ownerUri) === 'undefined' || ownerUri === null) {
|
||||||
throw new Error(localize('createSessionDialog.dialogOwnerInvalid', "Invalid dialog owner, cannot open dialog"));
|
throw new Error(localize('createSessionDialog.dialogOwnerInvalid', "Invalid dialog owner, cannot open dialog"));
|
||||||
}
|
}
|
||||||
|
if (typeof (providerType) === 'undefined' || providerType === null) {
|
||||||
|
throw new Error(localize('createSessionDialog.invalidProviderType', "Invalid provider type, cannot open dialog"));
|
||||||
|
}
|
||||||
|
this._providerType = providerType;
|
||||||
this.model = new CreateSessionData(ownerUri, templates);
|
this.model = new CreateSessionData(ownerUri, templates);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,8 +102,7 @@ export class CreateSessionDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async execute(): Promise<void> {
|
private async execute(): Promise<void> {
|
||||||
let currentConnection = await sqlops.connection.getCurrentConnection();
|
let profilerService = sqlops.dataprotocol.getProvider<sqlops.ProfilerProvider>(this._providerType, sqlops.DataProviderType.ProfilerProvider);
|
||||||
let profilerService = sqlops.dataprotocol.getProvider<sqlops.ProfilerProvider>(currentConnection.providerName, sqlops.DataProviderType.ProfilerProvider);
|
|
||||||
|
|
||||||
let name = this.sessionNameBox.value;
|
let name = this.sessionNameBox.value;
|
||||||
let selected = this.templatesBox.value.toString();
|
let selected = this.templatesBox.value.toString();
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ export class MainController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public activate(): void {
|
public activate(): void {
|
||||||
vscode.commands.registerCommand('profiler.openCreateSessionDialog', (ownerUri: string, templates: Array<sqlops.ProfilerSessionTemplate>) => {
|
vscode.commands.registerCommand('profiler.openCreateSessionDialog', (ownerUri: string, providerType: string, templates: Array<sqlops.ProfilerSessionTemplate>) => {
|
||||||
let dialog = new CreateSessionDialog(ownerUri, templates);
|
let dialog = new CreateSessionDialog(ownerUri, providerType, templates);
|
||||||
dialog.showDialog();
|
dialog.showDialog();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "profiler",
|
"name": "profiler",
|
||||||
"displayName": "SQL Server Profiler",
|
"displayName": "SQL Server Profiler",
|
||||||
"description": "SQL Server Profiler for Azure Data Studio",
|
"description": "SQL Server Profiler for Azure Data Studio",
|
||||||
"version": "0.2.0",
|
"version": "0.3.0",
|
||||||
"publisher": "Microsoft",
|
"publisher": "Microsoft",
|
||||||
"preview": true,
|
"preview": true,
|
||||||
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/LICENSE.txt",
|
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/LICENSE.txt",
|
||||||
@@ -26,7 +26,6 @@
|
|||||||
"Microsoft.mssql"
|
"Microsoft.mssql"
|
||||||
],
|
],
|
||||||
"contributes": {
|
"contributes": {
|
||||||
|
|
||||||
"commands": [
|
"commands": [
|
||||||
{
|
{
|
||||||
"command": "profiler.newProfiler",
|
"command": "profiler.newProfiler",
|
||||||
@@ -49,6 +48,15 @@
|
|||||||
"category": "Profiler"
|
"category": "Profiler"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"menus": {
|
||||||
|
"objectExplorer/item/context": [
|
||||||
|
{
|
||||||
|
"command": "profiler.newProfiler",
|
||||||
|
"when": "connectionProvider == MSSQL && nodeType && nodeType == Server",
|
||||||
|
"group": "profiler"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"outputChannels": [
|
"outputChannels": [
|
||||||
"sqlprofiler"
|
"sqlprofiler"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -6,17 +6,17 @@
|
|||||||
|
|
||||||
// base
|
// base
|
||||||
"foreground": "#fffffe",
|
"foreground": "#fffffe",
|
||||||
"focusBorder": "#0E639C",
|
"focusBorder": "#0078d7",
|
||||||
"selection.background": "#3062d6",
|
"selection.background": "#3062d6",
|
||||||
|
|
||||||
//text colors
|
//text colors
|
||||||
"textLinkForeground": "#30B4FF",
|
"textLinkForeground": "#30b4ff",
|
||||||
"textLinkActiveForeground": "#30B4FF",
|
"textLinkActiveForeground": "#30b4ff",
|
||||||
|
|
||||||
//Button control
|
//Button control
|
||||||
"button.background": "#00BCF2",
|
"button.background": "#0078d7cc",
|
||||||
"button.foreground": "#212121",
|
"button.foreground": "#ffffff",
|
||||||
"button.hoverBackground": "#0099BC",
|
"button.hoverBackground": "#0078d7",
|
||||||
|
|
||||||
// TODO add support for these
|
// TODO add support for these
|
||||||
// "button.secondaryBackground": "#c8c8c8",
|
// "button.secondaryBackground": "#c8c8c8",
|
||||||
@@ -25,6 +25,9 @@
|
|||||||
// "button.disabledBackground": "#444444" ,
|
// "button.disabledBackground": "#444444" ,
|
||||||
// "button.disabledForeground": "#888888" ,
|
// "button.disabledForeground": "#888888" ,
|
||||||
|
|
||||||
|
//Checkbox
|
||||||
|
"checkbox.disabled.foreground": "#888888",
|
||||||
|
|
||||||
//Dropdown Control
|
//Dropdown Control
|
||||||
"dropdown.background": "#212121",
|
"dropdown.background": "#212121",
|
||||||
"dropdown.foreground": "#fffffe",
|
"dropdown.foreground": "#fffffe",
|
||||||
@@ -35,24 +38,24 @@
|
|||||||
"input.border": "#888888",
|
"input.border": "#888888",
|
||||||
"input.disabled.background": "#444444",
|
"input.disabled.background": "#444444",
|
||||||
"input.disabled.foreground": "#888888",
|
"input.disabled.foreground": "#888888",
|
||||||
"inputOption.activeBorder": "#007ACC",
|
"inputOption.activeBorder": "#0078d7",
|
||||||
"input.placeholderForeground": "#888888",
|
"input.placeholderForeground": "#888888",
|
||||||
"inputValidation.errorBackground": "#D02E00",
|
"inputValidation.errorBackground": "#b62e00",
|
||||||
"inputValidation.errorBorder": "#D02E00",
|
"inputValidation.errorBorder": "#b62e00",
|
||||||
|
|
||||||
//List and trees
|
//List and trees
|
||||||
"list.activeSelectionBackground": "#3062d6",
|
"list.activeSelectionBackground": "#3062d6",
|
||||||
"list.hoverBackground": "#444444",
|
"list.hoverBackground": "#444444",
|
||||||
"pickerGroup.border": "#00BCF2",
|
"pickerGroup.border": "#0078d7",
|
||||||
"activityBar.background": "#444444",
|
"activityBar.background": "#444444",
|
||||||
"sideBar.background": "#333333",
|
"sideBar.background": "#333333",
|
||||||
"sideBarTitle.foreground": "#BBBBBB",
|
"sideBarTitle.foreground": "#bbbbbb",
|
||||||
"input.placeholderForeground": "#A6A6A6",
|
"input.placeholderForeground": "#a6a6a6",
|
||||||
"editorGroupHeader.tabsBackground": "#444444",
|
"editorGroupHeader.tabsBackground": "#444444",
|
||||||
"editor.background": "#212121",
|
"editor.background": "#212121",
|
||||||
"editor.foreground": "#ffffff",
|
"editor.foreground": "#ffffff",
|
||||||
"editorWidget.background": "#444444",
|
"editorWidget.background": "#444444",
|
||||||
"editorLink.activeForeground": "#30B4FF",
|
"editorLink.activeForeground": "#30b4ff",
|
||||||
"editorGroup.border": "#333333",
|
"editorGroup.border": "#333333",
|
||||||
"editorGroup.background": "#212121",
|
"editorGroup.background": "#212121",
|
||||||
"editorIndentGuide.activeBackground": "#707070",
|
"editorIndentGuide.activeBackground": "#707070",
|
||||||
@@ -64,7 +67,8 @@
|
|||||||
"panel.background": "#212121",
|
"panel.background": "#212121",
|
||||||
"panel.border": "#515151",
|
"panel.border": "#515151",
|
||||||
"panelTitle.activeForeground": "#ffffff",
|
"panelTitle.activeForeground": "#ffffff",
|
||||||
"panelTitle.inactiveForeground": "#888888"
|
"panelTitle.inactiveForeground": "#888888",
|
||||||
|
"panelTitle.activeBorder": "#026dc8"
|
||||||
},
|
},
|
||||||
"tokenColors": [
|
"tokenColors": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,18 +5,18 @@
|
|||||||
"colors": {
|
"colors": {
|
||||||
// base
|
// base
|
||||||
"foreground": "#4a4a4a",
|
"foreground": "#4a4a4a",
|
||||||
"focusBorder": "#00BCF2",
|
"focusBorder": "#0078d7",
|
||||||
"selection.background": "#C9D0D9",
|
"selection.background": "#c9d0d9",
|
||||||
"widget.shadow": "#666666",
|
"widget.shadow": "#666666",
|
||||||
|
|
||||||
// text colors
|
// text colors
|
||||||
"textLinkForeground": "#3062D6",
|
"textLinkForeground": "#3062d6",
|
||||||
"textLinkActiveForeground": "#3062D6",
|
"textLinkActiveForeground": "#3062d6",
|
||||||
|
|
||||||
//Button control
|
//Button control
|
||||||
"button.background": "#00BCF2",
|
"button.background": "#0078d7cc",
|
||||||
"button.foreground": "#212121",
|
"button.foreground": "#ffffff",
|
||||||
"button.hoverBackground": "#0099BC",
|
"button.hoverBackground": "#0078d7",
|
||||||
|
|
||||||
// TODO add support for these
|
// TODO add support for these
|
||||||
// "button.secondaryBackground": "#c8c8c8",
|
// "button.secondaryBackground": "#c8c8c8",
|
||||||
@@ -25,35 +25,38 @@
|
|||||||
// "button.disabledBackground": "#eaeaea",
|
// "button.disabledBackground": "#eaeaea",
|
||||||
// "button.disabledForeground": "#888888",
|
// "button.disabledForeground": "#888888",
|
||||||
|
|
||||||
|
//Checkbox
|
||||||
|
"checkbox.disabled.foreground": "#888888",
|
||||||
|
|
||||||
//Dropdown Control
|
//Dropdown Control
|
||||||
"dropdown.background": "#fffffe",
|
"dropdown.background": "#ffffff",
|
||||||
"dropdown.foreground": "#4a4a4a",
|
"dropdown.foreground": "#4a4a4a",
|
||||||
"dropdown.border": "#C8C8C8",
|
"dropdown.border": "#c8c8c8",
|
||||||
|
|
||||||
//badge
|
//badge
|
||||||
"badge.background": "#777777",
|
"badge.background": "#777777",
|
||||||
"badge.foreground": "#ffffff",
|
"badge.foreground": "#ffffff",
|
||||||
|
|
||||||
//Input Control
|
//Input Control
|
||||||
"input.background": "#fffffe",
|
"input.background": "#ffffff",
|
||||||
"input.border": "#c8c8c8",
|
"input.border": "#c8c8c8",
|
||||||
"input.disabled.background": "#dcdcdc",
|
"input.disabled.background": "#dcdcdc",
|
||||||
"input.disabled.foreground": "#888888",
|
"input.disabled.foreground": "#888888",
|
||||||
"inputOption.activeBorder": "#666666",
|
"inputOption.activeBorder": "#666666",
|
||||||
"input.placeholderForeground": "#767676",
|
"input.placeholderForeground": "#767676",
|
||||||
"inputValidation.errorBackground": "#ffeaea",
|
"inputValidation.errorBackground": "#ffeaea",
|
||||||
"inputValidation.errorBorder": "#f1897f",
|
"inputValidation.errorBorder": "#b62e00",
|
||||||
|
|
||||||
//List and tree
|
//List and tree
|
||||||
"list.activeSelectionBackground": "#3062d6",
|
"list.activeSelectionBackground": "#3062d6",
|
||||||
"list.hoverBackground": "#dcdcdc",
|
"list.hoverBackground": "#dcdcdc",
|
||||||
"pickerGroup.border": "#00BCF2",
|
"pickerGroup.border": "#0078d7",
|
||||||
|
|
||||||
// Workbench: Activity Bar
|
// Workbench: Activity Bar
|
||||||
"activityBar.background": "#212121",
|
"activityBar.background": "#212121",
|
||||||
|
|
||||||
// Workbench: Side Bar
|
// Workbench: Side Bar
|
||||||
"sideBar.background": "#EAEAEA",
|
"sideBar.background": "#eaeaea",
|
||||||
"editorGroupHeader.tabsBackground": "#f4f4f4",
|
"editorGroupHeader.tabsBackground": "#f4f4f4",
|
||||||
"editor.background": "#fffffe",
|
"editor.background": "#fffffe",
|
||||||
"editor.foreground": "#212121",
|
"editor.foreground": "#212121",
|
||||||
@@ -64,17 +67,18 @@
|
|||||||
"editorIndentGuide.activeBackground": "#939393",
|
"editorIndentGuide.activeBackground": "#939393",
|
||||||
|
|
||||||
// Workbench: Tabs
|
// Workbench: Tabs
|
||||||
"tab.activeBackground": "#FFFFFE",
|
"tab.activeBackground": "#ffffff",
|
||||||
"tab.activeForeground": "#4A4A4A",
|
"tab.activeForeground": "#4a4a4a",
|
||||||
"tab.inactiveBackground": "#f4f4f4",
|
"tab.inactiveBackground": "#f4f4f4",
|
||||||
"tab.inactiveForeground": "#707070",
|
"tab.inactiveForeground": "#707070",
|
||||||
"tab.border": "#EAEAEA",
|
"tab.border": "#eaeaea",
|
||||||
"tab.unfocusedInactiveForeground": "#888888",
|
"tab.unfocusedInactiveForeground": "#888888",
|
||||||
"tab.unfocusedActiveForeground": "#212121",
|
"tab.unfocusedActiveForeground": "#212121",
|
||||||
"panel.background": "#FFFFFE",
|
"panel.background": "#ffffff",
|
||||||
"panel.border": "#C8C8C8",
|
"panel.border": "#c8c8c8",
|
||||||
"panelTitle.activeForeground": "#212121",
|
"panelTitle.activeForeground": "#212121",
|
||||||
"panelTitle.inactiveForeground": "#757575"
|
"panelTitle.inactiveForeground": "#757575",
|
||||||
|
"panelTitle.activeBorder": "#026dc8"
|
||||||
},
|
},
|
||||||
"tokenColors": [
|
"tokenColors": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "azuredatastudio",
|
"name": "azuredatastudio",
|
||||||
"version": "1.2.2",
|
"version": "1.2.4",
|
||||||
"distro": "8c3e97e3425cc9814496472ab73e076de2ba99ee",
|
"distro": "8c3e97e3425cc9814496472ab73e076de2ba99ee",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Microsoft Corporation"
|
"name": "Microsoft Corporation"
|
||||||
|
|||||||
@@ -611,7 +611,7 @@
|
|||||||
</body></file>
|
</body></file>
|
||||||
<file original="src/sql/parts/connection/common/connectionActions" source-language="en" datatype="plaintext"><body>
|
<file original="src/sql/parts/connection/common/connectionActions" source-language="en" datatype="plaintext"><body>
|
||||||
<trans-unit id="ClearRecentlyUsedLabel">
|
<trans-unit id="ClearRecentlyUsedLabel">
|
||||||
<source xml:lang="en">Clear Recent Connections List</source>
|
<source xml:lang="en">Clear List</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ClearedRecentConnections">
|
<trans-unit id="ClearedRecentConnections">
|
||||||
<source xml:lang="en">Recent connections list cleared</source>
|
<source xml:lang="en">Recent connections list cleared</source>
|
||||||
@@ -1039,10 +1039,10 @@
|
|||||||
<source xml:lang="en">Connection</source>
|
<source xml:lang="en">Connection</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="recentConnectionTitle">
|
<trans-unit id="recentConnectionTitle">
|
||||||
<source xml:lang="en">Recent connections</source>
|
<source xml:lang="en">Recent Connections</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="savedConnectionTitle">
|
<trans-unit id="savedConnectionTitle">
|
||||||
<source xml:lang="en">Saved connections</source>
|
<source xml:lang="en">Saved Connections</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="connectType">
|
<trans-unit id="connectType">
|
||||||
<source xml:lang="en">Connection type</source>
|
<source xml:lang="en">Connection type</source>
|
||||||
@@ -1644,7 +1644,7 @@
|
|||||||
</body></file>
|
</body></file>
|
||||||
<file original="src/sql/parts/connection/connectionDialog/advancedPropertiesController" source-language="en" datatype="plaintext"><body>
|
<file original="src/sql/parts/connection/connectionDialog/advancedPropertiesController" source-language="en" datatype="plaintext"><body>
|
||||||
<trans-unit id="connectionAdvancedProperties">
|
<trans-unit id="connectionAdvancedProperties">
|
||||||
<source xml:lang="en">Advanced properties</source>
|
<source xml:lang="en">Advanced Properties</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="advancedProperties.discard">
|
<trans-unit id="advancedProperties.discard">
|
||||||
<source xml:lang="en">Discard</source>
|
<source xml:lang="en">Discard</source>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { Color } from 'vs/base/common/color';
|
||||||
import { Event, Emitter } from 'vs/base/common/event';
|
import { Event, Emitter } from 'vs/base/common/event';
|
||||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||||
import { Widget } from 'vs/base/browser/ui/widget';
|
import { Widget } from 'vs/base/browser/ui/widget';
|
||||||
@@ -15,9 +16,14 @@ export interface ICheckboxOptions {
|
|||||||
ariaLabel?: string;
|
ariaLabel?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ICheckboxStyles {
|
||||||
|
disabledCheckboxForeground?: Color;
|
||||||
|
}
|
||||||
|
|
||||||
export class Checkbox extends Widget {
|
export class Checkbox extends Widget {
|
||||||
private _el: HTMLInputElement;
|
private _el: HTMLInputElement;
|
||||||
private _label: HTMLSpanElement;
|
private _label: HTMLSpanElement;
|
||||||
|
private disabledCheckboxForeground: Color;
|
||||||
|
|
||||||
private _onChange = new Emitter<boolean>();
|
private _onChange = new Emitter<boolean>();
|
||||||
public readonly onChange: Event<boolean> = this._onChange.event;
|
public readonly onChange: Event<boolean> = this._onChange.event;
|
||||||
@@ -65,6 +71,7 @@ export class Checkbox extends Widget {
|
|||||||
|
|
||||||
public set enabled(val: boolean) {
|
public set enabled(val: boolean) {
|
||||||
this._el.disabled = !val;
|
this._el.disabled = !val;
|
||||||
|
this.updateStyle();
|
||||||
}
|
}
|
||||||
|
|
||||||
public get enabled(): boolean {
|
public get enabled(): boolean {
|
||||||
@@ -90,4 +97,13 @@ export class Checkbox extends Widget {
|
|||||||
public enable(): void {
|
public enable(): void {
|
||||||
this.enabled = true;
|
this.enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public style(styles: ICheckboxStyles): void {
|
||||||
|
this.disabledCheckboxForeground = styles.disabledCheckboxForeground;
|
||||||
|
this.updateStyle();
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateStyle(): void {
|
||||||
|
this._label.style.color = !this.enabled && this.disabledCheckboxForeground ? this.disabledCheckboxForeground.toString() : 'inherit';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,7 @@
|
|||||||
|
|
||||||
.modal .modal-title {
|
.modal .modal-title {
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal .modal-title-icon {
|
.modal .modal-title-icon {
|
||||||
@@ -66,14 +67,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.monaco-shell .modal.flyout-dialog .modal-body,
|
.monaco-shell .modal.flyout-dialog .modal-body,
|
||||||
.monaco-shell .modal.flyout-dialog .angular-modal-body {
|
.monaco-shell .modal.flyout-dialog .angular-modal-body,
|
||||||
margin-bottom: auto;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Style for body and footer in modal dialog. This should be applied to dialog created with angular component. */
|
/* Style for body and footer in modal dialog. This should be applied to dialog created with angular component. */
|
||||||
.monaco-shell .modal.flyout-dialog .modal-body-and-footer {
|
.monaco-shell .modal.flyout-dialog .modal-body-and-footer {
|
||||||
height: 100%;
|
flex: 1 1;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* modl body content style(excluding dialogErrorMessage section) for angulr component dialog */
|
/* modl body content style(excluding dialogErrorMessage section) for angulr component dialog */
|
||||||
@@ -85,6 +83,8 @@
|
|||||||
|
|
||||||
.modal.flyout-dialog .angular-form {
|
.modal.flyout-dialog .angular-form {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal.flyout-dialog .dialog-label {
|
.modal.flyout-dialog .dialog-label {
|
||||||
@@ -105,10 +105,6 @@
|
|||||||
padding-left: 4px;
|
padding-left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal.flyout-dialog .modal-body {
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vs-dark.monaco-shell .modal.flyout-dialog .input {
|
.vs-dark.monaco-shell .modal.flyout-dialog .input {
|
||||||
background-color: #3C3C3C;
|
background-color: #3C3C3C;
|
||||||
}
|
}
|
||||||
@@ -152,7 +148,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.modal .footer-button {
|
.modal .footer-button {
|
||||||
margin-right: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal .right-footer .footer-button:last-of-type {
|
.modal .right-footer .footer-button:last-of-type {
|
||||||
@@ -187,7 +183,6 @@
|
|||||||
|
|
||||||
.modal.flyout-dialog .dialog-message-header {
|
.modal.flyout-dialog .dialog-message-header {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
overflow-y: hidden;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,11 +20,34 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.optionsDialog-options-groups {
|
.optionsDialog-options-groups {
|
||||||
padding: 15px;
|
margin-top: 10px;
|
||||||
height: calc(100% - 150px);
|
flex: 1 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.optionsDialog-options-groups {
|
||||||
|
margin: 10px 0px;
|
||||||
|
flex: 1 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs .optionsDialog-options-groups {
|
||||||
|
box-shadow: 0 1px 4px 1px rgba(220, 220, 220, 0.71);
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs-dark .optionsDialog-options-groups {
|
||||||
|
box-shadow: 0 4px 5px 0px rgba(0, 0, 0, 0.71);
|
||||||
|
}
|
||||||
|
|
||||||
|
.optionsDialog-options-groups .split-view-view .header {
|
||||||
|
padding-left: 28px !important;
|
||||||
|
background-position-x: 8px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.optionsDialog-options-groups .split-view-view .body {
|
||||||
|
padding-left: 5px !important;
|
||||||
|
}
|
||||||
|
|
||||||
.backButtonIcon {
|
.backButtonIcon {
|
||||||
content: url('back.svg');
|
content: url('back.svg');
|
||||||
width: 20px;
|
width: 20px;
|
||||||
@@ -33,21 +56,42 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vs-dark.monaco-shell .backButtonIcon {
|
.hc-black .backButtonIcon,
|
||||||
|
.vs-dark .backButtonIcon {
|
||||||
content: url('back_inverse.svg');
|
content: url('back_inverse.svg');
|
||||||
}
|
}
|
||||||
|
|
||||||
.optionsDialog-description {
|
.optionsDialog-description {
|
||||||
padding: 15px;
|
height: 90px;
|
||||||
|
margin: 15px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.optionsDialog-description .modal-title {
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 2px center;
|
||||||
|
padding-left: 25px;
|
||||||
|
background-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs .optionsDialog-description .modal-title {
|
||||||
|
background-image: url('info_notification.svg')
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs-dark .optionsDialog-description .modal-title,
|
||||||
|
.hc-black .optionsDialog-description .modal-title {
|
||||||
|
background-image: url('info_notification_inverse.svg')
|
||||||
|
}
|
||||||
|
|
||||||
.optionsDialog-options {
|
.optionsDialog-options {
|
||||||
height: calc(100% - 30px);
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.optionsDialog-description-content {
|
.optionsDialog-description-content {
|
||||||
padding: 10px;
|
padding-top: 10px;
|
||||||
|
padding-left: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.optionsDialog-table{
|
.optionsDialog-table{
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
|
|||||||
|
|
||||||
export const MODAL_SHOWING_KEY = 'modalShowing';
|
export const MODAL_SHOWING_KEY = 'modalShowing';
|
||||||
export const MODAL_SHOWING_CONTEXT = new RawContextKey<Array<string>>(MODAL_SHOWING_KEY, []);
|
export const MODAL_SHOWING_CONTEXT = new RawContextKey<Array<string>>(MODAL_SHOWING_KEY, []);
|
||||||
const INFO_ALT_TEXT = localize('infoAltText', 'Infomation');
|
const INFO_ALT_TEXT = localize('infoAltText', 'Information');
|
||||||
const WARNING_ALT_TEXT = localize('warningAltText', 'Warning');
|
const WARNING_ALT_TEXT = localize('warningAltText', 'Warning');
|
||||||
const ERROR_ALT_TEXT = localize('errorAltText', 'Error');
|
const ERROR_ALT_TEXT = localize('errorAltText', 'Error');
|
||||||
const SHOW_DETAILS_TEXT = localize('showMessageDetails', 'Show Details');
|
const SHOW_DETAILS_TEXT = localize('showMessageDetails', 'Show Details');
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ export class OptionsDialog extends Modal {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let builder = new Builder(this._body);
|
let builder = new Builder(this._body);
|
||||||
builder.div({ class: 'Connection-divider' }, (dividerContainer) => {
|
builder.div({}, (dividerContainer) => {
|
||||||
this._dividerBuilder = dividerContainer;
|
this._dividerBuilder = dividerContainer;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -46,9 +46,9 @@ panel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.tabbedPanel .tabList .tab .tabLabel {
|
.tabbedPanel .tabList .tab .tabLabel {
|
||||||
text-transform: uppercase;
|
font-size: 14px;
|
||||||
font-size: 13px;
|
|
||||||
padding-bottom: 4px;
|
padding-bottom: 4px;
|
||||||
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabbedPanel.vertical .tabList .tab .tabLabel {
|
.tabbedPanel.vertical .tabList .tab .tabLabel {
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ export interface IPanelTab {
|
|||||||
interface IInternalPanelTab extends IPanelTab {
|
interface IInternalPanelTab extends IPanelTab {
|
||||||
header: HTMLElement;
|
header: HTMLElement;
|
||||||
label: HTMLElement;
|
label: HTMLElement;
|
||||||
dispose(): void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultOptions: IPanelOptions = {
|
const defaultOptions: IPanelOptions = {
|
||||||
@@ -143,8 +142,6 @@ export class TabbedPanel extends Disposable implements IThemable {
|
|||||||
this.tabList.appendChild(tabHeaderElement);
|
this.tabList.appendChild(tabHeaderElement);
|
||||||
tab.header = tabHeaderElement;
|
tab.header = tabHeaderElement;
|
||||||
tab.label = tabLabel;
|
tab.label = tabLabel;
|
||||||
tab.dispose = () => { };
|
|
||||||
this._register(tab);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public showTab(id: PanelTabIdentifier): void {
|
public showTab(id: PanelTabIdentifier): void {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
|||||||
.tabbedPanel > .title .tabList .tab .tabLabel.active {
|
.tabbedPanel > .title .tabList .tab .tabLabel.active {
|
||||||
color: ${titleActive};
|
color: ${titleActive};
|
||||||
border-bottom-color: ${titleActiveBorder};
|
border-bottom-color: ${titleActiveBorder};
|
||||||
|
border-bottom-width: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabbedPanel > .title .tabList .tab-header.active {
|
.tabbedPanel > .title .tabList .tab-header.active {
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElemen
|
|||||||
import { HeightMap, IView as HeightIView, IViewItem as HeightIViewItem } from './heightMap';
|
import { HeightMap, IView as HeightIView, IViewItem as HeightIViewItem } from './heightMap';
|
||||||
import { ArrayIterator } from 'vs/base/common/iterator';
|
import { ArrayIterator } from 'vs/base/common/iterator';
|
||||||
import { mixin } from 'vs/base/common/objects';
|
import { mixin } from 'vs/base/common/objects';
|
||||||
|
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||||
export { Orientation } from 'vs/base/browser/ui/sash/sash';
|
export { Orientation } from 'vs/base/browser/ui/sash/sash';
|
||||||
|
|
||||||
export interface ISplitViewOptions {
|
export interface ISplitViewOptions {
|
||||||
orientation?: Orientation; // default Orientation.VERTICAL
|
orientation?: Orientation; // default Orientation.VERTICAL
|
||||||
enableResizing?: boolean;
|
enableResizing?: boolean;
|
||||||
|
verticalScrollbarVisibility?: ScrollbarVisibility;
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultOptions: ISplitViewOptions = {
|
const defaultOptions: ISplitViewOptions = {
|
||||||
@@ -127,7 +129,7 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
|
|||||||
this.options = mixin(options, defaultOptions, false);
|
this.options = mixin(options, defaultOptions, false);
|
||||||
|
|
||||||
this.el = document.createElement('div');
|
this.el = document.createElement('div');
|
||||||
this.scrollable = new ScrollableElement(this.el, {});
|
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, 25)(e => {
|
||||||
this.render(e.scrollTop, e.height);
|
this.render(e.scrollTop, e.height);
|
||||||
this.relayout();
|
this.relayout();
|
||||||
|
|||||||
@@ -89,10 +89,6 @@
|
|||||||
-moz-transition-property: width;
|
-moz-transition-property: width;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hc-black .split-view-view .action-label {
|
|
||||||
background: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hc-black .split-view-view > .header .action-label:before {
|
.hc-black .split-view-view > .header .action-label:before {
|
||||||
top: 4px !important;
|
top: 4px !important;
|
||||||
}
|
}
|
||||||
@@ -3,11 +3,14 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { IDisposableDataProvider } from 'sql/base/browser/ui/table/interfaces';
|
||||||
|
|
||||||
export interface IObservableCollection<T> {
|
export interface IObservableCollection<T> {
|
||||||
getLength(): number;
|
getLength(): number;
|
||||||
at(index: number): T;
|
at(index: number): T;
|
||||||
getRange(start: number, end: number): T[];
|
getRange(start: number, end: number): T[];
|
||||||
setCollectionChangedCallback(callback: (change: CollectionChange, startIndex: number, count: number) => void): void;
|
setCollectionChangedCallback(callback: (change: CollectionChange, startIndex: number, count: number) => void): void;
|
||||||
|
dispose(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IGridDataRow {
|
export interface IGridDataRow {
|
||||||
@@ -24,24 +27,27 @@ class LoadCancellationToken {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class DataWindow<TData> {
|
class DataWindow<TData> {
|
||||||
private _dataSourceLength: number;
|
|
||||||
private _data: TData[];
|
private _data: TData[];
|
||||||
private _length: number = 0;
|
private _length: number = 0;
|
||||||
private _offsetFromDataSource: number = -1;
|
private _offsetFromDataSource: number = -1;
|
||||||
|
|
||||||
private loadFunction: (offset: number, count: number) => Thenable<TData[]>;
|
|
||||||
private lastLoadCancellationToken: LoadCancellationToken;
|
private lastLoadCancellationToken: LoadCancellationToken;
|
||||||
private loadCompleteCallback: (start: number, end: number) => void;
|
|
||||||
private placeholderItemGenerator: (index: number) => TData;
|
|
||||||
|
|
||||||
constructor(dataSourceLength: number,
|
constructor(
|
||||||
loadFunction: (offset: number, count: number) => Thenable<TData[]>,
|
private loadFunction: (offset: number, count: number) => Thenable<TData[]>,
|
||||||
placeholderItemGenerator: (index: number) => TData,
|
private placeholderItemGenerator: (index: number) => TData,
|
||||||
loadCompleteCallback: (start: number, end: number) => void) {
|
private loadCompleteCallback: (start: number, end: number) => void
|
||||||
this._dataSourceLength = dataSourceLength;
|
) {
|
||||||
this.loadFunction = loadFunction;
|
}
|
||||||
this.placeholderItemGenerator = placeholderItemGenerator;
|
|
||||||
this.loadCompleteCallback = loadCompleteCallback;
|
dispose() {
|
||||||
|
this._data = undefined;
|
||||||
|
this.loadFunction = undefined;
|
||||||
|
this.placeholderItemGenerator = undefined;
|
||||||
|
this.loadCompleteCallback = undefined;
|
||||||
|
if (this.lastLoadCancellationToken) {
|
||||||
|
this.lastLoadCancellationToken.isCancelled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getStartIndex(): number {
|
getStartIndex(): number {
|
||||||
@@ -76,10 +82,9 @@ class DataWindow<TData> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let cancellationToken = new LoadCancellationToken();
|
this.lastLoadCancellationToken = new LoadCancellationToken();
|
||||||
this.lastLoadCancellationToken = cancellationToken;
|
|
||||||
this.loadFunction(offset, length).then(data => {
|
this.loadFunction(offset, length).then(data => {
|
||||||
if (!cancellationToken.isCancelled) {
|
if (!this.lastLoadCancellationToken.isCancelled) {
|
||||||
this._data = data;
|
this._data = data;
|
||||||
this.loadCompleteCallback(this._offsetFromDataSource, this._offsetFromDataSource + this._length);
|
this.loadCompleteCallback(this._offsetFromDataSource, this._offsetFromDataSource + this._length);
|
||||||
}
|
}
|
||||||
@@ -97,10 +102,12 @@ export class VirtualizedCollection<TData> implements IObservableCollection<TData
|
|||||||
|
|
||||||
private collectionChangedCallback: (change: CollectionChange, startIndex: number, count: number) => void;
|
private collectionChangedCallback: (change: CollectionChange, startIndex: number, count: number) => void;
|
||||||
|
|
||||||
constructor(windowSize: number,
|
constructor(
|
||||||
|
windowSize: number,
|
||||||
length: number,
|
length: number,
|
||||||
loadFn: (offset: number, count: number) => Thenable<TData[]>,
|
loadFn: (offset: number, count: number) => Thenable<TData[]>,
|
||||||
private _placeHolderGenerator: (index: number) => TData) {
|
private _placeHolderGenerator: (index: number) => TData
|
||||||
|
) {
|
||||||
this._windowSize = windowSize;
|
this._windowSize = windowSize;
|
||||||
this._length = length;
|
this._length = length;
|
||||||
|
|
||||||
@@ -110,9 +117,15 @@ export class VirtualizedCollection<TData> implements IObservableCollection<TData
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this._bufferWindowBefore = new DataWindow(length, loadFn, _placeHolderGenerator, loadCompleteCallback);
|
this._bufferWindowBefore = new DataWindow(loadFn, _placeHolderGenerator, loadCompleteCallback);
|
||||||
this._window = new DataWindow(length, loadFn, _placeHolderGenerator, loadCompleteCallback);
|
this._window = new DataWindow(loadFn, _placeHolderGenerator, loadCompleteCallback);
|
||||||
this._bufferWindowAfter = new DataWindow(length, loadFn, _placeHolderGenerator, loadCompleteCallback);
|
this._bufferWindowAfter = new DataWindow(loadFn, _placeHolderGenerator, loadCompleteCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
dispose() {
|
||||||
|
this._bufferWindowAfter.dispose();
|
||||||
|
this._bufferWindowBefore.dispose();
|
||||||
|
this._window.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
setCollectionChangedCallback(callback: (change: CollectionChange, startIndex: number, count: number) => void): void {
|
setCollectionChangedCallback(callback: (change: CollectionChange, startIndex: number, count: number) => void): void {
|
||||||
@@ -197,7 +210,7 @@ export class VirtualizedCollection<TData> implements IObservableCollection<TData
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AsyncDataProvider<TData extends IGridDataRow> implements Slick.DataProvider<TData> {
|
export class AsyncDataProvider<TData extends IGridDataRow> implements IDisposableDataProvider<TData> {
|
||||||
|
|
||||||
constructor(private dataRows: IObservableCollection<TData>) { }
|
constructor(private dataRows: IObservableCollection<TData>) { }
|
||||||
|
|
||||||
@@ -212,4 +225,8 @@ export class AsyncDataProvider<TData extends IGridDataRow> implements Slick.Data
|
|||||||
public getRange(start: number, end: number): TData[] {
|
public getRange(start: number, end: number): TData[] {
|
||||||
return !this.dataRows ? undefined : this.dataRows.getRange(start, end);
|
return !this.dataRows ? undefined : this.dataRows.getRange(start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dispose() {
|
||||||
|
this.dataRows.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
31
src/sql/base/browser/ui/table/interfaces.ts
Normal file
31
src/sql/base/browser/ui/table/interfaces.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { IListStyles } from 'vs/base/browser/ui/list/listWidget';
|
||||||
|
import { Color } from 'vs/base/common/color';
|
||||||
|
|
||||||
|
export interface IDisposableDataProvider<T> extends Slick.DataProvider<T> {
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ITableMouseEvent {
|
||||||
|
anchor: HTMLElement | { x: number, y: number };
|
||||||
|
cell?: { row: number, cell: number };
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ITableStyles extends IListStyles {
|
||||||
|
tableHeaderBackground?: Color;
|
||||||
|
tableHeaderForeground?: Color;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ITableSorter<T> {
|
||||||
|
sort(args: Slick.OnSortEventArgs<T>);
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ITableConfiguration<T> {
|
||||||
|
dataProvider?: IDisposableDataProvider<T> | Array<T>;
|
||||||
|
columns?: Slick.Column<T>[];
|
||||||
|
sorter?: ITableSorter<T>;
|
||||||
|
}
|
||||||
@@ -5,28 +5,18 @@
|
|||||||
|
|
||||||
import 'vs/css!./media/table';
|
import 'vs/css!./media/table';
|
||||||
import { TableDataView } from './tableDataView';
|
import { TableDataView } from './tableDataView';
|
||||||
|
import { IDisposableDataProvider, ITableSorter, ITableMouseEvent, ITableConfiguration, ITableStyles } from 'sql/base/browser/ui/table/interfaces';
|
||||||
|
|
||||||
import { IThemable } from 'vs/platform/theme/common/styler';
|
import { IThemable } from 'vs/platform/theme/common/styler';
|
||||||
import { IListStyles } from 'vs/base/browser/ui/list/listWidget';
|
|
||||||
import * as DOM from 'vs/base/browser/dom';
|
import * as DOM from 'vs/base/browser/dom';
|
||||||
import { Color } from 'vs/base/common/color';
|
|
||||||
import { mixin } from 'vs/base/common/objects';
|
import { mixin } from 'vs/base/common/objects';
|
||||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||||
import { Orientation } from 'vs/base/browser/ui/splitview/splitview';
|
import { Orientation } from 'vs/base/browser/ui/splitview/splitview';
|
||||||
import { Widget } from 'vs/base/browser/ui/widget';
|
import { Widget } from 'vs/base/browser/ui/widget';
|
||||||
import { isArray, isBoolean } from 'vs/base/common/types';
|
import { isArray, isBoolean } from 'vs/base/common/types';
|
||||||
import { Event, Emitter } from 'vs/base/common/event';
|
import { Event, Emitter } from 'vs/base/common/event';
|
||||||
import { range } from 'vs/base/common/arrays';
|
import { range } from 'vs/base/common/arrays';
|
||||||
|
import { $ } from 'vs/base/browser/builder';
|
||||||
export interface ITableMouseEvent {
|
|
||||||
anchor: HTMLElement | { x: number, y: number };
|
|
||||||
cell?: { row: number, cell: number };
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ITableStyles extends IListStyles {
|
|
||||||
tableHeaderBackground?: Color;
|
|
||||||
tableHeaderForeground?: Color;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDefaultOptions<T>(): Slick.GridOptions<T> {
|
function getDefaultOptions<T>(): Slick.GridOptions<T> {
|
||||||
return <Slick.GridOptions<T>>{
|
return <Slick.GridOptions<T>>{
|
||||||
@@ -35,23 +25,13 @@ function getDefaultOptions<T>(): Slick.GridOptions<T> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ITableSorter<T> {
|
|
||||||
sort(args: Slick.OnSortEventArgs<T>);
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ITableConfiguration<T> {
|
|
||||||
dataProvider?: Slick.DataProvider<T> | Array<T>;
|
|
||||||
columns?: Slick.Column<T>[];
|
|
||||||
sorter?: ITableSorter<T>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Table<T extends Slick.SlickData> extends Widget implements IThemable, IDisposable {
|
export class Table<T extends Slick.SlickData> extends Widget implements IThemable, IDisposable {
|
||||||
private styleElement: HTMLStyleElement;
|
private styleElement: HTMLStyleElement;
|
||||||
private idPrefix: string;
|
private idPrefix: string;
|
||||||
|
|
||||||
private _grid: Slick.Grid<T>;
|
private _grid: Slick.Grid<T>;
|
||||||
private _columns: Slick.Column<T>[];
|
private _columns: Slick.Column<T>[];
|
||||||
private _data: Slick.DataProvider<T>;
|
private _data: IDisposableDataProvider<T>;
|
||||||
private _sorter: ITableSorter<T>;
|
private _sorter: ITableSorter<T>;
|
||||||
|
|
||||||
private _autoscroll: boolean;
|
private _autoscroll: boolean;
|
||||||
@@ -60,8 +40,6 @@ export class Table<T extends Slick.SlickData> extends Widget implements IThemabl
|
|||||||
|
|
||||||
private _classChangeTimeout: number;
|
private _classChangeTimeout: number;
|
||||||
|
|
||||||
private _disposables: IDisposable[] = [];
|
|
||||||
|
|
||||||
private _onContextMenu = new Emitter<ITableMouseEvent>();
|
private _onContextMenu = new Emitter<ITableMouseEvent>();
|
||||||
public readonly onContextMenu: Event<ITableMouseEvent> = this._onContextMenu.event;
|
public readonly onContextMenu: Event<ITableMouseEvent> = this._onContextMenu.event;
|
||||||
|
|
||||||
@@ -76,6 +54,8 @@ export class Table<T extends Slick.SlickData> extends Widget implements IThemabl
|
|||||||
this._data = configuration.dataProvider;
|
this._data = configuration.dataProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._register(this._data);
|
||||||
|
|
||||||
if (configuration && configuration.columns) {
|
if (configuration && configuration.columns) {
|
||||||
this._columns = configuration.columns;
|
this._columns = configuration.columns;
|
||||||
} else {
|
} else {
|
||||||
@@ -117,6 +97,12 @@ export class Table<T extends Slick.SlickData> extends Widget implements IThemabl
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._register({
|
||||||
|
dispose: () => {
|
||||||
|
this._grid.destroy();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.mapMouseEvent(this._grid.onContextMenu, this._onContextMenu);
|
this.mapMouseEvent(this._grid.onContextMenu, this._onContextMenu);
|
||||||
this.mapMouseEvent(this._grid.onClick, this._onClick);
|
this.mapMouseEvent(this._grid.onClick, this._onClick);
|
||||||
}
|
}
|
||||||
@@ -131,7 +117,8 @@ export class Table<T extends Slick.SlickData> extends Widget implements IThemabl
|
|||||||
}
|
}
|
||||||
|
|
||||||
public dispose() {
|
public dispose() {
|
||||||
dispose(this._disposables);
|
$(this._container).dispose();
|
||||||
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public invalidateRows(rows: number[], keepEditor: boolean) {
|
public invalidateRows(rows: number[], keepEditor: boolean) {
|
||||||
@@ -166,7 +153,7 @@ export class Table<T extends Slick.SlickData> extends Widget implements IThemabl
|
|||||||
this._grid.setData(this._data, true);
|
this._grid.setData(this._data, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
getData(): Slick.DataProvider<T> {
|
getData(): IDisposableDataProvider<T> {
|
||||||
return this._data;
|
return this._data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import { Event, Emitter } from 'vs/base/common/event';
|
|||||||
import { TPromise } from 'vs/base/common/winjs.base';
|
import { TPromise } from 'vs/base/common/winjs.base';
|
||||||
import * as types from 'vs/base/common/types';
|
import * as types from 'vs/base/common/types';
|
||||||
|
|
||||||
|
import { IDisposableDataProvider } from 'sql/base/browser/ui/table/interfaces';
|
||||||
|
|
||||||
export interface IFindPosition {
|
export interface IFindPosition {
|
||||||
col: number;
|
col: number;
|
||||||
row: number;
|
row: number;
|
||||||
@@ -20,7 +22,7 @@ function defaultSort<T>(args: Slick.OnSortEventArgs<T>, data: Array<T>): Array<T
|
|||||||
return data.sort((a, b) => (a[field] === b[field] ? 0 : (a[field] > b[field] ? 1 : -1)) * sign);
|
return data.sort((a, b) => (a[field] === b[field] ? 0 : (a[field] > b[field] ? 1 : -1)) * sign);
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TableDataView<T extends Slick.SlickData> implements Slick.DataProvider<T> {
|
export class TableDataView<T extends Slick.SlickData> implements IDisposableDataProvider<T> {
|
||||||
private _data: Array<T>;
|
private _data: Array<T>;
|
||||||
private _findArray: Array<IFindPosition>;
|
private _findArray: Array<IFindPosition>;
|
||||||
private _findObs: Observable<IFindPosition>;
|
private _findObs: Observable<IFindPosition>;
|
||||||
@@ -154,4 +156,10 @@ export class TableDataView<T extends Slick.SlickData> implements Slick.DataProvi
|
|||||||
get findCount(): number {
|
get findCount(): number {
|
||||||
return types.isUndefinedOrNull(this._findArray) ? 0 : this._findArray.length;
|
return types.isUndefinedOrNull(this._findArray) ? 0 : this._findArray.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dispose() {
|
||||||
|
this._data = undefined;
|
||||||
|
this._findArray = undefined;
|
||||||
|
this._findObs = undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export const tableHeaderForeground = registerColor('table.headerForeground', { d
|
|||||||
export const disabledInputBackground = registerColor('input.disabled.background', { dark: '#444444', light: '#dcdcdc', hc: Color.black }, nls.localize('disabledInputBoxBackground', "Disabled Input box background."));
|
export const disabledInputBackground = registerColor('input.disabled.background', { dark: '#444444', light: '#dcdcdc', hc: Color.black }, nls.localize('disabledInputBoxBackground', "Disabled Input box background."));
|
||||||
export const disabledInputForeground = registerColor('input.disabled.foreground', { dark: '#888888', light: '#888888', hc: foreground }, nls.localize('disabledInputBoxForeground', "Disabled Input box foreground."));
|
export const disabledInputForeground = registerColor('input.disabled.foreground', { dark: '#888888', light: '#888888', hc: foreground }, nls.localize('disabledInputBoxForeground', "Disabled Input box foreground."));
|
||||||
export const buttonFocusOutline = registerColor('button.focusOutline', { dark: '#eaeaea', light: '#666666', hc: null }, nls.localize('buttonFocusOutline', "Button outline color when focused."));
|
export const buttonFocusOutline = registerColor('button.focusOutline', { dark: '#eaeaea', light: '#666666', hc: null }, nls.localize('buttonFocusOutline', "Button outline color when focused."));
|
||||||
|
export const disabledCheckboxForeground = registerColor('checkbox.disabled.foreground', { dark: '#888888', light: '#888888', hc: Color.black }, nls.localize('disabledCheckboxforeground', "Disabled checkbox foreground."));
|
||||||
|
|
||||||
export const listFocusAndSelectionBackground = registerColor('list.focusAndSelectionBackground', { dark: '#2c3295', light: '#2c3295', hc: null }, nls.localize('listFocusAndSelectionBackground', "List/Table background color for the selected and focus item when the list/table is active"));
|
export const listFocusAndSelectionBackground = registerColor('list.focusAndSelectionBackground', { dark: '#2c3295', light: '#2c3295', hc: null }, nls.localize('listFocusAndSelectionBackground', "List/Table background color for the selected and focus item when the list/table is active"));
|
||||||
|
|
||||||
|
|||||||
@@ -255,3 +255,10 @@ export function attachButtonStyler(widget: IThemable, themeService: IThemeServic
|
|||||||
buttonFocusOutline: (style && style.buttonFocusOutline) || sqlcolors.buttonFocusOutline
|
buttonFocusOutline: (style && style.buttonFocusOutline) || sqlcolors.buttonFocusOutline
|
||||||
}, widget);
|
}, widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function attachCheckboxStyler(widget: IThemable, themeService: IThemeService, style?: { disabledCheckboxForeground?: cr.ColorIdentifier })
|
||||||
|
: IDisposable {
|
||||||
|
return attachStyler(themeService, {
|
||||||
|
disabledCheckboxForeground: (style && style.disabledCheckboxForeground) || sqlcolors.disabledCheckboxForeground
|
||||||
|
}, widget);
|
||||||
|
}
|
||||||
|
|||||||
17
src/sql/parts/commandLine/common/commandLine.ts
Normal file
17
src/sql/parts/commandLine/common/commandLine.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* 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 { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
export interface ICommandLineProcessing {
|
||||||
|
_serviceBrand: any;
|
||||||
|
/**
|
||||||
|
* Interprets the various Azure Data Studio-specific command line switches and
|
||||||
|
* performs the requisite tasks such as connecting to a server
|
||||||
|
*/
|
||||||
|
processCommandLine() : void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ICommandLineProcessing = createDecorator<ICommandLineProcessing>('commandLineService');
|
||||||
75
src/sql/parts/commandLine/common/commandLineService.ts
Normal file
75
src/sql/parts/commandLine/common/commandLineService.ts
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* 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 { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
|
||||||
|
import { ICommandLineProcessing } from 'sql/parts/commandLine/common/commandLine';
|
||||||
|
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
|
||||||
|
import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
|
||||||
|
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||||
|
import * as Constants from 'sql/parts/connection/common/constants';
|
||||||
|
import { IQueryEditorService } from 'sql/parts/query/common/queryEditorService';
|
||||||
|
import * as platform from 'vs/platform/registry/common/platform';
|
||||||
|
import { ConnectionProviderProperties, IConnectionProviderRegistry, Extensions as ConnectionProviderExtensions } from 'sql/workbench/parts/connection/common/connectionProviderExtension';
|
||||||
|
import * as TaskUtilities from 'sql/workbench/common/taskUtilities';
|
||||||
|
import { IObjectExplorerService } from 'sql/parts/objectExplorer/common/objectExplorerService';
|
||||||
|
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||||
|
|
||||||
|
export class CommandLineService implements ICommandLineProcessing {
|
||||||
|
private _connectionProfile: ConnectionProfile;
|
||||||
|
private _showConnectionDialog: boolean;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
|
||||||
|
@ICapabilitiesService private _capabilitiesService: ICapabilitiesService,
|
||||||
|
@IEnvironmentService private _environmentService: IEnvironmentService,
|
||||||
|
@IQueryEditorService private _queryEditorService: IQueryEditorService,
|
||||||
|
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
|
||||||
|
@IEditorService private _editorService: IEditorService,
|
||||||
|
) {
|
||||||
|
let profile = null;
|
||||||
|
if (this._environmentService && this._environmentService.args.server) {
|
||||||
|
profile = new ConnectionProfile(_capabilitiesService, null);
|
||||||
|
// We want connection store to use any matching password it finds
|
||||||
|
profile.savePassword = true;
|
||||||
|
profile.providerName = Constants.mssqlProviderName;
|
||||||
|
profile.serverName = _environmentService.args.server;
|
||||||
|
profile.databaseName = _environmentService.args.database ? _environmentService.args.database : '';
|
||||||
|
profile.userName = _environmentService.args.user ? _environmentService.args.user : '';
|
||||||
|
profile.authenticationType = _environmentService.args.integrated ? 'Integrated' : 'SqlLogin';
|
||||||
|
profile.connectionName = '';
|
||||||
|
profile.setOptionValue('applicationName', Constants.applicationName);
|
||||||
|
profile.setOptionValue('databaseDisplayName', profile.databaseName);
|
||||||
|
profile.setOptionValue('groupId', profile.groupId);
|
||||||
|
}
|
||||||
|
this._connectionProfile = profile;
|
||||||
|
const registry = platform.Registry.as<IConnectionProviderRegistry>(ConnectionProviderExtensions.ConnectionProviderContributions);
|
||||||
|
let sqlProvider = registry.getProperties(Constants.mssqlProviderName);
|
||||||
|
// We can't connect to object explorer until the MSSQL connection provider is registered
|
||||||
|
if (sqlProvider) {
|
||||||
|
this.processCommandLine();
|
||||||
|
} else {
|
||||||
|
registry.onNewProvider(e => {
|
||||||
|
if (e.id === Constants.mssqlProviderName) {
|
||||||
|
this.processCommandLine();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public _serviceBrand: any;
|
||||||
|
public processCommandLine(): void {
|
||||||
|
if (!this._connectionProfile && !this._connectionManagementService.hasRegisteredServers()) {
|
||||||
|
// prompt the user for a new connection on startup if no profiles are registered
|
||||||
|
this._connectionManagementService.showConnectionDialog();
|
||||||
|
} else if (this._connectionProfile) {
|
||||||
|
this._connectionManagementService.connectIfNotConnected(this._connectionProfile, 'connection')
|
||||||
|
.then(result => TaskUtilities.newQuery(this._connectionProfile,
|
||||||
|
this._connectionManagementService,
|
||||||
|
this._queryEditorService,
|
||||||
|
this._objectExplorerService,
|
||||||
|
this._editorService))
|
||||||
|
.catch(() => { });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,7 +26,7 @@ import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService
|
|||||||
export class ClearRecentConnectionsAction extends Action {
|
export class ClearRecentConnectionsAction extends Action {
|
||||||
|
|
||||||
public static ID = 'clearRecentConnectionsAction';
|
public static ID = 'clearRecentConnectionsAction';
|
||||||
public static LABEL = nls.localize('ClearRecentlyUsedLabel', 'Clear Recent Connections List');
|
public static LABEL = nls.localize('ClearRecentlyUsedLabel', 'Clear List');
|
||||||
public static ICON = 'search-action clear-search-results';
|
public static ICON = 'search-action clear-search-results';
|
||||||
|
|
||||||
private _onRecentConnectionsRemoved = new Emitter<void>();
|
private _onRecentConnectionsRemoved = new Emitter<void>();
|
||||||
@@ -83,7 +83,7 @@ export class ClearRecentConnectionsAction extends Action {
|
|||||||
{ key: nls.localize('connectionAction.no', 'No'), value: false }
|
{ key: nls.localize('connectionAction.no', 'No'), value: false }
|
||||||
];
|
];
|
||||||
|
|
||||||
self._quickOpenService.pick(choices.map(x => x.key), { placeHolder: nls.localize('ClearRecentlyUsedLabel', 'Clear Recent Connections List'), ignoreFocusLost: true }).then((choice) => {
|
self._quickOpenService.pick(choices.map(x => x.key), { placeHolder: nls.localize('ClearRecentlyUsedLabel', 'Clear List'), ignoreFocusLost: true }).then((choice) => {
|
||||||
let confirm = choices.find(x => x.key === choice);
|
let confirm = choices.find(x => x.key === choice);
|
||||||
resolve(confirm && confirm.value);
|
resolve(confirm && confirm.value);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -77,7 +77,6 @@ export class ConnectionManagementService extends Disposable implements IConnecti
|
|||||||
private _onConnectRequestSent = new Emitter<void>();
|
private _onConnectRequestSent = new Emitter<void>();
|
||||||
private _onConnectionChanged = new Emitter<IConnectionParams>();
|
private _onConnectionChanged = new Emitter<IConnectionParams>();
|
||||||
private _onLanguageFlavorChanged = new Emitter<sqlops.DidChangeLanguageFlavorParams>();
|
private _onLanguageFlavorChanged = new Emitter<sqlops.DidChangeLanguageFlavorParams>();
|
||||||
|
|
||||||
private _connectionGlobalStatus = new ConnectionGlobalStatus(this._statusBarService);
|
private _connectionGlobalStatus = new ConnectionGlobalStatus(this._statusBarService);
|
||||||
|
|
||||||
private _configurationEditService: ConfigurationEditingService;
|
private _configurationEditService: ConfigurationEditingService;
|
||||||
@@ -124,16 +123,6 @@ export class ConnectionManagementService extends Disposable implements IConnecti
|
|||||||
100 /* High Priority */
|
100 /* High Priority */
|
||||||
));
|
));
|
||||||
|
|
||||||
if (_capabilitiesService && Object.keys(_capabilitiesService.providers).length > 0 && !this.hasRegisteredServers()) {
|
|
||||||
// prompt the user for a new connection on startup if no profiles are registered
|
|
||||||
this.showConnectionDialog();
|
|
||||||
} else if (_capabilitiesService && !this.hasRegisteredServers()) {
|
|
||||||
_capabilitiesService.onCapabilitiesRegistered(e => {
|
|
||||||
// prompt the user for a new connection on startup if no profiles are registered
|
|
||||||
this.showConnectionDialog();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const registry = platform.Registry.as<IConnectionProviderRegistry>(ConnectionProviderExtensions.ConnectionProviderContributions);
|
const registry = platform.Registry.as<IConnectionProviderRegistry>(ConnectionProviderExtensions.ConnectionProviderContributions);
|
||||||
|
|
||||||
let providerRegistration = (p: { id: string, properties: ConnectionProviderProperties }) => {
|
let providerRegistration = (p: { id: string, properties: ConnectionProviderProperties }) => {
|
||||||
@@ -282,29 +271,30 @@ export class ConnectionManagementService extends Disposable implements IConnecti
|
|||||||
* @param options to use after the connection is complete
|
* @param options to use after the connection is complete
|
||||||
*/
|
*/
|
||||||
private tryConnect(connection: IConnectionProfile, owner: IConnectableInput, options?: IConnectionCompletionOptions): Promise<IConnectionResult> {
|
private tryConnect(connection: IConnectionProfile, owner: IConnectableInput, options?: IConnectionCompletionOptions): Promise<IConnectionResult> {
|
||||||
|
let self = this;
|
||||||
return new Promise<IConnectionResult>((resolve, reject) => {
|
return new Promise<IConnectionResult>((resolve, reject) => {
|
||||||
// Load the password if it's not already loaded
|
// Load the password if it's not already loaded
|
||||||
this._connectionStore.addSavedPassword(connection).then(result => {
|
self._connectionStore.addSavedPassword(connection).then(result => {
|
||||||
let newConnection = result.profile;
|
let newConnection = result.profile;
|
||||||
let foundPassword = result.savedCred;
|
let foundPassword = result.savedCred;
|
||||||
|
|
||||||
// If there is no password, try to load it from an existing connection
|
// If there is no password, try to load it from an existing connection
|
||||||
if (!foundPassword && this._connectionStore.isPasswordRequired(newConnection)) {
|
if (!foundPassword && self._connectionStore.isPasswordRequired(newConnection)) {
|
||||||
let existingConnection = this._connectionStatusManager.findConnectionProfile(connection);
|
let existingConnection = self._connectionStatusManager.findConnectionProfile(connection);
|
||||||
if (existingConnection && existingConnection.connectionProfile) {
|
if (existingConnection && existingConnection.connectionProfile) {
|
||||||
newConnection.password = existingConnection.connectionProfile.password;
|
newConnection.password = existingConnection.connectionProfile.password;
|
||||||
foundPassword = true;
|
foundPassword = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If the password is required and still not loaded show the dialog
|
// If the password is required and still not loaded show the dialog
|
||||||
if (!foundPassword && this._connectionStore.isPasswordRequired(newConnection) && !newConnection.password) {
|
if (!foundPassword && self._connectionStore.isPasswordRequired(newConnection) && !newConnection.password) {
|
||||||
resolve(this.showConnectionDialogOnError(connection, owner, { connected: false, errorMessage: undefined, callStack: undefined, errorCode: undefined }, options));
|
resolve(self.showConnectionDialogOnError(connection, owner, { connected: false, errorMessage: undefined, callStack: undefined, errorCode: undefined }, options));
|
||||||
} else {
|
} else {
|
||||||
// Try to connect
|
// Try to connect
|
||||||
this.connectWithOptions(newConnection, owner.uri, options, owner).then(connectionResult => {
|
self.connectWithOptions(newConnection, owner.uri, options, owner).then(connectionResult => {
|
||||||
if (!connectionResult.connected && !connectionResult.errorHandled) {
|
if (!connectionResult.connected && !connectionResult.errorHandled) {
|
||||||
// If connection fails show the dialog
|
// If connection fails show the dialog
|
||||||
resolve(this.showConnectionDialogOnError(connection, owner, connectionResult, options));
|
resolve(self.showConnectionDialogOnError(connection, owner, connectionResult, options));
|
||||||
} else {
|
} else {
|
||||||
//Resolve with the connection result
|
//Resolve with the connection result
|
||||||
resolve(connectionResult);
|
resolve(connectionResult);
|
||||||
@@ -390,7 +380,14 @@ export class ConnectionManagementService extends Disposable implements IConnecti
|
|||||||
if (this._connectionStatusManager.isConnected(ownerUri)) {
|
if (this._connectionStatusManager.isConnected(ownerUri)) {
|
||||||
resolve(this._connectionStatusManager.getOriginalOwnerUri(ownerUri));
|
resolve(this._connectionStatusManager.getOriginalOwnerUri(ownerUri));
|
||||||
} else {
|
} else {
|
||||||
this.connect(connection, ownerUri).then(connectionResult => {
|
const options: IConnectionCompletionOptions = {
|
||||||
|
saveTheConnection: false,
|
||||||
|
showConnectionDialogOnError: true,
|
||||||
|
showDashboard: purpose === 'dashboard',
|
||||||
|
params: undefined,
|
||||||
|
showFirewallRuleOnError: true,
|
||||||
|
};
|
||||||
|
this.connect(connection, ownerUri, options).then(connectionResult => {
|
||||||
if (connectionResult && connectionResult.connected) {
|
if (connectionResult && connectionResult.connected) {
|
||||||
resolve(this._connectionStatusManager.getOriginalOwnerUri(ownerUri));
|
resolve(this._connectionStatusManager.getOriginalOwnerUri(ownerUri));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -23,9 +23,7 @@ export class ConnectionStatusbarItem implements IStatusbarItem {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
|
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
|
||||||
@IEditorGroupsService private _editorGroupService: IEditorGroupsService,
|
|
||||||
@IEditorService private _editorService: EditorServiceImpl,
|
@IEditorService private _editorService: EditorServiceImpl,
|
||||||
@ICapabilitiesService private _capabilitiesService: ICapabilitiesService,
|
|
||||||
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
|
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ export function parseTimeString(value: string): number | boolean {
|
|||||||
* @param value The number of milliseconds to convert to a timespan string
|
* @param value The number of milliseconds to convert to a timespan string
|
||||||
* @returns A properly formatted timespan string.
|
* @returns A properly formatted timespan string.
|
||||||
*/
|
*/
|
||||||
export function parseNumAsTimeString(value: number): string {
|
export function parseNumAsTimeString(value: number, includeFraction: boolean = true): string {
|
||||||
let tempVal = value;
|
let tempVal = value;
|
||||||
let h = Math.floor(tempVal / msInH);
|
let h = Math.floor(tempVal / msInH);
|
||||||
tempVal %= msInH;
|
tempVal %= msInH;
|
||||||
@@ -85,7 +85,7 @@ export function parseNumAsTimeString(value: number): string {
|
|||||||
|
|
||||||
let rs = hs + ':' + ms + ':' + ss;
|
let rs = hs + ':' + ms + ':' + ss;
|
||||||
|
|
||||||
return tempVal > 0 ? rs + '.' + mss : rs;
|
return tempVal > 0 && includeFraction ? rs + '.' + mss : rs;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateUri(connection: IConnectionProfile, purpose?: 'dashboard' | 'insights' | 'connection'): string {
|
export function generateUri(connection: IConnectionProfile, purpose?: 'dashboard' | 'insights' | 'connection'): string {
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export class AdvancedPropertiesController {
|
|||||||
public get advancedDialog() {
|
public get advancedDialog() {
|
||||||
if (!this._advancedDialog) {
|
if (!this._advancedDialog) {
|
||||||
this._advancedDialog = this._instantiationService.createInstance(
|
this._advancedDialog = this._instantiationService.createInstance(
|
||||||
OptionsDialog, localize('connectionAdvancedProperties', 'Advanced properties'), TelemetryKeys.ConnectionAdvancedProperties, { hasBackButton: true });
|
OptionsDialog, localize('connectionAdvancedProperties', 'Advanced Properties'), TelemetryKeys.ConnectionAdvancedProperties, { hasBackButton: true });
|
||||||
this._advancedDialog.cancelLabel = localize('advancedProperties.discard', 'Discard');
|
this._advancedDialog.cancelLabel = localize('advancedProperties.discard', 'Discard');
|
||||||
this._advancedDialog.onCloseEvent(() => this._onCloseAdvancedProperties());
|
this._advancedDialog.onCloseEvent(() => this._onCloseAdvancedProperties());
|
||||||
this._advancedDialog.onOk(() => this.handleOnOk());
|
this._advancedDialog.onOk(() => this.handleOnOk());
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import * as styler from 'vs/platform/theme/common/styler';
|
|||||||
import * as DOM from 'vs/base/browser/dom';
|
import * as DOM from 'vs/base/browser/dom';
|
||||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||||
|
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
|
||||||
|
|
||||||
export interface OnShowUIResponse {
|
export interface OnShowUIResponse {
|
||||||
selectedProviderType: string;
|
selectedProviderType: string;
|
||||||
@@ -49,7 +50,7 @@ export class ConnectionDialogWidget extends Modal {
|
|||||||
private _noRecentConnectionBuilder: Builder;
|
private _noRecentConnectionBuilder: Builder;
|
||||||
private _savedConnectionBuilder: Builder;
|
private _savedConnectionBuilder: Builder;
|
||||||
private _noSavedConnectionBuilder: Builder;
|
private _noSavedConnectionBuilder: Builder;
|
||||||
private _dividerBuilder: Builder;
|
private _connectionDetailTitle: Builder;
|
||||||
private _connectButton: Button;
|
private _connectButton: Button;
|
||||||
private _closeButton: Button;
|
private _closeButton: Button;
|
||||||
private _providerTypeSelectBox: SelectBox;
|
private _providerTypeSelectBox: SelectBox;
|
||||||
@@ -143,7 +144,7 @@ export class ConnectionDialogWidget extends Modal {
|
|||||||
this._panel = new TabbedPanel(connectionContainer.getHTMLElement());
|
this._panel = new TabbedPanel(connectionContainer.getHTMLElement());
|
||||||
this._recentConnectionTabId = this._panel.pushTab({
|
this._recentConnectionTabId = this._panel.pushTab({
|
||||||
identifier: 'recent_connection',
|
identifier: 'recent_connection',
|
||||||
title: localize('recentConnectionTitle', 'Recent connections'),
|
title: localize('recentConnectionTitle', 'Recent Connections'),
|
||||||
view: {
|
view: {
|
||||||
render: c => {
|
render: c => {
|
||||||
recentConnectionTab.appendTo(c);
|
recentConnectionTab.appendTo(c);
|
||||||
@@ -154,7 +155,7 @@ export class ConnectionDialogWidget extends Modal {
|
|||||||
|
|
||||||
let savedConnectionTabId = this._panel.pushTab({
|
let savedConnectionTabId = this._panel.pushTab({
|
||||||
identifier: 'saved_connection',
|
identifier: 'saved_connection',
|
||||||
title: localize('savedConnectionTitle', 'Saved connections'),
|
title: localize('savedConnectionTitle', 'Saved Connections'),
|
||||||
view: {
|
view: {
|
||||||
layout: () => { },
|
layout: () => { },
|
||||||
render: c => {
|
render: c => {
|
||||||
@@ -179,8 +180,9 @@ export class ConnectionDialogWidget extends Modal {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this._bodyBuilder.div({ class: 'Connection-divider' }, (dividerContainer) => {
|
this._bodyBuilder.div({ class: 'connection-details-title' }, (dividerContainer) => {
|
||||||
this._dividerBuilder = dividerContainer;
|
this._connectionDetailTitle = dividerContainer;
|
||||||
|
this._connectionDetailTitle.text(localize('connectionDetailsTitle', 'Connection Details'));
|
||||||
});
|
});
|
||||||
|
|
||||||
this._bodyBuilder.div({ class: 'connection-type' }, (modelTableContent) => {
|
this._bodyBuilder.div({ class: 'connection-type' }, (modelTableContent) => {
|
||||||
@@ -217,10 +219,12 @@ export class ConnectionDialogWidget extends Modal {
|
|||||||
private updateTheme(theme: IColorTheme): void {
|
private updateTheme(theme: IColorTheme): void {
|
||||||
let borderColor = theme.getColor(contrastBorder);
|
let borderColor = theme.getColor(contrastBorder);
|
||||||
let border = borderColor ? borderColor.toString() : null;
|
let border = borderColor ? borderColor.toString() : null;
|
||||||
if (this._dividerBuilder) {
|
let backgroundColor = theme.getColor(SIDE_BAR_BACKGROUND);
|
||||||
this._dividerBuilder.style('border-top-width', border ? '1px' : null);
|
if (this._connectionDetailTitle) {
|
||||||
this._dividerBuilder.style('border-top-style', border ? 'solid' : null);
|
this._connectionDetailTitle.style('border-width', border ? '1px 0px' : null);
|
||||||
this._dividerBuilder.style('border-top-color', border);
|
this._connectionDetailTitle.style('border-style', border ? 'solid none' : null);
|
||||||
|
this._connectionDetailTitle.style('border-color', border);
|
||||||
|
this._connectionDetailTitle.style('background-color', backgroundColor ? backgroundColor.toString() : null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,17 +281,13 @@ export class ConnectionDialogWidget extends Modal {
|
|||||||
|
|
||||||
private createRecentConnectionList(): void {
|
private createRecentConnectionList(): void {
|
||||||
this._recentConnectionBuilder.div({ class: 'connection-recent-content' }, (recentConnectionContainer) => {
|
this._recentConnectionBuilder.div({ class: 'connection-recent-content' }, (recentConnectionContainer) => {
|
||||||
let recentHistoryLabel = localize('recentHistory', 'Recent history');
|
|
||||||
recentConnectionContainer.div({ class: 'recent-titles-container' }, (container) => {
|
recentConnectionContainer.div({ class: 'recent-titles-container' }, (container) => {
|
||||||
container.div({ class: 'connection-history-label' }, (recentTitle) => {
|
|
||||||
recentTitle.text(recentHistoryLabel);
|
|
||||||
});
|
|
||||||
container.div({ class: 'connection-history-actions' }, (actionsContainer) => {
|
container.div({ class: 'connection-history-actions' }, (actionsContainer) => {
|
||||||
this._actionbar = this._register(new ActionBar(actionsContainer.getHTMLElement(), { animated: false }));
|
this._actionbar = this._register(new ActionBar(actionsContainer.getHTMLElement(), { animated: false }));
|
||||||
let clearAction = this._instantiationService.createInstance(ClearRecentConnectionsAction, ClearRecentConnectionsAction.ID, ClearRecentConnectionsAction.LABEL);
|
let clearAction = this._instantiationService.createInstance(ClearRecentConnectionsAction, ClearRecentConnectionsAction.ID, ClearRecentConnectionsAction.LABEL);
|
||||||
clearAction.useConfirmationMessage = true;
|
clearAction.useConfirmationMessage = true;
|
||||||
clearAction.onRecentConnectionsRemoved(() => this.open(false));
|
clearAction.onRecentConnectionsRemoved(() => this.open(false));
|
||||||
this._actionbar.push(clearAction, { icon: true, label: false });
|
this._actionbar.push(clearAction, { icon: true, label: true });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
recentConnectionContainer.div({ class: 'server-explorer-viewlet' }, (divContainer: Builder) => {
|
recentConnectionContainer.div({ class: 'server-explorer-viewlet' }, (divContainer: Builder) => {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
|||||||
import { ConnectionOptionSpecialType } from 'sql/workbench/api/common/sqlExtHostTypes';
|
import { ConnectionOptionSpecialType } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||||
import * as Constants from 'sql/parts/connection/common/constants';
|
import * as Constants from 'sql/parts/connection/common/constants';
|
||||||
import { ConnectionProfileGroup, IConnectionProfileGroup } from 'sql/parts/connection/common/connectionProfileGroup';
|
import { ConnectionProfileGroup, IConnectionProfileGroup } from 'sql/parts/connection/common/connectionProfileGroup';
|
||||||
import { attachInputBoxStyler, attachButtonStyler, attachEditableDropdownStyler } from 'sql/common/theme/styler';
|
import { attachButtonStyler, attachCheckboxStyler, attachEditableDropdownStyler, attachInputBoxStyler } from 'sql/common/theme/styler';
|
||||||
import { Dropdown } from 'sql/base/browser/ui/editableDropdown/dropdown';
|
import { Dropdown } from 'sql/base/browser/ui/editableDropdown/dropdown';
|
||||||
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
|
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
|
||||||
import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
|
import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
|
||||||
@@ -83,7 +83,7 @@ export class ConnectionWidget {
|
|||||||
};
|
};
|
||||||
public NoneServerGroup: IConnectionProfileGroup = {
|
public NoneServerGroup: IConnectionProfileGroup = {
|
||||||
id: '',
|
id: '',
|
||||||
name: localize('noneServerGroup', '<None>'),
|
name: localize('noneServerGroup', '<Do not save>'),
|
||||||
parentId: undefined,
|
parentId: undefined,
|
||||||
color: undefined,
|
color: undefined,
|
||||||
description: undefined,
|
description: undefined,
|
||||||
@@ -274,6 +274,7 @@ export class ConnectionWidget {
|
|||||||
this._toDispose.push(attachInputBoxStyler(this._passwordInputBox, this._themeService));
|
this._toDispose.push(attachInputBoxStyler(this._passwordInputBox, this._themeService));
|
||||||
this._toDispose.push(styler.attachSelectBoxStyler(this._serverGroupSelectBox, this._themeService));
|
this._toDispose.push(styler.attachSelectBoxStyler(this._serverGroupSelectBox, this._themeService));
|
||||||
this._toDispose.push(attachButtonStyler(this._advancedButton, this._themeService));
|
this._toDispose.push(attachButtonStyler(this._advancedButton, this._themeService));
|
||||||
|
this._toDispose.push(attachCheckboxStyler(this._rememberPasswordCheckBox, this._themeService));
|
||||||
|
|
||||||
if (this._authTypeSelectBox) {
|
if (this._authTypeSelectBox) {
|
||||||
// Theme styler
|
// Theme styler
|
||||||
|
|||||||
@@ -9,25 +9,35 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.connection-input {
|
.connection-input {
|
||||||
padding-right:8px;
|
|
||||||
width: 200px;
|
width: 200px;
|
||||||
padding-bottom: 5px;
|
padding-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.connection-dialog {
|
.connection-dialog {
|
||||||
height: calc(100% - 20px);
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.connection-dialog .tabbedPanel {
|
.connection-dialog .tabbedPanel {
|
||||||
border-top-color: transparent;
|
border-top-color: transparent;
|
||||||
height: calc(100% - 350px);
|
flex: 1 1;
|
||||||
display: block;
|
|
||||||
min-height: 120px;
|
min-height: 120px;
|
||||||
|
overflow: hidden;
|
||||||
|
margin: 0px 11px;
|
||||||
|
}
|
||||||
|
.connection-dialog .tabBody {
|
||||||
|
overflow: hidden;
|
||||||
|
flex: 1 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.connection-recent, .connection-saved {
|
.connection-recent, .connection-saved {
|
||||||
margin: 15px;
|
margin: 5px;
|
||||||
height: calc(100% - 60px);
|
flex: 1 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,6 +55,8 @@
|
|||||||
.recent-titles-container {
|
.recent-titles-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
margin: 5px;
|
||||||
|
flex: 0 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.connection-provider-info {
|
.connection-provider-info {
|
||||||
@@ -53,7 +65,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.connection-recent-content {
|
.connection-recent-content {
|
||||||
height: calc(100% - 20px);
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.connection-recent-content .server-explorer-viewlet {
|
||||||
|
flex: 1 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.connection-table-content {
|
.connection-table-content {
|
||||||
@@ -66,8 +84,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.connection-type {
|
.connection-type {
|
||||||
margin: 15px;
|
flex: 0 0 auto;
|
||||||
overflow-y: hidden;
|
overflow: hidden;
|
||||||
|
margin: 0px 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.connection-dialog .connection-history-actions .action-label.icon {
|
.connection-dialog .connection-history-actions .action-label.icon {
|
||||||
@@ -76,8 +95,9 @@
|
|||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
min-width: 20px;
|
min-width: 20px;
|
||||||
background-size: 16px;
|
background-size: 16px;
|
||||||
background-position: center center;
|
background-position: 2px center;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
|
padding-left: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-action.clear-search-results {
|
.search-action.clear-search-results {
|
||||||
@@ -88,3 +108,10 @@
|
|||||||
.hc-black .search-action.clear-search-results {
|
.hc-black .search-action.clear-search-results {
|
||||||
background: url('clear-search-results-dark.svg');
|
background: url('clear-search-results-dark.svg');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.connection-details-title {
|
||||||
|
font-size: 14px;
|
||||||
|
margin: 5px 0px;
|
||||||
|
padding: 5px 15px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
@@ -5,6 +5,5 @@
|
|||||||
|
|
||||||
.advanced-button {
|
.advanced-button {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
padding-right:8px;
|
|
||||||
padding-bottom: 5px;
|
padding-bottom: 5px;
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,7 @@ import { ModalFooterStyle } from 'sql/base/browser/ui/modal/modal';
|
|||||||
import { CategoryView } from 'sql/base/browser/ui/modal/optionsDialog';
|
import { CategoryView } from 'sql/base/browser/ui/modal/optionsDialog';
|
||||||
import { SelectBox } from 'sql/base/browser/ui/selectBox/selectBox';
|
import { SelectBox } from 'sql/base/browser/ui/selectBox/selectBox';
|
||||||
import { SplitView } from 'sql/base/browser/ui/splitview/splitview';
|
import { SplitView } from 'sql/base/browser/ui/splitview/splitview';
|
||||||
import { attachButtonStyler, attachListBoxStyler, attachInputBoxStyler, attachSelectBoxStyler } from 'sql/common/theme/styler';
|
import { attachButtonStyler, attachListBoxStyler, attachInputBoxStyler, attachSelectBoxStyler, attachCheckboxStyler } from 'sql/common/theme/styler';
|
||||||
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
||||||
import * as BackupConstants from 'sql/parts/disasterRecovery/backup/constants';
|
import * as BackupConstants from 'sql/parts/disasterRecovery/backup/constants';
|
||||||
import { IBackupService, IBackupUiService, TaskExecutionMode } from 'sql/parts/disasterRecovery/backup/common/backupService';
|
import { IBackupService, IBackupUiService, TaskExecutionMode } from 'sql/parts/disasterRecovery/backup/common/backupService';
|
||||||
@@ -523,6 +523,11 @@ export class BackupComponent {
|
|||||||
this._toDispose.push(attachInputBoxStyler(this.mediaNameBox, this.themeService));
|
this._toDispose.push(attachInputBoxStyler(this.mediaNameBox, this.themeService));
|
||||||
this._toDispose.push(attachInputBoxStyler(this.mediaDescriptionBox, this.themeService));
|
this._toDispose.push(attachInputBoxStyler(this.mediaDescriptionBox, this.themeService));
|
||||||
this._toDispose.push(attachInputBoxStyler(this.backupRetainDaysBox, this.themeService));
|
this._toDispose.push(attachInputBoxStyler(this.backupRetainDaysBox, this.themeService));
|
||||||
|
this._toDispose.push(attachCheckboxStyler(this.copyOnlyCheckBox, this.themeService));
|
||||||
|
this._toDispose.push(attachCheckboxStyler(this.encryptCheckBox, this.themeService));
|
||||||
|
this._toDispose.push(attachCheckboxStyler(this.verifyCheckBox, this.themeService));
|
||||||
|
this._toDispose.push(attachCheckboxStyler(this.checksumCheckBox, this.themeService));
|
||||||
|
this._toDispose.push(attachCheckboxStyler(this.continueOnErrorCheckBox, this.themeService));
|
||||||
|
|
||||||
this._toDispose.push(this.backupTypeSelectBox.onDidSelect(selected => this.onBackupTypeChanged()));
|
this._toDispose.push(this.backupTypeSelectBox.onDidSelect(selected => this.onBackupTypeChanged()));
|
||||||
this.addButtonClickHandler(this.addPathButton, () => this.onAddClick());
|
this.addButtonClickHandler(this.addPathButton, () => this.onAddClick());
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.backup-dialog {
|
.backup-dialog {
|
||||||
height: calc(100% - 15px)
|
height: 100%
|
||||||
}
|
}
|
||||||
|
|
||||||
.backup-dialog .advanced-main-header {
|
.backup-dialog .advanced-main-header {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import { Table } from 'sql/base/browser/ui/table/table';
|
|||||||
import { TableDataView } from 'sql/base/browser/ui/table/tableDataView';
|
import { TableDataView } from 'sql/base/browser/ui/table/tableDataView';
|
||||||
import * as DialogHelper from 'sql/base/browser/ui/modal/dialogHelper';
|
import * as DialogHelper from 'sql/base/browser/ui/modal/dialogHelper';
|
||||||
import { Modal } from 'sql/base/browser/ui/modal/modal';
|
import { Modal } from 'sql/base/browser/ui/modal/modal';
|
||||||
import { attachButtonStyler, attachModalDialogStyler, attachTableStyler, attachInputBoxStyler, attachSelectBoxStyler, attachEditableDropdownStyler } from 'sql/common/theme/styler';
|
import { attachButtonStyler, attachModalDialogStyler, attachTableStyler, attachInputBoxStyler, attachSelectBoxStyler, attachEditableDropdownStyler, attachCheckboxStyler } from 'sql/common/theme/styler';
|
||||||
import * as TelemetryKeys from 'sql/common/telemetryKeys';
|
import * as TelemetryKeys from 'sql/common/telemetryKeys';
|
||||||
import * as BackupConstants from 'sql/parts/disasterRecovery/backup/constants';
|
import * as BackupConstants from 'sql/parts/disasterRecovery/backup/constants';
|
||||||
import { RestoreViewModel, RestoreOptionParam, SouceDatabaseNamesParam } from 'sql/parts/disasterRecovery/restore/restoreViewModel';
|
import { RestoreViewModel, RestoreOptionParam, SouceDatabaseNamesParam } from 'sql/parts/disasterRecovery/restore/restoreViewModel';
|
||||||
@@ -532,6 +532,7 @@ export class RestoreDialog extends Modal {
|
|||||||
ariaLabel: label
|
ariaLabel: label
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
this._register(attachCheckboxStyler(checkbox, this._themeService));
|
||||||
return checkbox;
|
return checkbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
div.qp-node {
|
div.qp-node {
|
||||||
background-color: #FFFFCC;
|
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
border: 1px solid black;
|
border: 1px solid;
|
||||||
}
|
}
|
||||||
div.qp-statement-header {
|
div.qp-statement-header {
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
@@ -33,8 +32,7 @@ div[class|='qp-icon'] {
|
|||||||
.qp-tt {
|
.qp-tt {
|
||||||
top: 4em;
|
top: 4em;
|
||||||
left: 2em;
|
left: 2em;
|
||||||
border: 1px solid black;
|
border: 1px solid;
|
||||||
background-color: #FFFFEE;
|
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
width: 30em;
|
width: 30em;
|
||||||
}
|
}
|
||||||
@@ -56,7 +54,7 @@ div[class|='qp-icon'] {
|
|||||||
.qp-tt td,
|
.qp-tt td,
|
||||||
.qp-tt th {
|
.qp-tt th {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
border-bottom: solid 1px Black;
|
border-bottom: solid 1px;
|
||||||
padding: 1px;
|
padding: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,8 +202,6 @@ div.qp-node:hover .qp-tt {
|
|||||||
.qp-root {
|
.qp-root {
|
||||||
display: table;
|
display: table;
|
||||||
position: relative;
|
position: relative;
|
||||||
background-color: #fff;
|
|
||||||
color: #000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.qp-root svg {
|
.qp-root svg {
|
||||||
|
|||||||
@@ -219,14 +219,10 @@ export class NewStepAction extends Action {
|
|||||||
|
|
||||||
public run(context: JobHistoryComponent): TPromise<boolean> {
|
public run(context: JobHistoryComponent): TPromise<boolean> {
|
||||||
let ownerUri = context.ownerUri;
|
let ownerUri = context.ownerUri;
|
||||||
let jobName = context.agentJobInfo.name;
|
|
||||||
let server = context.serverName;
|
let server = context.serverName;
|
||||||
let stepId = 0;
|
let jobInfo = context.agentJobInfo;
|
||||||
if (context.agentJobHistoryInfo && context.agentJobHistoryInfo.steps) {
|
|
||||||
stepId = context.agentJobHistoryInfo.steps.length + 1;
|
|
||||||
}
|
|
||||||
return new TPromise<boolean>((resolve, reject) => {
|
return new TPromise<boolean>((resolve, reject) => {
|
||||||
resolve(this._commandService.executeCommand('agent.openNewStepDialog', ownerUri, jobName, server, stepId));
|
resolve(this._commandService.executeCommand('agent.openNewStepDialog', ownerUri, server, jobInfo , null));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -923,33 +923,17 @@ export class JobsViewComponent extends JobManagementView implements OnInit {
|
|||||||
let steps = this.jobSteps[jobId];
|
let steps = this.jobSteps[jobId];
|
||||||
job[0].JobSteps = steps;
|
job[0].JobSteps = steps;
|
||||||
}
|
}
|
||||||
let jobHistories = this.jobHistories[job[0].jobId];
|
|
||||||
let schedules: sqlops.AgentJobScheduleInfo[] = this.jobSchedules[job[0].jobId];
|
|
||||||
let alerts: sqlops.AgentAlertInfo[] = this.jobAlerts[job[0].jobId];
|
|
||||||
if (jobHistories && jobHistories[jobHistories.length-1]) {
|
|
||||||
|
|
||||||
// add schedules
|
// add schedules
|
||||||
if (schedules && schedules.length > 0) {
|
if (this.jobSchedules && this.jobSchedules[jobId]) {
|
||||||
if (!job[0].JobSchedules) {
|
let schedules = this.jobSchedules[jobId];
|
||||||
job[0].JobSchedules = [];
|
job[0].JobSchedules = schedules;
|
||||||
}
|
|
||||||
if (job[0].JobSchedules.length !== schedules.length) {
|
|
||||||
job[0].JobSchedules = [];
|
|
||||||
schedules.forEach(schedule => {
|
|
||||||
job[0].JobSchedules.push(schedule);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// add alerts
|
// add alerts
|
||||||
if (!job[0].Alerts) {
|
if (this.jobAlerts && this.jobAlerts[jobId]) {
|
||||||
job[0].Alerts = [];
|
let alerts = this.jobAlerts[jobId];
|
||||||
}
|
job[0].Alerts = alerts;
|
||||||
if (job[0].Alerts.length !== alerts.length) {
|
|
||||||
job[0].Alerts = [];
|
|
||||||
alerts.forEach(alert => {
|
|
||||||
job[0].Alerts.push(alert);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return job && job.length > 0 ? job[0] : undefined;
|
return job && job.length > 0 ? job[0] : undefined;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import { ComponentBase } from 'sql/parts/modelComponents/componentBase';
|
|||||||
import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType } from 'sql/parts/modelComponents/interfaces';
|
import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType } from 'sql/parts/modelComponents/interfaces';
|
||||||
import { Checkbox, ICheckboxOptions } from 'sql/base/browser/ui/checkbox/checkbox';
|
import { Checkbox, ICheckboxOptions } from 'sql/base/browser/ui/checkbox/checkbox';
|
||||||
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
|
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
|
||||||
|
import { attachCheckboxStyler } from 'sql/common/theme/styler';
|
||||||
|
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'modelview-checkbox',
|
selector: 'modelview-checkbox',
|
||||||
@@ -30,7 +32,8 @@ export default class CheckBoxComponent extends ComponentBase implements ICompone
|
|||||||
constructor(
|
constructor(
|
||||||
@Inject(forwardRef(() => CommonServiceInterface)) private _commonService: CommonServiceInterface,
|
@Inject(forwardRef(() => CommonServiceInterface)) private _commonService: CommonServiceInterface,
|
||||||
@Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef,
|
@Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef,
|
||||||
@Inject(forwardRef(() => ElementRef)) el: ElementRef) {
|
@Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService,
|
||||||
|
@Inject(forwardRef(() => ElementRef)) el: ElementRef,) {
|
||||||
super(changeRef, el);
|
super(changeRef, el);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,6 +58,7 @@ export default class CheckBoxComponent extends ComponentBase implements ICompone
|
|||||||
args: e
|
args: e
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
this._register(attachCheckboxStyler(this._input, this.themeService));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,9 +90,11 @@ export class ServerTreeActionProvider extends ContributableActionProvider {
|
|||||||
* Return actions for connection elements
|
* Return actions for connection elements
|
||||||
*/
|
*/
|
||||||
public getConnectionActions(tree: ITree, profile: ConnectionProfile): IAction[] {
|
public getConnectionActions(tree: ITree, profile: ConnectionProfile): IAction[] {
|
||||||
|
let node = new TreeNode(NodeType.Server, '', false, '', '', '', undefined, undefined, undefined, undefined);
|
||||||
return this.getAllActions({
|
return this.getAllActions({
|
||||||
tree: tree,
|
tree: tree,
|
||||||
profile: profile
|
profile: profile,
|
||||||
|
treeNode: node
|
||||||
}, (context) => this.getBuiltinConnectionActions(context));
|
}, (context) => this.getBuiltinConnectionActions(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,10 +127,6 @@ export class ServerTreeActionProvider extends ContributableActionProvider {
|
|||||||
actions.push(this._instantiationService.createInstance(DeleteConnectionAction, DeleteConnectionAction.ID, DeleteConnectionAction.DELETE_CONNECTION_LABEL, context.profile));
|
actions.push(this._instantiationService.createInstance(DeleteConnectionAction, DeleteConnectionAction.ID, DeleteConnectionAction.DELETE_CONNECTION_LABEL, context.profile));
|
||||||
actions.push(this._instantiationService.createInstance(RefreshAction, RefreshAction.ID, RefreshAction.LABEL, context.tree, context.profile));
|
actions.push(this._instantiationService.createInstance(RefreshAction, RefreshAction.ID, RefreshAction.LABEL, context.tree, context.profile));
|
||||||
|
|
||||||
if (process.env['VSCODE_DEV'] && constants.MssqlProviderId === context.profile.providerName) {
|
|
||||||
actions.push(this._instantiationService.createInstance(OEAction, NewProfilerAction.ID, NewProfilerAction.LABEL));
|
|
||||||
}
|
|
||||||
|
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ export class TreeCreationUtils {
|
|||||||
|
|
||||||
return new Tree(treeContainer, { dataSource, renderer, controller, dnd, filter, sorter, accessibilityProvider },
|
return new Tree(treeContainer, { dataSource, renderer, controller, dnd, filter, sorter, accessibilityProvider },
|
||||||
{
|
{
|
||||||
indentPixels: 10,
|
indentPixels: 0,
|
||||||
twistiePixels: 20,
|
twistiePixels: 0,
|
||||||
ariaLabel: nls.localize('treeAriaLabel', "Recent Connections")
|
ariaLabel: nls.localize('treeAriaLabel', "Recent Connections")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiati
|
|||||||
import * as nls from 'vs/nls';
|
import * as nls from 'vs/nls';
|
||||||
import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||||
import { IEditorService, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService';
|
import { IEditorService, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService';
|
||||||
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
|
import { IConnectionManagementService, IConnectionDialogService} from 'sql/parts/connection/common/connectionManagement';
|
||||||
import { IObjectExplorerService } from '../../objectExplorer/common/objectExplorerService';
|
import { IObjectExplorerService } from '../../objectExplorer/common/objectExplorerService';
|
||||||
import { ProfilerInput } from 'sql/parts/profiler/editor/profilerInput';
|
import { ProfilerInput } from 'sql/parts/profiler/editor/profilerInput';
|
||||||
import { TPromise } from 'vs/base/common/winjs.base';
|
import { TPromise } from 'vs/base/common/winjs.base';
|
||||||
@@ -18,6 +18,10 @@ import { IProfilerService } from '../service/interfaces';
|
|||||||
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||||
import { KeyCode, KeyMod } from 'vs/editor/editor.api';
|
import { KeyCode, KeyMod } from 'vs/editor/editor.api';
|
||||||
import { ProfilerEditor } from '../editor/profilerEditor';
|
import { ProfilerEditor } from '../editor/profilerEditor';
|
||||||
|
import { ObjectExplorerActionsContext } from 'sql/parts/objectExplorer/viewlet/objectExplorerActions';
|
||||||
|
import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
|
||||||
|
import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
|
||||||
|
import { mssqlProviderName } from 'sql/parts/connection/common/constants';
|
||||||
|
|
||||||
// Contribute Global Actions
|
// Contribute Global Actions
|
||||||
const category = nls.localize('profilerCategory', "Profiler");
|
const category = nls.localize('profilerCategory', "Profiler");
|
||||||
@@ -30,15 +34,45 @@ const newProfilerSchema: IJSONSchema = {
|
|||||||
|
|
||||||
CommandsRegistry.registerCommand({
|
CommandsRegistry.registerCommand({
|
||||||
id: 'profiler.newProfiler',
|
id: 'profiler.newProfiler',
|
||||||
handler: (accessor: ServicesAccessor) => {
|
handler: (accessor: ServicesAccessor, ...args: any[]) => {
|
||||||
let editorService: IEditorService = accessor.get(IEditorService);
|
let connectionProfile: ConnectionProfile = undefined;
|
||||||
let instantiationService: IInstantiationService = accessor.get(IInstantiationService);
|
let instantiationService: IInstantiationService = accessor.get(IInstantiationService);
|
||||||
|
let editorService: IEditorService = accessor.get(IEditorService);
|
||||||
let connectionService: IConnectionManagementService = accessor.get(IConnectionManagementService);
|
let connectionService: IConnectionManagementService = accessor.get(IConnectionManagementService);
|
||||||
let objectExplorerService: IObjectExplorerService = accessor.get(IObjectExplorerService);
|
let objectExplorerService: IObjectExplorerService = accessor.get(IObjectExplorerService);
|
||||||
|
let connectionDialogService: IConnectionDialogService = accessor.get(IConnectionDialogService);
|
||||||
|
let capabilitiesService: ICapabilitiesService = accessor.get(ICapabilitiesService);
|
||||||
|
|
||||||
let connectionProfile = TaskUtilities.getCurrentGlobalConnection(objectExplorerService, connectionService, editorService);
|
// If a context is available if invoked from the context menu, we will use the connection profiler of the server node
|
||||||
|
if (args && args.length === 1 && args[0] && args[0] instanceof ObjectExplorerActionsContext) {
|
||||||
|
let context = args[0] as ObjectExplorerActionsContext;
|
||||||
|
connectionProfile = ConnectionProfile.fromIConnectionProfile(capabilitiesService, context.connectionProfile);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// No context available, we will try to get the current global active connection
|
||||||
|
connectionProfile = TaskUtilities.getCurrentGlobalConnection(objectExplorerService, connectionService, editorService) as ConnectionProfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
let promise;
|
||||||
|
if (connectionProfile) {
|
||||||
|
promise = connectionService.connectIfNotConnected(connectionProfile);
|
||||||
|
} else {
|
||||||
|
// if still no luck, we will open the Connection dialog and let user connect to a server
|
||||||
|
promise = connectionDialogService.openDialogAndWait(connectionService, { connectionType: 1, providers: [mssqlProviderName] }).then((profile) => {
|
||||||
|
connectionProfile = profile as ConnectionProfile;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return promise.then(() => {
|
||||||
|
if (!connectionProfile) {
|
||||||
|
connectionProfile = TaskUtilities.getCurrentGlobalConnection(objectExplorerService, connectionService, editorService) as ConnectionProfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connectionProfile && connectionProfile.providerName === mssqlProviderName) {
|
||||||
let profilerInput = instantiationService.createInstance(ProfilerInput, connectionProfile);
|
let profilerInput = instantiationService.createInstance(ProfilerInput, connectionProfile);
|
||||||
return editorService.openEditor(profilerInput, { pinned: true }, ACTIVE_GROUP).then(() => TPromise.as(true));
|
editorService.openEditor(profilerInput, { pinned: true }, ACTIVE_GROUP).then(() => TPromise.as(true));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -91,6 +91,10 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get providerType(): string {
|
||||||
|
return this._connection ? this._connection.providerName : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
public set viewTemplate(template: IProfilerViewTemplate) {
|
public set viewTemplate(template: IProfilerViewTemplate) {
|
||||||
this._data.clear();
|
this._data.clear();
|
||||||
this._viewTemplate = template;
|
this._viewTemplate = template;
|
||||||
|
|||||||
@@ -228,6 +228,6 @@ export class ProfilerService implements IProfilerService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public launchCreateSessionDialog(input?: ProfilerInput): Thenable<void> {
|
public launchCreateSessionDialog(input?: ProfilerInput): Thenable<void> {
|
||||||
return this._commandService.executeCommand('profiler.openCreateSessionDialog', input.id, this.getSessionTemplates());
|
return this._commandService.executeCommand('profiler.openCreateSessionDialog', input.id, input.providerType, this.getSessionTemplates());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -339,7 +339,7 @@ let registryProperties = {
|
|||||||
'sql.showConnectionInfoInTitle': {
|
'sql.showConnectionInfoInTitle': {
|
||||||
'type': 'boolean',
|
'type': 'boolean',
|
||||||
'description': localize('showConnectionInfoInTitle', "Controls whether to show the connection info for a tab in the title."),
|
'description': localize('showConnectionInfoInTitle', "Controls whether to show the connection info for a tab in the title."),
|
||||||
'default': false
|
'default': true
|
||||||
},
|
},
|
||||||
'mssql.intelliSense.enableIntelliSense': {
|
'mssql.intelliSense.enableIntelliSense': {
|
||||||
'type': 'boolean',
|
'type': 'boolean',
|
||||||
|
|||||||
@@ -32,9 +32,6 @@ export interface IQueryEditorService {
|
|||||||
// Creates new edit data session
|
// Creates new edit data session
|
||||||
newEditDataEditor(schemaName: string, tableName: string, queryString: string): Promise<IConnectableInput>;
|
newEditDataEditor(schemaName: string, tableName: string, queryString: string): Promise<IConnectableInput>;
|
||||||
|
|
||||||
// Clears any QueryEditor data for the given URI held by this service
|
|
||||||
onQueryInputClosed(uri: string): void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles updating of SQL files on a save as event. These need special consideration
|
* Handles updating of SQL files on a save as event. These need special consideration
|
||||||
* due to query results and other information being tied to the URI of the file
|
* due to query results and other information being tied to the URI of the file
|
||||||
|
|||||||
@@ -116,11 +116,11 @@ export class QueryInput extends EditorInput implements IEncodingSupport, IConnec
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this._configurationService) {
|
if (this._configurationService) {
|
||||||
this._configurationService.onDidChangeConfiguration(e => {
|
this._toDispose.push(this._configurationService.onDidChangeConfiguration(e => {
|
||||||
if (e.affectedKeys.includes('sql.showConnectionInfoInTitle')) {
|
if (e.affectedKeys.includes('sql.showConnectionInfoInTitle')) {
|
||||||
this._onDidChangeLabel.fire();
|
this._onDidChangeLabel.fire();
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.onDisconnect();
|
this.onDisconnect();
|
||||||
@@ -196,17 +196,17 @@ export class QueryInput extends EditorInput implements IEncodingSupport, IConnec
|
|||||||
|
|
||||||
// State update funtions
|
// State update funtions
|
||||||
public runQuery(selection: ISelectionData, executePlanOptions?: ExecutionPlanOptions): void {
|
public runQuery(selection: ISelectionData, executePlanOptions?: ExecutionPlanOptions): void {
|
||||||
this._queryModelService.runQuery(this.uri, selection, this.uri, this, executePlanOptions);
|
this._queryModelService.runQuery(this.uri, selection, this, executePlanOptions);
|
||||||
this.showQueryResultsEditor();
|
this.showQueryResultsEditor();
|
||||||
}
|
}
|
||||||
|
|
||||||
public runQueryStatement(selection: ISelectionData): void {
|
public runQueryStatement(selection: ISelectionData): void {
|
||||||
this._queryModelService.runQueryStatement(this.uri, selection, this.uri, this);
|
this._queryModelService.runQueryStatement(this.uri, selection, this);
|
||||||
this.showQueryResultsEditor();
|
this.showQueryResultsEditor();
|
||||||
}
|
}
|
||||||
|
|
||||||
public runQueryString(text: string): void {
|
public runQueryString(text: string): void {
|
||||||
this._queryModelService.runQueryString(this.uri, text, this.uri, this);
|
this._queryModelService.runQueryString(this.uri, text, this);
|
||||||
this.showQueryResultsEditor();
|
this.showQueryResultsEditor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,7 +276,6 @@ export class QueryInput extends EditorInput implements IEncodingSupport, IConnec
|
|||||||
|
|
||||||
// Clean up functions
|
// Clean up functions
|
||||||
public dispose(): void {
|
public dispose(): void {
|
||||||
this._queryModelService.disposeQuery(this.uri);
|
|
||||||
this._sql.dispose();
|
this._sql.dispose();
|
||||||
this._results.dispose();
|
this._results.dispose();
|
||||||
this._toDispose = dispose(this._toDispose);
|
this._toDispose = dispose(this._toDispose);
|
||||||
@@ -285,7 +284,7 @@ export class QueryInput extends EditorInput implements IEncodingSupport, IConnec
|
|||||||
}
|
}
|
||||||
|
|
||||||
public close(): void {
|
public close(): void {
|
||||||
this._queryEditorService.onQueryInputClosed(this.uri);
|
this._queryModelService.disposeQuery(this.uri);
|
||||||
this._connectionManagementService.disconnectEditor(this, true);
|
this._connectionManagementService.disconnectEditor(this, true);
|
||||||
|
|
||||||
this._sql.close();
|
this._sql.close();
|
||||||
|
|||||||
@@ -215,6 +215,7 @@ export class QueryManagementService implements IQueryManagementService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
public disposeQuery(ownerUri: string): Thenable<void> {
|
public disposeQuery(ownerUri: string): Thenable<void> {
|
||||||
|
this._queryRunners.delete(ownerUri);
|
||||||
return this._runAction(ownerUri, (runner) => {
|
return this._runAction(ownerUri, (runner) => {
|
||||||
return runner.disposeQuery(ownerUri);
|
return runner.disposeQuery(ownerUri);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -29,6 +29,13 @@ export class ResultsViewState {
|
|||||||
constructor(@IConfigurationService private configurationService: IConfigurationService) {
|
constructor(@IConfigurationService private configurationService: IConfigurationService) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dispose() {
|
||||||
|
this.gridPanelState.dispose();
|
||||||
|
this.messagePanelState.dispose();
|
||||||
|
this.chartState.dispose();
|
||||||
|
this.queryPlanState.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,7 +57,11 @@ export class QueryResultsInput extends EditorInput {
|
|||||||
public readonly onRestoreViewStateEmitter = new Emitter<void>();
|
public readonly onRestoreViewStateEmitter = new Emitter<void>();
|
||||||
public readonly onSaveViewStateEmitter = new Emitter<void>();
|
public readonly onSaveViewStateEmitter = new Emitter<void>();
|
||||||
|
|
||||||
public readonly state = new ResultsViewState(this.configurationService);
|
private _state = new ResultsViewState(this.configurationService);
|
||||||
|
|
||||||
|
public get state(): ResultsViewState {
|
||||||
|
return this._state;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(private _uri: string,
|
constructor(private _uri: string,
|
||||||
@IConfigurationService private configurationService: IConfigurationService
|
@IConfigurationService private configurationService: IConfigurationService
|
||||||
@@ -60,6 +71,12 @@ export class QueryResultsInput extends EditorInput {
|
|||||||
this._hasBootstrapped = false;
|
this._hasBootstrapped = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
close() {
|
||||||
|
this.state.dispose();
|
||||||
|
this._state = undefined;
|
||||||
|
super.close();
|
||||||
|
}
|
||||||
|
|
||||||
getTypeId(): string {
|
getTypeId(): string {
|
||||||
return QueryResultsInput.ID;
|
return QueryResultsInput.ID;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import QueryRunner from 'sql/parts/query/execution/queryRunner';
|
|||||||
|
|
||||||
import { IStatusbarItem } from 'vs/workbench/browser/parts/statusbar/statusbar';
|
import { IStatusbarItem } from 'vs/workbench/browser/parts/statusbar/statusbar';
|
||||||
import { IDisposable, combinedDisposable, dispose } from 'vs/base/common/lifecycle';
|
import { IDisposable, combinedDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||||
import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
|
|
||||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||||
import { IEditorCloseEvent } from 'vs/workbench/common/editor';
|
import { IEditorCloseEvent } from 'vs/workbench/common/editor';
|
||||||
import { append, $, hide, show } from 'vs/base/browser/dom';
|
import { append, $, hide, show } from 'vs/base/browser/dom';
|
||||||
@@ -25,7 +24,6 @@ export class RowCountStatusBarItem implements IStatusbarItem {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@IEditorService private _editorService: EditorServiceImpl,
|
@IEditorService private _editorService: EditorServiceImpl,
|
||||||
@IEditorGroupsService private _editorGroupService: IEditorGroupsService,
|
|
||||||
@IQueryModelService private _queryModelService: IQueryModelService
|
@IQueryModelService private _queryModelService: IQueryModelService
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
@@ -36,7 +34,7 @@ export class RowCountStatusBarItem implements IStatusbarItem {
|
|||||||
];
|
];
|
||||||
|
|
||||||
this._element = append(container, $('.query-statusbar-group'));
|
this._element = append(container, $('.query-statusbar-group'));
|
||||||
this._flavorElement = append(this._element, $('a.editor-status-selection'));
|
this._flavorElement = append(this._element, $('.editor-status-selection'));
|
||||||
this._flavorElement.title = nls.localize('rowStatus', "Row Count");
|
this._flavorElement.title = nls.localize('rowStatus', "Row Count");
|
||||||
hide(this._flavorElement);
|
hide(this._flavorElement);
|
||||||
|
|
||||||
@@ -65,11 +63,10 @@ export class RowCountStatusBarItem implements IStatusbarItem {
|
|||||||
if (queryRunner) {
|
if (queryRunner) {
|
||||||
if (queryRunner.hasCompleted) {
|
if (queryRunner.hasCompleted) {
|
||||||
this._displayValue(queryRunner);
|
this._displayValue(queryRunner);
|
||||||
} else if (queryRunner.isExecuting) {
|
}
|
||||||
this.dispose = queryRunner.addListener('complete', () => {
|
this.dispose = queryRunner.onQueryEnd(e => {
|
||||||
this._displayValue(queryRunner);
|
this._displayValue(queryRunner);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
this.dispose = this._queryModelService.onRunQueryComplete(e => {
|
this.dispose = this._queryModelService.onRunQueryComplete(e => {
|
||||||
if (e === currentUri) {
|
if (e === currentUri) {
|
||||||
|
|||||||
107
src/sql/parts/query/common/timeElapsedStatus.ts
Normal file
107
src/sql/parts/query/common/timeElapsedStatus.ts
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import * as WorkbenchUtils from 'sql/workbench/common/sqlWorkbenchUtils';
|
||||||
|
import { IQueryModelService } from '../execution/queryModel';
|
||||||
|
import QueryRunner from 'sql/parts/query/execution/queryRunner';
|
||||||
|
import { parseNumAsTimeString } from 'sql/parts/connection/common/utils';
|
||||||
|
|
||||||
|
import { IStatusbarItem } from 'vs/workbench/browser/parts/statusbar/statusbar';
|
||||||
|
import { IDisposable, combinedDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||||
|
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||||
|
import { IEditorCloseEvent } from 'vs/workbench/common/editor';
|
||||||
|
import { append, $, hide, show } from 'vs/base/browser/dom';
|
||||||
|
import * as nls from 'vs/nls';
|
||||||
|
import { EditorServiceImpl } from 'vs/workbench/browser/parts/editor/editor';
|
||||||
|
import { IntervalTimer } from 'vs/base/common/async';
|
||||||
|
|
||||||
|
export class TimeElapsedStatusBarItem implements IStatusbarItem {
|
||||||
|
|
||||||
|
private _element: HTMLElement;
|
||||||
|
private _flavorElement: HTMLElement;
|
||||||
|
|
||||||
|
private dispose: IDisposable[] = [];
|
||||||
|
private intervalTimer = new IntervalTimer();
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@IEditorService private _editorService: EditorServiceImpl,
|
||||||
|
@IQueryModelService private _queryModelService: IQueryModelService
|
||||||
|
) { }
|
||||||
|
|
||||||
|
render(container: HTMLElement): IDisposable {
|
||||||
|
let disposables = [
|
||||||
|
this._editorService.onDidVisibleEditorsChange(() => this._onEditorsChanged()),
|
||||||
|
this._editorService.onDidCloseEditor(event => this._onEditorClosed(event))
|
||||||
|
];
|
||||||
|
|
||||||
|
this._element = append(container, $('.query-statusbar-group'));
|
||||||
|
this._flavorElement = append(this._element, $('.editor-status-selection'));
|
||||||
|
this._flavorElement.title = nls.localize('timeElapsed', "Time Elapsed");
|
||||||
|
hide(this._flavorElement);
|
||||||
|
|
||||||
|
this._showStatus();
|
||||||
|
|
||||||
|
return combinedDisposable(disposables);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _onEditorsChanged() {
|
||||||
|
this._showStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _onEditorClosed(event: IEditorCloseEvent) {
|
||||||
|
hide(this._flavorElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show/hide query status for active editor
|
||||||
|
private _showStatus(): void {
|
||||||
|
this.intervalTimer.cancel();
|
||||||
|
hide(this._flavorElement);
|
||||||
|
dispose(this.dispose);
|
||||||
|
this._flavorElement.innerText = '';
|
||||||
|
this.dispose = [];
|
||||||
|
let activeEditor = this._editorService.activeControl;
|
||||||
|
if (activeEditor) {
|
||||||
|
let currentUri = WorkbenchUtils.getEditorUri(activeEditor.input);
|
||||||
|
if (currentUri) {
|
||||||
|
let queryRunner = this._queryModelService.getQueryRunner(currentUri);
|
||||||
|
if (queryRunner) {
|
||||||
|
if (queryRunner.hasCompleted || queryRunner.isExecuting) {
|
||||||
|
this._displayValue(queryRunner);
|
||||||
|
}
|
||||||
|
this.dispose.push(queryRunner.onQueryStart(e => {
|
||||||
|
this._displayValue(queryRunner);
|
||||||
|
}));
|
||||||
|
this.dispose.push(queryRunner.onQueryEnd(e => {
|
||||||
|
this._displayValue(queryRunner);
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
this.dispose.push(this._queryModelService.onRunQueryStart(e => {
|
||||||
|
if (e === currentUri) {
|
||||||
|
this._displayValue(this._queryModelService.getQueryRunner(currentUri));
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
this.dispose.push(this._queryModelService.onRunQueryComplete(e => {
|
||||||
|
if (e === currentUri) {
|
||||||
|
this._displayValue(this._queryModelService.getQueryRunner(currentUri));
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _displayValue(runner: QueryRunner) {
|
||||||
|
this.intervalTimer.cancel();
|
||||||
|
if (runner.isExecuting) {
|
||||||
|
this.intervalTimer.cancelAndSet(() => {
|
||||||
|
this._flavorElement.innerText = parseNumAsTimeString(Date.now() - runner.queryStartTime.getTime(), false);
|
||||||
|
}, 1000);
|
||||||
|
this._flavorElement.innerText = parseNumAsTimeString(Date.now() - runner.queryStartTime.getTime(), false);
|
||||||
|
} else {
|
||||||
|
this._flavorElement.innerText = parseNumAsTimeString(runner.queryEndTime.getTime() - runner.queryStartTime.getTime(), false);
|
||||||
|
}
|
||||||
|
show(this._flavorElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,4 +33,8 @@ export class ChartTab implements IPanelTab {
|
|||||||
public dispose() {
|
public dispose() {
|
||||||
this.view.dispose();
|
this.view.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public clear() {
|
||||||
|
this.view.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,10 @@ export class ChartState {
|
|||||||
options: IInsightOptions = {
|
options: IInsightOptions = {
|
||||||
type: ChartType.Bar
|
type: ChartType.Bar
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dispose() {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare class Proxy {
|
declare class Proxy {
|
||||||
@@ -134,6 +138,15 @@ export class ChartView extends Disposable implements IPanelView {
|
|||||||
this.buildOptions();
|
this.buildOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public clear() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public dispose() {
|
||||||
|
dispose(this.optionDisposables);
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
render(container: HTMLElement): void {
|
render(container: HTMLElement): void {
|
||||||
if (!this.container) {
|
if (!this.container) {
|
||||||
this.container = $('div.chart-parent-container');
|
this.container = $('div.chart-parent-container');
|
||||||
@@ -326,7 +339,7 @@ export class ChartView extends Disposable implements IPanelView {
|
|||||||
this.optionDisposables.push(attachInputBoxStyler(numberInput, this._themeService));
|
this.optionDisposables.push(attachInputBoxStyler(numberInput, this._themeService));
|
||||||
break;
|
break;
|
||||||
case ControlType.dateInput:
|
case ControlType.dateInput:
|
||||||
let dateInput = new InputBox(optionContainer, this._contextViewService, { type: 'date' });
|
let dateInput = new InputBox(optionContainer, this._contextViewService, { type: 'datetime-local' });
|
||||||
dateInput.value = value || '';
|
dateInput.value = value || '';
|
||||||
dateInput.onDidChange(e => {
|
dateInput.onDidChange(e => {
|
||||||
if (this.options[option.configEntry] !== e) {
|
if (this.options[option.configEntry] !== e) {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import { ChartType, DataDirection, LegendPosition, DataType, IPointDataSet, cust
|
|||||||
|
|
||||||
const noneLineGraphs = [ChartType.Doughnut, ChartType.Pie];
|
const noneLineGraphs = [ChartType.Doughnut, ChartType.Pie];
|
||||||
|
|
||||||
const timeSeriesScales = {
|
const timeSeriesScales: ChartJs.ChartOptions = {
|
||||||
scales: {
|
scales: {
|
||||||
xAxes: [{
|
xAxes: [{
|
||||||
type: 'time',
|
type: 'time',
|
||||||
@@ -64,7 +64,7 @@ export class Graph implements IInsight {
|
|||||||
this._theme = e;
|
this._theme = e;
|
||||||
this.data = this._data;
|
this.data = this._data;
|
||||||
});
|
});
|
||||||
this._options = mixin(options, defaultOptions, false);
|
this.options = mixin(options, defaultOptions, false);
|
||||||
|
|
||||||
let canvasContainer = document.createElement('div');
|
let canvasContainer = document.createElement('div');
|
||||||
canvasContainer.style.width = '100%';
|
canvasContainer.style.width = '100%';
|
||||||
@@ -89,9 +89,12 @@ export class Graph implements IInsight {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public set data(data: IInsightData) {
|
public set data(data: IInsightData) {
|
||||||
|
if (!data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this._data = data;
|
this._data = data;
|
||||||
let chartData: Array<ChartJs.ChartDataSets>;
|
|
||||||
let labels: Array<string>;
|
let labels: Array<string>;
|
||||||
|
let chartData: Array<ChartJs.ChartDataSets>;
|
||||||
|
|
||||||
if (this.options.dataDirection === DataDirection.Horizontal) {
|
if (this.options.dataDirection === DataDirection.Horizontal) {
|
||||||
if (this.options.labelFirstColumn) {
|
if (this.options.labelFirstColumn) {
|
||||||
@@ -158,19 +161,19 @@ export class Graph implements IInsight {
|
|||||||
if (this.chartjs) {
|
if (this.chartjs) {
|
||||||
this.chartjs.data.datasets = chartData;
|
this.chartjs.data.datasets = chartData;
|
||||||
this.chartjs.config.type = this.options.type;
|
this.chartjs.config.type = this.options.type;
|
||||||
this.chartjs.data.labels = labels;
|
// we don't want to include lables for timeSeries
|
||||||
|
this.chartjs.data.labels = this.originalType === 'timeSeries' ? [] : labels;
|
||||||
this.chartjs.options = this.transformOptions(this.options);
|
this.chartjs.options = this.transformOptions(this.options);
|
||||||
this.chartjs.update(0);
|
this.chartjs.update(0);
|
||||||
} else {
|
} else {
|
||||||
this.chartjs = new ChartJs(this.canvas.getContext('2d'), {
|
this.chartjs = new ChartJs(this.canvas.getContext('2d'), {
|
||||||
data: {
|
data: {
|
||||||
labels: labels,
|
// we don't want to include lables for timeSeries
|
||||||
|
labels: this.originalType === 'timeSeries' ? [] : labels,
|
||||||
datasets: chartData
|
datasets: chartData
|
||||||
},
|
},
|
||||||
type: this.options.type,
|
type: this.options.type,
|
||||||
options: {
|
options: this.transformOptions(this.options)
|
||||||
maintainAspectRatio: false
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -197,15 +200,21 @@ export class Graph implements IInsight {
|
|||||||
display: options.xAxisLabel ? true : false
|
display: options.xAxisLabel ? true : false
|
||||||
},
|
},
|
||||||
ticks: {
|
ticks: {
|
||||||
fontColor: foreground,
|
fontColor: foreground
|
||||||
max: options.xAxisMax,
|
|
||||||
min: options.xAxisMin
|
|
||||||
},
|
},
|
||||||
gridLines: {
|
gridLines: {
|
||||||
color: gridLines
|
color: gridLines
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
if (options.xAxisMax) {
|
||||||
|
retval.scales = mixin(retval.scales, { xAxes: [{ ticks: { max: options.xAxisMax } }] }, true, customMixin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.xAxisMin) {
|
||||||
|
retval.scales = mixin(retval.scales, { xAxes: [{ ticks: { min: options.xAxisMin } }] }, true, customMixin);
|
||||||
|
}
|
||||||
|
|
||||||
retval.scales.yAxes = [{
|
retval.scales.yAxes = [{
|
||||||
scaleLabel: {
|
scaleLabel: {
|
||||||
fontColor: foreground,
|
fontColor: foreground,
|
||||||
@@ -213,22 +222,27 @@ export class Graph implements IInsight {
|
|||||||
display: options.yAxisLabel ? true : false
|
display: options.yAxisLabel ? true : false
|
||||||
},
|
},
|
||||||
ticks: {
|
ticks: {
|
||||||
fontColor: foreground,
|
fontColor: foreground
|
||||||
max: options.yAxisMax,
|
|
||||||
min: options.yAxisMin
|
|
||||||
},
|
},
|
||||||
gridLines: {
|
gridLines: {
|
||||||
color: gridLines
|
color: gridLines
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
if (options.yAxisMax) {
|
||||||
|
retval.scales = mixin(retval.scales, { yAxes: [{ ticks: { max: options.yAxisMax } }] }, true, customMixin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.yAxisMin) {
|
||||||
|
retval.scales = mixin(retval.scales, { yAxes: [{ ticks: { min: options.yAxisMin } }] }, true, customMixin);
|
||||||
|
}
|
||||||
|
|
||||||
if (this.originalType === ChartType.TimeSeries) {
|
if (this.originalType === ChartType.TimeSeries) {
|
||||||
retval = mixin(retval, timeSeriesScales, true, customMixin);
|
retval = mixin(retval, timeSeriesScales, true, customMixin);
|
||||||
if (options.xAxisMax) {
|
if (options.xAxisMax) {
|
||||||
retval = mixin(retval, {
|
retval = mixin(retval, {
|
||||||
scales: {
|
scales: {
|
||||||
xAxes: [{
|
xAxes: [{
|
||||||
type: 'time',
|
|
||||||
time: {
|
time: {
|
||||||
max: options.xAxisMax
|
max: options.xAxisMax
|
||||||
}
|
}
|
||||||
@@ -241,7 +255,6 @@ export class Graph implements IInsight {
|
|||||||
retval = mixin(retval, {
|
retval = mixin(retval, {
|
||||||
scales: {
|
scales: {
|
||||||
xAxes: [{
|
xAxes: [{
|
||||||
type: 'time',
|
|
||||||
time: {
|
time: {
|
||||||
min: options.xAxisMin
|
min: options.xAxisMin
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
import { attachTableStyler } from 'sql/common/theme/styler';
|
import { attachTableStyler } from 'sql/common/theme/styler';
|
||||||
import QueryRunner from 'sql/parts/query/execution/queryRunner';
|
import QueryRunner from 'sql/parts/query/execution/queryRunner';
|
||||||
import { VirtualizedCollection, AsyncDataProvider } from 'sql/base/browser/ui/table/asyncDataView';
|
import { VirtualizedCollection, AsyncDataProvider } from 'sql/base/browser/ui/table/asyncDataView';
|
||||||
import { Table, ITableStyles, ITableMouseEvent } from 'sql/base/browser/ui/table/table';
|
import { Table } from 'sql/base/browser/ui/table/table';
|
||||||
import { ScrollableSplitView } from 'sql/base/browser/ui/scrollableSplitview/scrollableSplitview';
|
import { ScrollableSplitView } from 'sql/base/browser/ui/scrollableSplitview/scrollableSplitview';
|
||||||
import { MouseWheelSupport } from 'sql/base/browser/ui/table/plugins/mousewheelTableScroll.plugin';
|
import { MouseWheelSupport } from 'sql/base/browser/ui/table/plugins/mousewheelTableScroll.plugin';
|
||||||
import { AutoColumnSize } from 'sql/base/browser/ui/table/plugins/autoSizeColumns.plugin';
|
import { AutoColumnSize } from 'sql/base/browser/ui/table/plugins/autoSizeColumns.plugin';
|
||||||
@@ -19,6 +19,7 @@ import { escape } from 'sql/base/common/strings';
|
|||||||
import { hyperLinkFormatter, textFormatter } from 'sql/parts/grid/services/sharedServices';
|
import { hyperLinkFormatter, textFormatter } from 'sql/parts/grid/services/sharedServices';
|
||||||
import { CopyKeybind } from 'sql/base/browser/ui/table/plugins/copyKeybind.plugin';
|
import { CopyKeybind } from 'sql/base/browser/ui/table/plugins/copyKeybind.plugin';
|
||||||
import { AdditionalKeyBindings } from 'sql/base/browser/ui/table/plugins/additionalKeyBindings.plugin';
|
import { AdditionalKeyBindings } from 'sql/base/browser/ui/table/plugins/additionalKeyBindings.plugin';
|
||||||
|
import { ITableStyles, ITableMouseEvent } from 'sql/base/browser/ui/table/interfaces';
|
||||||
|
|
||||||
import * as sqlops from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
import * as pretty from 'pretty-data';
|
import * as pretty from 'pretty-data';
|
||||||
@@ -42,13 +43,14 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
|||||||
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
|
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
|
||||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||||
import { IAction } from 'vs/base/common/actions';
|
import { IAction } from 'vs/base/common/actions';
|
||||||
|
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||||
|
|
||||||
const ROW_HEIGHT = 29;
|
const ROW_HEIGHT = 29;
|
||||||
const HEADER_HEIGHT = 26;
|
const HEADER_HEIGHT = 26;
|
||||||
const MIN_GRID_HEIGHT_ROWS = 8;
|
const MIN_GRID_HEIGHT_ROWS = 8;
|
||||||
const ESTIMATED_SCROLL_BAR_HEIGHT = 10;
|
const ESTIMATED_SCROLL_BAR_HEIGHT = 10;
|
||||||
const BOTTOM_PADDING = 15;
|
const BOTTOM_PADDING = 15;
|
||||||
const ACTIONBAR_WIDTH = 26;
|
const ACTIONBAR_WIDTH = 36;
|
||||||
|
|
||||||
// minimum height needed to show the full actionbar
|
// minimum height needed to show the full actionbar
|
||||||
const ACTIONBAR_HEIGHT = 100;
|
const ACTIONBAR_HEIGHT = 100;
|
||||||
@@ -60,6 +62,10 @@ export class GridPanelState {
|
|||||||
public tableStates: GridTableState[] = [];
|
public tableStates: GridTableState[] = [];
|
||||||
public scrollPosition: number;
|
public scrollPosition: number;
|
||||||
public collapsed = false;
|
public collapsed = false;
|
||||||
|
|
||||||
|
dispose() {
|
||||||
|
dispose(this.tableStates);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IGridTableState {
|
export interface IGridTableState {
|
||||||
@@ -67,14 +73,14 @@ export interface IGridTableState {
|
|||||||
maximized: boolean;
|
maximized: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GridTableState {
|
export class GridTableState extends Disposable {
|
||||||
|
|
||||||
private _maximized: boolean;
|
private _maximized: boolean;
|
||||||
|
|
||||||
private _onMaximizedChange = new Emitter<boolean>();
|
private _onMaximizedChange = this._register(new Emitter<boolean>());
|
||||||
public onMaximizedChange: Event<boolean> = this._onMaximizedChange.event;
|
public onMaximizedChange: Event<boolean> = this._onMaximizedChange.event;
|
||||||
|
|
||||||
private _onCanBeMaximizedChange = new Emitter<boolean>();
|
private _onCanBeMaximizedChange = this._register(new Emitter<boolean>());
|
||||||
public onCanBeMaximizedChange: Event<boolean> = this._onCanBeMaximizedChange.event;
|
public onCanBeMaximizedChange: Event<boolean> = this._onCanBeMaximizedChange.event;
|
||||||
|
|
||||||
private _canBeMaximized: boolean;
|
private _canBeMaximized: boolean;
|
||||||
@@ -85,6 +91,7 @@ export class GridTableState {
|
|||||||
public activeCell: Slick.Cell;
|
public activeCell: Slick.Cell;
|
||||||
|
|
||||||
constructor(public readonly resultId: number, public readonly batchId: number) {
|
constructor(public readonly resultId: number, public readonly batchId: number) {
|
||||||
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public get canBeMaximized(): boolean {
|
public get canBeMaximized(): boolean {
|
||||||
@@ -134,7 +141,7 @@ export class GridPanel extends ViewletPanel {
|
|||||||
@IInstantiationService private instantiationService: IInstantiationService
|
@IInstantiationService private instantiationService: IInstantiationService
|
||||||
) {
|
) {
|
||||||
super(options, keybindingService, contextMenuService, configurationService);
|
super(options, keybindingService, contextMenuService, configurationService);
|
||||||
this.splitView = new ScrollableSplitView(this.container, { enableResizing: false });
|
this.splitView = new ScrollableSplitView(this.container, { enableResizing: false, verticalScrollbarVisibility: ScrollbarVisibility.Visible });
|
||||||
this.splitView.onScroll(e => {
|
this.splitView.onScroll(e => {
|
||||||
if (this.state) {
|
if (this.state) {
|
||||||
this.state.scrollPosition = e;
|
this.state.scrollPosition = e;
|
||||||
@@ -216,13 +223,13 @@ export class GridPanel extends ViewletPanel {
|
|||||||
}
|
}
|
||||||
let table = this.instantiationService.createInstance(GridTable, this.runner, set);
|
let table = this.instantiationService.createInstance(GridTable, this.runner, set);
|
||||||
table.state = tableState;
|
table.state = tableState;
|
||||||
tableState.onMaximizedChange(e => {
|
this.tableDisposable.push(tableState.onMaximizedChange(e => {
|
||||||
if (e) {
|
if (e) {
|
||||||
this.maximizeTable(table.id);
|
this.maximizeTable(table.id);
|
||||||
} else {
|
} else {
|
||||||
this.minimizeTables();
|
this.minimizeTables();
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
this.tableDisposable.push(attachTableStyler(table, this.themeService));
|
this.tableDisposable.push(attachTableStyler(table, this.themeService));
|
||||||
|
|
||||||
tables.push(table);
|
tables.push(table);
|
||||||
@@ -237,11 +244,17 @@ export class GridPanel extends ViewletPanel {
|
|||||||
this.tables = this.tables.concat(tables);
|
this.tables = this.tables.concat(tables);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public clear() {
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
|
||||||
private reset() {
|
private reset() {
|
||||||
for (let i = this.splitView.length - 1; i >= 0; i--) {
|
for (let i = this.splitView.length - 1; i >= 0; i--) {
|
||||||
this.splitView.removeView(i);
|
this.splitView.removeView(i);
|
||||||
}
|
}
|
||||||
dispose(this.tables);
|
dispose(this.tables);
|
||||||
|
dispose(this.tableDisposable);
|
||||||
|
this.tableDisposable = [];
|
||||||
this.tables = [];
|
this.tables = [];
|
||||||
this.maximizedGrid = undefined;
|
this.maximizedGrid = undefined;
|
||||||
|
|
||||||
@@ -292,6 +305,15 @@ export class GridPanel extends ViewletPanel {
|
|||||||
public get state(): GridPanelState {
|
public get state(): GridPanelState {
|
||||||
return this._state;
|
return this._state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public dispose() {
|
||||||
|
dispose(this.queryRunnerDisposables);
|
||||||
|
dispose(this.tableDisposable);
|
||||||
|
dispose(this.tables);
|
||||||
|
this.tableDisposable = undefined;
|
||||||
|
this.tables = undefined;
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GridTable<T> extends Disposable implements IView {
|
class GridTable<T> extends Disposable implements IView {
|
||||||
@@ -443,9 +465,9 @@ class GridTable<T> extends Disposable implements IView {
|
|||||||
|
|
||||||
private setupState() {
|
private setupState() {
|
||||||
// change actionbar on maximize change
|
// change actionbar on maximize change
|
||||||
this.state.onMaximizedChange(this.rebuildActionBar, this);
|
this._register(this.state.onMaximizedChange(this.rebuildActionBar, this));
|
||||||
|
|
||||||
this.state.onCanBeMaximizedChange(this.rebuildActionBar, this);
|
this._register(this.state.onCanBeMaximizedChange(this.rebuildActionBar, this));
|
||||||
|
|
||||||
if (this.state.scrollPosition) {
|
if (this.state.scrollPosition) {
|
||||||
// most of the time this won't do anything
|
// most of the time this won't do anything
|
||||||
@@ -655,6 +677,8 @@ class GridTable<T> extends Disposable implements IView {
|
|||||||
|
|
||||||
public dispose() {
|
public dispose() {
|
||||||
$(this.container).destroy();
|
$(this.container).destroy();
|
||||||
|
this.table.dispose();
|
||||||
|
this.actionBar.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
import 'vs/css!./media/messagePanel';
|
import 'vs/css!./media/messagePanel';
|
||||||
import { IMessagesActionContext, SelectAllMessagesAction, CopyMessagesAction } from './actions';
|
import { IMessagesActionContext, SelectAllMessagesAction, CopyMessagesAction } from './actions';
|
||||||
import QueryRunner from 'sql/parts/query/execution/queryRunner';
|
import QueryRunner from 'sql/parts/query/execution/queryRunner';
|
||||||
|
import { QueryInput } from 'sql/parts/query/common/queryInput';
|
||||||
|
|
||||||
import { IResultMessage, ISelectionData } from 'sqlops';
|
import { IResultMessage, ISelectionData } from 'sqlops';
|
||||||
|
|
||||||
@@ -28,8 +29,6 @@ import { $ } from 'vs/base/browser/builder';
|
|||||||
import { isArray, isUndefinedOrNull } from 'vs/base/common/types';
|
import { isArray, isUndefinedOrNull } from 'vs/base/common/types';
|
||||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||||
import { IEditor } from 'vs/editor/common/editorCommon';
|
|
||||||
import { QueryInput } from 'sql/parts/query/common/queryInput';
|
|
||||||
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||||
|
|
||||||
export interface IResultMessageIntern extends IResultMessage {
|
export interface IResultMessageIntern extends IResultMessage {
|
||||||
@@ -71,6 +70,10 @@ export class MessagePanelState {
|
|||||||
this.collapsed = !messagesOpenedSettings;
|
this.collapsed = !messagesOpenedSettings;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dispose() {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MessagePanel extends ViewletPanel {
|
export class MessagePanel extends ViewletPanel {
|
||||||
@@ -102,6 +105,7 @@ export class MessagePanel extends ViewletPanel {
|
|||||||
renderer: this.renderer,
|
renderer: this.renderer,
|
||||||
controller: this.controller
|
controller: this.controller
|
||||||
}, { keyboardSupport: false, horizontalScrollMode: ScrollbarVisibility.Auto });
|
}, { keyboardSupport: false, horizontalScrollMode: ScrollbarVisibility.Auto });
|
||||||
|
this.disposables.push(this.tree);
|
||||||
this.tree.onDidScroll(e => {
|
this.tree.onDidScroll(e => {
|
||||||
if (this.state) {
|
if (this.state) {
|
||||||
this.state.scrollPosition = this.tree.getScrollPosition();
|
this.state.scrollPosition = this.tree.getScrollPosition();
|
||||||
@@ -117,7 +121,7 @@ export class MessagePanel extends ViewletPanel {
|
|||||||
protected renderBody(container: HTMLElement): void {
|
protected renderBody(container: HTMLElement): void {
|
||||||
this.container.style.width = '100%';
|
this.container.style.width = '100%';
|
||||||
this.container.style.height = '100%';
|
this.container.style.height = '100%';
|
||||||
attachListStyler(this.tree, this.themeService);
|
this.disposables.push(attachListStyler(this.tree, this.themeService));
|
||||||
container.appendChild(this.container);
|
container.appendChild(this.container);
|
||||||
this.tree.setInput(this.model);
|
this.tree.setInput(this.model);
|
||||||
}
|
}
|
||||||
@@ -193,9 +197,19 @@ export class MessagePanel extends ViewletPanel {
|
|||||||
}
|
}
|
||||||
this.setExpanded(!this.state.collapsed);
|
this.setExpanded(!this.state.collapsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
public get state(): MessagePanelState {
|
public get state(): MessagePanelState {
|
||||||
return this._state;
|
return this._state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public clear() {
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public dispose() {
|
||||||
|
dispose(this.queryRunnerDisposables);
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MessageDataSource implements IDataSource {
|
class MessageDataSource implements IDataSource {
|
||||||
|
|||||||
@@ -478,11 +478,11 @@ export class QueryEditor extends BaseEditor {
|
|||||||
|
|
||||||
this.setTaskbarContent();
|
this.setTaskbarContent();
|
||||||
|
|
||||||
this._configurationService.onDidChangeConfiguration(e => {
|
this._toDispose.push(this._configurationService.onDidChangeConfiguration(e => {
|
||||||
if (e.affectedKeys.includes('workbench.enablePreviewFeatures')) {
|
if (e.affectedKeys.includes('workbench.enablePreviewFeatures')) {
|
||||||
this.setTaskbarContent();
|
this.setTaskbarContent();
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
private setTaskbarContent(): void {
|
private setTaskbarContent(): void {
|
||||||
|
|||||||
@@ -90,7 +90,6 @@ export class QueryResultsEditor extends BaseEditor {
|
|||||||
public static ID: string = 'workbench.editor.queryResultsEditor';
|
public static ID: string = 'workbench.editor.queryResultsEditor';
|
||||||
public static AngularSelectorString: string = 'slickgrid-container.slickgridContainer';
|
public static AngularSelectorString: string = 'slickgrid-container.slickgridContainer';
|
||||||
protected _rawOptions: BareResultsGridInfo;
|
protected _rawOptions: BareResultsGridInfo;
|
||||||
protected _input: QueryResultsInput;
|
|
||||||
|
|
||||||
private resultsView: QueryResultsView;
|
private resultsView: QueryResultsView;
|
||||||
private styleSheet = DOM.createStyleSheet();
|
private styleSheet = DOM.createStyleSheet();
|
||||||
@@ -104,17 +103,17 @@ export class QueryResultsEditor extends BaseEditor {
|
|||||||
) {
|
) {
|
||||||
super(QueryResultsEditor.ID, telemetryService, themeService);
|
super(QueryResultsEditor.ID, telemetryService, themeService);
|
||||||
this._rawOptions = BareResultsGridInfo.createFromRawSettings(this._configurationService.getValue('resultsGrid'), getZoomLevel());
|
this._rawOptions = BareResultsGridInfo.createFromRawSettings(this._configurationService.getValue('resultsGrid'), getZoomLevel());
|
||||||
this._configurationService.onDidChangeConfiguration(e => {
|
this._register(this._configurationService.onDidChangeConfiguration(e => {
|
||||||
if (e.affectsConfiguration('resultsGrid')) {
|
if (e.affectsConfiguration('resultsGrid')) {
|
||||||
this._rawOptions = BareResultsGridInfo.createFromRawSettings(this._configurationService.getValue('resultsGrid'), getZoomLevel());
|
this._rawOptions = BareResultsGridInfo.createFromRawSettings(this._configurationService.getValue('resultsGrid'), getZoomLevel());
|
||||||
this.applySettings();
|
this.applySettings();
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
this.applySettings();
|
this.applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
public get input(): QueryResultsInput {
|
public get input(): QueryResultsInput {
|
||||||
return this._input;
|
return this._input as QueryResultsInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
private applySettings() {
|
private applySettings() {
|
||||||
@@ -133,10 +132,16 @@ export class QueryResultsEditor extends BaseEditor {
|
|||||||
this.styleSheet.remove();
|
this.styleSheet.remove();
|
||||||
parent.appendChild(this.styleSheet);
|
parent.appendChild(this.styleSheet);
|
||||||
if (!this.resultsView) {
|
if (!this.resultsView) {
|
||||||
this.resultsView = new QueryResultsView(parent, this._instantiationService, this._queryModelService);
|
this.resultsView = this._register(new QueryResultsView(parent, this._instantiationService, this._queryModelService));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dispose() {
|
||||||
|
this.styleSheet.remove();
|
||||||
|
this.styleSheet = undefined;
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
layout(dimension: DOM.Dimension): void {
|
layout(dimension: DOM.Dimension): void {
|
||||||
this.resultsView.layout(dimension);
|
this.resultsView.layout(dimension);
|
||||||
}
|
}
|
||||||
@@ -147,6 +152,11 @@ export class QueryResultsEditor extends BaseEditor {
|
|||||||
return TPromise.wrap<void>(null);
|
return TPromise.wrap<void>(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearInput() {
|
||||||
|
this.resultsView.clearInput();
|
||||||
|
super.clearInput();
|
||||||
|
}
|
||||||
|
|
||||||
public chart(dataId: { batchId: number, resultId: number }) {
|
public chart(dataId: { batchId: number, resultId: number }) {
|
||||||
this.resultsView.chartData(dataId);
|
this.resultsView.chartData(dataId);
|
||||||
}
|
}
|
||||||
@@ -154,11 +164,4 @@ export class QueryResultsEditor extends BaseEditor {
|
|||||||
public showQueryPlan(xml: string) {
|
public showQueryPlan(xml: string) {
|
||||||
this.resultsView.showPlan(xml);
|
this.resultsView.showPlan(xml);
|
||||||
}
|
}
|
||||||
|
|
||||||
public dispose(): void {
|
|
||||||
super.dispose();
|
|
||||||
if (this.resultsView) {
|
|
||||||
this.resultsView.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,6 +111,15 @@ class ResultsView extends Disposable implements IPanelView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dispose() {
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public clear() {
|
||||||
|
this.gridPanel.clear();
|
||||||
|
this.messagePanel.clear();
|
||||||
|
}
|
||||||
|
|
||||||
remove(): void {
|
remove(): void {
|
||||||
this.container.remove();
|
this.container.remove();
|
||||||
}
|
}
|
||||||
@@ -151,6 +160,10 @@ class ResultsTab implements IPanelTab {
|
|||||||
public dispose() {
|
public dispose() {
|
||||||
dispose(this.view);
|
dispose(this.view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public clear() {
|
||||||
|
this.view.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class QueryResultsView extends Disposable {
|
export class QueryResultsView extends Disposable {
|
||||||
@@ -221,8 +234,11 @@ export class QueryResultsView extends Disposable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public dispose() {
|
clearInput() {
|
||||||
this._panelView.dispose();
|
this._input = undefined;
|
||||||
|
this.resultsTab.clear();
|
||||||
|
this.qpTab.clear();
|
||||||
|
this.chartTab.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public get input(): QueryResultsInput {
|
public get input(): QueryResultsInput {
|
||||||
@@ -264,4 +280,8 @@ export class QueryResultsView extends Disposable {
|
|||||||
this._panelView.removeTab(this.qpTab.identifier);
|
this._panelView.removeTab(this.qpTab.identifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public dispose() {
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ export interface IQueryModelService {
|
|||||||
getConfig(): Promise<{ [key: string]: any }>;
|
getConfig(): Promise<{ [key: string]: any }>;
|
||||||
getShortcuts(): Promise<any>;
|
getShortcuts(): Promise<any>;
|
||||||
getQueryRows(uri: string, rowStart: number, numberOfRows: number, batchId: number, resultId: number): Thenable<ResultSetSubset>;
|
getQueryRows(uri: string, rowStart: number, numberOfRows: number, batchId: number, resultId: number): Thenable<ResultSetSubset>;
|
||||||
runQuery(uri: string, selection: ISelectionData, title: string, queryInput: QueryInput, runOptions?: ExecutionPlanOptions): void;
|
runQuery(uri: string, selection: ISelectionData, queryInput: QueryInput, runOptions?: ExecutionPlanOptions): void;
|
||||||
runQueryStatement(uri: string, selection: ISelectionData, title: string, queryInput: QueryInput): void;
|
runQueryStatement(uri: string, selection: ISelectionData, queryInput: QueryInput): void;
|
||||||
runQueryString(uri: string, selection: string, title: string, queryInput: QueryInput);
|
runQueryString(uri: string, selection: string, queryInput: QueryInput);
|
||||||
cancelQuery(input: QueryRunner | string): void;
|
cancelQuery(input: QueryRunner | string): void;
|
||||||
disposeQuery(uri: string): void;
|
disposeQuery(uri: string): void;
|
||||||
isRunningQuery(uri: string): boolean;
|
isRunningQuery(uri: string): boolean;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import { QueryInput } from 'sql/parts/query/common/queryInput';
|
|||||||
import { QueryStatusbarItem } from 'sql/parts/query/execution/queryStatus';
|
import { QueryStatusbarItem } from 'sql/parts/query/execution/queryStatus';
|
||||||
import { SqlFlavorStatusbarItem } from 'sql/parts/query/common/flavorStatus';
|
import { SqlFlavorStatusbarItem } from 'sql/parts/query/common/flavorStatus';
|
||||||
import { RowCountStatusBarItem } from 'sql/parts/query/common/rowCountStatus';
|
import { RowCountStatusBarItem } from 'sql/parts/query/common/rowCountStatus';
|
||||||
|
import { TimeElapsedStatusBarItem } from 'sql/parts/query/common/timeElapsedStatus';
|
||||||
|
|
||||||
import * as sqlops from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
|
|
||||||
@@ -86,6 +87,12 @@ export class QueryModelService implements IQueryModelService {
|
|||||||
|
|
||||||
// Register Statusbar items
|
// Register Statusbar items
|
||||||
|
|
||||||
|
(<statusbar.IStatusbarRegistry>platform.Registry.as(statusbar.Extensions.Statusbar)).registerStatusbarItem(new statusbar.StatusbarItemDescriptor(
|
||||||
|
TimeElapsedStatusBarItem,
|
||||||
|
statusbar.StatusbarAlignment.RIGHT,
|
||||||
|
100 /* Should appear to the right of the SQL editor status */
|
||||||
|
));
|
||||||
|
|
||||||
(<statusbar.IStatusbarRegistry>platform.Registry.as(statusbar.Extensions.Statusbar)).registerStatusbarItem(new statusbar.StatusbarItemDescriptor(
|
(<statusbar.IStatusbarRegistry>platform.Registry.as(statusbar.Extensions.Statusbar)).registerStatusbarItem(new statusbar.StatusbarItemDescriptor(
|
||||||
RowCountStatusBarItem,
|
RowCountStatusBarItem,
|
||||||
statusbar.StatusbarAlignment.RIGHT,
|
statusbar.StatusbarAlignment.RIGHT,
|
||||||
@@ -202,32 +209,28 @@ export class QueryModelService implements IQueryModelService {
|
|||||||
/**
|
/**
|
||||||
* Run a query for the given URI with the given text selection
|
* Run a query for the given URI with the given text selection
|
||||||
*/
|
*/
|
||||||
public runQuery(uri: string, selection: sqlops.ISelectionData,
|
public runQuery(uri: string, selection: sqlops.ISelectionData, queryInput: QueryInput, runOptions?: sqlops.ExecutionPlanOptions): void {
|
||||||
title: string, queryInput: QueryInput, runOptions?: sqlops.ExecutionPlanOptions): void {
|
this.doRunQuery(uri, selection, queryInput, false, runOptions);
|
||||||
this.doRunQuery(uri, selection, title, queryInput, false, runOptions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run the current SQL statement for the given URI
|
* Run the current SQL statement for the given URI
|
||||||
*/
|
*/
|
||||||
public runQueryStatement(uri: string, selection: sqlops.ISelectionData,
|
public runQueryStatement(uri: string, selection: sqlops.ISelectionData, queryInput: QueryInput): void {
|
||||||
title: string, queryInput: QueryInput): void {
|
this.doRunQuery(uri, selection, queryInput, true);
|
||||||
this.doRunQuery(uri, selection, title, queryInput, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run the current SQL statement for the given URI
|
* Run the current SQL statement for the given URI
|
||||||
*/
|
*/
|
||||||
public runQueryString(uri: string, selection: string,
|
public runQueryString(uri: string, selection: string, queryInput: QueryInput): void {
|
||||||
title: string, queryInput: QueryInput): void {
|
this.doRunQuery(uri, selection, queryInput, true);
|
||||||
this.doRunQuery(uri, selection, title, queryInput, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run Query implementation
|
* Run Query implementation
|
||||||
*/
|
*/
|
||||||
private doRunQuery(uri: string, selection: sqlops.ISelectionData | string,
|
private doRunQuery(uri: string, selection: sqlops.ISelectionData | string, queryInput: QueryInput,
|
||||||
title: string, queryInput: QueryInput,
|
|
||||||
runCurrentStatement: boolean, runOptions?: sqlops.ExecutionPlanOptions): void {
|
runCurrentStatement: boolean, runOptions?: sqlops.ExecutionPlanOptions): void {
|
||||||
// Reuse existing query runner if it exists
|
// Reuse existing query runner if it exists
|
||||||
let queryRunner: QueryRunner;
|
let queryRunner: QueryRunner;
|
||||||
@@ -249,7 +252,7 @@ export class QueryModelService implements IQueryModelService {
|
|||||||
} else {
|
} else {
|
||||||
// We do not have a query runner for this editor, so create a new one
|
// We do not have a query runner for this editor, so create a new one
|
||||||
// and map it to the results uri
|
// and map it to the results uri
|
||||||
info = this.initQueryRunner(uri, title);
|
info = this.initQueryRunner(uri);
|
||||||
queryRunner = info.queryRunner;
|
queryRunner = info.queryRunner;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,8 +273,8 @@ export class QueryModelService implements IQueryModelService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private initQueryRunner(uri: string, title: string): QueryInfo {
|
private initQueryRunner(uri: string): QueryInfo {
|
||||||
let queryRunner = this._instantiationService.createInstance(QueryRunner, uri, title);
|
let queryRunner = this._instantiationService.createInstance(QueryRunner, uri);
|
||||||
let info = new QueryInfo();
|
let info = new QueryInfo();
|
||||||
queryRunner.addListener(QREvents.RESULT_SET, e => {
|
queryRunner.addListener(QREvents.RESULT_SET, e => {
|
||||||
this._fireQueryEvent(uri, 'resultSet', e);
|
this._fireQueryEvent(uri, 'resultSet', e);
|
||||||
@@ -352,10 +355,14 @@ export class QueryModelService implements IQueryModelService {
|
|||||||
|
|
||||||
public disposeQuery(ownerUri: string): void {
|
public disposeQuery(ownerUri: string): void {
|
||||||
// Get existing query runner
|
// Get existing query runner
|
||||||
let queryRunner = this.getQueryRunner(ownerUri);
|
let queryRunner = this.internalGetQueryRunner(ownerUri);
|
||||||
if (queryRunner) {
|
if (queryRunner) {
|
||||||
queryRunner.disposeQuery();
|
queryRunner.disposeQuery();
|
||||||
}
|
}
|
||||||
|
// remove our info map
|
||||||
|
if (this._queryInfoMap.has(ownerUri)) {
|
||||||
|
this._queryInfoMap.delete(ownerUri);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EDIT DATA METHODS /////////////////////////////////////////////////////
|
// EDIT DATA METHODS /////////////////////////////////////////////////////
|
||||||
@@ -379,7 +386,7 @@ export class QueryModelService implements IQueryModelService {
|
|||||||
|
|
||||||
// We do not have a query runner for this editor, so create a new one
|
// We do not have a query runner for this editor, so create a new one
|
||||||
// and map it to the results uri
|
// and map it to the results uri
|
||||||
queryRunner = this._instantiationService.createInstance(QueryRunner, ownerUri, ownerUri);
|
queryRunner = this._instantiationService.createInstance(QueryRunner, ownerUri);
|
||||||
queryRunner.addListener(QREvents.RESULT_SET, resultSet => {
|
queryRunner.addListener(QREvents.RESULT_SET, resultSet => {
|
||||||
this._fireQueryEvent(ownerUri, 'resultSet', resultSet);
|
this._fireQueryEvent(ownerUri, 'resultSet', resultSet);
|
||||||
});
|
});
|
||||||
@@ -444,7 +451,7 @@ export class QueryModelService implements IQueryModelService {
|
|||||||
|
|
||||||
public disposeEdit(ownerUri: string): Thenable<void> {
|
public disposeEdit(ownerUri: string): Thenable<void> {
|
||||||
// Get existing query runner
|
// Get existing query runner
|
||||||
let queryRunner = this.getQueryRunner(ownerUri);
|
let queryRunner = this.internalGetQueryRunner(ownerUri);
|
||||||
if (queryRunner) {
|
if (queryRunner) {
|
||||||
return queryRunner.disposeEdit(ownerUri);
|
return queryRunner.disposeEdit(ownerUri);
|
||||||
}
|
}
|
||||||
@@ -453,7 +460,7 @@ export class QueryModelService implements IQueryModelService {
|
|||||||
|
|
||||||
public updateCell(ownerUri: string, rowId: number, columnId: number, newValue: string): Thenable<sqlops.EditUpdateCellResult> {
|
public updateCell(ownerUri: string, rowId: number, columnId: number, newValue: string): Thenable<sqlops.EditUpdateCellResult> {
|
||||||
// Get existing query runner
|
// Get existing query runner
|
||||||
let queryRunner = this.getQueryRunner(ownerUri);
|
let queryRunner = this.internalGetQueryRunner(ownerUri);
|
||||||
if (queryRunner) {
|
if (queryRunner) {
|
||||||
return queryRunner.updateCell(ownerUri, rowId, columnId, newValue).then((result) => result, error => {
|
return queryRunner.updateCell(ownerUri, rowId, columnId, newValue).then((result) => result, error => {
|
||||||
this._notificationService.notify({
|
this._notificationService.notify({
|
||||||
@@ -468,7 +475,7 @@ export class QueryModelService implements IQueryModelService {
|
|||||||
|
|
||||||
public commitEdit(ownerUri): Thenable<void> {
|
public commitEdit(ownerUri): Thenable<void> {
|
||||||
// Get existing query runner
|
// Get existing query runner
|
||||||
let queryRunner = this.getQueryRunner(ownerUri);
|
let queryRunner = this.internalGetQueryRunner(ownerUri);
|
||||||
if (queryRunner) {
|
if (queryRunner) {
|
||||||
return queryRunner.commitEdit(ownerUri).then(() => { }, error => {
|
return queryRunner.commitEdit(ownerUri).then(() => { }, error => {
|
||||||
this._notificationService.notify({
|
this._notificationService.notify({
|
||||||
@@ -483,7 +490,7 @@ export class QueryModelService implements IQueryModelService {
|
|||||||
|
|
||||||
public createRow(ownerUri: string): Thenable<sqlops.EditCreateRowResult> {
|
public createRow(ownerUri: string): Thenable<sqlops.EditCreateRowResult> {
|
||||||
// Get existing query runner
|
// Get existing query runner
|
||||||
let queryRunner = this.getQueryRunner(ownerUri);
|
let queryRunner = this.internalGetQueryRunner(ownerUri);
|
||||||
if (queryRunner) {
|
if (queryRunner) {
|
||||||
return queryRunner.createRow(ownerUri);
|
return queryRunner.createRow(ownerUri);
|
||||||
}
|
}
|
||||||
@@ -492,7 +499,7 @@ export class QueryModelService implements IQueryModelService {
|
|||||||
|
|
||||||
public deleteRow(ownerUri: string, rowId: number): Thenable<void> {
|
public deleteRow(ownerUri: string, rowId: number): Thenable<void> {
|
||||||
// Get existing query runner
|
// Get existing query runner
|
||||||
let queryRunner = this.getQueryRunner(ownerUri);
|
let queryRunner = this.internalGetQueryRunner(ownerUri);
|
||||||
if (queryRunner) {
|
if (queryRunner) {
|
||||||
return queryRunner.deleteRow(ownerUri, rowId);
|
return queryRunner.deleteRow(ownerUri, rowId);
|
||||||
}
|
}
|
||||||
@@ -501,7 +508,7 @@ export class QueryModelService implements IQueryModelService {
|
|||||||
|
|
||||||
public revertCell(ownerUri: string, rowId: number, columnId: number): Thenable<sqlops.EditRevertCellResult> {
|
public revertCell(ownerUri: string, rowId: number, columnId: number): Thenable<sqlops.EditRevertCellResult> {
|
||||||
// Get existing query runner
|
// Get existing query runner
|
||||||
let queryRunner = this.getQueryRunner(ownerUri);
|
let queryRunner = this.internalGetQueryRunner(ownerUri);
|
||||||
if (queryRunner) {
|
if (queryRunner) {
|
||||||
return queryRunner.revertCell(ownerUri, rowId, columnId);
|
return queryRunner.revertCell(ownerUri, rowId, columnId);
|
||||||
}
|
}
|
||||||
@@ -510,16 +517,25 @@ export class QueryModelService implements IQueryModelService {
|
|||||||
|
|
||||||
public revertRow(ownerUri: string, rowId: number): Thenable<void> {
|
public revertRow(ownerUri: string, rowId: number): Thenable<void> {
|
||||||
// Get existing query runner
|
// Get existing query runner
|
||||||
let queryRunner = this.getQueryRunner(ownerUri);
|
let queryRunner = this.internalGetQueryRunner(ownerUri);
|
||||||
if (queryRunner) {
|
if (queryRunner) {
|
||||||
return queryRunner.revertRow(ownerUri, rowId);
|
return queryRunner.revertRow(ownerUri, rowId);
|
||||||
}
|
}
|
||||||
return TPromise.as(null);
|
return TPromise.as(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getQueryRunner(ownerUri): QueryRunner {
|
||||||
|
let queryRunner: QueryRunner = undefined;
|
||||||
|
if (this._queryInfoMap.has(ownerUri)) {
|
||||||
|
queryRunner = this._getQueryInfo(ownerUri).queryRunner;
|
||||||
|
}
|
||||||
|
// return undefined if not found or is already executing
|
||||||
|
return queryRunner;
|
||||||
|
}
|
||||||
|
|
||||||
// PRIVATE METHODS //////////////////////////////////////////////////////
|
// PRIVATE METHODS //////////////////////////////////////////////////////
|
||||||
|
|
||||||
public getQueryRunner(ownerUri): QueryRunner {
|
private internalGetQueryRunner(ownerUri): QueryRunner {
|
||||||
let queryRunner: QueryRunner = undefined;
|
let queryRunner: QueryRunner = undefined;
|
||||||
if (this._queryInfoMap.has(ownerUri)) {
|
if (this._queryInfoMap.has(ownerUri)) {
|
||||||
let existingRunner = this._getQueryInfo(ownerUri).queryRunner;
|
let existingRunner = this._getQueryInfo(ownerUri).queryRunner;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import * as nls from 'vs/nls';
|
|||||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||||
import * as types from 'vs/base/common/types';
|
import * as types from 'vs/base/common/types';
|
||||||
import { EventEmitter } from 'sql/base/common/eventEmitter';
|
import { EventEmitter } from 'sql/base/common/eventEmitter';
|
||||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||||
import { Emitter, Event } from 'vs/base/common/event';
|
import { Emitter, Event } from 'vs/base/common/event';
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
@@ -62,7 +62,7 @@ export interface IGridMessage extends sqlops.IResultMessage {
|
|||||||
* Query Runner class which handles running a query, reports the results to the content manager,
|
* Query Runner class which handles running a query, reports the results to the content manager,
|
||||||
* and handles getting more rows from the service layer and disposing when the content is closed.
|
* and handles getting more rows from the service layer and disposing when the content is closed.
|
||||||
*/
|
*/
|
||||||
export default class QueryRunner {
|
export default class QueryRunner extends Disposable {
|
||||||
// MEMBER VARIABLES ////////////////////////////////////////////////////
|
// MEMBER VARIABLES ////////////////////////////////////////////////////
|
||||||
private _resultLineOffset: number;
|
private _resultLineOffset: number;
|
||||||
private _totalElapsedMilliseconds: number = 0;
|
private _totalElapsedMilliseconds: number = 0;
|
||||||
@@ -76,7 +76,7 @@ export default class QueryRunner {
|
|||||||
private _planXml = new Deferred<string>();
|
private _planXml = new Deferred<string>();
|
||||||
public get planXml(): Thenable<string> { return this._planXml.promise; }
|
public get planXml(): Thenable<string> { return this._planXml.promise; }
|
||||||
|
|
||||||
private _onMessage = new Emitter<sqlops.IResultMessage>();
|
private _onMessage = this._register(new Emitter<sqlops.IResultMessage>());
|
||||||
private _debouncedMessage = debounceEvent<sqlops.IResultMessage, sqlops.IResultMessage[]>(this._onMessage.event, (l, e) => {
|
private _debouncedMessage = debounceEvent<sqlops.IResultMessage, sqlops.IResultMessage[]>(this._onMessage.event, (l, e) => {
|
||||||
// on first run
|
// on first run
|
||||||
if (types.isUndefinedOrNull(l)) {
|
if (types.isUndefinedOrNull(l)) {
|
||||||
@@ -88,7 +88,7 @@ export default class QueryRunner {
|
|||||||
private _echoedMessages = echo(this._debouncedMessage.event);
|
private _echoedMessages = echo(this._debouncedMessage.event);
|
||||||
public readonly onMessage = this._echoedMessages.event;
|
public readonly onMessage = this._echoedMessages.event;
|
||||||
|
|
||||||
private _onResultSet = new Emitter<sqlops.ResultSetSummary>();
|
private _onResultSet = this._register(new Emitter<sqlops.ResultSetSummary>());
|
||||||
private _debouncedResultSet = debounceEvent<sqlops.ResultSetSummary, sqlops.ResultSetSummary[]>(this._onResultSet.event, (l, e) => {
|
private _debouncedResultSet = debounceEvent<sqlops.ResultSetSummary, sqlops.ResultSetSummary[]>(this._onResultSet.event, (l, e) => {
|
||||||
// on first run
|
// on first run
|
||||||
if (types.isUndefinedOrNull(l)) {
|
if (types.isUndefinedOrNull(l)) {
|
||||||
@@ -100,28 +100,38 @@ export default class QueryRunner {
|
|||||||
private _echoedResultSet = echo(this._debouncedResultSet.event);
|
private _echoedResultSet = echo(this._debouncedResultSet.event);
|
||||||
public readonly onResultSet = this._echoedResultSet.event;
|
public readonly onResultSet = this._echoedResultSet.event;
|
||||||
|
|
||||||
private _onQueryStart = new Emitter<void>();
|
private _onQueryStart = this._register(new Emitter<void>());
|
||||||
public readonly onQueryStart: Event<void> = this._onQueryStart.event;
|
public readonly onQueryStart: Event<void> = this._onQueryStart.event;
|
||||||
|
|
||||||
private _onQueryEnd = new Emitter<string>();
|
private _onQueryEnd = this._register(new Emitter<string>());
|
||||||
public readonly onQueryEnd: Event<string> = this._onQueryEnd.event;
|
public readonly onQueryEnd: Event<string> = this._onQueryEnd.event;
|
||||||
|
|
||||||
private _onBatchStart = new Emitter<sqlops.BatchSummary>();
|
private _onBatchStart = this._register(new Emitter<sqlops.BatchSummary>());
|
||||||
public readonly onBatchStart: Event<sqlops.BatchSummary> = this._onBatchStart.event;
|
public readonly onBatchStart: Event<sqlops.BatchSummary> = this._onBatchStart.event;
|
||||||
|
|
||||||
private _onBatchEnd = new Emitter<sqlops.BatchSummary>();
|
private _onBatchEnd = this._register(new Emitter<sqlops.BatchSummary>());
|
||||||
public readonly onBatchEnd: Event<sqlops.BatchSummary> = this._onBatchEnd.event;
|
public readonly onBatchEnd: Event<sqlops.BatchSummary> = this._onBatchEnd.event;
|
||||||
|
|
||||||
|
private _queryStartTime: Date;
|
||||||
|
public get queryStartTime(): Date {
|
||||||
|
return this._queryStartTime;
|
||||||
|
}
|
||||||
|
private _queryEndTime: Date;
|
||||||
|
public get queryEndTime(): Date {
|
||||||
|
return this._queryEndTime;
|
||||||
|
}
|
||||||
|
|
||||||
// CONSTRUCTOR /////////////////////////////////////////////////////////
|
// CONSTRUCTOR /////////////////////////////////////////////////////////
|
||||||
constructor(
|
constructor(
|
||||||
public uri: string,
|
public uri: string,
|
||||||
public title: string,
|
|
||||||
@IQueryManagementService private _queryManagementService: IQueryManagementService,
|
@IQueryManagementService private _queryManagementService: IQueryManagementService,
|
||||||
@INotificationService private _notificationService: INotificationService,
|
@INotificationService private _notificationService: INotificationService,
|
||||||
@IWorkspaceConfigurationService private _workspaceConfigurationService: IWorkspaceConfigurationService,
|
@IWorkspaceConfigurationService private _workspaceConfigurationService: IWorkspaceConfigurationService,
|
||||||
@IClipboardService private _clipboardService: IClipboardService,
|
@IClipboardService private _clipboardService: IClipboardService,
|
||||||
@IInstantiationService private instantiationService: IInstantiationService
|
@IInstantiationService private instantiationService: IInstantiationService
|
||||||
) { }
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
get isExecuting(): boolean {
|
get isExecuting(): boolean {
|
||||||
return this._isExecuting;
|
return this._isExecuting;
|
||||||
@@ -185,9 +195,10 @@ export default class QueryRunner {
|
|||||||
this._debouncedMessage.clear();
|
this._debouncedMessage.clear();
|
||||||
this._debouncedResultSet.clear();
|
this._debouncedResultSet.clear();
|
||||||
this._planXml = new Deferred<string>();
|
this._planXml = new Deferred<string>();
|
||||||
let ownerUri = this.uri;
|
|
||||||
this._batchSets = [];
|
this._batchSets = [];
|
||||||
this._hasCompleted = false;
|
this._hasCompleted = false;
|
||||||
|
this._queryStartTime = undefined;
|
||||||
|
this._queryEndTime = undefined;
|
||||||
if (types.isObject(input) || types.isUndefinedOrNull(input)) {
|
if (types.isObject(input) || types.isUndefinedOrNull(input)) {
|
||||||
// Update internal state to show that we're executing the query
|
// Update internal state to show that we're executing the query
|
||||||
this._resultLineOffset = input ? input.startLine : 0;
|
this._resultLineOffset = input ? input.startLine : 0;
|
||||||
@@ -203,20 +214,22 @@ export default class QueryRunner {
|
|||||||
|
|
||||||
// Send the request to execute the query
|
// Send the request to execute the query
|
||||||
return runCurrentStatement
|
return runCurrentStatement
|
||||||
? this._queryManagementService.runQueryStatement(ownerUri, input.startLine, input.startColumn).then(() => this.handleSuccessRunQueryResult(), e => this.handleFailureRunQueryResult(e))
|
? this._queryManagementService.runQueryStatement(this.uri, input.startLine, input.startColumn).then(() => this.handleSuccessRunQueryResult(), e => this.handleFailureRunQueryResult(e))
|
||||||
: this._queryManagementService.runQuery(ownerUri, input, runOptions).then(() => this.handleSuccessRunQueryResult(), e => this.handleFailureRunQueryResult(e));
|
: this._queryManagementService.runQuery(this.uri, input, runOptions).then(() => this.handleSuccessRunQueryResult(), e => this.handleFailureRunQueryResult(e));
|
||||||
} else if (types.isString(input)) {
|
} else if (types.isString(input)) {
|
||||||
// Update internal state to show that we're executing the query
|
// Update internal state to show that we're executing the query
|
||||||
this._isExecuting = true;
|
this._isExecuting = true;
|
||||||
this._totalElapsedMilliseconds = 0;
|
this._totalElapsedMilliseconds = 0;
|
||||||
|
|
||||||
return this._queryManagementService.runQueryString(ownerUri, input).then(() => this.handleSuccessRunQueryResult(), e => this.handleFailureRunQueryResult(e));
|
return this._queryManagementService.runQueryString(this.uri, input).then(() => this.handleSuccessRunQueryResult(), e => this.handleFailureRunQueryResult(e));
|
||||||
} else {
|
} else {
|
||||||
return Promise.reject('Unknown input');
|
return Promise.reject('Unknown input');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleSuccessRunQueryResult() {
|
private handleSuccessRunQueryResult() {
|
||||||
|
// this isn't exact, but its the best we can do
|
||||||
|
this._queryStartTime = new Date();
|
||||||
// The query has started, so lets fire up the result pane
|
// The query has started, so lets fire up the result pane
|
||||||
this._onQueryStart.fire();
|
this._onQueryStart.fire();
|
||||||
this._eventEmitter.emit(EventType.START);
|
this._eventEmitter.emit(EventType.START);
|
||||||
@@ -241,6 +254,8 @@ export default class QueryRunner {
|
|||||||
* Handle a QueryComplete from the service layer
|
* Handle a QueryComplete from the service layer
|
||||||
*/
|
*/
|
||||||
public handleQueryComplete(result: sqlops.QueryExecuteCompleteNotificationResult): void {
|
public handleQueryComplete(result: sqlops.QueryExecuteCompleteNotificationResult): void {
|
||||||
|
// this also isn't exact but its the best we can do
|
||||||
|
this._queryEndTime = new Date();
|
||||||
|
|
||||||
// Store the batch sets we got back as a source of "truth"
|
// Store the batch sets we got back as a source of "truth"
|
||||||
this._isExecuting = false;
|
this._isExecuting = false;
|
||||||
@@ -490,10 +505,16 @@ export default class QueryRunner {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Disposes the Query from the service client
|
* Disposes the Query from the service client
|
||||||
* @returns A promise that will be rejected if a problem occured
|
|
||||||
*/
|
*/
|
||||||
public disposeQuery(): void {
|
public disposeQuery(): void {
|
||||||
this._queryManagementService.disposeQuery(this.uri);
|
this._queryManagementService.disposeQuery(this.uri).then(() => {
|
||||||
|
this.dispose();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public dispose() {
|
||||||
|
this._batchSets = undefined;
|
||||||
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
get totalElapsedMilliseconds(): number {
|
get totalElapsedMilliseconds(): number {
|
||||||
|
|||||||
@@ -152,12 +152,6 @@ export class QueryEditorService implements IQueryEditorService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears any QueryEditor data for the given URI held by this service
|
|
||||||
*/
|
|
||||||
public onQueryInputClosed(uri: string): void {
|
|
||||||
}
|
|
||||||
|
|
||||||
onSaveAsCompleted(oldResource: URI, newResource: URI): void {
|
onSaveAsCompleted(oldResource: URI, newResource: URI): void {
|
||||||
let oldResourceString: string = oldResource.toString();
|
let oldResourceString: string = oldResource.toString();
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ import { dispose, Disposable } from 'vs/base/common/lifecycle';
|
|||||||
|
|
||||||
export class QueryPlanState {
|
export class QueryPlanState {
|
||||||
xml: string;
|
xml: string;
|
||||||
|
dispose() {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class QueryPlanTab implements IPanelTab {
|
export class QueryPlanTab implements IPanelTab {
|
||||||
@@ -29,6 +32,10 @@ export class QueryPlanTab implements IPanelTab {
|
|||||||
public dispose() {
|
public dispose() {
|
||||||
dispose(this.view);
|
dispose(this.view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public clear() {
|
||||||
|
this.view.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class QueryPlanView implements IPanelView {
|
export class QueryPlanView implements IPanelView {
|
||||||
@@ -59,6 +66,12 @@ export class QueryPlanView implements IPanelView {
|
|||||||
this.container.style.height = dimension.height + 'px';
|
this.container.style.height = dimension.height + 'px';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public clear() {
|
||||||
|
if (this.qp) {
|
||||||
|
this.qp.xml = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public showPlan(xml: string) {
|
public showPlan(xml: string) {
|
||||||
if (this.qp) {
|
if (this.qp) {
|
||||||
this.qp.xml = xml;
|
this.qp.xml = xml;
|
||||||
@@ -93,6 +106,10 @@ export class QueryPlan {
|
|||||||
QP.showPlan(this.container, this._xml, {
|
QP.showPlan(this.container, this._xml, {
|
||||||
jsTooltips: false
|
jsTooltips: false
|
||||||
});
|
});
|
||||||
|
(<any>this.container.querySelectorAll('div.qp-tt')).forEach(toolTip=>{
|
||||||
|
toolTip.classList.add('monaco-editor');
|
||||||
|
toolTip.classList.add('monaco-editor-hover');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public get xml(): string {
|
public get xml(): string {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import { attachButtonStyler, attachModalDialogStyler } from 'sql/common/theme/st
|
|||||||
import { Builder } from 'vs/base/browser/builder';
|
import { Builder } from 'vs/base/browser/builder';
|
||||||
import Severity from 'vs/base/common/severity';
|
import Severity from 'vs/base/common/severity';
|
||||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||||
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
|
import { SIDE_BAR_BACKGROUND, SIDE_BAR_FOREGROUND } from 'vs/workbench/common/theme';
|
||||||
import { IPartService } from 'vs/workbench/services/part/common/partService';
|
import { IPartService } from 'vs/workbench/services/part/common/partService';
|
||||||
import { Event, Emitter } from 'vs/base/common/event';
|
import { Event, Emitter } from 'vs/base/common/event';
|
||||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||||
@@ -76,7 +76,7 @@ export class ErrorMessageDialog extends Modal {
|
|||||||
this._copyButton = this.addFooterButton(copyButtonLabel, () => this._clipboardService.writeText(this._messageDetails), 'left');
|
this._copyButton = this.addFooterButton(copyButtonLabel, () => this._clipboardService.writeText(this._messageDetails), 'left');
|
||||||
this._copyButton.icon = 'icon scriptToClipboard';
|
this._copyButton.icon = 'icon scriptToClipboard';
|
||||||
this._copyButton.element.title = copyButtonLabel;
|
this._copyButton.element.title = copyButtonLabel;
|
||||||
this._register(attachButtonStyler(this._copyButton, this._themeService, { buttonBackground: SIDE_BAR_BACKGROUND, buttonHoverBackground: SIDE_BAR_BACKGROUND }));
|
this._register(attachButtonStyler(this._copyButton, this._themeService, { buttonBackground: SIDE_BAR_BACKGROUND, buttonHoverBackground: SIDE_BAR_BACKGROUND, buttonForeground: SIDE_BAR_FOREGROUND }));
|
||||||
}
|
}
|
||||||
|
|
||||||
private createStandardButton(label: string, onSelect: () => void): Button {
|
private createStandardButton(label: string, onSelect: () => void): Button {
|
||||||
|
|||||||
176
src/sqltest/parts/commandLine/commandLineService.test.ts
Normal file
176
src/sqltest/parts/commandLine/commandLineService.test.ts
Normal 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 Constants from 'sql/parts/connection/common/constants';
|
||||||
|
import * as Utils from 'sql/parts/connection/common/utils';
|
||||||
|
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
||||||
|
import * as sqlops from 'sqlops';
|
||||||
|
|
||||||
|
import { TPromise } from 'vs/base/common/winjs.base';
|
||||||
|
import * as assert from 'assert';
|
||||||
|
import * as TypeMoq from 'typemoq';
|
||||||
|
|
||||||
|
import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
|
||||||
|
import { CommandLineService } from 'sql/parts/commandLine/common/commandLineService';
|
||||||
|
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
|
||||||
|
import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment';
|
||||||
|
import { CapabilitiesService, ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
|
||||||
|
import { CapabilitiesTestService } from 'sqltest/stubs/capabilitiesTestService';
|
||||||
|
import { QueryEditorService } from 'sql/parts/query/services/queryEditorService';
|
||||||
|
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||||
|
import { ObjectExplorerService } from 'sql/parts/objectExplorer/common/objectExplorerService';
|
||||||
|
import {
|
||||||
|
IConnectionManagementService, IConnectionDialogService, INewConnectionParams,
|
||||||
|
ConnectionType, IConnectableInput, IConnectionCompletionOptions, IConnectionCallbacks,
|
||||||
|
IConnectionParams, IConnectionResult, IServerGroupController, IServerGroupDialogCallbacks,
|
||||||
|
RunQueryOnConnectionMode
|
||||||
|
} from 'sql/parts/connection/common/connectionManagement';
|
||||||
|
import { ConnectionStore } from 'sql/parts/connection/common/connectionStore';
|
||||||
|
import { TestConnectionManagementService } from 'sqltest/stubs/connectionManagementService.test';
|
||||||
|
|
||||||
|
|
||||||
|
class TestParsedArgs implements ParsedArgs{
|
||||||
|
[arg: string]: any;
|
||||||
|
_: string[];
|
||||||
|
aad?: boolean;
|
||||||
|
add?: boolean;
|
||||||
|
database?:string;
|
||||||
|
debugBrkPluginHost?: string;
|
||||||
|
debugBrkSearch?: string;
|
||||||
|
debugId?: string;
|
||||||
|
debugPluginHost?: string;
|
||||||
|
debugSearch?: string;
|
||||||
|
diff?: boolean;
|
||||||
|
'disable-crash-reporter'?: string;
|
||||||
|
'disable-extension'?: string | string[];
|
||||||
|
'disable-extensions'?: boolean;
|
||||||
|
'disable-restore-windows'?: boolean;
|
||||||
|
'disable-telemetry'?: boolean;
|
||||||
|
'disable-updates'?: string;
|
||||||
|
'driver'?: string;
|
||||||
|
'enable-proposed-api'?: string | string[];
|
||||||
|
'export-default-configuration'?: string;
|
||||||
|
'extensions-dir'?: string;
|
||||||
|
extensionDevelopmentPath?: string;
|
||||||
|
extensionTestsPath?: string;
|
||||||
|
'file-chmod'?: boolean;
|
||||||
|
'file-write'?: boolean;
|
||||||
|
'folder-uri'?: string | string[];
|
||||||
|
goto?: boolean;
|
||||||
|
help?: boolean;
|
||||||
|
'install-extension'?: string | string[];
|
||||||
|
'install-source'?: string;
|
||||||
|
integrated?: boolean;
|
||||||
|
'list-extensions'?: boolean;
|
||||||
|
locale?: string;
|
||||||
|
log?: string;
|
||||||
|
logExtensionHostCommunication?: boolean;
|
||||||
|
'max-memory'?: number;
|
||||||
|
'new-window'?: boolean;
|
||||||
|
'open-url'?: boolean;
|
||||||
|
performance?: boolean;
|
||||||
|
'prof-append-timers'?: string;
|
||||||
|
'prof-startup'?: string;
|
||||||
|
'prof-startup-prefix'?: string;
|
||||||
|
'reuse-window'?: boolean;
|
||||||
|
server?: string;
|
||||||
|
'show-versions'?: boolean;
|
||||||
|
'skip-add-to-recently-opened'?: boolean;
|
||||||
|
'skip-getting-started'?: boolean;
|
||||||
|
'skip-release-notes'?: boolean;
|
||||||
|
status?: boolean;
|
||||||
|
'sticky-quickopen'?: boolean;
|
||||||
|
'uninstall-extension'?: string | string[];
|
||||||
|
'unity-launch'?: boolean; // Always open a new window, except if opening the first window or opening a file or folder as part of the launch.
|
||||||
|
'upload-logs'?: string;
|
||||||
|
user?: string;
|
||||||
|
'user-data-dir'?: string;
|
||||||
|
_urls?: string[];
|
||||||
|
verbose?: boolean;
|
||||||
|
version?: boolean;
|
||||||
|
wait?: boolean;
|
||||||
|
waitMarkerFilePath?: string;
|
||||||
|
}
|
||||||
|
suite('commandLineService tests', () => {
|
||||||
|
|
||||||
|
let capabilitiesService: CapabilitiesTestService;
|
||||||
|
let commandLineService : CommandLineService;
|
||||||
|
let environmentService : TypeMoq.Mock<EnvironmentService>;
|
||||||
|
let queryEditorService : TypeMoq.Mock<QueryEditorService>;
|
||||||
|
let editorService:TypeMoq.Mock<IEditorService>;
|
||||||
|
let objectExplorerService : TypeMoq.Mock<ObjectExplorerService>;
|
||||||
|
let connectionStore: TypeMoq.Mock<ConnectionStore>;
|
||||||
|
|
||||||
|
setup(() => {
|
||||||
|
capabilitiesService = new CapabilitiesTestService();
|
||||||
|
connectionStore = TypeMoq.Mock.ofType(ConnectionStore);
|
||||||
|
});
|
||||||
|
|
||||||
|
function getCommandLineService(connectionManagementService : IConnectionManagementService,
|
||||||
|
environmentService? : IEnvironmentService,
|
||||||
|
capabilitiesService? : ICapabilitiesService
|
||||||
|
) : CommandLineService
|
||||||
|
{
|
||||||
|
let service= new CommandLineService(
|
||||||
|
connectionManagementService,
|
||||||
|
capabilitiesService,
|
||||||
|
environmentService,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
return service;
|
||||||
|
}
|
||||||
|
|
||||||
|
test('processCommandLine shows connection dialog by default', done => {
|
||||||
|
const connectionManagementService : TypeMoq.Mock<IConnectionManagementService>
|
||||||
|
= TypeMoq.Mock.ofType<IConnectionManagementService>(TestConnectionManagementService, TypeMoq.MockBehavior.Strict);
|
||||||
|
|
||||||
|
connectionManagementService.setup((c) => c.showConnectionDialog()).verifiable();
|
||||||
|
connectionManagementService.setup(c => c.hasRegisteredServers()).returns(() => false);
|
||||||
|
connectionManagementService.setup(c => c.connectIfNotConnected(TypeMoq.It.isAny(), TypeMoq.It.isAny()))
|
||||||
|
.verifiable(TypeMoq.Times.never());
|
||||||
|
let service = getCommandLineService(connectionManagementService.object);
|
||||||
|
service.processCommandLine();
|
||||||
|
connectionManagementService.verifyAll();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('processCommandLine does nothing if registered servers exist and no server name is provided', done => {
|
||||||
|
const connectionManagementService : TypeMoq.Mock<IConnectionManagementService>
|
||||||
|
= TypeMoq.Mock.ofType<IConnectionManagementService>(TestConnectionManagementService, TypeMoq.MockBehavior.Strict);
|
||||||
|
|
||||||
|
connectionManagementService.setup((c) => c.showConnectionDialog()).verifiable(TypeMoq.Times.never());
|
||||||
|
connectionManagementService.setup(c => c.hasRegisteredServers()).returns(() => true);
|
||||||
|
connectionManagementService.setup(c => c.connectIfNotConnected(TypeMoq.It.isAny(), TypeMoq.It.isAny()))
|
||||||
|
.verifiable(TypeMoq.Times.never());
|
||||||
|
let service = getCommandLineService(connectionManagementService.object);
|
||||||
|
service.processCommandLine();
|
||||||
|
connectionManagementService.verifyAll();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('processCommandLine opens a new connection if a server name is passed', done => {
|
||||||
|
const connectionManagementService : TypeMoq.Mock<IConnectionManagementService>
|
||||||
|
= TypeMoq.Mock.ofType<IConnectionManagementService>(TestConnectionManagementService, TypeMoq.MockBehavior.Strict);
|
||||||
|
|
||||||
|
const environmentService : TypeMoq.Mock<IEnvironmentService> = TypeMoq.Mock.ofType<IEnvironmentService>(EnvironmentService);
|
||||||
|
const args : TestParsedArgs = new TestParsedArgs();
|
||||||
|
args.server = 'myserver';
|
||||||
|
args.database = 'mydatabase';
|
||||||
|
environmentService.setup(e => e.args).returns(() => args).verifiable(TypeMoq.Times.atLeastOnce());
|
||||||
|
connectionManagementService.setup((c) => c.showConnectionDialog()).verifiable(TypeMoq.Times.never());
|
||||||
|
connectionManagementService.setup(c => c.hasRegisteredServers()).returns(() => true).verifiable(TypeMoq.Times.atMostOnce());
|
||||||
|
connectionManagementService.setup(c => c.connectIfNotConnected(TypeMoq.It.isAny(), 'connection'))
|
||||||
|
.returns(() => new Promise<string>((resolve, reject) => { reject('unused');}))
|
||||||
|
.verifiable(TypeMoq.Times.once());
|
||||||
|
let service = getCommandLineService(connectionManagementService.object, environmentService.object, capabilitiesService);
|
||||||
|
service.processCommandLine();
|
||||||
|
environmentService.verifyAll();
|
||||||
|
connectionManagementService.verifyAll();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -141,6 +141,8 @@ suite('SQL QueryEditor Tests', () => {
|
|||||||
connectionManagementService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, memento.object, undefined);
|
connectionManagementService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, memento.object, undefined);
|
||||||
connectionManagementService.callBase = true;
|
connectionManagementService.callBase = true;
|
||||||
connectionManagementService.setup(x => x.isConnected(TypeMoq.It.isAny())).returns(() => false);
|
connectionManagementService.setup(x => x.isConnected(TypeMoq.It.isAny())).returns(() => false);
|
||||||
|
connectionManagementService.setup(x => x.disconnectEditor(TypeMoq.It.isAny())).returns(() => void 0);
|
||||||
|
connectionManagementService.setup(x => x.ensureDefaultLanguageFlavor(TypeMoq.It.isAnyString())).returns(() => void 0);
|
||||||
|
|
||||||
// Create a QueryModelService
|
// Create a QueryModelService
|
||||||
queryModelService = new QueryModelService(instantiationService.object, notificationService.object);
|
queryModelService = new QueryModelService(instantiationService.object, notificationService.object);
|
||||||
@@ -328,6 +330,9 @@ suite('SQL QueryEditor Tests', () => {
|
|||||||
queryConnectionService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, memento.object, undefined);
|
queryConnectionService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Loose, memento.object, undefined);
|
||||||
queryConnectionService.callBase = true;
|
queryConnectionService.callBase = true;
|
||||||
|
|
||||||
|
queryConnectionService.setup(x => x.disconnectEditor(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => void 0);
|
||||||
|
queryConnectionService.setup(x => x.ensureDefaultLanguageFlavor(TypeMoq.It.isAnyString())).returns(() => void 0);
|
||||||
|
|
||||||
// Mock InstantiationService to give us the actions
|
// Mock InstantiationService to give us the actions
|
||||||
queryActionInstantiationService = TypeMoq.Mock.ofType(InstantiationService, TypeMoq.MockBehavior.Loose);
|
queryActionInstantiationService = TypeMoq.Mock.ofType(InstantiationService, TypeMoq.MockBehavior.Loose);
|
||||||
|
|
||||||
@@ -354,12 +359,13 @@ suite('SQL QueryEditor Tests', () => {
|
|||||||
let fileInput = new UntitledEditorInput(URI.parse('testUri'), false, '', '', '', instantiationService.object, undefined, undefined, undefined);
|
let fileInput = new UntitledEditorInput(URI.parse('testUri'), false, '', '', '', instantiationService.object, undefined, undefined, undefined);
|
||||||
queryModelService = TypeMoq.Mock.ofType(QueryModelService, TypeMoq.MockBehavior.Loose, undefined, undefined);
|
queryModelService = TypeMoq.Mock.ofType(QueryModelService, TypeMoq.MockBehavior.Loose, undefined, undefined);
|
||||||
queryModelService.callBase = true;
|
queryModelService.callBase = true;
|
||||||
|
queryModelService.setup(x => x.disposeQuery(TypeMoq.It.isAny())).returns(() => void 0);
|
||||||
queryInput = new QueryInput(
|
queryInput = new QueryInput(
|
||||||
'',
|
'',
|
||||||
fileInput,
|
fileInput,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
connectionManagementService.object,
|
||||||
queryModelService.object,
|
queryModelService.object,
|
||||||
undefined,
|
undefined,
|
||||||
undefined
|
undefined
|
||||||
@@ -395,7 +401,7 @@ suite('SQL QueryEditor Tests', () => {
|
|||||||
test('Test that we attempt to dispose query when the queryInput is disposed', (done) => {
|
test('Test that we attempt to dispose query when the queryInput is disposed', (done) => {
|
||||||
let queryResultsInput = new QueryResultsInput('testUri', configurationService.object);
|
let queryResultsInput = new QueryResultsInput('testUri', configurationService.object);
|
||||||
queryInput['_results'] = queryResultsInput;
|
queryInput['_results'] = queryResultsInput;
|
||||||
queryInput.dispose();
|
queryInput.close();
|
||||||
queryModelService.verify(x => x.disposeQuery(TypeMoq.It.isAnyString()), TypeMoq.Times.once());
|
queryModelService.verify(x => x.disposeQuery(TypeMoq.It.isAnyString()), TypeMoq.Times.once());
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -62,6 +62,13 @@ export interface ParsedArgs {
|
|||||||
'upload-logs'?: string;
|
'upload-logs'?: string;
|
||||||
'driver'?: string;
|
'driver'?: string;
|
||||||
'driver-verbose'?: boolean;
|
'driver-verbose'?: boolean;
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
|
aad?: boolean;
|
||||||
|
database?: string;
|
||||||
|
integrated?: boolean;
|
||||||
|
server?: string;
|
||||||
|
user?: string;
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const IEnvironmentService = createDecorator<IEnvironmentService>('environmentService');
|
export const IEnvironmentService = createDecorator<IEnvironmentService>('environmentService');
|
||||||
|
|||||||
@@ -33,7 +33,12 @@ const options: minimist.Opts = {
|
|||||||
'export-default-configuration',
|
'export-default-configuration',
|
||||||
'install-source',
|
'install-source',
|
||||||
'upload-logs',
|
'upload-logs',
|
||||||
'driver'
|
'driver',
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
|
'database',
|
||||||
|
'server',
|
||||||
|
'user',
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
],
|
],
|
||||||
boolean: [
|
boolean: [
|
||||||
'help',
|
'help',
|
||||||
@@ -66,7 +71,11 @@ const options: minimist.Opts = {
|
|||||||
'status',
|
'status',
|
||||||
'file-write',
|
'file-write',
|
||||||
'file-chmod',
|
'file-chmod',
|
||||||
'driver-verbose'
|
'driver-verbose',
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
|
'aad',
|
||||||
|
'integrated',
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
],
|
],
|
||||||
alias: {
|
alias: {
|
||||||
add: 'a',
|
add: 'a',
|
||||||
@@ -85,6 +94,12 @@ const options: minimist.Opts = {
|
|||||||
'debugBrkPluginHost': 'inspect-brk-extensions',
|
'debugBrkPluginHost': 'inspect-brk-extensions',
|
||||||
'debugSearch': 'inspect-search',
|
'debugSearch': 'inspect-search',
|
||||||
'debugBrkSearch': 'inspect-brk-search',
|
'debugBrkSearch': 'inspect-brk-search',
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
|
database: 'D',
|
||||||
|
integrated: 'E',
|
||||||
|
server: 'S',
|
||||||
|
user: 'U',
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -172,6 +172,10 @@ import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService'
|
|||||||
import { WorkbenchThemeService } from 'vs/workbench/services/themes/electron-browser/workbenchThemeService';
|
import { WorkbenchThemeService } from 'vs/workbench/services/themes/electron-browser/workbenchThemeService';
|
||||||
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
||||||
import { IUriDisplayService, UriDisplayService } from 'vs/platform/uriDisplay/common/uriDisplay';
|
import { IUriDisplayService, UriDisplayService } from 'vs/platform/uriDisplay/common/uriDisplay';
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
|
import { ICommandLineProcessing } from 'sql/parts/commandLine/common/commandLine';
|
||||||
|
import { CommandLineService } from 'sql/parts/commandLine/common/commandLineService';
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
|
|
||||||
interface WorkbenchParams {
|
interface WorkbenchParams {
|
||||||
configuration: IWindowConfiguration;
|
configuration: IWindowConfiguration;
|
||||||
@@ -575,7 +579,9 @@ export class Workbench extends Disposable implements IPartService {
|
|||||||
serviceCollection.set(IAccountManagementService, accountManagementService);
|
serviceCollection.set(IAccountManagementService, accountManagementService);
|
||||||
serviceCollection.set(IAccountPickerService, this.instantiationService.createInstance(AccountPickerService));
|
serviceCollection.set(IAccountPickerService, this.instantiationService.createInstance(AccountPickerService));
|
||||||
serviceCollection.set(IProfilerService, this.instantiationService.createInstance(ProfilerService));
|
serviceCollection.set(IProfilerService, this.instantiationService.createInstance(ProfilerService));
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
|
serviceCollection.set(ICommandLineProcessing, this.instantiationService.createInstance(CommandLineService));
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
this._register(toDisposable(() => connectionManagementService.shutdown()));
|
this._register(toDisposable(() => connectionManagementService.shutdown()));
|
||||||
this._register(toDisposable(() => accountManagementService.shutdown()));
|
this._register(toDisposable(() => accountManagementService.shutdown()));
|
||||||
this._register(toDisposable(() => capabilitiesService.shutdown()));
|
this._register(toDisposable(() => capabilitiesService.shutdown()));
|
||||||
|
|||||||
Reference in New Issue
Block a user