diff --git a/src/sql/base/browser/ui/table/asyncDataView.ts b/src/sql/base/browser/ui/table/asyncDataView.ts index 16b5cb85f9..d6b15d2550 100644 --- a/src/sql/base/browser/ui/table/asyncDataView.ts +++ b/src/sql/base/browser/ui/table/asyncDataView.ts @@ -222,4 +222,8 @@ export class AsyncDataProvider implements IDisposable dispose() { this.dataRows.dispose(); } + + getItems(): T[] { + throw new Error('Method not supported.'); + } } diff --git a/src/sql/base/browser/ui/table/plugins/additionalKeyBindings.plugin.ts b/src/sql/base/browser/ui/table/plugins/additionalKeyBindings.plugin.ts index 74fb883212..3e15f8f70d 100644 --- a/src/sql/base/browser/ui/table/plugins/additionalKeyBindings.plugin.ts +++ b/src/sql/base/browser/ui/table/plugins/additionalKeyBindings.plugin.ts @@ -15,7 +15,7 @@ export class AdditionalKeyBindings implements Slick.Plugin { public init(grid: Slick.Grid) { this.grid = grid; - this.handler.subscribe(this.grid.onKeyDown, (e, args) => this.handleKeyDown(e, args)); + this.handler.subscribe(this.grid.onKeyDown, (e: KeyboardEvent, args) => this.handleKeyDown(e, args)); } public destroy() { diff --git a/src/sql/base/browser/ui/table/plugins/autoSizeColumns.plugin.ts b/src/sql/base/browser/ui/table/plugins/autoSizeColumns.plugin.ts index aaddfe28aa..ae6035f83d 100644 --- a/src/sql/base/browser/ui/table/plugins/autoSizeColumns.plugin.ts +++ b/src/sql/base/browser/ui/table/plugins/autoSizeColumns.plugin.ts @@ -49,7 +49,7 @@ export class AutoColumnSize implements Slick.Plugin { // since data can be async we want to only do this if we have the data to actual // work on since we are measuring the physical length of data - let data = this._grid.getData(); + let data = this._grid.getData() as Slick.DataProvider; let item = data.getItem(0); if (item && Object.keys(item).length > 0) { let hasValue = false; @@ -134,15 +134,15 @@ export class AutoColumnSize implements Slick.Plugin { } } - private getMaxColumnTextWidth(columnDef, colIndex: number): number { + private getMaxColumnTextWidth(columnDef: Slick.Column, colIndex: number): number { let texts: Array = []; - let rowEl = this.createRow(columnDef); - let data = this._grid.getData(); + let rowEl = this.createRow(); + let data = this._grid.getData() as Slick.DataProvider; let viewPort = this._grid.getViewport(); let start = Math.max(0, viewPort.top); let end = Math.min(data.getLength(), viewPort.bottom); for (let i = start; i < end; i++) { - texts.push(data.getItem(i)[columnDef.field]); + texts.push(data.getItem(i)[columnDef.field!]); } let template = this.getMaxTextTemplate(texts, columnDef, colIndex, data, rowEl); let width = this.getTemplateWidth(rowEl, template); @@ -150,21 +150,21 @@ export class AutoColumnSize implements Slick.Plugin { return width > this._options.maxWidth! ? this._options.maxWidth! : width; } - private getTemplateWidth(rowEl: JQuery, template: JQuery | HTMLElement): number { + private getTemplateWidth(rowEl: JQuery, template: JQuery | HTMLElement | string): number { let cell = jQuery(rowEl.find('.slick-cell')); cell.append(template); jQuery(cell).find('*').css('position', 'relative'); return cell.outerWidth() + 1; } - private getMaxTextTemplate(texts: string[], columnDef, colIndex: number, data, rowEl: JQuery): JQuery | HTMLElement { + private getMaxTextTemplate(texts: string[], columnDef: Slick.Column, colIndex: number, data: Slick.DataProvider, rowEl: JQuery): JQuery | HTMLElement | string { let max = 0, - maxTemplate = null; + maxTemplate: JQuery | HTMLElement | string | undefined; let formatFun = columnDef.formatter; texts.forEach((text, index) => { let template; if (formatFun) { - template = jQuery('' + formatFun(index, colIndex, text, columnDef, data[index]) + ''); + template = jQuery('' + formatFun(index, colIndex, text, columnDef, data.getItem(index)) + ''); text = template.text() || text; } let length = text ? this.getElementWidthUsingCanvas(rowEl, text) : 0; @@ -176,7 +176,7 @@ export class AutoColumnSize implements Slick.Plugin { return maxTemplate!; } - private createRow(columnDef): JQuery { + private createRow(): JQuery { let rowEl = jQuery('
'); rowEl.find('.slick-cell').css({ 'visibility': 'hidden', diff --git a/src/sql/base/browser/ui/table/plugins/cellRangeSelector.ts b/src/sql/base/browser/ui/table/plugins/cellRangeSelector.ts index b8ce4bcb5d..ed1523ee4a 100644 --- a/src/sql/base/browser/ui/table/plugins/cellRangeSelector.ts +++ b/src/sql/base/browser/ui/table/plugins/cellRangeSelector.ts @@ -26,13 +26,13 @@ export interface ICellRangeSelectorOptions { } export interface ICellRangeSelector extends Slick.Plugin { - onCellRangeSelected: Slick.Event<{ range: Slick.Range }>; + onCellRangeSelected: Slick.Event; onBeforeCellRangeSelected: Slick.Event; } export interface ICellRangeDecorator { - show(range: Slick.Range); - hide(); + show(range: Slick.Range): void; + hide(): void; } export class CellRangeSelector implements ICellRangeSelector { @@ -44,7 +44,7 @@ export class CellRangeSelector implements ICellRangeSelector { private currentlySelectedRange: { start: Slick.Cell, end?: Slick.Cell }; public onBeforeCellRangeSelected = new Slick.Event(); - public onCellRangeSelected = new Slick.Event<{ range: Slick.Range }>(); + public onCellRangeSelected = new Slick.Event(); constructor(private options: ICellRangeSelectorOptions) { require.__$__nodeRequire('slickgrid/plugins/slick.cellrangedecorator'); @@ -58,9 +58,9 @@ export class CellRangeSelector implements ICellRangeSelector { this.canvas = this.grid.getCanvasNode(); this.handler .subscribe(this.grid.onDragInit, e => this.handleDragInit(e)) - .subscribe(this.grid.onDragStart, (e, dd) => this.handleDragStart(e, dd)) - .subscribe(this.grid.onDrag, (e, dd) => this.handleDrag(e, dd)) - .subscribe(this.grid.onDragEnd, (e, dd) => this.handleDragEnd(e, dd)); + .subscribe(this.grid.onDragStart, (e: MouseEvent, dd) => this.handleDragStart(e, dd)) + .subscribe(this.grid.onDrag, (e: MouseEvent, dd) => this.handleDrag(e, dd)) + .subscribe(this.grid.onDragEnd, (e: MouseEvent, dd) => this.handleDragEnd(e, dd)); } public destroy() { @@ -138,13 +138,11 @@ export class CellRangeSelector implements ICellRangeSelector { if (!dd || !dd.range || !dd.range.start || !dd.range.end) { return; } - this.onCellRangeSelected.notify({ - range: new Slick.Range( - dd.range.start.row, - dd.range.start.cell, - dd.range.end.row, - dd.range.end.cell - ) - }); + this.onCellRangeSelected.notify(new Slick.Range( + dd.range.start.row, + dd.range.start.cell, + dd.range.end.row, + dd.range.end.cell + )); } } diff --git a/src/sql/base/browser/ui/table/plugins/cellSelectionModel.plugin.ts b/src/sql/base/browser/ui/table/plugins/cellSelectionModel.plugin.ts index 8458e45348..698469604d 100644 --- a/src/sql/base/browser/ui/table/plugins/cellSelectionModel.plugin.ts +++ b/src/sql/base/browser/ui/table/plugins/cellSelectionModel.plugin.ts @@ -19,6 +19,7 @@ export class CellSelectionModel implements Slick.SelectionModel; private selector: ICellRangeSelector; private ranges: Array = []; + private _handler = new Slick.EventHandler(); public onSelectedRangesChanged = new Slick.Event>(); @@ -35,19 +36,16 @@ export class CellSelectionModel implements Slick.SelectionModel) { this.grid = grid; - this.grid.onActiveCellChanged.subscribe((e, args) => this.handleActiveCellChange(e, args)); - this.grid.onKeyDown.subscribe(e => this.handleKeyDown(e)); - this.grid.onHeaderClick.subscribe((e: MouseEvent, args) => this.handleHeaderClick(e, args)); + this._handler.subscribe(this.grid.onActiveCellChanged, (e: Event, args: Slick.OnActiveCellChangedEventArgs) => this.handleActiveCellChange(e, args)); + this._handler.subscribe(this.grid.onKeyDown, (e: KeyboardEvent) => this.handleKeyDown(e)); + this._handler.subscribe(this.grid.onHeaderClick, (e: MouseEvent, args: Slick.OnHeaderClickEventArgs) => this.handleHeaderClick(e, args)); this.grid.registerPlugin(this.selector); - this.selector.onCellRangeSelected.subscribe((e, args) => this.handleCellRangeSelected(e, args)); - this.selector.onBeforeCellRangeSelected.subscribe((e, args) => this.handleBeforeCellRangeSelected(e, args)); + this._handler.subscribe(this.selector.onCellRangeSelected, (e: Event, range: Slick.Range) => this.handleCellRangeSelected(e, range)); + this._handler.subscribe(this.selector.onBeforeCellRangeSelected, (e: Event, cell: Slick.Cell) => this.handleBeforeCellRangeSelected(e, cell)); } public destroy() { - this.grid.onActiveCellChanged.unsubscribe((e, args) => this.handleActiveCellChange(e, args)); - this.grid.onKeyDown.unsubscribe(e => this.handleKeyDown(e)); - this.selector.onCellRangeSelected.unsubscribe((e, args) => this.handleCellRangeSelected(e, args)); - this.selector.onBeforeCellRangeSelected.unsubscribe((e, args) => this.handleBeforeCellRangeSelected(e, args)); + this._handler.unsubscribeAll(); this.grid.unregisterPlugin(this.selector); } @@ -81,7 +79,7 @@ export class CellSelectionModel implements Slick.SelectionModel implements Slick.SelectionModel) { if (this.options.selectActiveCell && !isUndefinedOrNull(args.row) && !isUndefinedOrNull(args.cell)) { this.setSelectedRanges([new Slick.Range(args.row, args.cell)]); } else if (!this.options.selectActiveCell) { @@ -120,7 +118,7 @@ export class CellSelectionModel implements Slick.SelectionModel implements Slick.SelectionModel implements Slick.SelectionModel `; -export class CheckboxSelectColumn implements Slick.Plugin { +export class CheckboxSelectColumn implements Slick.Plugin { private _options: ICheckboxSelectColumnOptions; private _grid: Slick.Grid; private _handler = new Slick.EventHandler(); - private _selectedRowsLookup = {}; + private _selectedRowsLookup: dict.INumberDictionary = {}; private _selectedCheckBoxLookup = {}; private _useState = false; @@ -64,10 +65,10 @@ export class CheckboxSelectColumn implements Slick.Plugin { public init(grid: Slick.Grid): void { this._grid = grid; this._handler - .subscribe(this._grid.onSelectedRowsChanged, (e, args) => this.handleSelectedRowsChanged(e, args)) - .subscribe(this._grid.onClick, (e, args) => this.handleClick(e, args)) - .subscribe(this._grid.onHeaderClick, (e, args) => this.handleHeaderClick(e, args)) - .subscribe(this._grid.onKeyDown, (e, args) => this.handleKeyDown(e, args)); + .subscribe(this._grid.onSelectedRowsChanged, (e: Event, args: Slick.OnSelectedRowsChangedEventArgs) => this.handleSelectedRowsChanged(e, args)) + .subscribe(this._grid.onClick, (e: MouseEvent, args: Slick.OnClickEventArgs) => this.handleClick(e, args)) + .subscribe(this._grid.onHeaderClick, (e: MouseEvent, args: Slick.OnHeaderClickEventArgs) => this.handleHeaderClick(e, args)) + .subscribe(this._grid.onKeyDown, (e: KeyboardEvent, args: Slick.OnKeyDownEventArgs) => this.handleKeyDown(e, args)); } public destroy(): void { @@ -82,7 +83,7 @@ export class CheckboxSelectColumn implements Slick.Plugin { } const selectedRows = this._grid.getSelectedRows(); - let lookup = {}, row, i; + let lookup: dict.INumberDictionary = {}, row: number, i: number; for (i = 0; i < selectedRows.length; i++) { row = selectedRows[i]; lookup[row] = true; @@ -91,9 +92,7 @@ export class CheckboxSelectColumn implements Slick.Plugin { delete this._selectedRowsLookup[row]; } } - for (i in this._selectedRowsLookup) { - this._grid.invalidateRow(i); - } + dict.forEach(this._selectedRowsLookup, (e) => this._grid.invalidateRow(e.key)); this._selectedRowsLookup = lookup; this._grid.render(); @@ -231,11 +230,11 @@ export class CheckboxSelectColumn implements Slick.Plugin { sortable: false, cssClass: this._options.cssClass, headerCssClass: this._options.headerCssClass, - formatter: (r, c, v, cd, dc) => this.checkboxSelectionFormatter(r, c, v, cd, dc) + formatter: (r, c, v, cd, dc) => this.checkboxSelectionFormatter(r, c, v, cd, dc as T) }; } - private checkboxSelectionFormatter(row, cell, value, columnDef: Slick.Column, dataContext): string { + private checkboxSelectionFormatter(row: number, cell: number, value: any, columnDef: Slick.Column, dataContext: T): string { if (this.isCustomActionRequested()) { return this.checkboxTemplateCustom(row); } diff --git a/src/sql/base/browser/ui/table/plugins/copyKeybind.plugin.ts b/src/sql/base/browser/ui/table/plugins/copyKeybind.plugin.ts index b0c6af3df2..375e8fbdc8 100644 --- a/src/sql/base/browser/ui/table/plugins/copyKeybind.plugin.ts +++ b/src/sql/base/browser/ui/table/plugins/copyKeybind.plugin.ts @@ -20,7 +20,7 @@ export class CopyKeybind implements Slick.Plugin { public init(grid: Slick.Grid) { this.grid = grid; - this.handler.subscribe(this.grid.onKeyDown, (e, args) => this.handleKeyDown(e, args)); + this.handler.subscribe(this.grid.onKeyDown, (e: KeyboardEvent, args: Slick.OnKeyDownEventArgs) => this.handleKeyDown(e, args)); } public destroy() { diff --git a/src/sql/base/browser/ui/table/plugins/headerFilter.plugin.ts b/src/sql/base/browser/ui/table/plugins/headerFilter.plugin.ts index c5d75a7372..35320298e6 100644 --- a/src/sql/base/browser/ui/table/plugins/headerFilter.plugin.ts +++ b/src/sql/base/browser/ui/table/plugins/headerFilter.plugin.ts @@ -1,46 +1,39 @@ // Adopted and converted to typescript from https://github.com/danny-sg/slickgrid-spreadsheet-plugins/blob/master/ext.headerfilter.js // heavily modified -import { mixin } from 'vs/base/common/objects'; import { IButtonStyles } from 'vs/base/browser/ui/button/button'; import { localize } from 'vs/nls'; import { Button } from 'sql/base/browser/ui/button/button'; import { escape } from 'sql/base/common/strings'; -export class HeaderFilter { +interface IExtendedColumn extends Slick.Column { + filterValues?: Array; +} + +export class HeaderFilter { public onFilterApplied = new Slick.Event(); public onCommand = new Slick.Event(); - private grid: Slick.Grid; + private grid: Slick.Grid; private handler = new Slick.EventHandler(); - private defaults = { - filterImage: 'src/sql/media/icons/filter.svg', - sortAscImage: 'sort-asc.gif', - sortDescImage: 'sort-desc.gif' - }; private $menu?: JQuery; - private options: any; private okButton: Button; private clearButton: Button; private cancelButton: Button; - private workingFilters: any; - private columnDef: any; + private workingFilters: Array; + private columnDef: IExtendedColumn; private buttonStyles: IButtonStyles; - constructor(options: any) { - this.options = mixin(options, this.defaults, false); - } - - public init(grid: Slick.Grid): void { + public init(grid: Slick.Grid): void { this.grid = grid; - this.handler.subscribe(this.grid.onHeaderCellRendered, (e, args) => this.handleHeaderCellRendered(e, args)) - .subscribe(this.grid.onBeforeHeaderCellDestroy, (e, args) => this.handleBeforeHeaderCellDestroy(e, args)) - .subscribe(this.grid.onClick, (e) => this.handleBodyMouseDown) + this.handler.subscribe(this.grid.onHeaderCellRendered, (e: Event, args: Slick.OnHeaderCellRenderedEventArgs) => this.handleHeaderCellRendered(e, args)) + .subscribe(this.grid.onBeforeHeaderCellDestroy, (e: Event, args: Slick.OnBeforeHeaderCellDestroyEventArgs) => this.handleBeforeHeaderCellDestroy(e, args)) + .subscribe(this.grid.onClick, (e: MouseEvent) => this.handleBodyMouseDown(e)) .subscribe(this.grid.onColumnsResized, () => this.columnsResized()) - .subscribe(this.grid.onKeyDown, (e) => this.handleKeyDown); + .subscribe(this.grid.onKeyDown, (e: KeyboardEvent) => this.handleKeyDown(e)); this.grid.setColumns(this.grid.getColumns()); jQuery(document.body).bind('mousedown', this.handleBodyMouseDown); @@ -53,7 +46,7 @@ export class HeaderFilter { jQuery(document.body).unbind('keydown', this.handleKeyDown); } - private handleKeyDown = (e) => { + private handleKeyDown(e: KeyboardEvent | JQuery.Event): void { if (this.$menu && (e.key === 'Escape' || e.keyCode === 27)) { this.hideMenu(); e.preventDefault(); @@ -61,8 +54,8 @@ export class HeaderFilter { } } - private handleBodyMouseDown = (e) => { - if (this.$menu && this.$menu[0] !== e.target && !jQuery.contains(this.$menu[0], e.target)) { + private handleBodyMouseDown(e: MouseEvent | JQuery.Event): void { + if (this.$menu && this.$menu[0] !== e.target && !jQuery.contains(this.$menu[0], e.target as Element)) { this.hideMenu(); e.preventDefault(); e.stopPropagation(); @@ -76,7 +69,7 @@ export class HeaderFilter { } } - private handleHeaderCellRendered(e, args) { + private handleHeaderCellRendered(e: Event, args: Slick.OnHeaderCellRenderedEventArgs) { const column = args.column; if (column.id === '_detail_selector') { return; @@ -88,13 +81,13 @@ export class HeaderFilter { $el.bind('click', (e) => this.showFilter(e)).appendTo(args.node); } - private handleBeforeHeaderCellDestroy(e, args) { + private handleBeforeHeaderCellDestroy(e: Event, args: Slick.OnBeforeHeaderCellDestroyEventArgs) { jQuery(args.node) .find('.slick-header-menubutton') .remove(); } - private addMenuItem(menu, columnDef, title, command, image) { + private addMenuItem(menu: JQuery, columnDef: Slick.Column, title: string, command: string) { const $item = jQuery('
') .data('command', command) .data('column', columnDef) @@ -115,7 +108,7 @@ export class HeaderFilter { .appendTo($item); } - private addMenuInput(menu, columnDef) { + private addMenuInput(menu: JQuery, columnDef: Slick.Column) { const self = this; jQuery('') .data('column', columnDef) @@ -126,7 +119,7 @@ export class HeaderFilter { .appendTo(menu); } - private updateFilterInputs(menu, columnDef, filterItems) { + private updateFilterInputs(menu: JQuery, columnDef: IExtendedColumn, filterItems: Array) { let filterOptions = ''; columnDef.filterValues = columnDef.filterValues || []; @@ -148,7 +141,7 @@ export class HeaderFilter { }); } - private showFilter(e) { + private showFilter(e: JQuery.Event) { const $menuButton = jQuery(e.target); this.columnDef = $menuButton.data('column'); @@ -157,15 +150,15 @@ export class HeaderFilter { // WorkingFilters is a copy of the filters to enable apply/cancel behaviour this.workingFilters = this.columnDef.filterValues.slice(0); - let filterItems; + let filterItems: Array; if (this.workingFilters.length === 0) { // Filter based all available values - filterItems = this.getFilterValues(this.grid.getData(), this.columnDef); + filterItems = this.getFilterValues(this.grid.getData() as Slick.DataProvider, this.columnDef); } else { // Filter based on current dataView subset - filterItems = this.getAllFilterValues(this.grid.getData().getItems(), this.columnDef); + filterItems = this.getAllFilterValues((this.grid.getData() as Slick.DataProvider).getItems(), this.columnDef); } if (!this.$menu) { @@ -174,8 +167,8 @@ export class HeaderFilter { this.$menu.empty(); - this.addMenuItem(this.$menu, this.columnDef, 'Sort Ascending', 'sort-asc', this.options.sortAscImage); - this.addMenuItem(this.$menu, this.columnDef, 'Sort Descending', 'sort-desc', this.options.sortDescImage); + this.addMenuItem(this.$menu, this.columnDef, 'Sort Ascending', 'sort-asc'); + this.addMenuItem(this.$menu, this.columnDef, 'Sort Descending', 'sort-desc'); this.addMenuInput(this.$menu, this.columnDef); let filterOptions = ''; @@ -209,7 +202,7 @@ export class HeaderFilter { this.clearButton.element.id = 'filter-clear-button'; const clearElement = jQuery('#filter-clear-button'); clearElement.bind('click', (ev) => { - this.columnDef.filterValues.length = 0; + this.columnDef.filterValues!.length = 0; this.setButtonImage($menuButton, false); this.handleApply(ev, this.columnDef); }); @@ -265,11 +258,11 @@ export class HeaderFilter { this.hideMenu(); } - private changeWorkingFilter(filterItems, workingFilters, $checkbox) { - const value = $checkbox.val(); + private changeWorkingFilter(filterItems: Array, workingFilters: Array, $checkbox: JQuery) { + const value = $checkbox.val() as number; const $filter = $checkbox.parent().parent(); - if ($checkbox.val() < 0) { + if ($checkbox.val() as number < 0) { // Select All if ($checkbox.prop('checked')) { jQuery(':checkbox', $filter).prop('checked', true); @@ -283,7 +276,7 @@ export class HeaderFilter { if ($checkbox.prop('checked') && index < 0) { workingFilters.push(filterItems[value]); - const nextRow = filterItems[(parseInt(value) + 1).toString()]; + const nextRow = filterItems[(parseInt(value) + 1).toString()]; // for some reason parseInt is defined as only supporting strings even though it works fine for numbers if (nextRow && nextRow.indexOf('Error:') >= 0) { workingFilters.push(nextRow); } @@ -298,7 +291,7 @@ export class HeaderFilter { return workingFilters; } - private setButtonImage($el, filtered) { + private setButtonImage($el: JQuery, filtered: boolean) { const element: HTMLElement = $el.get(0); if (filtered) { element.className += ' filtered'; @@ -310,7 +303,7 @@ export class HeaderFilter { } } - private handleApply(e, columnDef) { + private handleApply(e: JQuery.Event, columnDef: Slick.Column) { this.hideMenu(); this.onFilterApplied.notify({ 'grid': this.grid, 'column': columnDef }, e, self); @@ -318,10 +311,10 @@ export class HeaderFilter { e.stopPropagation(); } - private getFilterValues(dataView, column) { - const seen: Array = []; + private getFilterValues(dataView: Slick.DataProvider, column: Slick.Column): Array { + const seen: Array = []; for (let i = 0; i < dataView.getLength(); i++) { - const value = dataView.getItem(i)[column.field]; + const value = dataView.getItem(i)[column.field!]; if (!_.contains(seen, value)) { seen.push(value); @@ -330,10 +323,10 @@ export class HeaderFilter { return seen; } - private getFilterValuesByInput($input) { + private getFilterValuesByInput($input: JQuery): Array { const column = $input.data('column'), - filter = $input.val(), - dataView = this.grid.getData(), + filter = $input.val() as string, + dataView = this.grid.getData() as Slick.DataProvider, seen: Array = []; for (let i = 0; i < dataView.getLength(); i++) { @@ -357,10 +350,10 @@ export class HeaderFilter { return _.sortBy(seen, (v) => { return v; }); } - private getAllFilterValues(data, column) { + private getAllFilterValues(data: Array, column: Slick.Column) { const seen: Array = []; for (let i = 0; i < data.length; i++) { - const value = data[i][column.field]; + const value = data[i][column.field!]; if (!_.contains(seen, value)) { seen.push(value); @@ -370,7 +363,7 @@ export class HeaderFilter { return _.sortBy(seen, (v) => { return v; }); } - private handleMenuItemClick(e, command, columnDef) { + private handleMenuItemClick(e: JQuery.Event, command: string, columnDef: Slick.Column) { this.hideMenu(); this.onCommand.notify({ diff --git a/src/sql/base/browser/ui/table/plugins/rowDetailView.ts b/src/sql/base/browser/ui/table/plugins/rowDetailView.ts index 8c74664a24..83de2c43e2 100644 --- a/src/sql/base/browser/ui/table/plugins/rowDetailView.ts +++ b/src/sql/base/browser/ui/table/plugins/rowDetailView.ts @@ -4,44 +4,79 @@ import { escape } from 'sql/base/common/strings'; import { mixin } from 'vs/base/common/objects'; import * as nls from 'vs/nls'; -export class RowDetailView { +export interface IRowDetailViewOptions { + columnId?: string; + cssClass?: string; + toolTip?: string; + width?: number; + panelRows: number; + useRowClick?: boolean; + loadOnce?: boolean; + preTemplate: (item: ExtendedItem) => string; + process: (item: ExtendedItem) => void; + postTemplate: (item: ExtendedItem) => string; +} - public onAsyncResponse = new Slick.Event(); - public onAsyncEndUpdate = new Slick.Event(); - public onAfterRowDetailToggle = new Slick.Event(); - public onBeforeRowDetailToggle = new Slick.Event(); +const defaultOptions = { + columnId: '_detail_selector', + toolTip: '', + width: 30 +}; - private _grid: any; - private _expandedRows: any = []; +export interface IExtendedItem { + _collapsed?: boolean; + _parent?: IExtendedItem & T; + _detailContent?: string; + _detailViewLoaded?: boolean; + _sizePadding?: number; + id?: string; + _height?: number; + _isPadding?: boolean; + name?: string; + _child?: IExtendedItem; + message?: string; +} + +export type ExtendedItem = T & IExtendedItem; + +interface AugmentedDataView extends Slick.Data.DataView { + getItem(row: number): ExtendedItem; + getItemByIdx(row: number): ExtendedItem; +} + +export class RowDetailView { + + public readonly onAsyncResponse = new Slick.Event<{ itemDetail: ExtendedItem, detailView: string }>(); + public readonly onAsyncEndUpdate = new Slick.Event<{ grid: Slick.Grid, itemDetail: T }>(); + public readonly onAfterRowDetailToggle = new Slick.Event<{ grid: Slick.Grid, item: T }>(); + public readonly onBeforeRowDetailToggle = new Slick.Event<{ grid: Slick.Grid, item: T }>(); + + private _grid: Slick.Grid; + private _expandedRows: Array> = []; private _handler = new Slick.EventHandler(); - private _defaults: any = { - columnId: '_detail_selector', - cssClass: null, - toolTip: '', - width: 30 - }; - private _dataView: any; - private _options: any; + private _dataView: AugmentedDataView; + private _options: IRowDetailViewOptions; - constructor(options) { - this._options = mixin(options, this._defaults, false); + constructor(options: IRowDetailViewOptions) { + this._options = options || Object.create(null); + mixin(this._options, defaultOptions, false); } - public init(grid: any): void { + public init(grid: Slick.Grid): void { this._grid = grid; - this._dataView = this._grid.getData(); + this._dataView = this._grid.getData() as AugmentedDataView; // this is a bad assumption but the code is written with this assumption // Update the minRowBuffer so that the view doesn't disappear when it's at top of screen + the original default 3 this._grid.getOptions().minRowBuffer = this._options.panelRows + 3; this._handler - .subscribe(this._grid.onClick, (e, args) => this.handleClick(e, args)) - .subscribe(this._grid.onSort, (e, args) => this.handleSort(e, args)) - .subscribe(this._grid.onScroll, (e, args) => this.handleScroll(e, args)); + .subscribe(this._grid.onClick, (e: MouseEvent, args: Slick.OnClickEventArgs) => this.handleClick(e, args)) + .subscribe(this._grid.onSort, () => this.handleSort()) + .subscribe(this._grid.onScroll, () => this.handleScroll()); - this._grid.getData().onRowCountChanged.subscribe(() => { this._grid.updateRowCount(); this._grid.render(); }); - this._grid.getData().onRowsChanged.subscribe((e, a) => { this._grid.invalidateRows(a.rows); this._grid.render(); }); + this._dataView.onRowCountChanged.subscribe(() => { this._grid.updateRowCount(); this._grid.render(); }); + this._dataView.onRowsChanged.subscribe((e, a) => { this._grid.invalidateRows(a.rows); this._grid.render(); }); // subscribe to the onAsyncResponse so that the plugin knows when the user server side calls finished this.subscribeToOnAsyncResponse(); @@ -55,17 +90,17 @@ export class RowDetailView { this.onBeforeRowDetailToggle.unsubscribe(); } - public getOptions(options: any) { + public getOptions() { return this._options; } - public setOptions(options: any) { + public setOptions(options: IRowDetailViewOptions) { this._options = jQuery.extend(true, {}, this._options, options); } - public handleClick(e: any, args: any): void { + public handleClick(e: MouseEvent, args: Slick.OnClickEventArgs): void { // clicking on a row select checkbox - if (this._options.useRowClick || this._grid.getColumns()[args.cell].id === this._options.columnId && jQuery(e.target).hasClass('detailView-toggle')) { + if (this._options.useRowClick || this._grid.getColumns()[args.cell].id === this._options.columnId && jQuery(e.target!).hasClass('detailView-toggle')) { // if editing, try to commit if (this._grid.getEditorLock().isActive() && !this._grid.getEditorLock().commitCurrentEdit()) { e.preventDefault(); @@ -95,12 +130,12 @@ export class RowDetailView { } // Sort will just collapse all of the open items - public handleSort(e, args) { + public handleSort() { this.collapseAll(); } // If we scroll save detail views that go out of cache range - public handleScroll(e, args) { + public handleScroll() { const range = this._grid.getRenderedRange(); @@ -136,10 +171,10 @@ export class RowDetailView { } // Toggle between showing and hiding a row - public toggleRowSelection(row) { - this._grid.getData().beginUpdate(); + public toggleRowSelection(row: T) { + this._dataView.beginUpdate(); this.handleAccordionShowHide(row); - this._grid.getData().endUpdate(); + this._dataView.endUpdate(); } // Collapse all of the open items @@ -150,7 +185,7 @@ export class RowDetailView { } // Saves the current state of the detail view - public saveDetailView(item) { + public saveDetailView(item: ExtendedItem) { const view = jQuery('#innerDetailView_' + item.id); if (view) { const html = jQuery('#innerDetailView_' + item.id).html(); @@ -161,7 +196,7 @@ export class RowDetailView { } // Colapse an Item so it is notlonger seen - public collapseItem(item) { + public collapseItem(item: ExtendedItem) { // Save the details on the collapse assuming onetime loading if (this._options.loadOnce) { @@ -169,11 +204,11 @@ export class RowDetailView { } item._collapsed = true; - for (let idx = 1; idx <= item._sizePadding; idx++) { + for (let idx = 1; idx <= item._sizePadding!; idx++) { this._dataView.deleteItem(item.id + '.' + idx); } item._sizePadding = 0; - this._dataView.updateItem(item.id, item); + this._dataView.updateItem(item.id!, item); // Remove the item from the expandedRows this._expandedRows = this._expandedRows.filter((r) => { @@ -182,7 +217,7 @@ export class RowDetailView { } // Expand a row given the dataview item that is to be expanded - public expandItem(item) { + public expandItem(item: ExtendedItem) { item._collapsed = false; this._expandedRows.push(item); @@ -197,16 +232,16 @@ export class RowDetailView { } else { this.onAsyncResponse.notify({ itemDetail: item, - detailView: item._detailContent + detailView: item._detailContent! }, undefined, this); this.applyTemplateNewLineHeight(item); - this._dataView.updateItem(item.id, item); + this._dataView.updateItem(item.id!, item); return; } this.applyTemplateNewLineHeight(item); - this._dataView.updateItem(item.id, item); + this._dataView.updateItem(item.id!, item); // async server call this._options.process(item); @@ -231,7 +266,7 @@ export class RowDetailView { args.itemDetail._detailViewLoaded = true; - this._dataView.updateItem(args.itemDetail.id, args.itemDetail); + this._dataView.updateItem(args.itemDetail.id!, args.itemDetail); // trigger an event once the post template is finished loading this.onAsyncEndUpdate.notify({ @@ -241,7 +276,7 @@ export class RowDetailView { }); } - public handleAccordionShowHide(item) { + public handleAccordionShowHide(item?: ExtendedItem) { if (item) { if (!item._collapsed) { this.collapseItem(item); @@ -253,7 +288,7 @@ export class RowDetailView { ////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// - public getPaddingItem(parent, offset) { + public getPaddingItem(parent: ExtendedItem, offset: number | string) { const item: any = {}; for (const prop in this._grid.getData()) { @@ -265,18 +300,16 @@ export class RowDetailView { item._collapsed = true; item._isPadding = true; item._parent = parent; - item._offset = offset; return item; } - public getErrorItem(parent, offset) { - const item: any = {}; + public getErrorItem(parent: ExtendedItem, offset: number | string) { + const item: ExtendedItem = Object.create(null); item.id = parent.id + '.' + offset; item._collapsed = true; item._isPadding = false; item._parent = parent; - item._offset = offset; item.name = parent.message ? parent.message : nls.localize('rowDetailView.loadError', 'Loading Error...'); parent._child = item; return item; @@ -285,17 +318,17 @@ export class RowDetailView { ////////////////////////////////////////////////////////////// //create the detail ctr node. this belongs to the dev & can be custom-styled as per ////////////////////////////////////////////////////////////// - public applyTemplateNewLineHeight(item, showError = false) { + public applyTemplateNewLineHeight(item: ExtendedItem, showError = false) { // the height seems to be calculated by the template row count (how many line of items does the template have) const rowCount = this._options.panelRows; //calculate padding requirements based on detail-content.. //ie. worst-case: create an invisible dom node now &find it's height. const lineHeight = 13; //we know cuz we wrote the custom css innit ;) - item._sizePadding = Math.ceil(((rowCount * 2) * lineHeight) / this._grid.getOptions().rowHeight); - item._height = (item._sizePadding * this._grid.getOptions().rowHeight); + item._sizePadding = Math.ceil(((rowCount * 2) * lineHeight) / this._grid.getOptions().rowHeight!); + item._height = (item._sizePadding * this._grid.getOptions().rowHeight!); - const idxParent = this._dataView.getIdxById(item.id); + const idxParent = this._dataView.getIdxById(item.id!); for (let idx = 1; idx <= item._sizePadding; idx++) { if (showError) { this._dataView.insertItem(idxParent + idx, this.getErrorItem(item, 'error')); @@ -305,7 +338,7 @@ export class RowDetailView { } } - public getColumnDefinition() { + public getColumnDefinition(): Slick.Column { return { id: this._options.columnId, name: '', @@ -315,11 +348,11 @@ export class RowDetailView { resizable: false, sortable: false, cssClass: this._options.cssClass, - formatter: (row, cell, value, columnDef, dataContext) => this.detailSelectionFormatter(row, cell, value, columnDef, dataContext) + formatter: (row, cell, value, columnDef, dataContext) => this.detailSelectionFormatter(row, cell, value, columnDef, dataContext as ExtendedItem) }; } - public detailSelectionFormatter(row, cell, value, columnDef, dataContext) { + public detailSelectionFormatter(row: number, cell: number, value: any, columnDef: Slick.Column, dataContext: ExtendedItem): string | undefined { if (dataContext._collapsed === undefined) { dataContext._collapsed = true; @@ -327,7 +360,6 @@ export class RowDetailView { dataContext._height = 0; //the actual height in pixels of the detail field dataContext._isPadding = false; dataContext._parent = undefined; - dataContext._offset = 0; } if (dataContext._isPadding === true) { @@ -336,7 +368,7 @@ export class RowDetailView { return '
'; } else { const html: Array = []; - const rowHeight = this._grid.getOptions().rowHeight; + const rowHeight = this._grid.getOptions().rowHeight!; const bottomMargin = 5; //V313HAX: @@ -353,59 +385,12 @@ export class RowDetailView { html.push(`
`); //shift detail below 1st row - html.push(`
`); //sub ctr for custom styling - html.push(`
${escape(dataContext._detailContent)}
`); + html.push(`
`); //sub ctr for custom styling + html.push(`
${escape(dataContext._detailContent!)}
`); //&omit a final closing detail container
that would come next return html.join(''); } - return null; - } - - public resizeDetailView(item) { - if (!item) { - return; - } - - // Grad each of the dom items - const mainContainer = document.getElementById('detailViewContainer_' + item.id); - const cellItem = document.getElementById('cellDetailView_' + item.id); - const inner = document.getElementById('innerDetailView_' + item.id); - - if (!mainContainer || !cellItem || !inner) { - return; - } - - for (let idx = 1; idx <= item._sizePadding; idx++) { - this._dataView.deleteItem(item.id + '.' + idx); - } - - const rowHeight = this._grid.getOptions().rowHeight; // height of a row - const lineHeight = 13; //we know cuz we wrote the custom css innit ;) - - // Get the inner Item height as this will be the actual size - const itemHeight = inner.clientHeight; - - // Now work out how many rows - const rowCount = Math.ceil(itemHeight / rowHeight) + 1; - - item._sizePadding = Math.ceil(((rowCount * 2) * lineHeight) / rowHeight); - item._height = (item._sizePadding * rowHeight); - - // If the padding is now more than the original minRowBuff we need to increase it - if (this._grid.getOptions().minRowBuffer < item._sizePadding) { - // Update the minRowBuffer so that the view doesn't disappear when it's at top of screen + the original default 3 - this._grid.getOptions().minRowBuffer = item._sizePadding + 3; - } - - mainContainer.setAttribute('style', `max-height: ${item._height}px`); - if (cellItem) { - cellItem.setAttribute('style', `height: ${item._height}px;top:${rowHeight}px`); - } - - const idxParent = this._dataView.getIdxById(item.id); - for (let idx = 1; idx <= item._sizePadding; idx++) { - this._dataView.insertItem(idxParent + idx, this.getPaddingItem(item, idx)); - } + return undefined; } } diff --git a/src/sql/base/browser/ui/table/plugins/rowNumberColumn.plugin.ts b/src/sql/base/browser/ui/table/plugins/rowNumberColumn.plugin.ts index 51fed5ec69..cb3ea21b16 100644 --- a/src/sql/base/browser/ui/table/plugins/rowNumberColumn.plugin.ts +++ b/src/sql/base/browser/ui/table/plugins/rowNumberColumn.plugin.ts @@ -18,8 +18,8 @@ export class RowNumberColumn implements Slick.Plugin { public init(grid: Slick.Grid) { this.grid = grid; this.handler - .subscribe(this.grid.onClick, (e, args) => this.handleClick(e, args)) - .subscribe(this.grid.onHeaderClick, (e, args) => this.handleHeaderClick(e, args)); + .subscribe(this.grid.onClick, (e: MouseEvent, args: Slick.OnClickEventArgs) => this.handleClick(e, args)) + .subscribe(this.grid.onHeaderClick, (e: MouseEvent, args: Slick.OnHeaderClickEventArgs) => this.handleHeaderClick(e, args)); } public destroy() { @@ -56,11 +56,11 @@ export class RowNumberColumn implements Slick.Plugin { cssClass: this.options.cssClass, focusable: false, selectable: false, - formatter: (r, c, v, cd, dc) => this.formatter(r, c, v, cd, dc) + formatter: r => this.formatter(r) }; } - private formatter(row, cell, value, columnDef: Slick.Column, dataContext): string { + private formatter(row: number): string { // row is zero-based, we need make it 1 based for display in the result grid return `${row + 1}`; } diff --git a/src/sql/base/browser/ui/table/plugins/rowSelectionModel.plugin.ts b/src/sql/base/browser/ui/table/plugins/rowSelectionModel.plugin.ts index 37b3aafbd2..35d9eb42e8 100644 --- a/src/sql/base/browser/ui/table/plugins/rowSelectionModel.plugin.ts +++ b/src/sql/base/browser/ui/table/plugins/rowSelectionModel.plugin.ts @@ -25,9 +25,9 @@ export class RowSelectionModel implements Slick.Selec public init(grid: Slick.Grid) { this._grid = grid; this._handler - .subscribe(this._grid.onActiveCellChanged, (e, data) => this.handleActiveCellChange(e, data)) - .subscribe(this._grid.onKeyDown, e => this.handleKeyDown(e)) - .subscribe(this._grid.onClick, e => this.handleClick(e)); + .subscribe(this._grid.onActiveCellChanged, (e: Event, data: Slick.OnActiveCellChangedEventArgs) => this.handleActiveCellChange(e, data)) + .subscribe(this._grid.onKeyDown, (e: KeyboardEvent) => this.handleKeyDown(e)) + .subscribe(this._grid.onClick, (e: MouseEvent) => this.handleClick(e)); } private rangesToRows(ranges: Slick.Range[]): number[] { @@ -116,7 +116,7 @@ export class RowSelectionModel implements Slick.Selec } } - private handleClick(e: KeyboardEvent): boolean { + private handleClick(e: MouseEvent): boolean { const cell = this._grid.getCellFromEvent(e); if (!cell || !this._grid.canCellBeActive(cell.row, cell.cell)) { return false; diff --git a/src/sql/base/browser/ui/table/tableDataView.ts b/src/sql/base/browser/ui/table/tableDataView.ts index 116e2a7fb9..8e8c7a6738 100644 --- a/src/sql/base/browser/ui/table/tableDataView.ts +++ b/src/sql/base/browser/ui/table/tableDataView.ts @@ -117,6 +117,10 @@ export class TableDataView implements IDisposableData return this._data[index]; } + getItems(): T[] { + return this._data.slice(); + } + getLengthNonFiltered(): number { return this.filterEnabled ? this._allData.length : this._data.length; } diff --git a/src/sql/base/test/browser/ui/table/tableDataView.test.ts b/src/sql/base/test/browser/ui/table/tableDataView.test.ts index cc389895f1..a9730b1293 100644 --- a/src/sql/base/test/browser/ui/table/tableDataView.test.ts +++ b/src/sql/base/test/browser/ui/table/tableDataView.test.ts @@ -19,7 +19,7 @@ suite('TableDataView', () => { let rowCountEventInvokeCount = 0; let filterStateChangeEventInvokeCount = 0; - let rowCountEventParameter; + let rowCountEventParameter: number; obj.onRowCountChange((count) => { rowCountEventInvokeCount++; rowCountEventParameter = count; diff --git a/src/sql/workbench/parts/jobManagement/electron-browser/alertsView.component.ts b/src/sql/workbench/parts/jobManagement/electron-browser/alertsView.component.ts index 4aafc72c32..988930071f 100644 --- a/src/sql/workbench/parts/jobManagement/electron-browser/alertsView.component.ts +++ b/src/sql/workbench/parts/jobManagement/electron-browser/alertsView.component.ts @@ -134,7 +134,10 @@ export class AlertsViewComponent extends JobManagementView implements OnInit, On let rowDetail = new RowDetailView({ cssClass: '_detail_selector', useRowClick: false, - panelRows: 1 + panelRows: 1, + postTemplate: () => '', // I'm assuming these code paths are just never hit... + preTemplate: () => '', + process: () => { } }); columns.unshift(rowDetail.getColumnDefinition()); jQuery(this._gridEl.nativeElement).empty(); diff --git a/src/sql/workbench/parts/jobManagement/electron-browser/jobsView.component.ts b/src/sql/workbench/parts/jobManagement/electron-browser/jobsView.component.ts index 60061fa98e..5855eab7de 100644 --- a/src/sql/workbench/parts/jobManagement/electron-browser/jobsView.component.ts +++ b/src/sql/workbench/parts/jobManagement/electron-browser/jobsView.component.ts @@ -37,6 +37,11 @@ export const JOBSVIEW_SELECTOR: string = 'jobsview-component'; export const ROW_HEIGHT: number = 45; export const ACTIONBAR_PADDING: number = 10; +interface IItem extends Slick.SlickData { + jobId?: string; + id: string; +} + @Component({ selector: JOBSVIEW_SELECTOR, templateUrl: decodeURI(require.toUrl('./jobsView.component.html')), @@ -71,7 +76,7 @@ export class JobsViewComponent extends JobManagementView implements OnInit, OnDe ]; private _jobCacheObject: JobCacheObject; - private rowDetail: RowDetailView; + private rowDetail: RowDetailView; private filterPlugin: any; private dataView: any; private _isCloud: boolean; @@ -161,7 +166,7 @@ export class JobsViewComponent extends JobManagementView implements OnInit, OnDe this.dataView = new Slick.Data.DataView({ inlineFilters: false }); - let rowDetail = new RowDetailView({ + let rowDetail = new RowDetailView({ cssClass: '_detail_selector', process: (job) => { (rowDetail).onAsyncResponse.notify({ @@ -169,11 +174,13 @@ export class JobsViewComponent extends JobManagementView implements OnInit, OnDe }, undefined, this); }, useRowClick: false, - panelRows: 1 + panelRows: 1, + postTemplate: () => '', // I'm assuming these code paths are just never hit... + preTemplate: () => '', }); this.rowDetail = rowDetail; columns.unshift(this.rowDetail.getColumnDefinition()); - let filterPlugin = new HeaderFilter({}); + let filterPlugin = new HeaderFilter<{ inlineFilters: false }>(); this._register(attachButtonStyler(filterPlugin, this._themeService)); this.filterPlugin = filterPlugin; jQuery(this._gridEl.nativeElement).empty(); @@ -337,7 +344,7 @@ export class JobsViewComponent extends JobManagementView implements OnInit, OnDe this.filterPlugin.onCommand.subscribe((e, args: any) => { this.columnSort(args.column.name, args.command === 'sort-asc'); }); - this._table.registerPlugin(this.filterPlugin); + this._table.registerPlugin(this.filterPlugin); this.dataView.beginUpdate(); this.dataView.setItems(jobViews); @@ -900,7 +907,7 @@ export class JobsViewComponent extends JobManagementView implements OnInit, OnDe } protected getCurrentTableObject(rowIndex: number): JobActionContext { - let data = this._table.grid.getData(); + let data = this._table.grid.getData() as Slick.DataProvider; if (!data || rowIndex >= data.getLength()) { return undefined; } diff --git a/src/sql/workbench/parts/jobManagement/electron-browser/operatorsView.component.ts b/src/sql/workbench/parts/jobManagement/electron-browser/operatorsView.component.ts index 249b485055..9f392f1cbc 100644 --- a/src/sql/workbench/parts/jobManagement/electron-browser/operatorsView.component.ts +++ b/src/sql/workbench/parts/jobManagement/electron-browser/operatorsView.component.ts @@ -134,7 +134,10 @@ export class OperatorsViewComponent extends JobManagementView implements OnInit, let rowDetail = new RowDetailView({ cssClass: '_detail_selector', useRowClick: false, - panelRows: 1 + panelRows: 1, + postTemplate: () => '', // I'm assuming these code paths are just never hit... + preTemplate: () => '', + process: () => { } }); columns.unshift(rowDetail.getColumnDefinition()); diff --git a/src/sql/workbench/parts/jobManagement/electron-browser/proxiesView.component.ts b/src/sql/workbench/parts/jobManagement/electron-browser/proxiesView.component.ts index 6d3fc32178..f9d83a0975 100644 --- a/src/sql/workbench/parts/jobManagement/electron-browser/proxiesView.component.ts +++ b/src/sql/workbench/parts/jobManagement/electron-browser/proxiesView.component.ts @@ -137,7 +137,10 @@ export class ProxiesViewComponent extends JobManagementView implements OnInit, O let rowDetail = new RowDetailView({ cssClass: '_detail_selector', useRowClick: false, - panelRows: 1 + panelRows: 1, + postTemplate: () => '', // I'm assuming these code paths are just never hit... + preTemplate: () => '', + process: () => { } }); columns.unshift(rowDetail.getColumnDefinition()); diff --git a/src/sql/workbench/parts/notebook/notebook.component.ts b/src/sql/workbench/parts/notebook/notebook.component.ts index dd43aa47fd..5bc046dbff 100644 --- a/src/sql/workbench/parts/notebook/notebook.component.ts +++ b/src/sql/workbench/parts/notebook/notebook.component.ts @@ -423,7 +423,7 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe // Check extensions to create ActionItem; otherwise, return undefined // This is similar behavior that exists in MenuItemActionItem if (action instanceof MenuItemAction) { - return new LabeledMenuItemActionItem(action, this.keybindingService, this.notificationService, this.contextMenuService, 'notebook-button'); + return new LabeledMenuItemActionItem(action, this.keybindingService, this.contextMenuService, this.notificationService, 'notebook-button'); } return undefined; } diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 50b604a73a..3364214030 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -1,8 +1,10 @@ { - "extends": "./tsconfig.base.json", + "extends": "./tsconfig.json", "compilerOptions": { "noEmit": true, "strictNullChecks": true, + "noImplicitAny": true, + "suppressImplicitAnyIndexErrors": true, "moduleResolution": "classic" }, "include": [ @@ -11,6 +13,8 @@ "./vs/vscode.proposed.d.ts", "./sql/azdata.d.ts", "./sql/azdata.proposed.d.ts", + "./vs/base/**/*.ts", + "./vs/platform/**/*.ts", "./sql/base/**/*.ts", "./sql/platform/angularEventing/**/*.ts", "./sql/platform/clipboard/**/*.ts", diff --git a/src/typings/globals/slickgrid/index.d.ts b/src/typings/globals/slickgrid/index.d.ts index 16617e2c00..a73a9a34a3 100644 --- a/src/typings/globals/slickgrid/index.d.ts +++ b/src/typings/globals/slickgrid/index.d.ts @@ -96,8 +96,8 @@ declare namespace Slick { export class EventHandler { constructor(); - public subscribe(event: Event, handler: Function): EventHandler; - public unsubscribe(event: Event, handler: Function): EventHandler; + public subscribe(event: Event, handler: (event: DOMEvent, args: T) => void): EventHandler; + public unsubscribe(event: Event, handler: (event: DOMEvent, args: T) => void): EventHandler; public unsubscribeAll(): EventHandler; } @@ -668,6 +668,11 @@ declare namespace Slick { * Page grid when navigating */ emulatePagingWhenScrolling?: boolean; + + /** + * + */ + minRowBuffer?: number; } export interface DataProvider { @@ -687,10 +692,14 @@ declare namespace Slick { * @param index */ getItemMetadata?(index: number): RowMetadata; + + /** + * + */ + getItems(): Array; } - export interface SlickData { - // todo ? might be able to leave as empty + export interface SlickData extends Object { } export interface RowMetadata { @@ -772,7 +781,7 @@ declare namespace Slick { /** * Sets selected ranges for the grid */ - setSelectedRanges(ranges: Slick.Range[]); + setSelectedRanges(ranges: Slick.Range[]): void; /** * Gets selected ranges for the grid @@ -818,10 +827,7 @@ declare namespace Slick { * Returns an array of every data object, unless you're using DataView in which case it returns a DataView object. * @return **/ - public getData(): any; - //public getData(): T[]; - // Issue: typescript limitation, cannot differentiate calls by return type only, so need to cast to DataView or T[]. - //public getData(): DataView; + public getData(): T[] | DataProvider; /** * Returns the databinding item at a given position. @@ -1228,7 +1234,7 @@ declare namespace Slick { public render(): void; public invalidate(): void; public invalidateRow(row: number): void; - public invalidateRows(rows: number[], keepEditor: boolean): void; + public invalidateRows(rows: number[], keepEditor?: boolean): void; public invalidateAllRows(): void; public updateCell(row: number, cell: number): void; public updateRow(row: number): void; @@ -1543,7 +1549,7 @@ declare namespace Slick { } export interface Formatter { - (row: number, cell: number, value: any, columnDef: Column, dataContext: SlickData): string; + (row: number, cell: number, value: any, columnDef: Column, dataContext: SlickData): string | undefined; } export module Formatters { diff --git a/src/typings/modules/angular2-slickgrid/index.d.ts b/src/typings/modules/angular2-slickgrid/index.d.ts index cb7dc2ff41..aa4088a867 100644 --- a/src/typings/modules/angular2-slickgrid/index.d.ts +++ b/src/typings/modules/angular2-slickgrid/index.d.ts @@ -1,5 +1,5 @@ // Generated by typings -// Source: node_modules/angular2-slickgrid/out/js/interfaces.d.ts +// Source: ../node_modules/angular2-slickgrid/out/js/interfaces.d.ts declare module '~angular2-slickgrid/out/js/interfaces' { import { Observable } from 'rxjs/Rx'; export enum NotificationType { @@ -21,6 +21,7 @@ export interface IObservableCollection { at(index: number): T; getRange(start: number, end: number): T[]; setCollectionChangedCallback(callback: (change: CollectionChange, startIndex: number, count: number) => void): void; + resetWindowsAroundIndex(index: number): void; } export class CancellationToken { private _isCanceled; @@ -33,10 +34,6 @@ export interface IGridColumnDefinition { id: string; type: number; } -export interface IGridDataRow { - row?: number; - values: any[]; -} export interface ISlickColumn extends Slick.Column { isEditable?: boolean; } @@ -46,7 +43,7 @@ export * from '~angular2-slickgrid/out/js/interfaces'; } // Generated by typings -// Source: node_modules/angular2-slickgrid/out/js/selectionModel.d.ts +// Source: ../node_modules/angular2-slickgrid/out/js/selectionModel.d.ts declare module '~angular2-slickgrid/out/js/selectionModel' { import { ISelectionRange } from '~angular2-slickgrid/out/js/interfaces'; export class SelectionModel implements ISlickSelectionModel { @@ -106,20 +103,16 @@ export * from '~angular2-slickgrid/out/js/selectionModel'; } // Generated by typings -// Source: node_modules/angular2-slickgrid/out/js/slickGrid.d.ts +// Source: ../node_modules/angular2-slickgrid/out/js/slickGrid.d.ts declare module '~angular2-slickgrid/out/js/slickGrid' { import { OnChanges, OnInit, OnDestroy, SimpleChange, EventEmitter, AfterViewInit } from '@angular/core'; import { Observable } from 'rxjs/Rx'; -import { IObservableCollection, IGridDataRow, ISlickColumn } from '~angular2-slickgrid/out/js/interfaces'; -export class OnRangeRenderCompletedEventArgs { - startRow: number; - endRow: number; -} +import { IObservableCollection, ISlickColumn } from '~angular2-slickgrid/out/js/interfaces'; export function getOverridableTextEditorClass(grid: SlickGrid): any; export class SlickGrid implements OnChanges, OnInit, OnDestroy, AfterViewInit { private _el; columnDefinitions: ISlickColumn[]; - dataRows: IObservableCollection; + dataRows: IObservableCollection<{}>; resized: Observable; highlightedCells: { row: number; @@ -135,23 +128,18 @@ export class SlickGrid implements OnChanges, OnInit, OnDestroy, AfterViewInit { plugins: Array>; enableEditing: boolean; topRowNumber: number; - overrideCellFn: (rowNumber, columnId, value?, data?) => string; + overrideCellFn: (rowNumber: number, columnId: number, value?: any, data?: any) => string; isCellEditValid: (row: number, column: number, newValue: any) => boolean; + onBeforeAppendCell: (row: number, column: number) => string; loadFinished: EventEmitter; - onContextMenu: EventEmitter>; + onContextMenu: EventEmitter; onScroll: EventEmitter>; onActiveCellChanged: EventEmitter>; onBeforeEditCell: EventEmitter>; onCellChange: EventEmitter>; + onRendered: EventEmitter>; onFocus(): void; rowHeight: number; - private _rowHeight; - private _grid; - private _gridColumns; - private _columnNameToIndex; - private _gridData; - private _resizeSubscription; - private _gridSyncSubscription; constructor(_el: any); ngOnChanges(changes: { [propName: string]: SimpleChange; @@ -168,17 +156,7 @@ export class SlickGrid implements OnChanges, OnInit, OnDestroy, AfterViewInit { registerPlugin(plugin: Slick.Plugin | string): void; setActive(): void; selection: Slick.Range[] | boolean; - private initGrid(); - private changeEditSession(enabled); - private onResize(); - private invalidateRange(start, end); - private getColumnEditor(column); - private getFormatter; - private setupEvents(); - private updateSchema(); - private setCallbackOnDataRowsChanged(); readonly activeCell: Slick.Cell; - private renderGridDataRowsRange(startIndex, count); } } declare module 'angular2-slickgrid/out/js/slickGrid' { @@ -186,25 +164,16 @@ export * from '~angular2-slickgrid/out/js/slickGrid'; } // Generated by typings -// Source: node_modules/angular2-slickgrid/out/js/virtualizedCollection.d.ts +// Source: ../node_modules/angular2-slickgrid/out/js/virtualizedCollection.d.ts declare module '~angular2-slickgrid/out/js/virtualizedCollection' { import { IObservableCollection, CollectionChange } from '~angular2-slickgrid/out/js/interfaces'; export class VirtualizedCollection implements IObservableCollection { - private _placeHolderGenerator; - private _length; - private _windowSize; - private _bufferWindowBefore; - private _window; - private _bufferWindowAfter; - private collectionChangedCallback; constructor(windowSize: number, length: number, loadFn: (offset: number, count: number) => Promise, _placeHolderGenerator: (index: number) => TData); setCollectionChangedCallback(callback: (change: CollectionChange, startIndex: number, count: number) => void): void; getLength(): number; at(index: number): TData; getRange(start: number, end: number): TData[]; - private getRangeFromCurrent(start, end); - private getDataFromCurrent(index); - resetWindowsAroundIndex(index); + resetWindowsAroundIndex(index: number): void; } } declare module 'angular2-slickgrid/out/js/virtualizedCollection' { @@ -212,7 +181,7 @@ export * from '~angular2-slickgrid/out/js/virtualizedCollection'; } // Generated by typings -// Source: node_modules/angular2-slickgrid/out/index.d.ts +// Source: ../node_modules/angular2-slickgrid/out/index.d.ts declare module '~angular2-slickgrid/out/index' { export * from '~angular2-slickgrid/out/js/interfaces'; export * from '~angular2-slickgrid/out/js/selectionModel'; diff --git a/src/vs/base/common/collections.ts b/src/vs/base/common/collections.ts index a861efe664..84d731afbc 100644 --- a/src/vs/base/common/collections.ts +++ b/src/vs/base/common/collections.ts @@ -58,6 +58,8 @@ export function first(from: IStringDictionary | INumberDictionary): T | * Iterates over each entry in the provided set. The iterator allows * to remove elements and will stop when the callback returns {{false}}. */ +export function forEach(from: IStringDictionary, callback: (entry: { key: string; value: T; }, remove: () => void) => any): void; // {{SQL CARBON EDIT}} @anthonydresser add hard typings +export function forEach(from: INumberDictionary, callback: (entry: { key: number; value: T; }, remove: () => void) => any): void; export function forEach(from: IStringDictionary | INumberDictionary, callback: (entry: { key: any; value: T; }, remove: () => void) => any): void { for (let key in from) { if (hasOwnProperty.call(from, key)) { @@ -96,4 +98,4 @@ export function fromMap(original: Map): IStringDictionary { }); } return result; -} \ No newline at end of file +} diff --git a/src/vs/platform/actions/browser/menuEntryActionViewItem.ts b/src/vs/platform/actions/browser/menuEntryActionViewItem.ts index 9100366c47..7b190e4b6c 100644 --- a/src/vs/platform/actions/browser/menuEntryActionViewItem.ts +++ b/src/vs/platform/actions/browser/menuEntryActionViewItem.ts @@ -274,16 +274,16 @@ export class ContextAwareMenuEntryActionViewItem extends MenuEntryActionViewItem // an icon/CSS class. Useful for some toolbar scenarios in particular with // contributed actions from other extensions export class LabeledMenuItemActionItem extends MenuEntryActionViewItem { - private _labeledItemClassDispose: IDisposable; + private _labeledItemClassDispose?: IDisposable; constructor( public _action: MenuItemAction, - @IKeybindingService private readonly _labeledkeybindingService: IKeybindingService, + @IKeybindingService labeledkeybindingService: IKeybindingService, + @IContextMenuService labeledcontextMenuService: IContextMenuService, @INotificationService protected _notificationService: INotificationService, - @IContextMenuService private readonly _labeledcontextMenuService: IContextMenuService, private readonly _defaultCSSClassToAdd: string = '' ) { - super(_action, _labeledkeybindingService, _notificationService, _labeledcontextMenuService); + super(_action, labeledkeybindingService, _notificationService, labeledcontextMenuService); } updateLabel(): void { @@ -302,7 +302,7 @@ export class LabeledMenuItemActionItem extends MenuEntryActionViewItem { const iconPathMapKey = item.iconLocation.dark.toString(); if (MenuEntryActionViewItem.ICON_PATH_TO_CSS_RULES.has(iconPathMapKey)) { - iconClass = MenuEntryActionViewItem.ICON_PATH_TO_CSS_RULES.get(iconPathMapKey); + iconClass = MenuEntryActionViewItem.ICON_PATH_TO_CSS_RULES.get(iconPathMapKey)!; } else { iconClass = ids.nextId(); createCSSRule(`.icon.${iconClass}`, `background-image: url("${(item.iconLocation.light || item.iconLocation.dark).toString()}")`); diff --git a/src/vs/platform/extensionManagement/node/extensionGalleryService.ts b/src/vs/platform/extensionManagement/node/extensionGalleryService.ts index a150e82561..0050543941 100644 --- a/src/vs/platform/extensionManagement/node/extensionGalleryService.ts +++ b/src/vs/platform/extensionManagement/node/extensionGalleryService.ts @@ -259,7 +259,7 @@ function getVersionAsset(version: IRawGalleryExtensionVersion, type: string): IG const result = version.files.filter(f => f.assetType === type)[0]; // {{SQL CARBON EDIT}} - let uriFromSource: string = undefined; + let uriFromSource: string | undefined; if (result) { uriFromSource = result.source; } @@ -275,7 +275,7 @@ function getVersionAsset(version: IRawGalleryExtensionVersion, type: string): IG fallbackUri: `${version.fallbackAssetUri}/${type}` }; } else { - return result ? { uri: uriFromSource, fallbackUri: `${version.fallbackAssetUri}/${type}` } : null; + return result ? { uri: uriFromSource!, fallbackUri: `${version.fallbackAssetUri}/${type}` } : null; } // return result ? { uri: `${version.assetUri}/${type}`, fallbackUri: `${version.fallbackAssetUri}/${type}` } : null; // {{SQL CARBON EDIT}} - End @@ -410,7 +410,7 @@ export class ExtensionGalleryService implements IExtensionGalleryService { if (extension) { return Promise.resolve(extension); } - const { id, uuid } = extension ? extension.identifier : arg1; + const { id, uuid } = arg1; // {{SQL CARBON EDIT}} @anthonydresser remove extension ? extension.identifier let query = new Query() .withFlags(Flags.IncludeAssetUri, Flags.IncludeStatistics, Flags.IncludeFiles, Flags.IncludeVersionProperties, Flags.ExcludeNonValidated) .withPage(1, 1) @@ -542,15 +542,15 @@ export class ExtensionGalleryService implements IExtensionGalleryService { // Filtering let filteredExtensions = galleryExtensions; if (query.criteria) { - const ids = query.criteria.filter(x => x.filterType === FilterType.ExtensionId).map(v => v.value.toLocaleLowerCase()); + const ids = query.criteria.filter(x => x.filterType === FilterType.ExtensionId).map(v => v.value ? v.value.toLocaleLowerCase() : undefined); if (ids && ids.length > 0) { filteredExtensions = filteredExtensions.filter(e => e.extensionId && ids.includes(e.extensionId.toLocaleLowerCase())); } - const names = query.criteria.filter(x => x.filterType === FilterType.ExtensionName).map(v => v.value.toLocaleLowerCase()); + const names = query.criteria.filter(x => x.filterType === FilterType.ExtensionName).map(v => v.value ? v.value.toLocaleLowerCase() : undefined); if (names && names.length > 0) { filteredExtensions = filteredExtensions.filter(e => e.extensionName && e.publisher.publisherName && names.includes(`${e.publisher.publisherName.toLocaleLowerCase()}.${e.extensionName.toLocaleLowerCase()}`)); } - const searchTexts = query.criteria.filter(x => x.filterType === FilterType.SearchText).map(v => v.value.toLocaleLowerCase()); + const searchTexts = query.criteria.filter(x => x.filterType === FilterType.SearchText).map(v => v.value ? v.value.toLocaleLowerCase() : undefined); if (searchTexts && searchTexts.length > 0) { searchTexts.forEach(searchText => { if (searchText !== '@allmarketplace') { @@ -585,13 +585,13 @@ export class ExtensionGalleryService implements IExtensionGalleryService { /* * Checks whether the extension matches the search text */ - public static isMatchingExtension(extension: IRawGalleryExtension, searchText: string): boolean { + public static isMatchingExtension(extension?: IRawGalleryExtension, searchText?: string): boolean { if (!searchText) { return true; } let text = searchText.toLocaleLowerCase(); - return extension - && (extension.extensionName && extension.extensionName.toLocaleLowerCase().includes(text) || + return !!extension + && !!(extension.extensionName && extension.extensionName.toLocaleLowerCase().includes(text) || extension.publisher && extension.publisher.publisherName && extension.publisher.publisherName.toLocaleLowerCase().includes(text) || extension.publisher && extension.publisher.displayName && extension.publisher.displayName.toLocaleLowerCase().includes(text) || extension.displayName && extension.displayName.toLocaleLowerCase().includes(text) || diff --git a/src/vs/platform/extensionManagement/test/node/extensionGalleryService.test.ts b/src/vs/platform/extensionManagement/test/node/extensionGalleryService.test.ts index 7c895546c9..0a69f6a92c 100644 --- a/src/vs/platform/extensionManagement/test/node/extensionGalleryService.test.ts +++ b/src/vs/platform/extensionManagement/test/node/extensionGalleryService.test.ts @@ -47,14 +47,26 @@ suite('Extension Gallery Service', () => { // {{SQL CARBON EDIT}} test('sortByField', () => { - let a = { + let a: { + extensionId: string | undefined; + extensionName: string | undefined; + displayName: string | undefined; + shortDescription: string | undefined; + publisher: { displayName: string | undefined, publisherId: string | undefined, publisherName: string | undefined; } | undefined; + } = { extensionId: undefined, extensionName: undefined, displayName: undefined, shortDescription: undefined, publisher: undefined }; - let b = { + let b: { + extensionId: string | undefined; + extensionName: string | undefined; + displayName: string | undefined; + shortDescription: string | undefined; + publisher: { displayName: string | undefined, publisherId: string | undefined, publisherName: string | undefined; } | undefined; + } = { extensionId: undefined, extensionName: undefined, displayName: undefined, diff --git a/src/vs/platform/extensions/node/extensionValidator.ts b/src/vs/platform/extensions/node/extensionValidator.ts index ecc3a48b5c..3ef3051b79 100644 --- a/src/vs/platform/extensions/node/extensionValidator.ts +++ b/src/vs/platform/extensions/node/extensionValidator.ts @@ -222,7 +222,7 @@ export function isValidExtensionVersion(version: string, extensionDesc: IReduced } // {{SQL CARBON EDIT}} - return (extensionDesc.engines.azdata && extensionDesc.engines.azdata === '*') || isVersionValid(version, extensionDesc.engines.azdata, notices); + return extensionDesc.engines.azdata ? extensionDesc.engines.azdata === '*' || isVersionValid(version, extensionDesc.engines.azdata, notices) : true; } // {{SQL CARBON EDIT}}