mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[AAE-15815] Create Data Table widget (#8801)
* [AAE-15815] Create Data Table widget * [AAE-15815] Add check for corectness of column schema * fix mock name typo * improve method name * fix testing module config
This commit is contained in:
@@ -46,6 +46,7 @@ export class FormFieldTypes {
|
|||||||
static VIEWER: string = 'base-viewer';
|
static VIEWER: string = 'base-viewer';
|
||||||
static DISPLAY_RICH_TEXT: string = 'display-rich-text';
|
static DISPLAY_RICH_TEXT: string = 'display-rich-text';
|
||||||
static JSON: string = 'json';
|
static JSON: string = 'json';
|
||||||
|
static DATA_TABLE: string = 'data-table';
|
||||||
|
|
||||||
static READONLY_TYPES: string[] = [
|
static READONLY_TYPES: string[] = [
|
||||||
FormFieldTypes.HYPERLINK,
|
FormFieldTypes.HYPERLINK,
|
||||||
|
@@ -28,6 +28,7 @@ import { FormFieldRule } from './form-field-rule';
|
|||||||
import { ProcessFormModel } from './process-form-model.interface';
|
import { ProcessFormModel } from './process-form-model.interface';
|
||||||
import { isNumberValue } from './form-field-utils';
|
import { isNumberValue } from './form-field-utils';
|
||||||
import { VariableConfig } from './form-field-variable-options';
|
import { VariableConfig } from './form-field-variable-options';
|
||||||
|
import { DataColumn } from '../../../../datatable/data/data-column.model';
|
||||||
|
|
||||||
// Maps to FormFieldRepresentation
|
// Maps to FormFieldRepresentation
|
||||||
export class FormFieldModel extends FormWidgetModel {
|
export class FormFieldModel extends FormWidgetModel {
|
||||||
@@ -83,6 +84,7 @@ export class FormFieldModel extends FormWidgetModel {
|
|||||||
groupsRestriction: string[];
|
groupsRestriction: string[];
|
||||||
leftLabels: boolean = false;
|
leftLabels: boolean = false;
|
||||||
variableConfig: VariableConfig;
|
variableConfig: VariableConfig;
|
||||||
|
schemaDefinition: DataColumn[];
|
||||||
|
|
||||||
// container model members
|
// container model members
|
||||||
numberOfColumns: number = 1;
|
numberOfColumns: number = 1;
|
||||||
@@ -197,6 +199,7 @@ export class FormFieldModel extends FormWidgetModel {
|
|||||||
this.selectLoggedUser = json.selectLoggedUser;
|
this.selectLoggedUser = json.selectLoggedUser;
|
||||||
this.groupsRestriction = json.groupsRestriction?.groups;
|
this.groupsRestriction = json.groupsRestriction?.groups;
|
||||||
this.variableConfig = json.variableConfig;
|
this.variableConfig = json.variableConfig;
|
||||||
|
this.schemaDefinition = json.schemaDefinition;
|
||||||
|
|
||||||
if (json.placeholder && json.placeholder !== '' && json.placeholder !== 'null') {
|
if (json.placeholder && json.placeholder !== '' && json.placeholder !== 'null') {
|
||||||
this.placeholder = json.placeholder;
|
this.placeholder = json.placeholder;
|
||||||
|
@@ -47,6 +47,7 @@
|
|||||||
"REQUIRED": "This is a required field",
|
"REQUIRED": "This is a required field",
|
||||||
"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.",
|
||||||
"FILE_NAME": "File Name",
|
"FILE_NAME": "File Name",
|
||||||
"NO_FILE_ATTACHED": "No file attached",
|
"NO_FILE_ATTACHED": "No file attached",
|
||||||
"VALIDATOR": {
|
"VALIDATOR": {
|
||||||
|
@@ -26,6 +26,7 @@ import { PropertiesViewerWidgetComponent } from './widgets/properties-viewer/pro
|
|||||||
import { RadioButtonsCloudWidgetComponent } from './widgets/radio-buttons/radio-buttons-cloud.widget';
|
import { RadioButtonsCloudWidgetComponent } from './widgets/radio-buttons/radio-buttons-cloud.widget';
|
||||||
import { FileViewerWidgetComponent } from './widgets/file-viewer/file-viewer.widget';
|
import { FileViewerWidgetComponent } from './widgets/file-viewer/file-viewer.widget';
|
||||||
import { DisplayRichTextWidgetComponent } from './widgets/display-rich-text/display-rich-text.widget';
|
import { DisplayRichTextWidgetComponent } from './widgets/display-rich-text/display-rich-text.widget';
|
||||||
|
import { DataTableWidgetComponent } from './widgets/data-table/data-table.widget';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@@ -43,7 +44,8 @@ export class CloudFormRenderingService extends FormRenderingService {
|
|||||||
[FormFieldTypes.PROPERTIES_VIEWER]: () => PropertiesViewerWidgetComponent,
|
[FormFieldTypes.PROPERTIES_VIEWER]: () => PropertiesViewerWidgetComponent,
|
||||||
[FormFieldTypes.RADIO_BUTTONS]: () => RadioButtonsCloudWidgetComponent,
|
[FormFieldTypes.RADIO_BUTTONS]: () => RadioButtonsCloudWidgetComponent,
|
||||||
[FormFieldTypes.ALFRESCO_FILE_VIEWER]: () => FileViewerWidgetComponent,
|
[FormFieldTypes.ALFRESCO_FILE_VIEWER]: () => FileViewerWidgetComponent,
|
||||||
[FormFieldTypes.DISPLAY_RICH_TEXT]: () => DisplayRichTextWidgetComponent
|
[FormFieldTypes.DISPLAY_RICH_TEXT]: () => DisplayRichTextWidgetComponent,
|
||||||
|
[FormFieldTypes.DATA_TABLE]: () => DataTableWidgetComponent
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,76 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { WidgetDataTableAdapter } from './data-table-adapter.widget';
|
||||||
|
import {
|
||||||
|
mockCountriesData,
|
||||||
|
mockCountriesIncorrectData,
|
||||||
|
mockInvalidSchemaDefinition,
|
||||||
|
mockSchemaDefinition,
|
||||||
|
mockSchemaDefinitionWithDifferentTypes
|
||||||
|
} from '../../../mocks/data-table-widget.mock';
|
||||||
|
import { ObjectDataRow } from '@alfresco/adf-core';
|
||||||
|
|
||||||
|
describe('WidgetDataTableAdapter', () => {
|
||||||
|
let widgetDataTableAdapter: WidgetDataTableAdapter;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
widgetDataTableAdapter = new WidgetDataTableAdapter(mockCountriesData, mockSchemaDefinition);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set columns type to "text" during initialization', () => {
|
||||||
|
widgetDataTableAdapter = new WidgetDataTableAdapter(mockCountriesData, mockSchemaDefinitionWithDifferentTypes);
|
||||||
|
|
||||||
|
widgetDataTableAdapter.getColumns().forEach(column =>
|
||||||
|
expect(column.type).toBe('text')
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return rows if all columns are linked to data', () => {
|
||||||
|
const rows = widgetDataTableAdapter.getRows();
|
||||||
|
|
||||||
|
expect(rows).toEqual([
|
||||||
|
new ObjectDataRow({ id: 'IT', name: 'Italy' }),
|
||||||
|
new ObjectDataRow({ id: 'PL', name: 'Poland' }),
|
||||||
|
new ObjectDataRow({ id: 'UK', name: 'United Kingdom' })
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an empty array if not all columns are linked to data', () => {
|
||||||
|
widgetDataTableAdapter = new WidgetDataTableAdapter(mockCountriesIncorrectData, mockSchemaDefinition);
|
||||||
|
const rows = widgetDataTableAdapter.getRows();
|
||||||
|
const isDataSourceValid = widgetDataTableAdapter.isDataSourceValid();
|
||||||
|
|
||||||
|
expect(rows).toEqual([]);
|
||||||
|
expect(isDataSourceValid).toBeFalse();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an empty array if columns have invalid structure', () => {
|
||||||
|
widgetDataTableAdapter = new WidgetDataTableAdapter(mockCountriesData, mockInvalidSchemaDefinition);
|
||||||
|
const rows = widgetDataTableAdapter.getRows();
|
||||||
|
const isDataSourceValid = widgetDataTableAdapter.isDataSourceValid();
|
||||||
|
|
||||||
|
expect(rows).toEqual([]);
|
||||||
|
expect(isDataSourceValid).toBeFalse();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true for isDataSourceValid() if rows have data and valid columns schema', () => {
|
||||||
|
const isValid = widgetDataTableAdapter.isDataSourceValid();
|
||||||
|
|
||||||
|
expect(isValid).toBeTrue();
|
||||||
|
});
|
||||||
|
});
|
@@ -0,0 +1,62 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
ObjectDataTableAdapter,
|
||||||
|
DataColumn,
|
||||||
|
DataRow
|
||||||
|
} from '@alfresco/adf-core';
|
||||||
|
|
||||||
|
export class WidgetDataTableAdapter extends ObjectDataTableAdapter {
|
||||||
|
|
||||||
|
private rows: DataRow[];
|
||||||
|
private columns: DataColumn[];
|
||||||
|
|
||||||
|
constructor(data?: any[], schema?: DataColumn[]) {
|
||||||
|
super(data, schema);
|
||||||
|
this.rows = super.getRows();
|
||||||
|
this.columns = super.getColumns();
|
||||||
|
|
||||||
|
this.setColumnsTypeToText();
|
||||||
|
}
|
||||||
|
|
||||||
|
getRows(): DataRow[] {
|
||||||
|
if (this.isDataSourceValid()) {
|
||||||
|
return this.rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
isDataSourceValid(): boolean {
|
||||||
|
return this.hasAllColumnsLinkedToData() && this.hasAllMandatoryColumnPropertiesHaveValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
private hasAllMandatoryColumnPropertiesHaveValues(): boolean {
|
||||||
|
return this.columns.every(column => !!column.key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private hasAllColumnsLinkedToData(): boolean {
|
||||||
|
const availableColumnKeys: string[] = this.columns.map(column => column.key);
|
||||||
|
|
||||||
|
return availableColumnKeys.every(columnKey => this.rows.some(row => Object.keys(row.obj).includes(columnKey)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private setColumnsTypeToText(): void {
|
||||||
|
super.setColumns(this.columns.map(column => ({ ...column, type: 'text' })));
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,22 @@
|
|||||||
|
<div class="adf-data-table-widget-container">
|
||||||
|
<div class="adf-data-table-widget-label">
|
||||||
|
<label
|
||||||
|
class="adf-label"
|
||||||
|
[class.adf-left-label]="field.leftLabels"
|
||||||
|
[attr.for]="field.id">
|
||||||
|
{{field.name | translate }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ng-container *ngIf="!previewState; else previewTemplate">
|
||||||
|
<adf-datatable data-automation-id="adf-data-table-widget" [data]="dataSource"></adf-datatable>
|
||||||
|
|
||||||
|
<error-widget *ngIf="dataTableLoadFailed"
|
||||||
|
class="adf-data-table-widget-failed-message"
|
||||||
|
required="{{ 'FORM.FIELD.DATA_TABLE_LOAD_FAILED' | translate }}"></error-widget>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-template #previewTemplate>
|
||||||
|
<adf-datatable data-automation-id="adf-data-table-widget-preview"></adf-datatable>
|
||||||
|
</ng-template>
|
||||||
|
</div>
|
@@ -0,0 +1,3 @@
|
|||||||
|
.adf-data-table-widget-failed-message {
|
||||||
|
margin: 10px;
|
||||||
|
}
|
@@ -0,0 +1,186 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { DataColumn, FormFieldModel, FormFieldTypes, FormModel, LogService } from '@alfresco/adf-core';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
import { DataTableWidgetComponent } from './data-table.widget';
|
||||||
|
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
|
||||||
|
import { TaskVariableCloud } from '../../../models/task-variable-cloud.model';
|
||||||
|
import { FormCloudService } from '../../../services/form-cloud.service';
|
||||||
|
import { WidgetDataTableAdapter } from './data-table-adapter.widget';
|
||||||
|
import {
|
||||||
|
mockCountriesData,
|
||||||
|
mockInvalidSchemaDefinition,
|
||||||
|
mockJsonFormVariable,
|
||||||
|
mockJsonFormVariableWithIncorrectData,
|
||||||
|
mockJsonProcessVariables,
|
||||||
|
mockSchemaDefinition
|
||||||
|
} from '../../../mocks/data-table-widget.mock';
|
||||||
|
|
||||||
|
describe('DataTableWidgetComponent', () => {
|
||||||
|
let widget: DataTableWidgetComponent;
|
||||||
|
let fixture: ComponentFixture<DataTableWidgetComponent>;
|
||||||
|
let formCloudService: FormCloudService;
|
||||||
|
let logService: LogService;
|
||||||
|
let logServiceSpy: jasmine.Spy;
|
||||||
|
|
||||||
|
const errorIcon: string = 'error_outline';
|
||||||
|
|
||||||
|
const getDataVariable = (
|
||||||
|
variableName: string,
|
||||||
|
schemaDefinition: DataColumn[],
|
||||||
|
processVariables?: TaskVariableCloud[],
|
||||||
|
variables?: TaskVariableCloud[]
|
||||||
|
) => new FormFieldModel(
|
||||||
|
new FormModel({ taskId: 'fake-task-id', processVariables, variables }), {
|
||||||
|
id: 'fake-datatable-id',
|
||||||
|
name: 'Data Table',
|
||||||
|
type: FormFieldTypes.DATA_TABLE,
|
||||||
|
optionType: 'variable',
|
||||||
|
schemaDefinition,
|
||||||
|
variableConfig: {
|
||||||
|
variableName
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [
|
||||||
|
ProcessServiceCloudTestingModule
|
||||||
|
]
|
||||||
|
});
|
||||||
|
fixture = TestBed.createComponent(DataTableWidgetComponent);
|
||||||
|
widget = fixture.componentInstance;
|
||||||
|
|
||||||
|
formCloudService = TestBed.inject(FormCloudService);
|
||||||
|
logService = TestBed.inject(LogService);
|
||||||
|
|
||||||
|
widget.field = new FormFieldModel( new FormModel({ taskId: 'fake-task-id' }), {
|
||||||
|
type: FormFieldTypes.DATA_TABLE,
|
||||||
|
name: 'Data Table'
|
||||||
|
});
|
||||||
|
|
||||||
|
logServiceSpy = spyOn(logService, 'error');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display label', () => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const widgetLabel: HTMLElement = fixture.nativeElement.querySelector('.adf-label');
|
||||||
|
|
||||||
|
expect(widgetLabel).toBeTruthy();
|
||||||
|
expect(widgetLabel.textContent.trim()).toBe('Data Table');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display only data table with data source in NOT preview mode', () => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const dataTable = fixture.nativeElement.querySelector('[data-automation-id="adf-data-table-widget"]');
|
||||||
|
const dataTablePreview = fixture.nativeElement.querySelector('[data-automation-id="adf-data-table-widget-preview"]');
|
||||||
|
|
||||||
|
expect(dataTable).toBeTruthy();
|
||||||
|
expect(dataTablePreview).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should properly initialize column schema', () => {
|
||||||
|
widget.field = getDataVariable('json-form-variable', mockSchemaDefinition, [], mockJsonFormVariable);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
widget.dataSource.getColumns().forEach((column, index) =>
|
||||||
|
expect(column.key).toEqual(mockSchemaDefinition[index].key
|
||||||
|
));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should properly initialize data source based on form variable', () => {
|
||||||
|
widget.field = getDataVariable('json-form-variable', mockSchemaDefinition, [], mockJsonFormVariable);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const expectedData = new WidgetDataTableAdapter(mockCountriesData, mockSchemaDefinition);
|
||||||
|
expectedData.getRows().forEach(row => row.cssClass = '');
|
||||||
|
|
||||||
|
expect(widget.dataSource.getRows()).toEqual(expectedData.getRows());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should properly initialize data source based on process variable', () => {
|
||||||
|
widget.field = getDataVariable('json-variable', mockSchemaDefinition, mockJsonProcessVariables);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const expectedData = new WidgetDataTableAdapter(mockCountriesData, mockSchemaDefinition);
|
||||||
|
expectedData.getRows().forEach(row => row.cssClass = '');
|
||||||
|
|
||||||
|
expect(widget.dataSource.getRows()).toEqual(expectedData.getRows());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should NOT display error if form is in preview state', () => {
|
||||||
|
widget.field = getDataVariable('json-form-variable', mockSchemaDefinition, [], mockJsonFormVariableWithIncorrectData);
|
||||||
|
spyOn(formCloudService, 'getPreviewState').and.returnValue(true);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const failedErrorMsgElement = fixture.debugElement.query(By.css('.adf-data-table-widget-failed-message'));
|
||||||
|
const previewDataTable = fixture.nativeElement.querySelector('[data-automation-id="adf-data-table-widget-preview"]');
|
||||||
|
|
||||||
|
expect(failedErrorMsgElement).toBeNull();
|
||||||
|
expect(previewDataTable).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should NOT display data table with data source if form is in preview state', () => {
|
||||||
|
widget.field = getDataVariable('json-form-variable', mockSchemaDefinition, [], mockJsonFormVariable);
|
||||||
|
spyOn(formCloudService, 'getPreviewState').and.returnValue(true);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const previewDataTable = fixture.nativeElement.querySelector('[data-automation-id="adf-data-table-widget-preview"]');
|
||||||
|
const dataTable = fixture.nativeElement.querySelector('[data-automation-id="adf-data-table-widget"]');
|
||||||
|
|
||||||
|
expect(previewDataTable).toBeTruthy();
|
||||||
|
expect(dataTable).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to display and log error if data source is not linked to every column', () => {
|
||||||
|
widget.field = getDataVariable('json-form-variable', mockSchemaDefinition, [], mockJsonFormVariableWithIncorrectData);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const failedErrorMsgElement = fixture.debugElement.query(By.css('.adf-data-table-widget-failed-message'));
|
||||||
|
|
||||||
|
expect(failedErrorMsgElement.nativeElement.textContent.trim()).toBe(errorIcon.concat('FORM.FIELD.DATA_TABLE_LOAD_FAILED'));
|
||||||
|
expect(logServiceSpy).toHaveBeenCalledWith('Data source has corrupted model or structure');
|
||||||
|
expect(widget.dataSource.getRows()).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to display and log error if data source has invalid column structure', () => {
|
||||||
|
widget.field = getDataVariable('json-form-variable', mockInvalidSchemaDefinition, [], mockJsonFormVariableWithIncorrectData);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const failedErrorMsgElement = fixture.debugElement.query(By.css('.adf-data-table-widget-failed-message'));
|
||||||
|
|
||||||
|
expect(failedErrorMsgElement.nativeElement.textContent.trim()).toBe(errorIcon.concat('FORM.FIELD.DATA_TABLE_LOAD_FAILED'));
|
||||||
|
expect(logServiceSpy).toHaveBeenCalledWith('Data source has corrupted model or structure');
|
||||||
|
expect(widget.dataSource.getRows()).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to display and log error if variable is not found', () => {
|
||||||
|
const notFoundVariable = 'not-found-json-variable';
|
||||||
|
widget.field = getDataVariable(notFoundVariable, mockSchemaDefinition, [], mockJsonFormVariableWithIncorrectData);
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const failedErrorMsgElement = fixture.debugElement.query(By.css('.adf-data-table-widget-failed-message'));
|
||||||
|
|
||||||
|
expect(failedErrorMsgElement.nativeElement.textContent.trim()).toBe(errorIcon.concat('FORM.FIELD.DATA_TABLE_LOAD_FAILED'));
|
||||||
|
expect(logServiceSpy).toHaveBeenCalledWith(`${notFoundVariable} not found`);
|
||||||
|
expect(widget.dataSource).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
@@ -0,0 +1,128 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* eslint-disable @angular-eslint/component-selector */
|
||||||
|
|
||||||
|
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
|
||||||
|
import {
|
||||||
|
WidgetComponent,
|
||||||
|
FormService,
|
||||||
|
DataTableModule,
|
||||||
|
LogService,
|
||||||
|
FormBaseModule,
|
||||||
|
DataRow,
|
||||||
|
DataColumn
|
||||||
|
} from '@alfresco/adf-core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { FormCloudService } from '../../../services/form-cloud.service';
|
||||||
|
import { TaskVariableCloud } from '../../../models/task-variable-cloud.model';
|
||||||
|
import { WidgetDataTableAdapter } from './data-table-adapter.widget';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
standalone: true,
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
TranslateModule,
|
||||||
|
DataTableModule,
|
||||||
|
FormBaseModule
|
||||||
|
],
|
||||||
|
selector: 'data-table',
|
||||||
|
templateUrl: './data-table.widget.html',
|
||||||
|
styleUrls: ['./data-table.widget.scss'],
|
||||||
|
host: {
|
||||||
|
'(click)': 'event($event)',
|
||||||
|
'(blur)': 'event($event)',
|
||||||
|
'(change)': 'event($event)',
|
||||||
|
'(focus)': 'event($event)',
|
||||||
|
'(focusin)': 'event($event)',
|
||||||
|
'(focusout)': 'event($event)',
|
||||||
|
'(input)': 'event($event)',
|
||||||
|
'(invalid)': 'event($event)',
|
||||||
|
'(select)': 'event($event)'
|
||||||
|
},
|
||||||
|
encapsulation: ViewEncapsulation.None
|
||||||
|
})
|
||||||
|
export class DataTableWidgetComponent extends WidgetComponent implements OnInit {
|
||||||
|
|
||||||
|
dataSource: WidgetDataTableAdapter;
|
||||||
|
dataTableLoadFailed = false;
|
||||||
|
previewState = false;
|
||||||
|
|
||||||
|
private rowsData: DataRow[];
|
||||||
|
private columnsSchema: DataColumn[];
|
||||||
|
private variableName: string;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public formService: FormService,
|
||||||
|
private formCloudService: FormCloudService,
|
||||||
|
private logService: LogService
|
||||||
|
) {
|
||||||
|
super(formService);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.setPreviewState();
|
||||||
|
this.getTableData();
|
||||||
|
this.initDataTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
private getTableData(): void {
|
||||||
|
const processVariables = this.field?.form?.processVariables;
|
||||||
|
const formVariables = this.field?.form?.variables;
|
||||||
|
|
||||||
|
this.variableName = this.field?.variableConfig?.variableName;
|
||||||
|
this.columnsSchema = this.field?.schemaDefinition;
|
||||||
|
this.rowsData = this.getDataFromVariable(processVariables, formVariables);
|
||||||
|
}
|
||||||
|
|
||||||
|
private initDataTable(): void {
|
||||||
|
if (this.rowsData) {
|
||||||
|
this.dataSource = new WidgetDataTableAdapter(this.rowsData, this.columnsSchema);
|
||||||
|
|
||||||
|
if (this.dataSource.isDataSourceValid()) {
|
||||||
|
this.field.updateForm();
|
||||||
|
} else {
|
||||||
|
this.handleError('Data source has corrupted model or structure');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.handleError(`${this.variableName} not found`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getDataFromVariable(processVariables: TaskVariableCloud[], formVariables: TaskVariableCloud[]): any {
|
||||||
|
const processVariableDropdownOptions = this.getVariableValueByName(processVariables, this.variableName);
|
||||||
|
const formVariableDropdownOptions = this.getVariableValueByName(formVariables, this.variableName);
|
||||||
|
|
||||||
|
return processVariableDropdownOptions ?? formVariableDropdownOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getVariableValueByName(variables: TaskVariableCloud[], variableName: string): any {
|
||||||
|
return variables?.find((variable: TaskVariableCloud) => variable?.name === `variables.${variableName}` || variable?.name === variableName)?.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private setPreviewState(): void {
|
||||||
|
this.previewState = this.formCloudService.getPreviewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleError(error: any) {
|
||||||
|
if (!this.previewState) {
|
||||||
|
this.dataTableLoadFailed = true;
|
||||||
|
this.logService.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,107 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { DataColumn } from '@alfresco/adf-core';
|
||||||
|
import { TaskVariableCloud } from '../models/task-variable-cloud.model';
|
||||||
|
|
||||||
|
export const mockSchemaDefinition: DataColumn[] = [
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
key: 'id',
|
||||||
|
title: 'Country ID',
|
||||||
|
sortable: true,
|
||||||
|
draggable: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
key: 'name',
|
||||||
|
title: 'Country Name',
|
||||||
|
sortable: true,
|
||||||
|
draggable: true
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
export const mockSchemaDefinitionWithDifferentTypes: DataColumn[] = [
|
||||||
|
{
|
||||||
|
type: 'json',
|
||||||
|
key: 'id',
|
||||||
|
title: 'Country ID',
|
||||||
|
sortable: true,
|
||||||
|
draggable: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'date',
|
||||||
|
key: 'name',
|
||||||
|
title: 'Country Name',
|
||||||
|
sortable: true,
|
||||||
|
draggable: true
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
export const mockInvalidSchemaDefinition: DataColumn[] = [
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
key: '',
|
||||||
|
title: 'Country ID',
|
||||||
|
sortable: true,
|
||||||
|
draggable: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
key: undefined,
|
||||||
|
title: 'Country Name',
|
||||||
|
sortable: true,
|
||||||
|
draggable: true
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
export const mockCountriesData = [
|
||||||
|
{
|
||||||
|
id: 'PL',
|
||||||
|
name: 'Poland'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'IT',
|
||||||
|
name: 'Italy'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'UK',
|
||||||
|
name: 'United Kingdom'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
export const mockCountriesIncorrectData = [
|
||||||
|
{
|
||||||
|
id: 'PL'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'IT'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
export const mockJsonFormVariableWithIncorrectData = [
|
||||||
|
new TaskVariableCloud({ name: 'json-form-variable', value: mockCountriesIncorrectData, type: 'json', id: 'fake-id-1' })
|
||||||
|
];
|
||||||
|
|
||||||
|
export const mockJsonFormVariable = [
|
||||||
|
new TaskVariableCloud({ name: 'json-form-variable', value: mockCountriesData, type: 'json', id: 'fake-id-1' })
|
||||||
|
];
|
||||||
|
|
||||||
|
export const mockJsonProcessVariables = [
|
||||||
|
new TaskVariableCloud({ name: 'variables.json-variable', value: mockCountriesData, type: 'json', id: 'fake-id-1' }),
|
||||||
|
new TaskVariableCloud({ name: 'variables.different-variable', value: 'fake-value', type: 'json', id: 'fake-id-2' })
|
||||||
|
];
|
Reference in New Issue
Block a user