mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-01 17:23:35 -05:00
Agent - Step Actions (#2779)
* fixed right click context menu bug in jobs view * added stepInfo and edit job WIP * show jobs in job edit * added schedule description on select schedule * fetch schedules during history and show in edit job * added alerts to job histories and show in edit * made history calls async * filter menus now close when esc is pressed * fixed bug where clicking on error row wouldnt populate job details * added functionality to delete steps in a job * added real time adding steps in edit job
This commit is contained in:
@@ -25,6 +25,8 @@ export interface IJobManagementService {
|
||||
getJobHistory(connectionUri: string, jobID: string): Thenable<sqlops.AgentJobHistoryResult>;
|
||||
deleteJob(connectionUri: string, job: sqlops.AgentJobInfo): Thenable<sqlops.ResultStatus>;
|
||||
|
||||
deleteJobStep(connectionUri: string, step: sqlops.AgentJobStepInfo): Thenable<sqlops.ResultStatus>;
|
||||
|
||||
getAlerts(connectionUri: string): Thenable<sqlops.AgentAlertsResult>;
|
||||
deleteAlert(connectionUri: string, alert: sqlops.AgentAlertInfo): Thenable<sqlops.ResultStatus>;
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ export enum JobActions {
|
||||
export interface IJobActionInfo {
|
||||
ownerUri: string;
|
||||
targetObject: any;
|
||||
jobHistoryComponent?: JobHistoryComponent;
|
||||
}
|
||||
|
||||
// Job actions
|
||||
@@ -230,6 +231,48 @@ export class NewStepAction extends Action {
|
||||
}
|
||||
}
|
||||
|
||||
export class DeleteStepAction extends Action {
|
||||
public static ID = 'jobaction.deleteStep';
|
||||
public static LABEL = nls.localize('jobaction.deleteStep', "Delete Step");
|
||||
|
||||
constructor(
|
||||
@INotificationService private _notificationService: INotificationService,
|
||||
@IJobManagementService private _jobService: IJobManagementService,
|
||||
@IInstantiationService private instantationService: IInstantiationService
|
||||
) {
|
||||
super(DeleteStepAction.ID, DeleteStepAction.LABEL);
|
||||
}
|
||||
|
||||
public run(actionInfo: IJobActionInfo): TPromise<boolean> {
|
||||
let self = this;
|
||||
let step = actionInfo.targetObject as sqlops.AgentJobStepInfo;
|
||||
let refreshAction = this.instantationService.createInstance(JobsRefreshAction);
|
||||
self._notificationService.prompt(
|
||||
Severity.Info,
|
||||
nls.localize('jobaction.deleteStepConfirm,', "Are you sure you'd like to delete the step '{0}'?", step.stepName),
|
||||
[{
|
||||
label: DeleteStepAction.LABEL,
|
||||
run: () => {
|
||||
self._jobService.deleteJobStep(actionInfo.ownerUri, actionInfo.targetObject).then(result => {
|
||||
if (!result || !result.success) {
|
||||
let errorMessage = nls.localize("jobaction.failedToDeleteStep", "Could not delete step '{0}'.\nError: {1}",
|
||||
step.stepName, result.errorMessage ? result.errorMessage : 'Unknown error');
|
||||
self._notificationService.error(errorMessage);
|
||||
} else {
|
||||
refreshAction.run(actionInfo.jobHistoryComponent);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, {
|
||||
label: DeleteAlertAction.CancelLabel,
|
||||
run: () => { }
|
||||
}]
|
||||
);
|
||||
return TPromise.as(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Alert Actions
|
||||
|
||||
export class NewAlertAction extends Action {
|
||||
|
||||
@@ -30,6 +30,7 @@ export class JobManagementService implements IJobManagementService {
|
||||
this._onDidChange.fire(void 0);
|
||||
}
|
||||
|
||||
// Jobs
|
||||
public getJobs(connectionUri: string): Thenable<sqlops.AgentJobsResult> {
|
||||
return this._runAction(connectionUri, (runner) => {
|
||||
return runner.getJobs(connectionUri);
|
||||
@@ -42,6 +43,27 @@ export class JobManagementService implements IJobManagementService {
|
||||
});
|
||||
}
|
||||
|
||||
public getJobHistory(connectionUri: string, jobID: string): Thenable<sqlops.AgentJobHistoryResult> {
|
||||
return this._runAction(connectionUri, (runner) => {
|
||||
return runner.getJobHistory(connectionUri, jobID);
|
||||
});
|
||||
}
|
||||
|
||||
public jobAction(connectionUri: string, jobName: string, action: string): Thenable<sqlops.ResultStatus> {
|
||||
return this._runAction(connectionUri, (runner) => {
|
||||
return runner.jobAction(connectionUri, jobName, action);
|
||||
});
|
||||
}
|
||||
|
||||
// Steps
|
||||
public deleteJobStep(connectionUri: string, stepInfo: sqlops.AgentJobStepInfo): Thenable<sqlops.ResultStatus> {
|
||||
return this._runAction(connectionUri, (runner) => {
|
||||
return runner.deleteJobStep(connectionUri, stepInfo);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Alerts
|
||||
public getAlerts(connectionUri: string): Thenable<sqlops.AgentAlertsResult> {
|
||||
return this._runAction(connectionUri, (runner) => {
|
||||
return runner.getAlerts(connectionUri);
|
||||
@@ -54,6 +76,7 @@ export class JobManagementService implements IJobManagementService {
|
||||
});
|
||||
}
|
||||
|
||||
// Operators
|
||||
public getOperators(connectionUri: string): Thenable<sqlops.AgentOperatorsResult> {
|
||||
return this._runAction(connectionUri, (runner) => {
|
||||
return runner.getOperators(connectionUri);
|
||||
@@ -66,6 +89,7 @@ export class JobManagementService implements IJobManagementService {
|
||||
});
|
||||
}
|
||||
|
||||
// Proxies
|
||||
public getProxies(connectionUri: string): Thenable<sqlops.AgentProxiesResult> {
|
||||
return this._runAction(connectionUri, (runner) => {
|
||||
return runner.getProxies(connectionUri);
|
||||
@@ -84,18 +108,6 @@ export class JobManagementService implements IJobManagementService {
|
||||
});
|
||||
}
|
||||
|
||||
public getJobHistory(connectionUri: string, jobID: string): Thenable<sqlops.AgentJobHistoryResult> {
|
||||
return this._runAction(connectionUri, (runner) => {
|
||||
return runner.getJobHistory(connectionUri, jobID);
|
||||
});
|
||||
}
|
||||
|
||||
public jobAction(connectionUri: string, jobName: string, action: string): Thenable<sqlops.ResultStatus> {
|
||||
return this._runAction(connectionUri, (runner) => {
|
||||
return runner.jobAction(connectionUri, jobName, action);
|
||||
});
|
||||
}
|
||||
|
||||
private _runAction<T>(uri: string, action: (handler: sqlops.AgentServicesProvider) => Thenable<T>): Thenable<T> {
|
||||
let providerId: string = this._connectionService.getProviderIdFromUri(uri);
|
||||
|
||||
|
||||
@@ -74,7 +74,6 @@ export class JobHistoryComponent extends JobManagementView implements OnInit {
|
||||
@Inject(forwardRef(() => CommonServiceInterface)) commonService: CommonServiceInterface,
|
||||
@Inject(forwardRef(() => AgentViewComponent)) private _agentViewComponent: AgentViewComponent,
|
||||
@Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService,
|
||||
@Inject(INotificationService) private _notificationService: INotificationService,
|
||||
@Inject(IInstantiationService) private instantiationService: IInstantiationService,
|
||||
@Inject(IContextMenuService) private contextMenuService: IContextMenuService,
|
||||
@Inject(IJobManagementService) private _jobManagementService: IJobManagementService,
|
||||
|
||||
@@ -20,7 +20,7 @@ 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';
|
||||
import { IJobManagementService } from 'sql/parts/jobManagement/common/interfaces';
|
||||
|
||||
export const JOBSTEPSVIEW_SELECTOR: string = 'jobstepsview-component';
|
||||
|
||||
@@ -36,7 +36,7 @@ export class JobStepsViewComponent extends JobManagementView implements OnInit,
|
||||
private _treeDataSource = new JobStepsViewDataSource();
|
||||
private _treeRenderer = new JobStepsViewRenderer();
|
||||
private _treeFilter = new JobStepsViewFilter();
|
||||
private static _pageSize = 1024;
|
||||
private _pageSize = 1024;
|
||||
|
||||
@ViewChild('table') private _tableContainer: ElementRef;
|
||||
|
||||
@@ -66,7 +66,7 @@ export class JobStepsViewComponent extends JobManagementView implements OnInit,
|
||||
}, { verticalScrollMode: ScrollbarVisibility.Visible });
|
||||
this._register(attachListStyler(this._tree, this.themeService));
|
||||
}
|
||||
this._tree.layout(500);
|
||||
this._tree.layout(this._pageSize);
|
||||
this._tree.setInput(new JobStepsViewModel());
|
||||
$('jobstepsview-component .steps-tree .monaco-tree').attr('tabIndex', '-1');
|
||||
$('jobstepsview-component .steps-tree .monaco-tree-row').attr('tabIndex', '0');
|
||||
|
||||
@@ -10,7 +10,6 @@ import * as TreeDefaults from 'vs/base/parts/tree/browser/treeDefaults';
|
||||
import { Promise, TPromise } from 'vs/base/common/winjs.base';
|
||||
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { AgentJobHistoryInfo } from 'sqlops';
|
||||
import { JobManagementUtilities } from 'sql/parts/jobManagement/common/jobManagementUtilities';
|
||||
|
||||
export class JobStepsViewRow {
|
||||
@@ -27,7 +26,6 @@ export class JobStepsViewModel {
|
||||
}
|
||||
|
||||
export class JobStepsViewController extends TreeDefaults.DefaultController {
|
||||
private _jobHistories: AgentJobHistoryInfo[];
|
||||
|
||||
protected onLeftClick(tree: tree.ITree, element: JobStepsViewRow, event: IMouseEvent, origin: string = 'mouse'): boolean {
|
||||
return true;
|
||||
@@ -37,14 +35,6 @@ export class JobStepsViewController extends TreeDefaults.DefaultController {
|
||||
return true;
|
||||
}
|
||||
|
||||
public set jobHistories(value: AgentJobHistoryInfo[]) {
|
||||
this._jobHistories = value;
|
||||
}
|
||||
|
||||
public get jobHistories(): AgentJobHistoryInfo[] {
|
||||
return this._jobHistories;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class JobStepsViewDataSource implements tree.IDataSource {
|
||||
|
||||
@@ -584,7 +584,12 @@ export class JobsViewComponent extends JobManagementView implements OnInit {
|
||||
self.jobHistories[job.jobId] = result.jobs;
|
||||
self._jobCacheObject.setJobHistory(job.jobId, result.jobs);
|
||||
let jobHistories = self._jobCacheObject.getJobHistory(job.jobId);
|
||||
let previousRuns = jobHistories.slice(jobHistories.length - 5, jobHistories.length);
|
||||
let previousRuns: sqlops.AgentJobHistoryInfo[];
|
||||
if (jobHistories.length >= 5) {
|
||||
previousRuns = jobHistories.slice(jobHistories.length - 5, jobHistories.length);
|
||||
} else {
|
||||
previousRuns = jobHistories;
|
||||
}
|
||||
self.createJobChart(job.jobId, previousRuns);
|
||||
if (self._agentViewComponent.expanded.has(job.jobId)) {
|
||||
let lastJobHistory = jobHistories[result.jobs.length - 1];
|
||||
@@ -645,12 +650,22 @@ export class JobsViewComponent extends JobManagementView implements OnInit {
|
||||
maxDuration = maxDuration === 0 ? 1 : maxDuration;
|
||||
let maxBarHeight: number = 24;
|
||||
let chartHeights = [];
|
||||
let zeroDurationJobCount = 0;
|
||||
for (let i = 0; i < jobHistories.length; i++) {
|
||||
let duration = jobHistories[i].runDuration;
|
||||
let chartHeight = (maxBarHeight * JobManagementUtilities.convertDurationToSeconds(duration)) / maxDuration;
|
||||
chartHeights.push(`${chartHeight}px`);
|
||||
if (chartHeight === 0) {
|
||||
zeroDurationJobCount++;
|
||||
}
|
||||
}
|
||||
// if the durations are all 0 secs, show minimal chart
|
||||
// instead of nothing
|
||||
if (zeroDurationJobCount === jobHistories.length) {
|
||||
return ['5px', '5px', '5px', '5px', '5px'];
|
||||
} else {
|
||||
return chartHeights;
|
||||
}
|
||||
return chartHeights;
|
||||
}
|
||||
|
||||
private expandJobs(start: boolean): void {
|
||||
|
||||
6
src/sql/sqlops.d.ts
vendored
6
src/sql/sqlops.d.ts
vendored
@@ -1537,9 +1537,9 @@ declare module 'sqlops' {
|
||||
getJobDefaults(ownerUri: string): Thenable<AgentJobDefaultsResult>;
|
||||
|
||||
// Job Step management methods
|
||||
createJobStep(ownerUri: string, jobInfo: AgentJobStepInfo): Thenable<CreateAgentJobStepResult>;
|
||||
updateJobStep(ownerUri: string, originalJobStepName: string, jobInfo: AgentJobStepInfo): Thenable<UpdateAgentJobStepResult>;
|
||||
deleteJobStep(ownerUri: string, jobInfo: AgentJobStepInfo): Thenable<ResultStatus>;
|
||||
createJobStep(ownerUri: string, stepInfo: AgentJobStepInfo): Thenable<CreateAgentJobStepResult>;
|
||||
updateJobStep(ownerUri: string, originalJobStepName: string, stepInfo: AgentJobStepInfo): Thenable<UpdateAgentJobStepResult>;
|
||||
deleteJobStep(ownerUri: string, stepInfo: AgentJobStepInfo): Thenable<ResultStatus>;
|
||||
|
||||
// Alert management methods
|
||||
getAlerts(ownerUri: string): Thenable<AgentAlertsResult>;
|
||||
|
||||
@@ -596,6 +596,13 @@ export class ExtHostDataProtocol extends ExtHostDataProtocolShape {
|
||||
throw this._resolveProvider<sqlops.AgentServicesProvider>(handle).deleteJob(ownerUri, job);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a job step
|
||||
*/
|
||||
$deleteJobStep(handle: number, ownerUri: string, step: sqlops.AgentJobStepInfo): Thenable<sqlops.ResultStatus> {
|
||||
throw this._resolveProvider<sqlops.AgentServicesProvider>(handle).deleteJobStep(ownerUri, step);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Agent Alerts list
|
||||
*/
|
||||
|
||||
@@ -359,6 +359,9 @@ export class MainThreadDataProtocol implements MainThreadDataProtocolShape {
|
||||
deleteJob(connectionUri: string, jobInfo: sqlops.AgentJobInfo): Thenable<sqlops.ResultStatus> {
|
||||
return self._proxy.$deleteJob(handle, connectionUri, jobInfo);
|
||||
},
|
||||
deleteJobStep(connectionUri: string, stepInfo: sqlops.AgentJobStepInfo): Thenable<sqlops.ResultStatus> {
|
||||
return self._proxy.$deleteJobStep(handle, connectionUri, stepInfo);
|
||||
},
|
||||
getAlerts(connectionUri: string): Thenable<sqlops.AgentAlertsResult> {
|
||||
return self._proxy.$getAlerts(handle, connectionUri);
|
||||
},
|
||||
|
||||
@@ -370,6 +370,11 @@ export abstract class ExtHostDataProtocolShape {
|
||||
*/
|
||||
$deleteJob(handle: number, ownerUri: string, job: sqlops.AgentJobInfo): Thenable<sqlops.ResultStatus> { throw ni(); }
|
||||
|
||||
/**
|
||||
* Deletes a job step
|
||||
*/
|
||||
$deleteJobStep(handle: number, ownerUri: string, step: sqlops.AgentJobStepInfo): Thenable<sqlops.ResultStatus> { throw ni(); }
|
||||
|
||||
/**
|
||||
* Get Agent Alerts list
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user