Agent feature - ability to start at step (#3483)

* added ability to start at certain step

* fixed width for scrollbar

* localized string
This commit is contained in:
Aditya Bist
2018-12-06 17:43:26 -08:00
committed by Karl Burtram
parent f7809ec3a7
commit ec196f57bb
4 changed files with 112 additions and 74 deletions

View File

@@ -45,6 +45,7 @@ export class JobData implements IAgentDialogData {
public jobSchedules: sqlops.AgentJobScheduleInfo[]; public jobSchedules: sqlops.AgentJobScheduleInfo[];
public alerts: sqlops.AgentAlertInfo[]; public alerts: sqlops.AgentAlertInfo[];
public jobId: string; public jobId: string;
public startStepId: number;
constructor( constructor(
ownerUri: string, ownerUri: string,
@@ -60,10 +61,11 @@ export class JobData implements IAgentDialogData {
this.category = jobInfo.category; this.category = jobInfo.category;
this.description = jobInfo.description; this.description = jobInfo.description;
this.enabled = jobInfo.enabled; this.enabled = jobInfo.enabled;
this.jobSteps = jobInfo.JobSteps; this.jobSteps = jobInfo.jobSteps;
this.jobSchedules = jobInfo.JobSchedules; this.jobSchedules = jobInfo.jobSchedules;
this.alerts = jobInfo.Alerts; this.alerts = jobInfo.alerts;
this.jobId = jobInfo.jobId; this.jobId = jobInfo.jobId;
this.startStepId = jobInfo.startStepId;
} }
} }
@@ -141,17 +143,17 @@ export class JobData implements IAgentDialogData {
name: this.name, name: this.name,
owner: this.owner, owner: this.owner,
description: this.description, description: this.description,
EmailLevel: this.emailLevel, emailLevel: this.emailLevel,
PageLevel: this.pageLevel, pageLevel: this.pageLevel,
EventLogLevel: this.eventLogLevel, eventLogLevel: this.eventLogLevel,
DeleteLevel: this.deleteLevel, deleteLevel: this.deleteLevel,
OperatorToEmail: this.operatorToEmail, operatorToEmail: this.operatorToEmail,
OperatorToPage: this.operatorToPage, operatorToPage: this.operatorToPage,
enabled: this.enabled, enabled: this.enabled,
category: this.category, category: this.category,
Alerts: this.alerts, alerts: this.alerts,
JobSchedules: this.jobSchedules, jobSchedules: this.jobSchedules,
JobSteps: this.jobSteps, jobSteps: this.jobSteps,
// The properties below are not collected from UI // The properties below are not collected from UI
// We could consider using a seperate class for create job request // We could consider using a seperate class for create job request
// //
@@ -166,7 +168,8 @@ export class JobData implements IAgentDialogData {
categoryType: 1, // LocalJob, hard-coding the value, corresponds to the target tab in SSMS categoryType: 1, // LocalJob, hard-coding the value, corresponds to the target tab in SSMS
lastRun: '', lastRun: '',
nextRun: '', nextRun: '',
jobId: this.jobId jobId: this.jobId,
startStepId: this.startStepId
}; };
} }
} }

View File

