diff --git a/extensions/mssql/src/config.json b/extensions/mssql/src/config.json index fb4dd8244b..5e7ac50ddc 100644 --- a/extensions/mssql/src/config.json +++ b/extensions/mssql/src/config.json @@ -1,6 +1,6 @@ { "downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}", - "version": "1.4.0-alpha.44", + "version": "1.4.0-alpha.45", "downloadFileNames": { "Windows_86": "win-x86-netcoreapp2.1.zip", "Windows_64": "win-x64-netcoreapp2.1.zip", diff --git a/src/sql/parts/dashboard/common/dashboardPage.component.ts b/src/sql/parts/dashboard/common/dashboardPage.component.ts index 812e31ecf3..3498e3f0d7 100644 --- a/src/sql/parts/dashboard/common/dashboardPage.component.ts +++ b/src/sql/parts/dashboard/common/dashboardPage.component.ts @@ -11,8 +11,6 @@ import { Component, Inject, forwardRef, ViewChild, ElementRef, ViewChildren, Que import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service'; import { CommonServiceInterface, SingleConnectionManagementService } from 'sql/services/common/commonServiceInterface.service'; import { WidgetConfig, TabConfig, TabSettingConfig } from 'sql/parts/dashboard/common/dashboardWidget'; -import { Extensions, IInsightRegistry } from 'sql/platform/dashboard/common/insightRegistry'; -import { DashboardWidgetWrapper } from 'sql/parts/dashboard/contents/dashboardWidgetWrapper.component'; import { IPropertiesConfig } from 'sql/parts/dashboard/pages/serverDashboardPage.contribution'; import { PanelComponent } from 'sql/base/browser/ui/panel/panel.component'; import { IDashboardRegistry, Extensions as DashboardExtensions, IDashboardTab } from 'sql/platform/dashboard/common/dashboardRegistry'; @@ -27,13 +25,8 @@ import { AngularDisposable } from 'sql/base/common/lifecycle'; import { Registry } from 'vs/platform/registry/common/platform'; import * as types from 'vs/base/common/types'; -import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; +import { IDisposable } from 'vs/base/common/lifecycle'; import * as nls from 'vs/nls'; -import { ScrollbarVisibility } from 'vs/base/common/scrollable'; -import { addDisposableListener, getContentHeight, EventType } from 'vs/base/browser/dom'; -import { IColorTheme } from 'vs/workbench/services/themes/common/workbenchThemeService'; -import * as colors from 'vs/platform/theme/common/colorRegistry'; -import * as themeColors from 'vs/workbench/common/theme'; import * as objects from 'vs/base/common/objects'; import { Event, Emitter } from 'vs/base/common/event'; import { Action } from 'vs/base/common/actions'; diff --git a/src/sql/parts/dashboard/contents/controlHostContent.component.ts b/src/sql/parts/dashboard/contents/controlHostContent.component.ts index 08dabd90a7..3f1b31f41e 100644 --- a/src/sql/parts/dashboard/contents/controlHostContent.component.ts +++ b/src/sql/parts/dashboard/contents/controlHostContent.component.ts @@ -7,11 +7,7 @@ import 'vs/css!./controlHostContent'; import { Component, forwardRef, Input, OnInit, Inject, ChangeDetectorRef, ElementRef, ViewChild } from '@angular/core'; import { Event, Emitter } from 'vs/base/common/event'; -import { Parts } from 'vs/workbench/services/part/common/partService'; import { IDisposable } from 'vs/base/common/lifecycle'; - -import { TabConfig } from 'sql/parts/dashboard/common/dashboardWidget'; -import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service'; import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service'; import * as sqlops from 'sqlops'; diff --git a/src/sql/parts/grid/views/editData/editData.component.ts b/src/sql/parts/grid/views/editData/editData.component.ts index c9fdd55325..69467bf00c 100644 --- a/src/sql/parts/grid/views/editData/editData.component.ts +++ b/src/sql/parts/grid/views/editData/editData.component.ts @@ -214,23 +214,21 @@ export class EditDataComponent extends GridParentComponent implements OnInit, On onDeleteRow(): (index: number) => void { const self = this; return (index: number): void => { - self.dataService.deleteRow(index) - .then(() => self.dataService.commitEdit()) - .then(() => self.removeRow(index)); + // If the user is deleting a new row that hasn't been committed yet then use the revert code + if (self.newRowVisible && index === self.dataSet.dataRows.getLength() - 2) { + self.revertCurrentRow(); + } else { + self.dataService.deleteRow(index) + .then(() => self.dataService.commitEdit()) + .then(() => self.removeRow(index)); + } }; } - onRevertRow(): (index: number) => void { + onRevertRow(): () => void { const self = this; - return (index: number): void => { - // Force focus to the first cell (completing any active edit operation) - self.focusCell(index, 0, false); - this.currentEditCellValue = null; - // Perform a revert row operation - self.dataService.revertRow(index) - .then(() => { - self.refreshResultsets(); - }); + return (): void => { + self.revertCurrentRow(); }; } @@ -279,24 +277,27 @@ export class EditDataComponent extends GridParentComponent implements OnInit, On } if (this.currentCell.row !== row) { - // We're changing row, commit the changes - cellSelectTasks = cellSelectTasks.then(() => { - return self.dataService.commitEdit() - .then( - result => { + // If we're currently adding a new row, only commit it if it has changes or the user is trying to add another new row + if (this.newRowVisible && this.currentCell.row === this.dataSet.dataRows.getLength() - 2 && !this.isNullRow(row) && this.currentEditCellValue === null) { + cellSelectTasks = cellSelectTasks.then(() => { + return this.revertCurrentRow().then(() => this.focusCell(row, column)); + }); + } else { + // We're changing row, commit the changes + cellSelectTasks = cellSelectTasks.then(() => { + return self.dataService.commitEdit().then(result => { // Committing was successful, clean the grid self.setGridClean(); self.rowIdMappings = {}; self.newRowVisible = false; return Promise.resolve(); - }, - error => { + }, error => { // Committing failed, jump back to the last selected cell self.focusCell(self.currentCell.row, self.currentCell.column); return Promise.reject(null); - } - ); - }); + }); + }); + } } if (this.isNullRow(row) && !this.removingNewRow) { @@ -432,7 +433,18 @@ export class EditDataComponent extends GridParentComponent implements OnInit, On // If the esc key was pressed while in a create session let currentNewRowIndex = this.dataSet.totalRows - 2; - if (e.keyCode === KeyCode.Escape && this.newRowVisible && this.currentCell.row === currentNewRowIndex) { + if (e.keyCode === KeyCode.Escape) { + this.revertCurrentRow(); + handled = true; + } + return handled; + } + + // Private Helper Functions //////////////////////////////////////////////////////////////////////////// + + private async revertCurrentRow(): Promise { + let currentNewRowIndex = this.dataSet.totalRows - 2; + if (this.newRowVisible && this.currentCell.row === currentNewRowIndex) { // revert our last new row this.removingNewRow = true; @@ -441,17 +453,21 @@ export class EditDataComponent extends GridParentComponent implements OnInit, On this.removeRow(currentNewRowIndex); this.newRowVisible = false; }); - handled = true; - } else if (e.keyCode === KeyCode.Escape) { - this.currentEditCellValue = null; - this.onRevertRow()(this.currentCell.row); - handled = true; + } else { + try { + // Perform a revert row operation + if (this.currentCell) { + await this.dataService.revertRow(this.currentCell.row); + } + } finally { + // The operation may fail if there were no changes sent to the service to revert, + // so clear any existing client-side edit and refresh the table regardless + this.currentEditCellValue = null; + this.refreshResultsets(); + } } - return handled; } - // Private Helper Functions //////////////////////////////////////////////////////////////////////////// - // Checks if input row is our NULL new row private isNullRow(row: number): boolean { // Null row is always at index (totalRows - 1) @@ -539,9 +555,11 @@ export class EditDataComponent extends GridParentComponent implements OnInit, On // refresh results view this.onScroll(0); - // Set focus to the row index column of the removed row + // Set focus to the row index column of the removed row if the current selection is in the removed row setTimeout(() => { - this.focusCell(row, 0); + if (this.currentCell.row === row) { + this.focusCell(row, 0); + } this.removingNewRow = false; }, this.scrollTimeOutTime); } diff --git a/src/sql/parts/grid/views/editData/editDataGridActions.ts b/src/sql/parts/grid/views/editData/editDataGridActions.ts index f13da7fd01..0b9e2879c1 100644 --- a/src/sql/parts/grid/views/editData/editDataGridActions.ts +++ b/src/sql/parts/grid/views/editData/editDataGridActions.ts @@ -19,7 +19,7 @@ export class EditDataGridActionProvider extends GridActionProvider { dataService: DataService, selectAllCallback: (index: number) => void, private _deleteRowCallback: (index: number) => void, - private _revertRowCallback: (index: number) => void, + private _revertRowCallback: () => void, @IInstantiationService instantiationService: IInstantiationService ) { super(dataService, selectAllCallback, instantiationService); @@ -56,18 +56,18 @@ export class DeleteRowAction extends Action { export class RevertRowAction extends Action { public static ID = 'grid.revertRow'; - public static LABEL = localize('revertRow', 'Revert Row'); + public static LABEL = localize('revertRow', 'Revert Current Row'); constructor( id: string, label: string, - private callback: (index: number) => void + private callback: () => void ) { super(id, label); } public run(gridInfo: IGridInfo): TPromise { - this.callback(gridInfo.rowIndex); + this.callback(); return TPromise.as(true); } } diff --git a/src/sql/parts/jobManagement/agent/agentView.component.ts b/src/sql/parts/jobManagement/agent/agentView.component.ts index 454626e660..909573b517 100644 --- a/src/sql/parts/jobManagement/agent/agentView.component.ts +++ b/src/sql/parts/jobManagement/agent/agentView.component.ts @@ -82,7 +82,6 @@ export class AgentViewComponent { public set jobId(value: string) { this._jobId = value; - this._cd.detectChanges(); } public set showHistory(value: boolean) { @@ -92,7 +91,6 @@ export class AgentViewComponent { public set agentJobInfo(value: AgentJobInfo) { this._agentJobInfo = value; - this._cd.detectChanges(); } public set refresh(value: boolean) { @@ -104,6 +102,10 @@ export class AgentViewComponent { this._expanded.set(jobId, errorMessage); } + public set expanded(value: Map) { + this._expanded = value; + } + public layout() { this._panel.layout(); } diff --git a/src/sql/parts/jobManagement/common/media/jobs.css b/src/sql/parts/jobManagement/common/media/jobs.css index f751462eb1..8bc31f2d52 100644 --- a/src/sql/parts/jobManagement/common/media/jobs.css +++ b/src/sql/parts/jobManagement/common/media/jobs.css @@ -49,12 +49,12 @@ jobhistory-component { font-size: larger; } -.vs-dark #jobsDiv .slick-cell { - background:#333333 !important; +.vs-dark #jobsDiv jobsview-component .jobview-grid .grid-canvas .ui-widget-content.slick-row .slick-cell { + background:#333333; } -#jobsDiv .slick-cell { - background: white !important; +#jobsDiv jobsview-component .jobview-grid .grid-canvas .ui-widget-content.slick-row .slick-cell { + background: white; border-right: transparent !important; border-left: transparent !important; line-height: 33px !important; @@ -207,6 +207,18 @@ agentview-component .jobview-grid .grid-canvas > .ui-widget-content.slick-row.od background: none; } +#jobsDiv .jobview-grid > .monaco-table .slick-viewport > .grid-canvas > .ui-widget-content.slick-row:hover > .slick-cell, +#jobsDiv .jobview-grid > .monaco-table .slick-viewport > .grid-canvas > .ui-widget-content.slick-row.hovered > .slick-cell, +#jobsDiv .jobview-grid > .monaco-table .slick-viewport > .grid-canvas > .ui-widget-content.slick-row> .slick-cell.hovered { + background: #dcdcdc !important; +} + +.vs-dark #jobsDiv .jobview-grid > .monaco-table .slick-viewport > .grid-canvas > .ui-widget-content.slick-row:hover > .slick-cell, +.vs-dark #jobsDiv .jobview-grid > .monaco-table .slick-viewport > .grid-canvas > .ui-widget-content.slick-row > .slick-cell.hovered, +.vs-dark #jobsDiv .jobview-grid > .monaco-table .slick-viewport > .grid-canvas > .ui-widget-content.slick-row.hovered > .slick-cell { + background: #444444 !important; +} + table.jobprevruns div.bar1, table.jobprevruns div.bar2, table.jobprevruns div.bar3, table.jobprevruns div.bar4, table.jobprevruns div.bar5 { padding-top: 3px; diff --git a/src/sql/parts/jobManagement/views/jobHistory.component.ts b/src/sql/parts/jobManagement/views/jobHistory.component.ts index 5870fdf74f..2d49133275 100644 --- a/src/sql/parts/jobManagement/views/jobHistory.component.ts +++ b/src/sql/parts/jobManagement/views/jobHistory.component.ts @@ -7,31 +7,22 @@ import 'vs/css!./jobHistory'; import 'vs/css!sql/media/icons/common-icons'; import { OnInit, OnChanges, Component, Inject, Input, forwardRef, ElementRef, ChangeDetectorRef, ViewChild, ChangeDetectionStrategy, Injectable } from '@angular/core'; import { AgentJobHistoryInfo, AgentJobInfo } from 'sqlops'; - -import { Taskbar, ITaskbarContent } from 'sql/base/browser/ui/taskbar/taskbar'; +import { Taskbar } from 'sql/base/browser/ui/taskbar/taskbar'; import { RunJobAction, StopJobAction } from 'sql/parts/jobManagement/views/jobHistoryActions'; import { JobCacheObject } from 'sql/parts/jobManagement/common/jobManagementService'; import { AgentJobUtilities } from '../common/agentJobUtilities'; -import { PanelComponent } from 'sql/base/browser/ui/panel/panel.component'; import { IJobManagementService } from '../common/interfaces'; -import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service'; import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service'; import { AgentViewComponent } from 'sql/parts/jobManagement/agent/agentView.component'; import { JobHistoryController, JobHistoryDataSource, JobHistoryRenderer, JobHistoryFilter, JobHistoryModel, JobHistoryRow } from 'sql/parts/jobManagement/views/jobHistoryTree'; -import { JobStepsViewComponent } from 'sql/parts/jobManagement/views/jobStepsView.component'; import { JobStepsViewRow } from './jobStepsViewTree'; - import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService'; -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 { localize } from 'vs/nls'; +import { Disposable } from 'vs/base/common/lifecycle'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import Severity from 'vs/base/common/severity'; -import { ITreeOptions } from 'vs/base/parts/tree/browser/tree'; import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; diff --git a/src/sql/parts/jobManagement/views/jobHistoryActions.ts b/src/sql/parts/jobManagement/views/jobHistoryActions.ts index bb1b2bd258..5b31b5c434 100644 --- a/src/sql/parts/jobManagement/views/jobHistoryActions.ts +++ b/src/sql/parts/jobManagement/views/jobHistoryActions.ts @@ -8,9 +8,7 @@ import { Action } from 'vs/base/common/actions'; import * as nls from 'vs/nls'; import { INotificationService } from 'vs/platform/notification/common/notification'; import Severity from 'vs/base/common/severity'; -import { BaseActionContext } from '../../../workbench/common/actions'; import { JobHistoryComponent } from 'sql/parts/jobManagement/views/jobHistory.component'; -import { JobManagementService } from '../common/jobManagementService'; import { IJobManagementService } from '../common/interfaces'; export enum JobHistoryActions { diff --git a/src/sql/parts/jobManagement/views/jobHistoryTree.ts b/src/sql/parts/jobManagement/views/jobHistoryTree.ts index 4e5b47fc96..7149531ea2 100644 --- a/src/sql/parts/jobManagement/views/jobHistoryTree.ts +++ b/src/sql/parts/jobManagement/views/jobHistoryTree.ts @@ -3,33 +3,18 @@ * 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/services/common/commonServiceInterface.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/objectExplorer/viewlet/objectExplorerActions'; -import { $ } from 'vs/base/browser/builder'; import { AgentJobHistoryInfo } from 'sqlops'; -import { Agent } from 'vs/base/node/request'; import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; -import { JobHistoryComponent } from './jobHistory.component'; export class JobHistoryRow { runDate: string; diff --git a/src/sql/parts/jobManagement/views/jobStepsView.component.ts b/src/sql/parts/jobManagement/views/jobStepsView.component.ts index 66c51a584c..6733efb56d 100644 --- a/src/sql/parts/jobManagement/views/jobStepsView.component.ts +++ b/src/sql/parts/jobManagement/views/jobStepsView.component.ts @@ -6,22 +6,14 @@ import 'vs/css!./jobStepsView'; import { OnInit, Component, Inject, forwardRef, ElementRef, ChangeDetectorRef, ViewChild, Injectable, AfterContentChecked } from '@angular/core'; - -import { AgentJobHistoryInfo } 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'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; +import { Disposable } from 'vs/base/common/lifecycle'; import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService'; - -import { IJobManagementService } from '../common/interfaces'; -import { DashboardServiceInterface } from 'sql/parts/dashboard/services/dashboardServiceInterface.service'; import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service'; import { JobStepsViewController, JobStepsViewDataSource, JobStepsViewFilter, - JobStepsViewRenderer, JobStepsViewRow, JobStepsViewModel} from 'sql/parts/jobManagement/views/jobStepsViewTree'; + JobStepsViewRenderer, JobStepsViewModel} from 'sql/parts/jobManagement/views/jobStepsViewTree'; import { JobHistoryComponent } from 'sql/parts/jobManagement/views/jobHistory.component'; export const JOBSTEPSVIEW_SELECTOR: string = 'jobstepsview-component'; diff --git a/src/sql/parts/jobManagement/views/jobStepsViewTree.ts b/src/sql/parts/jobManagement/views/jobStepsViewTree.ts index a1d9f81231..020cbb067f 100644 --- a/src/sql/parts/jobManagement/views/jobStepsViewTree.ts +++ b/src/sql/parts/jobManagement/views/jobStepsViewTree.ts @@ -3,29 +3,17 @@ * 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/services/common/commonServiceInterface.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 { 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/objectExplorer/viewlet/objectExplorerActions'; import { AgentJobHistoryInfo } from 'sqlops'; -import { Agent } from 'vs/base/node/request'; import { AgentJobUtilities } from 'sql/parts/jobManagement/common/agentJobUtilities'; export class JobStepsViewRow { diff --git a/src/sql/parts/jobManagement/views/jobsView.component.ts b/src/sql/parts/jobManagement/views/jobsView.component.ts index 706e2af598..ff3b79511a 100644 --- a/src/sql/parts/jobManagement/views/jobsView.component.ts +++ b/src/sql/parts/jobManagement/views/jobsView.component.ts @@ -13,33 +13,23 @@ import 'vs/css!sql/media/icons/common-icons'; import 'vs/css!sql/base/browser/ui/table/media/table'; import { Component, Inject, forwardRef, ElementRef, ChangeDetectorRef, ViewChild, AfterContentChecked } from '@angular/core'; - import * as sqlops from 'sqlops'; import * as vscode from 'vscode'; - import * as nls from 'vs/nls'; - -import { IGridDataSet } from 'sql/parts/grid/common/interfaces'; import { Table } from 'sql/base/browser/ui/table/table'; -import { attachTableStyler } from 'sql/common/theme/styler'; -import { JobHistoryComponent } from 'src/sql/parts/jobManagement/views/jobHistory.component'; import { AgentViewComponent } from 'sql/parts/jobManagement/agent/agentView.component'; import { RowDetailView } from 'sql/base/browser/ui/table/plugins/rowdetailview'; import { JobCacheObject } from 'sql/parts/jobManagement/common/jobManagementService'; import { AgentJobUtilities } from 'sql/parts/jobManagement/common/agentJobUtilities'; import { HeaderFilter } from 'sql/base/browser/ui/table/plugins/headerFilter.plugin'; -import { BaseFocusDirectionTerminalAction } from 'vs/workbench/parts/terminal/electron-browser/terminalActions'; -import * as Utils from 'sql/parts/connection/common/utils'; import * as dom from 'vs/base/browser/dom'; import { IJobManagementService } from '../common/interfaces'; import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service'; -import { DashboardPage } from 'sql/parts/dashboard/common/dashboardPage.component'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { TabChild } from 'sql/base/browser/ui/panel/tab.component'; - - export const JOBSVIEW_SELECTOR: string = 'jobsview-component'; +export const ROW_HEIGHT: number = 45; @Component({ selector: JOBSVIEW_SELECTOR, @@ -82,6 +72,7 @@ export class JobsViewComponent implements AfterContentChecked { @ViewChild('jobsgrid') _gridEl: ElementRef; private isVisible: boolean = false; private isInitialized: boolean = false; + private isRefreshing: boolean = false; private _table: Table; public jobs: sqlops.AgentJobInfo[]; public jobHistories: { [jobId: string]: sqlops.AgentJobHistoryInfo[]; } = Object.create(null); @@ -137,10 +128,14 @@ export class JobsViewComponent implements AfterContentChecked { } else if (this.isVisible === true && this._agentViewComponent.refresh === true) { this._showProgressWheel = true; this.onFirstVisible(false); + this.isRefreshing = true; this._agentViewComponent.refresh = false; } else if (this.isVisible === true && this._agentViewComponent.refresh === false) { - this._showProgressWheel = true; - this.onFirstVisible(true); + if (!this.isRefreshing) { + this._showProgressWheel = true; + this.onFirstVisible(true); + } + this.isRefreshing = false; } else if (this.isVisible === true && this._gridEl.nativeElement.offsetParent === null) { this.isVisible = false; } @@ -152,8 +147,16 @@ export class JobsViewComponent implements AfterContentChecked { column.rerenderOnResize = true; return column; }); - // create the table - this.dataView = new Slick.Data.DataView(); + let options = >{ + syncColumnCellResize: true, + enableColumnReorder: false, + rowHeight: ROW_HEIGHT, + enableCellNavigation: true, + forceFitColumns: true + }; + + this.dataView = new Slick.Data.DataView({ inlineFilters: false }); + let rowDetail = new RowDetailView({ cssClass: '_detail_selector', process: (job) => { @@ -168,10 +171,8 @@ export class JobsViewComponent implements AfterContentChecked { columns.unshift(this.rowDetail.getColumnDefinition()); let filterPlugin = new HeaderFilter({}, this._themeService); this.filterPlugin = filterPlugin; + $(this._gridEl.nativeElement).empty(); this._table = new Table(this._gridEl.nativeElement, undefined, columns, this.options); - - - this._table.grid.setData(this.dataView, true); this._table.grid.onClick.subscribe((e, args) => { let job = self.getJob(args); @@ -195,9 +196,11 @@ export class JobsViewComponent implements AfterContentChecked { private onJobsAvailable(jobs: sqlops.AgentJobInfo[]) { let jobViews: any; + let start: boolean = true; if (!jobs) { let dataView = this._jobCacheObject.dataView; jobViews = dataView.getItems(); + start = false; } else { jobViews = jobs.map((job) => { return { @@ -321,7 +324,7 @@ export class JobsViewComponent implements AfterContentChecked { this._table.autosizeColumns(); this._table.resizeCanvas(); - this.expandJobs(true); + this.expandJobs(start); // tooltip for job name $('.jobview-jobnamerow').hover(e => { let currentTarget = e.currentTarget; @@ -360,6 +363,44 @@ export class JobsViewComponent implements AfterContentChecked { self.createJobChart(job.jobId, previousRuns); }); }); + $('#jobsDiv .jobview-grid .monaco-table .slick-viewport .grid-canvas .ui-widget-content.slick-row').hover((e) => { + // highlight the error row as well if a failing job row is hovered + if (e.currentTarget.children.item(0).classList.contains('job-with-error')) { + let target = $(e.currentTarget); + let targetChildren = $(e.currentTarget.children); + let siblings = target.nextAll().toArray(); + let top = parseInt(target.css('top'), 10); + for (let i = 0; i < siblings.length; i++) { + let sibling = siblings[i]; + let siblingTop = parseInt($(sibling).css('top'), 10); + if (siblingTop === top + ROW_HEIGHT) { + $(sibling.children).addClass('hovered'); + sibling.onmouseenter = (e) => { + targetChildren.addClass('hovered'); + }; + sibling.onmouseleave = (e) => { + targetChildren.removeClass('hovered'); + } + break; + } + } + } + }, (e) => { + // switch back to original background + if (e.currentTarget.children.item(0).classList.contains('job-with-error')) { + let target = $(e.currentTarget); + let siblings = target.nextAll().toArray(); + let top = parseInt(target.css('top'), 10); + for (let i = 0; i < siblings.length; i++) { + let sibling = siblings[i]; + let siblingTop = parseInt($(sibling).css('top'), 10); + if (siblingTop === top + ROW_HEIGHT) { + $(sibling.children).removeClass('hovered'); + break; + } + } + } + }); // cache the dataview for future use this._jobCacheObject.dataView = this.dataView; this.filterValueMap['start'] = [[], this.dataView.getItems()]; @@ -579,6 +620,9 @@ export class JobsViewComponent implements AfterContentChecked { } private expandJobs(start: boolean): void { + if (start) { + this._agentViewComponent.expanded = new Map(); + } let expandedJobs = this._agentViewComponent.expanded; let expansions = 0; for (let i = 0; i < this.jobs.length; i++){ diff --git a/src/sql/parts/modelComponents/componentBase.ts b/src/sql/parts/modelComponents/componentBase.ts index fa8d2a46db..c812f34272 100644 --- a/src/sql/parts/modelComponents/componentBase.ts +++ b/src/sql/parts/modelComponents/componentBase.ts @@ -138,9 +138,17 @@ export abstract class ComponentBase extends Disposable implements IComponent, On return +size; } + protected getWidth(): string { + return this.width ? this.convertSize(this.width) : ''; + } + + protected getHeight(): string { + return this.height ? this.convertSize(this.height) : ''; + } + protected convertSize(size: number | string): string { if (types.isUndefinedOrNull(size)) { - return ''; + return '100%'; } let convertedSize: string = size ? size.toString() : '100%'; if (!convertedSize.toLowerCase().endsWith('px') && !convertedSize.toLowerCase().endsWith('%')) { diff --git a/src/sql/parts/modelComponents/dropdown.component.ts b/src/sql/parts/modelComponents/dropdown.component.ts index 4665a0ddda..2f3f2788fa 100644 --- a/src/sql/parts/modelComponents/dropdown.component.ts +++ b/src/sql/parts/modelComponents/dropdown.component.ts @@ -27,7 +27,7 @@ import { attachListStyler } from 'vs/platform/theme/common/styler'; selector: 'modelview-dropdown', template: ` -
+