Edit Agent Alert updates (#1872)

* Set database name and severity when editing alert

* Add Operator and Proxy edit

* Add edit job hookup

* Edit WIP

* Additional edit alert updates

* Remove unused method
This commit is contained in:
Karl Burtram
2018-07-09 10:47:50 -07:00
committed by GitHub
parent bdc391d376
commit fbd5e819a2
14 changed files with 201 additions and 48 deletions

View File

@@ -13,6 +13,11 @@ import { IAgentDialogData, AgentDialogMode } from '../interfaces';
const localize = nls.loadMessageBundle();
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;
dialogMode: AgentDialogMode = AgentDialogMode.CREATE;
id: number;
@@ -23,7 +28,7 @@ export class AlertData implements IAgentDialogData {
eventSource: string;
hasNotification: number;
includeEventDescription: string;
isEnabled: boolean;
isEnabled: boolean = true;
jobId: string;
jobName: string;
lastOccurrenceDate: string;
@@ -36,7 +41,7 @@ export class AlertData implements IAgentDialogData {
databaseName: string;
countResetDate: string;
categoryName: string;
alertType: string;
alertType: string = AlertData.DefaultAlertTypeString;
wmiEventNamespace: string;
wmiEventQuery: string;
@@ -109,9 +114,19 @@ export class AlertData implements IAgentDialogData {
databaseName: this.databaseName,
countResetDate: this.countResetDate,
categoryName: this.categoryName,
alertType: sqlops.AlertType.sqlServerEvent, //this.alertType,
alertType: AlertData.getAlertTypeFromString(this.alertType),
wmiEventNamespace: this.wmiEventNamespace,
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;
}
}
}

View File

@@ -40,8 +40,17 @@ export class JobData implements IAgentDialogData {
public jobSchedules: sqlops.AgentJobScheduleInfo[];
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;
if (jobInfo) {
this.dialogMode = AgentDialogMode.EDIT;
this.name = jobInfo.name;
this.enabled = jobInfo.enabled;
}
}
public get jobCategories(): string[] {

View File

@@ -29,8 +29,14 @@ export class OperatorData implements IAgentDialogData {
weekdayPagerStartTime: string;
weekdayPagerEndTime: string;
constructor(ownerUri:string) {
constructor(ownerUri:string, operatorInfo: sqlops.AgentOperatorInfo) {
this.ownerUri = ownerUri;
if (operatorInfo) {
this.dialogMode = AgentDialogMode.EDIT;
this.name = operatorInfo.name;
this.enabled = operatorInfo.enabled;
}
}
public async initialize() {

View File

@@ -19,8 +19,14 @@ export class ProxyData implements IAgentDialogData {
credentialId: number;
isEnabled: boolean;
constructor(ownerUri:string) {
constructor(ownerUri:string, proxyInfo: sqlops.AgentProxyInfo) {
this.ownerUri = ownerUri;
if (proxyInfo) {
this.accountName = proxyInfo.accountName;
this.credentialName = proxyInfo.credentialName;
this.description = proxyInfo.description;
}
}
public async initialize() {

View File

@@ -31,9 +31,6 @@ export class AlertDialog extends AgentDialog<AlertData> {
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 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 AlertSeverity002Label: string = localize('alertDialog.Severity002', '002 - Reserved');
private static readonly AlertSeverity003Label: string = localize('alertDialog.Severity003', '003 - Reserved');
@@ -59,11 +56,12 @@ export class AlertDialog extends AgentDialog<AlertData> {
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 AlertSeverity025Label: string = localize('alertDialog.Severity025', '025 - Fatal Error');
private static readonly AllDatabases: string = localize('alertDialog.AllDatabases', '<all databases>');
private static readonly AlertTypes: string[] = [
AlertDialog.AlertTypeSqlServerEventString,
AlertDialog.AlertTypePerformanceConditionString,
AlertDialog.AlertTypeWmiEventString
AlertData.AlertTypeSqlServerEventString,
AlertData.AlertTypePerformanceConditionString,
AlertData.AlertTypeWmiEventString
];
private static readonly AlertSeverities: string[] = [
@@ -124,6 +122,10 @@ export class AlertDialog extends AgentDialog<AlertData> {
private severityDropDown: sqlops.DropDownComponent;
private databaseDropDown: sqlops.DropDownComponent;
private enabledCheckBox: sqlops.CheckBoxComponent;
private errorNumberRadioButton: sqlops.RadioButtonComponent;
private severityRadioButton: sqlops.RadioButtonComponent;
private errorNumberTextBox: sqlops.InputBoxComponent;
private raiseAlertMessageCheckBox: sqlops.CheckBoxComponent;
private raiseAlertMessageTextBox: sqlops.InputBoxComponent;
@@ -142,19 +144,23 @@ export class AlertDialog extends AgentDialog<AlertData> {
private delayMinutesTextBox: sqlops.InputBoxComponent;
private delaySecondsTextBox: sqlops.InputBoxComponent;
constructor(ownerUri: string, alertInfo: sqlops.AgentAlertInfo = null) {
private databases: string[];
constructor(ownerUri: string, alertInfo: sqlops.AgentAlertInfo = undefined) {
super(ownerUri,
new AlertData(ownerUri, alertInfo),
alertInfo ? AlertDialog.EditDialogTitle : AlertDialog.CreateDialogTitle);
}
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.responseTab = sqlops.window.modelviewdialog.createTab(AlertDialog.ResponseTabText);
this.optionsTab = sqlops.window.modelviewdialog.createTab(AlertDialog.OptionsTabText);
this.initializeGeneralTab(databases);
this.initializeGeneralTab(this.databases);
this.initializeResponseTab();
this.initializeOptionsTab();
@@ -163,6 +169,7 @@ export class AlertDialog extends AgentDialog<AlertData> {
private initializeGeneralTab(databases: string[]) {
this.generalTab.registerContent(async view => {
// create controls
this.nameTextBox = view.modelBuilder.inputBox().component();
this.enabledCheckBox = view.modelBuilder.checkBox()
@@ -182,18 +189,51 @@ export class AlertDialog extends AgentDialog<AlertData> {
values: AlertDialog.AlertTypes
}).component();
this.severityRadioButton = view.modelBuilder.radioButton()
.withProperties({
value: 'serverity',
name: 'alertTypeOptions',
label: AlertDialog.SeverityLabel,
checked: true
}).component();
this.severityDropDown = view.modelBuilder.dropDown()
.withProperties({
value: AlertDialog.AlertSeverities[0],
values: AlertDialog.AlertSeverities
}).component();
this.errorNumberRadioButton = view.modelBuilder.radioButton()
.withProperties({
value: 'errorNumber',
name: 'alertTypeOptions',
label: AlertDialog.ErrorNumberLabel
}).component();
this.errorNumberTextBox = view.modelBuilder.inputBox().component();
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()
.withProperties({
label: AlertDialog.RaiseIfMessageContainsLabel
}).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()
.withFormItems([{
@@ -208,10 +248,24 @@ export class AlertDialog extends AgentDialog<AlertData> {
}, {
component: this.databaseDropDown,
title: AlertDialog.DatabaseLabel
}, {
},
{
component: this.severityRadioButton,
title: ''
},
{
component: this.severityDropDown,
title: AlertDialog.SeverityLabel
}, {
title: ''
},
{
component: this.errorNumberRadioButton,
title: ''
},
{
component: this.errorNumberTextBox,
title: ''
},
{
component: this.raiseAlertMessageCheckBox,
title: ''
}, {
@@ -222,8 +276,28 @@ export class AlertDialog extends AgentDialog<AlertData> {
await view.initializeModel(formModel);
// initialize control values
this.nameTextBox.value = this.model.name;
this.raiseAlertMessageTextBox.value = this.model.eventDescriptionKeyword;
this.typeDropDown.value = this.model.alertType;
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];
}
}
});
}
@@ -343,13 +417,21 @@ export class AlertDialog extends AgentDialog<AlertData> {
this.model.isEnabled = this.enabledCheckBox.checked;
this.model.alertType = this.getDropdownValue(this.typeDropDown);
this.model.databaseName = this.getDropdownValue(this.databaseDropDown);
this.model.severity = this.getSeverityNumber();
this.model.messageId = undefined;
let databaseName = this.getDropdownValue(this.databaseDropDown);
this.model.databaseName = (databaseName !== AlertDialog.AllDatabases) ? databaseName : undefined;
let raiseIfError = this.raiseAlertMessageCheckBox.checked;
if (raiseIfError) {
let messageText = this.raiseAlertMessageTextBox.value;
if (this.severityRadioButton.checked) {
this.model.severity = this.getSeverityNumber();
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 = '';
}
}
}

View File

@@ -14,7 +14,8 @@ export class JobDialog extends AgentDialog<JobData> {
// TODO: localize
// Top level
private static readonly DialogTitle: string = 'New Job';
private static readonly CreateDialogTitle: string = 'New Job';
private static readonly EditDialogTitle: string = 'Edit Job';
private readonly GeneralTabText: string = 'General';
private readonly StepsTabText: string = 'Steps';
private readonly SchedulesTabText: string = 'Schedules';
@@ -97,8 +98,11 @@ export class JobDialog extends AgentDialog<JobData> {
private alertsTable: sqlops.TableComponent;
private newAlertButton: sqlops.ButtonComponent;
constructor(ownerUri: string) {
super(ownerUri, new JobData(ownerUri), JobDialog.DialogTitle);
constructor(ownerUri: string, jobInfo: sqlops.AgentJobInfo = undefined) {
super(
ownerUri,
new JobData(ownerUri),
jobInfo ? JobDialog.EditDialogTitle : JobDialog.CreateDialogTitle);
}
protected async initializeDialog() {
@@ -159,6 +163,7 @@ export class JobDialog extends AgentDialog<JobData> {
await view.initializeModel(formModel);
this.nameTextBox.value = this.model.name;
this.ownerTextBox.value = this.model.defaultOwner;
this.categoryDropdown.values = this.model.jobCategories;
this.categoryDropdown.value = this.model.jobCategories[0];

View File

@@ -16,7 +16,8 @@ const localize = nls.loadMessageBundle();
export class OperatorDialog extends AgentDialog<OperatorData> {
// 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 NotificationsTabText: string = localize('createOperator.Notifications', 'Notifications');
@@ -65,8 +66,11 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
// Notification tab controls
private alertsTable: sqlops.TableComponent;
constructor(ownerUri: string) {
super(ownerUri, new OperatorData(ownerUri), OperatorDialog.DialogTitle);
constructor(ownerUri: string, operatorInfo: sqlops.AgentOperatorInfo = undefined) {
super(
ownerUri,
new OperatorData(ownerUri, operatorInfo),
operatorInfo ? OperatorDialog.EditDialogTitle : OperatorDialog.CreateDialogTitle);
}
protected async initializeDialog(dialog: sqlops.window.modelviewdialog.Dialog) {

View File

@@ -15,7 +15,8 @@ const localize = nls.loadMessageBundle();
export class ProxyDialog extends AgentDialog<ProxyData> {
// Top level
private static readonly DialogTitle: string = localize('createProxy.createAlert', 'Create Alert');
private static readonly CreateDialogTitle: string = localize('createProxy.createAlert', 'Create Alert');
private static readonly EditDialogTitle: string = localize('createProxy.createAlert', 'Create Alert');
private static readonly GeneralTabText: string = localize('createProxy.General', 'General');
// General tab strings
@@ -34,8 +35,11 @@ export class ProxyDialog extends AgentDialog<ProxyData> {
private descriptionTextBox: sqlops.InputBoxComponent;
private subsystemsTable: sqlops.TableComponent;
constructor(ownerUri: string) {
super(ownerUri, new ProxyData(ownerUri), ProxyDialog.DialogTitle);
constructor(ownerUri: string, proxyInfo: sqlops.AgentProxyInfo = undefined) {
super(
ownerUri,
new ProxyData(ownerUri, proxyInfo),
proxyInfo ? ProxyDialog.EditDialogTitle : ProxyDialog.CreateDialogTitle);
}
protected async initializeDialog(dialog: sqlops.window.modelviewdialog.Dialog) {
@@ -80,6 +84,10 @@ export class ProxyDialog extends AgentDialog<ProxyData> {
}]).withLayout({ width: '100%' }).component();
await view.initializeModel(formModel);
this.proxyNameTextBox.value = this.model.accountName;
this.credentialNameTextBox.value = this.model.credentialName;
this.descriptionTextBox.value = this.model.description;
});
}

View File

@@ -27,8 +27,8 @@ export class MainController {
* Activates the extension
*/
public activate(): void {
vscode.commands.registerCommand('agent.openCreateJobDialog', (ownerUri: string) => {
let dialog = new JobDialog(ownerUri);
vscode.commands.registerCommand('agent.openJobDialog', (ownerUri: string, jobInfo: sqlops.AgentJobInfo) => {
let dialog = new JobDialog(ownerUri, jobInfo);
dialog.openDialog();
});
vscode.commands.registerCommand('agent.openNewStepDialog', (ownerUri: string, jobId: string, server: string, stepId: number) => {
@@ -43,12 +43,12 @@ export class MainController {
let dialog = new AlertDialog(ownerUri, alertInfo);
dialog.openDialog();
});
vscode.commands.registerCommand('agent.openCreateOperatorDialog', (ownerUri: string) => {
let dialog = new OperatorDialog(ownerUri);
vscode.commands.registerCommand('agent.openOperatorDialog', (ownerUri: string, operatorInfo: sqlops.AgentOperatorInfo) => {
let dialog = new OperatorDialog(ownerUri, operatorInfo);
dialog.openDialog();
});
vscode.commands.registerCommand('agent.openCreateProxyDialog', (ownerUri: string) => {
let dialog = new ProxyDialog(ownerUri);
vscode.commands.registerCommand('agent.openProxyDialog', (ownerUri: string, proxyInfo: sqlops.AgentProxyInfo) => {
let dialog = new ProxyDialog(ownerUri, proxyInfo);
dialog.openDialog();
});
}

View File

@@ -15,7 +15,7 @@ const testOwnerUri = 'agent://testuri';
suite('Agent extension', () => {
test('Create Job Data', async () => {
let testAgentService = new TestAgentService();
let data = new JobData(testOwnerUri, testAgentService);
let data = new JobData(testOwnerUri, undefined, testAgentService);
data.save();
});
});

View File

@@ -145,11 +145,17 @@ export class EditJobAction extends Action {
public static ID = 'jobaction.editJob';
public static LABEL = nls.localize('jobaction.editJob', "Edit Job");
constructor() {
constructor(
@ICommandService private _commandService: ICommandService
) {
super(EditJobAction.ID, EditJobAction.LABEL);
}
public run(actionInfo: IJobActionInfo): TPromise<boolean> {
this._commandService.executeCommand(
'agent.openJobDialog',
actionInfo.ownerUri,
actionInfo.targetObject);
return TPromise.as(true);
}
}
@@ -324,11 +330,17 @@ export class EditOperatorAction extends Action {
public static ID = 'jobaction.editAlert';
public static LABEL = nls.localize('jobaction.editOperator', "Edit Operator");
constructor() {
constructor(
@ICommandService private _commandService: ICommandService
) {
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);
}
}
@@ -398,11 +410,17 @@ export class EditProxyAction extends Action {
public static ID = 'jobaction.editProxy';
public static LABEL = nls.localize('jobaction.editProxy', "Edit Proxy");
constructor() {
constructor(
@ICommandService private _commandService: ICommandService
) {
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);
}
}

View File

@@ -844,7 +844,7 @@ export class JobsViewComponent extends JobManagementView implements OnInit {
public openCreateJobDialog() {
let ownerUri: string = this._commonService.connectionManagementService.connectionInfo.ownerUri;
this._commandService.executeCommand('agent.openCreateJobDialog', ownerUri);
this._commandService.executeCommand('agent.openJobDialog', ownerUri);
}
public refreshJobs() {

View File

@@ -163,7 +163,7 @@ export class OperatorsViewComponent extends JobManagementView implements OnInit
public openCreateOperatorDialog() {
let ownerUri: string = this._commonService.connectionManagementService.connectionInfo.ownerUri;
this._commandService.executeCommand('agent.openCreateOperatorDialog', ownerUri);
this._commandService.executeCommand('agent.openOperatorDialog', ownerUri);
}
private refreshJobs() {

View File

@@ -164,7 +164,7 @@ export class ProxiesViewComponent extends JobManagementView implements OnInit {
public openCreateProxyDialog() {
let ownerUri: string = this._commonService.connectionManagementService.connectionInfo.ownerUri;
this._commandService.executeCommand('agent.openCreateProxyDialog', ownerUri);
this._commandService.executeCommand('agent.openProxyDialog', ownerUri);
}
private refreshJobs() {