mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-12 17:04:57 +00:00
AAE-33007 Display empty data table without error (#10744)
* AAE-33007 Display empty data table without error * update translation key
This commit is contained in:
parent
9bbbc8193d
commit
abaf7df9c6
@ -51,6 +51,7 @@
|
|||||||
"REST_API_FAILED": "The server `{{ hostname }}` is not reachable",
|
"REST_API_FAILED": "The server `{{ hostname }}` is not reachable",
|
||||||
"VARIABLE_DROPDOWN_OPTIONS_FAILED": "There was a problem loading dropdown elements. Please contact administrator.",
|
"VARIABLE_DROPDOWN_OPTIONS_FAILED": "There was a problem loading dropdown elements. Please contact administrator.",
|
||||||
"DATA_TABLE_LOAD_FAILED": "There was a problem loading table elements. Please contact administrator.",
|
"DATA_TABLE_LOAD_FAILED": "There was a problem loading table elements. Please contact administrator.",
|
||||||
|
"DATA_TABLE_EMPTY_CONTENT": "No data found",
|
||||||
"EXTERNAL_PROPERTY_LOAD_FAILED": "There was a problem loading external property. Please contact administrator.",
|
"EXTERNAL_PROPERTY_LOAD_FAILED": "There was a problem loading external property. Please contact administrator.",
|
||||||
"FILE_NAME": "File Name",
|
"FILE_NAME": "File Name",
|
||||||
"TITLE": "Title",
|
"TITLE": "Title",
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
import { WidgetDataTableAdapter } from './data-table-adapter.widget';
|
import { WidgetDataTableAdapter } from './data-table-adapter.widget';
|
||||||
import {
|
import {
|
||||||
mockEuropeCountriesData,
|
mockEuropeCountriesData,
|
||||||
mockCountriesIncorrectData,
|
mockIncompleteCountriesData,
|
||||||
mockInvalidSchemaDefinition,
|
mockInvalidSchemaDefinition,
|
||||||
mockSchemaDefinition
|
mockSchemaDefinition
|
||||||
} from './mocks/data-table-widget.mock';
|
} from './mocks/data-table-widget.mock';
|
||||||
@ -42,13 +42,13 @@ describe('WidgetDataTableAdapter', () => {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return an empty array if not all columns are linked to data', () => {
|
it('should return rows if columns are partially linked to data', () => {
|
||||||
widgetDataTableAdapter = new WidgetDataTableAdapter(mockCountriesIncorrectData, mockSchemaDefinition);
|
widgetDataTableAdapter = new WidgetDataTableAdapter(mockIncompleteCountriesData, mockSchemaDefinition);
|
||||||
const rows = widgetDataTableAdapter.getRows();
|
const rows = widgetDataTableAdapter.getRows();
|
||||||
const isDataSourceValid = widgetDataTableAdapter.isDataSourceValid();
|
const isDataSourceValid = widgetDataTableAdapter.isDataSourceValid();
|
||||||
|
|
||||||
expect(rows).toEqual([]);
|
expect(rows).toEqual([new ObjectDataRow({ id: 'IT' }), new ObjectDataRow({ id: 'PL' })]);
|
||||||
expect(isDataSourceValid).toBeFalse();
|
expect(isDataSourceValid).toBeTrue();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return an empty array if columns have invalid structure', () => {
|
it('should return an empty array if columns have invalid structure', () => {
|
||||||
|
@ -128,16 +128,10 @@ export class WidgetDataTableAdapter implements DataTableAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isDataSourceValid(): boolean {
|
isDataSourceValid(): boolean {
|
||||||
return this.hasAllColumnsLinkedToData() && this.allMandatoryColumnPropertiesHaveValues();
|
return this.allColumnsHaveKeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
private allMandatoryColumnPropertiesHaveValues(): boolean {
|
private allColumnsHaveKeys(): boolean {
|
||||||
return this.adapter.getColumns().every((column) => !!column.key);
|
return this.adapter.getColumns().every((column) => !!column.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
private hasAllColumnsLinkedToData(): boolean {
|
|
||||||
const availableColumnKeys: string[] = this.adapter.getColumns().map((column) => column.key);
|
|
||||||
|
|
||||||
return availableColumnKeys.every((columnKey) => this.adapter.getRows().some((row) => Object.keys(row.obj).includes(columnKey)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -9,11 +9,19 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ng-container *ngIf="!previewState; else previewTemplate">
|
<ng-container *ngIf="!previewState; else previewTemplate">
|
||||||
<adf-datatable data-automation-id="adf-data-table-widget" [data]="dataSource" />
|
<adf-datatable data-automation-id="adf-data-table-widget" [data]="dataSource">
|
||||||
|
<adf-no-content-template>
|
||||||
|
<ng-template>
|
||||||
|
<adf-empty-content
|
||||||
|
icon="border_all"
|
||||||
|
[title]="'FORM.FIELD.DATA_TABLE_EMPTY_CONTENT' | translate" />
|
||||||
|
</ng-template>
|
||||||
|
</adf-no-content-template>
|
||||||
|
</adf-datatable>
|
||||||
|
|
||||||
<error-widget *ngIf="dataTableLoadFailed"
|
<error-widget *ngIf="dataTableLoadFailed"
|
||||||
class="adf-data-table-widget-failed-message"
|
class="adf-data-table-widget-failed-message"
|
||||||
required="{{ 'FORM.FIELD.DATA_TABLE_LOAD_FAILED' | translate }}" />
|
[required]="'FORM.FIELD.DATA_TABLE_LOAD_FAILED' | translate" />
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-template #previewTemplate>
|
<ng-template #previewTemplate>
|
||||||
|
@ -26,7 +26,7 @@ import {
|
|||||||
mockAmericaCountriesData,
|
mockAmericaCountriesData,
|
||||||
mockInvalidSchemaDefinition,
|
mockInvalidSchemaDefinition,
|
||||||
mockJsonFormVariable,
|
mockJsonFormVariable,
|
||||||
mockJsonFormVariableWithIncorrectData,
|
mockJsonFormVariableWithIncompleteData,
|
||||||
mockJsonProcessVariables,
|
mockJsonProcessVariables,
|
||||||
mockSchemaDefinition,
|
mockSchemaDefinition,
|
||||||
mockJsonResponseEuropeCountriesData,
|
mockJsonResponseEuropeCountriesData,
|
||||||
@ -39,7 +39,8 @@ import {
|
|||||||
mockEuropeCountriesRows,
|
mockEuropeCountriesRows,
|
||||||
mockAmericaCountriesRows,
|
mockAmericaCountriesRows,
|
||||||
mockNestedCountryColumns,
|
mockNestedCountryColumns,
|
||||||
mockNestedEuropeCountriesRows
|
mockNestedEuropeCountriesRows,
|
||||||
|
mockJsonFormVariableWithEmptyData
|
||||||
} from './mocks/data-table-widget.mock';
|
} from './mocks/data-table-widget.mock';
|
||||||
|
|
||||||
describe('DataTableWidgetComponent', () => {
|
describe('DataTableWidgetComponent', () => {
|
||||||
@ -238,7 +239,7 @@ describe('DataTableWidgetComponent', () => {
|
|||||||
|
|
||||||
describe('should NOT display error message if', () => {
|
describe('should NOT display error message if', () => {
|
||||||
it('form is in preview state', () => {
|
it('form is in preview state', () => {
|
||||||
widget.field = getDataVariable(mockVariableConfig, mockSchemaDefinition, [], mockJsonFormVariableWithIncorrectData);
|
widget.field = getDataVariable(mockVariableConfig, mockSchemaDefinition, [], mockJsonFormVariableWithIncompleteData);
|
||||||
spyOn(formCloudService, 'getPreviewState').and.returnValue(true);
|
spyOn(formCloudService, 'getPreviewState').and.returnValue(true);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
@ -249,6 +250,16 @@ describe('DataTableWidgetComponent', () => {
|
|||||||
expect(previewDataTable).toBeTruthy();
|
expect(previewDataTable).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('there are no rows', () => {
|
||||||
|
widget.field = getDataVariable(mockVariableConfig, mockSchemaDefinition, [], mockJsonFormVariableWithEmptyData);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const failedErrorMsgElement = fixture.debugElement.query(By.css('.adf-data-table-widget-failed-message'));
|
||||||
|
|
||||||
|
assertData(mockCountryColumns, []);
|
||||||
|
expect(failedErrorMsgElement).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
it('path points to single object with appropriate schema definition', () => {
|
it('path points to single object with appropriate schema definition', () => {
|
||||||
widget.field = getDataVariable({ ...mockVariableConfig, optionsPath: 'response.single-object' }, mockSchemaDefinition, [], []);
|
widget.field = getDataVariable({ ...mockVariableConfig, optionsPath: 'response.single-object' }, mockSchemaDefinition, [], []);
|
||||||
widget.field.value = mockJsonNestedResponseEuropeCountriesData;
|
widget.field.value = mockJsonNestedResponseEuropeCountriesData;
|
||||||
@ -262,16 +273,8 @@ describe('DataTableWidgetComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('should display error message if', () => {
|
describe('should display error message if', () => {
|
||||||
it('data source is NOT linked to every column', () => {
|
|
||||||
widget.field = getDataVariable(mockVariableConfig, mockSchemaDefinition, [], mockJsonFormVariableWithIncorrectData);
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
checkDataTableErrorMessage();
|
|
||||||
expect(widget.dataSource.getRows()).toEqual([]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('data source has invalid column structure', () => {
|
it('data source has invalid column structure', () => {
|
||||||
widget.field = getDataVariable(mockVariableConfig, mockInvalidSchemaDefinition, [], mockJsonFormVariableWithIncorrectData);
|
widget.field = getDataVariable(mockVariableConfig, mockInvalidSchemaDefinition, [], mockJsonFormVariableWithIncompleteData);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
checkDataTableErrorMessage();
|
checkDataTableErrorMessage();
|
||||||
@ -283,12 +286,11 @@ describe('DataTableWidgetComponent', () => {
|
|||||||
{ variableName: 'not-found-data-source' },
|
{ variableName: 'not-found-data-source' },
|
||||||
mockSchemaDefinition,
|
mockSchemaDefinition,
|
||||||
[],
|
[],
|
||||||
mockJsonFormVariableWithIncorrectData
|
mockJsonFormVariableWithIncompleteData
|
||||||
);
|
);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
checkDataTableErrorMessage();
|
checkDataTableErrorMessage();
|
||||||
expect(widget.dataSource).toBeUndefined();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('path is incorrect', () => {
|
it('path is incorrect', () => {
|
||||||
@ -301,7 +303,6 @@ describe('DataTableWidgetComponent', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
checkDataTableErrorMessage();
|
checkDataTableErrorMessage();
|
||||||
expect(widget.dataSource).toBeUndefined();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('provided data by path is NOT an array or object', () => {
|
it('provided data by path is NOT an array or object', () => {
|
||||||
@ -314,7 +315,6 @@ describe('DataTableWidgetComponent', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
checkDataTableErrorMessage();
|
checkDataTableErrorMessage();
|
||||||
expect(widget.dataSource).toBeUndefined();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -18,8 +18,17 @@
|
|||||||
/* eslint-disable @angular-eslint/component-selector */
|
/* eslint-disable @angular-eslint/component-selector */
|
||||||
|
|
||||||
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
|
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
|
||||||
import { WidgetComponent, FormService, FormBaseModule, DataRow, DataColumn, DataTableComponent } from '@alfresco/adf-core';
|
import {
|
||||||
import { CommonModule } from '@angular/common';
|
WidgetComponent,
|
||||||
|
FormService,
|
||||||
|
FormBaseModule,
|
||||||
|
DataRow,
|
||||||
|
DataColumn,
|
||||||
|
DataTableComponent,
|
||||||
|
NoContentTemplateDirective,
|
||||||
|
EmptyContentComponent
|
||||||
|
} from '@alfresco/adf-core';
|
||||||
|
import { NgIf } from '@angular/common';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { FormCloudService } from '../../../services/form-cloud.service';
|
import { FormCloudService } from '../../../services/form-cloud.service';
|
||||||
import { TaskVariableCloud } from '../../../models/task-variable-cloud.model';
|
import { TaskVariableCloud } from '../../../models/task-variable-cloud.model';
|
||||||
@ -28,7 +37,7 @@ import { DataTablePathParserHelper } from './helpers/data-table-path-parser.help
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [CommonModule, TranslateModule, FormBaseModule, DataTableComponent],
|
imports: [NgIf, TranslateModule, FormBaseModule, DataTableComponent, NoContentTemplateDirective, EmptyContentComponent],
|
||||||
selector: 'data-table',
|
selector: 'data-table',
|
||||||
templateUrl: './data-table.widget.html',
|
templateUrl: './data-table.widget.html',
|
||||||
styleUrls: ['./data-table.widget.scss'],
|
styleUrls: ['./data-table.widget.scss'],
|
||||||
@ -71,6 +80,8 @@ export class DataTableWidgetComponent extends WidgetComponent implements OnInit
|
|||||||
}
|
}
|
||||||
|
|
||||||
private init(): void {
|
private init(): void {
|
||||||
|
this.dataTableLoadFailed = false;
|
||||||
|
|
||||||
this.setPreviewState();
|
this.setPreviewState();
|
||||||
this.getTableData();
|
this.getTableData();
|
||||||
this.initDataTable();
|
this.initDataTable();
|
||||||
@ -84,40 +95,50 @@ export class DataTableWidgetComponent extends WidgetComponent implements OnInit
|
|||||||
}
|
}
|
||||||
|
|
||||||
private initDataTable(): void {
|
private initDataTable(): void {
|
||||||
this.dataTableLoadFailed = false;
|
this.dataSource = new WidgetDataTableAdapter(this.rowsData, this.columnsSchema);
|
||||||
|
|
||||||
if (this.rowsData?.length) {
|
if (!this.dataSource.isDataSourceValid()) {
|
||||||
this.dataSource = new WidgetDataTableAdapter(this.rowsData, this.columnsSchema);
|
this.handleError();
|
||||||
|
return;
|
||||||
if (this.dataSource.isDataSourceValid()) {
|
|
||||||
this.field.updateForm();
|
|
||||||
} else {
|
|
||||||
this.handleError('Data source has corrupted model or structure');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.handleError('Data source not found or it is not an array/object');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.field.updateForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
private getRowsData(): void {
|
private getRowsData(): void {
|
||||||
const optionsPath = this.field?.variableConfig?.optionsPath ?? this.defaultResponseProperty;
|
const optionsPath = this.field?.variableConfig?.optionsPath ?? this.defaultResponseProperty;
|
||||||
const fieldValue = this.field?.value;
|
const fieldValue = this.field?.value;
|
||||||
|
|
||||||
const rowsData = fieldValue || this.getDataFromVariable();
|
const rowsData = fieldValue || this.getDataFromVariable();
|
||||||
|
|
||||||
if (rowsData) {
|
if (!rowsData) {
|
||||||
const dataFromPath = this.pathParserHelper.retrieveDataFromPath(rowsData, optionsPath);
|
this.handleError();
|
||||||
this.rowsData = (dataFromPath?.length ? dataFromPath : rowsData) as DataRow[];
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.rowsData = this.extractRowsData(rowsData, optionsPath);
|
||||||
|
|
||||||
|
if (!this.rowsData) {
|
||||||
|
this.handleError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extractRowsData(rowsData: any, optionsPath: string): DataRow[] | undefined {
|
||||||
|
if (Array.isArray(rowsData)) {
|
||||||
|
return rowsData;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.pathParserHelper.retrieveDataFromPath(rowsData, optionsPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getDataFromVariable(): any {
|
private getDataFromVariable(): any {
|
||||||
const processVariables = this.field?.form?.processVariables;
|
const processVariables = this.field?.form?.processVariables;
|
||||||
const formVariables = this.field?.form?.variables;
|
const formVariables = this.field?.form?.variables;
|
||||||
|
|
||||||
const processVariableDropdownOptions = this.getVariableValueByName(processVariables, this.variableName);
|
const processVariableData = this.getVariableValueByName(processVariables, this.variableName);
|
||||||
const formVariableDropdownOptions = this.getVariableValueByName(formVariables, this.variableName);
|
const formVariableData = this.getVariableValueByName(formVariables, this.variableName);
|
||||||
|
|
||||||
return processVariableDropdownOptions ?? formVariableDropdownOptions;
|
return processVariableData ?? formVariableData;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getVariableValueByName(variables: TaskVariableCloud[], variableName: string): any {
|
private getVariableValueByName(variables: TaskVariableCloud[], variableName: string): any {
|
||||||
@ -129,10 +150,9 @@ export class DataTableWidgetComponent extends WidgetComponent implements OnInit
|
|||||||
this.previewState = this.formCloudService.getPreviewState();
|
this.previewState = this.formCloudService.getPreviewState();
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleError(error: any) {
|
private handleError(): void {
|
||||||
if (!this.previewState) {
|
if (!this.previewState) {
|
||||||
this.dataTableLoadFailed = true;
|
this.dataTableLoadFailed = true;
|
||||||
this.widgetError.emit(error);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ interface DataTablePathParserTestCase {
|
|||||||
path?: string;
|
path?: string;
|
||||||
data?: any;
|
data?: any;
|
||||||
propertyName?: string;
|
propertyName?: string;
|
||||||
expected?: unknown[];
|
expected: unknown[];
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('DataTablePathParserHelper', () => {
|
describe('DataTablePathParserHelper', () => {
|
||||||
@ -39,18 +39,18 @@ describe('DataTablePathParserHelper', () => {
|
|||||||
description: 'not existent',
|
description: 'not existent',
|
||||||
data: {},
|
data: {},
|
||||||
path: 'nonexistent.path',
|
path: 'nonexistent.path',
|
||||||
expected: []
|
expected: undefined
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: 'not defined',
|
description: 'not defined',
|
||||||
data: {},
|
data: {},
|
||||||
path: undefined,
|
path: undefined,
|
||||||
expected: []
|
expected: undefined
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: 'empty string',
|
description: 'empty string',
|
||||||
path: '',
|
path: '',
|
||||||
expected: []
|
expected: undefined
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: 'nested',
|
description: 'nested',
|
||||||
@ -76,77 +76,89 @@ describe('DataTablePathParserHelper', () => {
|
|||||||
{
|
{
|
||||||
description: 'with nested brackets followed by an additional part of property name',
|
description: 'with nested brackets followed by an additional part of property name',
|
||||||
propertyName: 'file.file[data]file',
|
propertyName: 'file.file[data]file',
|
||||||
path: 'response.[file.file[data]file]'
|
path: 'response.[file.file[data]file]',
|
||||||
|
expected: mockResultData
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: 'with nested brackets',
|
description: 'with nested brackets',
|
||||||
propertyName: 'file.file[data]',
|
propertyName: 'file.file[data]',
|
||||||
path: 'response.[file.file[data]]'
|
path: 'response.[file.file[data]]',
|
||||||
|
expected: mockResultData
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: 'with separator before nested brackets in property name',
|
description: 'with separator before nested brackets in property name',
|
||||||
propertyName: 'file.[data]file',
|
propertyName: 'file.[data]file',
|
||||||
path: 'response.[file.[data]file]'
|
path: 'response.[file.[data]file]',
|
||||||
|
expected: mockResultData
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: 'with separator before and no separator after nested brackets in property name',
|
description: 'with separator before and no separator after nested brackets in property name',
|
||||||
propertyName: 'file.[data]',
|
propertyName: 'file.[data]',
|
||||||
path: 'response.[file.[data]]'
|
path: 'response.[file.[data]]',
|
||||||
|
expected: mockResultData
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: 'with separator after nested brackets',
|
description: 'with separator after nested brackets',
|
||||||
propertyName: 'file[data].file',
|
propertyName: 'file[data].file',
|
||||||
path: 'response.[file[data].file]'
|
path: 'response.[file[data].file]',
|
||||||
|
expected: mockResultData
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: 'with multiple brackets in property name',
|
description: 'with multiple brackets in property name',
|
||||||
propertyName: 'file.file[data]file[data]',
|
propertyName: 'file.file[data]file[data]',
|
||||||
path: 'response.[file.file[data]file[data]]'
|
path: 'response.[file.file[data]file[data]]',
|
||||||
|
expected: mockResultData
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: 'with missing closing bracket in outermost square brackets',
|
description: 'with missing closing bracket in outermost square brackets',
|
||||||
propertyName: 'file.file[data',
|
propertyName: 'file.file[data',
|
||||||
path: 'response.[file.file[data]'
|
path: 'response.[file.file[data]',
|
||||||
|
expected: mockResultData
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: 'with missing openning bracket in outermost square brackets',
|
description: 'with missing openning bracket in outermost square brackets',
|
||||||
propertyName: 'file.filedata]',
|
propertyName: 'file.filedata]',
|
||||||
path: 'response.[file.filedata]]'
|
path: 'response.[file.filedata]]',
|
||||||
|
expected: mockResultData
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: 'with special characters except separator (.) in brackets',
|
description: 'with special characters except separator (.) in brackets',
|
||||||
propertyName: 'xyz:abc,xyz-abc,xyz_abc,abc+xyz',
|
propertyName: 'xyz:abc,xyz-abc,xyz_abc,abc+xyz',
|
||||||
path: 'response.[xyz:abc,xyz-abc,xyz_abc,abc+xyz]'
|
path: 'response.[xyz:abc,xyz-abc,xyz_abc,abc+xyz]',
|
||||||
|
expected: mockResultData
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: 'with special characters except separator (.) without brackets',
|
description: 'with special characters except separator (.) without brackets',
|
||||||
propertyName: 'xyz:abc,xyz-abc,xyz_abc,abc+xyz',
|
propertyName: 'xyz:abc,xyz-abc,xyz_abc,abc+xyz',
|
||||||
path: 'response.xyz:abc,xyz-abc,xyz_abc,abc+xyz'
|
path: 'response.xyz:abc,xyz-abc,xyz_abc,abc+xyz',
|
||||||
|
expected: mockResultData
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: 'without separator in brackets',
|
description: 'without separator in brackets',
|
||||||
propertyName: 'my-data',
|
propertyName: 'my-data',
|
||||||
path: '[response].[my-data]'
|
path: '[response].[my-data]',
|
||||||
|
expected: mockResultData
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: 'with property followed by single index reference',
|
description: 'with property followed by single index reference',
|
||||||
propertyName: 'users',
|
propertyName: 'users',
|
||||||
path: 'response.users[0].data',
|
path: 'response.users[0].data',
|
||||||
data: mockResponseResultDataWithArrayInsideArray('users')
|
data: mockResponseResultDataWithArrayInsideArray('users'),
|
||||||
|
expected: mockResultData
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: 'with property followed by multiple index references',
|
description: 'with property followed by multiple index references',
|
||||||
propertyName: 'users:Array',
|
propertyName: 'users:Array',
|
||||||
path: 'response.[users:Array][0][1][12].data',
|
path: 'response.[users:Array][0][1][12].data',
|
||||||
data: mockResponseResultDataWithArrayInsideArray('users:Array'),
|
data: mockResponseResultDataWithArrayInsideArray('users:Array'),
|
||||||
expected: []
|
expected: undefined
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: 'when path points to array in the middle (incorrect path)',
|
description: 'when path points to array in the middle (incorrect path)',
|
||||||
propertyName: 'users',
|
propertyName: 'users',
|
||||||
path: 'response.users.incorrectPath',
|
path: 'response.users.incorrectPath',
|
||||||
data: mockResponseResultDataWithArrayInsideArray('users'),
|
data: mockResponseResultDataWithArrayInsideArray('users'),
|
||||||
expected: []
|
expected: undefined
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: 'when path points to the particular element of the array',
|
description: 'when path points to the particular element of the array',
|
||||||
@ -158,7 +170,7 @@ describe('DataTablePathParserHelper', () => {
|
|||||||
description: 'when path points to the particular element of the array which does NOT exist',
|
description: 'when path points to the particular element of the array which does NOT exist',
|
||||||
propertyName: 'users',
|
propertyName: 'users',
|
||||||
path: 'response.users[100]',
|
path: 'response.users[100]',
|
||||||
expected: []
|
expected: undefined
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -166,7 +178,7 @@ describe('DataTablePathParserHelper', () => {
|
|||||||
it(testCase.description, () => {
|
it(testCase.description, () => {
|
||||||
const data = testCase.data ?? mockResponseResultData(testCase.propertyName);
|
const data = testCase.data ?? mockResponseResultData(testCase.propertyName);
|
||||||
const result = helper.retrieveDataFromPath(data, testCase.path);
|
const result = helper.retrieveDataFromPath(data, testCase.path);
|
||||||
const expectedResult = testCase.expected ?? mockResultData;
|
const expectedResult = testCase.expected as any;
|
||||||
expect(result).toEqual(expectedResult);
|
expect(result).toEqual(expectedResult);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -15,13 +15,15 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { DataRow } from '@alfresco/adf-core';
|
||||||
|
|
||||||
export class DataTablePathParserHelper {
|
export class DataTablePathParserHelper {
|
||||||
private readonly removeSquareBracketsRegEx = /^\[(.*)\]$/;
|
private readonly removeSquareBracketsRegEx = /^\[(.*)\]$/;
|
||||||
private readonly indexReferencesRegEx = /(\[\d+\])+$/;
|
private readonly indexReferencesRegEx = /(\[\d+\])+$/;
|
||||||
|
|
||||||
retrieveDataFromPath(data: any, path: string): any[] {
|
retrieveDataFromPath(data: any, path: string): DataRow[] | undefined {
|
||||||
if (!path) {
|
if (!path) {
|
||||||
return [];
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const properties = this.splitPathIntoProperties(path);
|
const properties = this.splitPathIntoProperties(path);
|
||||||
@ -31,7 +33,7 @@ export class DataTablePathParserHelper {
|
|||||||
const isPropertyWithMultipleIndexReferences = propertyIndexReferences.length > 1;
|
const isPropertyWithMultipleIndexReferences = propertyIndexReferences.length > 1;
|
||||||
|
|
||||||
if (isPropertyWithMultipleIndexReferences || !this.isPropertyExistsInData(data, purePropertyName)) {
|
if (isPropertyWithMultipleIndexReferences || !this.isPropertyExistsInData(data, purePropertyName)) {
|
||||||
return [];
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isPropertyWithSingleIndexReference = propertyIndexReferences.length === 1;
|
const isPropertyWithSingleIndexReference = propertyIndexReferences.length === 1;
|
||||||
|
@ -173,7 +173,7 @@ export const mockAmericaCountriesRows: DataRow[] = [
|
|||||||
new ObjectDataRow({ id: 'US', name: 'United States' })
|
new ObjectDataRow({ id: 'US', name: 'United States' })
|
||||||
];
|
];
|
||||||
|
|
||||||
export const mockCountriesIncorrectData = [
|
export const mockIncompleteCountriesData = [
|
||||||
{
|
{
|
||||||
id: 'PL'
|
id: 'PL'
|
||||||
},
|
},
|
||||||
@ -182,8 +182,10 @@ export const mockCountriesIncorrectData = [
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
export const mockJsonFormVariableWithIncorrectData = [
|
export const mockJsonFormVariableWithEmptyData = [new TaskVariableCloud({ name: 'json-form-variable', value: [], type: 'json', id: 'fake-id-1' })];
|
||||||
new TaskVariableCloud({ name: 'json-form-variable', value: mockCountriesIncorrectData, type: 'json', id: 'fake-id-1' })
|
|
||||||
|
export const mockJsonFormVariableWithIncompleteData = [
|
||||||
|
new TaskVariableCloud({ name: 'json-form-variable', value: mockIncompleteCountriesData, type: 'json', id: 'fake-id-1' })
|
||||||
];
|
];
|
||||||
|
|
||||||
export const mockJsonFormVariable = [
|
export const mockJsonFormVariable = [
|
||||||
|
Loading…
x
Reference in New Issue
Block a user