mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
table column with iconcss (#13056)
This commit is contained in:
@@ -28,20 +28,47 @@ export class AssessmentResultGrid implements vscode.Disposable {
|
|||||||
private descriptionCaption!: azdata.TextComponent;
|
private descriptionCaption!: azdata.TextComponent;
|
||||||
|
|
||||||
private asmtType!: AssessmentType;
|
private asmtType!: AssessmentType;
|
||||||
|
private targetTypeIcon: { [targetType: number]: azdata.IconColumnCellValue };
|
||||||
|
|
||||||
private readonly checkIdColOrder = 4;
|
|
||||||
private readonly targetColOrder = 0;
|
private readonly checkIdColOrder = 5;
|
||||||
|
private readonly targetColOrder = 1;
|
||||||
|
|
||||||
public get component(): azdata.Component {
|
public get component(): azdata.Component {
|
||||||
return this.rootContainer;
|
return this.rootContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public constructor(view: azdata.ModelView) {
|
public constructor(view: azdata.ModelView, extensionContext: vscode.ExtensionContext) {
|
||||||
const headerCssClass = 'no-borders align-with-header';
|
const headerCssClass = 'no-borders align-with-header';
|
||||||
|
this.targetTypeIcon = {
|
||||||
|
[azdata.sqlAssessment.SqlAssessmentTargetType.Database]: {
|
||||||
|
icon: {
|
||||||
|
dark: extensionContext.asAbsolutePath('resources/dark/database.svg'),
|
||||||
|
light: extensionContext.asAbsolutePath('resources/light/database.svg')
|
||||||
|
},
|
||||||
|
ariaLabel: localize('databaseIconLabel', "Database Icon")
|
||||||
|
},
|
||||||
|
[azdata.sqlAssessment.SqlAssessmentTargetType.Server]: {
|
||||||
|
icon: {
|
||||||
|
dark: extensionContext.asAbsolutePath('resources/dark/server.svg'),
|
||||||
|
light: extensionContext.asAbsolutePath('resources/light/server.svg')
|
||||||
|
},
|
||||||
|
ariaLabel: localize('serverIconLabel', "Server Icon")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
this.table = view.modelBuilder.table()
|
this.table = view.modelBuilder.table()
|
||||||
.withProperties<azdata.TableComponentProperties>({
|
.withProperties<azdata.TableComponentProperties>({
|
||||||
data: [],
|
data: [],
|
||||||
columns: [
|
columns: [
|
||||||
|
{
|
||||||
|
value: 'targetType',
|
||||||
|
name: '',
|
||||||
|
type: azdata.ColumnType.icon,
|
||||||
|
width: 10,
|
||||||
|
headerCssClass: headerCssClass,
|
||||||
|
toolTip: localize('asmt.column.targetType', "Target Type"),
|
||||||
|
},
|
||||||
{ value: LocalizedStrings.TARGET_COLUMN_NAME, headerCssClass: headerCssClass, width: 125 },
|
{ value: LocalizedStrings.TARGET_COLUMN_NAME, headerCssClass: headerCssClass, width: 125 },
|
||||||
{ value: LocalizedStrings.SEVERITY_COLUMN_NAME, headerCssClass: headerCssClass, width: 100 },
|
{ value: LocalizedStrings.SEVERITY_COLUMN_NAME, headerCssClass: headerCssClass, width: 100 },
|
||||||
{ value: LocalizedStrings.MESSAGE_COLUMN_NAME, headerCssClass: headerCssClass, width: 900 },
|
{ value: LocalizedStrings.MESSAGE_COLUMN_NAME, headerCssClass: headerCssClass, width: 900 },
|
||||||
@@ -250,6 +277,7 @@ export class AssessmentResultGrid implements vscode.Disposable {
|
|||||||
|
|
||||||
private convertToDataView(asmtResult: azdata.SqlAssessmentResultItem): any[] {
|
private convertToDataView(asmtResult: azdata.SqlAssessmentResultItem): any[] {
|
||||||
return [
|
return [
|
||||||
|
this.targetTypeIcon[asmtResult.targetType],
|
||||||
asmtResult.targetName,
|
asmtResult.targetName,
|
||||||
asmtResult.level,
|
asmtResult.level,
|
||||||
this.asmtType === AssessmentType.InvokeAssessment ? asmtResult.message : asmtResult.displayName,
|
this.asmtType === AssessmentType.InvokeAssessment ? asmtResult.message : asmtResult.displayName,
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ export class AssessmentEngine {
|
|||||||
let databaseListRequest = azdata.connection.listDatabases(this.connectionProfile.connectionId);
|
let databaseListRequest = azdata.connection.listDatabases(this.connectionProfile.connectionId);
|
||||||
|
|
||||||
let assessmentResult: azdata.SqlAssessmentResult;
|
let assessmentResult: azdata.SqlAssessmentResult;
|
||||||
if (AssessmentType.InvokeAssessment) {
|
if (asmtType === AssessmentType.InvokeAssessment) {
|
||||||
TelemetryReporter.sendActionEvent(SqlAssessmentTelemetryView, SqlTelemetryActions.InvokeServerAssessment);
|
TelemetryReporter.sendActionEvent(SqlAssessmentTelemetryView, SqlTelemetryActions.InvokeServerAssessment);
|
||||||
assessmentResult = await this.sqlAssessment.assessmentInvoke(this.connectionUri, azdata.sqlAssessment.SqlAssessmentTargetType.Server);
|
assessmentResult = await this.sqlAssessment.assessmentInvoke(this.connectionUri, azdata.sqlAssessment.SqlAssessmentTargetType.Server);
|
||||||
|
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ export class SqlAssessmentMainTab extends SqlAssessmentTab {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.resultGrid = new AssessmentResultGrid(view);
|
this.resultGrid = new AssessmentResultGrid(view, this.extensionContext);
|
||||||
rootContainer.addItem(this.resultGrid.component, {
|
rootContainer.addItem(this.resultGrid.component, {
|
||||||
flex: '1 1 auto',
|
flex: '1 1 auto',
|
||||||
CSSStyles: {
|
CSSStyles: {
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ export class SqlAssessmentHistoryTab extends SqlAssessmentTab {
|
|||||||
|
|
||||||
root.clearItems();
|
root.clearItems();
|
||||||
|
|
||||||
this.resultGrid = new AssessmentResultGrid(view);
|
this.resultGrid = new AssessmentResultGrid(view, this.extensionContext);
|
||||||
this.toDispose.push(this.resultGrid);
|
this.toDispose.push(this.resultGrid);
|
||||||
await view.initializeModel(title);
|
await view.initializeModel(title);
|
||||||
|
|
||||||
|
|||||||
17
src/sql/azdata.proposed.d.ts
vendored
17
src/sql/azdata.proposed.d.ts
vendored
@@ -819,10 +819,25 @@ declare module 'azdata' {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface TableComponent {
|
export interface TableComponent {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append data to an exsiting table data.
|
* Append data to an exsiting table data.
|
||||||
*/
|
*/
|
||||||
appendData(data: any[][]);
|
appendData(data: any[][]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IconColumnCellValue {
|
||||||
|
icon: string | vscode.Uri | { light: string | vscode.Uri; dark: string | vscode.Uri };
|
||||||
|
ariaLabel: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ColumnType {
|
||||||
|
icon = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TableColumn {
|
||||||
|
/**
|
||||||
|
* The text to display on the column heading. 'value' property will be used, if not specified
|
||||||
|
**/
|
||||||
|
name?: string;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,12 @@ export interface HyperlinkCellValue {
|
|||||||
linkOrCommand: string | ExecuteCommandInfo;
|
linkOrCommand: string | ExecuteCommandInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface CssIconCellValue {
|
||||||
|
iconCssClass: string,
|
||||||
|
ariaLabel: string
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export namespace DBCellValue {
|
export namespace DBCellValue {
|
||||||
export function isDBCellValue(object: any): boolean {
|
export function isDBCellValue(object: any): boolean {
|
||||||
return (object !== undefined && object.displayValue !== undefined && object.isNull !== undefined);
|
return (object !== undefined && object.displayValue !== undefined && object.isNull !== undefined);
|
||||||
@@ -50,6 +56,10 @@ export function isHyperlinkCellValue(obj: any | undefined): obj is HyperlinkCell
|
|||||||
return !!(<HyperlinkCellValue>obj)?.linkOrCommand;
|
return !!(<HyperlinkCellValue>obj)?.linkOrCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isCssIconCellValue(obj: any | undefined): obj is CssIconCellValue {
|
||||||
|
return !!(<CssIconCellValue>obj)?.iconCssClass;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format xml field into a hyperlink and performs HTML entity encoding
|
* Format xml field into a hyperlink and performs HTML entity encoding
|
||||||
*/
|
*/
|
||||||
@@ -102,6 +112,14 @@ export function textFormatter(row: number | undefined, cell: any | undefined, va
|
|||||||
return `<span title="${titleValue}" class="${cellClasses}">${valueToDisplay}</span>`;
|
return `<span title="${titleValue}" class="${cellClasses}">${valueToDisplay}</span>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function iconCssFormatter(row: number | undefined, cell: any | undefined, value: any, columnDef: any | undefined, dataContext: any | undefined): string {
|
||||||
|
if (isCssIconCellValue(value)) {
|
||||||
|
return `<div role='image' aria-label="${escape(value.ariaLabel)}" class="grid-cell-value-container icon codicon slick-icon-cell-content ${value.iconCssClass}"></div>`;
|
||||||
|
}
|
||||||
|
return textFormatter(row, cell, value, columnDef, dataContext);
|
||||||
|
}
|
||||||
|
|
||||||
export function imageFormatter(row: number | undefined, cell: any | undefined, value: any, columnDef: any | undefined, dataContext: any | undefined): string {
|
export function imageFormatter(row: number | undefined, cell: any | undefined, value: any, columnDef: any | undefined, dataContext: any | undefined): string {
|
||||||
return `<img src="${value.text}" />`;
|
return `<img src="${value.text}" />`;
|
||||||
}
|
}
|
||||||
@@ -129,7 +147,7 @@ export function slickGridDataItemColumnValueExtractor(value: any, columnDef: any
|
|||||||
* In this case, for no display value ariaLabel will be set to specific string "no data available" for accessibily support for screen readers
|
* In this case, for no display value ariaLabel will be set to specific string "no data available" for accessibily support for screen readers
|
||||||
* Set 'no data' label only if cell is present and has no value (so that checkbox and other custom plugins do not get 'no data' label)
|
* Set 'no data' label only if cell is present and has no value (so that checkbox and other custom plugins do not get 'no data' label)
|
||||||
*/
|
*/
|
||||||
export function slickGridDataItemColumnValueWithNoData(value: any, columnDef: any): { text: string; ariaLabel: string; } {
|
export function slickGridDataItemColumnValueWithNoData(value: any, columnDef: any): { text: string; ariaLabel: string; } | CssIconCellValue {
|
||||||
let displayValue = value[columnDef.field];
|
let displayValue = value[columnDef.field];
|
||||||
if (typeof displayValue === 'number') {
|
if (typeof displayValue === 'number') {
|
||||||
displayValue = displayValue.toString();
|
displayValue = displayValue.toString();
|
||||||
@@ -137,6 +155,11 @@ export function slickGridDataItemColumnValueWithNoData(value: any, columnDef: an
|
|||||||
if (displayValue instanceof Array) {
|
if (displayValue instanceof Array) {
|
||||||
displayValue = displayValue.toString();
|
displayValue = displayValue.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isCssIconCellValue(displayValue)) {
|
||||||
|
return displayValue;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
text: displayValue,
|
text: displayValue,
|
||||||
ariaLabel: displayValue ? escape(displayValue) : ((displayValue !== undefined) ? localize("tableCell.NoDataAvailable", "no data available") : displayValue)
|
ariaLabel: displayValue ? escape(displayValue) : ((displayValue !== undefined) ? localize("tableCell.NoDataAvailable", "no data available") : displayValue)
|
||||||
|
|||||||
@@ -12,29 +12,32 @@ export interface TextWithIconColumnDefinition<T extends Slick.SlickData> extends
|
|||||||
iconCssClassField?: string;
|
iconCssClassField?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TextWithIconColumnOptions {
|
export interface TextWithIconColumnOptions<T extends Slick.SlickData> {
|
||||||
iconCssClassField?: string;
|
iconCssClassField?: string;
|
||||||
field?: string;
|
field?: string;
|
||||||
width?: number;
|
width?: number;
|
||||||
id?: string;
|
id?: string;
|
||||||
resizable?: boolean;
|
resizable?: boolean;
|
||||||
name?: string;
|
name?: string;
|
||||||
|
headerCssClass?: string;
|
||||||
|
formatter?: Slick.Formatter<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TextWithIconColumn<T extends Slick.SlickData> {
|
export class TextWithIconColumn<T extends Slick.SlickData> {
|
||||||
|
|
||||||
private _definition: TextWithIconColumnDefinition<T>;
|
private _definition: TextWithIconColumnDefinition<T>;
|
||||||
|
|
||||||
constructor(options: TextWithIconColumnOptions) {
|
constructor(options: TextWithIconColumnOptions<T>) {
|
||||||
this._definition = {
|
this._definition = {
|
||||||
id: options.id,
|
id: options.id,
|
||||||
field: options.field,
|
field: options.field,
|
||||||
resizable: options.resizable,
|
resizable: options.resizable,
|
||||||
formatter: this.formatter,
|
formatter: options.formatter ?? this.formatter,
|
||||||
width: options.width,
|
width: options.width,
|
||||||
name: options.name,
|
name: options.name,
|
||||||
iconCssClassField: options.iconCssClassField,
|
iconCssClassField: options.iconCssClassField,
|
||||||
cssClass: 'slick-icon-cell'
|
cssClass: 'slick-icon-cell',
|
||||||
|
headerCssClass: options.headerCssClass
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
private formatter(row: number, cell: number, value: any, columnDef: Slick.Column<T>, dataContext: T): string {
|
private formatter(row: number, cell: number, value: any, columnDef: Slick.Column<T>, dataContext: T): string {
|
||||||
|
|||||||
@@ -811,7 +811,8 @@ export enum SchemaObjectType {
|
|||||||
export enum ColumnType {
|
export enum ColumnType {
|
||||||
text = 0,
|
text = 0,
|
||||||
checkBox = 1,
|
checkBox = 1,
|
||||||
button = 2
|
button = 2,
|
||||||
|
icon = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ActionOnCellCheckboxCheck {
|
export enum ActionOnCellCheckboxCheck {
|
||||||
|
|||||||
@@ -52,3 +52,7 @@ function getIconUri(iconPath: string | URI): URI {
|
|||||||
return URI.revive(iconPath);
|
return URI.revive(iconPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getIconKey(iconPath: IUserFriendlyIcon): string {
|
||||||
|
return getLightIconUri(iconPath).toString(true) + getDarkIconUri(iconPath)?.toString(true);
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,12 +23,12 @@ import { CheckboxSelectColumn, ICheckboxCellActionEventArgs } from 'sql/base/bro
|
|||||||
import { Emitter, Event as vsEvent } from 'vs/base/common/event';
|
import { Emitter, Event as vsEvent } from 'vs/base/common/event';
|
||||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||||
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
|
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
|
||||||
import { slickGridDataItemColumnValueWithNoData, textFormatter } from 'sql/base/browser/ui/table/formatters';
|
import { slickGridDataItemColumnValueWithNoData, textFormatter, iconCssFormatter, CssIconCellValue } from 'sql/base/browser/ui/table/formatters';
|
||||||
import { isUndefinedOrNull } from 'vs/base/common/types';
|
import { isUndefinedOrNull } from 'vs/base/common/types';
|
||||||
import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType, ModelViewAction } from 'sql/platform/dashboard/browser/interfaces';
|
import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType, ModelViewAction } from 'sql/platform/dashboard/browser/interfaces';
|
||||||
import { convertSizeToNumber } from 'sql/base/browser/dom';
|
import { convertSizeToNumber } from 'sql/base/browser/dom';
|
||||||
import { ButtonColumn, ButtonClickEventArgs } from 'sql/base/browser/ui/table/plugins/buttonColumn.plugin';
|
import { ButtonColumn, ButtonClickEventArgs } from 'sql/base/browser/ui/table/plugins/buttonColumn.plugin';
|
||||||
import { createIconCssClass } from 'sql/workbench/browser/modelComponents/iconUtils';
|
import { IUserFriendlyIcon, createIconCssClass, getIconKey } from 'sql/workbench/browser/modelComponents/iconUtils';
|
||||||
import { HeaderFilter } from 'sql/base/browser/ui/table/plugins/headerFilter.plugin';
|
import { HeaderFilter } from 'sql/base/browser/ui/table/plugins/headerFilter.plugin';
|
||||||
|
|
||||||
export enum ColumnSizingMode {
|
export enum ColumnSizingMode {
|
||||||
@@ -37,6 +37,13 @@ export enum ColumnSizingMode {
|
|||||||
DataFit = 2 // columns use sizing based on cell data, horiz scroll bar present if more cells than visible in view area
|
DataFit = 2 // columns use sizing based on cell data, horiz scroll bar present if more cells than visible in view area
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum ColumnType {
|
||||||
|
text = 0,
|
||||||
|
checkBox = 1,
|
||||||
|
button = 2,
|
||||||
|
icon = 3
|
||||||
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'modelview-table',
|
selector: 'modelview-table',
|
||||||
template: `
|
template: `
|
||||||
@@ -57,6 +64,7 @@ export default class TableComponent extends ComponentBase<azdata.TableComponentP
|
|||||||
private _onButtonClicked = new Emitter<ButtonClickEventArgs<{}>>();
|
private _onButtonClicked = new Emitter<ButtonClickEventArgs<{}>>();
|
||||||
public readonly onCheckBoxChanged: vsEvent<ICheckboxCellActionEventArgs> = this._onCheckBoxChanged.event;
|
public readonly onCheckBoxChanged: vsEvent<ICheckboxCellActionEventArgs> = this._onCheckBoxChanged.event;
|
||||||
public readonly onButtonClicked: vsEvent<ButtonClickEventArgs<{}>> = this._onButtonClicked.event;
|
public readonly onButtonClicked: vsEvent<ButtonClickEventArgs<{}>> = this._onButtonClicked.event;
|
||||||
|
private _iconCssMap: { [iconKey: string]: string } = {};
|
||||||
|
|
||||||
@ViewChild('table', { read: ElementRef }) private _inputContainer: ElementRef;
|
@ViewChild('table', { read: ElementRef }) private _inputContainer: ElementRef;
|
||||||
constructor(
|
constructor(
|
||||||
@@ -76,24 +84,17 @@ export default class TableComponent extends ComponentBase<azdata.TableComponentP
|
|||||||
if (tableColumns) {
|
if (tableColumns) {
|
||||||
let mycolumns: Slick.Column<any>[] = [];
|
let mycolumns: Slick.Column<any>[] = [];
|
||||||
let index: number = 0;
|
let index: number = 0;
|
||||||
|
|
||||||
(<any[]>columns).map(col => {
|
(<any[]>columns).map(col => {
|
||||||
if (col.type && col.type === 1) {
|
if (col.type === ColumnType.checkBox) {
|
||||||
this.createCheckBoxPlugin(col, index);
|
this.createCheckBoxPlugin(col, index);
|
||||||
}
|
} else if (col.type === ColumnType.button) {
|
||||||
else if (col.type && col.type === 2) {
|
|
||||||
this.createButtonPlugin(col);
|
this.createButtonPlugin(col);
|
||||||
|
} else if (col.type === ColumnType.icon) {
|
||||||
|
mycolumns.push(TableComponent.createIconColumn(col));
|
||||||
}
|
}
|
||||||
else if (col.value) {
|
else if (col.value) {
|
||||||
mycolumns.push(<Slick.Column<any>>{
|
mycolumns.push(TableComponent.createTextColumn(col as azdata.TableColumn));
|
||||||
name: col.value,
|
|
||||||
id: col.value,
|
|
||||||
field: col.value,
|
|
||||||
width: col.width,
|
|
||||||
cssClass: col.cssClass,
|
|
||||||
headerCssClass: col.headerCssClass,
|
|
||||||
toolTip: col.toolTip,
|
|
||||||
formatter: textFormatter,
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
mycolumns.push(<Slick.Column<any>>{
|
mycolumns.push(<Slick.Column<any>>{
|
||||||
name: <string>col,
|
name: <string>col,
|
||||||
@@ -116,16 +117,57 @@ export default class TableComponent extends ComponentBase<azdata.TableComponentP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static transformData(rows: string[][], columns: any[]): { [key: string]: string }[] {
|
private static createIconColumn<T extends Slick.SlickData>(col: azdata.TableColumn): Slick.Column<T> {
|
||||||
|
return <Slick.Column<T>>{
|
||||||
|
name: col.name ?? col.value,
|
||||||
|
id: col.value,
|
||||||
|
field: col.value,
|
||||||
|
width: col.width,
|
||||||
|
cssClass: col.cssClass,
|
||||||
|
headerCssClass: col.headerCssClass,
|
||||||
|
toolTip: col.toolTip,
|
||||||
|
formatter: iconCssFormatter,
|
||||||
|
filterable: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static createTextColumn<T extends Slick.SlickData>(col: azdata.TableColumn): Slick.Column<T> {
|
||||||
|
return {
|
||||||
|
name: col.name ?? col.value,
|
||||||
|
id: col.value,
|
||||||
|
field: col.value,
|
||||||
|
width: col.width,
|
||||||
|
cssClass: col.cssClass,
|
||||||
|
headerCssClass: col.headerCssClass,
|
||||||
|
toolTip: col.toolTip,
|
||||||
|
formatter: textFormatter
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public transformData(rows: (string | azdata.IconColumnCellValue)[][], columns: any[]): { [key: string]: string | CssIconCellValue }[] {
|
||||||
if (rows && columns) {
|
if (rows && columns) {
|
||||||
|
|
||||||
return rows.map(row => {
|
return rows.map(row => {
|
||||||
let object: { [key: string]: string } = {};
|
let object: { [key: string]: string | CssIconCellValue } = {};
|
||||||
if (row.forEach) {
|
if (!Array.isArray(row)) {
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
row.forEach((val, index) => {
|
row.forEach((val, index) => {
|
||||||
let columnName: string = (columns[index].value) ? columns[index].value : <string>columns[index];
|
let columnName: string = (columns[index].value) ? columns[index].value : <string>columns[index];
|
||||||
object[columnName] = val;
|
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 };
|
||||||
|
} else {
|
||||||
|
object[columnName] = <string>val;
|
||||||
|
}
|
||||||
|
});
|
||||||
return object;
|
return object;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -263,7 +305,7 @@ export default class TableComponent extends ComponentBase<azdata.TableComponentP
|
|||||||
public setProperties(properties: { [key: string]: any; }): void {
|
public setProperties(properties: { [key: string]: any; }): void {
|
||||||
super.setProperties(properties);
|
super.setProperties(properties);
|
||||||
this._tableData.clear();
|
this._tableData.clear();
|
||||||
this._tableData.push(TableComponent.transformData(this.data, this.columns));
|
this._tableData.push(this.transformData(this.data, this.columns));
|
||||||
this._tableColumns = this.transformColumns(this.columns);
|
this._tableColumns = this.transformColumns(this.columns);
|
||||||
this._table.columns = this._tableColumns;
|
this._table.columns = this._tableColumns;
|
||||||
this._table.setData(this._tableData);
|
this._table.setData(this._tableData);
|
||||||
@@ -497,8 +539,12 @@ export default class TableComponent extends ComponentBase<azdata.TableComponentP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private appendData(data: any[][]) {
|
private appendData(data: any[][]) {
|
||||||
this._tableData.push(TableComponent.transformData(data, this.columns));
|
this._tableData.push(this.transformData(data, this.columns));
|
||||||
this.data = this._tableData.getItems().map(dataObject => Object.values(dataObject));
|
this.data = this._tableData.getItems().map(dataObject => Object.values(dataObject));
|
||||||
this.layoutTable();
|
this.layoutTable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isIconColumnCellValue(obj: any | undefined): obj is azdata.IconColumnCellValue {
|
||||||
|
return !!(<azdata.IconColumnCellValue>obj)?.icon;
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,10 +5,12 @@
|
|||||||
|
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import TableComponent from 'sql/workbench/browser/modelComponents/table.component';
|
import TableComponent from 'sql/workbench/browser/modelComponents/table.component';
|
||||||
|
import { CssIconCellValue } from 'sql/base/browser/ui/table/formatters';
|
||||||
|
|
||||||
suite('TableComponent Tests', () => {
|
suite('TableComponent Tests', () => {
|
||||||
|
|
||||||
setup(() => {
|
setup(() => {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Table transformData should convert data and columns successfully given valid inputs', () => {
|
test('Table transformData should convert data and columns successfully given valid inputs', () => {
|
||||||
@@ -17,7 +19,9 @@ suite('TableComponent Tests', () => {
|
|||||||
['4', '5', '6']
|
['4', '5', '6']
|
||||||
];
|
];
|
||||||
let columns = ['c1', 'c2', 'c3'];
|
let columns = ['c1', 'c2', 'c3'];
|
||||||
let actual: { [key: string]: string }[] = TableComponent.transformData(data, columns);
|
const tableComponent = new TableComponent(undefined, undefined, undefined);
|
||||||
|
|
||||||
|
let actual: { [key: string]: string | CssIconCellValue }[] = tableComponent.transformData(data, columns);
|
||||||
let expected: { [key: string]: string }[] = [
|
let expected: { [key: string]: string }[] = [
|
||||||
{
|
{
|
||||||
'c1': '1',
|
'c1': '1',
|
||||||
@@ -35,8 +39,9 @@ suite('TableComponent Tests', () => {
|
|||||||
|
|
||||||
test('Table transformData should return empty array given undefined rows', () => {
|
test('Table transformData should return empty array given undefined rows', () => {
|
||||||
let data = undefined;
|
let data = undefined;
|
||||||
|
const tableComponent = new TableComponent(undefined, undefined, undefined);
|
||||||
let columns = ['c1', 'c2', 'c3'];
|
let columns = ['c1', 'c2', 'c3'];
|
||||||
let actual: { [key: string]: string }[] = TableComponent.transformData(data, columns);
|
let actual: { [key: string]: string | CssIconCellValue }[] = tableComponent.transformData(data, columns);
|
||||||
let expected: { [key: string]: string }[] = [];
|
let expected: { [key: string]: string }[] = [];
|
||||||
assert.deepEqual(actual, expected);
|
assert.deepEqual(actual, expected);
|
||||||
});
|
});
|
||||||
@@ -47,7 +52,8 @@ suite('TableComponent Tests', () => {
|
|||||||
['4', '5', '6']
|
['4', '5', '6']
|
||||||
];
|
];
|
||||||
let columns;
|
let columns;
|
||||||
let actual: { [key: string]: string }[] = TableComponent.transformData(data, columns);
|
const tableComponent = new TableComponent(undefined, undefined, undefined);
|
||||||
|
let actual: { [key: string]: string | CssIconCellValue }[] = tableComponent.transformData(data, columns);
|
||||||
let expected: { [key: string]: string }[] = [];
|
let expected: { [key: string]: string }[] = [];
|
||||||
assert.deepEqual(actual, expected);
|
assert.deepEqual(actual, expected);
|
||||||
});
|
});
|
||||||
@@ -57,8 +63,9 @@ suite('TableComponent Tests', () => {
|
|||||||
['1', '2'],
|
['1', '2'],
|
||||||
['4', '5']
|
['4', '5']
|
||||||
];
|
];
|
||||||
|
const tableComponent = new TableComponent(undefined, undefined, undefined);
|
||||||
let columns = ['c1', 'c2', 'c3'];
|
let columns = ['c1', 'c2', 'c3'];
|
||||||
let actual: { [key: string]: string }[] = TableComponent.transformData(data, columns);
|
let actual: { [key: string]: string | CssIconCellValue }[] = tableComponent.transformData(data, columns);
|
||||||
let expected: { [key: string]: string }[] = [
|
let expected: { [key: string]: string }[] = [
|
||||||
{
|
{
|
||||||
'c1': '1',
|
'c1': '1',
|
||||||
|
|||||||
Reference in New Issue
Block a user