Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,14 @@ jobs:
run: npm run build-angular-sdk-components
- name: Public API report is up to date
run: npm run api:check
- name: Component catalogue is up to date
run: npm run docs:components:check
- name: noImplicitAny ratchet
run: npm run check:any
- name: Build overrides package
run: npm run build-overrides
- name: Overrides package type-checks against the built library
run: npm run check:overrides
- name: Verify package tarballs
run: npm run smoke:pack

Expand Down
6 changes: 6 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ angular-sdk-components/
| `npm run fix` | ESLint + Prettier auto-fix |
| `npm run build-overrides` | Generate override templates package |
| `npm run create_and_install_sdk_packages` | Build, pack, and install into angular-sdk repo |
| `npm run test:unit` | Headless Karma/Jasmine unit tests (no Pega server) — see docs/testing.md |
| `npm run new:component -- <kind> <kebab-name> <PegaName>` | Scaffold a component and register it in `public-api.ts` + component map |
| `npm run check:any` / `check:any:update` | `noImplicitAny` per-file ratchet (do not add new implicit-any errors) |
| `npm run api:check` / `api:update` | Public API report guard (`etc/angular-sdk-components.api.md`) |
| `npm run check:overrides` | Type-check the generated overrides package against the built library |
| `npm run docs:components` | Regenerate `docs/components.md` from the component map |

### Prerequisites

Expand Down
4 changes: 3 additions & 1 deletion docs/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ Be sure to reference the original issue in the pull request.

## Run Tests

Since the Angular SDK requires interaction with a running Pega Infinity&trade; server, there is not an automated set of tests provided at this time.
Unit tests (`npm run test:unit`) and static checks run without a Pega server; see [testing.md](testing.md). To add a component use `npm run new:component` (it also registers the component in `public-api.ts` and the component map).

End-to-end verification still requires interaction with a running Pega Infinity&trade; server.

