mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Agent work (WIP) (#1012)
* WIP * wip * SQL Agent wip * wip * Initial control host (wip) * Initial hookup of SQL Agent service to job component * Update agent package.json * Hook up getJobs call * A couple job view updates * Add some more agent views * added back button, run actions and overview accordion * refactoring * overview table complete * fixed the dropdown arrow for the overview section * added table for prev job list * fixed agent job result type * Rename some 'agent' classes to 'jobManagement' * code cleaning and code review comments * fixed yarn.lock conflicts * added function for job history * changed vscode-languageclient version * changed yarn lock file * fixed yarn lock file * fixed yarn file * fixed css paths * added images to packaging step * fix resource path for packaging * job history page (#852) * added back button, run actions and overview accordion * refactoring * overview table complete * fixed the dropdown arrow for the overview section * added table for prev job list * fixed agent job result type * code cleaning and code review comments * fixed yarn.lock conflicts * added function for job history * changed vscode-languageclient version * changed yarn lock file * fixed yarn lock file * fixed yarn file * fixed css paths * added images to packaging step * fix resource path for packaging * added steps lists * fixed style and dimensions * fixed conflicts * Switch back getJobs return type * Make enum const * Remove sqlops const * WIP * WIP * implemented job list * added the Date and Status columns * update yarn files * merged feature/agent1 * added theme styling for light theme * changed yarn lock files * Feature/agent1 adbist (#899) * added back button, run actions and overview accordion * refactoring * overview table complete * fixed the dropdown arrow for the overview section * added table for prev job list * fixed agent job result type * code cleaning and code review comments * fixed yarn.lock conflicts * added function for job history * changed vscode-languageclient version * changed yarn lock file * fixed yarn lock file * fixed yarn file * fixed css paths * added images to packaging step * fix resource path for packaging * added steps lists * fixed style and dimensions * fixed conflicts * implemented job list * added the Date and Status columns * update yarn files * merged feature/agent1 * added theme styling for light theme * changed yarn lock files * made job history page css more specific * Add visiblity check to job view * added method signatures for job history with DMP * Clean up jobs styling and call getJobHistory * Add more Job Table styling * Enable detail view in job table * Use updated slickgrid repo * vbumped slickgrid * added methods for job running * added job actions to sqlops * Convert rowdetail slickgrid plug to TypeScript * Feature/agent1 adbist (#945) * added back button, run actions and overview accordion * refactoring * overview table complete * fixed the dropdown arrow for the overview section * added table for prev job list * fixed agent job result type * code cleaning and code review comments * fixed yarn.lock conflicts * added function for job history * changed vscode-languageclient version * changed yarn lock file * fixed yarn lock file * fixed yarn file * fixed css paths * added images to packaging step * fix resource path for packaging * added steps lists * fixed style and dimensions * fixed conflicts * implemented job list * added the Date and Status columns * update yarn files * merged feature/agent1 * added theme styling for light theme * changed yarn lock files * added method signatures for job history with DMP * added methods for job running * added job actions to sqlops * Refer to dataprotocol from feature/agentDmp1 branch * Update SQL Tools version to 1.4.0-alpha.13 * Change Feb to March in release note prompt * SQL Agent extension metadata * add feature explicitly in client creation * Update Agent job registration * navigation works but is really slow to load data * Update package.json * fixed conflicts * Feature/agent1 adbist (#955) * added back button, run actions and overview accordion * refactoring * overview table complete * fixed the dropdown arrow for the overview section * added table for prev job list * fixed agent job result type * code cleaning and code review comments * fixed yarn.lock conflicts * added function for job history * changed vscode-languageclient version * changed yarn lock file * fixed yarn lock file * fixed yarn file * fixed css paths * added images to packaging step * fix resource path for packaging * added steps lists * fixed style and dimensions * fixed conflicts * implemented job list * added the Date and Status columns * update yarn files * merged feature/agent1 * added theme styling for light theme * changed yarn lock files * added method signatures for job history with DMP * added methods for job running * added job actions to sqlops * navigation works but is really slow to load data * Add jobs view icon * fixed bug where not all steps were being shown * Misc. cleanups * added more to history page * added loadHistories and code review comments * made the params standard * fixed json local paths * added step implementation * fixed conflict * cleaned up code * removed extension-modules * CR comments * fix css * fixed data injection * steps now support big messages * improve history page UX
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -106,7 +106,15 @@
|
||||
<h3>Status:</h3>
|
||||
</td>
|
||||
<td height="30">
|
||||
<h3></h3>
|
||||
<h3>{{_runStatus}}</h3>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="step-row">
|
||||
<td height="30">
|
||||
Job ID:
|
||||
</td>
|
||||
<td height="30">
|
||||
{{agentJobHistoryInfo?.jobId}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="step-row">
|
||||
@@ -127,10 +135,10 @@
|
||||
</tr>
|
||||
<tr class="step-row">
|
||||
<td height="30">
|
||||
Log:
|
||||
Server:
|
||||
</td>
|
||||
<td>
|
||||
|
||||
{{agentJobHistoryInfo?.server}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="step-row">
|
||||
@@ -138,7 +146,7 @@
|
||||
SQL message ID:
|
||||
</td>
|
||||
<td height="30">
|
||||
|
||||
{{agentJobHistoryInfo?.sqlMessageId}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="step-row">
|
||||
@@ -150,6 +158,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<jobstepsview-component *ngIf="showSteps() === true" [stepRows]="_stepRows"></jobstepsview-component>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<!--
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
-->
|
||||
|
||||
<h1>Steps</h1>
|
||||
<table class='step-columns'>
|
||||
<tr>
|
||||
<td class='step-id-col'>
|
||||
<b>Step ID</b>
|
||||
</td>
|
||||
<td class='step-name-col'>
|
||||
<b>Step Name</b>
|
||||
</td>
|
||||
<td class='step-message-col'>
|
||||
<b>Message</b>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class='steps-tree' #table style="height: 100%; width: 100%"></div>
|
||||
80
src/sql/parts/jobManagement/views/jobStepsView.component.ts
Normal file
80
src/sql/parts/jobManagement/views/jobStepsView.component.ts
Normal file
@@ -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() {
|
||||
}
|
||||
}
|
||||
|
||||
61
src/sql/parts/jobManagement/views/jobStepsView.css
Normal file
61
src/sql/parts/jobManagement/views/jobStepsView.css
Normal file
@@ -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:
|
||||
}
|
||||
186
src/sql/parts/jobManagement/views/jobStepsViewTree.ts
Normal file
186
src/sql/parts/jobManagement/views/jobStepsViewTree.ts
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -208,8 +208,8 @@ export class JobsViewComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
private getJob(args: Slick.OnClickEventArgs<any>): 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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user