diff --git a/lib/core/src/lib/form/components/widgets/core/form-field-types.ts b/lib/core/src/lib/form/components/widgets/core/form-field-types.ts
index 77161c1804..2af8a706c6 100644
--- a/lib/core/src/lib/form/components/widgets/core/form-field-types.ts
+++ b/lib/core/src/lib/form/components/widgets/core/form-field-types.ts
@@ -46,6 +46,7 @@ export class FormFieldTypes {
static VIEWER: string = 'base-viewer';
static DISPLAY_RICH_TEXT: string = 'display-rich-text';
static JSON: string = 'json';
+ static DATA_TABLE: string = 'data-table';
static READONLY_TYPES: string[] = [
FormFieldTypes.HYPERLINK,
diff --git a/lib/core/src/lib/form/components/widgets/core/form-field.model.ts b/lib/core/src/lib/form/components/widgets/core/form-field.model.ts
index 8488bd2757..25c496f1fe 100644
--- a/lib/core/src/lib/form/components/widgets/core/form-field.model.ts
+++ b/lib/core/src/lib/form/components/widgets/core/form-field.model.ts
@@ -28,6 +28,7 @@ import { FormFieldRule } from './form-field-rule';
import { ProcessFormModel } from './process-form-model.interface';
import { isNumberValue } from './form-field-utils';
import { VariableConfig } from './form-field-variable-options';
+import { DataColumn } from '../../../../datatable/data/data-column.model';
// Maps to FormFieldRepresentation
export class FormFieldModel extends FormWidgetModel {
@@ -83,6 +84,7 @@ export class FormFieldModel extends FormWidgetModel {
groupsRestriction: string[];
leftLabels: boolean = false;
variableConfig: VariableConfig;
+ schemaDefinition: DataColumn[];
// container model members
numberOfColumns: number = 1;
@@ -197,6 +199,7 @@ export class FormFieldModel extends FormWidgetModel {
this.selectLoggedUser = json.selectLoggedUser;
this.groupsRestriction = json.groupsRestriction?.groups;
this.variableConfig = json.variableConfig;
+ this.schemaDefinition = json.schemaDefinition;
if (json.placeholder && json.placeholder !== '' && json.placeholder !== 'null') {
this.placeholder = json.placeholder;
diff --git a/lib/core/src/lib/i18n/en.json b/lib/core/src/lib/i18n/en.json
index dfb040f301..2da9563fd5 100644
--- a/lib/core/src/lib/i18n/en.json
+++ b/lib/core/src/lib/i18n/en.json
@@ -47,6 +47,7 @@
"REQUIRED": "This is a required field",
"REST_API_FAILED": "The server `{{ hostname }}` is not reachable",
"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",
"NO_FILE_ATTACHED": "No file attached",
"VALIDATOR": {
diff --git a/lib/process-services-cloud/src/lib/form/components/cloud-form-rendering.service.ts b/lib/process-services-cloud/src/lib/form/components/cloud-form-rendering.service.ts
index d7f284f4e8..1d6a692953 100644
--- a/lib/process-services-cloud/src/lib/form/components/cloud-form-rendering.service.ts
+++ b/lib/process-services-cloud/src/lib/form/components/cloud-form-rendering.service.ts
@@ -26,6 +26,7 @@ import { PropertiesViewerWidgetComponent } from './widgets/properties-viewer/pro
import { RadioButtonsCloudWidgetComponent } from './widgets/radio-buttons/radio-buttons-cloud.widget';
import { FileViewerWidgetComponent } from './widgets/file-viewer/file-viewer.widget';
import { DisplayRichTextWidgetComponent } from './widgets/display-rich-text/display-rich-text.widget';
+import { DataTableWidgetComponent } from './widgets/data-table/data-table.widget';
@Injectable({
providedIn: 'root'
@@ -43,7 +44,8 @@ export class CloudFormRenderingService extends FormRenderingService {
[FormFieldTypes.PROPERTIES_VIEWER]: () => PropertiesViewerWidgetComponent,
[FormFieldTypes.RADIO_BUTTONS]: () => RadioButtonsCloudWidgetComponent,
[FormFieldTypes.ALFRESCO_FILE_VIEWER]: () => FileViewerWidgetComponent,
- [FormFieldTypes.DISPLAY_RICH_TEXT]: () => DisplayRichTextWidgetComponent
+ [FormFieldTypes.DISPLAY_RICH_TEXT]: () => DisplayRichTextWidgetComponent,
+ [FormFieldTypes.DATA_TABLE]: () => DataTableWidgetComponent
}, true);
}
}
diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/data-table/data-table-adapter.widget.spec.ts b/lib/process-services-cloud/src/lib/form/components/widgets/data-table/data-table-adapter.widget.spec.ts
new file mode 100644
index 0000000000..2572961f6a
--- /dev/null
+++ b/lib/process-services-cloud/src/lib/form/components/widgets/data-table/data-table-adapter.widget.spec.ts
@@ -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();
+ });
+});
diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/data-table/data-table-adapter.widget.ts b/lib/process-services-cloud/src/lib/form/components/widgets/data-table/data-table-adapter.widget.ts
new file mode 100644
index 0000000000..f87a5af764
--- /dev/null
+++ b/lib/process-services-cloud/src/lib/form/components/widgets/data-table/data-table-adapter.widget.ts
@@ -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' })));
+ }
+}
diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/data-table/data-table.widget.html b/lib/process-services-cloud/src/lib/form/components/widgets/data-table/data-table.widget.html
new file mode 100644
index 0000000000..5671f24481
--- /dev/null
+++ b/lib/process-services-cloud/src/lib/form/components/widgets/data-table/data-table.widget.html
@@ -0,0 +1,22 @@
+
diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/data-table/data-table.widget.scss b/lib/process-services-cloud/src/lib/form/components/widgets/data-table/data-table.widget.scss
new file mode 100644
index 0000000000..e5f7fbd650
--- /dev/null
+++ b/lib/process-services-cloud/src/lib/form/components/widgets/data-table/data-table.widget.scss
@@ -0,0 +1,3 @@
+.adf-data-table-widget-failed-message {
+ margin: 10px;
+}
diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/data-table/data-table.widget.spec.ts b/lib/process-services-cloud/src/lib/form/components/widgets/data-table/data-table.widget.spec.ts
new file mode 100644
index 0000000000..166c0e24f7
--- /dev/null
+++ b/lib/process-services-cloud/src/lib/form/components/widgets/data-table/data-table.widget.spec.ts
@@ -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;
+ 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();
+ });
+});
diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/data-table/data-table.widget.ts b/lib/process-services-cloud/src/lib/form/components/widgets/data-table/data-table.widget.ts
new file mode 100644
index 0000000000..21dc302b90
--- /dev/null
+++ b/lib/process-services-cloud/src/lib/form/components/widgets/data-table/data-table.widget.ts
@@ -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);
+ }
+ }
+}
diff --git a/lib/process-services-cloud/src/lib/form/mocks/data-table-widget.mock.ts b/lib/process-services-cloud/src/lib/form/mocks/data-table-widget.mock.ts
new file mode 100644
index 0000000000..ea1e099b46
--- /dev/null
+++ b/lib/process-services-cloud/src/lib/form/mocks/data-table-widget.mock.ts
@@ -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' })
+];