mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-21 02:51:37 -05:00
Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6680be6a73 | ||
|
|
e026ab85a7 | ||
|
|
e53c903205 | ||
|
|
03dbe8565f | ||
|
|
708793cb23 | ||
|
|
43ae4fb0aa | ||
|
|
6b1d552277 | ||
|
|
f24f576b72 | ||
|
|
c23328564f | ||
|
|
cd6dd3dafa | ||
|
|
4081e15bef | ||
|
|
b05e3813d1 | ||
|
|
3048311f40 | ||
|
|
1045392d91 | ||
|
|
7b23ca8ee7 | ||
|
|
4d67eca8bb | ||
|
|
74c4b7311e | ||
|
|
713c74adfd | ||
|
|
408a8a6f19 | ||
|
|
e1485e49d3 | ||
|
|
30b66934cd | ||
|
|
fd49c081c2 | ||
|
|
1327120024 | ||
|
|
d2b5043972 | ||
|
|
a0e55ea3fd | ||
|
|
1f32de29c1 | ||
|
|
12be06d682 | ||
|
|
27ca9b13f8 | ||
|
|
be45905830 | ||
|
|
05d0a89655 | ||
|
|
3ba575dcd0 | ||
|
|
3e200b7f0f | ||
|
|
cbce1f7008 | ||
|
|
e99101447e | ||
|
|
0ddb326e44 | ||
|
|
460446a15c | ||
|
|
4eea24997f | ||
|
|
0b1e9c7c66 | ||
|
|
d51a7a9eb7 | ||
|
|
0f0b959e14 | ||
|
|
b2ceb09e4d | ||
|
|
53953f5cda | ||
|
|
fbd5e819a2 | ||
|
|
bdc391d376 | ||
|
|
6b618fb121 |
@@ -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.31.1",
|
"version": "0.31.4",
|
||||||
"publisher": "Microsoft",
|
"publisher": "Microsoft",
|
||||||
"preview": true,
|
"preview": true,
|
||||||
"license": "https://raw.githubusercontent.com/Microsoft/sqlopsstudio/master/LICENSE.txt",
|
"license": "https://raw.githubusercontent.com/Microsoft/sqlopsstudio/master/LICENSE.txt",
|
||||||
|
|||||||
@@ -13,6 +13,11 @@ import { IAgentDialogData, AgentDialogMode } from '../interfaces';
|
|||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
export class AlertData implements IAgentDialogData {
|
export class AlertData implements IAgentDialogData {
|
||||||
|
public static readonly AlertTypeSqlServerEventString: string = localize('alertData.DefaultAlertTypString', 'SQL Server event alert');
|
||||||
|
public static readonly AlertTypePerformanceConditionString: string = localize('alertDialog.PerformanceCondition', 'SQL Server performance condition alert');
|
||||||
|
public static readonly AlertTypeWmiEventString: string = localize('alertDialog.WmiEvent', 'WMI event alert');
|
||||||
|
public static readonly DefaultAlertTypeString: string = AlertData.AlertTypeSqlServerEventString;
|
||||||
|
|
||||||
ownerUri: string;
|
ownerUri: string;
|
||||||
dialogMode: AgentDialogMode = AgentDialogMode.CREATE;
|
dialogMode: AgentDialogMode = AgentDialogMode.CREATE;
|
||||||
id: number;
|
id: number;
|
||||||
@@ -23,7 +28,7 @@ export class AlertData implements IAgentDialogData {
|
|||||||
eventSource: string;
|
eventSource: string;
|
||||||
hasNotification: number;
|
hasNotification: number;
|
||||||
includeEventDescription: string;
|
includeEventDescription: string;
|
||||||
isEnabled: boolean;
|
isEnabled: boolean = true;
|
||||||
jobId: string;
|
jobId: string;
|
||||||
jobName: string;
|
jobName: string;
|
||||||
lastOccurrenceDate: string;
|
lastOccurrenceDate: string;
|
||||||
@@ -36,7 +41,7 @@ export class AlertData implements IAgentDialogData {
|
|||||||
databaseName: string;
|
databaseName: string;
|
||||||
countResetDate: string;
|
countResetDate: string;
|
||||||
categoryName: string;
|
categoryName: string;
|
||||||
alertType: string;
|
alertType: string = AlertData.DefaultAlertTypeString;
|
||||||
wmiEventNamespace: string;
|
wmiEventNamespace: string;
|
||||||
wmiEventQuery: string;
|
wmiEventQuery: string;
|
||||||
|
|
||||||
@@ -109,9 +114,19 @@ export class AlertData implements IAgentDialogData {
|
|||||||
databaseName: this.databaseName,
|
databaseName: this.databaseName,
|
||||||
countResetDate: this.countResetDate,
|
countResetDate: this.countResetDate,
|
||||||
categoryName: this.categoryName,
|
categoryName: this.categoryName,
|
||||||
alertType: sqlops.AlertType.sqlServerEvent, //this.alertType,
|
alertType: AlertData.getAlertTypeFromString(this.alertType),
|
||||||
wmiEventNamespace: this.wmiEventNamespace,
|
wmiEventNamespace: this.wmiEventNamespace,
|
||||||
wmiEventQuery: this.wmiEventQuery
|
wmiEventQuery: this.wmiEventQuery
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static getAlertTypeFromString(alertTypeString: string): sqlops.AlertType {
|
||||||
|
if (alertTypeString === AlertData.AlertTypePerformanceConditionString) {
|
||||||
|
return sqlops.AlertType.sqlServerPerformanceCondition;
|
||||||
|
} else if (alertTypeString === AlertData.AlertTypeWmiEventString) {
|
||||||
|
return sqlops.AlertType.wmiEvent;
|
||||||
|
} else {
|
||||||
|
return sqlops.AlertType.sqlServerEvent;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -4,18 +4,22 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
import * as nls from 'vscode-nls';
|
||||||
import * as sqlops from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
|
import * as vscode from 'vscode';
|
||||||
import { AgentUtils } from '../agentUtils';
|
import { AgentUtils } from '../agentUtils';
|
||||||
import { IAgentDialogData, AgentDialogMode } from '../interfaces';
|
import { IAgentDialogData, AgentDialogMode } from '../interfaces';
|
||||||
|
|
||||||
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
export class JobData implements IAgentDialogData {
|
export class JobData implements IAgentDialogData {
|
||||||
|
|
||||||
private readonly JobCompletionActionCondition_Always: string = 'When the job completes';
|
private readonly JobCompletionActionCondition_Always: string = localize('jobData.whenJobCompletes', 'When the job completes');
|
||||||
private readonly JobCompletionActionCondition_OnFailure: string = 'When the job fails';
|
private readonly JobCompletionActionCondition_OnFailure: string = localize('jobData.whenJobFails', 'When the job fails');
|
||||||
private readonly JobCompletionActionCondition_OnSuccess: string = 'When the job succeeds';
|
private readonly JobCompletionActionCondition_OnSuccess: string = localize('jobData.whenJobSucceeds', 'When the job succeeds');
|
||||||
|
|
||||||
// Error Messages
|
// Error Messages
|
||||||
private readonly CreateJobErrorMessage_NameIsEmpty = 'Job name must be provided';
|
private readonly CreateJobErrorMessage_NameIsEmpty = localize('jobData.jobNameRequired', 'Job name must be provided');
|
||||||
|
|
||||||
private _ownerUri: string;
|
private _ownerUri: string;
|
||||||
private _jobCategories: string[];
|
private _jobCategories: string[];
|
||||||
@@ -25,6 +29,7 @@ export class JobData implements IAgentDialogData {
|
|||||||
|
|
||||||
public dialogMode: AgentDialogMode = AgentDialogMode.CREATE;
|
public dialogMode: AgentDialogMode = AgentDialogMode.CREATE;
|
||||||
public name: string;
|
public name: string;
|
||||||
|
public originalName: string;
|
||||||
public enabled: boolean = true;
|
public enabled: boolean = true;
|
||||||
public description: string;
|
public description: string;
|
||||||
public category: string;
|
public category: string;
|
||||||
@@ -40,8 +45,21 @@ export class JobData implements IAgentDialogData {
|
|||||||
public jobSchedules: sqlops.AgentJobScheduleInfo[];
|
public jobSchedules: sqlops.AgentJobScheduleInfo[];
|
||||||
public alerts: sqlops.AgentAlertInfo[];
|
public alerts: sqlops.AgentAlertInfo[];
|
||||||
|
|
||||||
constructor(ownerUri: string, private _agentService: sqlops.AgentServicesProvider = null) {
|
constructor(
|
||||||
|
ownerUri: string,
|
||||||
|
jobInfo: sqlops.AgentJobInfo = undefined,
|
||||||
|
private _agentService: sqlops.AgentServicesProvider = undefined) {
|
||||||
|
|
||||||
this._ownerUri = ownerUri;
|
this._ownerUri = ownerUri;
|
||||||
|
if (jobInfo) {
|
||||||
|
this.dialogMode = AgentDialogMode.EDIT;
|
||||||
|
this.name = jobInfo.name;
|
||||||
|
this.originalName = jobInfo.name;
|
||||||
|
this.owner = jobInfo.owner;
|
||||||
|
this.category = jobInfo.category;
|
||||||
|
this.description = jobInfo.description;
|
||||||
|
this.enabled = jobInfo.enabled;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public get jobCategories(): string[] {
|
public get jobCategories(): string[] {
|
||||||
@@ -92,7 +110,39 @@ export class JobData implements IAgentDialogData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async save() {
|
public async save() {
|
||||||
await this._agentService.createJob(this.ownerUri, {
|
let jobInfo: sqlops.AgentJobInfo = this.toAgentJobInfo();
|
||||||
|
let result = this.dialogMode === AgentDialogMode.CREATE
|
||||||
|
? await this._agentService.createJob(this.ownerUri, jobInfo)
|
||||||
|
: await this._agentService.updateJob(this.ownerUri, this.originalName, jobInfo);
|
||||||
|
|
||||||
|
if (!result || !result.success) {
|
||||||
|
vscode.window.showErrorMessage(
|
||||||
|
localize('jobData.saveErrorMessage', "Job update failed '{0}'", result.errorMessage ? result.errorMessage : 'Unknown'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public validate(): { valid: boolean, errorMessages: string[] } {
|
||||||
|
let validationErrors: string[] = [];
|
||||||
|
|
||||||
|
if (!(this.name && this.name.trim())) {
|
||||||
|
validationErrors.push(this.CreateJobErrorMessage_NameIsEmpty);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
valid: validationErrors.length === 0,
|
||||||
|
errorMessages: validationErrors
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public addJobSchedule(schedule: sqlops.AgentJobScheduleInfo) {
|
||||||
|
let existingSchedule = this.jobSchedules.find(item => item.name === schedule.name);
|
||||||
|
if (!existingSchedule) {
|
||||||
|
this.jobSchedules.push(schedule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public toAgentJobInfo(): sqlops.AgentJobInfo {
|
||||||
|
return {
|
||||||
name: this.name,
|
name: this.name,
|
||||||
owner: this.owner,
|
owner: this.owner,
|
||||||
description: this.description,
|
description: this.description,
|
||||||
@@ -122,30 +172,6 @@ export class JobData implements IAgentDialogData {
|
|||||||
lastRun: '',
|
lastRun: '',
|
||||||
nextRun: '',
|
nextRun: '',
|
||||||
jobId: ''
|
jobId: ''
|
||||||
}).then(result => {
|
|
||||||
if (!result.success) {
|
|
||||||
console.info(result.errorMessage);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public validate(): { valid: boolean, errorMessages: string[] } {
|
|
||||||
let validationErrors: string[] = [];
|
|
||||||
|
|
||||||
if (!(this.name && this.name.trim())) {
|
|
||||||
validationErrors.push(this.CreateJobErrorMessage_NameIsEmpty);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
valid: validationErrors.length === 0,
|
|
||||||
errorMessages: validationErrors
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public addJobSchedule(schedule: sqlops.AgentJobScheduleInfo) {
|
|
||||||
let existingSchedule = this.jobSchedules.find(item => item.name === schedule.name);
|
|
||||||
if (!existingSchedule) {
|
|
||||||
this.jobSchedules.push(schedule);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -29,8 +29,14 @@ export class OperatorData implements IAgentDialogData {
|
|||||||
weekdayPagerStartTime: string;
|
weekdayPagerStartTime: string;
|
||||||
weekdayPagerEndTime: string;
|
weekdayPagerEndTime: string;
|
||||||
|
|
||||||
constructor(ownerUri:string) {
|
constructor(ownerUri:string, operatorInfo: sqlops.AgentOperatorInfo) {
|
||||||
this.ownerUri = ownerUri;
|
this.ownerUri = ownerUri;
|
||||||
|
|
||||||
|
if (operatorInfo) {
|
||||||
|
this.dialogMode = AgentDialogMode.EDIT;
|
||||||
|
this.name = operatorInfo.name;
|
||||||
|
this.enabled = operatorInfo.enabled;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async initialize() {
|
public async initialize() {
|
||||||
|
|||||||
@@ -19,8 +19,14 @@ export class ProxyData implements IAgentDialogData {
|
|||||||
credentialId: number;
|
credentialId: number;
|
||||||
isEnabled: boolean;
|
isEnabled: boolean;
|
||||||
|
|
||||||
constructor(ownerUri:string) {
|
constructor(ownerUri:string, proxyInfo: sqlops.AgentProxyInfo) {
|
||||||
this.ownerUri = ownerUri;
|
this.ownerUri = ownerUri;
|
||||||
|
|
||||||
|
if (proxyInfo) {
|
||||||
|
this.accountName = proxyInfo.accountName;
|
||||||
|
this.credentialName = proxyInfo.credentialName;
|
||||||
|
this.description = proxyInfo.description;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async initialize() {
|
public async initialize() {
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import * as sqlops from 'sqlops';
|
|||||||
import { AgentDialog } from './agentDialog';
|
import { AgentDialog } from './agentDialog';
|
||||||
import { AgentUtils } from '../agentUtils';
|
import { AgentUtils } from '../agentUtils';
|
||||||
import { AlertData } from '../data/alertData';
|
import { AlertData } from '../data/alertData';
|
||||||
|
import { OperatorDialog } from './operatorDialog';
|
||||||
|
import { JobDialog } from './jobDialog';
|
||||||
|
|
||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
@@ -21,6 +23,7 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
private static readonly GeneralTabText: string = localize('alertDialog.General', 'General');
|
private static readonly GeneralTabText: string = localize('alertDialog.General', 'General');
|
||||||
private static readonly ResponseTabText: string = localize('alertDialog.Response', 'Response');
|
private static readonly ResponseTabText: string = localize('alertDialog.Response', 'Response');
|
||||||
private static readonly OptionsTabText: string = localize('alertDialog.Options', 'Options');
|
private static readonly OptionsTabText: string = localize('alertDialog.Options', 'Options');
|
||||||
|
private static readonly EventAlertText: string = localize('alertDialog.eventAlert', 'Event alert definition');
|
||||||
|
|
||||||
// General tab strings
|
// General tab strings
|
||||||
private static readonly NameLabel: string = localize('alertDialog.Name', 'Name');
|
private static readonly NameLabel: string = localize('alertDialog.Name', 'Name');
|
||||||
@@ -31,9 +34,6 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
private static readonly SeverityLabel: string = localize('alertDialog.Severity', 'Severity');
|
private static readonly SeverityLabel: string = localize('alertDialog.Severity', 'Severity');
|
||||||
private static readonly RaiseIfMessageContainsLabel: string = localize('alertDialog.RaiseAlertContains', 'Raise alert when message contains');
|
private static readonly RaiseIfMessageContainsLabel: string = localize('alertDialog.RaiseAlertContains', 'Raise alert when message contains');
|
||||||
private static readonly MessageTextLabel: string = localize('alertDialog.MessageText', 'Message text');
|
private static readonly MessageTextLabel: string = localize('alertDialog.MessageText', 'Message text');
|
||||||
private static readonly AlertTypeSqlServerEventString: string = localize('alertDialog.SqlServerEventAlert', 'SQL Server event alert');
|
|
||||||
private static readonly AlertTypePerformanceConditionString: string = localize('alertDialog.PerformanceCondition', 'SQL Server performance condition alert');
|
|
||||||
private static readonly AlertTypeWmiEventString: string = localize('alertDialog.WmiEvent', 'WMI event alert');
|
|
||||||
private static readonly AlertSeverity001Label: string = localize('alertDialog.Severity001', '001 - Miscellaneous System Information');
|
private static readonly AlertSeverity001Label: string = localize('alertDialog.Severity001', '001 - Miscellaneous System Information');
|
||||||
private static readonly AlertSeverity002Label: string = localize('alertDialog.Severity002', '002 - Reserved');
|
private static readonly AlertSeverity002Label: string = localize('alertDialog.Severity002', '002 - Reserved');
|
||||||
private static readonly AlertSeverity003Label: string = localize('alertDialog.Severity003', '003 - Reserved');
|
private static readonly AlertSeverity003Label: string = localize('alertDialog.Severity003', '003 - Reserved');
|
||||||
@@ -59,11 +59,13 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
private static readonly AlertSeverity023Label: string = localize('alertDialog.Severity023', '023 - Fatal Error: Database Integrity Suspect');
|
private static readonly AlertSeverity023Label: string = localize('alertDialog.Severity023', '023 - Fatal Error: Database Integrity Suspect');
|
||||||
private static readonly AlertSeverity024Label: string = localize('alertDialog.Severity024', '024 - Fatal Error: Hardware Error');
|
private static readonly AlertSeverity024Label: string = localize('alertDialog.Severity024', '024 - Fatal Error: Hardware Error');
|
||||||
private static readonly AlertSeverity025Label: string = localize('alertDialog.Severity025', '025 - Fatal Error');
|
private static readonly AlertSeverity025Label: string = localize('alertDialog.Severity025', '025 - Fatal Error');
|
||||||
|
private static readonly AllDatabases: string = localize('alertDialog.AllDatabases', '<all databases>');
|
||||||
|
|
||||||
private static readonly AlertTypes: string[] = [
|
private static readonly AlertTypes: string[] = [
|
||||||
AlertDialog.AlertTypeSqlServerEventString,
|
AlertData.AlertTypeSqlServerEventString,
|
||||||
AlertDialog.AlertTypePerformanceConditionString,
|
// Disabled until next release
|
||||||
AlertDialog.AlertTypeWmiEventString
|
// AlertData.AlertTypePerformanceConditionString,
|
||||||
|
// AlertData.AlertTypeWmiEventString
|
||||||
];
|
];
|
||||||
|
|
||||||
private static readonly AlertSeverities: string[] = [
|
private static readonly AlertSeverities: string[] = [
|
||||||
@@ -124,6 +126,10 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
private severityDropDown: sqlops.DropDownComponent;
|
private severityDropDown: sqlops.DropDownComponent;
|
||||||
private databaseDropDown: sqlops.DropDownComponent;
|
private databaseDropDown: sqlops.DropDownComponent;
|
||||||
private enabledCheckBox: sqlops.CheckBoxComponent;
|
private enabledCheckBox: sqlops.CheckBoxComponent;
|
||||||
|
private errorNumberRadioButton: sqlops.RadioButtonComponent;
|
||||||
|
private severityRadioButton: sqlops.RadioButtonComponent;
|
||||||
|
private errorNumberTextBox: sqlops.InputBoxComponent;
|
||||||
|
|
||||||
private raiseAlertMessageCheckBox: sqlops.CheckBoxComponent;
|
private raiseAlertMessageCheckBox: sqlops.CheckBoxComponent;
|
||||||
private raiseAlertMessageTextBox: sqlops.InputBoxComponent;
|
private raiseAlertMessageTextBox: sqlops.InputBoxComponent;
|
||||||
|
|
||||||
@@ -142,58 +148,115 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
private delayMinutesTextBox: sqlops.InputBoxComponent;
|
private delayMinutesTextBox: sqlops.InputBoxComponent;
|
||||||
private delaySecondsTextBox: sqlops.InputBoxComponent;
|
private delaySecondsTextBox: sqlops.InputBoxComponent;
|
||||||
|
|
||||||
constructor(ownerUri: string, alertInfo: sqlops.AgentAlertInfo = null) {
|
private jobs: string[];
|
||||||
|
private databases: string[];
|
||||||
|
|
||||||
|
constructor(ownerUri: string, alertInfo: sqlops.AgentAlertInfo = undefined, jobs: string[]) {
|
||||||
super(ownerUri,
|
super(ownerUri,
|
||||||
new AlertData(ownerUri, alertInfo),
|
new AlertData(ownerUri, alertInfo),
|
||||||
alertInfo ? AlertDialog.EditDialogTitle : AlertDialog.CreateDialogTitle);
|
alertInfo ? AlertDialog.EditDialogTitle : AlertDialog.CreateDialogTitle);
|
||||||
|
this.jobs = jobs;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async initializeDialog(dialog: sqlops.window.modelviewdialog.Dialog) {
|
protected async initializeDialog(dialog: sqlops.window.modelviewdialog.Dialog) {
|
||||||
let databases = await AgentUtils.getDatabases(this.ownerUri);
|
this.databases = await AgentUtils.getDatabases(this.ownerUri);
|
||||||
|
this.databases.unshift(AlertDialog.AllDatabases);
|
||||||
|
|
||||||
this.generalTab = sqlops.window.modelviewdialog.createTab(AlertDialog.GeneralTabText);
|
this.generalTab = sqlops.window.modelviewdialog.createTab(AlertDialog.GeneralTabText);
|
||||||
this.responseTab = sqlops.window.modelviewdialog.createTab(AlertDialog.ResponseTabText);
|
this.responseTab = sqlops.window.modelviewdialog.createTab(AlertDialog.ResponseTabText);
|
||||||
this.optionsTab = sqlops.window.modelviewdialog.createTab(AlertDialog.OptionsTabText);
|
this.optionsTab = sqlops.window.modelviewdialog.createTab(AlertDialog.OptionsTabText);
|
||||||
|
|
||||||
this.initializeGeneralTab(databases);
|
this.initializeGeneralTab(this.databases, dialog);
|
||||||
this.initializeResponseTab();
|
this.initializeResponseTab();
|
||||||
this.initializeOptionsTab();
|
this.initializeOptionsTab();
|
||||||
|
|
||||||
dialog.content = [this.generalTab, this.responseTab, this.optionsTab];
|
dialog.content = [this.generalTab, this.responseTab, this.optionsTab];
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeGeneralTab(databases: string[]) {
|
private initializeGeneralTab(databases: string[], dialog: sqlops.window.modelviewdialog.Dialog) {
|
||||||
this.generalTab.registerContent(async view => {
|
this.generalTab.registerContent(async view => {
|
||||||
|
// create controls
|
||||||
this.nameTextBox = view.modelBuilder.inputBox().component();
|
this.nameTextBox = view.modelBuilder.inputBox().component();
|
||||||
|
this.nameTextBox.required = true;
|
||||||
|
this.nameTextBox.onTextChanged(() => {
|
||||||
|
if (this.nameTextBox.value.length > 0) {
|
||||||
|
dialog.okButton.enabled = true;
|
||||||
|
} else {
|
||||||
|
dialog.okButton.enabled = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
this.enabledCheckBox = view.modelBuilder.checkBox()
|
this.enabledCheckBox = view.modelBuilder.checkBox()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
label: AlertDialog.EnabledCheckboxLabel
|
label: AlertDialog.EnabledCheckboxLabel
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
|
this.enabledCheckBox.checked = true;
|
||||||
|
|
||||||
this.databaseDropDown = view.modelBuilder.dropDown()
|
this.databaseDropDown = view.modelBuilder.dropDown()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
value: databases[0],
|
value: databases[0],
|
||||||
values: databases
|
values: databases,
|
||||||
|
width: '100%'
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
this.typeDropDown = view.modelBuilder.dropDown()
|
this.typeDropDown = view.modelBuilder.dropDown()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
value: AlertDialog.AlertTypes[0],
|
value: '',
|
||||||
values: AlertDialog.AlertTypes
|
values: AlertDialog.AlertTypes,
|
||||||
|
width: '100%'
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
|
this.severityRadioButton = view.modelBuilder.radioButton()
|
||||||
|
.withProperties({
|
||||||
|
value: 'serverity',
|
||||||
|
name: 'alertTypeOptions',
|
||||||
|
label: AlertDialog.SeverityLabel,
|
||||||
|
checked: true
|
||||||
|
}).component();
|
||||||
|
this.severityRadioButton.checked = true;
|
||||||
|
|
||||||
this.severityDropDown = view.modelBuilder.dropDown()
|
this.severityDropDown = view.modelBuilder.dropDown()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
value: AlertDialog.AlertSeverities[0],
|
value: AlertDialog.AlertSeverities[0],
|
||||||
values: AlertDialog.AlertSeverities
|
values: AlertDialog.AlertSeverities,
|
||||||
|
width: '100%'
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
|
this.errorNumberRadioButton = view.modelBuilder.radioButton()
|
||||||
|
.withProperties({
|
||||||
|
value: 'errorNumber',
|
||||||
|
name: 'alertTypeOptions',
|
||||||
|
label: AlertDialog.ErrorNumberLabel
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
this.errorNumberTextBox = view.modelBuilder.inputBox()
|
||||||
|
.withProperties({
|
||||||
|
width: '100%'
|
||||||
|
})
|
||||||
|
.component();
|
||||||
|
this.errorNumberTextBox.enabled = false;
|
||||||
|
|
||||||
|
this.errorNumberRadioButton.onDidClick(() => {
|
||||||
|
this.errorNumberTextBox.enabled = true;
|
||||||
|
this.severityDropDown.enabled = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.severityRadioButton.onDidClick(() => {
|
||||||
|
this.errorNumberTextBox.enabled = false;
|
||||||
|
this.severityDropDown.enabled = true;
|
||||||
|
});
|
||||||
|
|
||||||
this.raiseAlertMessageCheckBox = view.modelBuilder.checkBox()
|
this.raiseAlertMessageCheckBox = view.modelBuilder.checkBox()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
label: AlertDialog.RaiseIfMessageContainsLabel
|
label: AlertDialog.RaiseIfMessageContainsLabel
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
this.raiseAlertMessageTextBox = view.modelBuilder.inputBox().component();
|
this.raiseAlertMessageTextBox = view.modelBuilder.inputBox().component();
|
||||||
|
this.raiseAlertMessageTextBox.enabled = false;
|
||||||
|
|
||||||
|
this.raiseAlertMessageCheckBox.onChanged(() => {
|
||||||
|
this.raiseAlertMessageTextBox.enabled = this.raiseAlertMessageCheckBox.checked;
|
||||||
|
});
|
||||||
|
|
||||||
let formModel = view.modelBuilder.formContainer()
|
let formModel = view.modelBuilder.formContainer()
|
||||||
.withFormItems([{
|
.withFormItems([{
|
||||||
@@ -206,24 +269,61 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
component: this.typeDropDown,
|
component: this.typeDropDown,
|
||||||
title: AlertDialog.TypeLabel
|
title: AlertDialog.TypeLabel
|
||||||
}, {
|
}, {
|
||||||
component: this.databaseDropDown,
|
components: [{
|
||||||
title: AlertDialog.DatabaseLabel
|
component: this.databaseDropDown,
|
||||||
}, {
|
title: AlertDialog.DatabaseLabel
|
||||||
component: this.severityDropDown,
|
},
|
||||||
title: AlertDialog.SeverityLabel
|
{
|
||||||
}, {
|
component: this.severityRadioButton,
|
||||||
component: this.raiseAlertMessageCheckBox,
|
title: ''
|
||||||
title: ''
|
},
|
||||||
}, {
|
{
|
||||||
component: this.raiseAlertMessageTextBox,
|
component: this.severityDropDown,
|
||||||
title: AlertDialog.MessageTextLabel
|
title: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: this.errorNumberRadioButton,
|
||||||
|
title: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: this.errorNumberTextBox,
|
||||||
|
title: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: this.raiseAlertMessageCheckBox,
|
||||||
|
title: ''
|
||||||
|
}, {
|
||||||
|
component: this.raiseAlertMessageTextBox,
|
||||||
|
title: AlertDialog.MessageTextLabel
|
||||||
|
}],
|
||||||
|
title: AlertDialog.EventAlertText
|
||||||
}
|
}
|
||||||
]).withLayout({ width: '100%' }).component();
|
]).withLayout({ width: '100%' }).component();
|
||||||
|
|
||||||
await view.initializeModel(formModel);
|
await view.initializeModel(formModel);
|
||||||
|
|
||||||
|
// initialize control values
|
||||||
this.nameTextBox.value = this.model.name;
|
this.nameTextBox.value = this.model.name;
|
||||||
|
this.raiseAlertMessageTextBox.value = this.model.eventDescriptionKeyword;
|
||||||
|
this.typeDropDown.value = this.model.alertType;
|
||||||
this.enabledCheckBox.checked = this.model.isEnabled;
|
this.enabledCheckBox.checked = this.model.isEnabled;
|
||||||
|
|
||||||
|
if (this.model.messageId > 0) {
|
||||||
|
this.errorNumberRadioButton.checked = true;
|
||||||
|
this.errorNumberTextBox.value = this.model.messageId.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.model.severity > 0) {
|
||||||
|
this.severityRadioButton.checked = true;
|
||||||
|
this.severityDropDown.value = this.severityDropDown.values[this.model.severity-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.model.databaseName) {
|
||||||
|
let idx = this.databases.indexOf(this.model.databaseName);
|
||||||
|
if (idx >= 0) {
|
||||||
|
this.databaseDropDown.value = this.databases[idx];
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,12 +334,38 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
label: AlertDialog.ExecuteJobCheckBoxLabel
|
label: AlertDialog.ExecuteJobCheckBoxLabel
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
this.executeJobTextBox = view.modelBuilder.inputBox().component();
|
this.executeJobTextBox = view.modelBuilder.inputBox()
|
||||||
|
.withProperties({ width: 375 })
|
||||||
|
.component();
|
||||||
|
this.executeJobTextBox.enabled = false;
|
||||||
this.newJobButton = view.modelBuilder.button().withProperties({
|
this.newJobButton = view.modelBuilder.button().withProperties({
|
||||||
label: AlertDialog.NewJobButtonLabel,
|
label: AlertDialog.NewJobButtonLabel,
|
||||||
width: 80
|
width: 80
|
||||||
}).component();
|
}).component();
|
||||||
|
this.newJobButton.enabled = false;
|
||||||
|
this.newJobButton.onDidClick(() => {
|
||||||
|
let jobDialog = new JobDialog(this.ownerUri);
|
||||||
|
jobDialog.openDialog();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.executeJobCheckBox.onChanged(() => {
|
||||||
|
if (this.executeJobCheckBox.checked) {
|
||||||
|
this.executeJobTextBox.enabled = true;
|
||||||
|
this.newJobButton.enabled = true;
|
||||||
|
} else {
|
||||||
|
this.executeJobTextBox.enabled = false;
|
||||||
|
this.newJobButton.enabled = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let executeJobContainer = view.modelBuilder.formContainer()
|
||||||
|
.withFormItems([{
|
||||||
|
component: this.executeJobTextBox,
|
||||||
|
title: AlertDialog.ExecuteJobTextBoxLabel
|
||||||
|
}, {
|
||||||
|
component: this.newJobButton,
|
||||||
|
title: AlertDialog.NewJobButtonLabel
|
||||||
|
}], { componentWidth: '100%'}).component();
|
||||||
|
|
||||||
this.notifyOperatorsCheckBox = view.modelBuilder.checkBox()
|
this.notifyOperatorsCheckBox = view.modelBuilder.checkBox()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
@@ -254,32 +380,57 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
AlertDialog.OperatorPagerColumnLabel
|
AlertDialog.OperatorPagerColumnLabel
|
||||||
],
|
],
|
||||||
data: [],
|
data: [],
|
||||||
height: 500
|
height: 500,
|
||||||
|
width: 375
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
this.newOperatorButton = view.modelBuilder.button().withProperties({
|
this.newOperatorButton = view.modelBuilder.button().withProperties({
|
||||||
label: this.newOperatorButton,
|
label: AlertDialog.NewOperatorButtonLabel,
|
||||||
width: 80
|
width: 80
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
|
this.operatorsTable.enabled = false;
|
||||||
|
this.newOperatorButton.enabled = false;
|
||||||
|
|
||||||
|
this.newOperatorButton.onDidClick(() => {
|
||||||
|
let operatorDialog = new OperatorDialog(this.ownerUri);
|
||||||
|
operatorDialog.openDialog();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.notifyOperatorsCheckBox.onChanged(() => {
|
||||||
|
if (this.notifyOperatorsCheckBox.checked) {
|
||||||
|
this.operatorsTable.enabled = true;
|
||||||
|
this.newOperatorButton.enabled = true;
|
||||||
|
} else {
|
||||||
|
this.operatorsTable.enabled = false;
|
||||||
|
this.newOperatorButton.enabled = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let notifyOperatorContainer = view.modelBuilder.formContainer()
|
||||||
|
.withFormItems([{
|
||||||
|
component: this.operatorsTable,
|
||||||
|
title: AlertDialog.OperatorListLabel
|
||||||
|
}, {
|
||||||
|
component: this.newOperatorButton,
|
||||||
|
title: ''
|
||||||
|
}], { componentWidth: '100%'}).component();
|
||||||
|
|
||||||
let formModel = view.modelBuilder.formContainer()
|
let formModel = view.modelBuilder.formContainer()
|
||||||
.withFormItems([{
|
.withFormItems([{
|
||||||
component: this.executeJobCheckBox,
|
component: this.executeJobCheckBox,
|
||||||
title: ''
|
title: ''
|
||||||
}, {
|
}, {
|
||||||
component: this.executeJobTextBox,
|
component: executeJobContainer,
|
||||||
title: AlertDialog.ExecuteJobTextBoxLabel
|
title: ''
|
||||||
}, {
|
|
||||||
component: this.newJobButton,
|
|
||||||
title: AlertDialog.NewJobButtonLabel
|
|
||||||
}, {
|
}, {
|
||||||
component: this.notifyOperatorsCheckBox,
|
component: this.notifyOperatorsCheckBox,
|
||||||
title: ''
|
title: ''
|
||||||
}, {
|
}, {
|
||||||
component: this.operatorsTable,
|
component: notifyOperatorContainer,
|
||||||
title: AlertDialog.OperatorListLabel,
|
title: ''
|
||||||
actions: [this.newOperatorButton]
|
}])
|
||||||
}]).withLayout({ width: '100%' }).component();
|
.withLayout({ width: '100%' }).component();
|
||||||
|
|
||||||
await view.initializeModel(formModel);
|
await view.initializeModel(formModel);
|
||||||
});
|
});
|
||||||
@@ -300,9 +451,19 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
|
|
||||||
this.additionalMessageTextBox = view.modelBuilder.inputBox().component();
|
this.additionalMessageTextBox = view.modelBuilder.inputBox().component();
|
||||||
|
|
||||||
this.delayMinutesTextBox = view.modelBuilder.inputBox().component();
|
this.delayMinutesTextBox = view.modelBuilder.inputBox()
|
||||||
|
.withProperties({
|
||||||
|
inputType: 'number',
|
||||||
|
placeHolder: 0
|
||||||
|
})
|
||||||
|
.component();
|
||||||
|
|
||||||
this.delaySecondsTextBox = view.modelBuilder.inputBox().component();
|
this.delaySecondsTextBox = view.modelBuilder.inputBox()
|
||||||
|
.withProperties({
|
||||||
|
inputType: 'number',
|
||||||
|
placeHolder: 0
|
||||||
|
})
|
||||||
|
.component();
|
||||||
|
|
||||||
let formModel = view.modelBuilder.formContainer()
|
let formModel = view.modelBuilder.formContainer()
|
||||||
.withFormItems([{
|
.withFormItems([{
|
||||||
@@ -343,13 +504,25 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
this.model.isEnabled = this.enabledCheckBox.checked;
|
this.model.isEnabled = this.enabledCheckBox.checked;
|
||||||
|
|
||||||
this.model.alertType = this.getDropdownValue(this.typeDropDown);
|
this.model.alertType = this.getDropdownValue(this.typeDropDown);
|
||||||
this.model.databaseName = this.getDropdownValue(this.databaseDropDown);
|
let databaseName = this.getDropdownValue(this.databaseDropDown);
|
||||||
this.model.severity = this.getSeverityNumber();
|
this.model.databaseName = (databaseName !== AlertDialog.AllDatabases) ? databaseName : undefined;
|
||||||
this.model.messageId = undefined;
|
|
||||||
|
|
||||||
let raiseIfError = this.raiseAlertMessageCheckBox.checked;
|
if (this.severityRadioButton.checked) {
|
||||||
if (raiseIfError) {
|
this.model.severity = this.getSeverityNumber();
|
||||||
let messageText = this.raiseAlertMessageTextBox.value;
|
this.model.messageId = 0;
|
||||||
|
} else {
|
||||||
|
this.model.severity = 0;
|
||||||
|
this.model.messageId = +this.errorNumberTextBox.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.raiseAlertMessageCheckBox.checked) {
|
||||||
|
this.model.eventDescriptionKeyword = this.raiseAlertMessageTextBox.value;
|
||||||
|
} else {
|
||||||
|
this.model.eventDescriptionKeyword = '';
|
||||||
|
}
|
||||||
|
let minutes = this.delayMinutesTextBox.value ? +this.delayMinutesTextBox.value : 0;
|
||||||
|
let seconds = this.delaySecondsTextBox.value ? +this.delaySecondsTextBox : 0;
|
||||||
|
this.model.delayBetweenResponses = minutes + seconds;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
import * as nls from 'vscode-nls';
|
||||||
import * as sqlops from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
import { JobData } from '../data/jobData';
|
import { JobData } from '../data/jobData';
|
||||||
import { JobStepDialog } from './jobStepDialog';
|
import { JobStepDialog } from './jobStepDialog';
|
||||||
@@ -10,50 +11,57 @@ import { PickScheduleDialog } from './pickScheduleDialog';
|
|||||||
import { AlertDialog } from './alertDialog';
|
import { AlertDialog } from './alertDialog';
|
||||||
import { AgentDialog } from './agentDialog';
|
import { AgentDialog } from './agentDialog';
|
||||||
|
|
||||||
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
export class JobDialog extends AgentDialog<JobData> {
|
export class JobDialog extends AgentDialog<JobData> {
|
||||||
|
|
||||||
// TODO: localize
|
// TODO: localize
|
||||||
// Top level
|
// Top level
|
||||||
private static readonly DialogTitle: string = 'New Job';
|
private static readonly CreateDialogTitle: string = localize('jobDialog.newJob', 'New Job');
|
||||||
private readonly GeneralTabText: string = 'General';
|
private static readonly EditDialogTitle: string = localize('jobDialog.editJob', 'Edit Job');
|
||||||
private readonly StepsTabText: string = 'Steps';
|
private readonly GeneralTabText: string = localize('jobDialog.general', 'General');
|
||||||
private readonly SchedulesTabText: string = 'Schedules';
|
private readonly StepsTabText: string = localize('jobDialog.steps', 'Steps');
|
||||||
private readonly AlertsTabText: string = 'Alerts';
|
private readonly SchedulesTabText: string = localize('jobDialog.schedules', 'Schedules');
|
||||||
private readonly NotificationsTabText: string = 'Notifications';
|
private readonly AlertsTabText: string = localize('jobDialog.alerts', 'Alerts');
|
||||||
|
private readonly NotificationsTabText: string = localize('jobDialog.notifications', 'Notifications');
|
||||||
|
private readonly BlankJobNameErrorText: string = localize('jobDialog.blankJobNameError', 'The name of the job cannot be blank.');
|
||||||
|
|
||||||
// General tab strings
|
// General tab strings
|
||||||
private readonly NameTextBoxLabel: string = 'Name';
|
private readonly NameTextBoxLabel: string = localize('jobDialog.name', 'Name');
|
||||||
private readonly OwnerTextBoxLabel: string = 'Owner';
|
private readonly OwnerTextBoxLabel: string = localize('jobDialog.owner', 'Owner');
|
||||||
private readonly CategoryDropdownLabel: string = 'Category';
|
private readonly CategoryDropdownLabel: string = localize('jobDialog.category', 'Category');
|
||||||
private readonly DescriptionTextBoxLabel: string = 'Description';
|
private readonly DescriptionTextBoxLabel: string = localize('jobDialog.description', 'Description');
|
||||||
private readonly EnabledCheckboxLabel: string = 'Enabled';
|
private readonly EnabledCheckboxLabel: string = localize('jobDialog.enabled', 'Enabled');
|
||||||
|
|
||||||
// Steps tab strings
|
// Steps tab strings
|
||||||
private readonly JobStepsTopLabelString: string = 'Job step list';
|
private readonly JobStepsTopLabelString: string = localize('jobDialog.jobStepList', 'Job step list');
|
||||||
private readonly StepsTable_StepColumnString: string = 'Step';
|
private readonly StepsTable_StepColumnString: string = localize('jobDialog.step', 'Step');
|
||||||
private readonly StepsTable_NameColumnString: string = 'Name';
|
private readonly StepsTable_NameColumnString: string = localize('jobDialog.name', 'Name');
|
||||||
private readonly StepsTable_TypeColumnString: string = 'Type';
|
private readonly StepsTable_TypeColumnString: string = localize('jobDialog.type', 'Type');
|
||||||
private readonly StepsTable_SuccessColumnString: string = 'On Success';
|
private readonly StepsTable_SuccessColumnString: string = localize('jobDialog.onSuccess', 'On Success');
|
||||||
private readonly StepsTable_FailureColumnString: string = 'On Failure';
|
private readonly StepsTable_FailureColumnString: string = localize('jobDialog.onFailure', 'On Failure');
|
||||||
private readonly NewStepButtonString: string = 'New...';
|
private readonly NewStepButtonString: string = localize('jobDialog.new', 'New...');
|
||||||
private readonly InsertStepButtonString: string = 'Insert...';
|
private readonly EditStepButtonString: string = localize('jobDialog.edit', 'Edit');
|
||||||
private readonly EditStepButtonString: string = 'Edit';
|
private readonly DeleteStepButtonString: string = localize('jobDialog.delete', 'Delete');
|
||||||
private readonly DeleteStepButtonString: string = 'Delete';
|
private readonly MoveStepUpButtonString: string = localize('jobDialog.moveUp', 'Move Step Up');
|
||||||
|
private readonly MoveStepDownButtonString: string = localize('jobDialog.moveDown', 'Move Step Up');
|
||||||
|
|
||||||
// Notifications tab strings
|
// Notifications tab strings
|
||||||
private readonly NotificationsTabTopLabelString: string = 'Actions to perform when the job completes';
|
private readonly NotificationsTabTopLabelString: string = localize('jobDialog.notificationsTabTop', 'Actions to perform when the job completes');
|
||||||
private readonly EmailCheckBoxString: string = 'Email';
|
private readonly EmailCheckBoxString: string = localize('jobDialog.email', 'Email');
|
||||||
private readonly PagerCheckBoxString: string = 'Page';
|
private readonly PagerCheckBoxString: string = localize('jobDialog.page', 'Page');
|
||||||
private readonly EventLogCheckBoxString: string = 'Write to the Windows Application event log';
|
private readonly EventLogCheckBoxString: string = localize('jobDialog.eventLogCheckBoxLabel', 'Write to the Windows Application event log');
|
||||||
private readonly DeleteJobCheckBoxString: string = 'Automatically delete job';
|
private readonly DeleteJobCheckBoxString: string = localize('jobDialog.deleteJobLabel', 'Automatically delete job');
|
||||||
|
|
||||||
// Schedules tab strings
|
// Schedules tab strings
|
||||||
private readonly SchedulesTopLabelString: string = 'Schedules list';
|
private readonly SchedulesTopLabelString: string = localize('jobDialog.schedulesaLabel', 'Schedules list');
|
||||||
private readonly PickScheduleButtonString: string = 'Pick Schedule';
|
private readonly PickScheduleButtonString: string = localize('jobDialog.pickSchedule', 'Pick Schedule');
|
||||||
|
private readonly ScheduleNameLabelString: string = localize('jobDialog.scheduleNameLabel', 'Schedule Name');
|
||||||
|
|
||||||
// Alerts tab strings
|
// Alerts tab strings
|
||||||
private readonly AlertsTopLabelString: string = 'Alerts list';
|
private readonly AlertsTopLabelString: string = localize('jobDialog.alertsList', 'Alerts list');
|
||||||
private readonly NewAlertButtonString: string = 'New Alert';
|
private readonly NewAlertButtonString: string = localize('jobDialog.newAlert', 'New Alert');
|
||||||
|
private readonly AlertNameLabelString: string = localize('jobDialog.alertNameLabel', 'Alert Name');
|
||||||
|
|
||||||
// UI Components
|
// UI Components
|
||||||
private generalTab: sqlops.window.modelviewdialog.DialogTab;
|
private generalTab: sqlops.window.modelviewdialog.DialogTab;
|
||||||
@@ -72,7 +80,8 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
// Steps tab controls
|
// Steps tab controls
|
||||||
private stepsTable: sqlops.TableComponent;
|
private stepsTable: sqlops.TableComponent;
|
||||||
private newStepButton: sqlops.ButtonComponent;
|
private newStepButton: sqlops.ButtonComponent;
|
||||||
private insertStepButton: sqlops.ButtonComponent;
|
private moveStepUpButton: sqlops.ButtonComponent;
|
||||||
|
private moveStepDownButton: sqlops.ButtonComponent;
|
||||||
private editStepButton: sqlops.ButtonComponent;
|
private editStepButton: sqlops.ButtonComponent;
|
||||||
private deleteStepButton: sqlops.ButtonComponent;
|
private deleteStepButton: sqlops.ButtonComponent;
|
||||||
|
|
||||||
@@ -97,8 +106,11 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
private alertsTable: sqlops.TableComponent;
|
private alertsTable: sqlops.TableComponent;
|
||||||
private newAlertButton: sqlops.ButtonComponent;
|
private newAlertButton: sqlops.ButtonComponent;
|
||||||
|
|
||||||
constructor(ownerUri: string) {
|
constructor(ownerUri: string, jobInfo: sqlops.AgentJobInfo = undefined) {
|
||||||
super(ownerUri, new JobData(ownerUri), JobDialog.DialogTitle);
|
super(
|
||||||
|
ownerUri,
|
||||||
|
new JobData(ownerUri, jobInfo),
|
||||||
|
jobInfo ? JobDialog.EditDialogTitle : JobDialog.CreateDialogTitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async initializeDialog() {
|
protected async initializeDialog() {
|
||||||
@@ -129,6 +141,12 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
private initializeGeneralTab() {
|
private initializeGeneralTab() {
|
||||||
this.generalTab.registerContent(async view => {
|
this.generalTab.registerContent(async view => {
|
||||||
this.nameTextBox = view.modelBuilder.inputBox().component();
|
this.nameTextBox = view.modelBuilder.inputBox().component();
|
||||||
|
this.nameTextBox.required = true;
|
||||||
|
this.nameTextBox.onTextChanged(() => {
|
||||||
|
if (this.nameTextBox.value && this.nameTextBox.value.length > 0) {
|
||||||
|
this.dialog.message = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
this.ownerTextBox = view.modelBuilder.inputBox().component();
|
this.ownerTextBox = view.modelBuilder.inputBox().component();
|
||||||
this.categoryDropdown = view.modelBuilder.dropDown().component();
|
this.categoryDropdown = view.modelBuilder.dropDown().component();
|
||||||
this.descriptionTextBox = view.modelBuilder.inputBox().withProperties({
|
this.descriptionTextBox = view.modelBuilder.inputBox().withProperties({
|
||||||
@@ -159,11 +177,18 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
|
|
||||||
await view.initializeModel(formModel);
|
await view.initializeModel(formModel);
|
||||||
|
|
||||||
|
this.nameTextBox.value = this.model.name;
|
||||||
this.ownerTextBox.value = this.model.defaultOwner;
|
this.ownerTextBox.value = this.model.defaultOwner;
|
||||||
this.categoryDropdown.values = this.model.jobCategories;
|
this.categoryDropdown.values = this.model.jobCategories;
|
||||||
this.categoryDropdown.value = this.model.jobCategories[0];
|
|
||||||
|
let idx: number = undefined;
|
||||||
|
if (this.model.category && this.model.category !== '') {
|
||||||
|
idx = this.model.jobCategories.indexOf(this.model.category);
|
||||||
|
}
|
||||||
|
this.categoryDropdown.value = this.model.jobCategories[idx > 0 ? idx : 0];
|
||||||
|
|
||||||
this.enabledCheckBox.checked = this.model.enabled;
|
this.enabledCheckBox.checked = this.model.enabled;
|
||||||
this.descriptionTextBox.value = '';
|
this.descriptionTextBox.value = this.model.description;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,24 +204,38 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
this.StepsTable_FailureColumnString
|
this.StepsTable_FailureColumnString
|
||||||
],
|
],
|
||||||
data: [],
|
data: [],
|
||||||
height: 800
|
height: 430
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
|
this.moveStepUpButton = view.modelBuilder.button()
|
||||||
|
.withProperties({
|
||||||
|
label: this.MoveStepUpButtonString,
|
||||||
|
width: 80
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
this.moveStepDownButton = view.modelBuilder.button()
|
||||||
|
.withProperties({
|
||||||
|
label: this.MoveStepDownButtonString,
|
||||||
|
width: 80
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
this.moveStepUpButton.enabled = false;
|
||||||
|
this.moveStepDownButton.enabled = false;
|
||||||
|
|
||||||
this.newStepButton = view.modelBuilder.button().withProperties({
|
this.newStepButton = view.modelBuilder.button().withProperties({
|
||||||
label: this.NewStepButtonString,
|
label: this.NewStepButtonString,
|
||||||
width: 80
|
width: 80
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
this.newStepButton.onDidClick((e)=>{
|
this.newStepButton.onDidClick((e)=>{
|
||||||
let stepDialog = new JobStepDialog(this.model.ownerUri, '', '', 1, this.model);
|
if (this.nameTextBox.value && this.nameTextBox.value.length > 0) {
|
||||||
stepDialog.openNewStepDialog();
|
let stepDialog = new JobStepDialog(this.model.ownerUri, this.nameTextBox.value, '' , 1, this.model);
|
||||||
|
stepDialog.openNewStepDialog();
|
||||||
|
} else {
|
||||||
|
this.dialog.message = { text: this.BlankJobNameErrorText };
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.insertStepButton = view.modelBuilder.button().withProperties({
|
|
||||||
label: this.InsertStepButtonString,
|
|
||||||
width: 80
|
|
||||||
}).component();
|
|
||||||
|
|
||||||
this.editStepButton = view.modelBuilder.button().withProperties({
|
this.editStepButton = view.modelBuilder.button().withProperties({
|
||||||
label: this.EditStepButtonString,
|
label: this.EditStepButtonString,
|
||||||
width: 80
|
width: 80
|
||||||
@@ -211,7 +250,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
.withFormItems([{
|
.withFormItems([{
|
||||||
component: this.stepsTable,
|
component: this.stepsTable,
|
||||||
title: this.JobStepsTopLabelString,
|
title: this.JobStepsTopLabelString,
|
||||||
actions: [this.newStepButton, this.insertStepButton, this.editStepButton, this.deleteStepButton]
|
actions: [this.moveStepUpButton, this.moveStepDownButton, this.newStepButton, this.editStepButton, this.deleteStepButton]
|
||||||
}]).withLayout({ width: '100%' }).component();
|
}]).withLayout({ width: '100%' }).component();
|
||||||
await view.initializeModel(formModel);
|
await view.initializeModel(formModel);
|
||||||
});
|
});
|
||||||
@@ -222,10 +261,10 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
this.alertsTable = view.modelBuilder.table()
|
this.alertsTable = view.modelBuilder.table()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
columns: [
|
columns: [
|
||||||
'Alert Name'
|
this.AlertNameLabelString
|
||||||
],
|
],
|
||||||
data: [],
|
data: [],
|
||||||
height: 600,
|
height: 430,
|
||||||
width: 400
|
width: 400
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
@@ -235,7 +274,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
this.newAlertButton.onDidClick((e)=>{
|
this.newAlertButton.onDidClick((e)=>{
|
||||||
let alertDialog = new AlertDialog(this.model.ownerUri);
|
let alertDialog = new AlertDialog(this.model.ownerUri, null, []);
|
||||||
alertDialog.onSuccess((dialogModel) => {
|
alertDialog.onSuccess((dialogModel) => {
|
||||||
});
|
});
|
||||||
alertDialog.openDialog();
|
alertDialog.openDialog();
|
||||||
@@ -257,11 +296,11 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
this.schedulesTable = view.modelBuilder.table()
|
this.schedulesTable = view.modelBuilder.table()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
columns: [
|
columns: [
|
||||||
'Schedule Name'
|
this.ScheduleNameLabelString
|
||||||
],
|
],
|
||||||
data: [],
|
data: [],
|
||||||
height: 600,
|
height: 430,
|
||||||
width: 400
|
width: 420
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
this.pickScheduleButton = view.modelBuilder.button().withProperties({
|
this.pickScheduleButton = view.modelBuilder.button().withProperties({
|
||||||
@@ -361,21 +400,23 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
|
|
||||||
let formModel = view.modelBuilder.formContainer().withFormItems([
|
let formModel = view.modelBuilder.formContainer().withFormItems([
|
||||||
{
|
{
|
||||||
component: this.notificationsTabTopLabel,
|
components:
|
||||||
title: ''
|
[{
|
||||||
}, {
|
component: emailContainer,
|
||||||
component: emailContainer,
|
title: ''
|
||||||
title: ''
|
},
|
||||||
}, {
|
{
|
||||||
component: pagerContainer,
|
component: pagerContainer,
|
||||||
title: ''
|
title: ''
|
||||||
}, {
|
},
|
||||||
component: eventLogContainer,
|
{
|
||||||
title: ''
|
component: eventLogContainer,
|
||||||
}, {
|
title: ''
|
||||||
component: deleteJobContainer,
|
},
|
||||||
title: ''
|
{
|
||||||
}]).withLayout({ width: '100%' }).component();
|
component: deleteJobContainer,
|
||||||
|
title: ''
|
||||||
|
}], title: this.NotificationsTabTopLabelString}]).withLayout({ width: '100%' }).component();
|
||||||
|
|
||||||
await view.initializeModel(formModel);
|
await view.initializeModel(formModel);
|
||||||
this.emailConditionDropdown.values = this.model.JobCompletionActionConditions;
|
this.emailConditionDropdown.values = this.model.JobCompletionActionConditions;
|
||||||
|
|||||||
@@ -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.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
import * as nls from 'vscode-nls';
|
||||||
import * as sqlops from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import { JobStepData } from '../data/jobStepData';
|
import { JobStepData } from '../data/jobStepData';
|
||||||
@@ -10,31 +11,58 @@ import { AgentUtils } from '../agentUtils';
|
|||||||
import { JobData } from '../data/jobData';
|
import { JobData } from '../data/jobData';
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
export class JobStepDialog {
|
export class JobStepDialog {
|
||||||
|
|
||||||
// TODO: localize
|
// TODO: localize
|
||||||
// Top level
|
// Top level
|
||||||
//
|
//
|
||||||
private static readonly DialogTitle: string = 'New Job Step';
|
private readonly DialogTitle: string = localize('jobStepDialog.newJobStep', 'New Job Step');
|
||||||
private static readonly FileBrowserDialogTitle: string = 'Locate Database Files - ';
|
private readonly FileBrowserDialogTitle: string = localize('jobStepDialog.fileBrowserTitle', 'Locate Database Files - ');
|
||||||
private static readonly OkButtonText: string = 'OK';
|
private readonly OkButtonText: string = localize('jobStepDialog.ok', 'OK');
|
||||||
private static readonly CancelButtonText: string = 'Cancel';
|
private readonly CancelButtonText: string = localize('jobStepDialog.cancel', 'Cancel');
|
||||||
private static readonly GeneralTabText: string = 'General';
|
private readonly GeneralTabText: string = localize('jobStepDialog.general', 'General');
|
||||||
private static readonly AdvancedTabText: string = 'Advanced';
|
private readonly AdvancedTabText: string = localize('jobStepDialog.advanced', 'Advanced');
|
||||||
private static readonly OpenCommandText: string = 'Open...';
|
private readonly OpenCommandText: string = localize('jobStepDialog.open', 'Open...');
|
||||||
private static readonly ParseCommandText: string = 'Parse';
|
private readonly ParseCommandText: string = localize('jobStepDialog.parse','Parse');
|
||||||
private static readonly NextButtonText: string = 'Next';
|
private readonly NextButtonText: string = localize('jobStepDialog.next', 'Next');
|
||||||
private static readonly PreviousButtonText: string = 'Previous';
|
private readonly PreviousButtonText: string = localize('jobStepDialog.previous','Previous');
|
||||||
private static readonly SuccessAction: string = 'On success action';
|
private readonly SuccessfulParseText: string = localize('jobStepDialog.successParse', 'The command was successfully parsed.');
|
||||||
private static readonly FailureAction: string = 'On failure action';
|
private readonly FailureParseText: string = localize('jobStepDialog.failParse', 'The command failed.');
|
||||||
|
private readonly BlankStepNameErrorText: string = localize('jobStepDialog.blankStepName', 'The step name cannot be left blank');
|
||||||
|
|
||||||
|
// General Control Titles
|
||||||
|
private readonly StepNameLabelString: string = localize('jobStepDialog.stepNameLabel', 'Step Name');
|
||||||
|
private readonly TypeLabelString: string = localize('jobStepDialog.typeLabel', 'Type');
|
||||||
|
private readonly RunAsLabelString: string = localize('jobStepDialog.runAsLabel', 'Run as');
|
||||||
|
private readonly DatabaseLabelString: string = localize('jobStepDialog.databaseLabel', 'Database');
|
||||||
|
private readonly CommandLabelString: string = localize('jobStepDialog.commandLabel', 'Command');
|
||||||
|
|
||||||
|
// Advanced Control Titles
|
||||||
|
private readonly SuccessActionLabel: string = localize('jobStepDialog.successAction', 'On success action');
|
||||||
|
private readonly FailureActionLabel: string = localize('jobStepDialog.failureAction', 'On failure action');
|
||||||
|
private readonly RunAsUserLabel: string = localize('jobStepDialog.runAsUser', 'Run as user');
|
||||||
|
private readonly RetryAttemptsLabel: string = localize('jobStepDialog.retryAttempts', 'Retry Attempts');
|
||||||
|
private readonly RetryIntervalLabel: string = localize('jobStepDialog.retryInterval', 'Retry Interval (minutes)');
|
||||||
|
private readonly LogToTableLabel: string = localize('jobStepDialog.logToTable', 'Log to table');
|
||||||
|
private readonly AppendExistingTableEntryLabel: string = localize('jobStepDialog.appendExistingTableEntry', 'Append output to exisiting entry in table');
|
||||||
|
private readonly IncludeStepOutputHistoryLabel: string = localize('jobStepDialog.includeStepOutputHistory', 'Include step output in history');
|
||||||
|
private readonly OutputFileNameLabel: string = localize('jobStepDialog.outputFile', 'Output File');
|
||||||
|
private readonly AppendOutputToFileLabel: string = localize('jobStepDialog.appendOutputToFile', 'Append output to existing file');
|
||||||
|
|
||||||
|
// File Browser Control Titles
|
||||||
|
private readonly SelectedPathLabelString: string = localize('jobStepDialog.selectedPath', 'Selected path');
|
||||||
|
private readonly FilesOfTypeLabelString: string = localize('jobStepDialog.filesOfType', 'Files of type');
|
||||||
|
private readonly FileNameLabelString: string = localize('jobStepDialog.fileName', 'File name');
|
||||||
|
private readonly AllFilesLabelString: string = localize('jobStepDialog.allFiles', 'All Files (*)');
|
||||||
|
|
||||||
// Dropdown options
|
// Dropdown options
|
||||||
private static readonly TSQLScript: string = 'Transact-SQL script (T-SQL)';
|
private readonly TSQLScript: string = localize('jobStepDialog.TSQL', 'Transact-SQL script (T-SQL)');
|
||||||
private static readonly AgentServiceAccount: string = 'SQL Server Agent Service Account';
|
private readonly AgentServiceAccount: string = localize('jobStepDialog.agentServiceAccount', 'SQL Server Agent Service Account');
|
||||||
private static readonly NextStep: string = 'Go to the next step';
|
private readonly NextStep: string = localize('jobStepDialog.nextStep', 'Go to the next step');
|
||||||
private static readonly QuitJobReportingSuccess: string = 'Quit the job reporting success';
|
private readonly QuitJobReportingSuccess: string = localize('jobStepDialog.quitJobSuccess', 'Quit the job reporting success');
|
||||||
private static readonly QuitJobReportingFailure: string = 'Quit the job reporting failure';
|
private readonly QuitJobReportingFailure: string = localize('jobStepDialog.quitJobFailure', 'Quit the job reporting failure');
|
||||||
|
|
||||||
// UI Components
|
// UI Components
|
||||||
|
|
||||||
@@ -54,6 +82,7 @@ export class JobStepDialog {
|
|||||||
private retryIntervalBox: sqlops.InputBoxComponent;
|
private retryIntervalBox: sqlops.InputBoxComponent;
|
||||||
private outputFileNameBox: sqlops.InputBoxComponent;
|
private outputFileNameBox: sqlops.InputBoxComponent;
|
||||||
private fileBrowserNameBox: sqlops.InputBoxComponent;
|
private fileBrowserNameBox: sqlops.InputBoxComponent;
|
||||||
|
private userInputBox: sqlops.InputBoxComponent;
|
||||||
|
|
||||||
// Dropdowns
|
// Dropdowns
|
||||||
private typeDropdown: sqlops.DropDownComponent;
|
private typeDropdown: sqlops.DropDownComponent;
|
||||||
@@ -98,33 +127,36 @@ export class JobStepDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private initializeUIComponents() {
|
private initializeUIComponents() {
|
||||||
this.dialog = sqlops.window.modelviewdialog.createDialog(JobStepDialog.DialogTitle);
|
this.dialog = sqlops.window.modelviewdialog.createDialog(this.DialogTitle);
|
||||||
this.generalTab = sqlops.window.modelviewdialog.createTab(JobStepDialog.GeneralTabText);
|
this.generalTab = sqlops.window.modelviewdialog.createTab(this.GeneralTabText);
|
||||||
this.advancedTab = sqlops.window.modelviewdialog.createTab(JobStepDialog.AdvancedTabText);
|
this.advancedTab = sqlops.window.modelviewdialog.createTab(this.AdvancedTabText);
|
||||||
this.dialog.content = [this.generalTab, this.advancedTab];
|
this.dialog.content = [this.generalTab, this.advancedTab];
|
||||||
this.dialog.okButton.onClick(async () => await this.execute());
|
this.dialog.okButton.onClick(async () => await this.execute());
|
||||||
this.dialog.okButton.label = JobStepDialog.OkButtonText;
|
this.dialog.okButton.label = this.OkButtonText;
|
||||||
this.dialog.cancelButton.label = JobStepDialog.CancelButtonText;
|
this.dialog.cancelButton.label = this.CancelButtonText;
|
||||||
}
|
}
|
||||||
|
|
||||||
private createCommands(view, queryProvider: sqlops.QueryProvider) {
|
private createCommands(view, queryProvider: sqlops.QueryProvider) {
|
||||||
this.openButton = view.modelBuilder.button()
|
this.openButton = view.modelBuilder.button()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
label: JobStepDialog.OpenCommandText,
|
label: this.OpenCommandText,
|
||||||
width: '80px'
|
width: '80px',
|
||||||
|
isFile: true
|
||||||
}).component();
|
}).component();
|
||||||
|
this.openButton.enabled = false;
|
||||||
this.parseButton = view.modelBuilder.button()
|
this.parseButton = view.modelBuilder.button()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
label: JobStepDialog.ParseCommandText,
|
label: this.ParseCommandText,
|
||||||
width: '80px'
|
width: '80px',
|
||||||
|
isFile: false
|
||||||
}).component();
|
}).component();
|
||||||
this.parseButton.onDidClick(e => {
|
this.parseButton.onDidClick(e => {
|
||||||
if (this.commandTextBox.value) {
|
if (this.commandTextBox.value) {
|
||||||
queryProvider.parseSyntax(this.ownerUri, this.commandTextBox.value).then(result => {
|
queryProvider.parseSyntax(this.ownerUri, this.commandTextBox.value).then(result => {
|
||||||
if (result && result.parseable) {
|
if (result && result.parseable) {
|
||||||
this.dialog.message = { text: 'The command was successfully parsed.', level: 2};
|
this.dialog.message = { text: this.SuccessfulParseText, level: 2};
|
||||||
} else if (result && !result.parseable) {
|
} else if (result && !result.parseable) {
|
||||||
this.dialog.message = { text: 'The command failed' };
|
this.dialog.message = { text: this.FailureParseText };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -139,13 +171,13 @@ export class JobStepDialog {
|
|||||||
.component();
|
.component();
|
||||||
this.nextButton = view.modelBuilder.button()
|
this.nextButton = view.modelBuilder.button()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
label: JobStepDialog.NextButtonText,
|
label: this.NextButtonText,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
width: '80px'
|
width: '80px'
|
||||||
}).component();
|
}).component();
|
||||||
this.previousButton = view.modelBuilder.button()
|
this.previousButton = view.modelBuilder.button()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
label: JobStepDialog.PreviousButtonText,
|
label: this.PreviousButtonText,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
width: '80px'
|
width: '80px'
|
||||||
}).component();
|
}).component();
|
||||||
@@ -157,10 +189,16 @@ export class JobStepDialog {
|
|||||||
.withProperties({
|
.withProperties({
|
||||||
}).component();
|
}).component();
|
||||||
this.nameTextBox.required = true;
|
this.nameTextBox.required = true;
|
||||||
|
this.nameTextBox.onTextChanged(() => {
|
||||||
|
if (this.nameTextBox.value.length > 0) {
|
||||||
|
this.dialog.message = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.typeDropdown = view.modelBuilder.dropDown()
|
this.typeDropdown = view.modelBuilder.dropDown()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
value: JobStepDialog.TSQLScript,
|
value: this.TSQLScript,
|
||||||
values: [JobStepDialog.TSQLScript]
|
values: [this.TSQLScript]
|
||||||
})
|
})
|
||||||
.component();
|
.component();
|
||||||
this.runAsDropdown = view.modelBuilder.dropDown()
|
this.runAsDropdown = view.modelBuilder.dropDown()
|
||||||
@@ -171,8 +209,8 @@ export class JobStepDialog {
|
|||||||
.component();
|
.component();
|
||||||
this.runAsDropdown.enabled = false;
|
this.runAsDropdown.enabled = false;
|
||||||
this.typeDropdown.onValueChanged((type) => {
|
this.typeDropdown.onValueChanged((type) => {
|
||||||
if (type.selected !== JobStepDialog.TSQLScript) {
|
if (type.selected !== this.TSQLScript) {
|
||||||
this.runAsDropdown.value = JobStepDialog.AgentServiceAccount;
|
this.runAsDropdown.value = this.AgentServiceAccount;
|
||||||
this.runAsDropdown.values = [this.runAsDropdown.value];
|
this.runAsDropdown.values = [this.runAsDropdown.value];
|
||||||
} else {
|
} else {
|
||||||
this.runAsDropdown.value = '';
|
this.runAsDropdown.value = '';
|
||||||
@@ -200,19 +238,19 @@ export class JobStepDialog {
|
|||||||
let formModel = view.modelBuilder.formContainer()
|
let formModel = view.modelBuilder.formContainer()
|
||||||
.withFormItems([{
|
.withFormItems([{
|
||||||
component: this.nameTextBox,
|
component: this.nameTextBox,
|
||||||
title: 'Step name'
|
title: this.StepNameLabelString
|
||||||
}, {
|
}, {
|
||||||
component: this.typeDropdown,
|
component: this.typeDropdown,
|
||||||
title: 'Type'
|
title: this.TypeLabelString
|
||||||
}, {
|
}, {
|
||||||
component: this.runAsDropdown,
|
component: this.runAsDropdown,
|
||||||
title: 'Run as'
|
title: this.RunAsLabelString
|
||||||
}, {
|
}, {
|
||||||
component: this.databaseDropdown,
|
component: this.databaseDropdown,
|
||||||
title: 'Database'
|
title: this.DatabaseLabelString
|
||||||
}, {
|
}, {
|
||||||
component: this.commandTextBox,
|
component: this.commandTextBox,
|
||||||
title: 'Command',
|
title: this.CommandLabelString,
|
||||||
actions: [buttonContainer]
|
actions: [buttonContainer]
|
||||||
}], {
|
}], {
|
||||||
horizontal: false,
|
horizontal: false,
|
||||||
@@ -224,81 +262,57 @@ export class JobStepDialog {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private createRunAsUserOptions(view) {
|
|
||||||
let userInputBox = view.modelBuilder.inputBox()
|
|
||||||
.withProperties({ inputType: 'text', width: '100px' }).component();
|
|
||||||
let viewButton = view.modelBuilder.button()
|
|
||||||
.withProperties({ label: '...', width: '20px' }).component();
|
|
||||||
let viewButtonContainer = view.modelBuilder.flexContainer()
|
|
||||||
.withLayout({ width: 100, textAlign: 'right' })
|
|
||||||
.withItems([viewButton], { flex: '1 1 50%' }).component();
|
|
||||||
let userInputBoxContainer = view.modelBuilder.flexContainer()
|
|
||||||
.withLayout({ width: 200, textAlign: 'left' })
|
|
||||||
.withItems([userInputBox], { flex: '1 1 50%' }).component();
|
|
||||||
let runAsUserContainer = view.modelBuilder.flexContainer()
|
|
||||||
.withLayout({ width: 200 })
|
|
||||||
.withItems([userInputBoxContainer, viewButtonContainer], { flex: '1 1 50%' })
|
|
||||||
.component();
|
|
||||||
let runAsUserForm = view.modelBuilder.formContainer()
|
|
||||||
.withFormItems([{
|
|
||||||
component: runAsUserContainer,
|
|
||||||
title: 'Run as user'
|
|
||||||
}], { horizontal: true, componentWidth: 200 }).component();
|
|
||||||
return runAsUserForm;
|
|
||||||
}
|
|
||||||
|
|
||||||
private createAdvancedTab() {
|
private createAdvancedTab() {
|
||||||
this.advancedTab.registerContent(async (view) => {
|
this.advancedTab.registerContent(async (view) => {
|
||||||
this.successActionDropdown = view.modelBuilder.dropDown()
|
this.successActionDropdown = view.modelBuilder.dropDown()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
value: JobStepDialog.NextStep,
|
width: '100%',
|
||||||
values: [JobStepDialog.NextStep, JobStepDialog.QuitJobReportingSuccess, JobStepDialog.QuitJobReportingFailure]
|
value: this.NextStep,
|
||||||
|
values: [this.NextStep, this.QuitJobReportingSuccess, this.QuitJobReportingFailure]
|
||||||
})
|
})
|
||||||
.component();
|
.component();
|
||||||
let retryFlexContainer = this.createRetryCounters(view);
|
let retryFlexContainer = this.createRetryCounters(view);
|
||||||
|
|
||||||
this.failureActionDropdown = view.modelBuilder.dropDown()
|
this.failureActionDropdown = view.modelBuilder.dropDown()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
value: JobStepDialog.QuitJobReportingFailure,
|
value: this.QuitJobReportingFailure,
|
||||||
values: [JobStepDialog.QuitJobReportingFailure, JobStepDialog.NextStep, JobStepDialog.QuitJobReportingSuccess]
|
values: [this.QuitJobReportingFailure, this.NextStep, this.QuitJobReportingSuccess]
|
||||||
})
|
})
|
||||||
.component();
|
.component();
|
||||||
let optionsGroup = this.createTSQLOptions(view);
|
let optionsGroup = this.createTSQLOptions(view);
|
||||||
let viewButton = view.modelBuilder.button()
|
|
||||||
.withProperties({ label: 'View', width: '50px' }).component();
|
|
||||||
viewButton.enabled = false;
|
|
||||||
this.logToTableCheckbox = view.modelBuilder.checkBox()
|
this.logToTableCheckbox = view.modelBuilder.checkBox()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
label: 'Log to table'
|
label: this.LogToTableLabel
|
||||||
}).component();
|
}).component();
|
||||||
let appendToExistingEntryInTableCheckbox = view.modelBuilder.checkBox()
|
let appendToExistingEntryInTableCheckbox = view.modelBuilder.checkBox()
|
||||||
.withProperties({ label: 'Append output to existing entry in table' }).component();
|
.withProperties({ label: this.AppendExistingTableEntryLabel }).component();
|
||||||
appendToExistingEntryInTableCheckbox.enabled = false;
|
appendToExistingEntryInTableCheckbox.enabled = false;
|
||||||
this.logToTableCheckbox.onChanged(e => {
|
this.logToTableCheckbox.onChanged(e => {
|
||||||
viewButton.enabled = e;
|
|
||||||
appendToExistingEntryInTableCheckbox.enabled = e;
|
appendToExistingEntryInTableCheckbox.enabled = e;
|
||||||
});
|
});
|
||||||
let appendCheckboxContainer = view.modelBuilder.groupContainer()
|
let appendCheckboxContainer = view.modelBuilder.groupContainer()
|
||||||
.withItems([appendToExistingEntryInTableCheckbox]).component();
|
.withItems([appendToExistingEntryInTableCheckbox]).component();
|
||||||
let logToTableContainer = view.modelBuilder.flexContainer()
|
let logToTableContainer = view.modelBuilder.flexContainer()
|
||||||
.withLayout({ flexFlow: 'row', justifyContent: 'space-between', width: 300 })
|
.withLayout({ flexFlow: 'row', justifyContent: 'space-between', width: 300 })
|
||||||
.withItems([this.logToTableCheckbox, viewButton]).component();
|
.withItems([this.logToTableCheckbox]).component();
|
||||||
let logStepOutputHistoryCheckbox = view.modelBuilder.checkBox()
|
let logStepOutputHistoryCheckbox = view.modelBuilder.checkBox()
|
||||||
.withProperties({ label: 'Include step output in history' }).component();
|
.withProperties({ label: this.IncludeStepOutputHistoryLabel }).component();
|
||||||
let runAsUserOptions = this.createRunAsUserOptions(view);
|
this.userInputBox = view.modelBuilder.inputBox()
|
||||||
|
.withProperties({ inputType: 'text', width: '100%' }).component();
|
||||||
let formModel = view.modelBuilder.formContainer()
|
let formModel = view.modelBuilder.formContainer()
|
||||||
.withFormItems(
|
.withFormItems(
|
||||||
[{
|
[{
|
||||||
component: this.successActionDropdown,
|
component: this.successActionDropdown,
|
||||||
title: JobStepDialog.SuccessAction
|
title: this.SuccessActionLabel
|
||||||
}, {
|
}, {
|
||||||
component: retryFlexContainer,
|
component: retryFlexContainer,
|
||||||
title: ''
|
title: ''
|
||||||
}, {
|
}, {
|
||||||
component: this.failureActionDropdown,
|
component: this.failureActionDropdown,
|
||||||
title: JobStepDialog.FailureAction
|
title: this.FailureActionLabel
|
||||||
}, {
|
}, {
|
||||||
component: optionsGroup,
|
component: optionsGroup,
|
||||||
title: 'Transact-SQL script (T-SQL)'
|
title: this.TSQLScript
|
||||||
}, {
|
}, {
|
||||||
component: logToTableContainer,
|
component: logToTableContainer,
|
||||||
title: ''
|
title: ''
|
||||||
@@ -309,8 +323,8 @@ export class JobStepDialog {
|
|||||||
component: logStepOutputHistoryCheckbox,
|
component: logStepOutputHistoryCheckbox,
|
||||||
title: ''
|
title: ''
|
||||||
}, {
|
}, {
|
||||||
component: runAsUserOptions,
|
component: this.userInputBox,
|
||||||
title: ''
|
title: this.RunAsUserLabel
|
||||||
}], {
|
}], {
|
||||||
componentWidth: 400
|
componentWidth: 400
|
||||||
}).component();
|
}).component();
|
||||||
@@ -323,32 +337,37 @@ export class JobStepDialog {
|
|||||||
|
|
||||||
private createRetryCounters(view) {
|
private createRetryCounters(view) {
|
||||||
this.retryAttemptsBox = view.modelBuilder.inputBox()
|
this.retryAttemptsBox = view.modelBuilder.inputBox()
|
||||||
.withValidation(component => component.value >= 0)
|
.withValidation(component => component.value >= 0)
|
||||||
.withProperties({
|
.withProperties({
|
||||||
inputType: 'number'
|
inputType: 'number',
|
||||||
})
|
width: '100%',
|
||||||
.component();
|
placeHolder: '0'
|
||||||
|
})
|
||||||
|
.component();
|
||||||
this.retryIntervalBox = view.modelBuilder.inputBox()
|
this.retryIntervalBox = view.modelBuilder.inputBox()
|
||||||
.withValidation(component => component.value >= 0)
|
.withValidation(component => component.value >= 0)
|
||||||
.withProperties({
|
.withProperties({
|
||||||
inputType: 'number'
|
inputType: 'number',
|
||||||
|
width: '100%',
|
||||||
|
placeHolder: '0'
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
let retryAttemptsContainer = view.modelBuilder.formContainer()
|
let retryAttemptsContainer = view.modelBuilder.formContainer()
|
||||||
.withFormItems(
|
.withFormItems(
|
||||||
[{
|
[{
|
||||||
component: this.retryAttemptsBox,
|
component: this.retryAttemptsBox,
|
||||||
title: 'Retry Attempts'
|
title: this.RetryAttemptsLabel
|
||||||
}], {
|
}], {
|
||||||
horizontal: false
|
horizontal: false,
|
||||||
})
|
componentWidth: '100%'
|
||||||
|
})
|
||||||
.component();
|
.component();
|
||||||
|
|
||||||
let retryIntervalContainer = view.modelBuilder.formContainer()
|
let retryIntervalContainer = view.modelBuilder.formContainer()
|
||||||
.withFormItems(
|
.withFormItems(
|
||||||
[{
|
[{
|
||||||
component: this.retryIntervalBox,
|
component: this.retryIntervalBox,
|
||||||
title: 'Retry Interval (minutes)'
|
title: this.RetryIntervalLabel
|
||||||
}], {
|
}], {
|
||||||
horizontal: false
|
horizontal: false
|
||||||
})
|
})
|
||||||
@@ -362,7 +381,7 @@ export class JobStepDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private openFileBrowserDialog() {
|
private openFileBrowserDialog() {
|
||||||
let fileBrowserTitle = JobStepDialog.FileBrowserDialogTitle + `${this.server}`;
|
let fileBrowserTitle = this.FileBrowserDialogTitle + `${this.server}`;
|
||||||
this.fileBrowserDialog = sqlops.window.modelviewdialog.createDialog(fileBrowserTitle);
|
this.fileBrowserDialog = sqlops.window.modelviewdialog.createDialog(fileBrowserTitle);
|
||||||
let fileBrowserTab = sqlops.window.modelviewdialog.createTab('File Browser');
|
let fileBrowserTab = sqlops.window.modelviewdialog.createTab('File Browser');
|
||||||
this.fileBrowserDialog.content = [fileBrowserTab];
|
this.fileBrowserDialog.content = [fileBrowserTab];
|
||||||
@@ -379,8 +398,8 @@ export class JobStepDialog {
|
|||||||
});
|
});
|
||||||
this.fileTypeDropdown = view.modelBuilder.dropDown()
|
this.fileTypeDropdown = view.modelBuilder.dropDown()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
value: 'All Files (*)',
|
value: this.AllFilesLabelString,
|
||||||
values: ['All Files (*)']
|
values: [this.AllFilesLabelString]
|
||||||
})
|
})
|
||||||
.component();
|
.component();
|
||||||
this.fileBrowserNameBox = view.modelBuilder.inputBox()
|
this.fileBrowserNameBox = view.modelBuilder.inputBox()
|
||||||
@@ -392,13 +411,13 @@ export class JobStepDialog {
|
|||||||
title: ''
|
title: ''
|
||||||
}, {
|
}, {
|
||||||
component: this.selectedPathTextBox,
|
component: this.selectedPathTextBox,
|
||||||
title: 'Selected path:'
|
title: this.SelectedPathLabelString
|
||||||
}, {
|
}, {
|
||||||
component: this.fileTypeDropdown,
|
component: this.fileTypeDropdown,
|
||||||
title: 'Files of type:'
|
title: this.FilesOfTypeLabelString
|
||||||
}, {
|
}, {
|
||||||
component: this.fileBrowserNameBox,
|
component: this.fileBrowserNameBox,
|
||||||
title: 'File name:'
|
title: this.FileNameLabelString
|
||||||
}
|
}
|
||||||
]).component();
|
]).component();
|
||||||
view.initializeModel(fileBrowserContainer);
|
view.initializeModel(fileBrowserContainer);
|
||||||
@@ -406,8 +425,8 @@ export class JobStepDialog {
|
|||||||
this.fileBrowserDialog.okButton.onClick(() => {
|
this.fileBrowserDialog.okButton.onClick(() => {
|
||||||
this.outputFileNameBox.value = path.join(path.dirname(this.selectedPathTextBox.value), this.fileBrowserNameBox.value);
|
this.outputFileNameBox.value = path.join(path.dirname(this.selectedPathTextBox.value), this.fileBrowserNameBox.value);
|
||||||
});
|
});
|
||||||
this.fileBrowserDialog.okButton.label = JobStepDialog.OkButtonText;
|
this.fileBrowserDialog.okButton.label = this.OkButtonText;
|
||||||
this.fileBrowserDialog.cancelButton.label = JobStepDialog.CancelButtonText;
|
this.fileBrowserDialog.cancelButton.label = this.CancelButtonText;
|
||||||
sqlops.window.modelviewdialog.openDialog(this.fileBrowserDialog);
|
sqlops.window.modelviewdialog.openDialog(this.fileBrowserDialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,21 +436,15 @@ export class JobStepDialog {
|
|||||||
this.outputFileBrowserButton.onDidClick(() => this.openFileBrowserDialog());
|
this.outputFileBrowserButton.onDidClick(() => this.openFileBrowserDialog());
|
||||||
this.outputFileNameBox = view.modelBuilder.inputBox()
|
this.outputFileNameBox = view.modelBuilder.inputBox()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
width: '150px',
|
width: 250,
|
||||||
inputType: 'text'
|
inputType: 'text'
|
||||||
}).component();
|
}).component();
|
||||||
let outputViewButton = view.modelBuilder.button()
|
|
||||||
.withProperties({
|
|
||||||
width: '50px',
|
|
||||||
label: 'View'
|
|
||||||
}).component();
|
|
||||||
outputViewButton.enabled = false;
|
|
||||||
let outputButtonContainer = view.modelBuilder.flexContainer()
|
let outputButtonContainer = view.modelBuilder.flexContainer()
|
||||||
.withLayout({
|
.withLayout({
|
||||||
flexFlow: 'row',
|
flexFlow: 'row',
|
||||||
textAlign: 'right',
|
textAlign: 'right',
|
||||||
width: 120
|
width: '100%'
|
||||||
}).withItems([this.outputFileBrowserButton, outputViewButton], { flex: '1 1 50%' }).component();
|
}).withItems([this.outputFileBrowserButton], { flex: '1 1 50%' }).component();
|
||||||
let outputFlexBox = view.modelBuilder.flexContainer()
|
let outputFlexBox = view.modelBuilder.flexContainer()
|
||||||
.withLayout({
|
.withLayout({
|
||||||
flexFlow: 'row',
|
flexFlow: 'row',
|
||||||
@@ -441,7 +454,7 @@ export class JobStepDialog {
|
|||||||
}).component();
|
}).component();
|
||||||
this.appendToExistingFileCheckbox = view.modelBuilder.checkBox()
|
this.appendToExistingFileCheckbox = view.modelBuilder.checkBox()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
label: 'Append output to existing file'
|
label: this.AppendOutputToFileLabel
|
||||||
}).component();
|
}).component();
|
||||||
this.appendToExistingFileCheckbox.enabled = false;
|
this.appendToExistingFileCheckbox.enabled = false;
|
||||||
this.outputFileNameBox.onTextChanged((input) => {
|
this.outputFileNameBox.onTextChanged((input) => {
|
||||||
@@ -454,15 +467,20 @@ export class JobStepDialog {
|
|||||||
let outputFileForm = view.modelBuilder.formContainer()
|
let outputFileForm = view.modelBuilder.formContainer()
|
||||||
.withFormItems([{
|
.withFormItems([{
|
||||||
component: outputFlexBox,
|
component: outputFlexBox,
|
||||||
title: 'Output file'
|
title: this.OutputFileNameLabel
|
||||||
}, {
|
}, {
|
||||||
component: this.appendToExistingFileCheckbox,
|
component: this.appendToExistingFileCheckbox,
|
||||||
title: ''
|
title: ''
|
||||||
}], { horizontal: true, componentWidth: 200 }).component();
|
}], { horizontal: false, componentWidth: 200 }).component();
|
||||||
return outputFileForm;
|
return outputFileForm;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async execute() {
|
protected execute() {
|
||||||
|
this.model.stepName = this.nameTextBox.value;
|
||||||
|
if (!this.model.stepName || this.model.stepName.length === 0) {
|
||||||
|
this.dialog.message = this.dialog.message = { text: this.BlankStepNameErrorText };
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.model.jobName = this.jobName;
|
this.model.jobName = this.jobName;
|
||||||
this.model.id = this.stepId;
|
this.model.id = this.stepId;
|
||||||
this.model.server = this.server;
|
this.model.server = this.server;
|
||||||
@@ -471,12 +489,11 @@ export class JobStepDialog {
|
|||||||
this.model.databaseName = this.databaseDropdown.value as string;
|
this.model.databaseName = this.databaseDropdown.value as string;
|
||||||
this.model.script = this.commandTextBox.value;
|
this.model.script = this.commandTextBox.value;
|
||||||
this.model.successAction = this.successActionDropdown.value as string;
|
this.model.successAction = this.successActionDropdown.value as string;
|
||||||
this.model.retryAttempts = +this.retryAttemptsBox.value;
|
this.model.retryAttempts = this.retryAttemptsBox.value ? +this.retryAttemptsBox.value : 0;
|
||||||
this.model.retryInterval = +this.retryIntervalBox.value;
|
this.model.retryInterval = +this.retryIntervalBox.value ? +this.retryIntervalBox.value : 0;
|
||||||
this.model.failureAction = this.failureActionDropdown.value as string;
|
this.model.failureAction = this.failureActionDropdown.value as string;
|
||||||
this.model.outputFileName = this.outputFileNameBox.value;
|
this.model.outputFileName = this.outputFileNameBox.value;
|
||||||
this.model.appendToLogFile = this.appendToExistingFileCheckbox.checked;
|
this.model.appendToLogFile = this.appendToExistingFileCheckbox.checked;
|
||||||
await this.model.save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async openNewStepDialog() {
|
public async openNewStepDialog() {
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ const localize = nls.loadMessageBundle();
|
|||||||
export class OperatorDialog extends AgentDialog<OperatorData> {
|
export class OperatorDialog extends AgentDialog<OperatorData> {
|
||||||
|
|
||||||
// Top level
|
// Top level
|
||||||
private static readonly DialogTitle: string = localize('createOperator.createOperator', 'Create Operator');
|
private static readonly CreateDialogTitle: string = localize('createOperator.createOperator', 'Create Operator');
|
||||||
|
private static readonly EditDialogTitle: string = localize('createOperator.editOperator', 'Edit Operator');
|
||||||
private static readonly GeneralTabText: string = localize('createOperator.General', 'General');
|
private static readonly GeneralTabText: string = localize('createOperator.General', 'General');
|
||||||
private static readonly NotificationsTabText: string = localize('createOperator.Notifications', 'Notifications');
|
private static readonly NotificationsTabText: string = localize('createOperator.Notifications', 'Notifications');
|
||||||
|
|
||||||
@@ -32,6 +33,9 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
|
|||||||
private static readonly PagerFridayCheckBoxLabel: string = localize('createOperator.PagerFridayCheckBox', 'Friday ');
|
private static readonly PagerFridayCheckBoxLabel: string = localize('createOperator.PagerFridayCheckBox', 'Friday ');
|
||||||
private static readonly PagerSaturdayCheckBoxLabel: string = localize('createOperator.PagerSaturdayCheckBox', 'Saturday');
|
private static readonly PagerSaturdayCheckBoxLabel: string = localize('createOperator.PagerSaturdayCheckBox', 'Saturday');
|
||||||
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 WorkdayEndLabel: string = localize('createOperator.workdayEnd', 'Workday end');
|
||||||
|
private static readonly PagerDutyScheduleLabel: string = localize('createOperator.PagerDutySchedule', 'Pager on duty schdule');
|
||||||
|
|
||||||
// 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');
|
||||||
@@ -65,8 +69,11 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
|
|||||||
// Notification tab controls
|
// Notification tab controls
|
||||||
private alertsTable: sqlops.TableComponent;
|
private alertsTable: sqlops.TableComponent;
|
||||||
|
|
||||||
constructor(ownerUri: string) {
|
constructor(ownerUri: string, operatorInfo: sqlops.AgentOperatorInfo = undefined) {
|
||||||
super(ownerUri, new OperatorData(ownerUri), OperatorDialog.DialogTitle);
|
super(
|
||||||
|
ownerUri,
|
||||||
|
new OperatorData(ownerUri, operatorInfo),
|
||||||
|
operatorInfo ? OperatorDialog.EditDialogTitle : OperatorDialog.CreateDialogTitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async initializeDialog(dialog: sqlops.window.modelviewdialog.Dialog) {
|
protected async initializeDialog(dialog: sqlops.window.modelviewdialog.Dialog) {
|
||||||
@@ -174,13 +181,13 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
|
|||||||
this.weekdayPagerStartTimeInput = view.modelBuilder.inputBox()
|
this.weekdayPagerStartTimeInput = view.modelBuilder.inputBox()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
inputType: 'time',
|
inputType: 'time',
|
||||||
placeHolder: '08:00:00'
|
placeHolder: '08:00:00',
|
||||||
}).component();
|
}).component();
|
||||||
this.weekdayPagerStartTimeInput.enabled = false;
|
this.weekdayPagerStartTimeInput.enabled = false;
|
||||||
let weekdayStartInputContainer = view.modelBuilder.formContainer()
|
let weekdayStartInputContainer = view.modelBuilder.formContainer()
|
||||||
.withFormItems([{
|
.withFormItems([{
|
||||||
component: this.weekdayPagerStartTimeInput,
|
component: this.weekdayPagerStartTimeInput,
|
||||||
title: 'Workday begin'
|
title: OperatorDialog.WorkdayBeginLabel
|
||||||
}]).component();
|
}]).component();
|
||||||
|
|
||||||
this.weekdayPagerEndTimeInput = view.modelBuilder.inputBox()
|
this.weekdayPagerEndTimeInput = view.modelBuilder.inputBox()
|
||||||
@@ -192,7 +199,7 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
|
|||||||
let weekdayEndInputContainer = view.modelBuilder.formContainer()
|
let weekdayEndInputContainer = view.modelBuilder.formContainer()
|
||||||
.withFormItems([{
|
.withFormItems([{
|
||||||
component: this.weekdayPagerEndTimeInput,
|
component: this.weekdayPagerEndTimeInput,
|
||||||
title: 'Workday end'
|
title: OperatorDialog.WorkdayEndLabel
|
||||||
}]).component();
|
}]).component();
|
||||||
|
|
||||||
this.pagerFridayCheckBox = view.modelBuilder.checkBox()
|
this.pagerFridayCheckBox = view.modelBuilder.checkBox()
|
||||||
@@ -216,7 +223,8 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
|
|||||||
let pagerFridayCheckboxContainer = view.modelBuilder.flexContainer()
|
let pagerFridayCheckboxContainer = view.modelBuilder.flexContainer()
|
||||||
.withLayout({
|
.withLayout({
|
||||||
flexFlow: 'row',
|
flexFlow: 'row',
|
||||||
alignItems: 'baseline'
|
alignItems: 'baseline',
|
||||||
|
width: '100%'
|
||||||
}).withItems([this.pagerFridayCheckBox, weekdayStartInputContainer, weekdayEndInputContainer])
|
}).withItems([this.pagerFridayCheckBox, weekdayStartInputContainer, weekdayEndInputContainer])
|
||||||
.component();
|
.component();
|
||||||
|
|
||||||
@@ -245,7 +253,7 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
|
|||||||
let saturdayStartInputContainer = view.modelBuilder.formContainer()
|
let saturdayStartInputContainer = view.modelBuilder.formContainer()
|
||||||
.withFormItems([{
|
.withFormItems([{
|
||||||
component: this.saturdayPagerStartTimeInput,
|
component: this.saturdayPagerStartTimeInput,
|
||||||
title: 'Workday begin'
|
title: OperatorDialog.WorkdayBeginLabel
|
||||||
}]).component();
|
}]).component();
|
||||||
|
|
||||||
this.saturdayPagerEndTimeInput = view.modelBuilder.inputBox()
|
this.saturdayPagerEndTimeInput = view.modelBuilder.inputBox()
|
||||||
@@ -257,7 +265,7 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
|
|||||||
let saturdayEndInputContainer = view.modelBuilder.formContainer()
|
let saturdayEndInputContainer = view.modelBuilder.formContainer()
|
||||||
.withFormItems([{
|
.withFormItems([{
|
||||||
component: this.saturdayPagerEndTimeInput,
|
component: this.saturdayPagerEndTimeInput,
|
||||||
title: 'Workday end'
|
title: OperatorDialog.WorkdayEndLabel
|
||||||
}]).component();
|
}]).component();
|
||||||
|
|
||||||
let pagerSaturdayCheckboxContainer = view.modelBuilder.flexContainer()
|
let pagerSaturdayCheckboxContainer = view.modelBuilder.flexContainer()
|
||||||
@@ -292,7 +300,7 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
|
|||||||
let sundayStartInputContainer = view.modelBuilder.formContainer()
|
let sundayStartInputContainer = view.modelBuilder.formContainer()
|
||||||
.withFormItems([{
|
.withFormItems([{
|
||||||
component: this.sundayPagerStartTimeInput,
|
component: this.sundayPagerStartTimeInput,
|
||||||
title: 'Workday begin'
|
title: OperatorDialog.WorkdayBeginLabel
|
||||||
}]).component();
|
}]).component();
|
||||||
|
|
||||||
this.sundayPagerEndTimeInput = view.modelBuilder.inputBox()
|
this.sundayPagerEndTimeInput = view.modelBuilder.inputBox()
|
||||||
@@ -304,7 +312,7 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
|
|||||||
let sundayEndInputContainer = view.modelBuilder.formContainer()
|
let sundayEndInputContainer = view.modelBuilder.formContainer()
|
||||||
.withFormItems([{
|
.withFormItems([{
|
||||||
component: this.sundayPagerEndTimeInput,
|
component: this.sundayPagerEndTimeInput,
|
||||||
title: 'Workday end'
|
title: OperatorDialog.WorkdayEndLabel
|
||||||
}]).component();
|
}]).component();
|
||||||
|
|
||||||
let pagerSundayCheckboxContainer = view.modelBuilder.flexContainer()
|
let pagerSundayCheckboxContainer = view.modelBuilder.flexContainer()
|
||||||
@@ -314,36 +322,6 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
|
|||||||
}).withItems([this.pagerSundayCheckBox, sundayStartInputContainer, sundayEndInputContainer])
|
}).withItems([this.pagerSundayCheckBox, sundayStartInputContainer, sundayEndInputContainer])
|
||||||
.component();
|
.component();
|
||||||
|
|
||||||
let checkBoxContainer = view.modelBuilder.formContainer()
|
|
||||||
.withFormItems([{
|
|
||||||
component: this.pagerMondayCheckBox,
|
|
||||||
title: ''
|
|
||||||
}, {
|
|
||||||
component: this.pagerTuesdayCheckBox,
|
|
||||||
title: ''
|
|
||||||
}, {
|
|
||||||
component: this.pagerWednesdayCheckBox,
|
|
||||||
title: ''
|
|
||||||
}, {
|
|
||||||
component: this.pagerThursdayCheckBox,
|
|
||||||
title: ''
|
|
||||||
}, {
|
|
||||||
component: pagerFridayCheckboxContainer,
|
|
||||||
title: ''
|
|
||||||
}, {
|
|
||||||
component: pagerSaturdayCheckboxContainer,
|
|
||||||
title: ''
|
|
||||||
}, {
|
|
||||||
component: pagerSundayCheckboxContainer,
|
|
||||||
title: ''
|
|
||||||
}]).component();
|
|
||||||
|
|
||||||
let pagerContainer = view.modelBuilder.flexContainer()
|
|
||||||
.withLayout({
|
|
||||||
flexFlow: 'row'
|
|
||||||
}).withItems([checkBoxContainer])
|
|
||||||
.component();
|
|
||||||
|
|
||||||
let formModel = view.modelBuilder.formContainer()
|
let formModel = view.modelBuilder.formContainer()
|
||||||
.withFormItems([{
|
.withFormItems([{
|
||||||
component: this.nameTextBox,
|
component: this.nameTextBox,
|
||||||
@@ -358,8 +336,29 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
|
|||||||
component: this.pagerEmailNameTextBox,
|
component: this.pagerEmailNameTextBox,
|
||||||
title: OperatorDialog.PagerEmailNameTextLabel
|
title: OperatorDialog.PagerEmailNameTextLabel
|
||||||
}, {
|
}, {
|
||||||
component: pagerContainer,
|
components: [{
|
||||||
title: ''
|
component: this.pagerMondayCheckBox,
|
||||||
|
title: ''
|
||||||
|
}, {
|
||||||
|
component: this.pagerTuesdayCheckBox,
|
||||||
|
title: ''
|
||||||
|
}, {
|
||||||
|
component: this.pagerWednesdayCheckBox,
|
||||||
|
title: ''
|
||||||
|
}, {
|
||||||
|
component: this.pagerThursdayCheckBox,
|
||||||
|
title: ''
|
||||||
|
}, {
|
||||||
|
component: pagerFridayCheckboxContainer,
|
||||||
|
title: ''
|
||||||
|
}, {
|
||||||
|
component: pagerSaturdayCheckboxContainer,
|
||||||
|
title: ''
|
||||||
|
}, {
|
||||||
|
component: pagerSundayCheckboxContainer,
|
||||||
|
title: ''
|
||||||
|
}] ,
|
||||||
|
title: OperatorDialog.PagerDutyScheduleLabel
|
||||||
}]).withLayout({ width: '100%' }).component();
|
}]).withLayout({ width: '100%' }).component();
|
||||||
|
|
||||||
await view.initializeModel(formModel);
|
await view.initializeModel(formModel);
|
||||||
|
|||||||
@@ -4,18 +4,22 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
import * as nls from 'vscode-nls';
|
||||||
import * as sqlops from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import { PickScheduleData } from '../data/pickScheduleData';
|
import { PickScheduleData } from '../data/pickScheduleData';
|
||||||
|
|
||||||
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
export class PickScheduleDialog {
|
export class PickScheduleDialog {
|
||||||
|
|
||||||
// TODO: localize
|
// TODO: localize
|
||||||
// Top level
|
// Top level
|
||||||
private readonly DialogTitle: string = 'Job Schedules';
|
private readonly DialogTitle: string = localize('pickSchedule.jobSchedules', 'Job Schedules');
|
||||||
private readonly OkButtonText: string = 'OK';
|
private readonly OkButtonText: string = localize('pickSchedule.ok', 'OK');
|
||||||
private readonly CancelButtonText: string = 'Cancel';
|
private readonly CancelButtonText: string = localize('pickSchedule.cancel', 'Cancel');
|
||||||
private readonly SchedulesTabText: string = 'Schedules';
|
private readonly ScheduleNameLabelText: string = localize('pickSchedule.scheduleName', 'Schedule Name');
|
||||||
|
private readonly SchedulesLabelText: string = localize('pickSchedule.schedules', 'Schedules');
|
||||||
|
|
||||||
// UI Components
|
// UI Components
|
||||||
private dialog: sqlops.window.modelviewdialog.Dialog;
|
private dialog: sqlops.window.modelviewdialog.Dialog;
|
||||||
@@ -38,7 +42,6 @@ export class PickScheduleDialog {
|
|||||||
this.dialog.cancelButton.onClick(async () => await this.cancel());
|
this.dialog.cancelButton.onClick(async () => await this.cancel());
|
||||||
this.dialog.okButton.label = this.OkButtonText;
|
this.dialog.okButton.label = this.OkButtonText;
|
||||||
this.dialog.cancelButton.label = this.CancelButtonText;
|
this.dialog.cancelButton.label = this.CancelButtonText;
|
||||||
|
|
||||||
sqlops.window.modelviewdialog.openDialog(this.dialog);
|
sqlops.window.modelviewdialog.openDialog(this.dialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,17 +50,17 @@ export class PickScheduleDialog {
|
|||||||
this.schedulesTable = view.modelBuilder.table()
|
this.schedulesTable = view.modelBuilder.table()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
columns: [
|
columns: [
|
||||||
'Schedule Name'
|
this.ScheduleNameLabelText
|
||||||
],
|
],
|
||||||
data: [],
|
data: [],
|
||||||
height: 600,
|
height: '80em',
|
||||||
width: 400
|
width: '40em'
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
let formModel = view.modelBuilder.formContainer()
|
let formModel = view.modelBuilder.formContainer()
|
||||||
.withFormItems([{
|
.withFormItems([{
|
||||||
component: this.schedulesTable,
|
component: this.schedulesTable,
|
||||||
title: 'Schedules'
|
title: this.SchedulesLabelText
|
||||||
}]).withLayout({ width: '100%' }).component();
|
}]).withLayout({ width: '100%' }).component();
|
||||||
|
|
||||||
await view.initializeModel(formModel);
|
await view.initializeModel(formModel);
|
||||||
|
|||||||
@@ -15,32 +15,60 @@ const localize = nls.loadMessageBundle();
|
|||||||
export class ProxyDialog extends AgentDialog<ProxyData> {
|
export class ProxyDialog extends AgentDialog<ProxyData> {
|
||||||
|
|
||||||
// Top level
|
// Top level
|
||||||
private static readonly DialogTitle: string = localize('createProxy.createAlert', 'Create Alert');
|
private static readonly CreateDialogTitle: string = localize('createProxy.createProxy', 'Create Proxy');
|
||||||
|
private static readonly EditDialogTitle: string = localize('createProxy.editProxy', 'Edit Proxy');
|
||||||
private static readonly GeneralTabText: string = localize('createProxy.General', 'General');
|
private static readonly GeneralTabText: string = localize('createProxy.General', 'General');
|
||||||
|
|
||||||
// General tab strings
|
// General tab strings
|
||||||
private static readonly ProxyNameTextBoxLabel: string = localize('createProxy.ProxyName', 'Proxy name');
|
private static readonly ProxyNameTextBoxLabel: string = localize('createProxy.ProxyName', 'Proxy name');
|
||||||
private static readonly CredentialNameTextBoxLabel: string = localize('createProxy.CredentialName', 'Credential name');
|
private static readonly CredentialNameTextBoxLabel: string = localize('createProxy.CredentialName', 'Credential name');
|
||||||
private static readonly DescriptionTextBoxLabel: string = localize('createProxy.Description', 'Description');
|
private static readonly DescriptionTextBoxLabel: string = localize('createProxy.Description', 'Description');
|
||||||
private static readonly SubsystemsTableLabel: string = localize('createProxy.Subsystems', 'Subsystems');
|
private static readonly SubsystemLabel: string = localize('createProxy.SubsystemName', 'Subsystem');
|
||||||
private static readonly SubsystemNameColumnLabel: string = localize('createProxy.SubsystemName', 'Subsystem');
|
private static readonly OperatingSystemLabel: string = localize('createProxy.OperatingSystem', 'Operating system (CmdExec)');
|
||||||
|
private static readonly ReplicationSnapshotLabel: string = localize('createProxy.ReplicationSnapshot', 'Replication Snapshot');
|
||||||
|
private static readonly ReplicationTransactionLogLabel: string = localize('createProxy.ReplicationTransactionLog', 'Replication Transaction-Log Reader');
|
||||||
|
private static readonly ReplicationDistributorLabel: string = localize('createProxy.ReplicationDistributor', 'Replication Distributor');
|
||||||
|
private static readonly ReplicationMergeLabel: string = localize('createProxy.ReplicationMerge', 'Replication Merge');
|
||||||
|
private static readonly ReplicationQueueReaderLabel: string = localize('createProxy.ReplicationQueueReader', 'Replication Queue Reader');
|
||||||
|
private static readonly SSASQueryLabel: string = localize('createProxy.SSASQueryLabel', 'SQL Server Analysis Services Query');
|
||||||
|
private static readonly SSASCommandLabel: string = localize('createProxy.SSASCommandLabel', 'SQL Server Analysis Services Command');
|
||||||
|
private static readonly SSISPackageLabel: string = localize('createProxy.SSISPackage', 'SQL Server Integration Services Package');
|
||||||
|
private static readonly PowerShellLabel: string = localize('createProxy.PowerShell', 'PowerShell');
|
||||||
|
private static readonly SubSystemHeadingLabel: string = localize('createProxy.subSystemHeading', 'Active to the following subsytems');
|
||||||
|
|
||||||
// UI Components
|
// UI Components
|
||||||
private generalTab: sqlops.window.modelviewdialog.DialogTab;
|
private generalTab: sqlops.window.modelviewdialog.DialogTab;
|
||||||
|
|
||||||
// General tab controls
|
// General tab controls
|
||||||
private proxyNameTextBox: sqlops.InputBoxComponent;
|
private proxyNameTextBox: sqlops.InputBoxComponent;
|
||||||
private credentialNameTextBox: sqlops.InputBoxComponent;
|
private credentialNameDropDown: sqlops.DropDownComponent;
|
||||||
private descriptionTextBox: sqlops.InputBoxComponent;
|
private descriptionTextBox: sqlops.InputBoxComponent;
|
||||||
private subsystemsTable: sqlops.TableComponent;
|
private subsystemCheckBox: sqlops.CheckBoxComponent;
|
||||||
|
private operatingSystemCheckBox: sqlops.CheckBoxComponent;
|
||||||
|
private replicationSnapshotCheckBox: sqlops.CheckBoxComponent;
|
||||||
|
private replicationTransactionLogCheckBox: sqlops.CheckBoxComponent;
|
||||||
|
private replicationDistributorCheckBox: sqlops.CheckBoxComponent;
|
||||||
|
private replicationMergeCheckbox: sqlops.CheckBoxComponent;
|
||||||
|
private replicationQueueReaderCheckbox: sqlops.CheckBoxComponent;
|
||||||
|
private sqlQueryCheckBox: sqlops.CheckBoxComponent;
|
||||||
|
private sqlCommandCheckBox: sqlops.CheckBoxComponent;
|
||||||
|
private sqlIntegrationServicesPackageCheckbox: sqlops.CheckBoxComponent;
|
||||||
|
private powershellCheckBox: sqlops.CheckBoxComponent;
|
||||||
|
|
||||||
constructor(ownerUri: string) {
|
private credentials: sqlops.CredentialInfo[];
|
||||||
super(ownerUri, new ProxyData(ownerUri), ProxyDialog.DialogTitle);
|
|
||||||
|
constructor(ownerUri: string, proxyInfo: sqlops.AgentProxyInfo = undefined, credentials: sqlops.CredentialInfo[]) {
|
||||||
|
super(
|
||||||
|
ownerUri,
|
||||||
|
new ProxyData(ownerUri, proxyInfo),
|
||||||
|
proxyInfo ? ProxyDialog.EditDialogTitle : ProxyDialog.CreateDialogTitle);
|
||||||
|
this.credentials = credentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async initializeDialog(dialog: sqlops.window.modelviewdialog.Dialog) {
|
protected async initializeDialog(dialog: sqlops.window.modelviewdialog.Dialog) {
|
||||||
this.generalTab = sqlops.window.modelviewdialog.createTab(ProxyDialog.GeneralTabText);
|
this.generalTab = sqlops.window.modelviewdialog.createTab(ProxyDialog.GeneralTabText);
|
||||||
|
|
||||||
|
|
||||||
this.initializeGeneralTab();
|
this.initializeGeneralTab();
|
||||||
|
|
||||||
this.dialog.content = [this.generalTab];
|
this.dialog.content = [this.generalTab];
|
||||||
@@ -49,43 +77,143 @@ export class ProxyDialog extends AgentDialog<ProxyData> {
|
|||||||
private initializeGeneralTab() {
|
private initializeGeneralTab() {
|
||||||
this.generalTab.registerContent(async view => {
|
this.generalTab.registerContent(async view => {
|
||||||
|
|
||||||
this.proxyNameTextBox = view.modelBuilder.inputBox().component();
|
this.proxyNameTextBox = view.modelBuilder.inputBox()
|
||||||
|
.withProperties({width: 420})
|
||||||
|
.component();
|
||||||
|
|
||||||
this.credentialNameTextBox = view.modelBuilder.inputBox().component();
|
this.credentialNameDropDown = view.modelBuilder.dropDown()
|
||||||
|
|
||||||
this.descriptionTextBox = view.modelBuilder.inputBox().component();
|
|
||||||
|
|
||||||
this.subsystemsTable = view.modelBuilder.table()
|
|
||||||
.withProperties({
|
.withProperties({
|
||||||
columns: [
|
width: 432,
|
||||||
ProxyDialog.SubsystemNameColumnLabel
|
value: '',
|
||||||
],
|
editable: true,
|
||||||
data: [],
|
values: this.credentials.length > 0 ? this.credentials.map(c => c.name) : ['']
|
||||||
height: 500
|
})
|
||||||
|
.component();
|
||||||
|
|
||||||
|
this.descriptionTextBox = view.modelBuilder.inputBox()
|
||||||
|
.withProperties({
|
||||||
|
width: 420,
|
||||||
|
multiline: true,
|
||||||
|
height: 300
|
||||||
|
})
|
||||||
|
.component();
|
||||||
|
|
||||||
|
this.subsystemCheckBox = view.modelBuilder.checkBox()
|
||||||
|
.withProperties({
|
||||||
|
label: ProxyDialog.SubsystemLabel
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
|
this.subsystemCheckBox.onChanged(() => {
|
||||||
|
if (this.subsystemCheckBox.checked) {
|
||||||
|
this.operatingSystemCheckBox.checked = true;
|
||||||
|
this.replicationSnapshotCheckBox.checked = true;
|
||||||
|
this.replicationTransactionLogCheckBox.checked = true;
|
||||||
|
this.replicationDistributorCheckBox.checked = true;
|
||||||
|
this.replicationMergeCheckbox.checked = true;
|
||||||
|
this.replicationQueueReaderCheckbox.checked = true;
|
||||||
|
this.sqlQueryCheckBox.checked = true;
|
||||||
|
this.sqlCommandCheckBox.checked = true;
|
||||||
|
this.sqlIntegrationServicesPackageCheckbox.checked = true;
|
||||||
|
this.powershellCheckBox.checked = true;
|
||||||
|
} else {
|
||||||
|
this.operatingSystemCheckBox.checked = false;
|
||||||
|
this.replicationSnapshotCheckBox.checked = false;
|
||||||
|
this.replicationTransactionLogCheckBox.checked = false;
|
||||||
|
this.replicationDistributorCheckBox.checked = false;
|
||||||
|
this.replicationMergeCheckbox.checked = false;
|
||||||
|
this.replicationQueueReaderCheckbox.checked = false;
|
||||||
|
this.sqlQueryCheckBox.checked = false;
|
||||||
|
this.sqlCommandCheckBox.checked = false;
|
||||||
|
this.sqlIntegrationServicesPackageCheckbox.checked = false;
|
||||||
|
this.powershellCheckBox.checked = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.operatingSystemCheckBox = view.modelBuilder.checkBox()
|
||||||
|
.withProperties({
|
||||||
|
label: ProxyDialog.OperatingSystemLabel
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
this.replicationSnapshotCheckBox = view.modelBuilder.checkBox()
|
||||||
|
.withProperties({
|
||||||
|
label: ProxyDialog.ReplicationSnapshotLabel
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
this.replicationTransactionLogCheckBox = view.modelBuilder.checkBox()
|
||||||
|
.withProperties({
|
||||||
|
label: ProxyDialog.ReplicationTransactionLogLabel
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
this.replicationDistributorCheckBox = view.modelBuilder.checkBox()
|
||||||
|
.withProperties({
|
||||||
|
label: ProxyDialog.ReplicationDistributorLabel
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
this.replicationMergeCheckbox = view.modelBuilder.checkBox()
|
||||||
|
.withProperties({
|
||||||
|
label: ProxyDialog.ReplicationMergeLabel
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
this.replicationQueueReaderCheckbox = view.modelBuilder.checkBox()
|
||||||
|
.withProperties({
|
||||||
|
label: ProxyDialog.ReplicationQueueReaderLabel
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
this.sqlQueryCheckBox = view.modelBuilder.checkBox()
|
||||||
|
.withProperties({
|
||||||
|
label: ProxyDialog.SSASQueryLabel
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
this.sqlCommandCheckBox = view.modelBuilder.checkBox()
|
||||||
|
.withProperties({
|
||||||
|
label: ProxyDialog.SSASCommandLabel
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
this.sqlIntegrationServicesPackageCheckbox = view.modelBuilder.checkBox()
|
||||||
|
.withProperties({
|
||||||
|
label: ProxyDialog.SSISPackageLabel
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
this.powershellCheckBox = view.modelBuilder.checkBox()
|
||||||
|
.withProperties({
|
||||||
|
label: ProxyDialog.PowerShellLabel
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
let checkBoxContainer = view.modelBuilder.groupContainer()
|
||||||
|
.withItems([this.operatingSystemCheckBox, this.replicationSnapshotCheckBox,
|
||||||
|
this.replicationTransactionLogCheckBox, this.replicationDistributorCheckBox, this.replicationMergeCheckbox,
|
||||||
|
this.replicationQueueReaderCheckbox, this.sqlQueryCheckBox, this.sqlCommandCheckBox, this.sqlIntegrationServicesPackageCheckbox,
|
||||||
|
this.powershellCheckBox])
|
||||||
|
.component();
|
||||||
|
|
||||||
let formModel = view.modelBuilder.formContainer()
|
let formModel = view.modelBuilder.formContainer()
|
||||||
.withFormItems([{
|
.withFormItems([{
|
||||||
component: this.proxyNameTextBox,
|
component: this.proxyNameTextBox,
|
||||||
title: ProxyDialog.ProxyNameTextBoxLabel
|
title: ProxyDialog.ProxyNameTextBoxLabel
|
||||||
}, {
|
}, {
|
||||||
component: this.credentialNameTextBox,
|
component: this.credentialNameDropDown,
|
||||||
title: ProxyDialog.CredentialNameTextBoxLabel
|
title: ProxyDialog.CredentialNameTextBoxLabel
|
||||||
}, {
|
}, {
|
||||||
component: this.descriptionTextBox,
|
component: this.descriptionTextBox,
|
||||||
title: ProxyDialog.DescriptionTextBoxLabel
|
title: ProxyDialog.DescriptionTextBoxLabel
|
||||||
}, {
|
}]).withLayout({ width: 420 }).component();
|
||||||
component: this.subsystemsTable,
|
|
||||||
title: ProxyDialog.SubsystemsTableLabel
|
|
||||||
}]).withLayout({ width: '100%' }).component();
|
|
||||||
|
|
||||||
await view.initializeModel(formModel);
|
await view.initializeModel(formModel);
|
||||||
|
|
||||||
|
this.proxyNameTextBox.value = this.model.accountName;
|
||||||
|
this.credentialNameDropDown.value = this.model.credentialName;
|
||||||
|
this.descriptionTextBox.value = this.model.description;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected updateModel() {
|
protected updateModel() {
|
||||||
this.model.accountName = this.proxyNameTextBox.value;
|
this.model.accountName = this.proxyNameTextBox.value;
|
||||||
this.model.credentialName = this.credentialNameTextBox.value;
|
this.model.credentialName = this.credentialNameDropDown.value as string;
|
||||||
|
this.model.credentialId = this.credentials.find(
|
||||||
|
c => c.name === this.model.credentialName).id;
|
||||||
|
this.model.credentialIdentity = this.credentials.find(
|
||||||
|
c => c.name === this.model.credentialName).identity;
|
||||||
this.model.description = this.descriptionTextBox.value;
|
this.model.description = this.descriptionTextBox.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,17 +4,21 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
import * as nls from 'vscode-nls';
|
||||||
import * as sqlops from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import { ScheduleData } from '../data/scheduleData';
|
import { ScheduleData } from '../data/scheduleData';
|
||||||
|
|
||||||
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
export class ScheduleDialog {
|
export class ScheduleDialog {
|
||||||
|
|
||||||
// Top level
|
// Top level
|
||||||
private readonly DialogTitle: string = 'New Schedule';
|
private readonly DialogTitle: string = localize('scheduleDialog.newSchedule', 'New Schedule');
|
||||||
private readonly OkButtonText: string = 'OK';
|
private readonly OkButtonText: string = localize('scheduleDialog.ok', 'OK');
|
||||||
private readonly CancelButtonText: string = 'Cancel';
|
private readonly CancelButtonText: string = localize('scheduleDialog.cancel', 'Cancel');
|
||||||
|
private readonly ScheduleNameText: string = localize('scheduleDialog.scheduleName', 'Schedule Name');
|
||||||
|
private readonly SchedulesLabelText: string = localize('scheduleDialog.schedules', 'Schedules');
|
||||||
|
|
||||||
// UI Components
|
// UI Components
|
||||||
private dialog: sqlops.window.modelviewdialog.Dialog;
|
private dialog: sqlops.window.modelviewdialog.Dialog;
|
||||||
@@ -46,7 +50,7 @@ export class ScheduleDialog {
|
|||||||
this.schedulesTable = view.modelBuilder.table()
|
this.schedulesTable = view.modelBuilder.table()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
columns: [
|
columns: [
|
||||||
'Schedule Name'
|
this.ScheduleNameText
|
||||||
],
|
],
|
||||||
data: [],
|
data: [],
|
||||||
height: 600,
|
height: 600,
|
||||||
@@ -56,7 +60,7 @@ export class ScheduleDialog {
|
|||||||
let formModel = view.modelBuilder.formContainer()
|
let formModel = view.modelBuilder.formContainer()
|
||||||
.withFormItems([{
|
.withFormItems([{
|
||||||
component: this.schedulesTable,
|
component: this.schedulesTable,
|
||||||
title: 'Schedules'
|
title: this.SchedulesLabelText
|
||||||
}]).withLayout({ width: '100%' }).component();
|
}]).withLayout({ width: '100%' }).component();
|
||||||
|
|
||||||
await view.initializeModel(formModel);
|
await view.initializeModel(formModel);
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
* 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.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
import * as nls from 'vscode-nls';
|
||||||
import * as sqlops from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import { AlertDialog } from './dialogs/alertDialog';
|
import { AlertDialog } from './dialogs/alertDialog';
|
||||||
@@ -12,6 +14,8 @@ 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';
|
||||||
|
|
||||||
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main controller class that initializes the extension
|
* The main controller class that initializes the extension
|
||||||
*/
|
*/
|
||||||
@@ -23,12 +27,17 @@ export class MainController {
|
|||||||
this._context = context;
|
this._context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static showNotYetImplemented(): void {
|
||||||
|
vscode.window.showInformationMessage(
|
||||||
|
localize('mainController.notImplemented', "This feature is under development. Check-out the latest insiders build if you'd like to try out the most recent changes!"));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activates the extension
|
* Activates the extension
|
||||||
*/
|
*/
|
||||||
public activate(): void {
|
public activate(): void {
|
||||||
vscode.commands.registerCommand('agent.openCreateJobDialog', (ownerUri: string) => {
|
vscode.commands.registerCommand('agent.openJobDialog', (ownerUri: string, jobInfo: sqlops.AgentJobInfo) => {
|
||||||
let dialog = new JobDialog(ownerUri);
|
let dialog = new JobDialog(ownerUri, jobInfo);
|
||||||
dialog.openDialog();
|
dialog.openDialog();
|
||||||
});
|
});
|
||||||
vscode.commands.registerCommand('agent.openNewStepDialog', (ownerUri: string, jobId: string, server: string, stepId: number) => {
|
vscode.commands.registerCommand('agent.openNewStepDialog', (ownerUri: string, jobId: string, server: string, stepId: number) => {
|
||||||
@@ -39,17 +48,19 @@ export class MainController {
|
|||||||
let dialog = new PickScheduleDialog(ownerUri);
|
let dialog = new PickScheduleDialog(ownerUri);
|
||||||
dialog.showDialog();
|
dialog.showDialog();
|
||||||
});
|
});
|
||||||
vscode.commands.registerCommand('agent.openAlertDialog', (ownerUri: string, alertInfo: sqlops.AgentAlertInfo) => {
|
vscode.commands.registerCommand('agent.openAlertDialog', (ownerUri: string, alertInfo: sqlops.AgentAlertInfo, jobs: string[]) => {
|
||||||
let dialog = new AlertDialog(ownerUri, alertInfo);
|
let dialog = new AlertDialog(ownerUri, alertInfo, jobs);
|
||||||
dialog.openDialog();
|
dialog.openDialog();
|
||||||
});
|
});
|
||||||
vscode.commands.registerCommand('agent.openCreateOperatorDialog', (ownerUri: string) => {
|
vscode.commands.registerCommand('agent.openOperatorDialog', (ownerUri: string, operatorInfo: sqlops.AgentOperatorInfo) => {
|
||||||
let dialog = new OperatorDialog(ownerUri);
|
let dialog = new OperatorDialog(ownerUri, operatorInfo);
|
||||||
dialog.openDialog();
|
dialog.openDialog();
|
||||||
});
|
});
|
||||||
vscode.commands.registerCommand('agent.openCreateProxyDialog', (ownerUri: string) => {
|
vscode.commands.registerCommand('agent.openProxyDialog', (ownerUri: string, proxyInfo: sqlops.AgentProxyInfo, credentials: sqlops.CredentialInfo[]) => {
|
||||||
let dialog = new ProxyDialog(ownerUri);
|
//@TODO: reenable create proxy after snapping July release (7/14/18)
|
||||||
dialog.openDialog();
|
// let dialog = new ProxyDialog(ownerUri, proxyInfo, credentials);
|
||||||
|
// dialog.openDialog();
|
||||||
|
MainController.showNotYetImplemented();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ const testOwnerUri = 'agent://testuri';
|
|||||||
suite('Agent extension', () => {
|
suite('Agent extension', () => {
|
||||||
test('Create Job Data', async () => {
|
test('Create Job Data', async () => {
|
||||||
let testAgentService = new TestAgentService();
|
let testAgentService = new TestAgentService();
|
||||||
let data = new JobData(testOwnerUri, testAgentService);
|
let data = new JobData(testOwnerUri, undefined, testAgentService);
|
||||||
data.save();
|
data.save();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -86,6 +86,11 @@ export class TestAgentService implements sqlops.AgentServicesProvider {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Agent Credential method
|
||||||
|
getCredentials(ownerUri: string): Thenable<sqlops.GetCredentialsResult> {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
// Job Schedule management methods
|
// Job Schedule management methods
|
||||||
getJobSchedules(ownerUri: string): Thenable<sqlops.AgentJobSchedulesResult> {
|
getJobSchedules(ownerUri: string): Thenable<sqlops.AgentJobSchedulesResult> {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|||||||
@@ -658,7 +658,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#0.1.9",
|
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#0.2.0",
|
||||||
"opener": "^1.4.3",
|
"opener": "^1.4.3",
|
||||||
"service-downloader": "github:anthonydresser/service-downloader#0.1.2",
|
"service-downloader": "github:anthonydresser/service-downloader#0.1.2",
|
||||||
"vscode-extension-telemetry": "^0.0.15"
|
"vscode-extension-telemetry": "^0.0.15"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
|
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
|
||||||
"version": "1.5.0-alpha.4",
|
"version": "1.5.0-alpha.12",
|
||||||
"downloadFileNames": {
|
"downloadFileNames": {
|
||||||
"Windows_86": "win-x86-netcoreapp2.1.zip",
|
"Windows_86": "win-x86-netcoreapp2.1.zip",
|
||||||
"Windows_64": "win-x64-netcoreapp2.1.zip",
|
"Windows_64": "win-x64-netcoreapp2.1.zip",
|
||||||
|
|||||||
@@ -148,6 +148,11 @@ export interface DeleteAgentProxyParams {
|
|||||||
proxy: sqlops.AgentProxyInfo;
|
proxy: sqlops.AgentProxyInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Agent Credentials parameters
|
||||||
|
export interface GetCredentialsParams {
|
||||||
|
ownerUri: string;
|
||||||
|
}
|
||||||
|
|
||||||
// Job Schedule management parameters
|
// Job Schedule management parameters
|
||||||
export interface AgentJobScheduleParams {
|
export interface AgentJobScheduleParams {
|
||||||
ownerUri: string;
|
ownerUri: string;
|
||||||
@@ -262,6 +267,11 @@ export namespace DeleteAgentProxyRequest {
|
|||||||
export const type = new RequestType<DeleteAgentProxyParams, sqlops.ResultStatus, void, void>('agent/deleteproxy');
|
export const type = new RequestType<DeleteAgentProxyParams, sqlops.ResultStatus, void, void>('agent/deleteproxy');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Agent Credentials request
|
||||||
|
export namespace AgentCredentialsRequest {
|
||||||
|
export const type = new RequestType<GetCredentialsParams, sqlops.GetCredentialsResult, void, void>('security/credentials');
|
||||||
|
}
|
||||||
|
|
||||||
// Job Schedules requests
|
// Job Schedules requests
|
||||||
export namespace AgentJobSchedulesRequest {
|
export namespace AgentJobSchedulesRequest {
|
||||||
export const type = new RequestType<AgentJobScheduleParams, sqlops.AgentJobSchedulesResult, void, void>('agent/schedules');
|
export const type = new RequestType<AgentJobScheduleParams, sqlops.AgentJobSchedulesResult, void, void>('agent/schedules');
|
||||||
|
|||||||
@@ -438,6 +438,22 @@ export class AgentServicesFeature extends SqlOpsFeature<undefined> {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Agent Credential Method
|
||||||
|
let getCredentials = (ownerUri: string): Thenable<sqlops.GetCredentialsResult> => {
|
||||||
|
let params: contracts.GetCredentialsParams = {
|
||||||
|
ownerUri: ownerUri
|
||||||
|
};
|
||||||
|
let requestType = contracts.AgentCredentialsRequest.type;
|
||||||
|
return client.sendRequest(requestType, params).then(
|
||||||
|
r => r,
|
||||||
|
e => {
|
||||||
|
client.logFailedRequest(requestType, e);
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Job Schedule management methods
|
// Job Schedule management methods
|
||||||
let getJobSchedules = (ownerUri: string): Thenable<sqlops.AgentJobSchedulesResult> => {
|
let getJobSchedules = (ownerUri: string): Thenable<sqlops.AgentJobSchedulesResult> => {
|
||||||
let params: contracts.AgentJobScheduleParams = {
|
let params: contracts.AgentJobScheduleParams = {
|
||||||
@@ -532,6 +548,7 @@ export class AgentServicesFeature extends SqlOpsFeature<undefined> {
|
|||||||
createProxy,
|
createProxy,
|
||||||
updateProxy,
|
updateProxy,
|
||||||
deleteProxy,
|
deleteProxy,
|
||||||
|
getCredentials,
|
||||||
getJobSchedules,
|
getJobSchedules,
|
||||||
createJobSchedule,
|
createJobSchedule,
|
||||||
updateJobSchedule,
|
updateJobSchedule,
|
||||||
|
|||||||
@@ -44,22 +44,6 @@ export class Telemetry {
|
|||||||
private static platformInformation: PlatformInformation;
|
private static platformInformation: PlatformInformation;
|
||||||
private static disabled: boolean;
|
private static disabled: boolean;
|
||||||
|
|
||||||
// Get the unique ID for the current user of the extension
|
|
||||||
public static getUserId(): Promise<string> {
|
|
||||||
return new Promise<string>(resolve => {
|
|
||||||
// Generate the user id if it has not been created already
|
|
||||||
if (typeof this.userId === 'undefined') {
|
|
||||||
let id = Utils.generateUserId();
|
|
||||||
id.then(newId => {
|
|
||||||
this.userId = newId;
|
|
||||||
resolve(this.userId);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
resolve(this.userId);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static getPlatformInformation(): Promise<PlatformInformation> {
|
public static getPlatformInformation(): Promise<PlatformInformation> {
|
||||||
if (this.platformInformation) {
|
if (this.platformInformation) {
|
||||||
return Promise.resolve(this.platformInformation);
|
return Promise.resolve(this.platformInformation);
|
||||||
@@ -143,8 +127,7 @@ export class Telemetry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Augment the properties structure with additional common properties before sending
|
// Augment the properties structure with additional common properties before sending
|
||||||
Promise.all([this.getUserId(), this.getPlatformInformation()]).then(() => {
|
Promise.all([this.getPlatformInformation()]).then(() => {
|
||||||
properties['userId'] = this.userId;
|
|
||||||
properties['distribution'] = (this.platformInformation && this.platformInformation.distribution) ?
|
properties['distribution'] = (this.platformInformation && this.platformInformation.distribution) ?
|
||||||
`${this.platformInformation.distribution.name}, ${this.platformInformation.distribution.version}` : '';
|
`${this.platformInformation.distribution.name}, ${this.platformInformation.distribution.version}` : '';
|
||||||
|
|
||||||
|
|||||||
@@ -49,9 +49,9 @@ core-util-is@~1.0.0:
|
|||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||||
|
|
||||||
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#0.1.9":
|
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#0.2.0":
|
||||||
version "0.1.9"
|
version "0.2.0"
|
||||||
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/a1a79895cb79658b75d78aa5cfd745855019148d"
|
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/c7a691c7fc5ad54a147090784a7f11efda301f4b"
|
||||||
dependencies:
|
dependencies:
|
||||||
vscode-languageclient "3.5.0"
|
vscode-languageclient "3.5.0"
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "sqlops",
|
"name": "sqlops",
|
||||||
"version": "0.31.2",
|
"version": "0.31.4",
|
||||||
"distro": "8c3e97e3425cc9814496472ab73e076de2ba99ee",
|
"distro": "8c3e97e3425cc9814496472ab73e076de2ba99ee",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Microsoft Corporation"
|
"name": "Microsoft Corporation"
|
||||||
@@ -60,7 +60,7 @@
|
|||||||
"reflect-metadata": "^0.1.8",
|
"reflect-metadata": "^0.1.8",
|
||||||
"rxjs": "5.4.0",
|
"rxjs": "5.4.0",
|
||||||
"semver": "4.3.6",
|
"semver": "4.3.6",
|
||||||
"slickgrid": "github:anthonydresser/SlickGrid#2.3.22",
|
"slickgrid": "github:anthonydresser/SlickGrid#2.3.23",
|
||||||
"spdlog": "0.6.0",
|
"spdlog": "0.6.0",
|
||||||
"sudo-prompt": "^8.0.0",
|
"sudo-prompt": "^8.0.0",
|
||||||
"svg.js": "^2.2.5",
|
"svg.js": "^2.2.5",
|
||||||
|
|||||||
@@ -69,10 +69,10 @@ export default class MainController implements vscode.Disposable {
|
|||||||
|
|
||||||
private async getTabContent(view: sqlops.ModelView, customButton1: sqlops.window.modelviewdialog.Button, customButton2: sqlops.window.modelviewdialog.Button, componentWidth: number | string): Promise<void> {
|
private async getTabContent(view: sqlops.ModelView, customButton1: sqlops.window.modelviewdialog.Button, customButton2: sqlops.window.modelviewdialog.Button, componentWidth: number | string): Promise<void> {
|
||||||
let inputBox = view.modelBuilder.inputBox()
|
let inputBox = view.modelBuilder.inputBox()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
multiline: true,
|
multiline: true,
|
||||||
height: 100
|
height: 100
|
||||||
}).component();
|
}).component();
|
||||||
let inputBoxWrapper = view.modelBuilder.loadingComponent().withItem(inputBox).component();
|
let inputBoxWrapper = view.modelBuilder.loadingComponent().withItem(inputBox).component();
|
||||||
inputBoxWrapper.loading = false;
|
inputBoxWrapper.loading = false;
|
||||||
customButton1.onClick(() => {
|
customButton1.onClick(() => {
|
||||||
@@ -145,8 +145,8 @@ export default class MainController implements vscode.Disposable {
|
|||||||
component: inputBox4,
|
component: inputBox4,
|
||||||
title: 'inputBox4'
|
title: 'inputBox4'
|
||||||
}], {
|
}], {
|
||||||
horizontal: true
|
horizontal: true
|
||||||
}).component();
|
}).component();
|
||||||
let groupModel1 = view.modelBuilder.groupContainer()
|
let groupModel1 = view.modelBuilder.groupContainer()
|
||||||
.withLayout({
|
.withLayout({
|
||||||
}).withItems([
|
}).withItems([
|
||||||
@@ -178,8 +178,8 @@ export default class MainController implements vscode.Disposable {
|
|||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
let declarativeTable = view.modelBuilder.declarativeTable()
|
let declarativeTable = view.modelBuilder.declarativeTable()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
columns: [{
|
columns: [{
|
||||||
displayName: 'Column 1',
|
displayName: 'Column 1',
|
||||||
valueType: sqlops.DeclarativeDataType.string,
|
valueType: sqlops.DeclarativeDataType.string,
|
||||||
width: '20px',
|
width: '20px',
|
||||||
@@ -204,12 +204,12 @@ export default class MainController implements vscode.Disposable {
|
|||||||
{ name: 'options2', displayName: 'option 2' }
|
{ name: 'options2', displayName: 'option 2' }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
data: [
|
data: [
|
||||||
['Data00', 'Data01', false, 'options2'],
|
['Data00', 'Data01', false, 'options2'],
|
||||||
['Data10', 'Data11', true, 'options1']
|
['Data10', 'Data11', true, 'options1']
|
||||||
]
|
]
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
declarativeTable.onDataChanged(e => {
|
declarativeTable.onDataChanged(e => {
|
||||||
inputBox2.value = e.row.toString() + ' ' + e.column.toString() + ' ' + e.value.toString();
|
inputBox2.value = e.row.toString() + ' ' + e.column.toString() + ' ' + e.value.toString();
|
||||||
@@ -223,7 +223,7 @@ export default class MainController implements vscode.Disposable {
|
|||||||
height: 150
|
height: 150
|
||||||
}).withItems([
|
}).withItems([
|
||||||
radioButton, groupModel1, radioButton2]
|
radioButton, groupModel1, radioButton2]
|
||||||
, { flex: '1 1 50%' }).component();
|
, { flex: '1 1 50%' }).component();
|
||||||
let formModel = view.modelBuilder.formContainer()
|
let formModel = view.modelBuilder.formContainer()
|
||||||
.withFormItems([{
|
.withFormItems([{
|
||||||
component: inputBoxWrapper,
|
component: inputBoxWrapper,
|
||||||
@@ -254,9 +254,9 @@ export default class MainController implements vscode.Disposable {
|
|||||||
component: listBox,
|
component: listBox,
|
||||||
title: 'List Box'
|
title: 'List Box'
|
||||||
}], {
|
}], {
|
||||||
horizontal: false,
|
horizontal: false,
|
||||||
componentWidth: componentWidth
|
componentWidth: componentWidth
|
||||||
}).component();
|
}).component();
|
||||||
let formWrapper = view.modelBuilder.loadingComponent().withItem(formModel).component();
|
let formWrapper = view.modelBuilder.loadingComponent().withItem(formModel).component();
|
||||||
formWrapper.loading = false;
|
formWrapper.loading = false;
|
||||||
customButton2.onClick(() => {
|
customButton2.onClick(() => {
|
||||||
@@ -285,7 +285,6 @@ export default class MainController implements vscode.Disposable {
|
|||||||
tab1.registerContent(async (view) => {
|
tab1.registerContent(async (view) => {
|
||||||
await this.getTabContent(view, customButton1, customButton2, 400);
|
await this.getTabContent(view, customButton1, customButton2, 400);
|
||||||
});
|
});
|
||||||
|
|
||||||
sqlops.window.modelviewdialog.openDialog(dialog);
|
sqlops.window.modelviewdialog.openDialog(dialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,6 +301,17 @@ export default class MainController implements vscode.Disposable {
|
|||||||
page1.registerContent(async (view) => {
|
page1.registerContent(async (view) => {
|
||||||
await this.getTabContent(view, customButton1, customButton2, 800);
|
await this.getTabContent(view, customButton1, customButton2, 800);
|
||||||
});
|
});
|
||||||
|
wizard.registerOperation({
|
||||||
|
displayName: 'test task',
|
||||||
|
description: 'task description',
|
||||||
|
isCancelable: true
|
||||||
|
}, op => {
|
||||||
|
op.updateStatus(sqlops.TaskStatus.InProgress);
|
||||||
|
op.updateStatus(sqlops.TaskStatus.InProgress, 'Task is running');
|
||||||
|
setTimeout(() => {
|
||||||
|
op.updateStatus(sqlops.TaskStatus.Succeeded);
|
||||||
|
}, 5000);
|
||||||
|
});
|
||||||
wizard.pages = [page1, page2];
|
wizard.pages = [page1, page2];
|
||||||
wizard.open();
|
wizard.open();
|
||||||
}
|
}
|
||||||
@@ -379,13 +389,14 @@ export default class MainController implements vscode.Disposable {
|
|||||||
let monitorLightPath = vscode.Uri.file(path.join(__dirname, '..', 'media', 'monitor.svg'));
|
let monitorLightPath = vscode.Uri.file(path.join(__dirname, '..', 'media', 'monitor.svg'));
|
||||||
let monitorIcon = {
|
let monitorIcon = {
|
||||||
light: monitorLightPath,
|
light: monitorLightPath,
|
||||||
dark: path.join(__dirname, '..', 'media', 'monitor_inverse.svg') };
|
dark: path.join(__dirname, '..', 'media', 'monitor_inverse.svg')
|
||||||
|
};
|
||||||
|
|
||||||
let monitorButton = view.modelBuilder.button()
|
let monitorButton = view.modelBuilder.button()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
label: 'Monitor',
|
label: 'Monitor',
|
||||||
iconPath: monitorIcon
|
iconPath: monitorIcon
|
||||||
}).component();
|
}).component();
|
||||||
let toolbarModel = view.modelBuilder.toolbarContainer()
|
let toolbarModel = view.modelBuilder.toolbarContainer()
|
||||||
.withToolbarItems([{
|
.withToolbarItems([{
|
||||||
component: inputBox,
|
component: inputBox,
|
||||||
|
|||||||
@@ -63,13 +63,13 @@ export class InputBox extends vsInputBox {
|
|||||||
this.enabledInputBorder = this.inputBorder;
|
this.enabledInputBorder = this.inputBorder;
|
||||||
this.disabledInputBackground = styles.disabledInputBackground;
|
this.disabledInputBackground = styles.disabledInputBackground;
|
||||||
this.disabledInputForeground = styles.disabledInputForeground;
|
this.disabledInputForeground = styles.disabledInputForeground;
|
||||||
|
this.updateInputEnabledDisabledColors();
|
||||||
|
this.applyStyles();
|
||||||
}
|
}
|
||||||
|
|
||||||
public enable(): void {
|
public enable(): void {
|
||||||
super.enable();
|
super.enable();
|
||||||
this.inputBackground = this.enabledInputBackground;
|
this.updateInputEnabledDisabledColors();
|
||||||
this.inputForeground = this.enabledInputForeground;
|
|
||||||
this.inputBorder = this.enabledInputBorder;
|
|
||||||
this.applyStyles();
|
this.applyStyles();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,9 +89,7 @@ export class InputBox extends vsInputBox {
|
|||||||
|
|
||||||
public disable(): void {
|
public disable(): void {
|
||||||
super.disable();
|
super.disable();
|
||||||
this.inputBackground = this.disabledInputBackground;
|
this.updateInputEnabledDisabledColors();
|
||||||
this.inputForeground = this.disabledInputForeground;
|
|
||||||
this.inputBorder = this.disabledInputBorder;
|
|
||||||
this.applyStyles();
|
this.applyStyles();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,4 +119,11 @@ export class InputBox extends vsInputBox {
|
|||||||
super.showMessage(message, force);
|
super.showMessage(message, force);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private updateInputEnabledDisabledColors(): void {
|
||||||
|
let enabled = this.isEnabled();
|
||||||
|
this.inputBackground = enabled ? this.enabledInputBackground : this.disabledInputBackground;
|
||||||
|
this.inputForeground = enabled ? this.enabledInputForeground : this.disabledInputForeground;
|
||||||
|
this.inputBorder = enabled ? this.enabledInputBorder : this.disabledInputBorder;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -17,7 +17,7 @@ export function appendRow(container: Builder, label: string, labelClass: string,
|
|||||||
container.element('tr', {}, (rowContainer) => {
|
container.element('tr', {}, (rowContainer) => {
|
||||||
rowContainer.element('td', { class: labelClass }, (labelCellContainer) => {
|
rowContainer.element('td', { class: labelClass }, (labelCellContainer) => {
|
||||||
labelCellContainer.div({}, (labelContainer) => {
|
labelCellContainer.div({}, (labelContainer) => {
|
||||||
labelContainer.innerHtml(label);
|
labelContainer.text(label);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
rowContainer.element('td', { class: cellContainerClass }, (inputCellContainer) => {
|
rowContainer.element('td', { class: cellContainerClass }, (inputCellContainer) => {
|
||||||
@@ -33,7 +33,7 @@ export function appendRowLink(container: Builder, label: string, labelClass: str
|
|||||||
container.element('tr', {}, (rowContainer) => {
|
container.element('tr', {}, (rowContainer) => {
|
||||||
rowContainer.element('td', { class: labelClass }, (labelCellContainer) => {
|
rowContainer.element('td', { class: labelClass }, (labelCellContainer) => {
|
||||||
labelCellContainer.div({}, (labelContainer) => {
|
labelCellContainer.div({}, (labelContainer) => {
|
||||||
labelContainer.innerHtml(label);
|
labelContainer.text(label);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
rowContainer.element('td', { class: cellContainerClass }, (inputCellContainer) => {
|
rowContainer.element('td', { class: cellContainerClass }, (inputCellContainer) => {
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ export abstract class Modal extends Disposable implements IThemable {
|
|||||||
}
|
}
|
||||||
modalHeader.div({ class: 'modal-title' }, (modalTitle) => {
|
modalHeader.div({ class: 'modal-title' }, (modalTitle) => {
|
||||||
this._modalTitle = modalTitle;
|
this._modalTitle = modalTitle;
|
||||||
modalTitle.innerHtml(this._title);
|
modalTitle.text(this._title);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
parts.push(this._modalHeaderSection.getHTMLElement());
|
parts.push(this._modalHeaderSection.getHTMLElement());
|
||||||
@@ -433,7 +433,7 @@ export abstract class Modal extends Disposable implements IThemable {
|
|||||||
*/
|
*/
|
||||||
protected set title(title: string) {
|
protected set title(title: string) {
|
||||||
if (this._title !== undefined) {
|
if (this._title !== undefined) {
|
||||||
this._modalTitle.innerHtml(title);
|
this._modalTitle.text(title);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -150,8 +150,8 @@ export class OptionsDialog extends Modal {
|
|||||||
|
|
||||||
private onOptionLinkClicked(optionName: string): void {
|
private onOptionLinkClicked(optionName: string): void {
|
||||||
var option = this._optionElements[optionName].option;
|
var option = this._optionElements[optionName].option;
|
||||||
this._optionTitle.innerHtml(option.displayName);
|
this._optionTitle.text(option.displayName);
|
||||||
this._optionDescription.innerHtml(option.description);
|
this._optionDescription.text(option.description);
|
||||||
}
|
}
|
||||||
|
|
||||||
private fillInOptions(container: Builder, options: sqlops.ServiceOption[]): void {
|
private fillInOptions(container: Builder, options: sqlops.ServiceOption[]): void {
|
||||||
|
|||||||
@@ -5,8 +5,9 @@
|
|||||||
import { Component, Input, ContentChild, OnDestroy, TemplateRef, ChangeDetectorRef, forwardRef, Inject } from '@angular/core';
|
import { Component, Input, ContentChild, OnDestroy, TemplateRef, ChangeDetectorRef, forwardRef, Inject } from '@angular/core';
|
||||||
|
|
||||||
import { Action } from 'vs/base/common/actions';
|
import { Action } from 'vs/base/common/actions';
|
||||||
|
import { Disposable } from 'vs/base/common/lifecycle';
|
||||||
|
|
||||||
export abstract class TabChild {
|
export abstract class TabChild extends Disposable {
|
||||||
public abstract layout(): void;
|
public abstract layout(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,7 +20,7 @@ export abstract class TabChild {
|
|||||||
`
|
`
|
||||||
})
|
})
|
||||||
export class TabComponent implements OnDestroy {
|
export class TabComponent implements OnDestroy {
|
||||||
@ContentChild(TabChild) private _child: TabChild;
|
private _child: TabChild;
|
||||||
@ContentChild(TemplateRef) templateRef;
|
@ContentChild(TemplateRef) templateRef;
|
||||||
@Input() public title: string;
|
@Input() public title: string;
|
||||||
@Input() public canClose: boolean;
|
@Input() public canClose: boolean;
|
||||||
@@ -29,19 +30,30 @@ export class TabComponent implements OnDestroy {
|
|||||||
@Input() public identifier: string;
|
@Input() public identifier: string;
|
||||||
@Input() private visibilityType: 'if' | 'visibility' = 'if';
|
@Input() private visibilityType: 'if' | 'visibility' = 'if';
|
||||||
private rendered = false;
|
private rendered = false;
|
||||||
|
private destroyed: boolean = false;
|
||||||
|
|
||||||
|
|
||||||
|
@ContentChild(TabChild) private set child(tab: TabChild) {
|
||||||
|
this._child = tab;
|
||||||
|
if (this.active && this._child) {
|
||||||
|
this._child.layout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(forwardRef(() => ChangeDetectorRef)) private _cd: ChangeDetectorRef
|
@Inject(forwardRef(() => ChangeDetectorRef)) private _cd: ChangeDetectorRef
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
public set active(val: boolean) {
|
public set active(val: boolean) {
|
||||||
this._active = val;
|
if (!this.destroyed) {
|
||||||
if (this.active) {
|
this._active = val;
|
||||||
this.rendered = true;
|
if (this.active) {
|
||||||
}
|
this.rendered = true;
|
||||||
this._cd.detectChanges();
|
}
|
||||||
if (this.active && this._child) {
|
this._cd.detectChanges();
|
||||||
this._child.layout();
|
if (this.active && this._child) {
|
||||||
|
this._child.layout();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,6 +62,7 @@ export class TabComponent implements OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
|
this.destroyed = true;
|
||||||
if (this.actions && this.actions.length > 0) {
|
if (this.actions && this.actions.length > 0) {
|
||||||
this.actions.forEach((action) => action.dispose());
|
this.actions.forEach((action) => action.dispose());
|
||||||
}
|
}
|
||||||
@@ -74,6 +87,8 @@ export class TabComponent implements OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public layout() {
|
public layout() {
|
||||||
this._child.layout();
|
if (this._child) {
|
||||||
|
this._child.layout();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ export class TabHeaderComponent extends Disposable implements AfterContentInit,
|
|||||||
tabLabelcontainer.classList.add(this.tab.iconClass);
|
tabLabelcontainer.classList.add(this.tab.iconClass);
|
||||||
} else {
|
} else {
|
||||||
tabLabelcontainer.className = 'tabLabel';
|
tabLabelcontainer.className = 'tabLabel';
|
||||||
tabLabelcontainer.innerHTML = this.tab.title;
|
tabLabelcontainer.textContent = this.tab.title;
|
||||||
}
|
}
|
||||||
tabLabelcontainer.title = this.tab.title;
|
tabLabelcontainer.title = this.tab.title;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,7 +84,7 @@
|
|||||||
{
|
{
|
||||||
border: 1px solid #BFBDBD;
|
border: 1px solid #BFBDBD;
|
||||||
font-size: 8pt;
|
font-size: 8pt;
|
||||||
height: 400px;
|
height: 250px;
|
||||||
margin-top: 6px;
|
margin-top: 6px;
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { mixin } from 'vs/base/common/objects';
|
|||||||
import { SlickGrid } from 'angular2-slickgrid';
|
import { SlickGrid } from 'angular2-slickgrid';
|
||||||
import { Button } from '../../button/button';
|
import { Button } from '../../button/button';
|
||||||
import { attachButtonStyler } from 'sql/common/theme/styler';
|
import { attachButtonStyler } from 'sql/common/theme/styler';
|
||||||
|
import { escape } from 'sql/base/common/strings';
|
||||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||||
|
|
||||||
export class HeaderFilter {
|
export class HeaderFilter {
|
||||||
@@ -174,7 +175,7 @@ export class HeaderFilter {
|
|||||||
if (filterItems[i] && filterItems[i].indexOf('Error:') < 0) {
|
if (filterItems[i] && filterItems[i].indexOf('Error:') < 0) {
|
||||||
filterOptions += '<label><input type="checkbox" value="' + i + '"'
|
filterOptions += '<label><input type="checkbox" value="' + i + '"'
|
||||||
+ (filtered ? ' checked="checked"' : '')
|
+ (filtered ? ' checked="checked"' : '')
|
||||||
+ '/>' + filterItems[i] + '</label>';
|
+ '/>' + escape(filterItems[i]) + '</label>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let $filter = $('<div class="filter">')
|
let $filter = $('<div class="filter">')
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// Adopted and converted to typescript from https://github.com/6pac/SlickGrid/blob/master/plugins/slick.rowdetailview.js
|
// Adopted and converted to typescript from https://github.com/6pac/SlickGrid/blob/master/plugins/slick.rowdetailview.js
|
||||||
// heavily modified
|
// heavily modified
|
||||||
|
import { escape } from 'sql/base/common/strings';
|
||||||
import { mixin } from 'vs/base/common/objects';
|
import { mixin } from 'vs/base/common/objects';
|
||||||
import * as nls from 'vs/nls';
|
import * as nls from 'vs/nls';
|
||||||
|
|
||||||
@@ -354,7 +355,7 @@ export class RowDetailView {
|
|||||||
html.push("style='height:", dataContext._height, "px;"); //set total height of padding
|
html.push("style='height:", dataContext._height, "px;"); //set total height of padding
|
||||||
html.push("top:", rowHeight, "px'>"); //shift detail below 1st row
|
html.push("top:", rowHeight, "px'>"); //shift detail below 1st row
|
||||||
html.push("<div id='detailViewContainer_", dataContext.id, "' class='detail-container' style='max-height:" + (dataContext._height - rowHeight + bottomMargin) + "px'>"); //sub ctr for custom styling
|
html.push("<div id='detailViewContainer_", dataContext.id, "' class='detail-container' style='max-height:" + (dataContext._height - rowHeight + bottomMargin) + "px'>"); //sub ctr for custom styling
|
||||||
html.push("<div id='innerDetailView_", dataContext.id, "'>", dataContext._detailContent, "</div></div>");
|
html.push("<div id='innerDetailView_", dataContext.id, "'>", escape(dataContext._detailContent), "</div></div>");
|
||||||
//&omit a final closing detail container </div> that would come next
|
//&omit a final closing detail container </div> that would come next
|
||||||
|
|
||||||
return html.join('');
|
return html.join('');
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ export class Taskbar {
|
|||||||
public static createTaskbarText(inputText: string): HTMLElement {
|
public static createTaskbarText(inputText: string): HTMLElement {
|
||||||
let element = document.createElement('div');
|
let element = document.createElement('div');
|
||||||
element.className = 'taskbarTextSeparator';
|
element.className = 'taskbarTextSeparator';
|
||||||
element.innerHTML = inputText;
|
element.textContent = inputText;
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,3 +13,6 @@ export const SerializationDisabled = 'Saving results into different format disab
|
|||||||
*/
|
*/
|
||||||
export const RestoreFeatureName = 'restore';
|
export const RestoreFeatureName = 'restore';
|
||||||
export const BackupFeatureName = 'backup';
|
export const BackupFeatureName = 'backup';
|
||||||
|
|
||||||
|
export const MssqlProviderId = 'MSSQL';
|
||||||
|
|
||||||
|
|||||||
@@ -81,6 +81,15 @@
|
|||||||
content: url("status_info.svg");
|
content: url("status_info.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vs .icon.help {
|
||||||
|
content: url("help.svg");
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs-dark .icon.help,
|
||||||
|
.hc-black .icon.help {
|
||||||
|
content: url("help_inverse.svg");
|
||||||
|
}
|
||||||
|
|
||||||
.vs .icon.success,
|
.vs .icon.success,
|
||||||
.vs-dark .icon.success,
|
.vs-dark .icon.success,
|
||||||
.hc-black .icon.success {
|
.hc-black .icon.success {
|
||||||
|
|||||||
1
src/sql/media/icons/help.svg
Normal file
1
src/sql/media/icons/help.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><title>help_16x16</title><path d="M10.13.45A8.14,8.14,0,0,1,12,1.23a8,8,0,0,1,1.62,1.21A7.8,7.8,0,0,1,14.91,4a7.59,7.59,0,0,1,.81,1.85,7.6,7.6,0,0,1,0,4.12,7.59,7.59,0,0,1-.81,1.85,7.8,7.8,0,0,1-1.25,1.57A8,8,0,0,1,12,14.62a8.2,8.2,0,0,1-8.08,0,8,8,0,0,1-1.62-1.21,7.8,7.8,0,0,1-1.25-1.57A7.63,7.63,0,0,1,.28,10a7.6,7.6,0,0,1,0-4.12A7.63,7.63,0,0,1,1.09,4,7.8,7.8,0,0,1,2.34,2.44,8,8,0,0,1,4,1.23,8.26,8.26,0,0,1,10.13.45Zm-.27,14a7.17,7.17,0,0,0,1.67-.69,7,7,0,0,0,1.41-1.06,6.75,6.75,0,0,0,1.8-3,6.59,6.59,0,0,0,0-3.6,6.75,6.75,0,0,0-1.8-3,7,7,0,0,0-1.41-1.06,7.17,7.17,0,0,0-1.67-.69,7.21,7.21,0,0,0-3.72,0,7.17,7.17,0,0,0-1.67.69A7,7,0,0,0,3.05,3.13,6.82,6.82,0,0,0,2,4.5a6.72,6.72,0,0,0-.71,1.62,6.59,6.59,0,0,0,0,3.6A6.72,6.72,0,0,0,2,11.35a6.82,6.82,0,0,0,1.09,1.37,7,7,0,0,0,1.41,1.06,7.17,7.17,0,0,0,1.67.69,7.21,7.21,0,0,0,3.72,0ZM9,4a2.75,2.75,0,0,1,.85.56,2.61,2.61,0,0,1,.57.82,2.44,2.44,0,0,1,.21,1,2.08,2.08,0,0,1-.16.85,2.82,2.82,0,0,1-.4.65,4.28,4.28,0,0,1-.51.53c-.18.16-.36.32-.51.48a2.55,2.55,0,0,0-.4.51,1.19,1.19,0,0,0-.16.61v.52H7.46V10a2.09,2.09,0,0,1,.16-.85A2.86,2.86,0,0,1,8,8.5,4.28,4.28,0,0,1,8.54,8c.18-.16.36-.32.51-.48A2.51,2.51,0,0,0,9.45,7a1.18,1.18,0,0,0,.16-.61,1.49,1.49,0,0,0-.13-.61,1.56,1.56,0,0,0-.34-.49A1.63,1.63,0,0,0,8,4.81a1.63,1.63,0,0,0-1.14.45,1.57,1.57,0,0,0-.34.49,1.49,1.49,0,0,0-.13.61H5.32a2.41,2.41,0,0,1,.21-1,2.68,2.68,0,0,1,.58-.82A2.77,2.77,0,0,1,7,4a2.62,2.62,0,0,1,1-.21A2.65,2.65,0,0,1,9,4ZM8.54,12.6H7.46v-1H8.54Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
1
src/sql/media/icons/help_inverse.svg
Normal file
1
src/sql/media/icons/help_inverse.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.cls-1{fill:#fff;}</style></defs><title>help_inverse_16x16</title><path class="cls-1" d="M10.13.45A8.14,8.14,0,0,1,12,1.23a8,8,0,0,1,1.62,1.21A7.8,7.8,0,0,1,14.91,4a7.59,7.59,0,0,1,.81,1.85,7.6,7.6,0,0,1,0,4.12,7.59,7.59,0,0,1-.81,1.85,7.8,7.8,0,0,1-1.25,1.57A8,8,0,0,1,12,14.62a8.2,8.2,0,0,1-8.08,0,8,8,0,0,1-1.62-1.21,7.8,7.8,0,0,1-1.25-1.57A7.63,7.63,0,0,1,.28,10a7.6,7.6,0,0,1,0-4.12A7.63,7.63,0,0,1,1.09,4,7.8,7.8,0,0,1,2.34,2.44,8,8,0,0,1,4,1.23,8.26,8.26,0,0,1,10.13.45Zm-.27,14a7.17,7.17,0,0,0,1.67-.69,7,7,0,0,0,1.41-1.06,6.75,6.75,0,0,0,1.8-3,6.59,6.59,0,0,0,0-3.6,6.75,6.75,0,0,0-1.8-3,7,7,0,0,0-1.41-1.06,7.17,7.17,0,0,0-1.67-.69,7.21,7.21,0,0,0-3.72,0,7.17,7.17,0,0,0-1.67.69A7,7,0,0,0,3.05,3.13,6.82,6.82,0,0,0,2,4.5a6.72,6.72,0,0,0-.71,1.62,6.59,6.59,0,0,0,0,3.6A6.72,6.72,0,0,0,2,11.35a6.82,6.82,0,0,0,1.09,1.37,7,7,0,0,0,1.41,1.06,7.17,7.17,0,0,0,1.67.69,7.21,7.21,0,0,0,3.72,0ZM9,4a2.75,2.75,0,0,1,.85.56,2.61,2.61,0,0,1,.57.82,2.44,2.44,0,0,1,.21,1,2.08,2.08,0,0,1-.16.85,2.82,2.82,0,0,1-.4.65,4.28,4.28,0,0,1-.51.53c-.18.16-.36.32-.51.48a2.55,2.55,0,0,0-.4.51,1.19,1.19,0,0,0-.16.61v.52H7.46V10a2.09,2.09,0,0,1,.16-.85A2.86,2.86,0,0,1,8,8.5,4.28,4.28,0,0,1,8.54,8c.18-.16.36-.32.51-.48A2.51,2.51,0,0,0,9.45,7a1.18,1.18,0,0,0,.16-.61,1.49,1.49,0,0,0-.13-.61,1.56,1.56,0,0,0-.34-.49A1.63,1.63,0,0,0,8,4.81a1.63,1.63,0,0,0-1.14.45,1.57,1.57,0,0,0-.34.49,1.49,1.49,0,0,0-.13.61H5.32a2.41,2.41,0,0,1,.21-1,2.68,2.68,0,0,1,.58-.82A2.77,2.77,0,0,1,7,4a2.62,2.62,0,0,1,1-.21A2.65,2.65,0,0,1,9,4ZM8.54,12.6H7.46v-1H8.54Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -131,7 +131,7 @@ export class AccountDialog extends Modal {
|
|||||||
this._noaccountViewContainer = DOM.$('div.no-account-view');
|
this._noaccountViewContainer = DOM.$('div.no-account-view');
|
||||||
let noAccountTitle = DOM.append(this._noaccountViewContainer, DOM.$('.no-account-view-label'));
|
let noAccountTitle = DOM.append(this._noaccountViewContainer, DOM.$('.no-account-view-label'));
|
||||||
let noAccountLabel = localize('accountDialog.noAccountLabel', 'There is no linked account. Please add an account.');
|
let noAccountLabel = localize('accountDialog.noAccountLabel', 'There is no linked account. Please add an account.');
|
||||||
noAccountTitle.innerHTML = noAccountLabel;
|
noAccountTitle.innerText = noAccountLabel;
|
||||||
|
|
||||||
// Show the add account button for the first provider
|
// Show the add account button for the first provider
|
||||||
// Todo: If we have more than 1 provider, need to show all add account buttons for all providers
|
// Todo: If we have more than 1 provider, need to show all add account buttons for all providers
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ export class AutoOAuthDialog extends Modal {
|
|||||||
let inputBox: InputBox;
|
let inputBox: InputBox;
|
||||||
container.div({ class: 'dialog-input-section' }, (inputContainer) => {
|
container.div({ class: 'dialog-input-section' }, (inputContainer) => {
|
||||||
inputContainer.div({ class: 'dialog-label' }, (labelContainer) => {
|
inputContainer.div({ class: 'dialog-label' }, (labelContainer) => {
|
||||||
labelContainer.innerHtml(label);
|
labelContainer.text(label);
|
||||||
});
|
});
|
||||||
|
|
||||||
inputContainer.div({ class: 'dialog-input' }, (inputCellContainer) => {
|
inputContainer.div({ class: 'dialog-input' }, (inputCellContainer) => {
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ export class FirewallRuleDialog extends Modal {
|
|||||||
subnetIPRangeSection = subnetIPRangeContainer.getHTMLElement();
|
subnetIPRangeSection = subnetIPRangeContainer.getHTMLElement();
|
||||||
subnetIPRangeContainer.div({ 'class': 'dialog-input-section' }, (inputContainer) => {
|
subnetIPRangeContainer.div({ 'class': 'dialog-input-section' }, (inputContainer) => {
|
||||||
inputContainer.div({ 'class': 'dialog-label' }, (labelContainer) => {
|
inputContainer.div({ 'class': 'dialog-label' }, (labelContainer) => {
|
||||||
labelContainer.innerHtml(LocalizedStrings.FROM);
|
labelContainer.text(LocalizedStrings.FROM);
|
||||||
});
|
});
|
||||||
|
|
||||||
inputContainer.div({ 'class': 'dialog-input' }, (inputCellContainer) => {
|
inputContainer.div({ 'class': 'dialog-input' }, (inputCellContainer) => {
|
||||||
@@ -155,7 +155,7 @@ export class FirewallRuleDialog extends Modal {
|
|||||||
});
|
});
|
||||||
|
|
||||||
inputContainer.div({ 'class': 'dialog-label' }, (labelContainer) => {
|
inputContainer.div({ 'class': 'dialog-label' }, (labelContainer) => {
|
||||||
labelContainer.innerHtml(LocalizedStrings.TO);
|
labelContainer.text(LocalizedStrings.TO);
|
||||||
});
|
});
|
||||||
|
|
||||||
inputContainer.div({ 'class': 'dialog-input' }, (inputCellContainer) => {
|
inputContainer.div({ 'class': 'dialog-input' }, (inputCellContainer) => {
|
||||||
@@ -234,7 +234,7 @@ export class FirewallRuleDialog extends Modal {
|
|||||||
className += ' header';
|
className += ' header';
|
||||||
}
|
}
|
||||||
container.div({ 'class': className }, (labelContainer) => {
|
container.div({ 'class': className }, (labelContainer) => {
|
||||||
labelContainer.innerHtml(content);
|
labelContainer.text(content);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
import { RawContextKey, IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
import { RawContextKey, IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||||
import { IConnectionProfile } from 'sqlops';
|
import { IConnectionProfile } from 'sqlops';
|
||||||
|
|
||||||
export class ConnectionContextkey implements IContextKey<IConnectionProfile> {
|
export class ConnectionContextKey implements IContextKey<IConnectionProfile> {
|
||||||
|
|
||||||
static Provider = new RawContextKey<string>('connectionProvider', undefined);
|
static Provider = new RawContextKey<string>('connectionProvider', undefined);
|
||||||
static Server = new RawContextKey<string>('serverName', undefined);
|
static Server = new RawContextKey<string>('serverName', undefined);
|
||||||
@@ -23,10 +23,10 @@ export class ConnectionContextkey implements IContextKey<IConnectionProfile> {
|
|||||||
constructor(
|
constructor(
|
||||||
@IContextKeyService contextKeyService: IContextKeyService
|
@IContextKeyService contextKeyService: IContextKeyService
|
||||||
) {
|
) {
|
||||||
this._providerKey = ConnectionContextkey.Provider.bindTo(contextKeyService);
|
this._providerKey = ConnectionContextKey.Provider.bindTo(contextKeyService);
|
||||||
this._serverKey = ConnectionContextkey.Server.bindTo(contextKeyService);
|
this._serverKey = ConnectionContextKey.Server.bindTo(contextKeyService);
|
||||||
this._databaseKey = ConnectionContextkey.Database.bindTo(contextKeyService);
|
this._databaseKey = ConnectionContextKey.Database.bindTo(contextKeyService);
|
||||||
this._connectionKey = ConnectionContextkey.Connection.bindTo(contextKeyService);
|
this._connectionKey = ConnectionContextKey.Connection.bindTo(contextKeyService);
|
||||||
}
|
}
|
||||||
|
|
||||||
set(value: IConnectionProfile) {
|
set(value: IConnectionProfile) {
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ export interface IConnectionManagementService {
|
|||||||
|
|
||||||
disconnectEditor(owner: IConnectableInput, force?: boolean): Promise<boolean>;
|
disconnectEditor(owner: IConnectableInput, force?: boolean): Promise<boolean>;
|
||||||
|
|
||||||
disconnect(connection: ConnectionProfile): Promise<void>;
|
disconnect(connection: IConnectionProfile): Promise<void>;
|
||||||
|
|
||||||
disconnect(ownerUri: string): Promise<void>;
|
disconnect(ownerUri: string): Promise<void>;
|
||||||
|
|
||||||
@@ -208,7 +208,7 @@ export interface IConnectionManagementService {
|
|||||||
*/
|
*/
|
||||||
cancelEditorConnection(owner: IConnectableInput): Thenable<boolean>;
|
cancelEditorConnection(owner: IConnectableInput): Thenable<boolean>;
|
||||||
|
|
||||||
showDashboard(connection: ConnectionProfile): Thenable<boolean>;
|
showDashboard(connection: IConnectionProfile): Thenable<boolean>;
|
||||||
|
|
||||||
closeDashboard(uri: string): void;
|
closeDashboard(uri: string): void;
|
||||||
|
|
||||||
@@ -216,7 +216,7 @@ export interface IConnectionManagementService {
|
|||||||
|
|
||||||
hasRegisteredServers(): boolean;
|
hasRegisteredServers(): boolean;
|
||||||
|
|
||||||
canChangeConnectionConfig(profile: ConnectionProfile, newGroupID: string): boolean;
|
canChangeConnectionConfig(profile: IConnectionProfile, newGroupID: string): boolean;
|
||||||
|
|
||||||
getTabColorForUri(uri: string): string;
|
getTabColorForUri(uri: string): string;
|
||||||
|
|
||||||
@@ -320,12 +320,13 @@ export enum MetadataType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export enum TaskStatus {
|
export enum TaskStatus {
|
||||||
notStarted = 0,
|
NotStarted = 0,
|
||||||
inProgress = 1,
|
InProgress = 1,
|
||||||
succeeded = 2,
|
Succeeded = 2,
|
||||||
succeededWithWarning = 3,
|
SucceededWithWarning = 3,
|
||||||
failed = 4,
|
Failed = 4,
|
||||||
canceled = 5
|
Canceled = 5,
|
||||||
|
Canceling = 6
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IConnectionParams {
|
export interface IConnectionParams {
|
||||||
|
|||||||
@@ -553,7 +553,7 @@ export class ConnectionManagementService extends Disposable implements IConnecti
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public showDashboard(connection: ConnectionProfile): Thenable<boolean> {
|
public showDashboard(connection: IConnectionProfile): Thenable<boolean> {
|
||||||
return this.showDashboardForConnectionManagementInfo(connection);
|
return this.showDashboardForConnectionManagementInfo(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -240,7 +240,7 @@ export class ConnectionStore {
|
|||||||
return connectionProfile;
|
return connectionProfile;
|
||||||
} else {
|
} else {
|
||||||
return undefined;
|
return undefined;
|
||||||
};
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,7 +352,7 @@ export class ConnectionStore {
|
|||||||
list.unshift(savedProfile);
|
list.unshift(savedProfile);
|
||||||
|
|
||||||
let newList = list.map(c => {
|
let newList = list.map(c => {
|
||||||
let connectionProfile = c ? c.toIConnectionProfile() : undefined;;
|
let connectionProfile = c ? c.toIConnectionProfile() : undefined;
|
||||||
return connectionProfile;
|
return connectionProfile;
|
||||||
});
|
});
|
||||||
return newList.filter(n => n !== undefined);
|
return newList.filter(n => n !== undefined);
|
||||||
@@ -372,7 +372,7 @@ export class ConnectionStore {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let newList = list.map(c => {
|
let newList = list.map(c => {
|
||||||
let connectionProfile = c ? c.toIConnectionProfile() : undefined;;
|
let connectionProfile = c ? c.toIConnectionProfile() : undefined;
|
||||||
return connectionProfile;
|
return connectionProfile;
|
||||||
});
|
});
|
||||||
return newList.filter(n => n !== undefined);
|
return newList.filter(n => n !== undefined);
|
||||||
|
|||||||
@@ -339,9 +339,9 @@ export class ConnectionDialogService implements IConnectionDialogService {
|
|||||||
if (!platform.isWindows && types.isString(message) && message.toLowerCase().includes('kerberos') && message.toLowerCase().includes('kinit')) {
|
if (!platform.isWindows && types.isString(message) && message.toLowerCase().includes('kerberos') && message.toLowerCase().includes('kinit')) {
|
||||||
message = [
|
message = [
|
||||||
localize('kerberosErrorStart', "Connection failed due to Kerberos error."),
|
localize('kerberosErrorStart', "Connection failed due to Kerberos error."),
|
||||||
localize('kerberosHelpLink', " Help configuring Kerberos is available at ") + helpLink,
|
localize('kerberosHelpLink', "Help configuring Kerberos is available at {0}", helpLink),
|
||||||
localize('kerberosKinit', " If you have previously connected you may need to re-run kinit.")
|
localize('kerberosKinit', "If you have previously connected you may need to re-run kinit.")
|
||||||
].join('<br/>');
|
].join('\r\n');
|
||||||
actions.push(new Action('Kinit', 'Run kinit', null, true, () => {
|
actions.push(new Action('Kinit', 'Run kinit', null, true, () => {
|
||||||
this._connectionDialog.close();
|
this._connectionDialog.close();
|
||||||
this._clipboardService.writeText('kinit\r');
|
this._clipboardService.writeText('kinit\r');
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ export class ConnectionDialogWidget extends Modal {
|
|||||||
let recentHistoryLabel = localize('recentHistory', 'Recent history');
|
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) => {
|
container.div({ class: 'connection-history-label' }, (recentTitle) => {
|
||||||
recentTitle.innerHtml(recentHistoryLabel);
|
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 }));
|
||||||
@@ -303,7 +303,7 @@ export class ConnectionDialogWidget extends Modal {
|
|||||||
this._noRecentConnectionBuilder.div({ class: 'connection-recent-content' }, (noRecentConnectionContainer) => {
|
this._noRecentConnectionBuilder.div({ class: 'connection-recent-content' }, (noRecentConnectionContainer) => {
|
||||||
let noRecentHistoryLabel = localize('noRecentConnections', 'No recent connection');
|
let noRecentHistoryLabel = localize('noRecentConnections', 'No recent connection');
|
||||||
noRecentConnectionContainer.div({ class: 'no-recent-connections' }, (noRecentTitle) => {
|
noRecentConnectionContainer.div({ class: 'no-recent-connections' }, (noRecentTitle) => {
|
||||||
noRecentTitle.innerHtml(noRecentHistoryLabel);
|
noRecentTitle.text(noRecentHistoryLabel);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -335,7 +335,7 @@ export class ConnectionDialogWidget extends Modal {
|
|||||||
this._noSavedConnectionBuilder.div({ class: 'connection-saved-content' }, (noSavedConnectionContainer) => {
|
this._noSavedConnectionBuilder.div({ class: 'connection-saved-content' }, (noSavedConnectionContainer) => {
|
||||||
let noSavedConnectionLabel = localize('noSavedConnections', 'No saved connection');
|
let noSavedConnectionLabel = localize('noSavedConnections', 'No saved connection');
|
||||||
noSavedConnectionContainer.div({ class: 'no-saved-connections' }, (titleContainer) => {
|
noSavedConnectionContainer.div({ class: 'no-saved-connections' }, (titleContainer) => {
|
||||||
titleContainer.innerHtml(noSavedConnectionLabel);
|
titleContainer.text(noSavedConnectionLabel);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,22 +32,10 @@ export abstract class DashboardTab extends TabChild implements OnDestroy {
|
|||||||
public enableEdit(): void {
|
public enableEdit(): void {
|
||||||
// no op
|
// no op
|
||||||
}
|
}
|
||||||
|
|
||||||
private _toDispose: IDisposable[] = [];
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public dispose(): void {
|
|
||||||
this._toDispose = dispose(this._toDispose);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected _register<T extends IDisposable>(t: T): T {
|
|
||||||
this._toDispose.push(t);
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
this.dispose();
|
this.dispose();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export class DashboardErrorContainer extends DashboardTab implements AfterViewIn
|
|||||||
|
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
let errorMessage = this._errorMessageContainer.nativeElement as HTMLElement;
|
let errorMessage = this._errorMessageContainer.nativeElement as HTMLElement;
|
||||||
errorMessage.innerHTML = nls.localize('dashboardNavSection_loadTabError', 'The "{0}" section has invalid content. Please contact extension owner.', this.tab.title);
|
errorMessage.innerText = nls.localize('dashboardNavSection_loadTabError', 'The "{0}" section has invalid content. Please contact extension owner.', this.tab.title);
|
||||||
}
|
}
|
||||||
|
|
||||||
public get id(): string {
|
public get id(): string {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import { DashboardModule } from './dashboard.module';
|
|||||||
import { bootstrapAngular } from 'sql/services/bootstrap/bootstrapService';
|
import { bootstrapAngular } from 'sql/services/bootstrap/bootstrapService';
|
||||||
import { IDashboardComponentParams } from 'sql/services/bootstrap/bootstrapParams';
|
import { IDashboardComponentParams } from 'sql/services/bootstrap/bootstrapParams';
|
||||||
import { DASHBOARD_SELECTOR } from 'sql/parts/dashboard/dashboard.component';
|
import { DASHBOARD_SELECTOR } from 'sql/parts/dashboard/dashboard.component';
|
||||||
import { ConnectionContextkey } from 'sql/parts/connection/common/connectionContextKey';
|
import { ConnectionContextKey } from 'sql/parts/connection/common/connectionContextKey';
|
||||||
import { IDashboardService } from 'sql/services/dashboard/common/dashboardService';
|
import { IDashboardService } from 'sql/services/dashboard/common/dashboardService';
|
||||||
import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
|
import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
|
||||||
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
||||||
@@ -71,6 +71,7 @@ export class DashboardEditor extends BaseEditor {
|
|||||||
* To be called when the container of this editor changes size.
|
* To be called when the container of this editor changes size.
|
||||||
*/
|
*/
|
||||||
public layout(dimension: DOM.Dimension): void {
|
public layout(dimension: DOM.Dimension): void {
|
||||||
|
this._dashboardService.layout(dimension);
|
||||||
}
|
}
|
||||||
|
|
||||||
public setInput(input: DashboardInput, options: EditorOptions): TPromise<void> {
|
public setInput(input: DashboardInput, options: EditorOptions): TPromise<void> {
|
||||||
@@ -110,7 +111,7 @@ export class DashboardEditor extends BaseEditor {
|
|||||||
let serverInfo = this._connMan.getConnectionInfo(this.input.uri).serverInfo;
|
let serverInfo = this._connMan.getConnectionInfo(this.input.uri).serverInfo;
|
||||||
this._dashboardService.changeToDashboard({ profile, serverInfo });
|
this._dashboardService.changeToDashboard({ profile, serverInfo });
|
||||||
let scopedContextService = this._contextKeyService.createScoped(input.container);
|
let scopedContextService = this._contextKeyService.createScoped(input.container);
|
||||||
let connectionContextKey = new ConnectionContextkey(scopedContextService);
|
let connectionContextKey = new ConnectionContextKey(scopedContextService);
|
||||||
connectionContextKey.set(input.connectionProfile);
|
connectionContextKey.set(input.connectionProfile);
|
||||||
|
|
||||||
let params: IDashboardComponentParams = {
|
let params: IDashboardComponentParams = {
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ export class NewDashboardTabDialog extends Modal {
|
|||||||
this._noExtensionViewContainer = DOM.$('.no-extension-view');
|
this._noExtensionViewContainer = DOM.$('.no-extension-view');
|
||||||
let noExtensionTitle = DOM.append(this._noExtensionViewContainer, DOM.$('.no-extensionTab-label'));
|
let noExtensionTitle = DOM.append(this._noExtensionViewContainer, DOM.$('.no-extensionTab-label'));
|
||||||
let noExtensionLabel = localize('newdashboardTabDialog.noExtensionLabel', 'No dashboard extensions are installed at this time. Go to Extension Manager to explore recommended extensions.');
|
let noExtensionLabel = localize('newdashboardTabDialog.noExtensionLabel', 'No dashboard extensions are installed at this time. Go to Extension Manager to explore recommended extensions.');
|
||||||
noExtensionTitle.innerHTML = noExtensionLabel;
|
noExtensionTitle.textContent = noExtensionLabel;
|
||||||
|
|
||||||
DOM.append(container, this._noExtensionViewContainer);
|
DOM.append(container, this._noExtensionViewContainer);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import {
|
|||||||
import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
|
import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
|
||||||
import { ConnectionManagementInfo } from 'sql/parts/connection/common/connectionManagementInfo';
|
import { ConnectionManagementInfo } from 'sql/parts/connection/common/connectionManagementInfo';
|
||||||
import * as Constants from 'sql/parts/connection/common/constants';
|
import * as Constants from 'sql/parts/connection/common/constants';
|
||||||
import { OEAction } from 'sql/parts/objectExplorer/viewlet/objectExplorerActions';
|
|
||||||
import { IQueryEditorService } from 'sql/parts/query/common/queryEditorService';
|
import { IQueryEditorService } from 'sql/parts/query/common/queryEditorService';
|
||||||
import { IScriptingService } from 'sql/services/scripting/scriptingService';
|
import { IScriptingService } from 'sql/services/scripting/scriptingService';
|
||||||
|
|
||||||
|
|||||||
@@ -179,8 +179,8 @@ export class RestoreDialogController implements IRestoreDialogController {
|
|||||||
private isSuccessfulRestore(response: TaskNode): boolean {
|
private isSuccessfulRestore(response: TaskNode): boolean {
|
||||||
return (response.taskName === this._restoreTaskName &&
|
return (response.taskName === this._restoreTaskName &&
|
||||||
response.message === this._restoreCompleted &&
|
response.message === this._restoreCompleted &&
|
||||||
(response.status === TaskStatus.succeeded ||
|
(response.status === TaskStatus.Succeeded ||
|
||||||
response.status === TaskStatus.succeededWithWarning) &&
|
response.status === TaskStatus.SucceededWithWarning) &&
|
||||||
(response.taskExecutionMode === TaskExecutionMode.execute ||
|
(response.taskExecutionMode === TaskExecutionMode.execute ||
|
||||||
response.taskExecutionMode === TaskExecutionMode.executeAndScript));
|
response.taskExecutionMode === TaskExecutionMode.executeAndScript));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ export class RestoreDialog extends Modal {
|
|||||||
|
|
||||||
destinationContainer.div({ class: 'dialog-input-section' }, (inputContainer) => {
|
destinationContainer.div({ class: 'dialog-input-section' }, (inputContainer) => {
|
||||||
inputContainer.div({ class: 'dialog-label' }, (labelContainer) => {
|
inputContainer.div({ class: 'dialog-label' }, (labelContainer) => {
|
||||||
labelContainer.innerHtml(LocalizedStrings.TARGETDATABASE);
|
labelContainer.text(LocalizedStrings.TARGETDATABASE);
|
||||||
});
|
});
|
||||||
|
|
||||||
inputContainer.div({ class: 'dialog-input' }, (inputCellContainer) => {
|
inputContainer.div({ class: 'dialog-input' }, (inputCellContainer) => {
|
||||||
@@ -471,7 +471,7 @@ export class RestoreDialog extends Modal {
|
|||||||
className += ' header';
|
className += ' header';
|
||||||
}
|
}
|
||||||
container.div({ class: className }, (labelContainer) => {
|
container.div({ class: className }, (labelContainer) => {
|
||||||
labelContainer.innerHtml(content);
|
labelContainer.text(content);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -535,7 +535,7 @@ export class RestoreDialog extends Modal {
|
|||||||
let selectBox: SelectBox;
|
let selectBox: SelectBox;
|
||||||
container.div({ class: 'dialog-input-section' }, (inputContainer) => {
|
container.div({ class: 'dialog-input-section' }, (inputContainer) => {
|
||||||
inputContainer.div({ class: 'dialog-label' }, (labelContainer) => {
|
inputContainer.div({ class: 'dialog-label' }, (labelContainer) => {
|
||||||
labelContainer.innerHtml(label);
|
labelContainer.text(label);
|
||||||
});
|
});
|
||||||
|
|
||||||
inputContainer.div({ class: 'dialog-input' }, (inputCellContainer) => {
|
inputContainer.div({ class: 'dialog-input' }, (inputCellContainer) => {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import { error } from 'sql/base/common/log';
|
|||||||
import { clone, mixin } from 'sql/base/common/objects';
|
import { clone, mixin } from 'sql/base/common/objects';
|
||||||
import { IQueryEditorService } from 'sql/parts/query/common/queryEditorService';
|
import { IQueryEditorService } from 'sql/parts/query/common/queryEditorService';
|
||||||
import { IBootstrapParams } from 'sql/services/bootstrap/bootstrapService';
|
import { IBootstrapParams } from 'sql/services/bootstrap/bootstrapService';
|
||||||
|
import { escape } from 'sql/base/common/strings';
|
||||||
|
|
||||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||||
import Severity from 'vs/base/common/severity';
|
import Severity from 'vs/base/common/severity';
|
||||||
@@ -197,7 +198,7 @@ export class EditDataComponent extends GridParentComponent implements OnInit, On
|
|||||||
rowIndex++;
|
rowIndex++;
|
||||||
return {
|
return {
|
||||||
values: row.cells.map(c => {
|
values: row.cells.map(c => {
|
||||||
return mixin({ ariaLabel: c.displayValue }, c);
|
return mixin({ ariaLabel: escape(c.displayValue) }, c);
|
||||||
}), row: row.id
|
}), row: row.id
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -367,11 +368,12 @@ export class EditDataComponent extends GridParentComponent implements OnInit, On
|
|||||||
columnDefinitions: resultSet.columnInfo.map((c, i) => {
|
columnDefinitions: resultSet.columnInfo.map((c, i) => {
|
||||||
let isLinked = c.isXml || c.isJson;
|
let isLinked = c.isXml || c.isJson;
|
||||||
let linkType = c.isXml ? 'xml' : 'json';
|
let linkType = c.isXml ? 'xml' : 'json';
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: i.toString(),
|
id: i.toString(),
|
||||||
name: c.columnName === 'Microsoft SQL Server 2005 XML Showplan'
|
name: c.columnName === 'Microsoft SQL Server 2005 XML Showplan'
|
||||||
? 'XML Showplan'
|
? 'XML Showplan'
|
||||||
: c.columnName,
|
: escape(c.columnName),
|
||||||
type: self.stringToFieldType('string'),
|
type: self.stringToFieldType('string'),
|
||||||
formatter: isLinked ? Services.hyperLinkFormatter : Services.textFormatter,
|
formatter: isLinked ? Services.hyperLinkFormatter : Services.textFormatter,
|
||||||
asyncPostRender: isLinked ? self.linkHandler(linkType) : undefined,
|
asyncPostRender: isLinked ? self.linkHandler(linkType) : undefined,
|
||||||
|
|||||||
@@ -348,11 +348,12 @@ export class QueryComponent extends GridParentComponent implements OnInit, OnDes
|
|||||||
columnDefinitions: resultSet.columnInfo.map((c, i) => {
|
columnDefinitions: resultSet.columnInfo.map((c, i) => {
|
||||||
let isLinked = c.isXml || c.isJson;
|
let isLinked = c.isXml || c.isJson;
|
||||||
let linkType = c.isXml ? 'xml' : 'json';
|
let linkType = c.isXml ? 'xml' : 'json';
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: i.toString(),
|
id: i.toString(),
|
||||||
name: c.columnName === 'Microsoft SQL Server 2005 XML Showplan'
|
name: c.columnName === 'Microsoft SQL Server 2005 XML Showplan'
|
||||||
? 'XML Showplan'
|
? 'XML Showplan'
|
||||||
: c.columnName,
|
: escape(c.columnName),
|
||||||
type: self.stringToFieldType('string'),
|
type: self.stringToFieldType('string'),
|
||||||
formatter: isLinked ? Services.hyperLinkFormatter : Services.textFormatter,
|
formatter: isLinked ? Services.hyperLinkFormatter : Services.textFormatter,
|
||||||
asyncPostRender: isLinked ? self.linkHandler(linkType) : undefined
|
asyncPostRender: isLinked ? self.linkHandler(linkType) : undefined
|
||||||
|
|||||||
@@ -7,18 +7,11 @@ import 'vs/css!../common/media/jobs';
|
|||||||
import 'sql/parts/dashboard/common/dashboardPanelStyles';
|
import 'sql/parts/dashboard/common/dashboardPanelStyles';
|
||||||
|
|
||||||
import * as nls from 'vs/nls';
|
import * as nls from 'vs/nls';
|
||||||
import { Component, Inject, forwardRef, ElementRef, ChangeDetectorRef, ViewChild, Injectable } from '@angular/core';
|
import { Component, Inject, forwardRef, ChangeDetectorRef, ViewChild, Injectable } from '@angular/core';
|
||||||
import * as Utils from 'sql/parts/connection/common/utils';
|
import { AgentJobInfo } from 'sqlops';
|
||||||
import { RefreshWidgetAction, EditDashboardAction } from 'sql/parts/dashboard/common/actions';
|
|
||||||
import { IColorTheme } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
|
||||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
|
||||||
import * as themeColors from 'vs/workbench/common/theme';
|
|
||||||
import { DashboardPage } from 'sql/parts/dashboard/common/dashboardPage.component';
|
|
||||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
|
||||||
import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service';
|
|
||||||
import { AgentJobInfo, AgentJobHistoryInfo } from 'sqlops';
|
|
||||||
import { PanelComponent, IPanelOptions, NavigationBarLayout } from 'sql/base/browser/ui/panel/panel.component';
|
import { PanelComponent, IPanelOptions, NavigationBarLayout } from 'sql/base/browser/ui/panel/panel.component';
|
||||||
import { IJobManagementService } from 'sql/parts/jobManagement/common/interfaces';
|
import { IJobManagementService } from 'sql/parts/jobManagement/common/interfaces';
|
||||||
|
import { IDashboardService } from 'sql/services/dashboard/common/dashboardService';
|
||||||
|
|
||||||
|
|
||||||
export const DASHBOARD_SELECTOR: string = 'agentview-component';
|
export const DASHBOARD_SELECTOR: string = 'agentview-component';
|
||||||
@@ -32,12 +25,6 @@ export class AgentViewComponent {
|
|||||||
|
|
||||||
@ViewChild(PanelComponent) private _panel: PanelComponent;
|
@ViewChild(PanelComponent) private _panel: PanelComponent;
|
||||||
|
|
||||||
// tslint:disable:no-unused-variable
|
|
||||||
private readonly jobsComponentTitle: string = nls.localize('jobview.Jobs', "Jobs");
|
|
||||||
private readonly alertsComponentTitle: string = nls.localize('jobview.Alerts', "Alerts");
|
|
||||||
private readonly proxiesComponentTitle: string = nls.localize('jobview.Proxies', "Proxies");
|
|
||||||
private readonly operatorsComponentTitle: string = nls.localize('jobview.Operators', "Operators");
|
|
||||||
|
|
||||||
private _showHistory: boolean = false;
|
private _showHistory: boolean = false;
|
||||||
private _jobId: string = null;
|
private _jobId: string = null;
|
||||||
private _agentJobInfo: AgentJobInfo = null;
|
private _agentJobInfo: AgentJobInfo = null;
|
||||||
@@ -49,6 +36,11 @@ export class AgentViewComponent {
|
|||||||
public proxiesIconClass: string = 'proxiesview-icon';
|
public proxiesIconClass: string = 'proxiesview-icon';
|
||||||
public operatorsIconClass: string = 'operatorsview-icon';
|
public operatorsIconClass: string = 'operatorsview-icon';
|
||||||
|
|
||||||
|
private readonly jobsComponentTitle: string = nls.localize('jobview.Jobs', "Jobs");
|
||||||
|
private readonly alertsComponentTitle: string = nls.localize('jobview.Alerts', "Alerts");
|
||||||
|
private readonly proxiesComponentTitle: string = nls.localize('jobview.Proxies', "Proxies");
|
||||||
|
private readonly operatorsComponentTitle: string = nls.localize('jobview.Operators', "Operators");
|
||||||
|
|
||||||
// tslint:disable-next-line:no-unused-variable
|
// tslint:disable-next-line:no-unused-variable
|
||||||
private readonly panelOpt: IPanelOptions = {
|
private readonly panelOpt: IPanelOptions = {
|
||||||
showTabsWhenOne: true,
|
showTabsWhenOne: true,
|
||||||
@@ -58,7 +50,8 @@ export class AgentViewComponent {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(forwardRef(() => ChangeDetectorRef)) private _cd: ChangeDetectorRef,
|
@Inject(forwardRef(() => ChangeDetectorRef)) private _cd: ChangeDetectorRef,
|
||||||
@Inject(IJobManagementService) jobManagementService: IJobManagementService) {
|
@Inject(IJobManagementService) jobManagementService: IJobManagementService,
|
||||||
|
@Inject(IDashboardService) dashboardService: IDashboardService,) {
|
||||||
this._expanded = new Map<string, string>();
|
this._expanded = new Map<string, string>();
|
||||||
|
|
||||||
let self = this;
|
let self = this;
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ export interface IJobManagementService {
|
|||||||
getProxies(connectionUri: string): Thenable<sqlops.AgentProxiesResult>;
|
getProxies(connectionUri: string): Thenable<sqlops.AgentProxiesResult>;
|
||||||
deleteProxy(connectionUri: string, proxy: sqlops.AgentProxyInfo): Thenable<sqlops.ResultStatus>;
|
deleteProxy(connectionUri: string, proxy: sqlops.AgentProxyInfo): Thenable<sqlops.ResultStatus>;
|
||||||
|
|
||||||
|
getCredentials(connectionUri: string): Thenable<sqlops.GetCredentialsResult>;
|
||||||
|
|
||||||
jobAction(connectionUri: string, jobName: string, action: string): Thenable<sqlops.ResultStatus>;
|
jobAction(connectionUri: string, jobName: string, action: string): Thenable<sqlops.ResultStatus>;
|
||||||
addToCache(server: string, cache: JobCacheObject);
|
addToCache(server: string, cache: JobCacheObject);
|
||||||
jobCacheObjectMap: { [server: string]: JobCacheObject; };
|
jobCacheObjectMap: { [server: string]: JobCacheObject; };
|
||||||
|
|||||||
@@ -145,11 +145,17 @@ export class EditJobAction extends Action {
|
|||||||
public static ID = 'jobaction.editJob';
|
public static ID = 'jobaction.editJob';
|
||||||
public static LABEL = nls.localize('jobaction.editJob', "Edit Job");
|
public static LABEL = nls.localize('jobaction.editJob', "Edit Job");
|
||||||
|
|
||||||
constructor() {
|
constructor(
|
||||||
|
@ICommandService private _commandService: ICommandService
|
||||||
|
) {
|
||||||
super(EditJobAction.ID, EditJobAction.LABEL);
|
super(EditJobAction.ID, EditJobAction.LABEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
public run(actionInfo: IJobActionInfo): TPromise<boolean> {
|
public run(actionInfo: IJobActionInfo): TPromise<boolean> {
|
||||||
|
this._commandService.executeCommand(
|
||||||
|
'agent.openJobDialog',
|
||||||
|
actionInfo.ownerUri,
|
||||||
|
actionInfo.targetObject);
|
||||||
return TPromise.as(true);
|
return TPromise.as(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -324,11 +330,17 @@ export class EditOperatorAction extends Action {
|
|||||||
public static ID = 'jobaction.editAlert';
|
public static ID = 'jobaction.editAlert';
|
||||||
public static LABEL = nls.localize('jobaction.editOperator', "Edit Operator");
|
public static LABEL = nls.localize('jobaction.editOperator', "Edit Operator");
|
||||||
|
|
||||||
constructor() {
|
constructor(
|
||||||
|
@ICommandService private _commandService: ICommandService
|
||||||
|
) {
|
||||||
super(EditOperatorAction.ID, EditOperatorAction.LABEL);
|
super(EditOperatorAction.ID, EditOperatorAction.LABEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
public run(info: any): TPromise<boolean> {
|
public run(actionInfo: IJobActionInfo): TPromise<boolean> {
|
||||||
|
this._commandService.executeCommand(
|
||||||
|
'agent.openOperatorDialog',
|
||||||
|
actionInfo.ownerUri,
|
||||||
|
actionInfo.targetObject);
|
||||||
return TPromise.as(true);
|
return TPromise.as(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -398,11 +410,17 @@ export class EditProxyAction extends Action {
|
|||||||
public static ID = 'jobaction.editProxy';
|
public static ID = 'jobaction.editProxy';
|
||||||
public static LABEL = nls.localize('jobaction.editProxy', "Edit Proxy");
|
public static LABEL = nls.localize('jobaction.editProxy', "Edit Proxy");
|
||||||
|
|
||||||
constructor() {
|
constructor(
|
||||||
|
@ICommandService private _commandService: ICommandService
|
||||||
|
) {
|
||||||
super(EditProxyAction.ID, EditProxyAction.LABEL);
|
super(EditProxyAction.ID, EditProxyAction.LABEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
public run(info: any): TPromise<boolean> {
|
public run(actionInfo: IJobActionInfo): TPromise<boolean> {
|
||||||
|
this._commandService.executeCommand(
|
||||||
|
'agent.openProxyDialog',
|
||||||
|
actionInfo.ownerUri,
|
||||||
|
actionInfo.targetObject);
|
||||||
return TPromise.as(true);
|
return TPromise.as(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,6 +78,12 @@ export class JobManagementService implements IJobManagementService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getCredentials(connectionUri: string): Thenable<sqlops.GetCredentialsResult> {
|
||||||
|
return this._runAction(connectionUri, (runner) => {
|
||||||
|
return runner.getCredentials(connectionUri);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public getJobHistory(connectionUri: string, jobID: string): Thenable<sqlops.AgentJobHistoryResult> {
|
public getJobHistory(connectionUri: string, jobID: string): Thenable<sqlops.AgentJobHistoryResult> {
|
||||||
return this._runAction(connectionUri, (runner) => {
|
return this._runAction(connectionUri, (runner) => {
|
||||||
return runner.getJobHistory(connectionUri, jobID);
|
return runner.getJobHistory(connectionUri, jobID);
|
||||||
|
|||||||
@@ -32,23 +32,11 @@ jobhistory-component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.jobview-grid {
|
.jobview-grid {
|
||||||
height: 94.7%;
|
height: calc(100% - 75px);
|
||||||
width : 100%;
|
width : 100%;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vs-dark #jobsDiv .slick-header-column {
|
|
||||||
background: #333333 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
#jobsDiv .slick-header-column {
|
|
||||||
background-color: transparent !important;
|
|
||||||
background: white !important;
|
|
||||||
border: 0px !important;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: larger;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vs-dark #agentViewDiv .slick-header-column {
|
.vs-dark #agentViewDiv .slick-header-column {
|
||||||
background: #333333 !important;
|
background: #333333 !important;
|
||||||
}
|
}
|
||||||
@@ -58,7 +46,6 @@ jobhistory-component {
|
|||||||
background: white !important;
|
background: white !important;
|
||||||
border: 0px !important;
|
border: 0px !important;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: larger;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.vs-dark #jobsDiv jobsview-component .jobview-grid .grid-canvas .ui-widget-content.slick-row .slick-cell {
|
.vs-dark #jobsDiv jobsview-component .jobview-grid .grid-canvas .ui-widget-content.slick-row .slick-cell {
|
||||||
@@ -164,7 +151,7 @@ jobhistory-component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#jobsDiv .preload {
|
#jobsDiv .preload {
|
||||||
font-size: 18px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#jobsDiv .dynamic-cell-detail > :first-child {
|
#jobsDiv .dynamic-cell-detail > :first-child {
|
||||||
@@ -299,19 +286,20 @@ table.jobprevruns > tbody {
|
|||||||
|
|
||||||
|
|
||||||
#alertsDiv .jobalertsview-grid {
|
#alertsDiv .jobalertsview-grid {
|
||||||
height: 94.7%;
|
height: calc(100% - 75px);
|
||||||
width : 100%;
|
width : 100%;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
#operatorsDiv .joboperatorsview-grid {
|
#operatorsDiv .joboperatorsview-grid {
|
||||||
height: 94.7%;
|
height: calc(100% - 75px);
|
||||||
width : 100%;
|
width : 100%;
|
||||||
display: block;
|
display: block;
|
||||||
|
overflow: scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
#proxiesDiv .jobproxiesview-grid {
|
#proxiesDiv .jobproxiesview-grid {
|
||||||
height: 94.7%;
|
height: calc(100% - 75px);
|
||||||
width : 100%;
|
width : 100%;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
@@ -340,3 +328,96 @@ jobsview-component .actionbar-container {
|
|||||||
jobsview-component .jobview-grid .slick-cell.error-row {
|
jobsview-component .jobview-grid .slick-cell.error-row {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vs-dark #alertsDiv jobalertsview-component .jobalertsview-grid .grid-canvas .ui-widget-content.slick-row .slick-cell {
|
||||||
|
background:#333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
#alertsDiv jobalertsview-component .jobalertsview-grid .grid-canvas .ui-widget-content.slick-row .slick-cell {
|
||||||
|
background: white;
|
||||||
|
border-right: transparent !important;
|
||||||
|
border-left: transparent !important;
|
||||||
|
line-height: 33px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#alertsDiv .jobalertsview-grid > .monaco-table .slick-viewport > .grid-canvas > .ui-widget-content.slick-row:hover > .slick-cell,
|
||||||
|
#alertsDiv .jobalertsview-grid > .monaco-table .slick-viewport > .grid-canvas > .ui-widget-content.slick-row.hovered > .slick-cell,
|
||||||
|
#alertsDiv .jobalertsview-grid > .monaco-table .slick-viewport > .grid-canvas > .ui-widget-content.slick-row> .slick-cell.hovered {
|
||||||
|
background: #dcdcdc !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs-dark #alertsDiv .jobalertsview-grid > .monaco-table .slick-viewport > .grid-canvas > .ui-widget-content.slick-row:hover > .slick-cell,
|
||||||
|
.vs-dark #alertsDiv .jobalertsview-grid > .monaco-table .slick-viewport > .grid-canvas > .ui-widget-content.slick-row > .slick-cell.hovered,
|
||||||
|
.vs-dark #alertsDiv .jobalertsview-grid > .monaco-table .slick-viewport > .grid-canvas > .ui-widget-content.slick-row.hovered > .slick-cell {
|
||||||
|
background: #444444 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs-dark .jobalertsview-grid > .monaco-table .slick-header-columns .slick-resizable-handle {
|
||||||
|
border-left: 1px dotted white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jobalertsview-grid > .monaco-table .slick-header-columns .slick-resizable-handle {
|
||||||
|
border-left: 1px dotted #444444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs-dark #operatorsDiv joboperatorsview-component .joboperatorsview-grid .grid-canvas .ui-widget-content.slick-row .slick-cell {
|
||||||
|
background:#333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
#operatorsDiv joboperatorsview-component .joboperatorsview-grid .grid-canvas .ui-widget-content.slick-row .slick-cell {
|
||||||
|
background: white;
|
||||||
|
border-right: transparent !important;
|
||||||
|
border-left: transparent !important;
|
||||||
|
line-height: 33px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#operatorsDiv .joboperatorsview-grid > .monaco-table .slick-viewport > .grid-canvas > .ui-widget-content.slick-row:hover > .slick-cell,
|
||||||
|
#operatorsDiv .joboperatorsview-grid > .monaco-table .slick-viewport > .grid-canvas > .ui-widget-content.slick-row.hovered > .slick-cell,
|
||||||
|
#operatorsDiv .joboperatorsview-grid > .monaco-table .slick-viewport > .grid-canvas > .ui-widget-content.slick-row> .slick-cell.hovered {
|
||||||
|
background: #dcdcdc !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs-dark #operatorsDiv .joboperatorsview-grid > .monaco-table .slick-viewport > .grid-canvas > .ui-widget-content.slick-row:hover > .slick-cell,
|
||||||
|
.vs-dark #operatorsDiv .joboperatorsview-grid > .monaco-table .slick-viewport > .grid-canvas > .ui-widget-content.slick-row > .slick-cell.hovered,
|
||||||
|
.vs-dark #operatorsDiv .joboperatorsview-grid > .monaco-table .slick-viewport > .grid-canvas > .ui-widget-content.slick-row.hovered > .slick-cell {
|
||||||
|
background: #444444 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs-dark .joboperatorsview-grid > .monaco-table .slick-header-columns .slick-resizable-handle {
|
||||||
|
border-left: 1px dotted white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.joboperatorsview-grid > .monaco-table .slick-header-columns .slick-resizable-handle {
|
||||||
|
border-left: 1px dotted #444444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs-dark #proxiesDiv jobproxiesview-component .jobproxiesview-grid .grid-canvas .ui-widget-content.slick-row .slick-cell {
|
||||||
|
background:#333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
#proxiesDiv jobproxiesview-component .jobproxiesview-grid .grid-canvas .ui-widget-content.slick-row .slick-cell {
|
||||||
|
background: white;
|
||||||
|
border-right: transparent !important;
|
||||||
|
border-left: transparent !important;
|
||||||
|
line-height: 33px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#proxiesDiv .jobproxiesview-grid > .monaco-table .slick-viewport > .grid-canvas > .ui-widget-content.slick-row:hover > .slick-cell,
|
||||||
|
#proxiesDiv .jobproxiesview-grid > .monaco-table .slick-viewport > .grid-canvas > .ui-widget-content.slick-row.hovered > .slick-cell,
|
||||||
|
#proxiesDiv .jobproxiesview-grid > .monaco-table .slick-viewport > .grid-canvas > .ui-widget-content.slick-row> .slick-cell.hovered {
|
||||||
|
background: #dcdcdc !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs-dark #proxiesDiv .jobproxiesview-grid > .monaco-table .slick-viewport > .grid-canvas > .ui-widget-content.slick-row:hover > .slick-cell,
|
||||||
|
.vs-dark #proxiesDiv .jobproxiesview-grid > .monaco-table .slick-viewport > .grid-canvas > .ui-widget-content.slick-row > .slick-cell.hovered,
|
||||||
|
.vs-dark #proxiesDiv .jobproxiesview-grid > .monaco-table .slick-viewport > .grid-canvas > .ui-widget-content.slick-row.hovered > .slick-cell {
|
||||||
|
background: #444444 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs-dark .jobproxiesview-grid > .monaco-table .slick-header-columns .slick-resizable-handle {
|
||||||
|
border-left: 1px dotted white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jobproxiesview-grid > .monaco-table .slick-header-columns .slick-resizable-handle {
|
||||||
|
border-left: 1px dotted #444444;
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,4 +12,4 @@
|
|||||||
|
|
||||||
<div #actionbarContainer class="actionbar-container"></div>
|
<div #actionbarContainer class="actionbar-container"></div>
|
||||||
|
|
||||||
<div #jobalertsgrid class="jobview-grid"></div>
|
<div #jobalertsgrid class="jobalertsview-grid"></div>
|
||||||
|
|||||||
@@ -29,9 +29,10 @@ import { IAction } from 'vs/base/common/actions';
|
|||||||
import { TPromise } from 'vs/base/common/winjs.base';
|
import { TPromise } from 'vs/base/common/winjs.base';
|
||||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
import { IDashboardService } from 'sql/services/dashboard/common/dashboardService';
|
||||||
|
|
||||||
export const VIEW_SELECTOR: string = 'jobalertsview-component';
|
export const VIEW_SELECTOR: string = 'jobalertsview-component';
|
||||||
export const ROW_HEIGHT: number = 45;
|
export const ROW_HEIGHT: number = 30;
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: VIEW_SELECTOR,
|
selector: VIEW_SELECTOR,
|
||||||
@@ -73,8 +74,9 @@ export class AlertsViewComponent extends JobManagementView implements OnInit {
|
|||||||
@Inject(IInstantiationService) instantiationService: IInstantiationService,
|
@Inject(IInstantiationService) instantiationService: IInstantiationService,
|
||||||
@Inject(forwardRef(() => CommonServiceInterface)) commonService: CommonServiceInterface,
|
@Inject(forwardRef(() => CommonServiceInterface)) commonService: CommonServiceInterface,
|
||||||
@Inject(IContextMenuService) contextMenuService: IContextMenuService,
|
@Inject(IContextMenuService) contextMenuService: IContextMenuService,
|
||||||
@Inject(IKeybindingService) keybindingService: IKeybindingService) {
|
@Inject(IKeybindingService) keybindingService: IKeybindingService,
|
||||||
super(commonService, contextMenuService, keybindingService, instantiationService);
|
@Inject(IDashboardService) _dashboardService: IDashboardService) {
|
||||||
|
super(commonService, _dashboardService, contextMenuService, keybindingService, instantiationService);
|
||||||
this._isCloud = commonService.connectionManagementService.connectionInfo.serverInfo.isCloud;
|
this._isCloud = commonService.connectionManagementService.connectionInfo.serverInfo.isCloud;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +87,14 @@ export class AlertsViewComponent extends JobManagementView implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public layout() {
|
public layout() {
|
||||||
this._table.layout(new dom.Dimension(dom.getContentWidth(this._gridEl.nativeElement), dom.getContentHeight(this._gridEl.nativeElement)));
|
let height = dom.getContentHeight(this._gridEl.nativeElement) - 10;
|
||||||
|
if (height < 0) {
|
||||||
|
height = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._table.layout(new dom.Dimension(
|
||||||
|
dom.getContentWidth(this._gridEl.nativeElement),
|
||||||
|
height));
|
||||||
}
|
}
|
||||||
|
|
||||||
onFirstVisible() {
|
onFirstVisible() {
|
||||||
@@ -94,13 +103,6 @@ export class AlertsViewComponent extends JobManagementView implements OnInit {
|
|||||||
column.rerenderOnResize = true;
|
column.rerenderOnResize = true;
|
||||||
return column;
|
return column;
|
||||||
});
|
});
|
||||||
let options = <Slick.GridOptions<any>>{
|
|
||||||
syncColumnCellResize: true,
|
|
||||||
enableColumnReorder: false,
|
|
||||||
rowHeight: ROW_HEIGHT,
|
|
||||||
enableCellNavigation: true,
|
|
||||||
forceFitColumns: true
|
|
||||||
};
|
|
||||||
|
|
||||||
this.dataView = new Slick.Data.DataView();
|
this.dataView = new Slick.Data.DataView();
|
||||||
|
|
||||||
@@ -164,7 +166,17 @@ export class AlertsViewComponent extends JobManagementView implements OnInit {
|
|||||||
|
|
||||||
public openCreateAlertDialog() {
|
public openCreateAlertDialog() {
|
||||||
let ownerUri: string = this._commonService.connectionManagementService.connectionInfo.ownerUri;
|
let ownerUri: string = this._commonService.connectionManagementService.connectionInfo.ownerUri;
|
||||||
this._commandService.executeCommand('agent.openAlertDialog', ownerUri);
|
this._jobManagementService.getJobs(ownerUri).then((result) => {
|
||||||
|
if (result && result.jobs.length > 0) {
|
||||||
|
let jobs = [];
|
||||||
|
result.jobs.forEach(job => {
|
||||||
|
jobs.push(job.name);
|
||||||
|
});
|
||||||
|
this._commandService.executeCommand('agent.openAlertDialog', ownerUri, null, jobs);
|
||||||
|
} else {
|
||||||
|
this._commandService.executeCommand('agent.openAlertDialog', ownerUri, null, null);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private refreshJobs() {
|
private refreshJobs() {
|
||||||
|
|||||||
@@ -154,8 +154,9 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<jobstepsview-component *ngIf="showSteps === true"></jobstepsview-component>
|
<div #jobsteps style="height: 100%">
|
||||||
|
<jobstepsview-component *ngIf="showSteps === true"></jobstepsview-component>
|
||||||
|
</div>
|
||||||
<h3 *ngIf="showSteps === false">No Steps Available</h3>
|
<h3 *ngIf="showSteps === false">No Steps Available</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import 'vs/css!./jobHistory';
|
|||||||
import 'vs/css!sql/media/icons/common-icons';
|
import 'vs/css!sql/media/icons/common-icons';
|
||||||
|
|
||||||
import * as sqlops from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
|
import * as dom from 'vs/base/browser/dom';
|
||||||
import { OnInit, Component, Inject, Input, forwardRef, ElementRef, ChangeDetectorRef, ViewChild, ChangeDetectionStrategy, Injectable } from '@angular/core';
|
import { OnInit, Component, Inject, Input, forwardRef, ElementRef, ChangeDetectorRef, ViewChild, ChangeDetectionStrategy, Injectable } from '@angular/core';
|
||||||
import { Taskbar } from 'sql/base/browser/ui/taskbar/taskbar';
|
import { Taskbar } from 'sql/base/browser/ui/taskbar/taskbar';
|
||||||
import { AgentViewComponent } from 'sql/parts/jobManagement/agent/agentView.component';
|
import { AgentViewComponent } from 'sql/parts/jobManagement/agent/agentView.component';
|
||||||
@@ -22,30 +23,33 @@ import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/work
|
|||||||
import { attachListStyler } from 'vs/platform/theme/common/styler';
|
import { attachListStyler } from 'vs/platform/theme/common/styler';
|
||||||
import { Tree } from 'vs/base/parts/tree/browser/treeImpl';
|
import { Tree } from 'vs/base/parts/tree/browser/treeImpl';
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
import { Disposable } from 'vs/base/common/lifecycle';
|
|
||||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||||
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||||
|
import { JobManagementView } from 'sql/parts/jobManagement/views/jobManagementView';
|
||||||
|
import { TabChild } from 'sql/base/browser/ui/panel/tab.component';
|
||||||
|
import { IDashboardService } from 'sql/services/dashboard/common/dashboardService';
|
||||||
|
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||||
|
|
||||||
export const DASHBOARD_SELECTOR: string = 'jobhistory-component';
|
export const DASHBOARD_SELECTOR: string = 'jobhistory-component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: DASHBOARD_SELECTOR,
|
selector: DASHBOARD_SELECTOR,
|
||||||
templateUrl: decodeURI(require.toUrl('./jobHistory.component.html')),
|
templateUrl: decodeURI(require.toUrl('./jobHistory.component.html')),
|
||||||
|
providers: [{ provide: TabChild, useExisting: forwardRef(() => JobHistoryComponent) }],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class JobHistoryComponent extends Disposable implements OnInit {
|
export class JobHistoryComponent extends JobManagementView implements OnInit {
|
||||||
|
|
||||||
private _tree: Tree;
|
private _tree: Tree;
|
||||||
private _treeController: JobHistoryController;
|
private _treeController: JobHistoryController;
|
||||||
private _treeDataSource: JobHistoryDataSource;
|
private _treeDataSource: JobHistoryDataSource;
|
||||||
private _treeRenderer: JobHistoryRenderer;
|
private _treeRenderer: JobHistoryRenderer;
|
||||||
private _treeFilter: JobHistoryFilter;
|
private _treeFilter: JobHistoryFilter;
|
||||||
private _actionBar: Taskbar;
|
|
||||||
|
|
||||||
@ViewChild('table') private _tableContainer: ElementRef;
|
@ViewChild('table') private _tableContainer: ElementRef;
|
||||||
@ViewChild('actionbarContainer') private _actionbarContainer: ElementRef;
|
@ViewChild('jobsteps') private _jobStepsView: ElementRef;
|
||||||
|
|
||||||
@Input() public agentJobInfo: sqlops.AgentJobInfo = undefined;
|
@Input() public agentJobInfo: sqlops.AgentJobInfo = undefined;
|
||||||
@Input() public agentJobHistories: sqlops.AgentJobHistoryInfo[] = undefined;
|
@Input() public agentJobHistories: sqlops.AgentJobHistoryInfo[] = undefined;
|
||||||
@@ -67,21 +71,23 @@ export class JobHistoryComponent extends Disposable implements OnInit {
|
|||||||
constructor(
|
constructor(
|
||||||
@Inject(forwardRef(() => ElementRef)) el: ElementRef,
|
@Inject(forwardRef(() => ElementRef)) el: ElementRef,
|
||||||
@Inject(forwardRef(() => ChangeDetectorRef)) private _cd: ChangeDetectorRef,
|
@Inject(forwardRef(() => ChangeDetectorRef)) private _cd: ChangeDetectorRef,
|
||||||
@Inject(forwardRef(() => CommonServiceInterface)) private _dashboardService: CommonServiceInterface,
|
@Inject(forwardRef(() => CommonServiceInterface)) commonService: CommonServiceInterface,
|
||||||
@Inject(forwardRef(() => AgentViewComponent)) private _agentViewComponent: AgentViewComponent,
|
@Inject(forwardRef(() => AgentViewComponent)) private _agentViewComponent: AgentViewComponent,
|
||||||
@Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService,
|
@Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService,
|
||||||
@Inject(INotificationService) private _notificationService: INotificationService,
|
@Inject(INotificationService) private _notificationService: INotificationService,
|
||||||
@Inject(IInstantiationService) private instantiationService: IInstantiationService,
|
@Inject(IInstantiationService) private instantiationService: IInstantiationService,
|
||||||
@Inject(IContextMenuService) private contextMenuService: IContextMenuService,
|
@Inject(IContextMenuService) private contextMenuService: IContextMenuService,
|
||||||
@Inject(IJobManagementService) private _jobManagementService: IJobManagementService
|
@Inject(IJobManagementService) private _jobManagementService: IJobManagementService,
|
||||||
|
@Inject(IKeybindingService) keybindingService: IKeybindingService,
|
||||||
|
@Inject(IDashboardService) dashboardService: IDashboardService
|
||||||
) {
|
) {
|
||||||
super();
|
super(commonService, dashboardService, contextMenuService, keybindingService, instantiationService);
|
||||||
this._treeController = new JobHistoryController();
|
this._treeController = new JobHistoryController();
|
||||||
this._treeDataSource = new JobHistoryDataSource();
|
this._treeDataSource = new JobHistoryDataSource();
|
||||||
this._treeRenderer = new JobHistoryRenderer();
|
this._treeRenderer = new JobHistoryRenderer();
|
||||||
this._treeFilter = new JobHistoryFilter();
|
this._treeFilter = new JobHistoryFilter();
|
||||||
let jobCacheObjectMap = this._jobManagementService.jobCacheObjectMap;
|
let jobCacheObjectMap = this._jobManagementService.jobCacheObjectMap;
|
||||||
this._serverName = _dashboardService.connectionManagementService.connectionInfo.connectionProfile.serverName;
|
this._serverName = commonService.connectionManagementService.connectionInfo.connectionProfile.serverName;
|
||||||
let jobCache = jobCacheObjectMap[this._serverName];
|
let jobCache = jobCacheObjectMap[this._serverName];
|
||||||
if (jobCache) {
|
if (jobCache) {
|
||||||
this._jobCacheObject = jobCache;
|
this._jobCacheObject = jobCache;
|
||||||
@@ -93,7 +99,11 @@ export class JobHistoryComponent extends Disposable implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
let ownerUri: string = this._dashboardService.connectionManagementService.connectionInfo.ownerUri;
|
// set base class elements
|
||||||
|
this._visibilityElement = this._tableContainer;
|
||||||
|
this._parentComponent = this._agentViewComponent;
|
||||||
|
|
||||||
|
let ownerUri: string = this._commonService.connectionManagementService.connectionInfo.ownerUri;
|
||||||
const self = this;
|
const self = this;
|
||||||
this._treeController.onClick = (tree, element, event, origin = 'mouse') => {
|
this._treeController.onClick = (tree, element, event, origin = 'mouse') => {
|
||||||
const payload = { origin: origin };
|
const payload = { origin: origin };
|
||||||
@@ -130,56 +140,13 @@ export class JobHistoryComponent extends Disposable implements OnInit {
|
|||||||
}, {verticalScrollMode: ScrollbarVisibility.Visible});
|
}, {verticalScrollMode: ScrollbarVisibility.Visible});
|
||||||
this._register(attachListStyler(this._tree, this.themeService));
|
this._register(attachListStyler(this._tree, this.themeService));
|
||||||
this._tree.layout(JobHistoryComponent.INITIAL_TREE_HEIGHT);
|
this._tree.layout(JobHistoryComponent.INITIAL_TREE_HEIGHT);
|
||||||
this._initActionBar();
|
this.initActionBar();
|
||||||
$(window).resize(() => {
|
|
||||||
let historyDetails = $('.overview-container').get(0);
|
|
||||||
let statusBar = $('.part.statusbar').get(0);
|
|
||||||
if (historyDetails && statusBar) {
|
|
||||||
let historyBottom = historyDetails.getBoundingClientRect().bottom;
|
|
||||||
let statusTop = statusBar.getBoundingClientRect().top;
|
|
||||||
this._tree.layout(statusTop - historyBottom - JobHistoryComponent.HEADING_HEIGHT);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
ngAfterContentChecked() {
|
|
||||||
this._agentJobInfo = this._agentViewComponent.agentJobInfo;
|
|
||||||
if (!this.agentJobInfo) {
|
|
||||||
this.agentJobInfo = this._agentJobInfo;
|
|
||||||
this.setActions();
|
|
||||||
}
|
|
||||||
if (this._isVisible === false && this._tableContainer.nativeElement.offsetParent !== null) {
|
|
||||||
this._isVisible = true;
|
|
||||||
let jobHistories = this._jobCacheObject.jobHistories[this._agentViewComponent.jobId];
|
|
||||||
if (jobHistories && jobHistories.length > 0) {
|
|
||||||
const self = this;
|
|
||||||
if (this._jobCacheObject.prevJobID === this._agentViewComponent.jobId || jobHistories[0].jobId === this._agentViewComponent.jobId) {
|
|
||||||
this._showPreviousRuns = true;
|
|
||||||
this.buildHistoryTree(self, jobHistories);
|
|
||||||
$('jobhistory-component .history-details .prev-run-list .monaco-tree').attr('tabIndex', '-1');
|
|
||||||
$('jobhistory-component .history-details .prev-run-list .monaco-tree-row').attr('tabIndex', '0');
|
|
||||||
this._cd.detectChanges();
|
|
||||||
}
|
|
||||||
} else if (jobHistories && jobHistories.length === 0 ){
|
|
||||||
this._showPreviousRuns = false;
|
|
||||||
this._showSteps = false;
|
|
||||||
this._noJobsAvailable = true;
|
|
||||||
this._cd.detectChanges();
|
|
||||||
} else {
|
|
||||||
this.loadHistory();
|
|
||||||
}
|
|
||||||
this._jobCacheObject.prevJobID = this._agentViewComponent.jobId;
|
|
||||||
} else if (this._isVisible === true && this._agentViewComponent.refresh) {
|
|
||||||
this.loadHistory();
|
|
||||||
this._agentViewComponent.refresh = false;
|
|
||||||
} else if (this._isVisible === true && this._tableContainer.nativeElement.offsetParent === null) {
|
|
||||||
this._isVisible = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private loadHistory() {
|
private loadHistory() {
|
||||||
const self = this;
|
const self = this;
|
||||||
let ownerUri: string = this._dashboardService.connectionManagementService.connectionInfo.ownerUri;
|
let ownerUri: string = this._commonService.connectionManagementService.connectionInfo.ownerUri;
|
||||||
this._jobManagementService.getJobHistory(ownerUri, this._agentViewComponent.jobId).then((result) => {
|
this._jobManagementService.getJobHistory(ownerUri, this._agentViewComponent.jobId).then((result) => {
|
||||||
if (result && result.jobs) {
|
if (result && result.jobs) {
|
||||||
if (result.jobs.length > 0) {
|
if (result.jobs.length > 0) {
|
||||||
@@ -207,10 +174,12 @@ export class JobHistoryComponent extends Disposable implements OnInit {
|
|||||||
if (self.agentJobHistoryInfo) {
|
if (self.agentJobHistoryInfo) {
|
||||||
self.agentJobHistoryInfo.runDate = self.formatTime(self.agentJobHistoryInfo.runDate);
|
self.agentJobHistoryInfo.runDate = self.formatTime(self.agentJobHistoryInfo.runDate);
|
||||||
if (self.agentJobHistoryInfo.steps) {
|
if (self.agentJobHistoryInfo.steps) {
|
||||||
|
let jobStepStatus = this.didJobFail(self.agentJobHistoryInfo);
|
||||||
self._stepRows = self.agentJobHistoryInfo.steps.map(step => {
|
self._stepRows = self.agentJobHistoryInfo.steps.map(step => {
|
||||||
let stepViewRow = new JobStepsViewRow();
|
let stepViewRow = new JobStepsViewRow();
|
||||||
stepViewRow.message = step.message;
|
stepViewRow.message = step.message;
|
||||||
stepViewRow.runStatus = JobManagementUtilities.convertToStatusString(step.runStatus);
|
stepViewRow.runStatus = jobStepStatus ? JobManagementUtilities.convertToStatusString(0) :
|
||||||
|
JobManagementUtilities.convertToStatusString(step.runStatus);
|
||||||
self._runStatus = JobManagementUtilities.convertToStatusString(self.agentJobHistoryInfo.runStatus);
|
self._runStatus = JobManagementUtilities.convertToStatusString(self.agentJobHistoryInfo.runStatus);
|
||||||
stepViewRow.stepName = step.stepName;
|
stepViewRow.stepName = step.stepName;
|
||||||
stepViewRow.stepID = step.stepId.toString();
|
stepViewRow.stepID = step.stepId.toString();
|
||||||
@@ -224,6 +193,15 @@ export class JobHistoryComponent extends Disposable implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private didJobFail(job: sqlops.AgentJobHistoryInfo): boolean {
|
||||||
|
for (let i = 0; i < job.steps.length; i++) {
|
||||||
|
if (job.steps[i].runStatus === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private buildHistoryTree(self: any, jobHistories: sqlops.AgentJobHistoryInfo[]) {
|
private buildHistoryTree(self: any, jobHistories: sqlops.AgentJobHistoryInfo[]) {
|
||||||
self._treeController.jobHistories = jobHistories;
|
self._treeController.jobHistories = jobHistories;
|
||||||
self._jobCacheObject.setJobHistory(self._agentViewComponent.jobId, jobHistories);
|
self._jobCacheObject.setJobHistory(self._agentViewComponent.jobId, jobHistories);
|
||||||
@@ -273,12 +251,71 @@ export class JobHistoryComponent extends Disposable implements OnInit {
|
|||||||
JobManagementUtilities.getActionIconClassName(startIcon, stopIcon, this.agentJobInfo.currentExecutionStatus);
|
JobManagementUtilities.getActionIconClassName(startIcon, stopIcon, this.agentJobInfo.currentExecutionStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public onFirstVisible() {
|
||||||
|
this._agentJobInfo = this._agentViewComponent.agentJobInfo;
|
||||||
|
if (!this.agentJobInfo) {
|
||||||
|
this.agentJobInfo = this._agentJobInfo;
|
||||||
|
this.setActions();
|
||||||
|
}
|
||||||
|
|
||||||
private _initActionBar() {
|
if (this.isRefreshing ) {
|
||||||
|
this.loadHistory();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let jobHistories = this._jobCacheObject.jobHistories[this._agentViewComponent.jobId];
|
||||||
|
if (jobHistories && jobHistories.length > 0) {
|
||||||
|
const self = this;
|
||||||
|
if (this._jobCacheObject.prevJobID === this._agentViewComponent.jobId || jobHistories[0].jobId === this._agentViewComponent.jobId) {
|
||||||
|
this._showPreviousRuns = true;
|
||||||
|
this.buildHistoryTree(self, jobHistories);
|
||||||
|
$('jobhistory-component .history-details .prev-run-list .monaco-tree').attr('tabIndex', '-1');
|
||||||
|
$('jobhistory-component .history-details .prev-run-list .monaco-tree-row').attr('tabIndex', '0');
|
||||||
|
this._cd.detectChanges();
|
||||||
|
}
|
||||||
|
} else if (jobHistories && jobHistories.length === 0 ){
|
||||||
|
this._showPreviousRuns = false;
|
||||||
|
this._showSteps = false;
|
||||||
|
this._noJobsAvailable = true;
|
||||||
|
this._cd.detectChanges();
|
||||||
|
} else {
|
||||||
|
this.loadHistory();
|
||||||
|
}
|
||||||
|
this._jobCacheObject.prevJobID = this._agentViewComponent.jobId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public layout() {
|
||||||
|
let historyDetails = $('.overview-container').get(0);
|
||||||
|
let statusBar = $('.part.statusbar').get(0);
|
||||||
|
if (historyDetails && statusBar) {
|
||||||
|
let historyBottom = historyDetails.getBoundingClientRect().bottom;
|
||||||
|
let statusTop = statusBar.getBoundingClientRect().top;
|
||||||
|
let height: number = statusTop - historyBottom - JobHistoryComponent.HEADING_HEIGHT;
|
||||||
|
|
||||||
|
if (this._table) {
|
||||||
|
this._table.layout(new dom.Dimension(
|
||||||
|
dom.getContentWidth(this._tableContainer.nativeElement),
|
||||||
|
height));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._tree) {
|
||||||
|
this._tree.layout(height);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._jobStepsView) {
|
||||||
|
let element = this._jobStepsView.nativeElement as HTMLElement;
|
||||||
|
if (element) {
|
||||||
|
element.style.height = height + 'px';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected initActionBar() {
|
||||||
let runJobAction = this.instantiationService.createInstance(RunJobAction);
|
let runJobAction = this.instantiationService.createInstance(RunJobAction);
|
||||||
let stopJobAction = this.instantiationService.createInstance(StopJobAction);
|
let stopJobAction = this.instantiationService.createInstance(StopJobAction);
|
||||||
let newStepAction = this.instantiationService.createInstance(NewStepAction);
|
let newStepAction = this.instantiationService.createInstance(NewStepAction);
|
||||||
let taskbar = <HTMLElement>this._actionbarContainer.nativeElement;
|
let taskbar = <HTMLElement>this.actionBarContainer.nativeElement;
|
||||||
this._actionBar = new Taskbar(taskbar, this.contextMenuService);
|
this._actionBar = new Taskbar(taskbar, this.contextMenuService);
|
||||||
this._actionBar.context = this;
|
this._actionBar.context = this;
|
||||||
this._actionBar.setContent([
|
this._actionBar.setContent([
|
||||||
@@ -299,7 +336,7 @@ export class JobHistoryComponent extends Disposable implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public get ownerUri(): string {
|
public get ownerUri(): string {
|
||||||
return this._dashboardService.connectionManagementService.connectionInfo.ownerUri;
|
return this._commonService.connectionManagementService.connectionInfo.ownerUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get serverName(): string {
|
public get serverName(): string {
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ table.step-list tr.step-row td {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.vs-dark .history-details > .job-steps {
|
.vs-dark .history-details > .job-steps {
|
||||||
display: inline-block;
|
display: block;
|
||||||
border-left: 3px solid #444444;
|
border-left: 3px solid #444444;
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -176,10 +176,12 @@ table.step-list tr.step-row td {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.history-details > .job-steps {
|
.history-details > .job-steps {
|
||||||
display: inline-block;
|
display: block;
|
||||||
border-left: 3px solid #f4f4f4;
|
border-left: 3px solid #f4f4f4;
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
width: 90%;
|
||||||
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
.history-details > .job-steps > .step-list {
|
.history-details > .job-steps > .step-list {
|
||||||
|
|||||||
@@ -104,7 +104,6 @@ export interface IListTemplate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class JobHistoryRenderer implements tree.IRenderer {
|
export class JobHistoryRenderer implements tree.IRenderer {
|
||||||
private _statusIcon: HTMLElement;
|
|
||||||
|
|
||||||
public getHeight(tree: tree.ITree, element: JobHistoryRow): number {
|
public getHeight(tree: tree.ITree, element: JobHistoryRow): number {
|
||||||
return 30;
|
return 30;
|
||||||
@@ -121,11 +120,10 @@ export class JobHistoryRenderer implements tree.IRenderer {
|
|||||||
public renderTemplate(tree: tree.ITree, templateId: string, container: HTMLElement): IListTemplate {
|
public renderTemplate(tree: tree.ITree, templateId: string, container: HTMLElement): IListTemplate {
|
||||||
let row = DOM.$('.list-row');
|
let row = DOM.$('.list-row');
|
||||||
let label = DOM.$('.label');
|
let label = DOM.$('.label');
|
||||||
this._statusIcon = this.createStatusIcon();
|
let statusIcon = this.createStatusIcon();
|
||||||
row.appendChild(this._statusIcon);
|
row.appendChild(statusIcon);
|
||||||
row.appendChild(label);
|
row.appendChild(label);
|
||||||
container.appendChild(row);
|
container.appendChild(row);
|
||||||
let statusIcon = this._statusIcon;
|
|
||||||
return { statusIcon, label };
|
return { statusIcon, label };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,13 +131,13 @@ export class JobHistoryRenderer implements tree.IRenderer {
|
|||||||
templateData.label.innerHTML = element.runDate + ' ' + element.runStatus;
|
templateData.label.innerHTML = element.runDate + ' ' + element.runStatus;
|
||||||
let statusClass: string;
|
let statusClass: string;
|
||||||
if (element.runStatus === 'Succeeded') {
|
if (element.runStatus === 'Succeeded') {
|
||||||
statusClass = ' job-passed';
|
statusClass = 'status-icon job-passed';
|
||||||
} else if (element.runStatus === 'Failed') {
|
} else if (element.runStatus === 'Failed') {
|
||||||
statusClass = ' job-failed';
|
statusClass = 'status-icon job-failed';
|
||||||
} else {
|
} else {
|
||||||
statusClass = ' job-unknown';
|
statusClass = 'status-icon job-unknown';
|
||||||
}
|
}
|
||||||
this._statusIcon.className += statusClass;
|
templateData.statusIcon.className = statusClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
public disposeTemplate(tree: tree.ITree, templateId: string, templateData: IListTemplate): void {
|
public disposeTemplate(tree: tree.ITree, templateId: string, templateData: IListTemplate): void {
|
||||||
@@ -148,7 +146,6 @@ export class JobHistoryRenderer implements tree.IRenderer {
|
|||||||
|
|
||||||
private createStatusIcon(): HTMLElement {
|
private createStatusIcon(): HTMLElement {
|
||||||
let statusIcon: HTMLElement = DOM.$('div');
|
let statusIcon: HTMLElement = DOM.$('div');
|
||||||
statusIcon.className += ' status-icon';
|
|
||||||
return statusIcon;
|
return statusIcon;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,10 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
|||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
import { Taskbar } from '../../../base/browser/ui/taskbar/taskbar';
|
import { Taskbar } from '../../../base/browser/ui/taskbar/taskbar';
|
||||||
import { JobsRefreshAction } from 'sql/parts/jobManagement/common/jobActions';
|
import { JobsRefreshAction } from 'sql/parts/jobManagement/common/jobActions';
|
||||||
|
import { TabChild } from 'sql/base/browser/ui/panel/tab.component';
|
||||||
|
import { IDashboardService } from 'sql/services/dashboard/common/dashboardService';
|
||||||
|
|
||||||
export abstract class JobManagementView extends Disposable implements AfterContentChecked {
|
export abstract class JobManagementView extends TabChild implements AfterContentChecked {
|
||||||
protected isVisible: boolean = false;
|
protected isVisible: boolean = false;
|
||||||
protected isInitialized: boolean = false;
|
protected isInitialized: boolean = false;
|
||||||
protected isRefreshing: boolean = false;
|
protected isRefreshing: boolean = false;
|
||||||
@@ -32,10 +34,16 @@ export abstract class JobManagementView extends Disposable implements AfterConte
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected _commonService: CommonServiceInterface,
|
protected _commonService: CommonServiceInterface,
|
||||||
|
protected _dashboardService: IDashboardService,
|
||||||
protected _contextMenuService: IContextMenuService,
|
protected _contextMenuService: IContextMenuService,
|
||||||
protected _keybindingService: IKeybindingService,
|
protected _keybindingService: IKeybindingService,
|
||||||
protected _instantiationService: IInstantiationService) {
|
protected _instantiationService: IInstantiationService) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
let self = this;
|
||||||
|
this._dashboardService.onLayout((d) => {
|
||||||
|
self.layout();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterContentChecked() {
|
ngAfterContentChecked() {
|
||||||
@@ -49,8 +57,9 @@ export abstract class JobManagementView extends Disposable implements AfterConte
|
|||||||
}
|
}
|
||||||
} else if (this.isVisible === true && this._parentComponent.refresh === true) {
|
} else if (this.isVisible === true && this._parentComponent.refresh === true) {
|
||||||
this._showProgressWheel = true;
|
this._showProgressWheel = true;
|
||||||
this.onFirstVisible();
|
|
||||||
this.isRefreshing = true;
|
this.isRefreshing = true;
|
||||||
|
this.onFirstVisible();
|
||||||
|
this.layout();
|
||||||
this._parentComponent.refresh = false;
|
this._parentComponent.refresh = false;
|
||||||
} else if (this.isVisible === true && this._visibilityElement.nativeElement.offsetParent === null) {
|
} else if (this.isVisible === true && this._visibilityElement.nativeElement.offsetParent === null) {
|
||||||
this.isVisible = false;
|
this.isVisible = false;
|
||||||
|
|||||||
@@ -8,21 +8,28 @@ import 'vs/css!./jobStepsView';
|
|||||||
import { OnInit, Component, Inject, forwardRef, ElementRef, ChangeDetectorRef, ViewChild, Injectable, AfterContentChecked } from '@angular/core';
|
import { OnInit, Component, Inject, forwardRef, ElementRef, ChangeDetectorRef, ViewChild, Injectable, AfterContentChecked } from '@angular/core';
|
||||||
import { attachListStyler } from 'vs/platform/theme/common/styler';
|
import { attachListStyler } from 'vs/platform/theme/common/styler';
|
||||||
import { Tree } from 'vs/base/parts/tree/browser/treeImpl';
|
import { Tree } from 'vs/base/parts/tree/browser/treeImpl';
|
||||||
import { Disposable } from 'vs/base/common/lifecycle';
|
|
||||||
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||||
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
||||||
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
|
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
|
||||||
import { JobStepsViewController, JobStepsViewDataSource, JobStepsViewFilter,
|
import { JobStepsViewController, JobStepsViewDataSource, JobStepsViewFilter,
|
||||||
JobStepsViewRenderer, JobStepsViewModel} from 'sql/parts/jobManagement/views/jobStepsViewTree';
|
JobStepsViewRenderer, JobStepsViewModel} from 'sql/parts/jobManagement/views/jobStepsViewTree';
|
||||||
import { JobHistoryComponent } from 'sql/parts/jobManagement/views/jobHistory.component';
|
import { JobHistoryComponent } from 'sql/parts/jobManagement/views/jobHistory.component';
|
||||||
|
import { JobManagementView } from 'sql/parts/jobManagement/views/jobManagementView';
|
||||||
|
import { IDashboardService } from 'sql/services/dashboard/common/dashboardService';
|
||||||
|
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||||
|
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||||
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
import { TabChild } from 'sql/base/browser/ui/panel/tab.component';
|
||||||
|
import * as dom from 'vs/base/browser/dom';
|
||||||
|
|
||||||
export const JOBSTEPSVIEW_SELECTOR: string = 'jobstepsview-component';
|
export const JOBSTEPSVIEW_SELECTOR: string = 'jobstepsview-component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: JOBSTEPSVIEW_SELECTOR,
|
selector: JOBSTEPSVIEW_SELECTOR,
|
||||||
templateUrl: decodeURI(require.toUrl('./jobStepsView.component.html'))
|
templateUrl: decodeURI(require.toUrl('./jobStepsView.component.html')),
|
||||||
|
providers: [{ provide: TabChild, useExisting: forwardRef(() => JobStepsViewComponent) }],
|
||||||
})
|
})
|
||||||
export class JobStepsViewComponent extends Disposable implements OnInit, AfterContentChecked {
|
export class JobStepsViewComponent extends JobManagementView implements OnInit, AfterContentChecked {
|
||||||
|
|
||||||
private _tree: Tree;
|
private _tree: Tree;
|
||||||
private _treeController = new JobStepsViewController();
|
private _treeController = new JobStepsViewController();
|
||||||
@@ -33,15 +40,18 @@ export class JobStepsViewComponent extends Disposable implements OnInit, AfterCo
|
|||||||
|
|
||||||
@ViewChild('table') private _tableContainer: ElementRef;
|
@ViewChild('table') private _tableContainer: ElementRef;
|
||||||
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(forwardRef(() => ElementRef)) el: ElementRef,
|
@Inject(forwardRef(() => ElementRef)) el: ElementRef,
|
||||||
@Inject(forwardRef(() => ChangeDetectorRef)) private _cd: ChangeDetectorRef,
|
@Inject(forwardRef(() => ChangeDetectorRef)) private _cd: ChangeDetectorRef,
|
||||||
@Inject(forwardRef(() => CommonServiceInterface)) private _dashboardService: CommonServiceInterface,
|
@Inject(forwardRef(() => CommonServiceInterface)) commonService: CommonServiceInterface,
|
||||||
@Inject(forwardRef(() => JobHistoryComponent)) private _jobHistoryComponent: JobHistoryComponent,
|
@Inject(forwardRef(() => JobHistoryComponent)) private _jobHistoryComponent: JobHistoryComponent,
|
||||||
@Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService
|
@Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService,
|
||||||
|
@Inject(IInstantiationService) instantiationService: IInstantiationService,
|
||||||
|
@Inject(IContextMenuService) contextMenuService: IContextMenuService,
|
||||||
|
@Inject(IKeybindingService) keybindingService: IKeybindingService,
|
||||||
|
@Inject(IDashboardService) dashboardService: IDashboardService
|
||||||
) {
|
) {
|
||||||
super();
|
super(commonService, dashboardService, contextMenuService, keybindingService, instantiationService);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterContentChecked() {
|
ngAfterContentChecked() {
|
||||||
@@ -64,7 +74,7 @@ export class JobStepsViewComponent extends Disposable implements OnInit, AfterCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
let ownerUri: string = this._dashboardService.connectionManagementService.connectionInfo.ownerUri;
|
let ownerUri: string = this._commonService.connectionManagementService.connectionInfo.ownerUri;
|
||||||
this._tree = new Tree(this._tableContainer.nativeElement, {
|
this._tree = new Tree(this._tableContainer.nativeElement, {
|
||||||
controller: this._treeController,
|
controller: this._treeController,
|
||||||
dataSource: this._treeDataSource,
|
dataSource: this._treeDataSource,
|
||||||
@@ -73,5 +83,11 @@ export class JobStepsViewComponent extends Disposable implements OnInit, AfterCo
|
|||||||
}, {verticalScrollMode: ScrollbarVisibility.Visible});
|
}, {verticalScrollMode: ScrollbarVisibility.Visible});
|
||||||
this._register(attachListStyler(this._tree, this.themeService));
|
this._register(attachListStyler(this._tree, this.themeService));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public onFirstVisible() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public layout() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
|||||||
import { TPromise } from 'vs/base/common/winjs.base';
|
import { TPromise } from 'vs/base/common/winjs.base';
|
||||||
import { IAction } from 'vs/base/common/actions';
|
import { IAction } from 'vs/base/common/actions';
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
import { IDashboardService } from 'sql/services/dashboard/common/dashboardService';
|
||||||
|
import { escape } from 'sql/base/common/strings';
|
||||||
|
|
||||||
export const JOBSVIEW_SELECTOR: string = 'jobsview-component';
|
export const JOBSVIEW_SELECTOR: string = 'jobsview-component';
|
||||||
export const ROW_HEIGHT: number = 45;
|
export const ROW_HEIGHT: number = 45;
|
||||||
@@ -99,8 +101,9 @@ export class JobsViewComponent extends JobManagementView implements OnInit {
|
|||||||
@Inject(IInstantiationService) instantiationService: IInstantiationService,
|
@Inject(IInstantiationService) instantiationService: IInstantiationService,
|
||||||
@Inject(IContextMenuService) contextMenuService: IContextMenuService,
|
@Inject(IContextMenuService) contextMenuService: IContextMenuService,
|
||||||
@Inject(IKeybindingService) keybindingService: IKeybindingService,
|
@Inject(IKeybindingService) keybindingService: IKeybindingService,
|
||||||
|
@Inject(IDashboardService) _dashboardService: IDashboardService
|
||||||
) {
|
) {
|
||||||
super(commonService, contextMenuService, keybindingService, instantiationService);
|
super(commonService, _dashboardService, contextMenuService, keybindingService, instantiationService);
|
||||||
let jobCacheObjectMap = this._jobManagementService.jobCacheObjectMap;
|
let jobCacheObjectMap = this._jobManagementService.jobCacheObjectMap;
|
||||||
this._serverName = commonService.connectionManagementService.connectionInfo.connectionProfile.serverName;
|
this._serverName = commonService.connectionManagementService.connectionInfo.connectionProfile.serverName;
|
||||||
let jobCache = jobCacheObjectMap[this._serverName];
|
let jobCache = jobCacheObjectMap[this._serverName];
|
||||||
@@ -121,7 +124,15 @@ export class JobsViewComponent extends JobManagementView implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public layout() {
|
public layout() {
|
||||||
this._table.layout(new dom.Dimension(dom.getContentWidth(this._gridEl.nativeElement), dom.getContentHeight(this._gridEl.nativeElement)));
|
let jobsViewToolbar = $('jobsview-component .actionbar-container').get(0);
|
||||||
|
let statusBar = $('.part.statusbar').get(0);
|
||||||
|
if (jobsViewToolbar && statusBar) {
|
||||||
|
let toolbarBottom = jobsViewToolbar.getBoundingClientRect().bottom;
|
||||||
|
let statusTop = statusBar.getBoundingClientRect().top;
|
||||||
|
this._table.layout(new dom.Dimension(
|
||||||
|
dom.getContentWidth(this._gridEl.nativeElement),
|
||||||
|
statusTop - toolbarBottom));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onFirstVisible() {
|
onFirstVisible() {
|
||||||
@@ -141,7 +152,7 @@ export class JobsViewComponent extends JobManagementView implements OnInit {
|
|||||||
enableColumnReorder: false,
|
enableColumnReorder: false,
|
||||||
rowHeight: ROW_HEIGHT,
|
rowHeight: ROW_HEIGHT,
|
||||||
enableCellNavigation: true,
|
enableCellNavigation: true,
|
||||||
forceFitColumns: true
|
forceFitColumns: false
|
||||||
};
|
};
|
||||||
|
|
||||||
this.dataView = new Slick.Data.DataView({ inlineFilters: false });
|
this.dataView = new Slick.Data.DataView({ inlineFilters: false });
|
||||||
@@ -328,7 +339,6 @@ export class JobsViewComponent extends JobManagementView implements OnInit {
|
|||||||
this.dataView.beginUpdate();
|
this.dataView.beginUpdate();
|
||||||
this.dataView.setItems(jobViews);
|
this.dataView.setItems(jobViews);
|
||||||
this.dataView.setFilter((item) => this.filter(item));
|
this.dataView.setFilter((item) => this.filter(item));
|
||||||
|
|
||||||
this.dataView.endUpdate();
|
this.dataView.endUpdate();
|
||||||
this._table.autosizeColumns();
|
this._table.autosizeColumns();
|
||||||
this._table.resizeCanvas();
|
this._table.resizeCanvas();
|
||||||
@@ -341,17 +351,6 @@ export class JobsViewComponent extends JobManagementView implements OnInit {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const self = this;
|
const self = this;
|
||||||
$(window).resize(() => {
|
|
||||||
let jobsViewToolbar = $('jobsview-component .actionbar-container').get(0);
|
|
||||||
let statusBar = $('.part.statusbar').get(0);
|
|
||||||
if (jobsViewToolbar && statusBar) {
|
|
||||||
let toolbarBottom = jobsViewToolbar.getBoundingClientRect().bottom;
|
|
||||||
let statusTop = statusBar.getBoundingClientRect().top;
|
|
||||||
$('agentview-component #jobsDiv .jobview-grid').css('height', statusTop - toolbarBottom);
|
|
||||||
self._table.resizeCanvas();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this._table.grid.onColumnsResized.subscribe((e, data: any) => {
|
this._table.grid.onColumnsResized.subscribe((e, data: any) => {
|
||||||
let nameWidth: number = data.grid.getColumnWidths()[1];
|
let nameWidth: number = data.grid.getColumnWidths()[1];
|
||||||
// adjust job name when resized
|
// adjust job name when resized
|
||||||
@@ -487,7 +486,7 @@ export class JobsViewComponent extends JobManagementView implements OnInit {
|
|||||||
|
|
||||||
return '<table class="jobview-jobnametable"><tr class="jobview-jobnamerow">' +
|
return '<table class="jobview-jobnametable"><tr class="jobview-jobnamerow">' +
|
||||||
'<td nowrap class=' + resultIndicatorClass + '></td>' +
|
'<td nowrap class=' + resultIndicatorClass + '></td>' +
|
||||||
'<td nowrap class="jobview-jobnametext">' + dataContext.name + '</td>' +
|
'<td nowrap class="jobview-jobnametext">' + escape(dataContext.name) + '</td>' +
|
||||||
'</tr></table>';
|
'</tr></table>';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -844,7 +843,7 @@ export class JobsViewComponent extends JobManagementView implements OnInit {
|
|||||||
|
|
||||||
public openCreateJobDialog() {
|
public openCreateJobDialog() {
|
||||||
let ownerUri: string = this._commonService.connectionManagementService.connectionInfo.ownerUri;
|
let ownerUri: string = this._commonService.connectionManagementService.connectionInfo.ownerUri;
|
||||||
this._commandService.executeCommand('agent.openCreateJobDialog', ownerUri);
|
this._commandService.executeCommand('agent.openJobDialog', ownerUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
public refreshJobs() {
|
public refreshJobs() {
|
||||||
|
|||||||
@@ -29,9 +29,10 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
|||||||
import { TPromise } from 'vs/base/common/winjs.base';
|
import { TPromise } from 'vs/base/common/winjs.base';
|
||||||
import { IAction } from 'vs/base/common/actions';
|
import { IAction } from 'vs/base/common/actions';
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
import { IDashboardService } from 'sql/services/dashboard/common/dashboardService';
|
||||||
|
|
||||||
export const VIEW_SELECTOR: string = 'joboperatorsview-component';
|
export const VIEW_SELECTOR: string = 'joboperatorsview-component';
|
||||||
export const ROW_HEIGHT: number = 45;
|
export const ROW_HEIGHT: number = 30;
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: VIEW_SELECTOR,
|
selector: VIEW_SELECTOR,
|
||||||
@@ -73,9 +74,10 @@ export class OperatorsViewComponent extends JobManagementView implements OnInit
|
|||||||
@Inject(IInstantiationService) instantiationService: IInstantiationService,
|
@Inject(IInstantiationService) instantiationService: IInstantiationService,
|
||||||
@Inject(forwardRef(() => CommonServiceInterface)) commonService: CommonServiceInterface,
|
@Inject(forwardRef(() => CommonServiceInterface)) commonService: CommonServiceInterface,
|
||||||
@Inject(IContextMenuService) contextMenuService: IContextMenuService,
|
@Inject(IContextMenuService) contextMenuService: IContextMenuService,
|
||||||
@Inject(IKeybindingService) keybindingService: IKeybindingService
|
@Inject(IKeybindingService) keybindingService: IKeybindingService,
|
||||||
|
@Inject(IDashboardService) _dashboardService: IDashboardService
|
||||||
) {
|
) {
|
||||||
super(commonService, contextMenuService, keybindingService, instantiationService);
|
super(commonService, _dashboardService, contextMenuService, keybindingService, instantiationService);
|
||||||
this._isCloud = commonService.connectionManagementService.connectionInfo.serverInfo.isCloud;
|
this._isCloud = commonService.connectionManagementService.connectionInfo.serverInfo.isCloud;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +88,14 @@ export class OperatorsViewComponent extends JobManagementView implements OnInit
|
|||||||
}
|
}
|
||||||
|
|
||||||
public layout() {
|
public layout() {
|
||||||
this._table.layout(new dom.Dimension(dom.getContentWidth(this._gridEl.nativeElement), dom.getContentHeight(this._gridEl.nativeElement)));
|
let height = dom.getContentHeight(this._gridEl.nativeElement) - 10;
|
||||||
|
if (height < 0) {
|
||||||
|
height = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._table.layout(new dom.Dimension(
|
||||||
|
dom.getContentWidth(this._gridEl.nativeElement),
|
||||||
|
height));
|
||||||
}
|
}
|
||||||
|
|
||||||
onFirstVisible() {
|
onFirstVisible() {
|
||||||
@@ -95,13 +104,6 @@ export class OperatorsViewComponent extends JobManagementView implements OnInit
|
|||||||
column.rerenderOnResize = true;
|
column.rerenderOnResize = true;
|
||||||
return column;
|
return column;
|
||||||
});
|
});
|
||||||
let options = <Slick.GridOptions<any>>{
|
|
||||||
syncColumnCellResize: true,
|
|
||||||
enableColumnReorder: false,
|
|
||||||
rowHeight: ROW_HEIGHT,
|
|
||||||
enableCellNavigation: true,
|
|
||||||
forceFitColumns: true
|
|
||||||
};
|
|
||||||
|
|
||||||
this.dataView = new Slick.Data.DataView();
|
this.dataView = new Slick.Data.DataView();
|
||||||
|
|
||||||
@@ -163,7 +165,7 @@ export class OperatorsViewComponent extends JobManagementView implements OnInit
|
|||||||
|
|
||||||
public openCreateOperatorDialog() {
|
public openCreateOperatorDialog() {
|
||||||
let ownerUri: string = this._commonService.connectionManagementService.connectionInfo.ownerUri;
|
let ownerUri: string = this._commonService.connectionManagementService.connectionInfo.ownerUri;
|
||||||
this._commandService.executeCommand('agent.openCreateOperatorDialog', ownerUri);
|
this._commandService.executeCommand('agent.openOperatorDialog', ownerUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
private refreshJobs() {
|
private refreshJobs() {
|
||||||
|
|||||||
@@ -29,9 +29,10 @@ import { TPromise } from 'vs/base/common/winjs.base';
|
|||||||
import { IAction } from 'vs/base/common/actions';
|
import { IAction } from 'vs/base/common/actions';
|
||||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
import { IDashboardService } from 'sql/services/dashboard/common/dashboardService';
|
||||||
|
|
||||||
export const VIEW_SELECTOR: string = 'jobproxiesview-component';
|
export const VIEW_SELECTOR: string = 'jobproxiesview-component';
|
||||||
export const ROW_HEIGHT: number = 45;
|
export const ROW_HEIGHT: number = 30;
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: VIEW_SELECTOR,
|
selector: VIEW_SELECTOR,
|
||||||
@@ -75,9 +76,10 @@ export class ProxiesViewComponent extends JobManagementView implements OnInit {
|
|||||||
@Inject(IInstantiationService) instantiationService: IInstantiationService,
|
@Inject(IInstantiationService) instantiationService: IInstantiationService,
|
||||||
@Inject(forwardRef(() => CommonServiceInterface)) commonService: CommonServiceInterface,
|
@Inject(forwardRef(() => CommonServiceInterface)) commonService: CommonServiceInterface,
|
||||||
@Inject(IContextMenuService) contextMenuService: IContextMenuService,
|
@Inject(IContextMenuService) contextMenuService: IContextMenuService,
|
||||||
@Inject(IKeybindingService) keybindingService: IKeybindingService
|
@Inject(IKeybindingService) keybindingService: IKeybindingService,
|
||||||
|
@Inject(IDashboardService) _dashboardService: IDashboardService
|
||||||
) {
|
) {
|
||||||
super(commonService, contextMenuService, keybindingService, instantiationService);
|
super(commonService, _dashboardService, contextMenuService, keybindingService, instantiationService);
|
||||||
this._isCloud = commonService.connectionManagementService.connectionInfo.serverInfo.isCloud;
|
this._isCloud = commonService.connectionManagementService.connectionInfo.serverInfo.isCloud;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +90,14 @@ export class ProxiesViewComponent extends JobManagementView implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public layout() {
|
public layout() {
|
||||||
this._table.layout(new dom.Dimension(dom.getContentWidth(this._gridEl.nativeElement), dom.getContentHeight(this._gridEl.nativeElement)));
|
let height = dom.getContentHeight(this._gridEl.nativeElement) - 10;
|
||||||
|
if (height < 0) {
|
||||||
|
height = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._table.layout(new dom.Dimension(
|
||||||
|
dom.getContentWidth(this._gridEl.nativeElement),
|
||||||
|
height));
|
||||||
}
|
}
|
||||||
|
|
||||||
onFirstVisible() {
|
onFirstVisible() {
|
||||||
@@ -97,13 +106,6 @@ export class ProxiesViewComponent extends JobManagementView implements OnInit {
|
|||||||
column.rerenderOnResize = true;
|
column.rerenderOnResize = true;
|
||||||
return column;
|
return column;
|
||||||
});
|
});
|
||||||
let options = <Slick.GridOptions<any>>{
|
|
||||||
syncColumnCellResize: true,
|
|
||||||
enableColumnReorder: false,
|
|
||||||
rowHeight: ROW_HEIGHT,
|
|
||||||
enableCellNavigation: true,
|
|
||||||
forceFitColumns: true
|
|
||||||
};
|
|
||||||
|
|
||||||
this.dataView = new Slick.Data.DataView();
|
this.dataView = new Slick.Data.DataView();
|
||||||
|
|
||||||
@@ -164,7 +166,11 @@ export class ProxiesViewComponent extends JobManagementView implements OnInit {
|
|||||||
|
|
||||||
public openCreateProxyDialog() {
|
public openCreateProxyDialog() {
|
||||||
let ownerUri: string = this._commonService.connectionManagementService.connectionInfo.ownerUri;
|
let ownerUri: string = this._commonService.connectionManagementService.connectionInfo.ownerUri;
|
||||||
this._commandService.executeCommand('agent.openCreateProxyDialog', ownerUri);
|
this._jobManagementService.getCredentials(ownerUri).then((result) => {
|
||||||
|
if (result && result.credentials) {
|
||||||
|
this._commandService.executeCommand('agent.openProxyDialog', ownerUri, undefined, result.credentials);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private refreshJobs() {
|
private refreshJobs() {
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
import 'vs/css!./button';
|
import 'vs/css!./button';
|
||||||
import {
|
import {
|
||||||
Component, Input, Inject, ChangeDetectorRef, forwardRef, ComponentFactoryResolver,
|
Component, Input, Inject, ChangeDetectorRef, forwardRef,
|
||||||
ViewChild, ViewChildren, ElementRef, Injector, OnDestroy, QueryList, AfterViewInit
|
ViewChild, ElementRef, OnDestroy, AfterViewInit
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
|
|
||||||
import * as sqlops from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
@@ -24,7 +24,13 @@ import { Color } from 'vs/base/common/color';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'modelview-button',
|
selector: 'modelview-button',
|
||||||
template: `
|
template: `
|
||||||
<div #input style="width: 100%"></div>
|
<div>
|
||||||
|
<label for={{this.label}}>
|
||||||
|
<div #input style="width: 100%">
|
||||||
|
<input *ngIf="this.isFile === true" id={{this.label}} type="file" style="display: none">
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
export default class ButtonComponent extends ComponentWithIconBase implements IComponent, OnDestroy, AfterViewInit {
|
export default class ButtonComponent extends ComponentWithIconBase implements IComponent, OnDestroy, AfterViewInit {
|
||||||
@@ -119,9 +125,19 @@ export default class ButtonComponent extends ComponentWithIconBase implements IC
|
|||||||
this.setPropertyFromUI<sqlops.ButtonProperties, string>(this.setValueProperties, newValue);
|
this.setPropertyFromUI<sqlops.ButtonProperties, string>(this.setValueProperties, newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private get isFile(): boolean {
|
||||||
|
return this.getPropertyOrDefault<sqlops.ButtonProperties, boolean>((props) => props.isFile, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private set isFile(newValue: boolean) {
|
||||||
|
this.setPropertyFromUI<sqlops.ButtonProperties, boolean>(this.setFileProperties, newValue);
|
||||||
|
}
|
||||||
|
|
||||||
private setValueProperties(properties: sqlops.ButtonProperties, label: string): void {
|
private setValueProperties(properties: sqlops.ButtonProperties, label: string): void {
|
||||||
properties.label = label;
|
properties.label = label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private setFileProperties(properties: sqlops.ButtonProperties, isFile: boolean): void {
|
||||||
|
properties.isFile = isFile;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,11 +130,14 @@ export abstract class ComponentBase extends Disposable implements IComponent, On
|
|||||||
this.setPropertyFromUI<sqlops.ComponentProperties, number | string>((props, value) => props.width = value, newValue);
|
this.setPropertyFromUI<sqlops.ComponentProperties, number | string>((props, value) => props.width = value, newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected convertSizeToNumber(size: number | string): number {
|
public convertSizeToNumber(size: number | string): number {
|
||||||
if (size && typeof (size) === 'string') {
|
if (size && typeof (size) === 'string') {
|
||||||
if (size.toLowerCase().endsWith('px')) {
|
if (size.toLowerCase().endsWith('px')) {
|
||||||
return +size.replace('px', '');
|
return +size.replace('px', '');
|
||||||
|
} else if (size.toLowerCase().endsWith('em')) {
|
||||||
|
return +size.replace('em', '') * 11;
|
||||||
}
|
}
|
||||||
|
} else if (!size) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return +size;
|
return +size;
|
||||||
@@ -148,7 +151,7 @@ export abstract class ComponentBase extends Disposable implements IComponent, On
|
|||||||
return this.height ? this.convertSize(this.height) : '';
|
return this.height ? this.convertSize(this.height) : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected convertSize(size: number | string, defaultValue?: string): string {
|
public convertSize(size: number | string, defaultValue?: string): string {
|
||||||
defaultValue = defaultValue || '';
|
defaultValue = defaultValue || '';
|
||||||
if (types.isUndefinedOrNull(size)) {
|
if (types.isUndefinedOrNull(size)) {
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import { IContextViewService } from 'vs/platform/contextview/browser/contextView
|
|||||||
template: `
|
template: `
|
||||||
|
|
||||||
<div [style.width]="getWidth()">
|
<div [style.width]="getWidth()">
|
||||||
<div [style.display]="getEditableDisplay()" #editableDropDown style="width: 100%;"></div>
|
<div [style.display]="getEditableDisplay()" #editableDropDown style="width: 100%;"></div>
|
||||||
<div [style.display]="getNotEditableDisplay()" #dropDown style="width: 100%;"></div>
|
<div [style.display]="getNotEditableDisplay()" #dropDown style="width: 100%;"></div>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
@@ -79,7 +79,6 @@ export default class DropDownComponent extends ComponentBase implements ICompone
|
|||||||
this._selectBox = new SelectBox(this.getValues(), this.getSelectedValue(), this.contextViewService, this._dropDownContainer.nativeElement);
|
this._selectBox = new SelectBox(this.getValues(), this.getSelectedValue(), this.contextViewService, this._dropDownContainer.nativeElement);
|
||||||
this._selectBox.render(this._dropDownContainer.nativeElement);
|
this._selectBox.render(this._dropDownContainer.nativeElement);
|
||||||
this._register(this._selectBox);
|
this._register(this._selectBox);
|
||||||
|
|
||||||
this._register(attachSelectBoxStyler(this._selectBox, this.themeService));
|
this._register(attachSelectBoxStyler(this._selectBox, this.themeService));
|
||||||
this._register(this._selectBox.onDidSelect(e => {
|
this._register(this._selectBox.onDidSelect(e => {
|
||||||
if (!this.editable) {
|
if (!this.editable) {
|
||||||
@@ -187,7 +186,7 @@ export default class DropDownComponent extends ComponentBase implements ICompone
|
|||||||
}
|
}
|
||||||
|
|
||||||
private get values(): string[] | sqlops.CategoryValue[] {
|
private get values(): string[] | sqlops.CategoryValue[] {
|
||||||
return this.getPropertyOrDefault<sqlops.DropDownProperties, string[] | sqlops.CategoryValue[]>((props) => props.values, undefined);
|
return this.getPropertyOrDefault<sqlops.DropDownProperties, string[] | sqlops.CategoryValue[]>((props) => props.values, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
private set values(newValue: string[] | sqlops.CategoryValue[]) {
|
private set values(newValue: string[] | sqlops.CategoryValue[]) {
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class FormItem {
|
|||||||
template: `
|
template: `
|
||||||
<div #container *ngIf="items" class="form-table" [style.padding]="getFormPadding()" [style.width]="getFormWidth()" [style.height]="getFormHeight()">
|
<div #container *ngIf="items" class="form-table" [style.padding]="getFormPadding()" [style.width]="getFormWidth()" [style.height]="getFormHeight()">
|
||||||
<ng-container *ngFor="let item of items">
|
<ng-container *ngFor="let item of items">
|
||||||
<div class="form-row" *ngIf="isGroupLabel(item)">
|
<div class="form-row" *ngIf="isGroupLabel(item)" [style.font-size]="getItemTitleFontSize(item)">
|
||||||
<div class="form-item-row form-group-label">
|
<div class="form-item-row form-group-label">
|
||||||
<model-component-wrapper [descriptor]="item.descriptor" [modelStore]="modelStore">
|
<model-component-wrapper [descriptor]="item.descriptor" [modelStore]="modelStore">
|
||||||
</model-component-wrapper>
|
</model-component-wrapper>
|
||||||
@@ -56,7 +56,7 @@ class FormItem {
|
|||||||
<ng-container *ngIf="isHorizontal(item)">
|
<ng-container *ngIf="isHorizontal(item)">
|
||||||
<div class="form-cell" [style.font-size]="getItemTitleFontSize(item)" [ngClass]="{'form-group-item': isInGroup(item)}">
|
<div class="form-cell" [style.font-size]="getItemTitleFontSize(item)" [ngClass]="{'form-group-item': isInGroup(item)}">
|
||||||
{{getItemTitle(item)}}<span class="form-required" *ngIf="isItemRequired(item)">*</span>
|
{{getItemTitle(item)}}<span class="form-required" *ngIf="isItemRequired(item)">*</span>
|
||||||
<span class="icon info form-info" *ngIf="itemHasInfo(item)" [title]="getItemInfo(item)"></span>
|
<span class="icon help form-info" *ngIf="itemHasInfo(item)" [title]="getItemInfo(item)"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-cell">
|
<div class="form-cell">
|
||||||
<div class="form-component-container">
|
<div class="form-component-container">
|
||||||
@@ -76,7 +76,7 @@ class FormItem {
|
|||||||
<div class="form-vertical-container" *ngIf="isVertical(item)" [style.height]="getRowHeight(item)" [ngClass]="{'form-group-item': isInGroup(item)}">
|
<div class="form-vertical-container" *ngIf="isVertical(item)" [style.height]="getRowHeight(item)" [ngClass]="{'form-group-item': isInGroup(item)}">
|
||||||
<div class="form-item-row" [style.font-size]="getItemTitleFontSize(item)">
|
<div class="form-item-row" [style.font-size]="getItemTitleFontSize(item)">
|
||||||
{{getItemTitle(item)}}<span class="form-required" *ngIf="isItemRequired(item)">*</span>
|
{{getItemTitle(item)}}<span class="form-required" *ngIf="isItemRequired(item)">*</span>
|
||||||
<span class="icon info form-info" *ngIf="itemHasInfo(item)" [title]="getItemInfo(item)"></span>
|
<span class="icon help form-info" *ngIf="itemHasInfo(item)" [title]="getItemInfo(item)"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-item-row" [style.width]="getComponentWidth(item)" [style.height]="getRowHeight(item)">
|
<div class="form-item-row" [style.width]="getComponentWidth(item)" [style.height]="getRowHeight(item)">
|
||||||
<model-component-wrapper [descriptor]="item.descriptor" [modelStore]="modelStore" [style.width]="getComponentWidth(item)" [style.height]="getRowHeight(item)">
|
<model-component-wrapper [descriptor]="item.descriptor" [modelStore]="modelStore" [style.width]="getComponentWidth(item)" [style.height]="getRowHeight(item)">
|
||||||
@@ -179,8 +179,12 @@ export default class FormContainer extends ContainerBase<FormItemLayout> impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
private getItemTitleFontSize(item: FormItem): string {
|
private getItemTitleFontSize(item: FormItem): string {
|
||||||
|
let defaultFontSize = '14px';
|
||||||
|
if (this.isInGroup(item)) {
|
||||||
|
defaultFontSize = '12px';
|
||||||
|
}
|
||||||
let itemConfig = item.config;
|
let itemConfig = item.config;
|
||||||
return itemConfig && itemConfig.titleFontSize ? this.convertSize(itemConfig.titleFontSize, '11px') : '11px';
|
return itemConfig && itemConfig.titleFontSize ? this.convertSize(itemConfig.titleFontSize, defaultFontSize) : defaultFontSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getActionComponents(item: FormItem): FormItem[] {
|
private getActionComponents(item: FormItem): FormItem[] {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.form-vertical-container {
|
.form-vertical-container {
|
||||||
padding-bottom: 15px;
|
padding-bottom: 5px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,11 +57,8 @@
|
|||||||
display: table-cell;
|
display: table-cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-group-item .form-item-row,
|
|
||||||
.form-group-item.form-cell {
|
|
||||||
padding-left: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-group-label {
|
.form-group-label {
|
||||||
|
padding-top: 3px;
|
||||||
padding-bottom: 0px;
|
padding-bottom: 0px;
|
||||||
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
@@ -4,22 +4,25 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Component, Input, Inject, ChangeDetectorRef, forwardRef, ComponentFactoryResolver,
|
Component, Input, Inject, ChangeDetectorRef, forwardRef,
|
||||||
ViewChild, ViewChildren, ElementRef, Injector, OnDestroy, QueryList, AfterViewInit
|
ViewChild, ElementRef, OnDestroy, AfterViewInit
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
|
|
||||||
import * as sqlops from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
|
|
||||||
import { ComponentBase } from 'sql/parts/modelComponents/componentBase';
|
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 { InputBox } from 'sql/base/browser/ui/inputBox/inputBox';
|
import { InputBox } from 'sql/base/browser/ui/inputBox/inputBox';
|
||||||
|
import { attachInputBoxStyler } from 'sql/common/theme/styler';
|
||||||
|
|
||||||
import { IInputOptions, MessageType } from 'vs/base/browser/ui/inputbox/inputBox';
|
import { IInputOptions, MessageType } from 'vs/base/browser/ui/inputbox/inputBox';
|
||||||
import { attachInputBoxStyler, attachListStyler } from 'vs/platform/theme/common/styler';
|
|
||||||
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
||||||
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
||||||
import * as nls from 'vs/nls';
|
import * as nls from 'vs/nls';
|
||||||
import { inputBackground, inputBorder } from 'vs/platform/theme/common/colorRegistry';
|
import { inputBackground, inputBorder } from 'vs/platform/theme/common/colorRegistry';
|
||||||
|
import * as DomUtils from 'vs/base/browser/dom';
|
||||||
|
import { StandardKeyboardEvent, IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||||
|
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'modelview-inputBox',
|
selector: 'modelview-inputBox',
|
||||||
@@ -73,11 +76,31 @@ export default class InputBoxComponent extends ComponentBase implements ICompone
|
|||||||
if (this._textareaContainer) {
|
if (this._textareaContainer) {
|
||||||
let textAreaInputOptions = Object.assign({}, inputOptions, { flexibleHeight: true, type: 'textarea' });
|
let textAreaInputOptions = Object.assign({}, inputOptions, { flexibleHeight: true, type: 'textarea' });
|
||||||
this._textAreaInput = new InputBox(this._textareaContainer.nativeElement, this.contextViewService, textAreaInputOptions);
|
this._textAreaInput = new InputBox(this._textareaContainer.nativeElement, this.contextViewService, textAreaInputOptions);
|
||||||
|
this.onkeydown(this._textAreaInput.inputElement, (e: StandardKeyboardEvent) => {
|
||||||
|
if (this.tryHandleKeyEvent(e)) {
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
// Else assume that keybinding service handles routing this to a command
|
||||||
|
});
|
||||||
|
|
||||||
this.registerInput(this._textAreaInput, () => this.multiline);
|
this.registerInput(this._textAreaInput, () => this.multiline);
|
||||||
}
|
}
|
||||||
this.inputElement.hideErrors = true;
|
this.inputElement.hideErrors = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private onkeydown(domNode: HTMLElement, listener: (e: IKeyboardEvent) => void): void {
|
||||||
|
this._register(DomUtils.addDisposableListener(domNode, DomUtils.EventType.KEY_DOWN, (e: KeyboardEvent) => listener(new StandardKeyboardEvent(e))));
|
||||||
|
}
|
||||||
|
|
||||||
|
private tryHandleKeyEvent(e: StandardKeyboardEvent): boolean {
|
||||||
|
let handled: boolean = false;
|
||||||
|
|
||||||
|
if (this.multiline && e.keyCode === KeyCode.Enter) {
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
return handled;
|
||||||
|
}
|
||||||
|
|
||||||
private get inputElement(): InputBox {
|
private get inputElement(): InputBox {
|
||||||
return this.multiline ? this._textAreaInput : this._input;
|
return this.multiline ? this._textAreaInput : this._input;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ 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 { attachTableStyler } from 'sql/common/theme/styler';
|
import { attachTableStyler } from 'sql/common/theme/styler';
|
||||||
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
||||||
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
|
||||||
import { getContentHeight, getContentWidth, Dimension } from 'vs/base/browser/dom';
|
import { getContentHeight, getContentWidth, Dimension } from 'vs/base/browser/dom';
|
||||||
import { RowSelectionModel } from 'sql/base/browser/ui/table/plugins/rowSelectionModel.plugin';
|
import { RowSelectionModel } from 'sql/base/browser/ui/table/plugins/rowSelectionModel.plugin';
|
||||||
|
|
||||||
@@ -74,15 +73,21 @@ export default class TableComponent extends ComponentBase implements IComponent,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
transformData(rows: string[][], columns: any[]): { [key: string]: string }[] {
|
public static transformData(rows: string[][], columns: any[]): { [key: string]: string }[] {
|
||||||
return rows.map(row => {
|
if (rows && columns) {
|
||||||
let object: { [key: string]: string } = {};
|
return rows.map(row => {
|
||||||
row.forEach((val, index) => {
|
let object: { [key: string]: string } = {};
|
||||||
let columnName: string = (columns[index].value) ? columns[index].value : <string>columns[index];
|
if (row.forEach) {
|
||||||
object[columnName] = val;
|
row.forEach((val, index) => {
|
||||||
|
let columnName: string = (columns[index].value) ? columns[index].value : <string>columns[index];
|
||||||
|
object[columnName] = val;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return object;
|
||||||
});
|
});
|
||||||
return object;
|
} else {
|
||||||
});
|
return [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewInit(): void {
|
ngAfterViewInit(): void {
|
||||||
@@ -147,7 +152,7 @@ export default class TableComponent extends ComponentBase implements IComponent,
|
|||||||
public setProperties(properties: { [key: string]: any; }): void {
|
public setProperties(properties: { [key: string]: any; }): void {
|
||||||
super.setProperties(properties);
|
super.setProperties(properties);
|
||||||
this._tableData.clear();
|
this._tableData.clear();
|
||||||
this._tableData.push(this.transformData(this.data, this.columns));
|
this._tableData.push(TableComponent.transformData(this.data, this.columns));
|
||||||
this._tableColumns = this.transformColumns(this.columns);
|
this._tableColumns = this.transformColumns(this.columns);
|
||||||
this._table.columns = this._tableColumns;
|
this._table.columns = this._tableColumns;
|
||||||
this._table.setData(this._tableData);
|
this._table.setData(this._tableData);
|
||||||
|
|||||||
@@ -95,3 +95,7 @@ export class NodeType {
|
|||||||
public static ColumnMasterKey = 'ColumnMasterKey';
|
public static ColumnMasterKey = 'ColumnMasterKey';
|
||||||
public static ColumnEncryptionKey = 'ColumnEncryptionKey';
|
public static ColumnEncryptionKey = 'ColumnEncryptionKey';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SqlThemeIcon {
|
||||||
|
readonly id: string;
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { NodeType } from 'sql/parts/objectExplorer/common/nodeType';
|
import { NodeType } from 'sql/parts/objectExplorer/common/nodeType';
|
||||||
import { TreeNode, TreeItemCollapsibleState, ObjectExplorerCallbacks } from 'sql/parts/objectExplorer/common/treeNode';
|
import { TreeNode, TreeItemCollapsibleState } from 'sql/parts/objectExplorer/common/treeNode';
|
||||||
import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
|
import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
|
||||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||||
@@ -20,7 +20,6 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
|||||||
import { warn, error } from 'sql/base/common/log';
|
import { warn, error } from 'sql/base/common/log';
|
||||||
import { ServerTreeView } from 'sql/parts/objectExplorer/viewlet/serverTreeView';
|
import { ServerTreeView } from 'sql/parts/objectExplorer/viewlet/serverTreeView';
|
||||||
import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
|
import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
|
||||||
import * as vscode from 'vscode';
|
|
||||||
|
|
||||||
export const SERVICE_ID = 'ObjectExplorerService';
|
export const SERVICE_ID = 'ObjectExplorerService';
|
||||||
|
|
||||||
@@ -162,10 +161,16 @@ export class ObjectExplorerService implements IObjectExplorerService {
|
|||||||
error(expandResponse.errorMessage);
|
error(expandResponse.errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
let nodeStatus = this._sessions[expandResponse.sessionId].nodes[expandResponse.nodePath];
|
let sessionStatus = this._sessions[expandResponse.sessionId];
|
||||||
if (nodeStatus && nodeStatus.expandEmitter) {
|
let foundSession = false;
|
||||||
nodeStatus.expandEmitter.fire(expandResponse);
|
if (sessionStatus) {
|
||||||
} else {
|
let nodeStatus = this._sessions[expandResponse.sessionId].nodes[expandResponse.nodePath];
|
||||||
|
foundSession = !!nodeStatus;
|
||||||
|
if (foundSession && nodeStatus.expandEmitter) {
|
||||||
|
nodeStatus.expandEmitter.fire(expandResponse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!foundSession) {
|
||||||
warn(`Cannot find node status for session: ${expandResponse.sessionId} and node path: ${expandResponse.nodePath}`);
|
warn(`Cannot find node status for session: ${expandResponse.sessionId} and node path: ${expandResponse.nodePath}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -396,7 +401,7 @@ export class ObjectExplorerService implements IObjectExplorerService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new TreeNode(nodeInfo.nodeType, nodeInfo.label, isLeaf, nodeInfo.nodePath,
|
return new TreeNode(nodeInfo.nodeType, nodeInfo.label, isLeaf, nodeInfo.nodePath,
|
||||||
nodeInfo.nodeSubType, nodeInfo.nodeStatus, parent, nodeInfo.metadata, {
|
nodeInfo.nodeSubType, nodeInfo.nodeStatus, parent, nodeInfo.metadata, nodeInfo.iconType, {
|
||||||
getChildren: treeNode => this.getChildren(treeNode),
|
getChildren: treeNode => this.getChildren(treeNode),
|
||||||
isExpanded: treeNode => this.isExpanded(treeNode),
|
isExpanded: treeNode => this.isExpanded(treeNode),
|
||||||
setNodeExpandedState: (treeNode, expandedState) => this.setNodeExpandedState(treeNode, expandedState),
|
setNodeExpandedState: (treeNode, expandedState) => this.setNodeExpandedState(treeNode, expandedState),
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
|
import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
|
||||||
import { NodeType } from 'sql/parts/objectExplorer/common/nodeType';
|
import { NodeType, SqlThemeIcon } from 'sql/parts/objectExplorer/common/nodeType';
|
||||||
import * as sqlops from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
|
|
||||||
import * as UUID from 'vs/base/common/uuid';
|
import * as UUID from 'vs/base/common/uuid';
|
||||||
@@ -83,6 +83,23 @@ export class TreeNode {
|
|||||||
|
|
||||||
public metadata: sqlops.ObjectMetadata;
|
public metadata: sqlops.ObjectMetadata;
|
||||||
|
|
||||||
|
public iconType: string | SqlThemeIcon;
|
||||||
|
|
||||||
|
constructor(nodeTypeId: string, label: string, isAlwaysLeaf: boolean, nodePath: string,
|
||||||
|
nodeSubType: string, nodeStatus: string, parent: TreeNode, metadata: sqlops.ObjectMetadata,
|
||||||
|
iconType: string | SqlThemeIcon,
|
||||||
|
private _objectExplorerCallbacks: ObjectExplorerCallbacks) {
|
||||||
|
this.nodeTypeId = nodeTypeId;
|
||||||
|
this.label = label;
|
||||||
|
this.isAlwaysLeaf = isAlwaysLeaf;
|
||||||
|
this.nodePath = nodePath;
|
||||||
|
this.parent = parent;
|
||||||
|
this.metadata = metadata;
|
||||||
|
this.iconType = iconType;
|
||||||
|
this.id = UUID.generateUuid();
|
||||||
|
this.nodeSubType = nodeSubType;
|
||||||
|
this.nodeStatus = nodeStatus;
|
||||||
|
}
|
||||||
public getConnectionProfile(): ConnectionProfile {
|
public getConnectionProfile(): ConnectionProfile {
|
||||||
var currentNode: TreeNode = this;
|
var currentNode: TreeNode = this;
|
||||||
while (!currentNode.connection && currentNode.parent) {
|
while (!currentNode.connection && currentNode.parent) {
|
||||||
@@ -149,18 +166,4 @@ export class TreeNode {
|
|||||||
public setSelected(selected: boolean, clearOtherSelections?: boolean): Thenable<void> {
|
public setSelected(selected: boolean, clearOtherSelections?: boolean): Thenable<void> {
|
||||||
return this._objectExplorerCallbacks.setNodeSelected(this, selected, clearOtherSelections);
|
return this._objectExplorerCallbacks.setNodeSelected(this, selected, clearOtherSelections);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(nodeTypeId: string, label: string, isAlwaysLeaf: boolean, nodePath: string,
|
|
||||||
nodeSubType: string, nodeStatus: string, parent: TreeNode, metadata: sqlops.ObjectMetadata,
|
|
||||||
private _objectExplorerCallbacks: ObjectExplorerCallbacks) {
|
|
||||||
this.nodeTypeId = nodeTypeId;
|
|
||||||
this.label = label;
|
|
||||||
this.isAlwaysLeaf = isAlwaysLeaf;
|
|
||||||
this.nodePath = nodePath;
|
|
||||||
this.parent = parent;
|
|
||||||
this.metadata = metadata;
|
|
||||||
this.id = UUID.generateUuid();
|
|
||||||
this.nodeSubType = nodeSubType;
|
|
||||||
this.nodeStatus = nodeStatus;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -79,7 +79,7 @@ export class ServerGroupDialog extends Modal {
|
|||||||
// Connection Group Name
|
// Connection Group Name
|
||||||
let serverGroupNameLabel = localize('connectionGroupName', 'Server group name');
|
let serverGroupNameLabel = localize('connectionGroupName', 'Server group name');
|
||||||
this._bodyBuilder.div({ class: 'dialog-label' }, (labelContainer) => {
|
this._bodyBuilder.div({ class: 'dialog-label' }, (labelContainer) => {
|
||||||
labelContainer.innerHtml(serverGroupNameLabel);
|
labelContainer.text(serverGroupNameLabel);
|
||||||
});
|
});
|
||||||
this._bodyBuilder.div({ class: 'input-divider' }, (inputCellContainer) => {
|
this._bodyBuilder.div({ class: 'input-divider' }, (inputCellContainer) => {
|
||||||
let errorMessage = localize('MissingGroupNameError', 'Group name is required.');
|
let errorMessage = localize('MissingGroupNameError', 'Group name is required.');
|
||||||
@@ -94,7 +94,7 @@ export class ServerGroupDialog extends Modal {
|
|||||||
// Connection Group Description
|
// Connection Group Description
|
||||||
let groupDescriptionLabel = localize('groupDescription', 'Group description');
|
let groupDescriptionLabel = localize('groupDescription', 'Group description');
|
||||||
this._bodyBuilder.div({ class: 'dialog-label' }, (labelContainer) => {
|
this._bodyBuilder.div({ class: 'dialog-label' }, (labelContainer) => {
|
||||||
labelContainer.innerHtml(groupDescriptionLabel);
|
labelContainer.text(groupDescriptionLabel);
|
||||||
});
|
});
|
||||||
this._bodyBuilder.div({ class: 'input-divider' }, (inputCellContainer) => {
|
this._bodyBuilder.div({ class: 'input-divider' }, (inputCellContainer) => {
|
||||||
this._groupDescriptionInputBox = new InputBox(inputCellContainer.getHTMLElement(), this._contextViewService, {
|
this._groupDescriptionInputBox = new InputBox(inputCellContainer.getHTMLElement(), this._contextViewService, {
|
||||||
@@ -105,7 +105,7 @@ export class ServerGroupDialog extends Modal {
|
|||||||
// Connection Group Color
|
// Connection Group Color
|
||||||
this._bodyBuilder.div({ class: 'dialog-label' }, (labelContainer) => {
|
this._bodyBuilder.div({ class: 'dialog-label' }, (labelContainer) => {
|
||||||
let groupColorLabel = localize('groupColor', 'Group color');
|
let groupColorLabel = localize('groupColor', 'Group color');
|
||||||
labelContainer.innerHtml(groupColorLabel);
|
labelContainer.text(groupColorLabel);
|
||||||
});
|
});
|
||||||
|
|
||||||
this._bodyBuilder.div({ class: 'group-color-options' }, (groupColorContainer) => {
|
this._bodyBuilder.div({ class: 'group-color-options' }, (groupColorContainer) => {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export class RefreshAction extends Action {
|
|||||||
id: string,
|
id: string,
|
||||||
label: string,
|
label: string,
|
||||||
tree: ITree,
|
tree: ITree,
|
||||||
private element: ConnectionProfile | TreeNode,
|
private element: IConnectionProfile | TreeNode,
|
||||||
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
|
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
|
||||||
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
|
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
|
||||||
@IErrorMessageService private _errorMessageService: IErrorMessageService
|
@IErrorMessageService private _errorMessageService: IErrorMessageService
|
||||||
@@ -88,80 +88,31 @@ export class DisconnectConnectionAction extends Action {
|
|||||||
public static ID = 'objectExplorer.disconnect';
|
public static ID = 'objectExplorer.disconnect';
|
||||||
public static LABEL = localize('DisconnectAction', 'Disconnect');
|
public static LABEL = localize('DisconnectAction', 'Disconnect');
|
||||||
|
|
||||||
private _disposables: IDisposable[] = [];
|
|
||||||
private _connectionProfile: ConnectionProfile;
|
|
||||||
|
|
||||||
private _container: HTMLElement;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
id: string,
|
id: string,
|
||||||
label: string,
|
label: string,
|
||||||
|
private _connectionProfile: ConnectionProfile,
|
||||||
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
|
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
|
||||||
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
|
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
|
||||||
@IErrorMessageService private _errorMessageService: IErrorMessageService
|
@IErrorMessageService private _errorMessageService: IErrorMessageService
|
||||||
) {
|
) {
|
||||||
super(id, label);
|
super(id, label);
|
||||||
const self = this;
|
|
||||||
this._disposables.push(this._connectionManagementService.onConnect(() => {
|
|
||||||
self.setLabel();
|
|
||||||
})
|
|
||||||
);
|
|
||||||
this._disposables.push(this._connectionManagementService.onDisconnect((disconnectParams) => {
|
|
||||||
if (this._connectionProfile) {
|
|
||||||
this._connectionProfile.isDisconnecting = false;
|
|
||||||
}
|
|
||||||
self.setLabel();
|
|
||||||
self._connectionManagementService.closeDashboard(disconnectParams.connectionUri);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
if (this._objectExplorerService && this._objectExplorerService.onUpdateObjectExplorerNodes) {
|
|
||||||
this._disposables.push(this._objectExplorerService.onUpdateObjectExplorerNodes((args) => {
|
|
||||||
self.removeSpinning(args.connection);
|
|
||||||
if (args.errorMessage !== undefined) {
|
|
||||||
self.showError(args.errorMessage);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private showError(errorMessage: string) {
|
|
||||||
if (this._errorMessageService) {
|
|
||||||
this._errorMessageService.showDialog(Severity.Error, '', errorMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private setLabel(): void {
|
|
||||||
if (!this._connectionProfile) {
|
|
||||||
this.label = 'Connect';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.label = this._connectionManagementService.isProfileConnected(this._connectionProfile) ? 'Disconnect' : 'Connect';
|
|
||||||
}
|
|
||||||
|
|
||||||
private removeSpinning(connection: IConnectionProfile): void {
|
|
||||||
if (this._connectionProfile) {
|
|
||||||
if (connection.id === this._connectionProfile.id && this._container) {
|
|
||||||
ObjectExplorerActionUtilities.hideLoadingIcon(this._container, ObjectExplorerActionUtilities.connectionElementClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
run(actionContext: ObjectExplorerActionsContext): TPromise<any> {
|
run(actionContext: ObjectExplorerActionsContext): TPromise<any> {
|
||||||
return new TPromise<boolean>((resolve, reject) => {
|
return new TPromise<boolean>((resolve, reject) => {
|
||||||
if (actionContext instanceof ObjectExplorerActionsContext) {
|
|
||||||
//set objectExplorerTreeNode for context menu clicks
|
|
||||||
this._connectionProfile = actionContext.connectionProfile;
|
|
||||||
this._container = actionContext.container;
|
|
||||||
resolve(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this._connectionProfile) {
|
if (!this._connectionProfile) {
|
||||||
resolve(true);
|
resolve(true);
|
||||||
}
|
}
|
||||||
if (this._connectionManagementService.isProfileConnected(this._connectionProfile)) {
|
if (this._connectionManagementService.isProfileConnected(this._connectionProfile)) {
|
||||||
this._connectionProfile.isDisconnecting = true;
|
let profileImpl = this._connectionProfile as ConnectionProfile;
|
||||||
|
if (profileImpl) {
|
||||||
|
profileImpl.isDisconnecting = true;
|
||||||
|
}
|
||||||
this._connectionManagementService.disconnect(this._connectionProfile).then((value) => {
|
this._connectionManagementService.disconnect(this._connectionProfile).then((value) => {
|
||||||
|
if (profileImpl) {
|
||||||
|
profileImpl.isDisconnecting = false;
|
||||||
|
}
|
||||||
resolve(true);
|
resolve(true);
|
||||||
}
|
}
|
||||||
).catch(disconnectError => {
|
).catch(disconnectError => {
|
||||||
@@ -172,11 +123,6 @@ export class DisconnectConnectionAction extends Action {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose(): void {
|
|
||||||
super.dispose();
|
|
||||||
this._disposables = dispose(this._disposables);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -362,11 +308,11 @@ export class RecentConnectionsFilterAction extends Action {
|
|||||||
export class NewQueryAction extends Action {
|
export class NewQueryAction extends Action {
|
||||||
public static ID = 'registeredServers.newQuery';
|
public static ID = 'registeredServers.newQuery';
|
||||||
public static LABEL = localize('registeredServers.newQuery', 'New Query');
|
public static LABEL = localize('registeredServers.newQuery', 'New Query');
|
||||||
private _connectionProfile: ConnectionProfile;
|
private _connectionProfile: IConnectionProfile;
|
||||||
get connectionProfile(): ConnectionProfile {
|
get connectionProfile(): IConnectionProfile {
|
||||||
return this._connectionProfile;
|
return this._connectionProfile;
|
||||||
}
|
}
|
||||||
set connectionProfile(profile: ConnectionProfile) {
|
set connectionProfile(profile: IConnectionProfile) {
|
||||||
this._connectionProfile = profile;
|
this._connectionProfile = profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -403,7 +349,7 @@ export class DeleteConnectionAction extends Action {
|
|||||||
constructor(
|
constructor(
|
||||||
id: string,
|
id: string,
|
||||||
label: string,
|
label: string,
|
||||||
private element: ConnectionProfile | ConnectionProfileGroup,
|
private element: IConnectionProfile | ConnectionProfileGroup,
|
||||||
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService
|
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService
|
||||||
) {
|
) {
|
||||||
super(id, label);
|
super(id, label);
|
||||||
@@ -413,7 +359,6 @@ export class DeleteConnectionAction extends Action {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (element instanceof ConnectionProfile) {
|
if (element instanceof ConnectionProfile) {
|
||||||
element = <ConnectionProfile>element;
|
|
||||||
let parent: ConnectionProfileGroup = element.parent;
|
let parent: ConnectionProfileGroup = element.parent;
|
||||||
if (parent && parent.id === Constants.unsavedGroupId) {
|
if (parent && parent.id === Constants.unsavedGroupId) {
|
||||||
this.enabled = false;
|
this.enabled = false;
|
||||||
|
|||||||
@@ -8,11 +8,14 @@ import { localize } from 'vs/nls';
|
|||||||
import { TPromise } from 'vs/base/common/winjs.base';
|
import { TPromise } from 'vs/base/common/winjs.base';
|
||||||
import { Action } from 'vs/base/common/actions';
|
import { Action } from 'vs/base/common/actions';
|
||||||
import { ITree } from 'vs/base/parts/tree/browser/tree';
|
import { ITree } from 'vs/base/parts/tree/browser/tree';
|
||||||
|
import { ExecuteCommandAction } from 'vs/platform/actions/common/actions';
|
||||||
|
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||||
|
|
||||||
|
import * as sqlops from 'sqlops';
|
||||||
import { IConnectionManagementService, IConnectionCompletionOptions, IErrorMessageService } from 'sql/parts/connection/common/connectionManagement';
|
import { IConnectionManagementService, IConnectionCompletionOptions, IErrorMessageService } from 'sql/parts/connection/common/connectionManagement';
|
||||||
import { TreeNode } from 'sql/parts/objectExplorer/common/treeNode';
|
import { TreeNode } from 'sql/parts/objectExplorer/common/treeNode';
|
||||||
import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
|
|
||||||
import {
|
import {
|
||||||
NewQueryAction, ScriptSelectAction, EditDataAction, ScriptCreateAction,
|
ScriptSelectAction, EditDataAction, ScriptCreateAction,
|
||||||
ScriptExecuteAction, ScriptDeleteAction, ScriptAlterAction
|
ScriptExecuteAction, ScriptDeleteAction, ScriptAlterAction
|
||||||
} from 'sql/workbench/common/actions';
|
} from 'sql/workbench/common/actions';
|
||||||
import { NodeType } from 'sql/parts/objectExplorer/common/nodeType';
|
import { NodeType } from 'sql/parts/objectExplorer/common/nodeType';
|
||||||
@@ -23,41 +26,51 @@ import { IScriptingService } from 'sql/services/scripting/scriptingService';
|
|||||||
import { IQueryEditorService } from 'sql/parts/query/common/queryEditorService';
|
import { IQueryEditorService } from 'sql/parts/query/common/queryEditorService';
|
||||||
import { IObjectExplorerService } from 'sql/parts/objectExplorer/common/objectExplorerService';
|
import { IObjectExplorerService } from 'sql/parts/objectExplorer/common/objectExplorerService';
|
||||||
import * as Constants from 'sql/parts/connection/common/constants';
|
import * as Constants from 'sql/parts/connection/common/constants';
|
||||||
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
|
|
||||||
import { ExecuteCommandAction } from 'vs/platform/actions/common/actions';
|
|
||||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
|
||||||
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
||||||
|
import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
|
||||||
|
import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
|
||||||
|
|
||||||
export class ObjectExplorerActionsContext {
|
|
||||||
public treeNode: TreeNode;
|
export class ObjectExplorerActionsContext implements sqlops.ObjectExplorerContext {
|
||||||
public connectionProfile: ConnectionProfile;
|
public connectionProfile: IConnectionProfile;
|
||||||
public container: HTMLElement;
|
public nodeInfo: sqlops.NodeInfo;
|
||||||
public tree: ITree;
|
public isConnectionNode: boolean = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getTreeNode(context: ObjectExplorerActionsContext, objectExplorerService: IObjectExplorerService): TPromise<TreeNode> {
|
||||||
|
if (context.isConnectionNode) {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
return await objectExplorerService.getTreeNode(context.connectionProfile.id, context.nodeInfo.nodePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export class OEAction extends ExecuteCommandAction {
|
export class OEAction extends ExecuteCommandAction {
|
||||||
private _objectExplorerTreeNode: TreeNode;
|
|
||||||
private _container: HTMLElement;
|
|
||||||
private _treeSelectionHandler: TreeSelectionHandler;
|
private _treeSelectionHandler: TreeSelectionHandler;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
id: string, label: string,
|
id: string, label: string,
|
||||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||||
@ICommandService commandService: ICommandService,
|
@ICommandService commandService: ICommandService,
|
||||||
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService
|
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
|
||||||
|
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService
|
||||||
) {
|
) {
|
||||||
super(id, label, commandService);
|
super(id, label, commandService);
|
||||||
}
|
}
|
||||||
|
|
||||||
public run(actionContext: any): TPromise<boolean> {
|
public async run(actionContext: any): TPromise<boolean> {
|
||||||
this._treeSelectionHandler = this._instantiationService.createInstance(TreeSelectionHandler);
|
this._treeSelectionHandler = this._instantiationService.createInstance(TreeSelectionHandler);
|
||||||
|
|
||||||
|
|
||||||
let profile: IConnectionProfile;
|
let profile: IConnectionProfile;
|
||||||
if (actionContext.connectionProfile) {
|
if (actionContext instanceof ObjectExplorerActionsContext) {
|
||||||
profile = actionContext.connectionProfile;
|
if (actionContext.isConnectionNode) {
|
||||||
} else {
|
profile = actionContext.connectionProfile;
|
||||||
profile = TreeUpdateUtils.getConnectionProfile(<TreeNode>actionContext.treeNode);
|
} else {
|
||||||
|
// Get the "correct" version from the tree
|
||||||
|
let treeNode = await getTreeNode(actionContext, this._objectExplorerService);
|
||||||
|
profile = TreeUpdateUtils.getConnectionProfile(treeNode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this._treeSelectionHandler.onTreeActionStateChange(true);
|
this._treeSelectionHandler.onTreeActionStateChange(true);
|
||||||
|
|
||||||
@@ -72,18 +85,16 @@ export class ManageConnectionAction extends Action {
|
|||||||
public static ID = 'objectExplorer.manage';
|
public static ID = 'objectExplorer.manage';
|
||||||
public static LABEL = localize('ManageAction', 'Manage');
|
public static LABEL = localize('ManageAction', 'Manage');
|
||||||
|
|
||||||
private _connectionProfile: ConnectionProfile;
|
|
||||||
private _objectExplorerTreeNode: TreeNode;
|
|
||||||
private _treeSelectionHandler: TreeSelectionHandler;
|
private _treeSelectionHandler: TreeSelectionHandler;
|
||||||
|
|
||||||
protected _container: HTMLElement;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
id: string,
|
id: string,
|
||||||
label: string,
|
label: string,
|
||||||
|
private _tree: ITree,
|
||||||
@IConnectionManagementService protected _connectionManagementService: IConnectionManagementService,
|
@IConnectionManagementService protected _connectionManagementService: IConnectionManagementService,
|
||||||
|
@ICapabilitiesService protected _capabilitiesService: ICapabilitiesService,
|
||||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||||
@IObjectExplorerService private _objectExplorerService?: IObjectExplorerService,
|
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService
|
||||||
) {
|
) {
|
||||||
super(id, label);
|
super(id, label);
|
||||||
}
|
}
|
||||||
@@ -91,33 +102,37 @@ export class ManageConnectionAction extends Action {
|
|||||||
run(actionContext: ObjectExplorerActionsContext): TPromise<any> {
|
run(actionContext: ObjectExplorerActionsContext): TPromise<any> {
|
||||||
this._treeSelectionHandler = this._instantiationService.createInstance(TreeSelectionHandler);
|
this._treeSelectionHandler = this._instantiationService.createInstance(TreeSelectionHandler);
|
||||||
this._treeSelectionHandler.onTreeActionStateChange(true);
|
this._treeSelectionHandler.onTreeActionStateChange(true);
|
||||||
|
let self = this;
|
||||||
let promise = new TPromise<boolean>((resolve, reject) => {
|
let promise = new TPromise<boolean>((resolve, reject) => {
|
||||||
this.doManage(actionContext).then((success) => {
|
self.doManage(actionContext).then((success) => {
|
||||||
this.done();
|
self.done();
|
||||||
resolve(success);
|
resolve(success);
|
||||||
}, error => {
|
}, error => {
|
||||||
this.done();
|
self.done();
|
||||||
reject(error);
|
reject(error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
private doManage(actionContext: ObjectExplorerActionsContext): Thenable<boolean> {
|
private async doManage(actionContext: ObjectExplorerActionsContext): TPromise<boolean> {
|
||||||
|
let treeNode: TreeNode = undefined;
|
||||||
|
let connectionProfile: IConnectionProfile = undefined;
|
||||||
if (actionContext instanceof ObjectExplorerActionsContext) {
|
if (actionContext instanceof ObjectExplorerActionsContext) {
|
||||||
//set objectExplorerTreeNode for context menu clicks
|
// Must use a real connection profile for this action due to lookup
|
||||||
this._connectionProfile = actionContext.connectionProfile;
|
connectionProfile = ConnectionProfile.fromIConnectionProfile(this._capabilitiesService, actionContext.connectionProfile);
|
||||||
this._objectExplorerTreeNode = actionContext.treeNode;
|
if (!actionContext.isConnectionNode) {
|
||||||
if (this._connectionProfile === undefined && TreeUpdateUtils.isDatabaseNode(this._objectExplorerTreeNode)) {
|
treeNode = await getTreeNode(actionContext, this._objectExplorerService);
|
||||||
this._connectionProfile = TreeUpdateUtils.getConnectionProfile(<TreeNode>this._objectExplorerTreeNode);
|
if (TreeUpdateUtils.isDatabaseNode(treeNode)) {
|
||||||
|
connectionProfile = TreeUpdateUtils.getConnectionProfile(treeNode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this._container = actionContext.container;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this._connectionProfile) {
|
if (!connectionProfile) {
|
||||||
// This should never happen. There should be always a valid connection if the manage action is called for
|
// This should never happen. There should be always a valid connection if the manage action is called for
|
||||||
// an OE node or a database node
|
// an OE node or a database node
|
||||||
return TPromise.wrap(true);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let options: IConnectionCompletionOptions = {
|
let options: IConnectionCompletionOptions = {
|
||||||
@@ -130,10 +145,10 @@ export class ManageConnectionAction extends Action {
|
|||||||
|
|
||||||
// If it's a database node just open a database connection and open dashboard,
|
// If it's a database node just open a database connection and open dashboard,
|
||||||
// the node is already from an open OE session we don't need to create new session
|
// the node is already from an open OE session we don't need to create new session
|
||||||
if (TreeUpdateUtils.isAvailableDatabaseNode(this._objectExplorerTreeNode)) {
|
if (TreeUpdateUtils.isAvailableDatabaseNode(treeNode)) {
|
||||||
return this._connectionManagementService.showDashboard(this._connectionProfile);
|
return this._connectionManagementService.showDashboard(connectionProfile);
|
||||||
} else {
|
} else {
|
||||||
return TreeUpdateUtils.connectAndCreateOeSession(this._connectionProfile, options, this._connectionManagementService, this._objectExplorerService, actionContext.tree);
|
return TreeUpdateUtils.connectAndCreateOeSession(connectionProfile, options, this._connectionManagementService, this._objectExplorerService, this._tree);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,7 +164,6 @@ export class ManageConnectionAction extends Action {
|
|||||||
export class OEScriptSelectAction extends ScriptSelectAction {
|
export class OEScriptSelectAction extends ScriptSelectAction {
|
||||||
public static ID = 'objectExplorer.' + ScriptSelectAction.ID;
|
public static ID = 'objectExplorer.' + ScriptSelectAction.ID;
|
||||||
private _objectExplorerTreeNode: TreeNode;
|
private _objectExplorerTreeNode: TreeNode;
|
||||||
private _container: HTMLElement;
|
|
||||||
private _treeSelectionHandler: TreeSelectionHandler;
|
private _treeSelectionHandler: TreeSelectionHandler;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@@ -157,23 +171,23 @@ export class OEScriptSelectAction extends ScriptSelectAction {
|
|||||||
@IQueryEditorService protected _queryEditorService: IQueryEditorService,
|
@IQueryEditorService protected _queryEditorService: IQueryEditorService,
|
||||||
@IConnectionManagementService protected _connectionManagementService: IConnectionManagementService,
|
@IConnectionManagementService protected _connectionManagementService: IConnectionManagementService,
|
||||||
@IScriptingService protected _scriptingService: IScriptingService,
|
@IScriptingService protected _scriptingService: IScriptingService,
|
||||||
|
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
|
||||||
@IInstantiationService private _instantiationService: IInstantiationService
|
@IInstantiationService private _instantiationService: IInstantiationService
|
||||||
) {
|
) {
|
||||||
super(id, label, _queryEditorService, _connectionManagementService, _scriptingService);
|
super(id, label, _queryEditorService, _connectionManagementService, _scriptingService);
|
||||||
}
|
}
|
||||||
|
|
||||||
public run(actionContext: any): TPromise<boolean> {
|
public async run(actionContext: any): TPromise<boolean> {
|
||||||
this._treeSelectionHandler = this._instantiationService.createInstance(TreeSelectionHandler);
|
this._treeSelectionHandler = this._instantiationService.createInstance(TreeSelectionHandler);
|
||||||
if (actionContext instanceof ObjectExplorerActionsContext) {
|
if (actionContext instanceof ObjectExplorerActionsContext) {
|
||||||
//set objectExplorerTreeNode for context menu clicks
|
//set objectExplorerTreeNode for context menu clicks
|
||||||
this._objectExplorerTreeNode = actionContext.treeNode;
|
this._objectExplorerTreeNode = await getTreeNode(actionContext, this._objectExplorerService);
|
||||||
this._container = actionContext.container;
|
|
||||||
}
|
}
|
||||||
this._treeSelectionHandler.onTreeActionStateChange(true);
|
this._treeSelectionHandler.onTreeActionStateChange(true);
|
||||||
var connectionProfile = TreeUpdateUtils.getConnectionProfile(<TreeNode>this._objectExplorerTreeNode);
|
var connectionProfile = TreeUpdateUtils.getConnectionProfile(this._objectExplorerTreeNode);
|
||||||
var ownerUri = this._connectionManagementService.getConnectionId(connectionProfile);
|
var ownerUri = this._connectionManagementService.getConnectionId(connectionProfile);
|
||||||
ownerUri = this._connectionManagementService.getFormattedUri(ownerUri, connectionProfile);
|
ownerUri = this._connectionManagementService.getFormattedUri(ownerUri, connectionProfile);
|
||||||
var metadata = (<TreeNode>this._objectExplorerTreeNode).metadata;
|
var metadata = this._objectExplorerTreeNode.metadata;
|
||||||
|
|
||||||
return super.run({ profile: connectionProfile, object: metadata }).then((result) => {
|
return super.run({ profile: connectionProfile, object: metadata }).then((result) => {
|
||||||
this._treeSelectionHandler.onTreeActionStateChange(false);
|
this._treeSelectionHandler.onTreeActionStateChange(false);
|
||||||
@@ -185,7 +199,6 @@ export class OEScriptSelectAction extends ScriptSelectAction {
|
|||||||
export class OEEditDataAction extends EditDataAction {
|
export class OEEditDataAction extends EditDataAction {
|
||||||
public static ID = 'objectExplorer.' + EditDataAction.ID;
|
public static ID = 'objectExplorer.' + EditDataAction.ID;
|
||||||
private _objectExplorerTreeNode: TreeNode;
|
private _objectExplorerTreeNode: TreeNode;
|
||||||
private _container: HTMLElement;
|
|
||||||
private _treeSelectionHandler: TreeSelectionHandler;
|
private _treeSelectionHandler: TreeSelectionHandler;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@@ -193,17 +206,17 @@ export class OEEditDataAction extends EditDataAction {
|
|||||||
@IQueryEditorService protected _queryEditorService: IQueryEditorService,
|
@IQueryEditorService protected _queryEditorService: IQueryEditorService,
|
||||||
@IConnectionManagementService protected _connectionManagementService: IConnectionManagementService,
|
@IConnectionManagementService protected _connectionManagementService: IConnectionManagementService,
|
||||||
@IScriptingService protected _scriptingService: IScriptingService,
|
@IScriptingService protected _scriptingService: IScriptingService,
|
||||||
|
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
|
||||||
@IInstantiationService private _instantiationService: IInstantiationService
|
@IInstantiationService private _instantiationService: IInstantiationService
|
||||||
) {
|
) {
|
||||||
super(id, label, _queryEditorService, _connectionManagementService, _scriptingService);
|
super(id, label, _queryEditorService, _connectionManagementService, _scriptingService);
|
||||||
}
|
}
|
||||||
|
|
||||||
public run(actionContext: any): TPromise<boolean> {
|
public async run(actionContext: any): TPromise<boolean> {
|
||||||
this._treeSelectionHandler = this._instantiationService.createInstance(TreeSelectionHandler);
|
this._treeSelectionHandler = this._instantiationService.createInstance(TreeSelectionHandler);
|
||||||
if (actionContext instanceof ObjectExplorerActionsContext) {
|
if (actionContext instanceof ObjectExplorerActionsContext) {
|
||||||
//set objectExplorerTreeNode for context menu clicks
|
//set objectExplorerTreeNode for context menu clicks
|
||||||
this._objectExplorerTreeNode = actionContext.treeNode;
|
this._objectExplorerTreeNode = await getTreeNode(actionContext, this._objectExplorerService);
|
||||||
this._container = actionContext.container;
|
|
||||||
}
|
}
|
||||||
this._treeSelectionHandler.onTreeActionStateChange(true);
|
this._treeSelectionHandler.onTreeActionStateChange(true);
|
||||||
var connectionProfile = TreeUpdateUtils.getConnectionProfile(<TreeNode>this._objectExplorerTreeNode);
|
var connectionProfile = TreeUpdateUtils.getConnectionProfile(<TreeNode>this._objectExplorerTreeNode);
|
||||||
@@ -219,7 +232,6 @@ export class OEEditDataAction extends EditDataAction {
|
|||||||
export class OEScriptCreateAction extends ScriptCreateAction {
|
export class OEScriptCreateAction extends ScriptCreateAction {
|
||||||
public static ID = 'objectExplorer.' + ScriptCreateAction.ID;
|
public static ID = 'objectExplorer.' + ScriptCreateAction.ID;
|
||||||
private _objectExplorerTreeNode: TreeNode;
|
private _objectExplorerTreeNode: TreeNode;
|
||||||
private _container: HTMLElement;
|
|
||||||
private _treeSelectionHandler: TreeSelectionHandler;
|
private _treeSelectionHandler: TreeSelectionHandler;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@@ -227,18 +239,18 @@ export class OEScriptCreateAction extends ScriptCreateAction {
|
|||||||
@IQueryEditorService protected _queryEditorService: IQueryEditorService,
|
@IQueryEditorService protected _queryEditorService: IQueryEditorService,
|
||||||
@IConnectionManagementService protected _connectionManagementService: IConnectionManagementService,
|
@IConnectionManagementService protected _connectionManagementService: IConnectionManagementService,
|
||||||
@IScriptingService protected _scriptingService: IScriptingService,
|
@IScriptingService protected _scriptingService: IScriptingService,
|
||||||
|
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
|
||||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||||
@IErrorMessageService protected _errorMessageService: IErrorMessageService
|
@IErrorMessageService protected _errorMessageService: IErrorMessageService
|
||||||
) {
|
) {
|
||||||
super(id, label, _queryEditorService, _connectionManagementService, _scriptingService, _errorMessageService);
|
super(id, label, _queryEditorService, _connectionManagementService, _scriptingService, _errorMessageService);
|
||||||
}
|
}
|
||||||
|
|
||||||
public run(actionContext: any): TPromise<boolean> {
|
public async run(actionContext: any): TPromise<boolean> {
|
||||||
this._treeSelectionHandler = this._instantiationService.createInstance(TreeSelectionHandler);
|
this._treeSelectionHandler = this._instantiationService.createInstance(TreeSelectionHandler);
|
||||||
if (actionContext instanceof ObjectExplorerActionsContext) {
|
if (actionContext instanceof ObjectExplorerActionsContext) {
|
||||||
//set objectExplorerTreeNode for context menu clicks
|
//set objectExplorerTreeNode for context menu clicks
|
||||||
this._objectExplorerTreeNode = actionContext.treeNode;
|
this._objectExplorerTreeNode = await getTreeNode(actionContext, this._objectExplorerService);
|
||||||
this._container = actionContext.container;
|
|
||||||
}
|
}
|
||||||
this._treeSelectionHandler.onTreeActionStateChange(true);
|
this._treeSelectionHandler.onTreeActionStateChange(true);
|
||||||
var connectionProfile = TreeUpdateUtils.getConnectionProfile(<TreeNode>this._objectExplorerTreeNode);
|
var connectionProfile = TreeUpdateUtils.getConnectionProfile(<TreeNode>this._objectExplorerTreeNode);
|
||||||
@@ -256,7 +268,6 @@ export class OEScriptCreateAction extends ScriptCreateAction {
|
|||||||
export class OEScriptExecuteAction extends ScriptExecuteAction {
|
export class OEScriptExecuteAction extends ScriptExecuteAction {
|
||||||
public static ID = 'objectExplorer.' + ScriptExecuteAction.ID;
|
public static ID = 'objectExplorer.' + ScriptExecuteAction.ID;
|
||||||
private _objectExplorerTreeNode: TreeNode;
|
private _objectExplorerTreeNode: TreeNode;
|
||||||
private _container: HTMLElement;
|
|
||||||
private _treeSelectionHandler: TreeSelectionHandler;
|
private _treeSelectionHandler: TreeSelectionHandler;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@@ -264,18 +275,18 @@ export class OEScriptExecuteAction extends ScriptExecuteAction {
|
|||||||
@IQueryEditorService protected _queryEditorService: IQueryEditorService,
|
@IQueryEditorService protected _queryEditorService: IQueryEditorService,
|
||||||
@IConnectionManagementService protected _connectionManagementService: IConnectionManagementService,
|
@IConnectionManagementService protected _connectionManagementService: IConnectionManagementService,
|
||||||
@IScriptingService protected _scriptingService: IScriptingService,
|
@IScriptingService protected _scriptingService: IScriptingService,
|
||||||
|
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
|
||||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||||
@IErrorMessageService protected _errorMessageService: IErrorMessageService
|
@IErrorMessageService protected _errorMessageService: IErrorMessageService
|
||||||
) {
|
) {
|
||||||
super(id, label, _queryEditorService, _connectionManagementService, _scriptingService, _errorMessageService);
|
super(id, label, _queryEditorService, _connectionManagementService, _scriptingService, _errorMessageService);
|
||||||
}
|
}
|
||||||
|
|
||||||
public run(actionContext: any): TPromise<boolean> {
|
public async run(actionContext: any): TPromise<boolean> {
|
||||||
this._treeSelectionHandler = this._instantiationService.createInstance(TreeSelectionHandler);
|
this._treeSelectionHandler = this._instantiationService.createInstance(TreeSelectionHandler);
|
||||||
if (actionContext instanceof ObjectExplorerActionsContext) {
|
if (actionContext instanceof ObjectExplorerActionsContext) {
|
||||||
//set objectExplorerTreeNode for context menu clicks
|
//set objectExplorerTreeNode for context menu clicks
|
||||||
this._objectExplorerTreeNode = actionContext.treeNode;
|
this._objectExplorerTreeNode = await getTreeNode(actionContext, this._objectExplorerService);
|
||||||
this._container = actionContext.container;
|
|
||||||
}
|
}
|
||||||
this._treeSelectionHandler.onTreeActionStateChange(true);
|
this._treeSelectionHandler.onTreeActionStateChange(true);
|
||||||
var connectionProfile = TreeUpdateUtils.getConnectionProfile(<TreeNode>this._objectExplorerTreeNode);
|
var connectionProfile = TreeUpdateUtils.getConnectionProfile(<TreeNode>this._objectExplorerTreeNode);
|
||||||
@@ -293,7 +304,6 @@ export class OEScriptExecuteAction extends ScriptExecuteAction {
|
|||||||
export class OEScriptAlterAction extends ScriptAlterAction {
|
export class OEScriptAlterAction extends ScriptAlterAction {
|
||||||
public static ID = 'objectExplorer.' + ScriptAlterAction.ID;
|
public static ID = 'objectExplorer.' + ScriptAlterAction.ID;
|
||||||
private _objectExplorerTreeNode: TreeNode;
|
private _objectExplorerTreeNode: TreeNode;
|
||||||
private _container: HTMLElement;
|
|
||||||
private _treeSelectionHandler: TreeSelectionHandler;
|
private _treeSelectionHandler: TreeSelectionHandler;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@@ -301,18 +311,18 @@ export class OEScriptAlterAction extends ScriptAlterAction {
|
|||||||
@IQueryEditorService protected _queryEditorService: IQueryEditorService,
|
@IQueryEditorService protected _queryEditorService: IQueryEditorService,
|
||||||
@IConnectionManagementService protected _connectionManagementService: IConnectionManagementService,
|
@IConnectionManagementService protected _connectionManagementService: IConnectionManagementService,
|
||||||
@IScriptingService protected _scriptingService: IScriptingService,
|
@IScriptingService protected _scriptingService: IScriptingService,
|
||||||
|
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
|
||||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||||
@IErrorMessageService protected _errorMessageService: IErrorMessageService
|
@IErrorMessageService protected _errorMessageService: IErrorMessageService
|
||||||
) {
|
) {
|
||||||
super(id, label, _queryEditorService, _connectionManagementService, _scriptingService, _errorMessageService);
|
super(id, label, _queryEditorService, _connectionManagementService, _scriptingService, _errorMessageService);
|
||||||
}
|
}
|
||||||
|
|
||||||
public run(actionContext: any): TPromise<boolean> {
|
public async run(actionContext: any): TPromise<boolean> {
|
||||||
this._treeSelectionHandler = this._instantiationService.createInstance(TreeSelectionHandler);
|
this._treeSelectionHandler = this._instantiationService.createInstance(TreeSelectionHandler);
|
||||||
if (actionContext instanceof ObjectExplorerActionsContext) {
|
if (actionContext instanceof ObjectExplorerActionsContext) {
|
||||||
//set objectExplorerTreeNode for context menu clicks
|
//set objectExplorerTreeNode for context menu clicks
|
||||||
this._objectExplorerTreeNode = actionContext.treeNode;
|
this._objectExplorerTreeNode = await getTreeNode(actionContext, this._objectExplorerService);
|
||||||
this._container = actionContext.container;
|
|
||||||
}
|
}
|
||||||
this._treeSelectionHandler.onTreeActionStateChange(true);
|
this._treeSelectionHandler.onTreeActionStateChange(true);
|
||||||
var connectionProfile = TreeUpdateUtils.getConnectionProfile(<TreeNode>this._objectExplorerTreeNode);
|
var connectionProfile = TreeUpdateUtils.getConnectionProfile(<TreeNode>this._objectExplorerTreeNode);
|
||||||
@@ -330,7 +340,6 @@ export class OEScriptAlterAction extends ScriptAlterAction {
|
|||||||
export class OEScriptDeleteAction extends ScriptDeleteAction {
|
export class OEScriptDeleteAction extends ScriptDeleteAction {
|
||||||
public static ID = 'objectExplorer.' + ScriptDeleteAction.ID;
|
public static ID = 'objectExplorer.' + ScriptDeleteAction.ID;
|
||||||
private _objectExplorerTreeNode: TreeNode;
|
private _objectExplorerTreeNode: TreeNode;
|
||||||
private _container: HTMLElement;
|
|
||||||
private _treeSelectionHandler: TreeSelectionHandler;
|
private _treeSelectionHandler: TreeSelectionHandler;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@@ -338,18 +347,18 @@ export class OEScriptDeleteAction extends ScriptDeleteAction {
|
|||||||
@IQueryEditorService protected _queryEditorService: IQueryEditorService,
|
@IQueryEditorService protected _queryEditorService: IQueryEditorService,
|
||||||
@IConnectionManagementService protected _connectionManagementService: IConnectionManagementService,
|
@IConnectionManagementService protected _connectionManagementService: IConnectionManagementService,
|
||||||
@IScriptingService protected _scriptingService: IScriptingService,
|
@IScriptingService protected _scriptingService: IScriptingService,
|
||||||
|
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
|
||||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||||
@IErrorMessageService protected _errorMessageService: IErrorMessageService
|
@IErrorMessageService protected _errorMessageService: IErrorMessageService
|
||||||
) {
|
) {
|
||||||
super(id, label, _queryEditorService, _connectionManagementService, _scriptingService, _errorMessageService);
|
super(id, label, _queryEditorService, _connectionManagementService, _scriptingService, _errorMessageService);
|
||||||
}
|
}
|
||||||
|
|
||||||
public run(actionContext: any): TPromise<boolean> {
|
public async run(actionContext: any): TPromise<boolean> {
|
||||||
this._treeSelectionHandler = this._instantiationService.createInstance(TreeSelectionHandler);
|
this._treeSelectionHandler = this._instantiationService.createInstance(TreeSelectionHandler);
|
||||||
if (actionContext instanceof ObjectExplorerActionsContext) {
|
if (actionContext instanceof ObjectExplorerActionsContext) {
|
||||||
//set objectExplorerTreeNode for context menu clicks
|
//set objectExplorerTreeNode for context menu clicks
|
||||||
this._objectExplorerTreeNode = actionContext.treeNode;
|
this._objectExplorerTreeNode = await getTreeNode(actionContext, this._objectExplorerService);
|
||||||
this._container = actionContext.container;
|
|
||||||
}
|
}
|
||||||
this._treeSelectionHandler.onTreeActionStateChange(true);
|
this._treeSelectionHandler.onTreeActionStateChange(true);
|
||||||
var connectionProfile = TreeUpdateUtils.getConnectionProfile(<TreeNode>this._objectExplorerTreeNode);
|
var connectionProfile = TreeUpdateUtils.getConnectionProfile(<TreeNode>this._objectExplorerTreeNode);
|
||||||
@@ -364,77 +373,11 @@ export class OEScriptDeleteAction extends ScriptDeleteAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DisconnectAction extends Action {
|
|
||||||
public static ID = 'objectExplorer.disconnect';
|
|
||||||
public static LABEL = localize('objectExplorAction.disconnect', 'Disconnect');
|
|
||||||
private _objectExplorerTreeNode: TreeNode;
|
|
||||||
private _container: HTMLElement;
|
|
||||||
private _treeSelectionHandler: TreeSelectionHandler;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
id: string,
|
|
||||||
label: string,
|
|
||||||
@IConnectionManagementService private connectionManagementService: IConnectionManagementService,
|
|
||||||
@IInstantiationService private _instantiationService: IInstantiationService
|
|
||||||
) {
|
|
||||||
super(id, label);
|
|
||||||
}
|
|
||||||
|
|
||||||
public run(actionContext: any): TPromise<boolean> {
|
|
||||||
this._treeSelectionHandler = this._instantiationService.createInstance(TreeSelectionHandler);
|
|
||||||
if (actionContext instanceof ObjectExplorerActionsContext) {
|
|
||||||
//set objectExplorerTreeNode for context menu clicks
|
|
||||||
this._objectExplorerTreeNode = actionContext.treeNode;
|
|
||||||
this._container = actionContext.container;
|
|
||||||
}
|
|
||||||
|
|
||||||
var connectionProfile = (<TreeNode>this._objectExplorerTreeNode).getConnectionProfile();
|
|
||||||
if (this.connectionManagementService.isProfileConnected(connectionProfile)) {
|
|
||||||
this._treeSelectionHandler.onTreeActionStateChange(true);
|
|
||||||
|
|
||||||
this.connectionManagementService.disconnect(connectionProfile).then(() => {
|
|
||||||
this._treeSelectionHandler.onTreeActionStateChange(false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return TPromise.as(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ObjectExplorerActionUtilities {
|
export class ObjectExplorerActionUtilities {
|
||||||
|
|
||||||
public static readonly objectExplorerElementClass = 'object-element-group';
|
public static readonly objectExplorerElementClass = 'object-element-group';
|
||||||
public static readonly connectionElementClass = 'connection-tile';
|
public static readonly connectionElementClass = 'connection-tile';
|
||||||
|
|
||||||
|
|
||||||
private static getGroupContainer(container: HTMLElement, elementName: string): HTMLElement {
|
|
||||||
var element = container;
|
|
||||||
while (element && element.className !== elementName) {
|
|
||||||
element = element.parentElement;
|
|
||||||
}
|
|
||||||
return element ? element.parentElement : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static showLoadingIcon(container: HTMLElement, elementName: string): void {
|
|
||||||
if (container) {
|
|
||||||
let groupContainer = this.getGroupContainer(container, elementName);
|
|
||||||
if (groupContainer) {
|
|
||||||
groupContainer.classList.add('icon');
|
|
||||||
groupContainer.classList.add('in-progress');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static hideLoadingIcon(container: HTMLElement, elementName: string): void {
|
|
||||||
if (container) {
|
|
||||||
let element = this.getGroupContainer(container, elementName);
|
|
||||||
if (element && element.classList) {
|
|
||||||
element.classList.remove('icon');
|
|
||||||
element.classList.remove('in-progress');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static getScriptMap(treeNode: TreeNode): Map<NodeType, any[]> {
|
public static getScriptMap(treeNode: TreeNode): Map<NodeType, any[]> {
|
||||||
let scriptMap = new Map<NodeType, any[]>();
|
let scriptMap = new Map<NodeType, any[]>();
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import { ITree } from 'vs/base/parts/tree/browser/tree';
|
|||||||
import { ContributableActionProvider } from 'vs/workbench/browser/actions';
|
import { ContributableActionProvider } from 'vs/workbench/browser/actions';
|
||||||
import { IAction } from 'vs/base/common/actions';
|
import { IAction } from 'vs/base/common/actions';
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||||
|
import { fillInActions } from 'vs/platform/actions/browser/menuItemActionItem';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DisconnectConnectionAction, AddServerAction,
|
DisconnectConnectionAction, AddServerAction,
|
||||||
@@ -16,9 +18,7 @@ import {
|
|||||||
}
|
}
|
||||||
from 'sql/parts/objectExplorer/viewlet/connectionTreeAction';
|
from 'sql/parts/objectExplorer/viewlet/connectionTreeAction';
|
||||||
import {
|
import {
|
||||||
DisconnectAction, ObjectExplorerActionUtilities,
|
ObjectExplorerActionUtilities, ManageConnectionAction, OEAction
|
||||||
ManageConnectionAction,
|
|
||||||
OEAction
|
|
||||||
} from 'sql/parts/objectExplorer/viewlet/objectExplorerActions';
|
} from 'sql/parts/objectExplorer/viewlet/objectExplorerActions';
|
||||||
import { TreeNode } from 'sql/parts/objectExplorer/common/treeNode';
|
import { TreeNode } from 'sql/parts/objectExplorer/common/treeNode';
|
||||||
import { NodeType } from 'sql/parts/objectExplorer/common/nodeType';
|
import { NodeType } from 'sql/parts/objectExplorer/common/nodeType';
|
||||||
@@ -27,8 +27,14 @@ import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile
|
|||||||
import { NewProfilerAction } from 'sql/parts/profiler/contrib/profilerActions';
|
import { NewProfilerAction } from 'sql/parts/profiler/contrib/profilerActions';
|
||||||
import { TreeUpdateUtils } from 'sql/parts/objectExplorer/viewlet/treeUpdateUtils';
|
import { TreeUpdateUtils } from 'sql/parts/objectExplorer/viewlet/treeUpdateUtils';
|
||||||
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
|
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
|
||||||
import { ExecuteCommandAction } from 'vs/platform/actions/common/actions';
|
import { MenuId, IMenuService } from 'vs/platform/actions/common/actions';
|
||||||
import { NewQueryAction } from 'sql/workbench/common/actions';
|
import { NewQueryAction } from 'sql/workbench/common/actions';
|
||||||
|
import { ConnectionContextKey } from 'sql/parts/connection/common/connectionContextKey';
|
||||||
|
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||||
|
import { TreeNodeContextKey } from './treeNodeContextKey';
|
||||||
|
import { IQueryManagementService } from 'sql/parts/query/common/queryManagement';
|
||||||
|
import { IScriptingService } from 'sql/services/scripting/scriptingService';
|
||||||
|
import * as constants from 'sql/common/constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides actions for the server tree elements
|
* Provides actions for the server tree elements
|
||||||
@@ -37,7 +43,12 @@ export class ServerTreeActionProvider extends ContributableActionProvider {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||||
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService
|
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
|
||||||
|
@IQueryManagementService private _queryManagementService: IQueryManagementService,
|
||||||
|
@IScriptingService private _scriptingService: IScriptingService,
|
||||||
|
@IContextMenuService private contextMenuService: IContextMenuService,
|
||||||
|
@IMenuService private menuService: IMenuService,
|
||||||
|
@IContextKeyService private _contextKeyService: IContextKeyService
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
@@ -57,8 +68,11 @@ export class ServerTreeActionProvider extends ContributableActionProvider {
|
|||||||
return TPromise.as(this.getConnectionProfileGroupActions(tree, element));
|
return TPromise.as(this.getConnectionProfileGroupActions(tree, element));
|
||||||
}
|
}
|
||||||
if (element instanceof TreeNode) {
|
if (element instanceof TreeNode) {
|
||||||
var treeNode = <TreeNode>element;
|
return TPromise.as(this.getObjectExplorerNodeActions({
|
||||||
return TPromise.as(this.getObjectExplorerNodeActions(tree, treeNode));
|
tree: tree,
|
||||||
|
profile: element.getConnectionProfile(),
|
||||||
|
treeNode: element
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
return TPromise.as([]);
|
return TPromise.as([]);
|
||||||
@@ -75,23 +89,58 @@ export class ServerTreeActionProvider extends ContributableActionProvider {
|
|||||||
/**
|
/**
|
||||||
* Return actions for connection elements
|
* Return actions for connection elements
|
||||||
*/
|
*/
|
||||||
public getConnectionActions(tree: ITree, element: ConnectionProfile): IAction[] {
|
public getConnectionActions(tree: ITree, profile: ConnectionProfile): IAction[] {
|
||||||
let actions: IAction[] = [];
|
return this.getAllActions({
|
||||||
actions.push(this._instantiationService.createInstance(ManageConnectionAction, ManageConnectionAction.ID, ManageConnectionAction.LABEL));
|
tree: tree,
|
||||||
actions.push(this._instantiationService.createInstance(OEAction, NewQueryAction.ID, NewQueryAction.LABEL));
|
profile: profile
|
||||||
if (this._connectionManagementService.isProfileConnected(element)) {
|
}, (context) => this.getBuiltinConnectionActions(context));
|
||||||
actions.push(this._instantiationService.createInstance(DisconnectConnectionAction, DisconnectConnectionAction.ID, DisconnectConnectionAction.LABEL));
|
}
|
||||||
}
|
|
||||||
actions.push(this._instantiationService.createInstance(DeleteConnectionAction, DeleteConnectionAction.ID, DeleteConnectionAction.DELETE_CONNECTION_LABEL, element));
|
|
||||||
actions.push(this._instantiationService.createInstance(RefreshAction, RefreshAction.ID, RefreshAction.LABEL, tree, element));
|
|
||||||
|
|
||||||
if (process.env['VSCODE_DEV']) {
|
private getAllActions(context: ObjectExplorerContext, getDefaultActions: (ObjectExplorerContext) => IAction[]) {
|
||||||
|
// Create metadata needed to get a useful set of actions
|
||||||
|
let scopedContextService = this.getContextKeyService(context);
|
||||||
|
let menu = this.menuService.createMenu(MenuId.ObjectExplorerItemContext, scopedContextService);
|
||||||
|
|
||||||
|
// Fill in all actions
|
||||||
|
let actions = getDefaultActions(context);
|
||||||
|
fillInActions(menu, { arg: undefined, shouldForwardArgs: true }, actions, this.contextMenuService);
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
scopedContextService.dispose();
|
||||||
|
menu.dispose();
|
||||||
|
return actions;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private getBuiltinConnectionActions(context: ObjectExplorerContext): IAction[] {
|
||||||
|
let actions: IAction[] = [];
|
||||||
|
actions.push(this._instantiationService.createInstance(ManageConnectionAction, ManageConnectionAction.ID, ManageConnectionAction.LABEL, context.tree));
|
||||||
|
this.addNewQueryAction(context, actions);
|
||||||
|
|
||||||
|
if (this._connectionManagementService.isProfileConnected(context.profile)) {
|
||||||
|
actions.push(this._instantiationService.createInstance(DisconnectConnectionAction, DisconnectConnectionAction.ID, DisconnectConnectionAction.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));
|
||||||
|
|
||||||
|
if (process.env['VSCODE_DEV'] && constants.MssqlProviderId === context.profile.providerName) {
|
||||||
actions.push(this._instantiationService.createInstance(OEAction, NewProfilerAction.ID, NewProfilerAction.LABEL));
|
actions.push(this._instantiationService.createInstance(OEAction, NewProfilerAction.ID, NewProfilerAction.LABEL));
|
||||||
}
|
}
|
||||||
|
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getContextKeyService(context: ObjectExplorerContext): IContextKeyService {
|
||||||
|
let scopedContextService = this._contextKeyService.createScoped();
|
||||||
|
let connectionContextKey = new ConnectionContextKey(scopedContextService);
|
||||||
|
connectionContextKey.set(context.profile);
|
||||||
|
let treeNodeContextKey = new TreeNodeContextKey(scopedContextService);
|
||||||
|
if (context.treeNode) {
|
||||||
|
treeNodeContextKey.set(context.treeNode);
|
||||||
|
}
|
||||||
|
return scopedContextService;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return actions for connection group elements
|
* Return actions for connection group elements
|
||||||
*/
|
*/
|
||||||
@@ -106,32 +155,50 @@ export class ServerTreeActionProvider extends ContributableActionProvider {
|
|||||||
/**
|
/**
|
||||||
* Return actions for OE elements
|
* Return actions for OE elements
|
||||||
*/
|
*/
|
||||||
public getObjectExplorerNodeActions(tree: ITree, treeNode: TreeNode): IAction[] {
|
private getObjectExplorerNodeActions(context: ObjectExplorerContext): IAction[] {
|
||||||
let actions = [];
|
return this.getAllActions(context, (context) => this.getBuiltInNodeActions(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
private getBuiltInNodeActions(context: ObjectExplorerContext): IAction[] {
|
||||||
|
let actions: IAction[] = [];
|
||||||
|
let treeNode = context.treeNode;
|
||||||
if (TreeUpdateUtils.isDatabaseNode(treeNode)) {
|
if (TreeUpdateUtils.isDatabaseNode(treeNode)) {
|
||||||
if (TreeUpdateUtils.isAvailableDatabaseNode(treeNode)) {
|
if (TreeUpdateUtils.isAvailableDatabaseNode(treeNode)) {
|
||||||
actions.push(this._instantiationService.createInstance(ManageConnectionAction, ManageConnectionAction.ID, ManageConnectionAction.LABEL));
|
actions.push(this._instantiationService.createInstance(ManageConnectionAction, ManageConnectionAction.ID, ManageConnectionAction.LABEL, context.tree));
|
||||||
} else {
|
} else {
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions.push(this._instantiationService.createInstance(OEAction, NewQueryAction.ID, NewQueryAction.LABEL));
|
|
||||||
let scriptMap: Map<NodeType, any[]> = ObjectExplorerActionUtilities.getScriptMap(treeNode);
|
|
||||||
let supportedActions = scriptMap.get(treeNode.nodeTypeId);
|
|
||||||
let self = this;
|
|
||||||
|
|
||||||
if (supportedActions !== null && supportedActions !== undefined) {
|
this.addNewQueryAction(context, actions);
|
||||||
supportedActions.forEach(action => {
|
this.addScriptingActions(context, actions);
|
||||||
actions.push(self._instantiationService.createInstance(action, action.ID, action.LABEL));
|
actions.push(this._instantiationService.createInstance(RefreshAction, RefreshAction.ID, RefreshAction.LABEL, context.tree, treeNode));
|
||||||
});
|
|
||||||
}
|
|
||||||
actions.push(this._instantiationService.createInstance(RefreshAction, RefreshAction.ID, RefreshAction.LABEL, tree, treeNode));
|
|
||||||
|
|
||||||
|
|
||||||
if (treeNode.isTopLevel()) {
|
|
||||||
actions.push(this._instantiationService.createInstance(DisconnectAction, DisconnectAction.ID, DisconnectAction.LABEL));
|
|
||||||
}
|
|
||||||
|
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private addNewQueryAction(context: ObjectExplorerContext, actions: IAction[]): void {
|
||||||
|
if (this._queryManagementService.isProviderRegistered(context.profile.providerName)) {
|
||||||
|
actions.push(this._instantiationService.createInstance(OEAction, NewQueryAction.ID, NewQueryAction.LABEL));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private addScriptingActions(context: ObjectExplorerContext, actions: IAction[]): void {
|
||||||
|
if (this._scriptingService.isProviderRegistered(context.profile.providerName)) {
|
||||||
|
let scriptMap: Map<NodeType, any[]> = ObjectExplorerActionUtilities.getScriptMap(context.treeNode);
|
||||||
|
let supportedActions = scriptMap.get(context.treeNode.nodeTypeId);
|
||||||
|
let self = this;
|
||||||
|
if (supportedActions !== null && supportedActions !== undefined) {
|
||||||
|
supportedActions.forEach(action => {
|
||||||
|
actions.push(self._instantiationService.createInstance(action, action.ID, action.LABEL));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ObjectExplorerContext {
|
||||||
|
tree: ITree;
|
||||||
|
profile: ConnectionProfile;
|
||||||
|
treeNode?: TreeNode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import { ServerTreeActionProvider } from 'sql/parts/objectExplorer/viewlet/serve
|
|||||||
import { ObjectExplorerActionsContext } from 'sql/parts/objectExplorer/viewlet/objectExplorerActions';
|
import { ObjectExplorerActionsContext } from 'sql/parts/objectExplorer/viewlet/objectExplorerActions';
|
||||||
import { TreeNode } from 'sql/parts/objectExplorer/common/treeNode';
|
import { TreeNode } from 'sql/parts/objectExplorer/common/treeNode';
|
||||||
import { OpenMode } from 'vs/base/parts/tree/browser/treeDefaults';
|
import { OpenMode } from 'vs/base/parts/tree/browser/treeDefaults';
|
||||||
|
import { TreeUpdateUtils } from 'sql/parts/objectExplorer/viewlet/treeUpdateUtils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extends the tree controller to handle clicks on the tree elements
|
* Extends the tree controller to handle clicks on the tree elements
|
||||||
@@ -73,26 +74,24 @@ export class ServerTreeController extends treedefaults.DefaultController {
|
|||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
tree.setFocus(element);
|
tree.setFocus(element);
|
||||||
let parent: ConnectionProfileGroup = undefined;
|
|
||||||
if (element instanceof ConnectionProfileGroup) {
|
|
||||||
parent = <ConnectionProfileGroup>element;
|
|
||||||
}
|
|
||||||
else if (element instanceof ConnectionProfile) {
|
|
||||||
parent = (<ConnectionProfile>element).parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
var actionContext: any;
|
var actionContext: any;
|
||||||
if (element instanceof TreeNode) {
|
if (element instanceof TreeNode) {
|
||||||
actionContext = new ObjectExplorerActionsContext();
|
let context = new ObjectExplorerActionsContext();
|
||||||
actionContext.container = event.target;
|
context.nodeInfo = element.toNodeInfo();
|
||||||
actionContext.treeNode = <TreeNode>element;
|
// Note: getting DB name before, but intentionally not using treeUpdateUtils.getConnectionProfile as it replaces
|
||||||
actionContext.tree = tree;
|
// the connection ID with a new one. This breaks a number of internal tasks
|
||||||
|
context.connectionProfile = element.getConnectionProfile().toIConnectionProfile();
|
||||||
|
context.connectionProfile.databaseName = element.getDatabaseName();
|
||||||
|
actionContext = context;
|
||||||
} else if (element instanceof ConnectionProfile) {
|
} else if (element instanceof ConnectionProfile) {
|
||||||
actionContext = new ObjectExplorerActionsContext();
|
let context = new ObjectExplorerActionsContext();
|
||||||
actionContext.container = event.target;
|
context.connectionProfile = element.toIConnectionProfile();
|
||||||
actionContext.connectionProfile = <ConnectionProfile>element;
|
context.isConnectionNode = true;
|
||||||
actionContext.tree = tree;
|
actionContext = context;
|
||||||
} else {
|
} else {
|
||||||
|
// TODO: because the connection group is used as a context object and isn't serializable,
|
||||||
|
// the Group-level context menu is not currently extensible
|
||||||
actionContext = element;
|
actionContext = element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,12 +31,10 @@ export class ServerTreeDataSource implements IDataSource {
|
|||||||
* No more than one element may use a given identifier.
|
* No more than one element may use a given identifier.
|
||||||
*/
|
*/
|
||||||
public getId(tree: ITree, element: any): string {
|
public getId(tree: ITree, element: any): string {
|
||||||
if (element instanceof ConnectionProfile) {
|
if (element instanceof ConnectionProfile
|
||||||
return (<ConnectionProfile>element).id;
|
|| element instanceof ConnectionProfileGroup
|
||||||
} else if (element instanceof ConnectionProfileGroup) {
|
|| element instanceof TreeNode) {
|
||||||
return (<ConnectionProfileGroup>element).id;
|
return element.id;
|
||||||
} else if (element instanceof TreeNode) {
|
|
||||||
return (<TreeNode>element).id;
|
|
||||||
} else {
|
} else {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@@ -49,9 +47,9 @@ export class ServerTreeDataSource implements IDataSource {
|
|||||||
if (element instanceof ConnectionProfile) {
|
if (element instanceof ConnectionProfile) {
|
||||||
return true;
|
return true;
|
||||||
} else if (element instanceof ConnectionProfileGroup) {
|
} else if (element instanceof ConnectionProfileGroup) {
|
||||||
return (<ConnectionProfileGroup>element).hasChildren();
|
return element.hasChildren();
|
||||||
} else if (element instanceof TreeNode) {
|
} else if (element instanceof TreeNode) {
|
||||||
return !(<TreeNode>element).isAlwaysLeaf;
|
return !element.isAlwaysLeaf;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -70,7 +68,7 @@ export class ServerTreeDataSource implements IDataSource {
|
|||||||
} else if (element instanceof ConnectionProfileGroup) {
|
} else if (element instanceof ConnectionProfileGroup) {
|
||||||
resolve((<ConnectionProfileGroup>element).getChildren());
|
resolve((<ConnectionProfileGroup>element).getChildren());
|
||||||
} else if (element instanceof TreeNode) {
|
} else if (element instanceof TreeNode) {
|
||||||
var node = <TreeNode>element;
|
var node = element;
|
||||||
if (node.children) {
|
if (node.children) {
|
||||||
resolve(node.children);
|
resolve(node.children);
|
||||||
} else {
|
} else {
|
||||||
@@ -92,11 +90,11 @@ export class ServerTreeDataSource implements IDataSource {
|
|||||||
*/
|
*/
|
||||||
public getParent(tree: ITree, element: any): TPromise<any> {
|
public getParent(tree: ITree, element: any): TPromise<any> {
|
||||||
if (element instanceof ConnectionProfile) {
|
if (element instanceof ConnectionProfile) {
|
||||||
return TPromise.as((<ConnectionProfile>element).getParent());
|
return TPromise.as(element.getParent());
|
||||||
} else if (element instanceof ConnectionProfileGroup) {
|
} else if (element instanceof ConnectionProfileGroup) {
|
||||||
return TPromise.as((<ConnectionProfileGroup>element).getParent());
|
return TPromise.as(element.getParent());
|
||||||
} else if (element instanceof TreeNode) {
|
} else if (element instanceof TreeNode) {
|
||||||
return TPromise.as(TreeUpdateUtils.getObjectExplorerParent(<TreeNode>element, this._connectionManagementService));
|
return TPromise.as(TreeUpdateUtils.getObjectExplorerParent(element, this._connectionManagementService));
|
||||||
} else {
|
} else {
|
||||||
return TPromise.as(null);
|
return TPromise.as(null);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,38 +105,45 @@ export class ServerTreeRenderer implements IRenderer {
|
|||||||
*/
|
*/
|
||||||
public renderElement(tree: ITree, element: any, templateId: string, templateData: any): void {
|
public renderElement(tree: ITree, element: any, templateId: string, templateData: any): void {
|
||||||
if (templateId === ServerTreeRenderer.CONNECTION_TEMPLATE_ID) {
|
if (templateId === ServerTreeRenderer.CONNECTION_TEMPLATE_ID) {
|
||||||
this.renderConnection(tree, element, templateData);
|
this.renderConnection(element, templateData);
|
||||||
} else if (templateId === ServerTreeRenderer.CONNECTION_GROUP_TEMPLATE_ID) {
|
} else if (templateId === ServerTreeRenderer.CONNECTION_GROUP_TEMPLATE_ID) {
|
||||||
this.renderConnectionProfileGroup(tree, element, templateData);
|
this.renderConnectionProfileGroup(element, templateData);
|
||||||
} else {
|
} else {
|
||||||
this.renderObjectExplorer(tree, element, templateData);
|
this.renderObjectExplorer(element, templateData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderObjectExplorer(tree: ITree, treeNode: TreeNode, templateData: IObjectExplorerTemplateData): void {
|
private renderObjectExplorer(treeNode: TreeNode, templateData: IObjectExplorerTemplateData): void {
|
||||||
var iconName = treeNode.nodeTypeId;
|
// Use an explicitly defined iconType first. If not defined, fall back to using nodeType and
|
||||||
if (treeNode.nodeStatus) {
|
// other compount indicators instead.
|
||||||
iconName = treeNode.nodeTypeId + '_' + treeNode.nodeStatus;
|
let iconName: string = undefined;
|
||||||
}
|
if (treeNode.iconType) {
|
||||||
if (treeNode.nodeSubType) {
|
iconName = (typeof treeNode.iconType === 'string') ? treeNode.iconType : treeNode.iconType.id;
|
||||||
iconName = treeNode.nodeTypeId + '_' + treeNode.nodeSubType;
|
} else {
|
||||||
|
iconName = treeNode.nodeTypeId;
|
||||||
|
if (treeNode.nodeStatus) {
|
||||||
|
iconName = treeNode.nodeTypeId + '_' + treeNode.nodeStatus;
|
||||||
|
}
|
||||||
|
if (treeNode.nodeSubType) {
|
||||||
|
iconName = treeNode.nodeTypeId + '_' + treeNode.nodeSubType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let tokens: string[] = [];
|
let tokens: string[] = [];
|
||||||
for (var index = 1; index < templateData.icon.classList.length; index++) {
|
for (let index = 1; index < templateData.icon.classList.length; index++) {
|
||||||
tokens.push(templateData.icon.classList.item(index));
|
tokens.push(templateData.icon.classList.item(index));
|
||||||
}
|
}
|
||||||
templateData.icon.classList.remove(...tokens);
|
templateData.icon.classList.remove(...tokens);
|
||||||
templateData.icon.classList.add('icon');
|
templateData.icon.classList.add('icon');
|
||||||
let iconLoweCaseName = iconName.toLocaleLowerCase();
|
let iconLowerCaseName = iconName.toLocaleLowerCase();
|
||||||
templateData.icon.classList.add(iconLoweCaseName);
|
templateData.icon.classList.add(iconLowerCaseName);
|
||||||
|
|
||||||
templateData.label.textContent = treeNode.label;
|
templateData.label.textContent = treeNode.label;
|
||||||
templateData.root.title = treeNode.label;
|
templateData.root.title = treeNode.label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private renderConnection(tree: ITree, connection: ConnectionProfile, templateData: IConnectionTemplateData): void {
|
private renderConnection(connection: ConnectionProfile, templateData: IConnectionTemplateData): void {
|
||||||
if (!this._isCompact) {
|
if (!this._isCompact) {
|
||||||
if (this._connectionManagementService.isConnected(undefined, connection)) {
|
if (this._connectionManagementService.isConnected(undefined, connection)) {
|
||||||
templateData.icon.classList.remove('disconnected');
|
templateData.icon.classList.remove('disconnected');
|
||||||
@@ -157,9 +164,9 @@ export class ServerTreeRenderer implements IRenderer {
|
|||||||
templateData.connectionProfile = connection;
|
templateData.connectionProfile = connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderConnectionProfileGroup(tree: ITree, connectionProfileGroup: ConnectionProfileGroup, templateData: IConnectionProfileGroupTemplateData): void {
|
private renderConnectionProfileGroup(connectionProfileGroup: ConnectionProfileGroup, templateData: IConnectionProfileGroupTemplateData): void {
|
||||||
|
|
||||||
var rowElement = this.findParentElement(templateData.root, 'monaco-tree-row');
|
let rowElement = this.findParentElement(templateData.root, 'monaco-tree-row');
|
||||||
if (rowElement) {
|
if (rowElement) {
|
||||||
if (connectionProfileGroup.color) {
|
if (connectionProfileGroup.color) {
|
||||||
rowElement.style.background = connectionProfileGroup.color;
|
rowElement.style.background = connectionProfileGroup.color;
|
||||||
@@ -179,7 +186,7 @@ export class ServerTreeRenderer implements IRenderer {
|
|||||||
* Returns the first parent which contains the className
|
* Returns the first parent which contains the className
|
||||||
*/
|
*/
|
||||||
private findParentElement(container: HTMLElement, className: string): HTMLElement {
|
private findParentElement(container: HTMLElement, className: string): HTMLElement {
|
||||||
var currentElement = container;
|
let currentElement = container;
|
||||||
while (currentElement) {
|
while (currentElement) {
|
||||||
if (currentElement.className.includes(className)) {
|
if (currentElement.className.includes(className)) {
|
||||||
break;
|
break;
|
||||||
|
|||||||
50
src/sql/parts/objectExplorer/viewlet/treeNodeContextKey.ts
Normal file
50
src/sql/parts/objectExplorer/viewlet/treeNodeContextKey.ts
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* 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 { RawContextKey, IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||||
|
import { IConnectionProfile } from 'sqlops';
|
||||||
|
import { TreeNode } from 'sql/parts/objectExplorer/common/treeNode';
|
||||||
|
|
||||||
|
export class TreeNodeContextKey implements IContextKey<TreeNode> {
|
||||||
|
|
||||||
|
static NodeType = new RawContextKey<string>('nodeType', undefined);
|
||||||
|
static SubType = new RawContextKey<string>('nodeSubType', undefined);
|
||||||
|
static Status = new RawContextKey<string>('nodeStatus', undefined);
|
||||||
|
static TreeNode = new RawContextKey<TreeNode>('treeNode', undefined);
|
||||||
|
|
||||||
|
private _nodeTypeKey: IContextKey<string>;
|
||||||
|
private _subTypeKey: IContextKey<string>;
|
||||||
|
private _statusKey: IContextKey<string>;
|
||||||
|
private _treeNodeKey: IContextKey<TreeNode>;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@IContextKeyService contextKeyService: IContextKeyService
|
||||||
|
) {
|
||||||
|
this._nodeTypeKey = TreeNodeContextKey.NodeType.bindTo(contextKeyService);
|
||||||
|
this._subTypeKey = TreeNodeContextKey.SubType.bindTo(contextKeyService);
|
||||||
|
this._statusKey = TreeNodeContextKey.Status.bindTo(contextKeyService);
|
||||||
|
this._treeNodeKey = TreeNodeContextKey.TreeNode.bindTo(contextKeyService);
|
||||||
|
}
|
||||||
|
|
||||||
|
set(value: TreeNode) {
|
||||||
|
this._treeNodeKey.set(value);
|
||||||
|
this._nodeTypeKey.set(value && value.nodeTypeId);
|
||||||
|
this._subTypeKey.set(value && value.nodeSubType);
|
||||||
|
this._statusKey.set(value && value.nodeStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
reset(): void {
|
||||||
|
this._nodeTypeKey.reset();
|
||||||
|
this._subTypeKey.reset();
|
||||||
|
this._statusKey.reset();
|
||||||
|
this._treeNodeKey.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public get(): TreeNode {
|
||||||
|
return this._treeNodeKey.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -104,7 +104,7 @@ export class TreeSelectionHandler {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if (isDoubleClick && selection && selection.length > 0 && (selection[0] instanceof TreeNode)) {
|
} else if (isDoubleClick && selection && selection.length > 0 && (selection[0] instanceof TreeNode)) {
|
||||||
let treeNode = <TreeNode>selection[0];
|
let treeNode = selection[0];
|
||||||
if (TreeUpdateUtils.isAvailableDatabaseNode(treeNode)) {
|
if (TreeUpdateUtils.isAvailableDatabaseNode(treeNode)) {
|
||||||
connectionProfile = TreeUpdateUtils.getConnectionProfile(treeNode);
|
connectionProfile = TreeUpdateUtils.getConnectionProfile(treeNode);
|
||||||
if (connectionProfile) {
|
if (connectionProfile) {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { NodeType } from 'sql/parts/objectExplorer/common/nodeType';
|
|||||||
import { TPromise } from 'vs/base/common/winjs.base';
|
import { TPromise } from 'vs/base/common/winjs.base';
|
||||||
import { TreeNode } from 'sql/parts/objectExplorer/common/treeNode';
|
import { TreeNode } from 'sql/parts/objectExplorer/common/treeNode';
|
||||||
import errors = require('vs/base/common/errors');
|
import errors = require('vs/base/common/errors');
|
||||||
|
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
||||||
|
|
||||||
export class TreeUpdateUtils {
|
export class TreeUpdateUtils {
|
||||||
|
|
||||||
@@ -113,7 +114,7 @@ export class TreeUpdateUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static connectIfNotConnected(
|
public static connectIfNotConnected(
|
||||||
connection: ConnectionProfile,
|
connection: IConnectionProfile,
|
||||||
options: IConnectionCompletionOptions,
|
options: IConnectionCompletionOptions,
|
||||||
connectionManagementService: IConnectionManagementService,
|
connectionManagementService: IConnectionManagementService,
|
||||||
tree: ITree): TPromise<ConnectionProfile> {
|
tree: ITree): TPromise<ConnectionProfile> {
|
||||||
@@ -172,7 +173,7 @@ export class TreeUpdateUtils {
|
|||||||
* @param connectionManagementService Connection management service instance
|
* @param connectionManagementService Connection management service instance
|
||||||
* @param objectExplorerService Object explorer service instance
|
* @param objectExplorerService Object explorer service instance
|
||||||
*/
|
*/
|
||||||
public static connectAndCreateOeSession(connection: ConnectionProfile, options: IConnectionCompletionOptions,
|
public static connectAndCreateOeSession(connection: IConnectionProfile, options: IConnectionCompletionOptions,
|
||||||
connectionManagementService: IConnectionManagementService, objectExplorerService: IObjectExplorerService, tree: ITree): TPromise<boolean> {
|
connectionManagementService: IConnectionManagementService, objectExplorerService: IObjectExplorerService, tree: ITree): TPromise<boolean> {
|
||||||
return new TPromise<boolean>((resolve, reject) => {
|
return new TPromise<boolean>((resolve, reject) => {
|
||||||
TreeUpdateUtils.connectIfNotConnected(connection, options, connectionManagementService, tree).then(connectedConnection => {
|
TreeUpdateUtils.connectIfNotConnected(connection, options, connectionManagementService, tree).then(connectedConnection => {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import * as nls from 'vs/nls';
|
|||||||
|
|
||||||
import { ProfilerInput } from 'sql/parts/profiler/editor/profilerInput';
|
import { ProfilerInput } from 'sql/parts/profiler/editor/profilerInput';
|
||||||
import { ProfilerEditor } from 'sql/parts/profiler/editor/profilerEditor';
|
import { ProfilerEditor } from 'sql/parts/profiler/editor/profilerEditor';
|
||||||
import { PROFILER_SESSION_TEMPLATE_SETTINGS, IProfilerSessionTemplate } from 'sql/parts/profiler/service/interfaces';
|
import { PROFILER_VIEW_TEMPLATE_SETTINGS, IProfilerViewTemplate } from 'sql/parts/profiler/service/interfaces';
|
||||||
|
|
||||||
const profilerDescriptor = new EditorDescriptor(
|
const profilerDescriptor = new EditorDescriptor(
|
||||||
ProfilerEditor,
|
ProfilerEditor,
|
||||||
@@ -24,84 +24,213 @@ const profilerDescriptor = new EditorDescriptor(
|
|||||||
Registry.as<IEditorRegistry>(EditorExtensions.Editors)
|
Registry.as<IEditorRegistry>(EditorExtensions.Editors)
|
||||||
.registerEditor(profilerDescriptor, [new SyncDescriptor(ProfilerInput)]);
|
.registerEditor(profilerDescriptor, [new SyncDescriptor(ProfilerInput)]);
|
||||||
|
|
||||||
const profilerSessionTemplateSchema: IJSONSchema = {
|
const profilerViewTemplateSchema: IJSONSchema = {
|
||||||
description: nls.localize('profiler.settings.sessionTemplates', "Specifies session templates"),
|
description: nls.localize('profiler.settings.viewTemplates', "Specifies view templates"),
|
||||||
type: 'array',
|
type: 'array',
|
||||||
items: <IJSONSchema>{
|
items: <IJSONSchema>{
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
name: {
|
name: {
|
||||||
type: 'string'
|
type: 'string'
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
default: <Array<IProfilerSessionTemplate>>[
|
|
||||||
{
|
|
||||||
name: 'Standard',
|
|
||||||
events: [
|
|
||||||
{
|
|
||||||
name: 'Audit Login',
|
|
||||||
optionalColumns: ['TextData', 'ApplicationName', 'NTUserName', 'LoginName', 'ClientProcessID', 'SPID', 'StartTime', 'BinaryData']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Audit Logout',
|
|
||||||
optionalColumns: ['ApplicationName', 'NTUserName', 'LoginName', 'CPU', 'Reads', 'Writes', 'Duration', 'ClientProcessID', 'SPID', 'StartTime', 'EndTime']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'ExistingConnection',
|
|
||||||
optionalColumns: ['TextData', 'ApplicationName', 'NTUserName', 'LoginName', 'Duration', 'ClientProcessID', 'SPID', 'StartTime', 'EndTime', 'BinaryData']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'RPC:Completed',
|
|
||||||
optionalColumns: ['TextData', 'ApplicationName', 'NTUserName', 'LoginName', 'CPU', 'Reads', 'Writes', 'Duration', 'ClientProcessID', 'SPID', 'StartTime', 'EndTime', 'BinaryData']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'SQL:BatchCompleted',
|
|
||||||
optionalColumns: ['TextData', 'ApplicationName', 'NTUserName', 'LoginName', 'CPU', 'Reads', 'Writes', 'Duration', 'ClientProcessID', 'SPID', 'StartTime', 'EndTime', 'BinaryData']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'SQL:BatchStarting',
|
|
||||||
optionalColumns: ['TextData', 'ApplicationName', 'NTUserName', 'LoginName', 'ClientProcessID', 'SPID', 'StartTime']
|
|
||||||
}
|
}
|
||||||
],
|
}
|
||||||
view: {
|
},
|
||||||
events: [
|
default: <Array<IProfilerViewTemplate>>[
|
||||||
|
{
|
||||||
|
name: 'Standard View',
|
||||||
|
columns: [
|
||||||
{
|
{
|
||||||
name: 'Audit Login',
|
name: 'EventClass',
|
||||||
columns: ['TextData', 'ApplicationName', 'NTUserName', 'LoginName', 'ClientProcessID', 'SPID', 'StartTime']
|
eventsMapped: ['name']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Audit Logout',
|
name: 'TextData',
|
||||||
columns: ['ApplicationName', 'NTUserName', 'LoginName', 'CPU', 'Reads', 'Writes', 'Duration', 'ClientProcessID', 'SPID', 'StartTime', 'EndTime']
|
eventsMapped: ['options_text', 'batch_text']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'ExistingConnection',
|
name: 'ApplicationName',
|
||||||
columns: ['TextData', 'ApplicationName', 'NTUserName', 'LoginName', 'ClientProcessID', 'SPID', 'StartTime']
|
width: '1',
|
||||||
|
eventsMapped: ['client_app_name']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'RPC:Completed',
|
name: 'NTUserName',
|
||||||
columns: ['ApplicationName', 'NTUserName', 'LoginName', 'CPU', 'Reads', 'Writes', 'Duration', 'ClientProcessID', 'SPID', 'StartTime', 'EndTime', 'BinaryData']
|
eventsMapped: ['nt_username']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'SQL:BatchCompleted',
|
name: 'LoginName',
|
||||||
columns: ['TextData', 'ApplicationName', 'NTUserName', 'LoginName', 'CPU', 'Reads', 'Writes', 'Duration', 'ClientProcessID', 'SPID', 'StartTime', 'EndTime', 'BinaryData']
|
eventsMapped: ['server_principal_name']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'SQL:BatchStarting',
|
name: 'ClientProcessID',
|
||||||
columns: ['TextData', 'ApplicationName', 'NTUserName', 'LoginName', 'ClientProcessID', 'SPID', 'StartTime']
|
eventsMapped: ['client_pid']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'SPID',
|
||||||
|
eventsMapped: ['session_id']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'StartTime',
|
||||||
|
eventsMapped: ['timestamp']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'CPU',
|
||||||
|
eventsMapped: ['cpu_time']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Reads',
|
||||||
|
eventsMapped: ['logical_reads']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Writes',
|
||||||
|
eventsMapped: ['writes']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Duration',
|
||||||
|
eventsMapped: ['duration']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'TSQL View',
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
name: 'EventClass',
|
||||||
|
eventsMapped: ['name']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'TextData',
|
||||||
|
eventsMapped: ['options_text', 'batch_text']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'SPID',
|
||||||
|
eventsMapped: ['session_id']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'StartTime',
|
||||||
|
eventsMapped: ['timestamp']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Tuning View',
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
name: 'EventClass',
|
||||||
|
eventsMapped: ['name']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'TextData',
|
||||||
|
eventsMapped: ['options_text', 'batch_text']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Duration',
|
||||||
|
eventsMapped: ['duration']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'SPID',
|
||||||
|
eventsMapped: ['session_id']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'DatabaseID',
|
||||||
|
eventsMapped: ['database_id']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'DatabaseName',
|
||||||
|
eventsMapped: ['database_name']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'ObjectType',
|
||||||
|
eventsMapped: ['object_type']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'LoginName',
|
||||||
|
eventsMapped: ['server_principal_name']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'TSQL_Locks View',
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
name: 'EventClass',
|
||||||
|
eventsMapped: ['name']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'TextData',
|
||||||
|
eventsMapped: ['options_text', 'batch_text']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'ApplicationName',
|
||||||
|
eventsMapped: ['client_app_name']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'NTUserName',
|
||||||
|
eventsMapped: ['nt_username']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'LoginName',
|
||||||
|
eventsMapped: ['server_principal_name']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'ClientProcessID',
|
||||||
|
eventsMapped: ['client_pid']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'SPID',
|
||||||
|
eventsMapped: ['session_id']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'StartTime',
|
||||||
|
eventsMapped: ['timestamp']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'CPU',
|
||||||
|
eventsMapped: ['cpu_time']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Reads',
|
||||||
|
eventsMapped: ['logical_reads']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Writes',
|
||||||
|
eventsMapped: ['writes']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Duration',
|
||||||
|
eventsMapped: ['duration']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'TSQL_Duration View',
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
name: 'EventClass',
|
||||||
|
eventsMapped: ['name']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Duration',
|
||||||
|
eventsMapped: ['duration']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'TextData',
|
||||||
|
eventsMapped: ['options_text', 'batch_text']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'SPID',
|
||||||
|
eventsMapped: ['session_id']
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
]
|
||||||
]
|
};
|
||||||
};
|
|
||||||
|
|
||||||
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
|
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
|
||||||
const dashboardConfig: IConfigurationNode = {
|
const dashboardConfig: IConfigurationNode = {
|
||||||
id: 'Profiler',
|
id: 'Profiler',
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
[PROFILER_SESSION_TEMPLATE_SETTINGS]: profilerSessionTemplateSchema
|
[PROFILER_VIEW_TEMPLATE_SETTINGS]: profilerViewTemplateSchema
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -55,13 +55,17 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
|
|||||||
id: 'profiler.newProfiler',
|
id: 'profiler.newProfiler',
|
||||||
weight: KeybindingsRegistry.WEIGHT.builtinExtension(),
|
weight: KeybindingsRegistry.WEIGHT.builtinExtension(),
|
||||||
when: undefined,
|
when: undefined,
|
||||||
primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_P,
|
primary: KeyMod.Alt | KeyCode.KEY_P,
|
||||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_P },
|
mac: { primary: KeyMod.WinCtrl | KeyMod.Alt | KeyCode.KEY_P },
|
||||||
handler: CommandsRegistry.getCommand('profiler.newProfiler').handler
|
handler: CommandsRegistry.getCommand('profiler.newProfiler').handler
|
||||||
});
|
});
|
||||||
|
|
||||||
CommandsRegistry.registerCommand({
|
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||||
id: 'profiler.start',
|
id: 'profiler.toggleStartStop',
|
||||||
|
weight: KeybindingsRegistry.WEIGHT.editorContrib(),
|
||||||
|
when: undefined,
|
||||||
|
primary: KeyMod.Alt | KeyCode.KEY_S,
|
||||||
|
mac: { primary: KeyMod.WinCtrl | KeyMod.Alt | KeyCode.KEY_S },
|
||||||
handler: (accessor: ServicesAccessor) => {
|
handler: (accessor: ServicesAccessor) => {
|
||||||
let profilerService: IProfilerService = accessor.get(IProfilerService);
|
let profilerService: IProfilerService = accessor.get(IProfilerService);
|
||||||
let editorService: IWorkbenchEditorService = accessor.get(IWorkbenchEditorService);
|
let editorService: IWorkbenchEditorService = accessor.get(IWorkbenchEditorService);
|
||||||
@@ -69,22 +73,13 @@ CommandsRegistry.registerCommand({
|
|||||||
let activeEditor = editorService.getActiveEditor();
|
let activeEditor = editorService.getActiveEditor();
|
||||||
if (activeEditor instanceof ProfilerEditor) {
|
if (activeEditor instanceof ProfilerEditor) {
|
||||||
let profilerInput = activeEditor.input;
|
let profilerInput = activeEditor.input;
|
||||||
return profilerService.startSession(profilerInput.id);
|
if (profilerInput.state.isRunning){
|
||||||
}
|
return profilerService.stopSession(profilerInput.id);
|
||||||
return TPromise.as(false);
|
} else {
|
||||||
}
|
// clear data when profiler is started
|
||||||
});
|
profilerInput.data.clear();
|
||||||
|
return profilerService.startSession(profilerInput.id);
|
||||||
CommandsRegistry.registerCommand({
|
}
|
||||||
id: 'profiler.stop',
|
|
||||||
handler: (accessor: ServicesAccessor) => {
|
|
||||||
let profilerService: IProfilerService = accessor.get(IProfilerService);
|
|
||||||
let editorService: IWorkbenchEditorService = accessor.get(IWorkbenchEditorService);
|
|
||||||
|
|
||||||
let activeEditor = editorService.getActiveEditor();
|
|
||||||
if (activeEditor instanceof ProfilerEditor) {
|
|
||||||
let profilerInput = activeEditor.input;
|
|
||||||
return profilerService.stopSession(profilerInput.id);
|
|
||||||
}
|
}
|
||||||
return TPromise.as(false);
|
return TPromise.as(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,6 @@ export class ProfilerStart extends Action {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public run(input: ProfilerInput): TPromise<boolean> {
|
public run(input: ProfilerInput): TPromise<boolean> {
|
||||||
this.enabled = false;
|
|
||||||
input.data.clear();
|
input.data.clear();
|
||||||
return TPromise.wrap(this._profilerService.startSession(input.id));
|
return TPromise.wrap(this._profilerService.startSession(input.id));
|
||||||
}
|
}
|
||||||
@@ -127,7 +126,6 @@ export class ProfilerStop extends Action {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public run(input: ProfilerInput): TPromise<boolean> {
|
public run(input: ProfilerInput): TPromise<boolean> {
|
||||||
this.enabled = false;
|
|
||||||
return TPromise.wrap(this._profilerService.stopSession(input.id));
|
return TPromise.wrap(this._profilerService.stopSession(input.id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,7 +135,7 @@ export class ProfilerClear extends Action {
|
|||||||
public static LABEL = nls.localize('profiler.clear', "Clear Data");
|
public static LABEL = nls.localize('profiler.clear', "Clear Data");
|
||||||
|
|
||||||
constructor(id: string, label: string) {
|
constructor(id: string, label: string) {
|
||||||
super(id, label, 'stop');
|
super(id, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
run(input: ProfilerInput): TPromise<void> {
|
run(input: ProfilerInput): TPromise<void> {
|
||||||
@@ -148,14 +146,15 @@ export class ProfilerClear extends Action {
|
|||||||
|
|
||||||
export class ProfilerAutoScroll extends Action {
|
export class ProfilerAutoScroll extends Action {
|
||||||
public static ID = 'profiler.autoscroll';
|
public static ID = 'profiler.autoscroll';
|
||||||
public static LABEL = nls.localize('profiler.toggleAutoscroll', "Toggle Auto Scroll");
|
public static LABEL = nls.localize('profiler.autoscrollOn', "Auto Scroll: On");
|
||||||
|
|
||||||
constructor(id: string, label: string) {
|
constructor(id: string, label: string) {
|
||||||
super(id, label, 'stop');
|
super(id, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
run(input: ProfilerInput): TPromise<boolean> {
|
run(input: ProfilerInput): TPromise<boolean> {
|
||||||
this.checked = !this.checked;
|
this.checked = !this.checked;
|
||||||
|
this._setLabel(this.checked ? nls.localize('profilerAction.autoscrollOn', "Auto Scroll: On") : nls.localize('profilerAction.autoscrollOff', "Auto Scroll: Off"));
|
||||||
input.state.change({ autoscroll: this.checked });
|
input.state.change({ autoscroll: this.checked });
|
||||||
return TPromise.as(true);
|
return TPromise.as(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -360,7 +360,10 @@ export class ProfilerColumnEditorDialog extends Modal {
|
|||||||
super.onAccept(e);
|
super.onAccept(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// currently not used, this dialog is a work in progress
|
||||||
|
// tracked in issue #1545 https://github.com/Microsoft/sqlopsstudio/issues/1545
|
||||||
private _updateInput(): void {
|
private _updateInput(): void {
|
||||||
|
/*
|
||||||
this._element.getUnsortedChildren().forEach(e => {
|
this._element.getUnsortedChildren().forEach(e => {
|
||||||
let origEvent = this._input.sessionTemplate.view.events.find(i => i.name === e.id);
|
let origEvent = this._input.sessionTemplate.view.events.find(i => i.name === e.id);
|
||||||
if (e.indeterminate) {
|
if (e.indeterminate) {
|
||||||
@@ -387,9 +390,13 @@ export class ProfilerColumnEditorDialog extends Modal {
|
|||||||
}, []);
|
}, []);
|
||||||
newColumns.unshift('EventClass');
|
newColumns.unshift('EventClass');
|
||||||
this._input.setColumns(newColumns);
|
this._input.setColumns(newColumns);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// currently not used, this dialog is a work in progress
|
||||||
|
// tracked in issue #1545 https://github.com/Microsoft/sqlopsstudio/issues/1545
|
||||||
private _updateList(): void {
|
private _updateList(): void {
|
||||||
|
/*
|
||||||
this._element = new SessionItem(this._input.sessionTemplate.name, this._selectedValue === 0 ? 'event' : 'column');
|
this._element = new SessionItem(this._input.sessionTemplate.name, this._selectedValue === 0 ? 'event' : 'column');
|
||||||
this._input.sessionTemplate.events.forEach(item => {
|
this._input.sessionTemplate.events.forEach(item => {
|
||||||
let event = new EventItem(item.name, this._element);
|
let event = new EventItem(item.name, this._element);
|
||||||
@@ -402,6 +409,7 @@ export class ProfilerColumnEditorDialog extends Modal {
|
|||||||
});
|
});
|
||||||
this._tree.setInput(this._element);
|
this._tree.setInput(this._element);
|
||||||
this._tree.layout(DOM.getTotalHeight(this._treeContainer));
|
this._tree.layout(DOM.getTotalHeight(this._treeContainer));
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
protected layout(height?: number): void {
|
protected layout(height?: number): void {
|
||||||
|
|||||||
@@ -166,6 +166,7 @@ export class ProfilerTableEditor extends BaseEditor implements IProfilerControll
|
|||||||
public layout(dimension: Dimension): void {
|
public layout(dimension: Dimension): void {
|
||||||
this._currentDimensions = dimension;
|
this._currentDimensions = dimension;
|
||||||
this._profilerTable.layout(dimension);
|
this._profilerTable.layout(dimension);
|
||||||
|
this._profilerTable.autosizeColumns();
|
||||||
this._onDidChangeConfiguration.fire({ layoutInfo: true });
|
this._onDidChangeConfiguration.fire({ layoutInfo: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { ProfilerInput } from './profilerInput';
|
|||||||
import { TabbedPanel } from 'sql/base/browser/ui/panel/panel';
|
import { TabbedPanel } from 'sql/base/browser/ui/panel/panel';
|
||||||
import { Table } from 'sql/base/browser/ui/table/table';
|
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 { IProfilerService, IProfilerSessionTemplate } from 'sql/parts/profiler/service/interfaces';
|
import { IProfilerService, IProfilerViewTemplate } from 'sql/parts/profiler/service/interfaces';
|
||||||
import { Taskbar } from 'sql/base/browser/ui/taskbar/taskbar';
|
import { Taskbar } from 'sql/base/browser/ui/taskbar/taskbar';
|
||||||
import { attachTableStyler } from 'sql/common/theme/styler';
|
import { attachTableStyler } from 'sql/common/theme/styler';
|
||||||
import { IProfilerStateChangedEvent } from './profilerState';
|
import { IProfilerStateChangedEvent } from './profilerState';
|
||||||
@@ -50,6 +50,7 @@ class BasicView extends View {
|
|||||||
private _previousSize: number;
|
private _previousSize: number;
|
||||||
private _collapsed: boolean;
|
private _collapsed: boolean;
|
||||||
public headerSize: number;
|
public headerSize: number;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
initialSize: number,
|
initialSize: number,
|
||||||
private _element: HTMLElement,
|
private _element: HTMLElement,
|
||||||
@@ -58,6 +59,7 @@ class BasicView extends View {
|
|||||||
opts: IViewOptions
|
opts: IViewOptions
|
||||||
) {
|
) {
|
||||||
super(initialSize, opts);
|
super(initialSize, opts);
|
||||||
|
this._previousSize = initialSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
render(container: HTMLElement, orientation: Orientation): void {
|
render(container: HTMLElement, orientation: Orientation): void {
|
||||||
@@ -114,8 +116,9 @@ export class ProfilerEditor extends BaseEditor {
|
|||||||
|
|
||||||
private _profilerEditorContextKey: IContextKey<boolean>;
|
private _profilerEditorContextKey: IContextKey<boolean>;
|
||||||
|
|
||||||
private _sessionTemplateSelector: SelectBox;
|
private _viewTemplateSelector: SelectBox;
|
||||||
private _sessionTemplates: Array<IProfilerSessionTemplate>;
|
private _viewTemplates: Array<IProfilerViewTemplate>;
|
||||||
|
private _connectionInfoText: HTMLElement;
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
private _connectAction: Actions.ProfilerConnect;
|
private _connectAction: Actions.ProfilerConnect;
|
||||||
@@ -125,6 +128,7 @@ export class ProfilerEditor extends BaseEditor {
|
|||||||
private _autoscrollAction: Actions.ProfilerAutoScroll;
|
private _autoscrollAction: Actions.ProfilerAutoScroll;
|
||||||
private _collapsedPanelAction: Actions.ProfilerCollapsablePanelAction;
|
private _collapsedPanelAction: Actions.ProfilerCollapsablePanelAction;
|
||||||
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ITelemetryService telemetryService: ITelemetryService,
|
@ITelemetryService telemetryService: ITelemetryService,
|
||||||
@IWorkbenchThemeService themeService: IWorkbenchThemeService,
|
@IWorkbenchThemeService themeService: IWorkbenchThemeService,
|
||||||
@@ -189,27 +193,37 @@ export class ProfilerEditor extends BaseEditor {
|
|||||||
this._connectAction = this._instantiationService.createInstance(Actions.ProfilerConnect, Actions.ProfilerConnect.ID, Actions.ProfilerConnect.LABEL);
|
this._connectAction = this._instantiationService.createInstance(Actions.ProfilerConnect, Actions.ProfilerConnect.ID, Actions.ProfilerConnect.LABEL);
|
||||||
this._autoscrollAction = this._instantiationService.createInstance(Actions.ProfilerAutoScroll, Actions.ProfilerAutoScroll.ID, Actions.ProfilerAutoScroll.LABEL);
|
this._autoscrollAction = this._instantiationService.createInstance(Actions.ProfilerAutoScroll, Actions.ProfilerAutoScroll.ID, Actions.ProfilerAutoScroll.LABEL);
|
||||||
|
|
||||||
this._sessionTemplates = this._profilerService.getSessionTemplates();
|
this._viewTemplates = this._profilerService.getViewTemplates();
|
||||||
this._sessionTemplateSelector = new SelectBox(this._sessionTemplates.map(i => i.name), 'Standard', this._contextViewService);
|
this._viewTemplateSelector = new SelectBox(this._viewTemplates.map(i => i.name), 'Standard View', this._contextViewService);
|
||||||
this._register(this._sessionTemplateSelector.onDidSelect(e => {
|
this._register(this._viewTemplateSelector.onDidSelect(e => {
|
||||||
if (this.input) {
|
if (this.input) {
|
||||||
this.input.sessionTemplate = this._sessionTemplates.find(i => i.name === e.selected);
|
this.input.viewTemplate = this._viewTemplates.find(i => i.name === e.selected);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
let dropdownContainer = document.createElement('div');
|
let dropdownContainer = document.createElement('div');
|
||||||
dropdownContainer.style.width = '150px';
|
dropdownContainer.style.width = '150px';
|
||||||
this._sessionTemplateSelector.render(dropdownContainer);
|
dropdownContainer.style.paddingRight = '5px';
|
||||||
|
this._viewTemplateSelector.render(dropdownContainer);
|
||||||
|
|
||||||
this._register(attachSelectBoxStyler(this._sessionTemplateSelector, this.themeService));
|
this._connectionInfoText = document.createElement('div');
|
||||||
|
this._connectionInfoText.style.paddingRight = '5px';
|
||||||
|
this._connectionInfoText.innerText = '';
|
||||||
|
this._connectionInfoText.style.textAlign = 'center';
|
||||||
|
this._connectionInfoText.style.display = 'flex';
|
||||||
|
this._connectionInfoText.style.alignItems = 'center';
|
||||||
|
|
||||||
|
this._register(attachSelectBoxStyler(this._viewTemplateSelector, this.themeService));
|
||||||
|
|
||||||
this._actionBar.setContent([
|
this._actionBar.setContent([
|
||||||
{ action: this._startAction },
|
{ action: this._startAction },
|
||||||
{ action: this._stopAction },
|
{ action: this._stopAction },
|
||||||
{ element: dropdownContainer },
|
|
||||||
{ element: Taskbar.createTaskbarSeparator() },
|
{ element: Taskbar.createTaskbarSeparator() },
|
||||||
{ action: this._pauseAction },
|
{ action: this._pauseAction },
|
||||||
{ action: this._autoscrollAction },
|
{ action: this._autoscrollAction },
|
||||||
{ action: this._instantiationService.createInstance(Actions.ProfilerClear, Actions.ProfilerClear.ID, Actions.ProfilerClear.LABEL) }
|
{ action: this._instantiationService.createInstance(Actions.ProfilerClear, Actions.ProfilerClear.ID, Actions.ProfilerClear.LABEL) },
|
||||||
|
{ element: dropdownContainer },
|
||||||
|
{ element: Taskbar.createTaskbarSeparator() },
|
||||||
|
{ element: this._connectionInfoText }
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,10 +354,10 @@ export class ProfilerEditor extends BaseEditor {
|
|||||||
return super.setInput(input, options).then(() => {
|
return super.setInput(input, options).then(() => {
|
||||||
this._profilerTableEditor.setInput(input);
|
this._profilerTableEditor.setInput(input);
|
||||||
|
|
||||||
if (input.sessionTemplate) {
|
if (input.viewTemplate) {
|
||||||
this._sessionTemplateSelector.selectWithOptionName(input.sessionTemplate.name);
|
this._viewTemplateSelector.selectWithOptionName(input.viewTemplate.name);
|
||||||
} else {
|
} else {
|
||||||
input.sessionTemplate = this._sessionTemplates.find(i => i.name === 'Standard');
|
input.viewTemplate = this._viewTemplates.find(i => i.name === 'Standard View');
|
||||||
}
|
}
|
||||||
|
|
||||||
this._actionBar.context = input;
|
this._actionBar.context = input;
|
||||||
@@ -360,6 +374,7 @@ export class ProfilerEditor extends BaseEditor {
|
|||||||
autoscroll: true,
|
autoscroll: true,
|
||||||
isPanelCollapsed: true
|
isPanelCollapsed: true
|
||||||
});
|
});
|
||||||
|
this._connectionInfoText.innerText = input.connectionName;
|
||||||
this._profilerTableEditor.updateState();
|
this._profilerTableEditor.updateState();
|
||||||
this._splitView.layout();
|
this._splitView.layout();
|
||||||
this._profilerTableEditor.focus();
|
this._profilerTableEditor.focus();
|
||||||
@@ -401,10 +416,7 @@ export class ProfilerEditor extends BaseEditor {
|
|||||||
|
|
||||||
if (e.isConnected) {
|
if (e.isConnected) {
|
||||||
this._connectAction.connected = this.input.state.isConnected;
|
this._connectAction.connected = this.input.state.isConnected;
|
||||||
if (this.input.state.isConnected) {
|
if (!this.input.state.isConnected) {
|
||||||
this._sessionTemplateSelector.disable();
|
|
||||||
} else {
|
|
||||||
this._sessionTemplateSelector.enable();
|
|
||||||
this._startAction.enabled = this.input.state.isConnected;
|
this._startAction.enabled = this.input.state.isConnected;
|
||||||
this._stopAction.enabled = false;
|
this._stopAction.enabled = false;
|
||||||
this._pauseAction.enabled = false;
|
this._pauseAction.enabled = false;
|
||||||
|
|||||||
@@ -4,11 +4,12 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { TableDataView } from 'sql/base/browser/ui/table/tableDataView';
|
import { TableDataView } from 'sql/base/browser/ui/table/tableDataView';
|
||||||
import { IProfilerSession, IProfilerService, ProfilerSessionID, IProfilerSessionTemplate } from 'sql/parts/profiler/service/interfaces';
|
import { IProfilerSession, IProfilerService, ProfilerSessionID, IProfilerViewTemplate } from 'sql/parts/profiler/service/interfaces';
|
||||||
import { ProfilerState } from './profilerState';
|
import { ProfilerState } from './profilerState';
|
||||||
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
||||||
|
|
||||||
import * as sqlops from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
|
import * as nls from 'vs/nls';
|
||||||
|
|
||||||
import { TPromise } from 'vs/base/common/winjs.base';
|
import { TPromise } from 'vs/base/common/winjs.base';
|
||||||
import { EditorInput } from 'vs/workbench/common/editor';
|
import { EditorInput } from 'vs/workbench/common/editor';
|
||||||
@@ -17,8 +18,8 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
|||||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||||
import { Event, Emitter } from 'vs/base/common/event';
|
import { Event, Emitter } from 'vs/base/common/event';
|
||||||
import { generateUuid } from 'vs/base/common/uuid';
|
import { generateUuid } from 'vs/base/common/uuid';
|
||||||
|
import { IDialogService, IConfirmation, IConfirmationResult } from 'vs/platform/dialogs/common/dialogs';
|
||||||
import * as nls from 'vs/nls';
|
import { escape } from 'sql/base/common/strings';
|
||||||
|
|
||||||
export class ProfilerInput extends EditorInput implements IProfilerSession {
|
export class ProfilerInput extends EditorInput implements IProfilerSession {
|
||||||
|
|
||||||
@@ -28,7 +29,10 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
|||||||
private _id: ProfilerSessionID;
|
private _id: ProfilerSessionID;
|
||||||
private _state: ProfilerState;
|
private _state: ProfilerState;
|
||||||
private _columns: string[] = [];
|
private _columns: string[] = [];
|
||||||
private _sessionTemplate: IProfilerSessionTemplate;
|
private _viewTemplate: IProfilerViewTemplate;
|
||||||
|
// mapping of event categories to what column they display under
|
||||||
|
// used for coallescing multiple events with different names to the same column
|
||||||
|
private _columnMapping: { [event: string]: string } = {};
|
||||||
|
|
||||||
private _onColumnsChanged = new Emitter<Slick.Column<Slick.SlickData>[]>();
|
private _onColumnsChanged = new Emitter<Slick.Column<Slick.SlickData>[]>();
|
||||||
public onColumnsChanged: Event<Slick.Column<Slick.SlickData>[]> = this._onColumnsChanged.event;
|
public onColumnsChanged: Event<Slick.Column<Slick.SlickData>[]> = this._onColumnsChanged.event;
|
||||||
@@ -37,7 +41,8 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
|||||||
private _connection: IConnectionProfile,
|
private _connection: IConnectionProfile,
|
||||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||||
@IProfilerService private _profilerService: IProfilerService,
|
@IProfilerService private _profilerService: IProfilerService,
|
||||||
@INotificationService private _notificationService: INotificationService
|
@INotificationService private _notificationService: INotificationService,
|
||||||
|
@IDialogService private _dialogService: IDialogService
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this._state = new ProfilerState();
|
this._state = new ProfilerState();
|
||||||
@@ -61,24 +66,45 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
|||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
this._data = new TableDataView<Slick.SlickData>(undefined, searchFn);
|
this._data = new TableDataView<Slick.SlickData>(undefined, searchFn);
|
||||||
|
|
||||||
|
this.onDispose(() => {
|
||||||
|
if (this._state.isRunning || this.state.isPaused) {
|
||||||
|
let confirm: IConfirmation = {
|
||||||
|
message: nls.localize('confirmStopProfilerSession', "Would you like to stop the running XEvent session?"),
|
||||||
|
primaryButton: nls.localize('profilerClosingActions.yes', 'Yes'),
|
||||||
|
secondaryButton: nls.localize('profilerClosingActions.no', 'No'),
|
||||||
|
type: 'question'
|
||||||
|
};
|
||||||
|
|
||||||
|
this._dialogService.confirm(confirm).then(result => {
|
||||||
|
if (result.confirmed) {
|
||||||
|
this._profilerService.stopSession(this.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public set sessionTemplate(template: IProfilerSessionTemplate) {
|
public set viewTemplate(template: IProfilerViewTemplate) {
|
||||||
this._sessionTemplate = template;
|
this._data.clear();
|
||||||
let newColumns = this.sessionTemplate.view.events.reduce<Array<string>>((p, e) => {
|
this._viewTemplate = template;
|
||||||
e.columns.forEach(c => {
|
|
||||||
if (!p.includes(c)) {
|
let newColumns = this._viewTemplate.columns.reduce<Array<string>>((p, e) => {
|
||||||
p.push(c);
|
p.push(e.name);
|
||||||
}
|
|
||||||
});
|
|
||||||
return p;
|
return p;
|
||||||
}, []);
|
}, []);
|
||||||
newColumns.unshift('EventClass');
|
|
||||||
this.setColumns(newColumns);
|
let newMapping: { [event: string]: string } = {};
|
||||||
|
this._viewTemplate.columns.forEach(c => {
|
||||||
|
c.eventsMapped.forEach(e => {
|
||||||
|
newMapping[e] = c.name;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
this.setColumnMapping(newColumns, newMapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
public get sessionTemplate(): IProfilerSessionTemplate {
|
public get viewTemplate(): IProfilerViewTemplate {
|
||||||
return this._sessionTemplate;
|
return this._viewTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getTypeId(): string {
|
public getTypeId(): string {
|
||||||
@@ -117,6 +143,25 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
|||||||
this._onColumnsChanged.fire(this.columns);
|
this._onColumnsChanged.fire(this.columns);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setColumnMapping(columns: Array<string>, mapping: { [event: string]: string }) {
|
||||||
|
this._columns = columns;
|
||||||
|
this._columnMapping = mapping;
|
||||||
|
this._onColumnsChanged.fire(this.columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
public get connectionName(): string {
|
||||||
|
if (this._connection !== null) {
|
||||||
|
if (this._connection.databaseName) {
|
||||||
|
return `${ this._connection.serverName } ${ this._connection.databaseName }`;
|
||||||
|
} else {
|
||||||
|
return `${ this._connection.serverName }`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return nls.localize('profilerInput.notConnected', "Not connected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public get id(): ProfilerSessionID {
|
public get id(): ProfilerSessionID {
|
||||||
return this._id;
|
return this._id;
|
||||||
}
|
}
|
||||||
@@ -140,54 +185,25 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public onMoreRows(eventMessage: sqlops.ProfilerSessionEvents) {
|
public onMoreRows(eventMessage: sqlops.ProfilerSessionEvents) {
|
||||||
if (eventMessage.eventsLost){
|
if (eventMessage.eventsLost) {
|
||||||
this._notificationService.warn(nls.localize("profiler.eventsLost", "The XEvent Profiler session for {0} has lost events.", this._connection.serverName));
|
this._notificationService.warn(nls.localize("profiler.eventsLost", "The XEvent Profiler session for {0} has lost events.", this._connection.serverName));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i: number = 0; i < eventMessage.events.length && i < 500; ++i) {
|
for (let i: number = 0; i < eventMessage.events.length && i < 500; ++i) {
|
||||||
let e: sqlops.ProfilerEvent = eventMessage.events[i];
|
let e: sqlops.ProfilerEvent = eventMessage.events[i];
|
||||||
let data = {};
|
let data = {};
|
||||||
data['EventClass'] = e.name;
|
data['EventClass'] = e.name;
|
||||||
data['StartTime'] = e.timestamp;
|
data['StartTime'] = e.timestamp;
|
||||||
const columns = [
|
|
||||||
'TextData',
|
|
||||||
'ApplicationName',
|
|
||||||
'NTUserName',
|
|
||||||
'LoginName',
|
|
||||||
'CPU',
|
|
||||||
'Reads',
|
|
||||||
'Writes',
|
|
||||||
'Duration',
|
|
||||||
'ClientProcessID',
|
|
||||||
'SPID',
|
|
||||||
'StartTime',
|
|
||||||
'EndTime',
|
|
||||||
'BinaryData'
|
|
||||||
];
|
|
||||||
|
|
||||||
let columnNameMap: Map<string, string> = new Map<string, string>();
|
|
||||||
columnNameMap['client_app_name'] = 'ApplicationName';
|
|
||||||
columnNameMap['nt_username'] = 'NTUserName';
|
|
||||||
columnNameMap['options_text'] = 'TextData';
|
|
||||||
columnNameMap['server_principal_name'] = 'LoginName';
|
|
||||||
columnNameMap['session_id'] = 'SPID';
|
|
||||||
columnNameMap['batch_text'] = 'TextData';
|
|
||||||
columnNameMap['cpu_time'] = 'CPU';
|
|
||||||
columnNameMap['duration'] = 'Duration';
|
|
||||||
columnNameMap['logical_reads'] = 'Reads';
|
|
||||||
columnNameMap['event_sequence'] = 'EventSequence';
|
|
||||||
columnNameMap['client_pid'] = 'ClientProcessID';
|
|
||||||
columnNameMap['writes'] = 'Writes';
|
|
||||||
|
|
||||||
// Using ' ' instead of '' fixed the error where clicking through events
|
// Using ' ' instead of '' fixed the error where clicking through events
|
||||||
// with empty text fields causes future text panes to be highlighted.
|
// with empty text fields causes future text panes to be highlighted.
|
||||||
// This is a temporary fix, and should be changed before the July release
|
// This is a temporary fix
|
||||||
data['TextData'] = ' ';
|
data['TextData'] = ' ';
|
||||||
for (let key in e.values) {
|
for (let key in e.values) {
|
||||||
let columnName = columnNameMap[key];
|
let columnName = this._columnMapping[key];
|
||||||
if (columnName) {
|
if (columnName) {
|
||||||
let value = e.values[key];
|
let value = e.values[key];
|
||||||
data[columnName] = value;
|
data[columnName] = escape(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this._data.push(data);
|
this._data.push(data);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export const IProfilerService = createDecorator<IProfilerService>(PROFILER_SERVI
|
|||||||
|
|
||||||
export type ProfilerSessionID = string;
|
export type ProfilerSessionID = string;
|
||||||
|
|
||||||
export const PROFILER_SESSION_TEMPLATE_SETTINGS = 'profiler.sessionTemplates';
|
export const PROFILER_VIEW_TEMPLATE_SETTINGS = 'profiler.viewTemplates';
|
||||||
export const PROFILER_SETTINGS = 'profiler';
|
export const PROFILER_SETTINGS = 'profiler';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -84,7 +84,7 @@ export interface IProfilerService {
|
|||||||
* @returns An array of session templates that match the provider passed, if passed, and generic ones (no provider specified),
|
* @returns An array of session templates that match the provider passed, if passed, and generic ones (no provider specified),
|
||||||
* otherwise returns all session templates
|
* otherwise returns all session templates
|
||||||
*/
|
*/
|
||||||
getSessionTemplates(providerId?: string): Array<IProfilerSessionTemplate>;
|
getViewTemplates(providerId?: string): Array<IProfilerViewTemplate>;
|
||||||
/**
|
/**
|
||||||
* Launches the dialog for editing the view columns of a profiler session template for the given input
|
* Launches the dialog for editing the view columns of a profiler session template for the given input
|
||||||
* @param input input object that contains the necessary information which will be modified based on used input
|
* @param input input object that contains the necessary information which will be modified based on used input
|
||||||
@@ -93,25 +93,15 @@ export interface IProfilerService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IProfilerSettings {
|
export interface IProfilerSettings {
|
||||||
sessionTemplates: Array<IProfilerSessionTemplate>;
|
viewTemplates: Array<IProfilerViewTemplate>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IEventTemplate {
|
export interface IColumnViewTemplate {
|
||||||
name: string;
|
name: string;
|
||||||
optionalColumns: Array<string>;
|
eventsMapped: Array<string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IEventViewTemplate {
|
export interface IProfilerViewTemplate {
|
||||||
name: string;
|
name: string;
|
||||||
columns: Array<string>;
|
columns: Array<IColumnViewTemplate>;
|
||||||
}
|
|
||||||
|
|
||||||
export interface ISessionViewTemplate {
|
|
||||||
events: Array<IEventViewTemplate>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IProfilerSessionTemplate {
|
|
||||||
name: string;
|
|
||||||
events: Array<IEventTemplate>;
|
|
||||||
view: ISessionViewTemplate;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
import { IConnectionManagementService, IConnectionCompletionOptions, ConnectionType, RunQueryOnConnectionMode } from 'sql/parts/connection/common/connectionManagement';
|
import { IConnectionManagementService, IConnectionCompletionOptions, ConnectionType, RunQueryOnConnectionMode } from 'sql/parts/connection/common/connectionManagement';
|
||||||
import {
|
import {
|
||||||
ProfilerSessionID, IProfilerSession, IProfilerService, IProfilerSessionTemplate,
|
ProfilerSessionID, IProfilerSession, IProfilerService, IProfilerViewTemplate,
|
||||||
PROFILER_SETTINGS, IProfilerSettings
|
PROFILER_SETTINGS, IProfilerSettings
|
||||||
} from './interfaces';
|
} from './interfaces';
|
||||||
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
||||||
@@ -17,6 +17,7 @@ import * as sqlops from 'sqlops';
|
|||||||
import { TPromise } from 'vs/base/common/winjs.base';
|
import { TPromise } from 'vs/base/common/winjs.base';
|
||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||||
|
|
||||||
class TwoWayMap<T, K> {
|
class TwoWayMap<T, K> {
|
||||||
private forwardMap: Map<T, K>;
|
private forwardMap: Map<T, K>;
|
||||||
@@ -52,7 +53,8 @@ export class ProfilerService implements IProfilerService {
|
|||||||
constructor(
|
constructor(
|
||||||
@IConnectionManagementService private _connectionService: IConnectionManagementService,
|
@IConnectionManagementService private _connectionService: IConnectionManagementService,
|
||||||
@IConfigurationService public _configurationService: IConfigurationService,
|
@IConfigurationService public _configurationService: IConfigurationService,
|
||||||
@IInstantiationService private _instantiationService: IInstantiationService
|
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||||
|
@INotificationService private _notificationService: INotificationService
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
public registerProvider(providerId: string, provider: sqlops.ProfilerProvider): void {
|
public registerProvider(providerId: string, provider: sqlops.ProfilerProvider): void {
|
||||||
@@ -99,6 +101,8 @@ export class ProfilerService implements IProfilerService {
|
|||||||
return this._runAction(id, provider => provider.startSession(this._idMap.get(id))).then(() => {
|
return this._runAction(id, provider => provider.startSession(this._idMap.get(id))).then(() => {
|
||||||
this._sessionMap.get(this._idMap.reverseGet(id)).onSessionStateChanged({ isRunning: true, isStopped: false, isPaused: false });
|
this._sessionMap.get(this._idMap.reverseGet(id)).onSessionStateChanged({ isRunning: true, isStopped: false, isPaused: false });
|
||||||
return true;
|
return true;
|
||||||
|
}, (reason) => {
|
||||||
|
this._notificationService.error(reason.message);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,6 +114,8 @@ export class ProfilerService implements IProfilerService {
|
|||||||
return this._runAction(id, provider => provider.stopSession(this._idMap.get(id))).then(() => {
|
return this._runAction(id, provider => provider.stopSession(this._idMap.get(id))).then(() => {
|
||||||
this._sessionMap.get(this._idMap.reverseGet(id)).onSessionStateChanged({ isStopped: true, isPaused: false, isRunning: false });
|
this._sessionMap.get(this._idMap.reverseGet(id)).onSessionStateChanged({ isStopped: true, isPaused: false, isRunning: false });
|
||||||
return true;
|
return true;
|
||||||
|
}, (reason) => {
|
||||||
|
this._notificationService.error(reason.message);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,13 +134,13 @@ export class ProfilerService implements IProfilerService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public getSessionTemplates(provider?: string): Array<IProfilerSessionTemplate> {
|
public getViewTemplates(provider?: string): Array<IProfilerViewTemplate> {
|
||||||
let config = <IProfilerSettings>this._configurationService.getValue(PROFILER_SETTINGS);
|
let config = <IProfilerSettings>this._configurationService.getValue(PROFILER_SETTINGS);
|
||||||
|
|
||||||
if (provider) {
|
if (provider) {
|
||||||
return config.sessionTemplates;
|
return config.viewTemplates;
|
||||||
} else {
|
} else {
|
||||||
return config.sessionTemplates;
|
return config.viewTemplates;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user