|
|
|
|
@@ -19,7 +19,7 @@ import { attachTableStyler, attachButtonStyler } from 'sql/platform/theme/common
|
|
|
|
|
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
|
|
|
|
import { getContentHeight, getContentWidth, Dimension, isAncestor } from 'vs/base/browser/dom';
|
|
|
|
|
import { RowSelectionModel } from 'sql/base/browser/ui/table/plugins/rowSelectionModel.plugin';
|
|
|
|
|
import { CheckboxSelectColumn, ICheckboxCellActionEventArgs } from 'sql/base/browser/ui/table/plugins/checkboxSelectColumn.plugin';
|
|
|
|
|
import { ActionOnCheck, CheckboxSelectColumn, ICheckboxCellActionEventArgs } from 'sql/base/browser/ui/table/plugins/checkboxSelectColumn.plugin';
|
|
|
|
|
import { Emitter, Event as vsEvent } from 'vs/base/common/event';
|
|
|
|
|
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
|
|
|
|
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
|
|
|
|
|
@@ -27,11 +27,13 @@ import { slickGridDataItemColumnValueWithNoData, textFormatter, iconCssFormatter
|
|
|
|
|
import { isUndefinedOrNull } from 'vs/base/common/types';
|
|
|
|
|
import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType, ModelViewAction } from 'sql/platform/dashboard/browser/interfaces';
|
|
|
|
|
import { convertSizeToNumber } from 'sql/base/browser/dom';
|
|
|
|
|
import { ButtonColumn, ButtonClickEventArgs } from 'sql/base/browser/ui/table/plugins/buttonColumn.plugin';
|
|
|
|
|
import { ButtonCellValue, ButtonColumn } from 'sql/base/browser/ui/table/plugins/buttonColumn.plugin';
|
|
|
|
|
import { IUserFriendlyIcon, createIconCssClass, getIconKey } from 'sql/workbench/browser/modelComponents/iconUtils';
|
|
|
|
|
import { HeaderFilter } from 'sql/base/browser/ui/table/plugins/headerFilter.plugin';
|
|
|
|
|
import { onUnexpectedError } from 'vs/base/common/errors';
|
|
|
|
|
import { ILogService } from 'vs/platform/log/common/log';
|
|
|
|
|
import { TableCellClickEventArgs } from 'sql/base/browser/ui/table/plugins/tableColumn';
|
|
|
|
|
import { HyperlinkCellValue, HyperlinkColumn } from 'sql/base/browser/ui/table/plugins/hyperlinkColumn.plugin';
|
|
|
|
|
|
|
|
|
|
export enum ColumnSizingMode {
|
|
|
|
|
ForceFit = 0, // all columns will be sized to fit in viewable space, no horiz scroll bar
|
|
|
|
|
@@ -43,9 +45,13 @@ enum ColumnType {
|
|
|
|
|
text = 0,
|
|
|
|
|
checkBox = 1,
|
|
|
|
|
button = 2,
|
|
|
|
|
icon = 3
|
|
|
|
|
icon = 3,
|
|
|
|
|
hyperlink = 4
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type TableCellInputDataType = string | azdata.IconColumnCellValue | azdata.ButtonColumnCellValue | azdata.HyperlinkColumnCellValue | undefined;
|
|
|
|
|
type TableCellDataType = string | CssIconCellValue | ButtonCellValue | HyperlinkCellValue | undefined;
|
|
|
|
|
|
|
|
|
|
@Component({
|
|
|
|
|
selector: 'modelview-table',
|
|
|
|
|
template: `
|
|
|
|
|
@@ -59,13 +65,14 @@ export default class TableComponent extends ComponentBase<azdata.TableComponentP
|
|
|
|
|
private _tableData: TableDataView<Slick.SlickData>;
|
|
|
|
|
private _tableColumns;
|
|
|
|
|
private _checkboxColumns: CheckboxSelectColumn<{}>[] = [];
|
|
|
|
|
private _buttonsColumns: ButtonColumn<{}>[] = [];
|
|
|
|
|
private _buttonColumns: ButtonColumn<{}>[] = [];
|
|
|
|
|
private _hyperlinkColumns: HyperlinkColumn<{}>[] = [];
|
|
|
|
|
private _pluginsRegisterStatus: boolean[] = [];
|
|
|
|
|
private _filterPlugin: HeaderFilter<Slick.SlickData>;
|
|
|
|
|
private _onCheckBoxChanged = new Emitter<ICheckboxCellActionEventArgs>();
|
|
|
|
|
private _onButtonClicked = new Emitter<ButtonClickEventArgs<{}>>();
|
|
|
|
|
private _onButtonClicked = new Emitter<TableCellClickEventArgs<{}>>();
|
|
|
|
|
public readonly onCheckBoxChanged: vsEvent<ICheckboxCellActionEventArgs> = this._onCheckBoxChanged.event;
|
|
|
|
|
public readonly onButtonClicked: vsEvent<ButtonClickEventArgs<{}>> = this._onButtonClicked.event;
|
|
|
|
|
public readonly onButtonClicked: vsEvent<TableCellClickEventArgs<{}>> = this._onButtonClicked.event;
|
|
|
|
|
private _iconCssMap: { [iconKey: string]: string } = {};
|
|
|
|
|
|
|
|
|
|
@ViewChild('table', { read: ElementRef }) private _inputContainer: ElementRef;
|
|
|
|
|
@@ -80,7 +87,7 @@ export default class TableComponent extends ComponentBase<azdata.TableComponentP
|
|
|
|
|
transformColumns(columns: string[] | azdata.TableColumn[]): Slick.Column<any>[] {
|
|
|
|
|
let tableColumns: any[] = <any[]>columns;
|
|
|
|
|
if (tableColumns) {
|
|
|
|
|
let mycolumns: Slick.Column<any>[] = [];
|
|
|
|
|
const mycolumns: Slick.Column<any>[] = [];
|
|
|
|
|
let index: number = 0;
|
|
|
|
|
|
|
|
|
|
(<any[]>columns).map(col => {
|
|
|
|
|
@@ -90,6 +97,8 @@ export default class TableComponent extends ComponentBase<azdata.TableComponentP
|
|
|
|
|
this.createButtonPlugin(col);
|
|
|
|
|
} else if (col.type === ColumnType.icon) {
|
|
|
|
|
mycolumns.push(TableComponent.createIconColumn(col));
|
|
|
|
|
} else if (col.type === ColumnType.hyperlink) {
|
|
|
|
|
this.createHyperlinkPlugin(col);
|
|
|
|
|
}
|
|
|
|
|
else if (col.value) {
|
|
|
|
|
mycolumns.push(TableComponent.createTextColumn(col as azdata.TableColumn));
|
|
|
|
|
@@ -142,28 +151,52 @@ export default class TableComponent extends ComponentBase<azdata.TableComponentP
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public transformData(rows: (string | azdata.IconColumnCellValue)[][], columns: any[]): { [key: string]: string | CssIconCellValue }[] {
|
|
|
|
|
public transformData(rows: (TableCellInputDataType)[][], columns: string[] | azdata.TableColumn[]): { [key: string]: TableCellDataType }[] {
|
|
|
|
|
if (rows && columns) {
|
|
|
|
|
|
|
|
|
|
return rows.map(row => {
|
|
|
|
|
let object: { [key: string]: string | CssIconCellValue } = {};
|
|
|
|
|
const object: { [key: string]: TableCellDataType } = {};
|
|
|
|
|
if (!Array.isArray(row)) {
|
|
|
|
|
return object;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
row.forEach((val, index) => {
|
|
|
|
|
let columnName: string = (columns[index].value) ? columns[index].value : <string>columns[index];
|
|
|
|
|
if (isIconColumnCellValue(val)) {
|
|
|
|
|
const icon: IUserFriendlyIcon = val.icon;
|
|
|
|
|
const iconKey: string = getIconKey(icon);
|
|
|
|
|
const iconCssClass = this._iconCssMap[iconKey] ?? createIconCssClass(icon);
|
|
|
|
|
if (!this._iconCssMap[iconKey]) {
|
|
|
|
|
this._iconCssMap[iconKey] = iconCssClass;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
object[columnName] = { iconCssClass: iconCssClass, ariaLabel: val.ariaLabel };
|
|
|
|
|
const column = columns[index];
|
|
|
|
|
if (typeof column === 'string') {
|
|
|
|
|
object[column] = <string>val;
|
|
|
|
|
} else {
|
|
|
|
|
object[columnName] = <string>val;
|
|
|
|
|
const columnType = <ColumnType>column.type;
|
|
|
|
|
let cellValue = undefined;
|
|
|
|
|
switch (columnType) {
|
|
|
|
|
case ColumnType.icon:
|
|
|
|
|
const iconValue = <azdata.IconColumnCellValue>val;
|
|
|
|
|
cellValue = <CssIconCellValue>{
|
|
|
|
|
iconCssClass: this.createIconCssClassInternal(iconValue.icon),
|
|
|
|
|
title: iconValue.title
|
|
|
|
|
};
|
|
|
|
|
break;
|
|
|
|
|
case ColumnType.button:
|
|
|
|
|
if (val) {
|
|
|
|
|
const buttonValue = <azdata.ButtonColumnCellValue>val;
|
|
|
|
|
cellValue = <ButtonCellValue>{
|
|
|
|
|
iconCssClass: buttonValue.icon ? this.createIconCssClassInternal(buttonValue.icon) : undefined,
|
|
|
|
|
title: buttonValue.title
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case ColumnType.hyperlink:
|
|
|
|
|
if (val) {
|
|
|
|
|
const hyperlinkValue = <azdata.HyperlinkColumnCellValue>val;
|
|
|
|
|
cellValue = <HyperlinkCellValue>{
|
|
|
|
|
iconCssClass: hyperlinkValue.icon ? this.createIconCssClassInternal(hyperlinkValue.icon) : undefined,
|
|
|
|
|
title: hyperlinkValue.title,
|
|
|
|
|
url: hyperlinkValue.url
|
|
|
|
|
};
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
cellValue = val;
|
|
|
|
|
}
|
|
|
|
|
object[column.value] = cellValue;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return object;
|
|
|
|
|
@@ -173,6 +206,15 @@ export default class TableComponent extends ComponentBase<azdata.TableComponentP
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private createIconCssClassInternal(icon: IUserFriendlyIcon): string {
|
|
|
|
|
const iconKey: string = getIconKey(icon);
|
|
|
|
|
const iconCssClass = this._iconCssMap[iconKey] ?? createIconCssClass(icon);
|
|
|
|
|
if (!this._iconCssMap[iconKey]) {
|
|
|
|
|
this._iconCssMap[iconKey] = iconCssClass;
|
|
|
|
|
}
|
|
|
|
|
return iconCssClass;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ngAfterViewInit(): void {
|
|
|
|
|
if (this._inputContainer) {
|
|
|
|
|
this._tableData = new TableDataView<Slick.SlickData>(
|
|
|
|
|
@@ -307,7 +349,8 @@ export default class TableComponent extends ComponentBase<azdata.TableComponentP
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Object.keys(this._checkboxColumns).forEach(col => this.registerPlugins(col, this._checkboxColumns[col]));
|
|
|
|
|
Object.keys(this._buttonsColumns).forEach(col => this.registerPlugins(col, this._buttonsColumns[col]));
|
|
|
|
|
Object.keys(this._buttonColumns).forEach(col => this.registerPlugins(col, this._buttonColumns[col]));
|
|
|
|
|
Object.keys(this._hyperlinkColumns).forEach(col => this.registerPlugins(col, this._hyperlinkColumns[col]));
|
|
|
|
|
|
|
|
|
|
if (this.headerFilter === true) {
|
|
|
|
|
this.registerFilterPlugin();
|
|
|
|
|
@@ -356,16 +399,17 @@ export default class TableComponent extends ComponentBase<azdata.TableComponentP
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private createCheckBoxPlugin(col: any, index: number) {
|
|
|
|
|
private createCheckBoxPlugin(col: azdata.CheckboxColumn, index: number) {
|
|
|
|
|
let name = col.value;
|
|
|
|
|
if (!this._checkboxColumns[col.value]) {
|
|
|
|
|
const checkboxAction = <ActionOnCheck>(col.options ? (<any>col.options).actionOnCheckbox : col.action);
|
|
|
|
|
this._checkboxColumns[col.value] = new CheckboxSelectColumn({
|
|
|
|
|
title: col.value,
|
|
|
|
|
toolTip: col.toolTip,
|
|
|
|
|
width: col.width,
|
|
|
|
|
cssClass: col.cssClass,
|
|
|
|
|
headerCssClass: col.headerCssClass,
|
|
|
|
|
actionOnCheck: col.options ? col.options.actionOnCheckbox : null
|
|
|
|
|
actionOnCheck: checkboxAction,
|
|
|
|
|
}, index);
|
|
|
|
|
|
|
|
|
|
this._register(this._checkboxColumns[col.value].onChange((state) => {
|
|
|
|
|
@@ -382,15 +426,19 @@ export default class TableComponent extends ComponentBase<azdata.TableComponentP
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private createButtonPlugin(col: any) {
|
|
|
|
|
private createButtonPlugin(col: azdata.ButtonColumn) {
|
|
|
|
|
let name = col.value;
|
|
|
|
|
if (!this._buttonsColumns[col.value]) {
|
|
|
|
|
this._buttonsColumns[col.value] = new ButtonColumn({
|
|
|
|
|
title: col.title,
|
|
|
|
|
iconCssClass: 'modelview-table-button-icon ' + (col.options ? createIconCssClass(col.options.icon) : '')
|
|
|
|
|
if (!this._buttonColumns[col.value]) {
|
|
|
|
|
const icon = <IUserFriendlyIcon>(col.options ? (<any>col.options).icon : col.icon);
|
|
|
|
|
this._buttonColumns[col.value] = new ButtonColumn({
|
|
|
|
|
title: col.value,
|
|
|
|
|
iconCssClass: icon ? this.createIconCssClassInternal(icon) : undefined,
|
|
|
|
|
field: col.value,
|
|
|
|
|
showText: col.showText,
|
|
|
|
|
name: col.name
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this._register(this._buttonsColumns[col.value].onClick((state) => {
|
|
|
|
|
this._register(this._buttonColumns[col.value].onClick((state) => {
|
|
|
|
|
this.fireEvent({
|
|
|
|
|
eventType: ComponentEventType.onCellAction,
|
|
|
|
|
args: {
|
|
|
|
|
@@ -403,7 +451,33 @@ export default class TableComponent extends ComponentBase<azdata.TableComponentP
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private registerPlugins(col: string, plugin: CheckboxSelectColumn<{}> | ButtonColumn<{}>): void {
|
|
|
|
|
private createHyperlinkPlugin(col: azdata.HyperlinkColumn) {
|
|
|
|
|
const name = col.value;
|
|
|
|
|
if (!this._hyperlinkColumns[col.value]) {
|
|
|
|
|
const hyperlinkColumn = new HyperlinkColumn({
|
|
|
|
|
title: col.value,
|
|
|
|
|
width: col.width,
|
|
|
|
|
iconCssClass: col.icon ? this.createIconCssClassInternal(col.icon) : undefined,
|
|
|
|
|
field: col.value,
|
|
|
|
|
name: col.name
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this._hyperlinkColumns[col.value] = hyperlinkColumn;
|
|
|
|
|
|
|
|
|
|
this._register(hyperlinkColumn.onClick((state) => {
|
|
|
|
|
this.fireEvent({
|
|
|
|
|
eventType: ComponentEventType.onCellAction,
|
|
|
|
|
args: {
|
|
|
|
|
row: state.row,
|
|
|
|
|
column: state.column,
|
|
|
|
|
name: name
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private registerPlugins(col: string, plugin: CheckboxSelectColumn<{}> | ButtonColumn<{}> | HyperlinkColumn<{}>): void {
|
|
|
|
|
|
|
|
|
|
const index = 'index' in plugin ? plugin.index : this.columns?.findIndex(x => x === col || ('value' in x && x['value'] === col));
|
|
|
|
|
if (index >= 0) {
|
|
|
|
|
@@ -548,7 +622,3 @@ export default class TableComponent extends ComponentBase<azdata.TableComponentP
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isIconColumnCellValue(obj: any | undefined): obj is azdata.IconColumnCellValue {
|
|
|
|
|
return !!(<azdata.IconColumnCellValue>obj)?.icon;
|
|
|
|
|
}
|
|
|
|
|
|