AAE-48227 adding storybooks for updated components

This commit is contained in:
Isoumyajit
2026-08-25 12:10:44 +05:30
parent 93e818d5ba
commit 77bade2a49
13 changed files with 712 additions and 18 deletions
@@ -0,0 +1,89 @@
/*!
* @license
* Copyright © 2005-2026 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 { applicationConfig, Meta, moduleMetadata, StoryObj } from '@storybook/angular';
import { DateWidgetComponent } from './date.widget';
import { FormFieldModel, FormFieldTypes, FormModel } from '../core';
import { provideStoryCore } from '../../../../stories/core-story.providers';
const meta: Meta<DateWidgetComponent> = {
component: DateWidgetComponent,
title: 'Core/Form/Widgets/Date Widget',
decorators: [
moduleMetadata({
imports: [DateWidgetComponent]
}),
applicationConfig({
providers: [...provideStoryCore()]
})
]
};
export default meta;
type Story = StoryObj<DateWidgetComponent>;
export const Default: Story = {
render: (args) => ({
props: args
}),
args: {
field: new FormFieldModel(new FormModel(), {
id: 'date-field',
name: 'Date field',
type: FormFieldTypes.DATE,
value: null,
required: false,
dateDisplayFormat: 'DD-MM-YYYY'
}),
readOnly: false
}
};
export const Required: Story = {
render: (args) => ({
props: args
}),
args: {
field: new FormFieldModel(new FormModel(), {
id: 'date-field-required',
name: 'Date field',
type: FormFieldTypes.DATE,
value: null,
required: true,
dateDisplayFormat: 'DD-MM-YYYY'
}),
readOnly: false
}
};
export const ReadOnly: Story = {
render: (args) => ({
props: args
}),
args: {
field: new FormFieldModel(new FormModel(), {
id: 'date-field-readonly',
name: 'Date field',
type: FormFieldTypes.DATE,
value: '24-12-1983',
required: false,
readOnly: true,
dateDisplayFormat: 'DD-MM-YYYY'
}),
readOnly: true
}
};
@@ -0,0 +1,86 @@
/*!
* @license
* Copyright © 2005-2026 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 { applicationConfig, Meta, moduleMetadata, StoryObj } from '@storybook/angular';
import { MultilineTextWidgetComponentComponent } from './multiline-text.widget';
import { FormFieldModel, FormFieldTypes, FormModel } from '../core';
import { provideStoryCore } from '../../../../stories/core-story.providers';
const meta: Meta<MultilineTextWidgetComponentComponent> = {
component: MultilineTextWidgetComponentComponent,
title: 'Core/Form/Widgets/Multiline Text Widget',
decorators: [
moduleMetadata({
imports: [MultilineTextWidgetComponentComponent]
}),
applicationConfig({
providers: [...provideStoryCore()]
})
]
};
export default meta;
type Story = StoryObj<MultilineTextWidgetComponentComponent>;
export const Default: Story = {
render: (args) => ({
props: args
}),
args: {
field: new FormFieldModel(new FormModel(), {
id: 'multiline-text-field',
name: 'Multiline text field',
type: FormFieldTypes.MULTILINE_TEXT,
value: '',
required: false
}),
readOnly: false
}
};
export const Required: Story = {
render: (args) => ({
props: args
}),
args: {
field: new FormFieldModel(new FormModel(), {
id: 'multiline-text-field-required',
name: 'Multiline text field',
type: FormFieldTypes.MULTILINE_TEXT,
value: '',
required: true
}),
readOnly: false
}
};
export const ReadOnly: Story = {
render: (args) => ({
props: args
}),
args: {
field: new FormFieldModel(new FormModel(), {
id: 'multiline-text-field-readonly',
name: 'Multiline text field',
type: FormFieldTypes.MULTILINE_TEXT,
value: 'This is a multi-line\ntext value shown in read-only mode.',
required: false,
readOnly: true
}),
readOnly: true
}
};
@@ -159,6 +159,28 @@ const allWidgetTypesForm: FormContent = {
}
]
}
},
{
type: 'container',
id: 'row-multiline-text',
name: 'Label',
tab: '',
numberOfColumns: 1,
fields: {
1: [
{
type: 'multi-line-text',
id: 'multilineTextField',
name: 'Multiline Text Field',
colspan: 1,
placeholder: null,
value: '',
required: false,
visibilityCondition: null,
params: { existingColspan: 1, maxColspan: 1 }
}
]
}
}
],
outcomes: [],
@@ -20,7 +20,7 @@ import { FormSaveRepresentation } from '@alfresco/js-api';
export class FormDefinitionModel extends FormSaveRepresentation {
reusable: boolean = false;
newVersion: boolean = false;
formRepresentation: any;
declare formRepresentation: any;
formImageBase64: string = '';
constructor(id: string, name: any, lastUpdatedByFullName: string, lastUpdated: string, metadata: any) {
@@ -36,19 +36,21 @@ export class FormDefinitionModel extends FormSaveRepresentation {
stencilSetId: 0,
referenceId: null,
formDefinition: {
fields: [{
name: 'Label',
type: 'container',
fieldType: 'ContainerRepresentation',
numberOfColumns: 2,
required: false,
readOnly: false,
sizeX: 2,
sizeY: 1,
row: -1,
col: -1,
fields: {1: this.metadataToFields(metadata)}
}],
fields: [
{
name: 'Label',
type: 'container',
fieldType: 'ContainerRepresentation',
numberOfColumns: 2,
required: false,
readOnly: false,
sizeX: 2,
sizeY: 1,
row: -1,
col: -1,
fields: { 1: this.metadataToFields(metadata) }
}
],
gridsterForm: false,
javascriptEvents: [],
metadata: {},
@@ -0,0 +1,96 @@
/*!
* @license
* Copyright © 2005-2026 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 { applicationConfig, Meta, moduleMetadata, StoryObj } from '@storybook/angular';
import { DropdownWidgetComponent } from './dropdown.widget';
import { FormFieldModel, FormFieldTypes, FormModel } from '@alfresco/adf-core';
import { provideStoryProcessServices } from '../../../stories/process-services-story.providers';
const dropdownOptions = [
{ id: 'opt_1', name: 'Option 1' },
{ id: 'opt_2', name: 'Option 2' },
{ id: 'opt_3', name: 'Option 3' }
];
const meta: Meta<DropdownWidgetComponent> = {
component: DropdownWidgetComponent,
title: 'Process Services/Form/Widgets/Dropdown Widget',
decorators: [
moduleMetadata({
imports: [DropdownWidgetComponent]
}),
applicationConfig({
providers: [...provideStoryProcessServices()]
})
]
};
export default meta;
type Story = StoryObj<DropdownWidgetComponent>;
export const Default: Story = {
render: (args) => ({
props: args
}),
args: {
field: new FormFieldModel(new FormModel(), {
id: 'dropdown-field',
name: 'Dropdown field',
type: FormFieldTypes.DROPDOWN,
required: false,
optionType: 'manual',
options: dropdownOptions
}),
readOnly: false
}
};
export const Required: Story = {
render: (args) => ({
props: args
}),
args: {
field: new FormFieldModel(new FormModel(), {
id: 'dropdown-field-required',
name: 'Dropdown field',
type: FormFieldTypes.DROPDOWN,
required: true,
optionType: 'manual',
options: dropdownOptions
}),
readOnly: false
}
};
export const ReadOnly: Story = {
render: (args) => ({
props: args
}),
args: {
field: new FormFieldModel(new FormModel(), {
id: 'dropdown-field-readonly',
name: 'Dropdown field',
type: FormFieldTypes.DROPDOWN,
value: 'opt_2',
required: false,
readOnly: true,
optionType: 'manual',
options: dropdownOptions
}),
readOnly: true
}
};
@@ -26,7 +26,7 @@ import { NumberCellValidator } from './number-cell-validator.model';
import { RequiredCellValidator } from './required-cell-validator.model';
export class DynamicTableModel extends FormWidgetModel {
field: FormFieldModel;
declare field: FormFieldModel;
columns: DynamicTableColumn[] = [];
visibleColumns: DynamicTableColumn[] = [];
rows: DynamicTableRow[] = [];
@@ -0,0 +1,86 @@
/*!
* @license
* Copyright © 2005-2026 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 { applicationConfig, Meta, moduleMetadata, StoryObj } from '@storybook/angular';
import { FunctionalGroupWidgetComponent } from './functional-group.widget';
import { FormFieldModel, FormFieldTypes, FormModel } from '@alfresco/adf-core';
import { provideStoryProcessServices } from '../../../stories/process-services-story.providers';
import { PeopleProcessService } from '../../../services/people-process.service';
import { mockWorkflowGroups, PeopleProcessServiceMock } from '../../../stories/people-process.service.mock';
const meta: Meta<FunctionalGroupWidgetComponent> = {
component: FunctionalGroupWidgetComponent,
title: 'Process Services/Form/Widgets/Functional Group Widget',
decorators: [
moduleMetadata({
imports: [FunctionalGroupWidgetComponent]
}),
applicationConfig({
providers: [{ provide: PeopleProcessService, useClass: PeopleProcessServiceMock }, ...provideStoryProcessServices()]
})
]
};
export default meta;
type Story = StoryObj<FunctionalGroupWidgetComponent>;
export const Default: Story = {
render: (args) => ({
props: args
}),
args: {
field: new FormFieldModel(new FormModel(), {
id: 'functional-group-field',
name: 'Functional group field',
type: FormFieldTypes.FUNCTIONAL_GROUP,
required: false
}),
readOnly: false
}
};
export const Required: Story = {
render: (args) => ({
props: args
}),
args: {
field: new FormFieldModel(new FormModel(), {
id: 'functional-group-field-required',
name: 'Functional group field',
type: FormFieldTypes.FUNCTIONAL_GROUP,
required: true
}),
readOnly: false
}
};
export const ReadOnly: Story = {
render: (args) => ({
props: args
}),
args: {
field: new FormFieldModel(new FormModel(), {
id: 'functional-group-field-readonly',
name: 'Functional group field',
type: FormFieldTypes.FUNCTIONAL_GROUP,
value: mockWorkflowGroups[0],
required: false,
readOnly: true
}),
readOnly: true
}
};
@@ -0,0 +1,86 @@
/*!
* @license
* Copyright © 2005-2026 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 { applicationConfig, Meta, moduleMetadata, StoryObj } from '@storybook/angular';
import { PeopleWidgetComponent } from './people.widget';
import { FormFieldModel, FormFieldTypes, FormModel } from '@alfresco/adf-core';
import { provideStoryProcessServices } from '../../../stories/process-services-story.providers';
import { PeopleProcessService } from '../../../services/people-process.service';
import { mockWorkflowUsers, PeopleProcessServiceMock } from '../../../stories/people-process.service.mock';
const meta: Meta<PeopleWidgetComponent> = {
component: PeopleWidgetComponent,
title: 'Process Services/Form/Widgets/People Widget',
decorators: [
moduleMetadata({
imports: [PeopleWidgetComponent]
}),
applicationConfig({
providers: [{ provide: PeopleProcessService, useClass: PeopleProcessServiceMock }, ...provideStoryProcessServices()]
})
]
};
export default meta;
type Story = StoryObj<PeopleWidgetComponent>;
export const Default: Story = {
render: (args) => ({
props: args
}),
args: {
field: new FormFieldModel(new FormModel(), {
id: 'people-field',
name: 'People field',
type: FormFieldTypes.PEOPLE,
required: false
}),
readOnly: false
}
};
export const Required: Story = {
render: (args) => ({
props: args
}),
args: {
field: new FormFieldModel(new FormModel(), {
id: 'people-field-required',
name: 'People field',
type: FormFieldTypes.PEOPLE,
required: true
}),
readOnly: false
}
};
export const ReadOnly: Story = {
render: (args) => ({
props: args
}),
args: {
field: new FormFieldModel(new FormModel(), {
id: 'people-field-readonly',
name: 'People field',
type: FormFieldTypes.PEOPLE,
value: mockWorkflowUsers[0],
required: false,
readOnly: true
}),
readOnly: true
}
};
@@ -0,0 +1,98 @@
/*!
* @license
* Copyright © 2005-2026 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 { applicationConfig, Meta, moduleMetadata, StoryObj } from '@storybook/angular';
import { TypeaheadWidgetComponent } from './typeahead.widget';
import { FormFieldModel, FormFieldTypes, FormModel } from '@alfresco/adf-core';
import { provideStoryProcessServices } from '../../../stories/process-services-story.providers';
// No `restUrl` is set on any of the fields below, so `ngOnInit` skips both REST lookups entirely -
// options are supplied manually via `field.options`, matching how the widget filters suggestions locally.
const typeaheadOptions = [
{ id: 'opt_1', name: 'Alpha' },
{ id: 'opt_2', name: 'Bravo' },
{ id: 'opt_3', name: 'Charlie' }
];
const meta: Meta<TypeaheadWidgetComponent> = {
component: TypeaheadWidgetComponent,
title: 'Process Services/Form/Widgets/Typeahead Widget',
decorators: [
moduleMetadata({
imports: [TypeaheadWidgetComponent]
}),
applicationConfig({
providers: [...provideStoryProcessServices()]
})
]
};
export default meta;
type Story = StoryObj<TypeaheadWidgetComponent>;
export const Default: Story = {
render: (args) => ({
props: args
}),
args: {
field: new FormFieldModel(new FormModel(), {
id: 'typeahead-field',
name: 'Typeahead field',
type: FormFieldTypes.TYPEAHEAD,
required: false,
optionType: 'manual',
options: typeaheadOptions
}),
readOnly: false
}
};
export const Required: Story = {
render: (args) => ({
props: args
}),
args: {
field: new FormFieldModel(new FormModel(), {
id: 'typeahead-field-required',
name: 'Typeahead field',
type: FormFieldTypes.TYPEAHEAD,
required: true,
optionType: 'manual',
options: typeaheadOptions
}),
readOnly: false
}
};
export const ReadOnly: Story = {
render: (args) => ({
props: args
}),
args: {
field: new FormFieldModel(new FormModel(), {
id: 'typeahead-field-readonly',
name: 'Typeahead field',
type: FormFieldTypes.TYPEAHEAD,
value: 'opt_2',
required: false,
readOnly: true,
optionType: 'manual',
options: typeaheadOptions
}),
readOnly: true
}
};
@@ -0,0 +1,49 @@
/*!
* @license
* Copyright © 2005-2026 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 { GroupModel } from '@alfresco/adf-core';
import { LightUserRepresentation } from '@alfresco/js-api';
import { Observable, of } from 'rxjs';
export const mockWorkflowGroups: GroupModel[] = [
{ id: 'group-1', name: 'Marketing' },
{ id: 'group-2', name: 'Engineering' },
{ id: 'group-3', name: 'Sales' }
];
export const mockWorkflowUsers: LightUserRepresentation[] = [
{ id: 1, firstName: 'John', lastName: 'Doe', email: 'john.doe@example.com' },
{ id: 2, firstName: 'Jane', lastName: 'Smith', email: 'jane.smith@example.com' }
];
/**
* Lightweight stub used by process-services storybook stories that render widgets depending on
* `PeopleProcessService`. Avoids issuing real REST calls when a story is interacted with.
*/
export class PeopleProcessServiceMock {
getWorkflowGroups(filter: string): Observable<GroupModel[]> {
return of(mockWorkflowGroups.filter((group) => group.name.toLowerCase().includes((filter || '').toLowerCase())));
}
getWorkflowUsers(_taskId?: string, searchWord?: string): Observable<LightUserRepresentation[]> {
return of(mockWorkflowUsers.filter((user) => `${user.firstName} ${user.lastName}`.toLowerCase().includes((searchWord || '').toLowerCase())));
}
getUserImage(_userId: string): string {
return '';
}
}
@@ -0,0 +1,42 @@
/*!
* @license
* Copyright © 2005-2026 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 { Provider, EnvironmentProviders } from '@angular/core';
import { provideCoreAuth, provideAppConfig, provideI18N } from '@alfresco/adf-core';
import { provideAnimations } from '@angular/platform-browser/animations';
import { provideRouter, withHashLocation } from '@angular/router';
/**
* Provides the providers for the process services (non-cloud) storybook stories.
*
* @returns An array of providers for the process services story.
*/
export function provideStoryProcessServices(): (Provider | EnvironmentProviders)[] {
return [
provideI18N({
assets: [
['adf-core', 'assets/adf-core'],
['adf-process-services', 'assets/adf-process-services'],
['adf-process-services-cloud', 'assets/adf-process-services-cloud']
]
}),
provideAppConfig(),
provideCoreAuth(),
provideAnimations(),
provideRouter([], withHashLocation())
];
}
+30 -2
View File
@@ -1,5 +1,22 @@
/*!
* @license
* Copyright © 2005-2026 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 type { StorybookConfig } from '@storybook/angular';
import rootMain from '../../../.storybook/main.ts';
import rootMain from '../../../.storybook/main';
import { dirname } from 'path';
import { fileURLToPath } from 'url';
@@ -9,7 +26,12 @@ const config: StorybookConfig = {
name: getAbsolutePath('@storybook/angular'),
options: {}
},
stories: ['../../core/**/*.stories.ts', '../../content-services/**/*.stories.ts', '../../process-services-cloud/**/*.stories.ts'],
stories: [
'../../core/**/*.stories.ts',
'../../content-services/**/*.stories.ts',
'../../process-services/**/*.stories.ts',
'../../process-services-cloud/**/*.stories.ts'
],
staticDirs: [
{ from: '../../core/src/lib/i18n', to: 'assets/adf-core/i18n' },
{ from: '../../core/src/lib/assets/images', to: 'assets/images' },
@@ -34,6 +56,12 @@ const config: StorybookConfig = {
export default config;
/**
* Resolves the absolute filesystem path to a package's directory.
*
* @param value the package name to resolve
* @returns the absolute path to the directory containing the package's package.json
*/
function getAbsolutePath(value: string): any {
return dirname(fileURLToPath(import.meta.resolve(`${value}/package.json`)));
}
+11 -1
View File
@@ -35,7 +35,17 @@
"../../process-services-cloud/**/mock/**/*",
"../../process-services-cloud/src/lib/testing/**/*",
"../../process-services-cloud/src/test.ts",
"../../process-services/**/*.spec.ts",
"../../process-services/src/lib/testing/**/*",
"../../process-services/src/test.ts",
"../../../.storybook/main.ts"
],
"include": ["../src/**/*", "preview.ts", "../../core/**/*", "../../content-services/**/*", "../../process-services-cloud/**/*"]
"include": [
"../src/**/*",
"*.ts",
"../../core/**/*",
"../../content-services/**/*",
"../../process-services/**/*",
"../../process-services-cloud/**/*"
]
}