mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Change tables to make them work for our scenario (#12193)
* Change tables to make them work for our scenario * Comments & deprecate API * Disable selections by default
This commit is contained in:
@@ -104,6 +104,7 @@ export function createViewContext(): ViewTestContext {
|
|||||||
});
|
});
|
||||||
let declarativeTable: () => azdata.DeclarativeTableComponent = () => Object.assign({}, componentBase, {
|
let declarativeTable: () => azdata.DeclarativeTableComponent = () => Object.assign({}, componentBase, {
|
||||||
onDataChanged: undefined!,
|
onDataChanged: undefined!,
|
||||||
|
onRowSelected: undefined!,
|
||||||
data: [],
|
data: [],
|
||||||
columns: []
|
columns: []
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -346,6 +346,7 @@ class TestDeclarativeTableComponent extends TestComponentBase implements azdata.
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
onDataChanged: vscode.Event<any> = this.onClick.event;
|
onDataChanged: vscode.Event<any> = this.onClick.event;
|
||||||
|
onRowSelected: vscode.Event<any> = this.onClick.event;
|
||||||
data: any[][];
|
data: any[][];
|
||||||
columns: azdata.DeclarativeTableColumn[];
|
columns: azdata.DeclarativeTableColumn[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -180,6 +180,7 @@ describe('Manage Package Dialog', () => {
|
|||||||
});
|
});
|
||||||
let declarativeTable: () => azdata.DeclarativeTableComponent = () => Object.assign({}, componentBase, {
|
let declarativeTable: () => azdata.DeclarativeTableComponent = () => Object.assign({}, componentBase, {
|
||||||
onDataChanged: undefined!,
|
onDataChanged: undefined!,
|
||||||
|
onRowSelected: undefined!,
|
||||||
data: [],
|
data: [],
|
||||||
columns: []
|
columns: []
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -416,7 +416,7 @@ export class PublishDatabaseDialog {
|
|||||||
|
|
||||||
table.onDataChanged(() => {
|
table.onDataChanged(() => {
|
||||||
this.sqlCmdVars = {};
|
this.sqlCmdVars = {};
|
||||||
table.data.forEach((row) => {
|
table.data?.forEach((row) => {
|
||||||
(<Record<string, string>>this.sqlCmdVars)[row[0]] = row[1];
|
(<Record<string, string>>this.sqlCmdVars)[row[0]] = row[1];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -16,32 +16,77 @@ export class SqlDatabaseTree extends AssessmentDialogComponent {
|
|||||||
|
|
||||||
private createTableComponent(view: azdata.ModelView): azdata.DeclarativeTableComponent {
|
private createTableComponent(view: azdata.ModelView): azdata.DeclarativeTableComponent {
|
||||||
|
|
||||||
const table = view.modelBuilder.declarativeTable().withProperties<azdata.DeclarativeTableProperties>(
|
const style: azdata.CssStyles = {
|
||||||
|
'border': 'none',
|
||||||
|
'text-align': 'left'
|
||||||
|
};
|
||||||
|
|
||||||
|
const table = view.modelBuilder.declarativeTable().withProps(
|
||||||
{
|
{
|
||||||
|
selectEffect: true,
|
||||||
columns: [
|
columns: [
|
||||||
|
{
|
||||||
|
displayName: '',
|
||||||
|
valueType: azdata.DeclarativeDataType.boolean,
|
||||||
|
width: 5,
|
||||||
|
isReadOnly: false,
|
||||||
|
showCheckAll: true,
|
||||||
|
headerCssStyles: style,
|
||||||
|
ariaLabel: 'Database Migration Check' // TODO localize
|
||||||
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Database', // TODO localize
|
displayName: 'Database', // TODO localize
|
||||||
valueType: azdata.DeclarativeDataType.string,
|
valueType: azdata.DeclarativeDataType.string,
|
||||||
width: 50,
|
width: 50,
|
||||||
isReadOnly: true,
|
isReadOnly: true,
|
||||||
showCheckAll: true
|
headerCssStyles: style
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: '', // Incidents
|
displayName: '', // Incidents
|
||||||
valueType: azdata.DeclarativeDataType.string,
|
valueType: azdata.DeclarativeDataType.string,
|
||||||
width: 5,
|
width: 5,
|
||||||
isReadOnly: true,
|
isReadOnly: true,
|
||||||
showCheckAll: false
|
headerCssStyles: style,
|
||||||
|
ariaLabel: 'Issue Count' // TODO localize
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
data: [
|
dataValues: [
|
||||||
['DB1', '1'],
|
[
|
||||||
['DB2', '0']
|
{
|
||||||
|
value: false,
|
||||||
|
style
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'DB1',
|
||||||
|
style
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 1,
|
||||||
|
style
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
value: true,
|
||||||
|
style
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'DB2',
|
||||||
|
style
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 2,
|
||||||
|
style
|
||||||
|
}
|
||||||
|
]
|
||||||
],
|
],
|
||||||
width: '200px'
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
table.component().onRowSelected(({ row }) => {
|
||||||
|
console.log(row);
|
||||||
|
});
|
||||||
|
|
||||||
return table.component();
|
return table.component();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
5
src/sql/azdata.d.ts
vendored
5
src/sql/azdata.d.ts
vendored
@@ -3306,7 +3306,10 @@ declare module 'azdata' {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface DeclarativeTableProperties {
|
export interface DeclarativeTableProperties {
|
||||||
data: any[][];
|
/**
|
||||||
|
* @deprecated Use dataValues instead.
|
||||||
|
*/
|
||||||
|
data?: any[][];
|
||||||
columns: DeclarativeTableColumn[];
|
columns: DeclarativeTableColumn[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
28
src/sql/azdata.proposed.d.ts
vendored
28
src/sql/azdata.proposed.d.ts
vendored
@@ -203,17 +203,26 @@ declare module 'azdata' {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface DeclarativeTableColumn {
|
export interface DeclarativeTableColumn {
|
||||||
headerCssStyles?: { [key: string]: string };
|
headerCssStyles?: CssStyles;
|
||||||
rowCssStyles?: { [key: string]: string };
|
rowCssStyles?: CssStyles;
|
||||||
ariaLabel?: string;
|
ariaLabel?: string;
|
||||||
showCheckAll?: boolean;
|
showCheckAll?: boolean;
|
||||||
isChecked?: boolean;
|
isChecked?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export enum DeclarativeDataType {
|
export enum DeclarativeDataType {
|
||||||
component = 'component'
|
component = 'component'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type DeclarativeTableRowSelectedEvent = {
|
||||||
|
row: number
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface DeclarativeTableComponent extends Component, DeclarativeTableProperties {
|
||||||
|
onRowSelected: vscode.Event<DeclarativeTableRowSelectedEvent>;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add optional azureAccount for connectionWidget.
|
* Add optional azureAccount for connectionWidget.
|
||||||
*/
|
*/
|
||||||
@@ -295,6 +304,21 @@ declare module 'azdata' {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface DeclarativeTableProperties extends ComponentProperties {
|
export interface DeclarativeTableProperties extends ComponentProperties {
|
||||||
|
/**
|
||||||
|
* dataValues will only be used if data is an empty array
|
||||||
|
*/
|
||||||
|
dataValues?: DeclarativeTableCellValue[][];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should the table react to user selections
|
||||||
|
*/
|
||||||
|
selectEffect?: boolean; // Defaults to false
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeclarativeTableCellValue {
|
||||||
|
value: string | number | boolean;
|
||||||
|
ariaLabel?: string;
|
||||||
|
style?: CssStyles
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ComponentProperties {
|
export interface ComponentProperties {
|
||||||
|
|||||||
@@ -1462,15 +1462,26 @@ class DeclarativeTableWrapper extends ComponentWrapper implements azdata.Declara
|
|||||||
super(proxy, handle, ModelComponentTypes.DeclarativeTable, id);
|
super(proxy, handle, ModelComponentTypes.DeclarativeTable, id);
|
||||||
this.properties = {};
|
this.properties = {};
|
||||||
this._emitterMap.set(ComponentEventType.onDidChange, new Emitter<any>());
|
this._emitterMap.set(ComponentEventType.onDidChange, new Emitter<any>());
|
||||||
|
this._emitterMap.set(ComponentEventType.onDidClick, new Emitter<any>());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public get data(): any[][] {
|
public get data(): any[][] {
|
||||||
return this.properties['data'];
|
return this.properties['data'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public set data(v: any[][]) {
|
public set data(v: any[][]) {
|
||||||
this.setProperty('data', v);
|
this.setProperty('data', v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get dataValues(): azdata.DeclarativeTableCellValue[][] {
|
||||||
|
return this.properties['dataValues'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public set dataValues(v: azdata.DeclarativeTableCellValue[][]) {
|
||||||
|
this.setProperty('dataValues', v);
|
||||||
|
}
|
||||||
|
|
||||||
public get columns(): azdata.DeclarativeTableColumn[] {
|
public get columns(): azdata.DeclarativeTableColumn[] {
|
||||||
return this.properties['columns'];
|
return this.properties['columns'];
|
||||||
}
|
}
|
||||||
@@ -1484,10 +1495,23 @@ class DeclarativeTableWrapper extends ComponentWrapper implements azdata.Declara
|
|||||||
return emitter && emitter.event;
|
return emitter && emitter.event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get onRowSelected(): vscode.Event<any> {
|
||||||
|
let emitter = this._emitterMap.get(ComponentEventType.onDidClick);
|
||||||
|
return emitter && emitter.event;
|
||||||
|
}
|
||||||
|
|
||||||
protected notifyPropertyChanged(): Thenable<void> {
|
protected notifyPropertyChanged(): Thenable<void> {
|
||||||
return this._proxy.$setProperties(this._handle, this._id, this.getPropertiesForMainThread());
|
return this._proxy.$setProperties(this._handle, this._id, this.getPropertiesForMainThread());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get selectEffect(): boolean | undefined {
|
||||||
|
return this.properties['selectEffect'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public set selectEffect(v: boolean | undefined) {
|
||||||
|
this.setProperty('selectEffect', v);
|
||||||
|
}
|
||||||
|
|
||||||
public toComponentShape(): IComponentShape {
|
public toComponentShape(): IComponentShape {
|
||||||
// Overridden to ensure we send the correct properties mapping.
|
// Overridden to ensure we send the correct properties mapping.
|
||||||
return <IComponentShape>{
|
return <IComponentShape>{
|
||||||
|
|||||||
@@ -372,6 +372,17 @@ export abstract class ContainerBase<T, TPropertyBag extends azdata.ComponentProp
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public mergeCss(...styles: azdata.CssStyles[]): azdata.CssStyles {
|
||||||
|
const x = styles.reduce((previous, current) => {
|
||||||
|
if (current) {
|
||||||
|
return Object.assign(previous, current);
|
||||||
|
}
|
||||||
|
return previous;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
protected onItemsUpdated(): void {
|
protected onItemsUpdated(): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,26 +1,45 @@
|
|||||||
<table role=grid #container *ngIf="columns" class="declarative-table" [style.height]="getHeight()" [style.width]="getWidth()" [attr.aria-label]="ariaLabel">
|
<table role=grid #container *ngIf="columns" class="declarative-table" [style.height]="getHeight()"
|
||||||
|
[style.width]="getWidth()" [attr.aria-label]="ariaLabel">
|
||||||
<thead>
|
<thead>
|
||||||
<ng-container *ngFor="let column of columns; let c = index;">
|
<ng-container *ngFor="let column of columns; let c = index;">
|
||||||
<th class="declarative-table-header" aria-sort="none" [style.width]="getColumnWidth(column)" [attr.aria-label]="column.ariaLabel" [ngStyle]="column.headerCssStyles" role="columnheader">
|
<th class="declarative-table-header" aria-sort="none" [style.width]="getColumnWidth(column)"
|
||||||
{{column.displayName}}
|
[attr.aria-label]="column.ariaLabel" [ngStyle]="column.headerCssStyles" role="columnheader">
|
||||||
<checkbox *ngIf="isCheckBox(c)" [checked]="isHeaderChecked(c)" (onChange)="onHeaderCheckBoxChanged($event,c)" label="" ></checkbox>
|
{{column.displayName}}
|
||||||
</th>
|
<checkbox *ngIf="isCheckBox(c)" [checked]="isHeaderChecked(c)"
|
||||||
|
(onChange)="onHeaderCheckBoxChanged($event,c)" label=""></checkbox>
|
||||||
|
</th>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</thead>
|
</thead>
|
||||||
<ng-container *ngIf="data">
|
<ng-container *ngIf="data.length > 0">
|
||||||
<ng-container *ngFor="let row of data;let r = index;">
|
<ng-container *ngFor="let row of data;let r = index;">
|
||||||
<tr class="declarative-table-row">
|
<tr class="declarative-table-row" [class.selected]="isRowSelected(r)">
|
||||||
<ng-container *ngFor="let cellData of row;let c = index;trackBy:trackByFnCols">
|
<ng-container *ngFor="let cellData of row;let c = index;trackBy:trackByFnCols">
|
||||||
<td class="declarative-table-cell" [style.width]="getColumnWidth(c)" [attr.aria-label]="getAriaLabel(r, c)" [ngStyle]="columns[c].rowCssStyles">
|
<td class="declarative-table-cell" [style.width]="getColumnWidth(c)"
|
||||||
<checkbox *ngIf="isCheckBox(c)" label="" (onChange)="onCheckBoxChanged($event,r,c)" [enabled]="isControlEnabled(c)" [checked]="isChecked(r,c)"></checkbox>
|
[attr.aria-label]="getAriaLabel(r, c)"
|
||||||
<select-box *ngIf="isSelectBox(c)" [options]="getOptions(c)" (onDidSelect)="onSelectBoxChanged($event,r,c)" [selectedOption]="getSelectedOptionDisplayName(r,c)"></select-box>
|
[ngStyle]="mergeCss(columns[c].rowCssStyles, cellData.style)">
|
||||||
<editable-select-box *ngIf="isEditableSelectBox(c)" [options]="getOptions(c)" (onDidSelect)="onSelectBoxChanged($event,r,c)" [selectedOption]="getSelectedOptionDisplayName(r,c)"></editable-select-box>
|
<checkbox *ngIf="isCheckBox(c)" label="" (onChange)="onCheckBoxChanged($event,r,c)"
|
||||||
<input-box *ngIf="isInputBox(c)" [value]="cellData" (onDidChange)="onInputBoxChanged($event,r,c)"></input-box>
|
[enabled]="isControlEnabled(c)" [checked]="isChecked(r,c)"
|
||||||
<ng-container *ngIf="isLabel(c)" >{{cellData}}</ng-container>
|
[ngStyle]="mergeCss(columns[c].rowCssStyles, cellData.style)">
|
||||||
<model-component-wrapper *ngIf="isComponent(c) && getItemDescriptor(cellData)" [descriptor]="getItemDescriptor(cellData)" [modelStore]="modelStore"></model-component-wrapper>
|
</checkbox>
|
||||||
</td>
|
<select-box *ngIf="isSelectBox(c)" [options]="getOptions(c)"
|
||||||
</ng-container>
|
(onDidSelect)="onSelectBoxChanged($event,r,c)"
|
||||||
</tr>
|
[selectedOption]="getSelectedOptionDisplayName(r,c)">
|
||||||
</ng-container>
|
</select-box>
|
||||||
|
<editable-select-box *ngIf="isEditableSelectBox(c)" [options]="getOptions(c)"
|
||||||
|
(onDidSelect)="onSelectBoxChanged($event,r,c)"
|
||||||
|
[selectedOption]="getSelectedOptionDisplayName(r,c)">
|
||||||
|
</editable-select-box>
|
||||||
|
<input-box *ngIf="isInputBox(c)" [value]="cellData.value"
|
||||||
|
(onDidChange)="onInputBoxChanged($event,r,c)"></input-box>
|
||||||
|
<span *ngIf="isLabel(c)" (click)="onCellClick(r)">
|
||||||
|
{{cellData.value}}
|
||||||
|
</span>
|
||||||
|
<model-component-wrapper *ngIf="isComponent(c) && getItemDescriptor(cellData)"
|
||||||
|
[descriptor]="getItemDescriptor(cellData)" [modelStore]="modelStore">
|
||||||
|
</model-component-wrapper>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
</tr>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</table>
|
</ng-container>
|
||||||
|
</table>
|
||||||
|
|||||||
@@ -30,12 +30,13 @@ export enum DeclarativeDataType {
|
|||||||
selector: 'modelview-declarativeTable',
|
selector: 'modelview-declarativeTable',
|
||||||
templateUrl: decodeURI(require.toUrl('./declarativeTable.component.html'))
|
templateUrl: decodeURI(require.toUrl('./declarativeTable.component.html'))
|
||||||
})
|
})
|
||||||
export default class DeclarativeTableComponent extends ContainerBase<any> implements IComponent, OnDestroy, AfterViewInit {
|
export default class DeclarativeTableComponent extends ContainerBase<any, azdata.DeclarativeTableProperties> implements IComponent, OnDestroy, AfterViewInit {
|
||||||
@Input() descriptor: IComponentDescriptor;
|
@Input() descriptor: IComponentDescriptor;
|
||||||
@Input() modelStore: IModelStore;
|
@Input() modelStore: IModelStore;
|
||||||
|
|
||||||
private data: any[][] = [];
|
private _data: azdata.DeclarativeTableCellValue[][] = [];
|
||||||
private columns: azdata.DeclarativeTableColumn[] = [];
|
private columns: azdata.DeclarativeTableColumn[] = [];
|
||||||
|
private _selectedRow: number;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef,
|
@Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef,
|
||||||
@@ -77,7 +78,12 @@ export default class DeclarativeTableComponent extends ContainerBase<any> implem
|
|||||||
|
|
||||||
public isChecked(rowIdx: number, colIdx: number): boolean {
|
public isChecked(rowIdx: number, colIdx: number): boolean {
|
||||||
let cellData = this.data[rowIdx][colIdx];
|
let cellData = this.data[rowIdx][colIdx];
|
||||||
return cellData;
|
if (cellData?.value === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Disabling it to check for null and undefined.
|
||||||
|
// eslint-disable-next-line eqeqeq
|
||||||
|
return cellData != undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
public onInputBoxChanged(e: string, rowIdx: number, colIdx: number): void {
|
public onInputBoxChanged(e: string, rowIdx: number, colIdx: number): void {
|
||||||
@@ -86,10 +92,11 @@ export default class DeclarativeTableComponent extends ContainerBase<any> implem
|
|||||||
|
|
||||||
public onCheckBoxChanged(e: boolean, rowIdx: number, colIdx: number): void {
|
public onCheckBoxChanged(e: boolean, rowIdx: number, colIdx: number): void {
|
||||||
this.onCellDataChanged(e, rowIdx, colIdx);
|
this.onCellDataChanged(e, rowIdx, colIdx);
|
||||||
|
// If all of the rows in that column are now checked, let's update the header.
|
||||||
if (this.columns[colIdx].showCheckAll) {
|
if (this.columns[colIdx].showCheckAll) {
|
||||||
if (e) {
|
if (e) {
|
||||||
for (let rowIdx = 0; rowIdx < this.data.length; rowIdx++) {
|
for (let rowIdx = 0; rowIdx < this.data.length; rowIdx++) {
|
||||||
if (!this.data[rowIdx][colIdx]) {
|
if (this.data[rowIdx][colIdx].value === false) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,20 +109,20 @@ export default class DeclarativeTableComponent extends ContainerBase<any> implem
|
|||||||
public onHeaderCheckBoxChanged(e: boolean, colIdx: number): void {
|
public onHeaderCheckBoxChanged(e: boolean, colIdx: number): void {
|
||||||
this.columns[colIdx].isChecked = e;
|
this.columns[colIdx].isChecked = e;
|
||||||
this.data.forEach((row, rowIdx) => {
|
this.data.forEach((row, rowIdx) => {
|
||||||
if (row[colIdx] !== e) {
|
if (row[colIdx].value !== e) {
|
||||||
this.onCellDataChanged(e, rowIdx, colIdx);
|
this.onCellDataChanged(e, rowIdx, colIdx);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this._changeRef.detectChanges();
|
this._changeRef.detectChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
public trackByFnCols(index: number, item: any): any {
|
public trackByFnCols(index: number, _item: any): number {
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
public onSelectBoxChanged(e: ISelectData | string, rowIdx: number, colIdx: number): void {
|
public onSelectBoxChanged(e: ISelectData | string, rowIdx: number, colIdx: number): void {
|
||||||
|
|
||||||
let column: azdata.DeclarativeTableColumn = this.columns[colIdx];
|
let column: azdata.DeclarativeTableColumn = this.columns[colIdx];
|
||||||
|
|
||||||
if (column.categoryValues) {
|
if (column.categoryValues) {
|
||||||
if (typeof e === 'string') {
|
if (typeof e === 'string') {
|
||||||
let category = find(column.categoryValues, c => c.displayName === e);
|
let category = find(column.categoryValues, c => c.displayName === e);
|
||||||
@@ -130,8 +137,8 @@ export default class DeclarativeTableComponent extends ContainerBase<any> implem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private onCellDataChanged(newValue: any, rowIdx: number, colIdx: number): void {
|
private onCellDataChanged(newValue: string | number | boolean | any, rowIdx: number, colIdx: number): void {
|
||||||
this.data[rowIdx][colIdx] = newValue;
|
this.data[rowIdx][colIdx].value = newValue;
|
||||||
this.setPropertyFromUI<any[][]>((props, value) => props.data = value, this.data);
|
this.setPropertyFromUI<any[][]>((props, value) => props.data = value, this.data);
|
||||||
let newCellData: azdata.TableCell = {
|
let newCellData: azdata.TableCell = {
|
||||||
row: rowIdx,
|
row: rowIdx,
|
||||||
@@ -177,11 +184,11 @@ export default class DeclarativeTableComponent extends ContainerBase<any> implem
|
|||||||
let column: azdata.DeclarativeTableColumn = this.columns[colIdx];
|
let column: azdata.DeclarativeTableColumn = this.columns[colIdx];
|
||||||
let cellData = this.data[rowIdx][colIdx];
|
let cellData = this.data[rowIdx][colIdx];
|
||||||
if (cellData && column.categoryValues) {
|
if (cellData && column.categoryValues) {
|
||||||
let category = find(column.categoryValues, v => v.name === cellData);
|
let category = find(column.categoryValues, v => v.name === cellData.value);
|
||||||
if (category) {
|
if (category) {
|
||||||
return category.displayName;
|
return category.displayName;
|
||||||
} else if (this.isEditableSelectBox(colIdx)) {
|
} else if (this.isEditableSelectBox(colIdx)) {
|
||||||
return cellData;
|
return String(cellData.value);
|
||||||
} else {
|
} else {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@@ -192,7 +199,19 @@ export default class DeclarativeTableComponent extends ContainerBase<any> implem
|
|||||||
|
|
||||||
public getAriaLabel(rowIdx: number, colIdx: number): string {
|
public getAriaLabel(rowIdx: number, colIdx: number): string {
|
||||||
const cellData = this.data[rowIdx][colIdx];
|
const cellData = this.data[rowIdx][colIdx];
|
||||||
return this.isLabel(colIdx) ? (cellData && cellData !== '' ? cellData : localize('blankValue', "blank")) : '';
|
if (this.isLabel(colIdx)) {
|
||||||
|
if (cellData) {
|
||||||
|
if (cellData.ariaLabel) {
|
||||||
|
return cellData.ariaLabel;
|
||||||
|
} else if (cellData.value) {
|
||||||
|
return String(cellData.value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return localize('blankValue', "blank");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public getItemDescriptor(componentId: string): IComponentDescriptor {
|
public getItemDescriptor(componentId: string): IComponentDescriptor {
|
||||||
@@ -206,12 +225,34 @@ export default class DeclarativeTableComponent extends ContainerBase<any> implem
|
|||||||
this.layout();
|
this.layout();
|
||||||
}
|
}
|
||||||
|
|
||||||
public setProperties(properties: { [key: string]: any; }): void {
|
private static ACCEPTABLE_VALUES = new Set<string>(['number', 'string', 'boolean']);
|
||||||
const newData = properties.data ?? [];
|
public setProperties(properties: azdata.DeclarativeTableProperties): void {
|
||||||
|
const basicData: any[][] = properties.data ?? [];
|
||||||
|
const complexData: azdata.DeclarativeTableCellValue[][] = properties.dataValues;
|
||||||
|
let finalData: azdata.DeclarativeTableCellValue[][];
|
||||||
|
|
||||||
|
finalData = basicData.map(row => {
|
||||||
|
return row.map((value): azdata.DeclarativeTableCellValue => {
|
||||||
|
if (DeclarativeTableComponent.ACCEPTABLE_VALUES.has(typeof (value))) {
|
||||||
|
return {
|
||||||
|
value: value
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
value: JSON.stringify(value)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (finalData.length <= 0) {
|
||||||
|
finalData = complexData;
|
||||||
|
}
|
||||||
|
|
||||||
this.columns = properties.columns ?? [];
|
this.columns = properties.columns ?? [];
|
||||||
|
|
||||||
// check whether the data property is changed before actually setting the properties.
|
// check whether the data property is changed before actually setting the properties.
|
||||||
const isDataPropertyChanged = !arrayEquals(this.data, newData ?? [], (a, b) => {
|
const isDataPropertyChanged = !arrayEquals(this.data, finalData ?? [], (a, b) => {
|
||||||
return arrayEquals(a, b);
|
return arrayEquals(a, b);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -221,15 +262,45 @@ export default class DeclarativeTableComponent extends ContainerBase<any> implem
|
|||||||
// so that the events can be passed upwards through the control hierarchy.
|
// so that the events can be passed upwards through the control hierarchy.
|
||||||
if (isDataPropertyChanged) {
|
if (isDataPropertyChanged) {
|
||||||
this.clearContainer();
|
this.clearContainer();
|
||||||
this.data = newData;
|
this._data = finalData;
|
||||||
this.data?.forEach(row => {
|
this.data?.forEach(row => {
|
||||||
for (let i = 0; i < row.length; i++) {
|
for (let i = 0; i < row.length; i++) {
|
||||||
if (this.isComponent(i)) {
|
if (this.isComponent(i)) {
|
||||||
this.addToContainer(this.getItemDescriptor(row[i] as string), undefined);
|
this.addToContainer(this.getItemDescriptor(row[i].value as string), undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
super.setProperties(properties);
|
super.setProperties(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get data(): azdata.DeclarativeTableCellValue[][] {
|
||||||
|
return this._data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isRowSelected(row: number): boolean {
|
||||||
|
// Only react when the user wants you to
|
||||||
|
if (this.getProperties().selectEffect !== true) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return this._selectedRow === row;
|
||||||
|
}
|
||||||
|
|
||||||
|
public onCellClick(row: number) {
|
||||||
|
// Only react when the user wants you to
|
||||||
|
if (this.getProperties().selectEffect !== true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this.isRowSelected(row)) {
|
||||||
|
this._selectedRow = row;
|
||||||
|
this._changeRef.detectChanges();
|
||||||
|
|
||||||
|
this.fireEvent({
|
||||||
|
eventType: ComponentEventType.onDidClick,
|
||||||
|
args: {
|
||||||
|
row
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,3 +26,7 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.declarative-table-row.selected {
|
||||||
|
background-color: rgb(0, 120, 215);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user