@@ -42,11 +42,12 @@ export class JobDialog extends AgentDialog<JobData> {
private readonly StepsTable_TypeColumnString: string = localize('jobDialog.type', 'Type'); private readonly StepsTable_TypeColumnString: string = localize('jobDialog.type', 'Type');
private readonly StepsTable_SuccessColumnString: string = localize('jobDialog.onSuccess', 'On Success'); private readonly StepsTable_SuccessColumnString: string = localize('jobDialog.onSuccess', 'On Success');
private readonly StepsTable_FailureColumnString: string = localize('jobDialog.onFailure', 'On Failure'); private readonly StepsTable_FailureColumnString: string = localize('jobDialog.onFailure', 'On Failure');
private readonly NewStepButtonString: string = localize('jobDialog.new', 'New...'); private readonly NewStepButtonString: string = localize('jobDialog.new', 'New Step');
private readonly EditStepButtonString: string = localize('jobDialog.edit', 'Edit'); private readonly EditStepButtonString: string = localize('jobDialog.edit', 'Edit Step');
private readonly DeleteStepButtonString: string = localize('jobDialog.delete', 'Delete'); private readonly DeleteStepButtonString: string = localize('jobDialog.delete', 'Delete Step');
private readonly MoveStepUpButtonString: string = localize('jobDialog.moveUp', 'Move Step Up'); private readonly MoveStepUpButtonString: string = localize('jobDialog.moveUp', 'Move Step Up');
private readonly MoveStepDownButtonString: string = localize('jobDialog.moveDown', 'Move Step Down'); private readonly MoveStepDownButtonString: string = localize('jobDialog.moveDown', 'Move Step Down');
private readonly StartStepDropdownString: string = localize('jobDialog.startStepAt', 'Start step');
// Notifications tab strings // Notifications tab strings
private readonly NotificationsTabTopLabelString: string = localize('jobDialog.notificationsTabTop', 'Actions to perform when the job completes'); private readonly NotificationsTabTopLabelString: string = localize('jobDialog.notificationsTabTop', 'Actions to perform when the job completes');
@@ -105,6 +106,7 @@ export class JobDialog extends AgentDialog<JobData> {
private eventLogConditionDropdown: sqlops.DropDownComponent; private eventLogConditionDropdown: sqlops.DropDownComponent;
private deleteJobCheckBox: sqlops.CheckBoxComponent; private deleteJobCheckBox: sqlops.CheckBoxComponent;
private deleteJobConditionDropdown: sqlops.DropDownComponent; private deleteJobConditionDropdown: sqlops.DropDownComponent;
private startStepDropdown: sqlops.DropDownComponent;
// Schedule tab controls // Schedule tab controls
private schedulesTable: sqlops.TableComponent; private schedulesTable: sqlops.TableComponent;
@@ -119,6 +121,7 @@ export class JobDialog extends AgentDialog<JobData> {
private steps: sqlops.AgentJobStepInfo[]; private steps: sqlops.AgentJobStepInfo[];
private schedules: sqlops.AgentJobScheduleInfo[]; private schedules: sqlops.AgentJobScheduleInfo[];
private alerts: sqlops.AgentAlertInfo[] = []; private alerts: sqlops.AgentAlertInfo[] = [];
private startStepDropdownValues: sqlops.CategoryValue[] = [];
constructor(ownerUri: string, jobInfo: sqlops.AgentJobInfo = undefined) { constructor(ownerUri: string, jobInfo: sqlops.AgentJobInfo = undefined) {
super( super(
@@ -223,13 +226,20 @@ export class JobDialog extends AgentDialog<JobData> {
this.StepsTable_FailureColumnString this.StepsTable_FailureColumnString
], ],
data: data, data: data,
height: 750 height: 650
}).component(); }).component();
this.startStepDropdown = view.modelBuilder.dropDown().withProperties({ width: 180 }).component();
this.startStepDropdown.enabled = this.steps.length > 1 ? true : false;
this.steps.forEach((step) => {
this.startStepDropdownValues.push({ displayName: step.id + ': ' + step.stepName, name: step.id.toString() });
});
this.startStepDropdown.values = this.startStepDropdownValues;
this.moveStepUpButton = view.modelBuilder.button() this.moveStepUpButton = view.modelBuilder.button()
.withProperties({ .withProperties({
label: this.MoveStepUpButtonString, label: this.MoveStepUpButtonString,
width: 80 width: 120
}).component(); }).component();
this.moveStepDownButton = view.modelBuilder.button() this.moveStepDownButton = view.modelBuilder.button()
@@ -243,7 +253,7 @@ export class JobDialog extends AgentDialog<JobData> {
this.newStepButton = view.modelBuilder.button().withProperties({ this.newStepButton = view.modelBuilder.button().withProperties({
label: this.NewStepButtonString, label: this.NewStepButtonString,
width: 80 width: 140
}).component(); }).component();
let stepDialog = new JobStepDialog(this.model.ownerUri, '' , this.model, null, true); let stepDialog = new JobStepDialog(this.model.ownerUri, '' , this.model, null, true);
@@ -251,6 +261,11 @@ export class JobDialog extends AgentDialog<JobData> {
let stepInfo = JobStepData.convertToAgentJobStepInfo(step); let stepInfo = JobStepData.convertToAgentJobStepInfo(step);
this.steps.push(stepInfo); this.steps.push(stepInfo);
this.stepsTable.data = this.convertStepsToData(this.steps); this.stepsTable.data = this.convertStepsToData(this.steps);
this.startStepDropdownValues = [];
this.steps.forEach((step) => {
this.startStepDropdownValues.push({ displayName: step.id + ': ' + step.stepName, name: step.id.toString() });
});
this.startStepDropdown.values = this.startStepDropdownValues;
}); });
this.newStepButton.onDidClick((e)=>{ this.newStepButton.onDidClick((e)=>{
if (this.nameTextBox.value && this.nameTextBox.value.length > 0) { if (this.nameTextBox.value && this.nameTextBox.value.length > 0) {
@@ -263,12 +278,12 @@ export class JobDialog extends AgentDialog<JobData> {
this.editStepButton = view.modelBuilder.button().withProperties({ this.editStepButton = view.modelBuilder.button().withProperties({
label: this.EditStepButtonString, label: this.EditStepButtonString,
width: 80 width: 140
}).component(); }).component();
this.deleteStepButton = view.modelBuilder.button().withProperties({ this.deleteStepButton = view.modelBuilder.button().withProperties({
label: this.DeleteStepButtonString, label: this.DeleteStepButtonString,
width: 80 width: 140
}).component(); }).component();
this.stepsTable.enabled = false; this.stepsTable.enabled = false;
@@ -276,41 +291,31 @@ export class JobDialog extends AgentDialog<JobData> {
this.deleteStepButton.enabled = false; this.deleteStepButton.enabled = false;
this.moveStepUpButton.onDidClick(() => { this.moveStepUpButton.onDidClick(() => {
if (this.stepsTable.selectedRows.length === 1) { let rowNumber = this.stepsTable.selectedRows[0];
let rowNumber = this.stepsTable.selectedRows[0]; let previousRow = rowNumber - 1;
// if it's not the first step let previousStep = this.steps[previousRow];
if (rowNumber !== 0) { let previousStepId = this.steps[previousRow].id;
let previousRow = rowNumber - 1; let currentStep = this.steps[rowNumber];
let previousStep = this.steps[previousRow]; let currentStepId = this.steps[rowNumber].id;
let previousStepId = this.steps[previousRow].id; this.steps[previousRow] = currentStep;
let currentStep = this.steps[rowNumber]; this.steps[rowNumber] = previousStep;
let currentStepId = this.steps[rowNumber].id; this.stepsTable.data = this.convertStepsToData(this.steps);
this.steps[previousRow] = currentStep; this.steps[previousRow].id = previousStepId;
this.steps[rowNumber] = previousStep; this.steps[rowNumber].id = currentStepId;
this.stepsTable.data = this.convertStepsToData(this.steps);
this.steps[previousRow].id = previousStepId;
this.steps[rowNumber].id = currentStepId;
}
}
}); });
this.moveStepDownButton.onDidClick(() => { this.moveStepDownButton.onDidClick(() => {
if (this.stepsTable.selectedRows.length === 1) { let rowNumber = this.stepsTable.selectedRows[0];
let rowNumber = this.stepsTable.selectedRows[0]; let nextRow = rowNumber + 1;
// if it's not the last step let nextStep = this.steps[nextRow];
if (this.steps.length !== rowNumber + 1) { let nextStepId = this.steps[nextRow].id;
let nextRow = rowNumber + 1; let currentStep = this.steps[rowNumber];
let nextStep = this.steps[nextRow]; let currentStepId = this.steps[rowNumber].id;
let nextStepId = this.steps[nextRow].id; this.steps[nextRow] = currentStep;
let currentStep = this.steps[rowNumber]; this.steps[rowNumber] = nextStep;
let currentStepId = this.steps[rowNumber].id; this.stepsTable.data = this.convertStepsToData(this.steps);
this.steps[nextRow] = currentStep; this.steps[nextRow].id = nextStepId;
this.steps[rowNumber] = nextStep; this.steps[rowNumber].id = currentStepId;
this.stepsTable.data = this.convertStepsToData(this.steps);
this.steps[nextRow].id = nextStepId;
this.steps[rowNumber].id = currentStepId;
}
}
}); });
this.editStepButton.onDidClick(() => { this.editStepButton.onDidClick(() => {
@@ -326,6 +331,12 @@ export class JobDialog extends AgentDialog<JobData> {
} }
} }
this.stepsTable.data = this.convertStepsToData(this.steps); this.stepsTable.data = this.convertStepsToData(this.steps);
this.startStepDropdownValues = [];
this.steps.forEach((step) => {
this.startStepDropdownValues.push({ displayName: step.id + ': ' + step.stepName, name: step.id.toString() });
});
this.startStepDropdown.values = this.startStepDropdownValues;
}); });
editStepDialog.openDialog(); editStepDialog.openDialog();
} }
@@ -342,30 +353,52 @@ export class JobDialog extends AgentDialog<JobData> {
delete steps[rowNumber]; delete steps[rowNumber];
let data = this.convertStepsToData(steps); let data = this.convertStepsToData(steps);
this.stepsTable.data = data; this.stepsTable.data = data;
this.startStepDropdownValues = [];
this.steps.forEach((step) => {
this.startStepDropdownValues.push({ displayName: step.id + ': ' + step.stepName, name: step.id.toString() });
});
this.startStepDropdown.values = this.startStepDropdownValues;
} }
}); });
}); });
} }
}); });
this.stepsTable.onRowSelected(() => { this.stepsTable.onRowSelected((row) => {
// only let edit or delete steps if there's // only let edit or delete steps if there's
// one step selection // one step selection
if (this.stepsTable.selectedRows.length === 1) { if (this.stepsTable.selectedRows.length === 1) {
this.moveStepUpButton.enabled = true; let rowNumber = this.stepsTable.selectedRows[0];
this.moveStepDownButton.enabled = true; // if it's not the last step
if (this.steps.length !== rowNumber + 1) {
this.moveStepDownButton.enabled = true;
}
// if it's not the first step
if (rowNumber !== 0) {
this.moveStepUpButton.enabled = true;
}
this.deleteStepButton.enabled = true; this.deleteStepButton.enabled = true;
this.editStepButton.enabled = true; this.editStepButton.enabled = true;
} }
}); });
let stepMoveContainer = this.createRowContainer(view).withItems([this.startStepDropdown, this.moveStepUpButton, this.moveStepDownButton]).component();
let formModel = view.modelBuilder.formContainer() let stepsDialogContainer = this.createRowContainer(view).withItems([this.newStepButton, this.editStepButton, this.deleteStepButton]).component();
.withFormItems([{ let formModel = view.modelBuilder.formContainer().withFormItems([
{
component: this.stepsTable, component: this.stepsTable,
title: this.JobStepsTopLabelString, title: this.JobStepsTopLabelString
actions: [this.moveStepUpButton, this.moveStepDownButton, this.newStepButton, this.editStepButton, this.deleteStepButton] },
}]).withLayout({ width: '100%' }).component(); {
component: stepMoveContainer,
title: this.StartStepDropdownString
},
{
component: stepsDialogContainer,
title: ''
}
]).withLayout({ width: '100%' }).component();
await view.initializeModel(formModel); await view.initializeModel(formModel);
this.setConditionDropdownSelectedValue(this.startStepDropdown, this.model.startStepId);
}); });
} }
@@ -628,6 +661,7 @@ export class JobDialog extends AgentDialog<JobData> {
this.model.pageLevel = this.getActualConditionValue(this.pagerCheckBox, this.pagerConditionDropdown); this.model.pageLevel = this.getActualConditionValue(this.pagerCheckBox, this.pagerConditionDropdown);
this.model.eventLogLevel = this.getActualConditionValue(this.eventLogCheckBox, this.eventLogConditionDropdown); this.model.eventLogLevel = this.getActualConditionValue(this.eventLogCheckBox, this.eventLogConditionDropdown);
this.model.deleteLevel = this.getActualConditionValue(this.deleteJobCheckBox, this.deleteJobConditionDropdown); this.model.deleteLevel = this.getActualConditionValue(this.deleteJobCheckBox, this.deleteJobConditionDropdown);
this.model.startStepId = +this.getDropdownValue(this.startStepDropdown);
if (!this.model.jobSteps) { if (!this.model.jobSteps) {
this.model.jobSteps = []; this.model.jobSteps = [];
} }

View File

@@ -937,19 +937,19 @@ export class JobsViewComponent extends JobManagementView implements OnInit, OnDe
// add steps // add steps
if (this.jobSteps && this.jobSteps[jobId]) { if (this.jobSteps && this.jobSteps[jobId]) {
let steps = this.jobSteps[jobId]; let steps = this.jobSteps[jobId];
job[0].JobSteps = steps; job[0].jobSteps = steps;
} }
// add schedules // add schedules
if (this.jobSchedules && this.jobSchedules[jobId]) { if (this.jobSchedules && this.jobSchedules[jobId]) {
let schedules = this.jobSchedules[jobId]; let schedules = this.jobSchedules[jobId];
job[0].JobSchedules = schedules; job[0].jobSchedules = schedules;
} }
// add alerts // add alerts
if (this.jobAlerts && this.jobAlerts[jobId]) { if (this.jobAlerts && this.jobAlerts[jobId]) {
let alerts = this.jobAlerts[jobId]; let alerts = this.jobAlerts[jobId];
job[0].Alerts = alerts; job[0].alerts = alerts;
} }
return job && job.length > 0 ? job[0] : undefined; return job && job.length > 0 ? job[0] : undefined;
} }

19
src/sql/sqlops.d.ts vendored
View File

@@ -1300,15 +1300,16 @@ declare module 'sqlops' {
lastRun: string; lastRun: string;
nextRun: string; nextRun: string;
jobId: string; jobId: string;
EmailLevel: JobCompletionActionCondition; startStepId: number;
PageLevel: JobCompletionActionCondition; emailLevel: JobCompletionActionCondition;
EventLogLevel: JobCompletionActionCondition; pageLevel: JobCompletionActionCondition;
DeleteLevel: JobCompletionActionCondition; eventLogLevel: JobCompletionActionCondition;
OperatorToEmail: string; deleteLevel: JobCompletionActionCondition;
OperatorToPage: string; operatorToEmail: string;
JobSteps: AgentJobStepInfo[]; operatorToPage: string;
JobSchedules: AgentJobScheduleInfo[]; jobSteps: AgentJobStepInfo[];
Alerts: AgentAlertInfo[]; jobSchedules: AgentJobScheduleInfo[];
alerts: AgentAlertInfo[];
} }
export interface AgentJobScheduleInfo { export interface AgentJobScheduleInfo {