diff --git a/extensions/mssql/src/config.json b/extensions/mssql/src/config.json
index 80bf8df933..07822768fa 100644
--- a/extensions/mssql/src/config.json
+++ b/extensions/mssql/src/config.json
@@ -16,4 +16,4 @@
},
"installDirectory": "../sqltoolsservice/{#platform#}/{#version#}",
"executableFiles": ["MicrosoftSqlToolsServiceLayer.exe", "MicrosoftSqlToolsServiceLayer"]
-}
+}
\ No newline at end of file
diff --git a/src/sql/parts/dashboard/dashboard.module.ts b/src/sql/parts/dashboard/dashboard.module.ts
index a02e67064b..d046b9c72a 100644
--- a/src/sql/parts/dashboard/dashboard.module.ts
+++ b/src/sql/parts/dashboard/dashboard.module.ts
@@ -51,7 +51,7 @@ import { JobHistoryComponent } from 'sql/parts/jobManagement/views/jobHistory.co
let baseComponents = [DashboardHomeContainer, DashboardComponent, DashboardWidgetWrapper, DashboardWebviewContainer,
DashboardWidgetContainer, DashboardGridContainer, DashboardErrorContainer, DashboardNavSection, WebviewContent, WidgetContent,
ComponentHostDirective, BreadcrumbComponent, ControlHostContent, DashboardControlHostContainer,
- JobsViewComponent, AgentViewComponent, JobHistoryComponent];
+ JobsViewComponent, AgentViewComponent, JobHistoryComponent, JobStepsViewComponent];
/* Panel */
import { PanelModule } from 'sql/base/browser/ui/panel/panel.module';
@@ -68,6 +68,7 @@ import { ExplorerWidget } from 'sql/parts/dashboard/widgets/explorer/explorerWid
import { TasksWidget } from 'sql/parts/dashboard/widgets/tasks/tasksWidget.component';
import { InsightsWidget } from 'sql/parts/dashboard/widgets/insights/insightsWidget.component';
import { WebviewWidget } from 'sql/parts/dashboard/widgets/webview/webviewWidget.component';
+import { JobStepsViewComponent } from '../jobManagement/views/jobStepsView.component';
let widgetComponents = [
PropertiesWidgetComponent,
diff --git a/src/sql/parts/jobManagement/views/jobHistory.component.html b/src/sql/parts/jobManagement/views/jobHistory.component.html
index 43da359029..96b92c9947 100644
--- a/src/sql/parts/jobManagement/views/jobHistory.component.html
+++ b/src/sql/parts/jobManagement/views/jobHistory.component.html
@@ -106,7 +106,15 @@
Status:
-
+ {{_runStatus}}
+ |
+
+
+ |
+ Job ID:
+ |
+
+ {{agentJobHistoryInfo?.jobId}}
|
@@ -127,10 +135,10 @@
|
- Log:
+ Server:
|
-
+ {{agentJobHistoryInfo?.server}}
|
@@ -138,7 +146,7 @@
SQL message ID:
|
-
+ {{agentJobHistoryInfo?.sqlMessageId}}
|
@@ -150,6 +158,7 @@
+
diff --git a/src/sql/parts/jobManagement/views/jobHistory.component.ts b/src/sql/parts/jobManagement/views/jobHistory.component.ts
index ebc5775a04..9331a399a0 100644
--- a/src/sql/parts/jobManagement/views/jobHistory.component.ts
+++ b/src/sql/parts/jobManagement/views/jobHistory.component.ts
@@ -5,7 +5,8 @@
import 'vs/css!./jobHistory';
-import { OnInit, Component, Inject, forwardRef, ElementRef, ChangeDetectorRef, OnDestroy, ViewChild, Input, Injectable } from '@angular/core';
+import { OnInit, OnChanges, Component, Inject, forwardRef, ElementRef, ChangeDetectorRef, OnDestroy, ViewChild, Input, Injectable } from '@angular/core';
+import { AgentJobHistoryInfo, AgentJobInfo } from 'sqlops';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { attachListStyler } from 'vs/platform/theme/common/styler';
import { Tree } from 'vs/base/parts/tree/browser/treeImpl';
@@ -18,8 +19,8 @@ import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboar
import { AgentViewComponent } from 'sql/parts/jobManagement/agent/agentView.component';
import { JobHistoryController, JobHistoryDataSource,
JobHistoryRenderer, JobHistoryFilter, JobHistoryModel, JobHistoryRow } from 'sql/parts/jobManagement/views/jobHistoryTree';
-import { AgentJobHistoryInfo, AgentJobInfo } from 'sqlops';
-
+import { JobStepsViewComponent } from 'sql/parts/jobManagement/views/jobStepsView.component';
+import { JobStepsViewRow } from './jobStepsViewTree';
export const DASHBOARD_SELECTOR: string = 'jobhistory-component';
@@ -27,7 +28,7 @@ export const DASHBOARD_SELECTOR: string = 'jobhistory-component';
selector: DASHBOARD_SELECTOR,
templateUrl: decodeURI(require.toUrl('./jobHistory.component.html'))
})
-export class JobHistoryComponent extends Disposable implements OnInit, OnDestroy {
+export class JobHistoryComponent extends Disposable implements OnInit {
private _jobManagementService: IJobManagementService;
private _tree: Tree;
@@ -42,8 +43,11 @@ export class JobHistoryComponent extends Disposable implements OnInit, OnDestroy
@Input() public jobId: string = undefined;
@Input() public agentJobHistoryInfo: AgentJobHistoryInfo = undefined;
- private prevJobId: string = undefined;
- private isVisible: boolean = false;
+ private _prevJobId: string = undefined;
+ private _isVisible: boolean = false;
+ private _stepRows: JobStepsViewRow[] = [];
+ private _showSteps: boolean = false;
+ private _runStatus: string = undefined;
constructor(
@@ -65,23 +69,31 @@ export class JobHistoryComponent extends Disposable implements OnInit, OnDestroy
const isDoubleClick = (origin === 'mouse' && event.detail === 2);
// Cancel Event
const isMouseDown = event && event.browserEvent && event.browserEvent.type === 'mousedown';
-
if (!isMouseDown) {
event.preventDefault(); // we cannot preventDefault onMouseDown because this would break DND otherwise
}
-
event.stopPropagation();
-
tree.setFocus(element, payload);
-
if (element && isDoubleClick) {
event.preventDefault(); // focus moves to editor, we need to prevent default
} else {
tree.setFocus(element, payload);
tree.setSelection([element], payload);
self.agentJobHistoryInfo = self._treeController.jobHistories.filter(history => history.instanceId === element.instanceID)[0];
- self.agentJobHistoryInfo.runDate = self.formatTime(self.agentJobHistoryInfo.runDate);
- self._cd.detectChanges();
+ if (self.agentJobHistoryInfo) {
+ self.agentJobHistoryInfo.runDate = self.formatTime(self.agentJobHistoryInfo.runDate);
+ self._stepRows = self.agentJobHistoryInfo.steps.map(step => {
+ let stepViewRow = new JobStepsViewRow();
+ stepViewRow.message = step.message;
+ stepViewRow.runStatus = JobHistoryRow.convertToStatusString(self.agentJobHistoryInfo.runStatus);
+ self._runStatus = stepViewRow.runStatus;
+ stepViewRow.stepName = step.stepName;
+ stepViewRow.stepID = step.stepId.toString();
+ return stepViewRow;
+ });
+ this._showSteps = true;
+ self._cd.detectChanges();
+ }
}
return true;
};
@@ -95,14 +107,11 @@ export class JobHistoryComponent extends Disposable implements OnInit, OnDestroy
this._tree.layout(1024);
}
- ngOnDestroy() {
- }
-
ngAfterContentChecked() {
- if (this.isVisible === false && this._tableContainer.nativeElement.offsetParent !== null) {
- if (this.prevJobId !== this.jobId) {
+ if (this._isVisible === false && this._tableContainer.nativeElement.offsetParent !== null) {
+ if (this._prevJobId !== this.jobId) {
this.loadHistory();
- this.prevJobId = this.jobId;
+ this._prevJobId = this.jobId;
}
}
}
@@ -139,7 +148,7 @@ export class JobHistoryComponent extends Disposable implements OnInit, OnDestroy
}
private goToJobs(): void {
- this.isVisible = false;
+ this._isVisible = false;
this._agentViewComponent.showHistory = false;
}
@@ -154,5 +163,9 @@ export class JobHistoryComponent extends Disposable implements OnInit, OnDestroy
private formatTime(time: string): string {
return time.replace('T', ' ');
}
+
+ public showSteps(): boolean {
+ return this._showSteps;
+ }
}
diff --git a/src/sql/parts/jobManagement/views/jobHistory.css b/src/sql/parts/jobManagement/views/jobHistory.css
index 5ff2b29c6e..68cec7e72d 100644
--- a/src/sql/parts/jobManagement/views/jobHistory.css
+++ b/src/sql/parts/jobManagement/views/jobHistory.css
@@ -153,6 +153,11 @@ input#accordion:checked ~ .accordion-content {
padding: 10px;
}
+.accordion-content #col1,
+.accordion-content #col3 {
+ font-weight: bold;
+}
+
.accordion-content #col2 {
padding-right: 300px;
}
@@ -171,6 +176,7 @@ table.step-list tr.step-row td {
border-left: 3px solid #444444;
padding-left: 10px;
height: 100%;
+ width: 90%;
}
.history-details > .job-steps {
@@ -203,15 +209,15 @@ table.step-list tr.step-row td {
display: inline-block;
}
-.passed {
+.job-passed {
background: green;
}
-.failed {
+.job-failed {
background: red;
}
-.unknown {
+.job-unknown {
background: yellow;
}
@@ -219,3 +225,8 @@ table.step-list tr.step-row td {
padding-left: 50px;
width: 140px;
}
+
+.steps-tree .monaco-tree .monaco-tree-row {
+ white-space: normal;
+ height: 40px !important;
+}
\ No newline at end of file
diff --git a/src/sql/parts/jobManagement/views/jobHistoryTree.ts b/src/sql/parts/jobManagement/views/jobHistoryTree.ts
index de2f3e484f..80e44d55a3 100644
--- a/src/sql/parts/jobManagement/views/jobHistoryTree.ts
+++ b/src/sql/parts/jobManagement/views/jobHistoryTree.ts
@@ -145,11 +145,11 @@ export class JobHistoryRenderer implements tree.IRenderer {
templateData.label.innerText = element.runDate + '\t\t\t' + element.runStatus;
let statusClass: string;
if (element.runStatus === 'Succeeded') {
- statusClass = ' passed';
+ statusClass = ' job-passed';
} else if (element.runStatus === 'Failed') {
- statusClass = ' failed';
+ statusClass = ' job-failed';
} else {
- statusClass = ' unknown';
+ statusClass = ' job-unknown';
}
this._statusIcon.className += statusClass;
}
diff --git a/src/sql/parts/jobManagement/views/jobStepsView.component.html b/src/sql/parts/jobManagement/views/jobStepsView.component.html
new file mode 100644
index 0000000000..a6f68f325e
--- /dev/null
+++ b/src/sql/parts/jobManagement/views/jobStepsView.component.html
@@ -0,0 +1,22 @@
+
+
+Steps
+
+
+ |
+ Step ID
+ |
+
+ Step Name
+ |
+
+ Message
+ |
+
+
+
\ No newline at end of file
diff --git a/src/sql/parts/jobManagement/views/jobStepsView.component.ts b/src/sql/parts/jobManagement/views/jobStepsView.component.ts
new file mode 100644
index 0000000000..f20d3cbabc
--- /dev/null
+++ b/src/sql/parts/jobManagement/views/jobStepsView.component.ts
@@ -0,0 +1,80 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the Source EULA. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import 'vs/css!./jobStepsView';
+
+import { OnInit, Component, Inject, forwardRef, ElementRef, ChangeDetectorRef, OnChanges, ViewChild, Input, Injectable } from '@angular/core';
+import { IThemeService } from 'vs/platform/theme/common/themeService';
+import { attachListStyler } from 'vs/platform/theme/common/styler';
+import { Tree } from 'vs/base/parts/tree/browser/treeImpl';
+import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
+import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
+import { IBootstrapService, BOOTSTRAP_SERVICE_ID } from 'sql/services/bootstrap/bootstrapService';
+import { IJobManagementService } from '../common/interfaces';
+import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service';
+import { AgentJobHistoryInfo } from 'sqlops';
+import { JobStepsViewController, JobStepsViewDataSource, JobStepsViewFilter,
+ JobStepsViewRenderer, JobStepsViewRow, JobStepsViewModel} from 'sql/parts/jobManagement/views/jobStepsViewTree';
+
+export const JOBSTEPSVIEW_SELECTOR: string = 'jobstepsview-component';
+
+@Component({
+ selector: JOBSTEPSVIEW_SELECTOR,
+ templateUrl: decodeURI(require.toUrl('./jobStepsView.component.html'))
+})
+export class JobStepsViewComponent extends Disposable implements OnInit, OnChanges {
+
+ private _jobManagementService: IJobManagementService;
+ private _tree: Tree;
+ private _treeController = new JobStepsViewController();
+ private _treeDataSource = new JobStepsViewDataSource();
+ private _treeRenderer = new JobStepsViewRenderer();
+ private _treeFilter = new JobStepsViewFilter();
+ private static _pageSize = 1024;
+
+ @ViewChild('table') private _tableContainer: ElementRef;
+
+ @Input() public stepRows: JobStepsViewRow[] = [];
+
+ constructor(
+ @Inject(BOOTSTRAP_SERVICE_ID) private bootstrapService: IBootstrapService,
+ @Inject(forwardRef(() => ElementRef)) el: ElementRef,
+ @Inject(forwardRef(() => ChangeDetectorRef)) private _cd: ChangeDetectorRef,
+ @Inject(forwardRef(() => DashboardServiceInterface)) private _dashboardService: DashboardServiceInterface
+ ) {
+ super();
+ this._jobManagementService = bootstrapService.jobManagementService;
+ }
+
+ ngOnInit() {
+ let ownerUri: string = this._dashboardService.connectionManagementService.connectionInfo.ownerUri;
+ this._tree = new Tree(this._tableContainer.nativeElement, {
+ controller: this._treeController,
+ dataSource: this._treeDataSource,
+ filter: this._treeFilter,
+ renderer: this._treeRenderer
+ });
+ }
+
+ ngOnChanges() {
+ if (this.stepRows.length > 0) {
+ this._treeDataSource.data = this.stepRows;
+ if (!this._tree) {
+ this._tree = new Tree(this._tableContainer.nativeElement, {
+ controller: this._treeController,
+ dataSource: this._treeDataSource,
+ filter: this._treeFilter,
+ renderer: this._treeRenderer
+ });
+ }
+ this._tree.layout(JobStepsViewComponent._pageSize);
+ this._tree.setInput(new JobStepsViewModel());
+ }
+ }
+
+ ngAfterContentChecked() {
+ }
+}
+
diff --git a/src/sql/parts/jobManagement/views/jobStepsView.css b/src/sql/parts/jobManagement/views/jobStepsView.css
new file mode 100644
index 0000000000..cf0bd6a7c6
--- /dev/null
+++ b/src/sql/parts/jobManagement/views/jobStepsView.css
@@ -0,0 +1,61 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the Source EULA. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+.steps-tree .list-row .status-icon {
+ height: 10px;
+ width: 10px;
+ display: inline-block;
+ margin-top: 4px;
+}
+
+.list-row .label {
+ padding-left: 10px;
+ display: flex;
+ text-align: center;
+}
+
+.step-passed {
+ background: green;
+}
+
+.step-failed {
+ background: red;
+}
+
+.step-unknown {
+ background: yellow;
+}
+
+.steps-tree .list-row {
+ display: inline-flex;
+ height: 20px
+}
+
+.step-columns {
+ padding-left: 50px;
+}
+
+.step-id-col, .tree-id-col {
+ padding-left: 10px;
+ white-space: normal;
+ text-align: center;
+ width: 60px;
+
+}
+
+.step-name-col, .tree-name-col {
+ padding-right: 10px;
+ white-space: normal;
+ text-align: center;
+ width: 350px;
+}
+
+.step-message-col, .tree-message-col {
+ padding-right: 10px;
+ white-space: normal;
+ text-align: center;
+ width: 680px;
+ height:
+}
\ No newline at end of file
diff --git a/src/sql/parts/jobManagement/views/jobStepsViewTree.ts b/src/sql/parts/jobManagement/views/jobStepsViewTree.ts
new file mode 100644
index 0000000000..070f76d53f
--- /dev/null
+++ b/src/sql/parts/jobManagement/views/jobStepsViewTree.ts
@@ -0,0 +1,186 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the Source EULA. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import { Router } from '@angular/router';
+
+import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
+import { MetadataType } from 'sql/parts/connection/common/connectionManagement';
+import { SingleConnectionManagementService } from 'sql/parts/dashboard/services/dashboardServiceInterface.service';
+import {
+ NewQueryAction, ScriptSelectAction, EditDataAction, ScriptCreateAction, ScriptExecuteAction, ScriptAlterAction,
+ BackupAction, ManageActionContext, BaseActionContext, ManageAction, RestoreAction
+} from 'sql/workbench/common/actions';
+import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
+import { ConnectionManagementInfo } from 'sql/parts/connection/common/connectionManagementInfo';
+import * as Constants from 'sql/parts/connection/common/constants';
+import * as tree from 'vs/base/parts/tree/browser/tree';
+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 { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
+import { IAction } from 'vs/base/common/actions';
+import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
+import { generateUuid } from 'vs/base/common/uuid';
+import * as DOM from 'vs/base/browser/dom';
+import { OEAction } from 'sql/parts/registeredServer/viewlet/objectExplorerActions';
+import { Builder, $, withElementById } from 'vs/base/browser/builder';
+import { AgentJobHistoryInfo } from 'sqlops';
+import { Agent } from 'vs/base/node/request';
+
+export class JobStepsViewRow {
+ public stepID: string;
+ public stepName: string;
+ public message: string;
+ public rowID: string = generateUuid();
+ public runStatus: string;
+}
+
+// Empty class just for tree input
+export class JobStepsViewModel {
+ public static readonly id = generateUuid();
+}
+
+export class JobStepsViewController extends TreeDefaults.DefaultController {
+ private _jobHistories: AgentJobHistoryInfo[];
+
+ protected onLeftClick(tree: tree.ITree, element: JobStepsViewRow, event: IMouseEvent, origin: string = 'mouse'): boolean {
+ return true;
+ }
+
+ public onContextMenu(tree: tree.ITree, element: JobStepsViewRow, event: tree.ContextMenuEvent): boolean {
+ return true;
+ }
+
+ public set jobHistories(value: AgentJobHistoryInfo[]) {
+ this._jobHistories = value;
+ }
+
+ public get jobHistories(): AgentJobHistoryInfo[] {
+ return this._jobHistories;
+ }
+
+}
+
+export class JobStepsViewDataSource implements tree.IDataSource {
+ private _data: JobStepsViewRow[];
+
+ public getId(tree: tree.ITree, element: JobStepsViewRow | JobStepsViewModel): string {
+ if (element instanceof JobStepsViewModel) {
+ return JobStepsViewModel.id;
+ } else {
+ return (element as JobStepsViewRow).rowID;
+ }
+ }
+
+ public hasChildren(tree: tree.ITree, element: JobStepsViewRow | JobStepsViewModel): boolean {
+ if (element instanceof JobStepsViewModel) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public getChildren(tree: tree.ITree, element: JobStepsViewRow | JobStepsViewModel): Promise {
+ if (element instanceof JobStepsViewModel) {
+ return TPromise.as(this._data);
+ } else {
+ return TPromise.as(undefined);
+ }
+ }
+
+ public getParent(tree: tree.ITree, element: JobStepsViewRow | JobStepsViewModel): Promise {
+ if (element instanceof JobStepsViewModel) {
+ return TPromise.as(undefined);
+ } else {
+ return TPromise.as(new JobStepsViewModel());
+ }
+ }
+
+ public set data(data: JobStepsViewRow[]) {
+ this._data = data;
+ }
+}
+
+export interface IListTemplate {
+ statusIcon: HTMLElement;
+ label: HTMLElement;
+}
+
+export class JobStepsViewRenderer implements tree.IRenderer {
+ private _statusIcon: HTMLElement;
+
+ public getHeight(tree: tree.ITree, element: JobStepsViewRow): number {
+ return 22;
+ }
+
+ public getTemplateId(tree: tree.ITree, element: JobStepsViewRow | JobStepsViewModel): string {
+ if (element instanceof JobStepsViewModel) {
+ return 'jobStepsViewModel';
+ } else {
+ return 'jobStepsViewRow';
+ }
+ }
+
+ public renderTemplate(tree: tree.ITree, templateId: string, container: HTMLElement): IListTemplate {
+ let row = DOM.$('.list-row');
+ let label = DOM.$('.label');
+ this._statusIcon = this.createStatusIcon();
+ row.appendChild(this._statusIcon);
+ row.appendChild(label);
+ container.appendChild(row);
+ let statusIcon = this._statusIcon;
+ return { statusIcon, label };
+ }
+
+ public renderElement(tree: tree.ITree, element: JobStepsViewRow, templateId: string, templateData: IListTemplate): void {
+ let stepIdCol: HTMLElement = DOM.$('div');
+ stepIdCol.className = 'tree-id-col';
+ stepIdCol.innerText = element.stepID;
+ let stepNameCol: HTMLElement = DOM.$('div');
+ stepNameCol.className = 'tree-name-col';
+ stepNameCol.innerText = element.stepName;
+ let stepMessageCol: HTMLElement = DOM.$('div');
+ stepMessageCol.className = 'tree-message-col';
+ stepMessageCol.innerText = element.message;
+ templateData.label.appendChild(stepIdCol);
+ templateData.label.appendChild(stepNameCol);
+ templateData.label.appendChild(stepMessageCol);
+ let statusClass: string;
+ if (element.runStatus === 'Succeeded') {
+ statusClass = ' step-passed';
+ } else if (element.runStatus === 'Failed') {
+ statusClass = ' step-failed';
+ } else {
+ statusClass = ' step-unknown';
+ }
+ this._statusIcon.className += statusClass;
+ }
+
+ public disposeTemplate(tree: tree.ITree, templateId: string, templateData: IListTemplate): void {
+ // no op
+ }
+
+ private createStatusIcon(): HTMLElement {
+ let statusIcon: HTMLElement = DOM.$('div');
+ statusIcon.className += ' status-icon';
+ return statusIcon;
+ }
+}
+
+export class JobStepsViewFilter implements tree.IFilter {
+ private _filterString: string;
+
+ public isVisible(tree: tree.ITree, element: JobStepsViewRow): boolean {
+ return this._isJobVisible();
+ }
+
+ private _isJobVisible(): boolean {
+ return true;
+ }
+
+ public set filterString(val: string) {
+ this._filterString = val;
+ }
+}
diff --git a/src/sql/parts/jobManagement/views/jobsView.component.ts b/src/sql/parts/jobManagement/views/jobsView.component.ts
index ac80d9bca5..3eac711029 100644
--- a/src/sql/parts/jobManagement/views/jobsView.component.ts
+++ b/src/sql/parts/jobManagement/views/jobsView.component.ts
@@ -208,8 +208,8 @@ export class JobsViewComponent implements OnInit, OnDestroy {
}
private getJob(args: Slick.OnClickEventArgs): sqlops.AgentJobInfo {
- let cell = args.cell;
- let jobName = args.grid.getCellNode(1, cell).innerText.trim();
+ let row = args.row;
+ let jobName = args.grid.getCellNode(row, 1).innerText.trim();
let job = this.jobs.filter(job => job.name === jobName)[0];
return job;
}
diff --git a/src/sql/sqlops.d.ts b/src/sql/sqlops.d.ts
index aa32e247ae..27c45762c2 100644
--- a/src/sql/sqlops.d.ts
+++ b/src/sql/sqlops.d.ts
@@ -1060,6 +1060,13 @@ declare module 'sqlops' {
jobId: string;
}
+ export interface AgentJobStep {
+ stepId: number;
+ stepName: string;
+ message: string;
+ runDate: string;
+ }
+
export interface AgentJobHistoryInfo {
instanceId: number;
sqlMessageId: number;
@@ -1077,6 +1084,7 @@ declare module 'sqlops' {
operatorPaged: string;
retriesAttempted: number;
server: string;
+ steps: AgentJobStep[];
}
export interface AgentServicesProvider extends DataProvider {