diff --git a/src/sql/parts/jobManagement/views/jobHistory.component.html b/src/sql/parts/jobManagement/views/jobHistory.component.html
index 642f84f64d..43da359029 100644
--- a/src/sql/parts/jobManagement/views/jobHistory.component.html
+++ b/src/sql/parts/jobManagement/views/jobHistory.component.html
@@ -15,10 +15,10 @@
- {{agentJobInfo.lastRun}}
+ {{agentJobHistoryInfo?.runDate}}
Status:
|
-
+ |
|
|
- Error Message:
+ Message:
|
-
-
+ |
+ {{agentJobHistoryInfo?.message}}
|
|
Duration:
|
-
-
+ |
+ {{agentJobHistoryInfo?.runDuration}}
|
@@ -137,7 +137,7 @@
|
SQL message ID:
|
-
+ |
|
@@ -145,8 +145,8 @@
Retries Attempted:
|
-
-
+ |
+ {{agentJobHistoryInfo?.retriesAttempted}}
|
diff --git a/src/sql/parts/jobManagement/views/jobHistory.component.ts b/src/sql/parts/jobManagement/views/jobHistory.component.ts
index e36d39973a..ebc5775a04 100644
--- a/src/sql/parts/jobManagement/views/jobHistory.component.ts
+++ b/src/sql/parts/jobManagement/views/jobHistory.component.ts
@@ -5,25 +5,20 @@
import 'vs/css!./jobHistory';
-import { OnInit, Component, Inject, forwardRef, ElementRef, ChangeDetectorRef, OnDestroy, ViewChild, Input } from '@angular/core';
-import { ICancelableEvent } from 'vs/base/parts/tree/browser/treeDefaults';
+import { OnInit, Component, Inject, forwardRef, ElementRef, ChangeDetectorRef, OnDestroy, ViewChild, Input, Injectable } from '@angular/core';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { attachListStyler } from 'vs/platform/theme/common/styler';
-import { getContentHeight } from 'vs/base/browser/dom';
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 { PanelComponent } from 'sql/base/browser/ui/panel/panel.component';
import { IBootstrapService, BOOTSTRAP_SERVICE_ID } from 'sql/services/bootstrap/bootstrapService';
import { IJobManagementService } from '../common/interfaces';
-import { ExplorerDataSource } from 'sql/parts/dashboard/widgets/explorer/explorerTree';
-import { TreeCreationUtils } from 'sql/parts/registeredServer/viewlet/treeCreationUtils';
import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service';
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 { toDisposableSubscription } from '../../common/rxjsUtils';
export const DASHBOARD_SELECTOR: string = 'jobhistory-component';
@@ -46,9 +41,8 @@ export class JobHistoryComponent extends Disposable implements OnInit, OnDestroy
@Input() public agentJobInfo: AgentJobInfo = undefined;
@Input() public jobId: string = undefined;
@Input() public agentJobHistoryInfo: AgentJobHistoryInfo = undefined;
- private prevJobId: string = undefined;
- private jobName: string = undefined;
+ private prevJobId: string = undefined;
private isVisible: boolean = false;
@@ -65,8 +59,32 @@ export class JobHistoryComponent extends Disposable implements OnInit, OnDestroy
ngOnInit() {
let ownerUri: string = this._dashboardService.connectionManagementService.connectionInfo.ownerUri;
- this.loadHistory();
- this._treeDataSource.data = [];
+ const self = this;
+ this._treeController.onClick = (tree, element, event, origin = 'mouse') => {
+ const payload = { origin: origin };
+ 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();
+ }
+ return true;
+ };
this._tree = new Tree(this._tableContainer.nativeElement, {
controller: this._treeController,
dataSource: this._treeDataSource,
@@ -75,7 +93,6 @@ export class JobHistoryComponent extends Disposable implements OnInit, OnDestroy
});
this._register(attachListStyler(this._tree, this.bootstrapService.themeService));
this._tree.layout(1024);
- //this._tree.setInput(new JobHistoryModel());
}
ngOnDestroy() {
@@ -83,7 +100,7 @@ export class JobHistoryComponent extends Disposable implements OnInit, OnDestroy
ngAfterContentChecked() {
if (this.isVisible === false && this._tableContainer.nativeElement.offsetParent !== null) {
- if (this.prevJobId !== undefined && this.prevJobId !== this.jobId) {
+ if (this.prevJobId !== this.jobId) {
this.loadHistory();
this.prevJobId = this.jobId;
}
@@ -91,12 +108,17 @@ export class JobHistoryComponent extends Disposable implements OnInit, OnDestroy
}
loadHistory() {
+ const self = this;
let ownerUri: string = this._dashboardService.connectionManagementService.connectionInfo.ownerUri;
this._jobManagementService.getJobHistory(ownerUri, this.jobId).then((result) => {
if (result.jobs) {
- let jobHistory = result.jobs;
- this._treeDataSource.data = jobHistory.map(job => this.convertToJobHistoryRow(job));
- this._tree.setInput(new JobHistoryModel());
+ self._treeController.jobHistories = result.jobs;
+ let jobHistoryRows = self._treeController.jobHistories.map(job => self.convertToJobHistoryRow(job));
+ self._treeDataSource.data = jobHistoryRows;
+ self._tree.setInput(new JobHistoryModel());
+ self.agentJobHistoryInfo = self._treeController.jobHistories[0];
+ self.agentJobHistoryInfo.runDate = self.formatTime(self.agentJobHistoryInfo.runDate);
+ self._cd.detectChanges();
}
});
}
@@ -111,22 +133,26 @@ export class JobHistoryComponent extends Disposable implements OnInit, OnDestroy
}
}
- private jobAction(action: string): void {
+ private jobAction(action: string, jobName: string): void {
let ownerUri: string = this._dashboardService.connectionManagementService.connectionInfo.ownerUri;
- this._jobManagementService.jobAction(ownerUri, 'jobName', action);
+ this._jobManagementService.jobAction(ownerUri, jobName, action);
}
private goToJobs(): void {
+ this.isVisible = false;
this._agentViewComponent.showHistory = false;
}
private convertToJobHistoryRow(historyInfo: AgentJobHistoryInfo): JobHistoryRow {
- let jobHistoryRow = {
- runDate: historyInfo.runDate,
- runStatus: JobHistoryRow.convertToStatusString(historyInfo.runStatus),
- jobID: historyInfo.jobID
- };
+ let jobHistoryRow = new JobHistoryRow();
+ jobHistoryRow.runDate = historyInfo.runDate;
+ jobHistoryRow.runStatus = JobHistoryRow.convertToStatusString(historyInfo.runStatus);
+ jobHistoryRow.instanceID = historyInfo.instanceId;
return jobHistoryRow;
}
+
+ private formatTime(time: string): string {
+ return time.replace('T', ' ');
+ }
}
diff --git a/src/sql/parts/jobManagement/views/jobHistory.css b/src/sql/parts/jobManagement/views/jobHistory.css
index 0fdc781484..5ff2b29c6e 100644
--- a/src/sql/parts/jobManagement/views/jobHistory.css
+++ b/src/sql/parts/jobManagement/views/jobHistory.css
@@ -158,7 +158,7 @@ input#accordion:checked ~ .accordion-content {
}
table.step-list tr.step-row td {
- padding-right: 100px;
+ padding-right: 10px;
}
.history-details {
diff --git a/src/sql/parts/jobManagement/views/jobHistoryTree.ts b/src/sql/parts/jobManagement/views/jobHistoryTree.ts
index 75b8eba4be..de2f3e484f 100644
--- a/src/sql/parts/jobManagement/views/jobHistoryTree.ts
+++ b/src/sql/parts/jobManagement/views/jobHistoryTree.ts
@@ -26,11 +26,14 @@ 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 JobHistoryRow {
runDate: string;
runStatus: string;
- jobID: string;
+ instanceID: number;
+ rowID: string = generateUuid();
public static convertToStatusString(status: number): string {
switch(status) {
@@ -47,28 +50,9 @@ export class JobHistoryModel {
}
export class JobHistoryController extends TreeDefaults.DefaultController {
+ private _jobHistories: AgentJobHistoryInfo[];
protected onLeftClick(tree: tree.ITree, element: JobHistoryRow, event: IMouseEvent, origin: string = 'mouse'): boolean {
- const payload = { origin: origin };
- 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);
- }
-
return true;
}
@@ -76,6 +60,14 @@ export class JobHistoryController extends TreeDefaults.DefaultController {
return true;
}
+ public set jobHistories(value: AgentJobHistoryInfo[]) {
+ this._jobHistories = value;
+ }
+
+ public get jobHistories(): AgentJobHistoryInfo[] {
+ return this._jobHistories;
+ }
+
}
export class JobHistoryDataSource implements tree.IDataSource {
@@ -85,7 +77,7 @@ export class JobHistoryDataSource implements tree.IDataSource {
if (element instanceof JobHistoryModel) {
return JobHistoryModel.id;
} else {
- return (element as JobHistoryRow).jobID;
+ return (element as JobHistoryRow).rowID;
}
}
diff --git a/src/sql/parts/jobManagement/views/jobsView.component.ts b/src/sql/parts/jobManagement/views/jobsView.component.ts
index 9113c0264a..ac80d9bca5 100644
--- a/src/sql/parts/jobManagement/views/jobsView.component.ts
+++ b/src/sql/parts/jobManagement/views/jobsView.component.ts
@@ -93,36 +93,6 @@ export class JobsViewComponent implements OnInit, OnDestroy {
}
}
- loadJobHistories() {
- if (this.jobs) {
- this.jobs.forEach((job) => {
- let ownerUri: string = this._dashboardService.connectionManagementService.connectionInfo.ownerUri;
- this._jobManagementService.getJobHistory(ownerUri, job.jobId).then((result) => {
- if (result.jobs) {
- this.jobHistories[job.jobId] = result.jobs;
- this.expandJobsWithFailures();
- }
- });
- });
- }
- }
-
- private expandJobsWithFailures(): void {
- for (let i: number = 0; i < this.jobs.length; ++i) {
- let job = this.jobs[i];
- let jobHistory = this.jobHistories[job.jobId];
- if (jobHistory && jobHistory.length > 0) {
- let latestExecution = jobHistory[jobHistory.length - 1];
- if (latestExecution.runStatus !== 0) {
- this.expandJobRowDetails(i);
- }
- }
- }
- }
-
- private expandJobRowDetails(rowIdx: number): void {
- }
-
onFirstVisible() {
let self = this;
let columns = this.columns.map((column) => {
@@ -157,11 +127,6 @@ export class JobsViewComponent implements OnInit, OnDestroy {
let job = self.getJob(args);
self._agentViewComponent.jobId = job.jobId;
self._agentViewComponent.agentJobInfo = job;
- self.getJobHistoryInfo(ownerUri, job).then(result => {
- if (result) {
- this._agentViewComponent.agentJobHistoryInfo = result;
- }
- });
self.isVisible = false;
self._agentViewComponent.showHistory = true;
});
@@ -176,22 +141,6 @@ export class JobsViewComponent implements OnInit, OnDestroy {
});
}
- getJobHistoryInfo(ownerUri: string, job: any): Thenable
{
- return new Promise((resolve, reject) => {
- if (this.jobHistories[job.jobId]){
- Promise.resolve(this.jobHistories[job.jobId]);
- } else {
- this._jobManagementService.getJobHistory(ownerUri, job.jobId).then(result => {
- if (result && result.jobs) {
- Promise.resolve(result.jobs);
- } else {
- Promise.reject(undefined);
- }
- });
- }
- });
- }
-
onJobsAvailable(jobs: sqlops.AgentJobInfo[]) {
let jobViews = jobs.map((job) => {
return {
@@ -225,7 +174,6 @@ export class JobsViewComponent implements OnInit, OnDestroy {
this._table.resizeCanvas();
this._table.autosizeColumns();
-
this.loadJobHistories();
}
@@ -246,6 +194,19 @@ export class JobsViewComponent implements OnInit, OnDestroy {
'';
}
+ loadJobHistories() {
+ if (this.jobs) {
+ this.jobs.forEach((job) => {
+ let ownerUri: string = this._dashboardService.connectionManagementService.connectionInfo.ownerUri;
+ this._jobManagementService.getJobHistory(ownerUri, job.jobId).then((result) => {
+ if (result.jobs) {
+ this.jobHistories[job.jobId] = result.jobs;
+ }
+ });
+ });
+ }
+ }
+
private getJob(args: Slick.OnClickEventArgs): sqlops.AgentJobInfo {
let cell = args.cell;
let jobName = args.grid.getCellNode(1, cell).innerText.trim();
diff --git a/src/sql/sqlops.d.ts b/src/sql/sqlops.d.ts
index ca9a851042..a3726d68a5 100644
--- a/src/sql/sqlops.d.ts
+++ b/src/sql/sqlops.d.ts
@@ -1061,13 +1061,13 @@ declare module 'sqlops' {
}
export interface AgentJobHistoryInfo {
- instanceID: number;
- sqlMessageID: number;
+ instanceId: number;
+ sqlMessageId: number;
message: string;
- stepID: number;
+ stepId: number;
stepName: string;
sqlSeverity: number;
- jobID: string;
+ jobId: string;
jobName: string;
runStatus: number;
runDate: string;
@@ -1081,7 +1081,7 @@ declare module 'sqlops' {
export interface AgentServicesProvider extends DataProvider {
getJobs(connectionUri: string): Thenable;
- getJobHistory(connectionUri: string, jobID: string): Thenable;
+ getJobHistory(connectionUri: string, jobId: string): Thenable;
jobAction(connectionUri: string, jobName: string, action: string): Thenable;
}