We suggest you begin by using the **MediaCo** application provided in the [Angular SDK download](https://community.pega.com/marketplace/components/angular-sdk). Test your change by using the MediaCo application and completing a complete case flow using the **New Service** casetype provided in that sample application.

Expand Down
26 changes: 26 additions & 0 deletions docs/adr/0002-phase-b-c-outcomes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# ADR 0002: Phase B and C outcomes

Status: Accepted

## Delivered
**Phase B (additive)**
- `noImplicitAny` per-file ratchet (`npm run check:any`); `_bridge` is clean. Strict null checks were already enabled through `strict: true`.
- `FieldBase<TValue = any>` generic (non-breaking default) and a `markForCheck()` hook.
- Bridge characterization tests (`AngularPConnectService`, component map) so the bridge can be refactored safely.
- axe-core accessibility checks for 12 field components.
- `npm run new:component` scaffolds and registers components; `npm run check:overrides` type-checks the generated overrides package. This found and fixed a real defect: `build-overrides` did not rewrite `import type` paths, so the shipped `field.base.ts` in `@pega/angular-sdk-overrides` pointed at a non-existent relative module.
- Generated component catalogue (`docs/components.md`), testing and theming guides.

**Phase C (applied where it is verifiable without a Pega server)**
- `OnPush` for 17 synchronous field components and 6 presentational design-system components. The bridge calls `markForCheck()` after store callbacks so store-driven updates re-render.
- Material 3 token theming is documented (`docs/theming.md`).

## Deferred, with reasons
- **Signal inputs (`input()`/`model()`)**: the `ComponentMapper` already uses `setInput`, so it is compatible, but every `$`-suffixed property is also an override contract (consumers copy and subclass components). Converting ~99 components is a breaking change for them and needs a major release plus a codemod and migration guide.
- **OnPush for the remaining components** (templates, infra, widgets, async fields such as AutoComplete/Dropdown/Location): these mutate state in promise/subscription callbacks and in the containers' rendering pipeline. Zoneless + OnPush there needs each mutation site to call `markForCheck()` or move to signals, and must be validated end-to-end against Infinity (Playwright MediaCo), which was not available here.
- **Secondary entry points** (`/fields`, `/templates`, `/widgets`): components import each other and the bridge by relative path; ng-packagr entry points require package-name imports across entries and would change public import paths. Needs its own design and a major release.
- **`@defer` for heavy widgets** (rich text/maps): changes loading behavior; validate with E2E first.
- **Bridge split**: the characterization tests are in place; splitting `angular-pconnect.ts` into registry/subscription/diff services is the next step.

## Verification required before release
The OnPush changes are covered by unit tests but **must be exercised end-to-end** (MediaCo portal + embedded) before merging, since runtime store-driven rendering cannot be fully reproduced with mocks.
148 changes: 148 additions & 0 deletions docs/components.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
# Component catalogue

<!-- Generated by `npm run docs:components`; do not edit by hand. -->

117 Pega component names are mapped to Angular implementations. Override any of them through `sdk-local-component-map.ts` (see the overrides package).

## designSystemExtension

| Pega component | Angular class | Source |
| --- | --- | --- |
| `Alert` | `AlertComponent` | `_components/designSystemExtension/alert/alert.component.ts` |
| `AlertBanner` | `AlertBannerComponent` | `_components/designSystemExtension/alert-banner/alert-banner.component.ts` |
| `Banner` | `BannerComponent` | `_components/designSystemExtension/banner/banner.component.ts` |
| `CaseCreateStage` | `CaseCreateStageComponent` | `_components/designSystemExtension/case-create-stage/case-create-stage.component.ts` |
| `CaseSummaryFields` | `MaterialCaseSummaryComponent` | `_components/designSystemExtension/material-case-summary/material-case-summary.component.ts` |
| `FieldGroup` | `FieldGroupComponent` | `_components/designSystemExtension/field-group/field-group.component.ts` |
| `MaterialUtility` | `MaterialUtilityComponent` | `_components/designSystemExtension/material-utility/material-utility.component.ts` |
| `Operator` | `OperatorComponent` | `_components/designSystemExtension/operator/operator.component.ts` |
| `Pulse` | `PulseComponent` | `_components/designSystemExtension/pulse/pulse.component.ts` |
| `RichTextEditor` | `RichTextEditorComponent` | `_components/designSystemExtension/rich-text-editor/rich-text-editor.component.ts` |
| `SummaryItem` | `MaterialSummaryItemComponent` | `_components/designSystemExtension/material-summary-item/material-summary-item.component.ts` |
| `SummaryList` | `MaterialSummaryListComponent` | `_components/designSystemExtension/material-summary-list/material-summary-list.component.ts` |
| `VerticalTabs` | `MaterialVerticalTabsComponent` | `_components/designSystemExtension/material-vertical-tabs/material-vertical-tabs.component.ts` |
| `WssQuickCreate` | `WssQuickCreateComponent` | `_components/designSystemExtension/wss-quick-create/wss-quick-create.component.ts` |

## field

| Pega component | Angular class | Source |
| --- | --- | --- |
| `AutoComplete` | `AutoCompleteComponent` | `_components/field/auto-complete/auto-complete.component.ts` |
| `CancelAlert` | `CancelAlertComponent` | `_components/field/cancel-alert/cancel-alert.component.ts` |
| `Checkbox` | `CheckBoxComponent` | `_components/field/check-box/check-box.component.ts` |
| `Currency` | `CurrencyComponent` | `_components/field/currency/currency.component.ts` |
| `Date` | `DateComponent` | `_components/field/date/date.component.ts` |
| `DateTime` | `DateTimeComponent` | `_components/field/date-time/date-time.component.ts` |
| `Decimal` | `DecimalComponent` | `_components/field/decimal/decimal.component.ts` |
| `Dropdown` | `DropdownComponent` | `_components/field/dropdown/dropdown.component.ts` |
| `Email` | `EmailComponent` | `_components/field/email/email.component.ts` |
| `EmbeddedDataMulti` | `EmbeddedDataMultiComponent` | `_components/field/embedded-data-multi/embedded-data-multi.component.ts` |
| `Group` | `GroupComponent` | `_components/field/group/group.component.ts` |
| `Integer` | `IntegerComponent` | `_components/field/integer/integer.component.ts` |
| `ListViewActionButtons` | `ListViewActionButtonsComponent` | `_components/field/list-view-action-buttons/list-view-action-buttons.component.ts` |
| `Location` | `LocationComponent` | `_components/field/location/location.component.ts` |
| `Multiselect` | `MultiselectComponent` | `_components/field/multiselect/multiselect.component.ts` |
| `ObjectReference` | `ObjectReferenceComponent` | `_components/field/object-reference/object-reference.component.ts` |
| `Percentage` | `PercentageComponent` | `_components/field/percentage/percentage.component.ts` |
| `Phone` | `PhoneComponent` | `_components/field/phone/phone.component.ts` |
| `RadioButtons` | `RadioButtonsComponent` | `_components/field/radio-buttons/radio-buttons.component.ts` |
| `RichText` | `RichTextComponent` | `_components/field/rich-text/rich-text.component.ts` |
| `ScalarList` | `ScalarListComponent` | `_components/field/scalar-list/scalar-list.component.ts` |
| `SelectableCard` | `SelectableCardComponent` | `_components/field/selectable-card/selectable-card.component.ts` |
| `SemanticLink` | `SemanticLinkComponent` | `_components/field/semantic-link/semantic-link.component.ts` |
| `Text` | `TextComponent` | `_components/field/text/text.component.ts` |
| `TextArea` | `TextAreaComponent` | `_components/field/text-area/text-area.component.ts` |
| `TextContent` | `TextContentComponent` | `_components/field/text-content/text-content.component.ts` |
| `TextInput` | `TextInputComponent` | `_components/field/text-input/text-input.component.ts` |
| `Time` | `TimeComponent` | `_components/field/time/time.component.ts` |
| `URL` | `UrlComponent` | `_components/field/url/url.component.ts` |
| `UserReference` | `UserReferenceComponent` | `_components/field/user-reference/user-reference.component.ts` |

## infra

| Pega component | Angular class | Source |
| --- | --- | --- |
| `ActionButtons` | `ActionButtonsComponent` | `_components/infra/action-buttons/action-buttons.component.ts` |
| `Assignment` | `AssignmentComponent` | `_components/infra/assignment/assignment.component.ts` |
| `AssignmentCard` | `AssignmentCardComponent` | `_components/infra/assignment-card/assignment-card.component.ts` |
| `DashboardFilter` | `DashboardFilterComponent` | `_components/infra/dashboard-filter/dashboard-filter.component.ts` |
| `DataViewActionButtons` | `DataViewActionButtonsComponent` | `_components/infra/Containers/modal-view-container/data-view-action-buttons/data-view-action-buttons.component.ts` |
| `DeferLoad` | `DeferLoadComponent` | `_components/infra/defer-load/defer-load.component.ts` |
| `ErrorBoundary` | `ErrorBoundaryComponent` | `_components/infra/error-boundary/error-boundary.component.ts` |
| `FlowContainer` | `FlowContainerComponent` | `_components/infra/Containers/flow-container/flow-container.component.ts` |
| `ModalViewContainer` | `ModalViewContainerComponent` | `_components/infra/Containers/modal-view-container/modal-view-container.component.ts` |
| `MultiStep` | `MultiStepComponent` | `_components/infra/multi-step/multi-step.component.ts` |
| `NavBar` | `NavbarComponent` | `_components/infra/navbar/navbar.component.ts` |
| `reference` | `ReferenceComponent` | `_components/infra/reference/reference.component.ts` |
| `Region` | `RegionComponent` | `_components/infra/region/region.component.ts` |
| `RootContainer` | `RootContainerComponent` | `_components/infra/root-container/root-container.component.ts` |
| `Stages` | `StagesComponent` | `_components/infra/stages/stages.component.ts` |
| `View` | `ViewComponent` | `_components/infra/view/view.component.ts` |
| `ViewContainer` | `ViewContainerComponent` | `_components/infra/Containers/view-container/view-container.component.ts` |

## template

| Pega component | Angular class | Source |
| --- | --- | --- |
| `AdvancedSearch` | `AdvancedSearchComponent` | `_components/template/advanced-search/advanced-search.component.ts` |
| `AppShell` | `AppShellComponent` | `_components/template/app-shell/app-shell.component.ts` |
| `BannerPage` | `BannerPageComponent` | `_components/template/banner-page/banner-page.component.ts` |
| `CaseSummary` | `CaseSummaryComponent` | `_components/template/case-summary/case-summary.component.ts` |
| `CaseView` | `CaseViewComponent` | `_components/template/case-view/case-view.component.ts` |
| `Confirmation` | `ConfirmationComponent` | `_components/template/confirmation/confirmation.component.ts` |
| `DataReference` | `DataReferenceComponent` | `_components/template/data-reference/data-reference.component.ts` |
| `DefaultForm` | `DefaultFormComponent` | `_components/template/default-form/default-form.component.ts` |
| `DefaultPage` | `DefaultPageComponent` | `_components/template/default-page/default-page.component.ts` |
| `Details` | `DetailsComponent` | `_components/template/details/details.component.ts` |
| `DetailsOneColumn` | `DetailsOneColumnComponent` | `_components/template/details-one-column/details-one-column.component.ts` |
| `DetailsSubTabs` | `DetailsSubTabsComponent` | `_components/template/details-sub-tabs/details-sub-tabs.component.ts` |
| `DetailsThreeColumn` | `DetailsThreeColumnComponent` | `_components/template/details-three-column/details-three-column.component.ts` |
| `DetailsTwoColumn` | `DetailsTwoColumnComponent` | `_components/template/details-two-column/details-two-column.component.ts` |
| `DynamicTabs` | `DynamicTabsComponent` | `_components/template/dynamic-tabs/dynamic-tabs.component.ts` |
| `FieldGroupList` | `FieldGroupListComponent` | `_components/template/field-group-list/field-group-list.component.ts` |
| `FieldGroupTemplate` | `FieldGroupTemplateComponent` | `_components/template/field-group-template/field-group-template.component.ts` |
| `FieldValueList` | `FieldValueListComponent` | `_components/template/field-value-list/field-value-list.component.ts` |
| `InlineDashboard` | `InlineDashboardComponent` | `_components/template/inline-dashboard/inline-dashboard.component.ts` |
| `InlineDashboardPage` | `InlineDashboardPageComponent` | `_components/template/inline-dashboard-page/inline-dashboard-page.component.ts` |
| `ListPage` | `ListPageComponent` | `_components/template/list-page/list-page.component.ts` |
| `ListView` | `ListViewComponent` | `_components/template/list-view/list-view.component.ts` |
| `MultiReferenceReadOnly` | `MultiReferenceReadonlyComponent` | `_components/template/multi-reference-readonly/multi-reference-readonly.component.ts` |
| `NarrowWideDetails` | `DetailsNarrowWideComponent` | `_components/template/details-narrow-wide/details-narrow-wide.component.ts` |
| `NarrowWideForm` | `NarrowWideFormComponent` | `_components/template/narrow-wide-form/narrow-wide-form.component.ts` |
| `ObjectPage` | `ObjectPageComponent` | `_components/template/object-page/object-page.component.ts` |
| `OneColumn` | `OneColumnComponent` | `_components/template/one-column/one-column.component.ts` |
| `OneColumnPage` | `OneColumnPageComponent` | `_components/template/one-column-page/one-column-page.component.ts` |
| `OneColumnTab` | `OneColumnTabComponent` | `_components/template/one-column-tab/one-column-tab.component.ts` |
| `Page` | `PageComponent` | `_components/template/page/page.component.ts` |
| `PromotedFilters` | `PromotedFiltersComponent` | `_components/template/promoted-filters/promoted-filters.component.ts` |
| `SearchForm` | `SearchFormComponent` | `_components/template/data-reference/search-form/search-form.component.ts` |
| `SearchGroups` | `SearchGroupsComponent` | `_components/template/advanced-search/search-groups/search-groups.component.ts` |
| `SelfServiceCaseView` | `SelfServiceCaseViewComponent` | `_components/template/self-service-case-view/self-service-case-view.component.ts` |
| `SimpleTable` | `SimpleTableComponent` | `_components/template/simple-table/simple-table.component.ts` |
| `SimpleTableManual` | `SimpleTableManualComponent` | `_components/template/simple-table-manual/simple-table-manual.component.ts` |
| `SimpleTableSelect` | `SimpleTableSelectComponent` | `_components/template/simple-table-select/simple-table-select.component.ts` |
| `SingleReferenceReadOnly` | `SingleReferenceReadonlyComponent` | `_components/template/single-reference-readonly/single-reference-readonly.component.ts` |
| `SubTabs` | `SubTabsComponent` | `_components/template/sub-tabs/sub-tabs.component.ts` |
| `ThreeColumn` | `ThreeColumnComponent` | `_components/template/three-column/three-column.component.ts` |
| `ThreeColumnPage` | `ThreeColumnPageComponent` | `_components/template/three-column-page/three-column-page.component.ts` |
| `TwoColumn` | `TwoColumnComponent` | `_components/template/two-column/two-column.component.ts` |
| `TwoColumnPage` | `TwoColumnPageComponent` | `_components/template/two-column-page/two-column-page.component.ts` |
| `TwoColumnTab` | `TwoColumnTabComponent` | `_components/template/two-column-tab/two-column-tab.component.ts` |
| `WideNarrowDetails` | `DetailsWideNarrowComponent` | `_components/template/details-wide-narrow/details-wide-narrow.component.ts` |
| `WideNarrowForm` | `WideNarrowFormComponent` | `_components/template/wide-narrow-form/wide-narrow-form.component.ts` |
| `WideNarrowPage` | `WideNarrowPageComponent` | `_components/template/wide-narrow-page/wide-narrow-page.component.ts` |
| `WssNavBar` | `WssNavBarComponent` | `_components/template/wss-nav-bar/wss-nav-bar.component.ts` |

## widget

| Pega component | Angular class | Source |
| --- | --- | --- |
| `AppAnnouncement` | `AppAnnouncementComponent` | `_components/widget/app-announcement/app-announcement.component.ts` |
| `Attachment` | `AttachmentComponent` | `_components/widget/attachment/attachment.component.ts` |
| `CaseHistory` | `CaseHistoryComponent` | `_components/widget/case-history/case-history.component.ts` |
| `FeedContainer` | `FeedContainerComponent` | `_components/widget/feed-container/feed-container.component.ts` |
| `FileUtility` | `FileUtilityComponent` | `_components/widget/file-utility/file-utility.component.ts` |
| `ListUtility` | `ListUtilityComponent` | `_components/widget/list-utility/list-utility.component.ts` |
| `QuickCreate` | `QuickCreateComponent` | `_components/widget/quick-create/quick-create.component.ts` |
| `Todo` | `TodoComponent` | `_components/widget/todo/todo.component.ts` |

Loading
Loading