Rules for working in packages/workbench, the Angular 21 frontend. This page covers
the workbench-specific services and patterns; the general Angular rules are in
angular, components & templates,
state and services.
inject() vs. service().gw token prefix.DialogProviderService.NotificationProviderService, failure handling.*appRestrictAccess directive and ViewPermissions.UnsavedChangesService.transloco pipe and provideTranslocoForTesting().standalone: true). Do not use NgModule declarations.signal(), computed() (see state).inject(); inject API-layer singletons via service() (see architecture).The workbench uses primeng. When building or changing pages:
Details in components.
PrimeNG is configured with the token prefix gw (see packages/workbench/src/app/app.config.ts), so generated CSS custom properties use the --gw-* prefix. See theming.
Open dialogs imperatively via DialogProviderService (packages/workbench/src/app/services/dialog/dialog-provider.service.ts). Do not call PrimeNG DialogService directly — the wrapper applies the onto-dialog CSS class to all dialogs.
Put action buttons in the dialog’s #footer template, not in the body.
NotificationProviderService (services/notification/), not OntoToastrService or
toastr. It feeds the API-layer NotificationService queue, which a future notifications panel will read.
Outside Angular DI (Stencil, legacy) call notify(Notification.error(code)) from @ontotext/workbench-api.Wrap a third-party web component (YASGUI, Reactodia, …) in a facade under components/<name>-facade/ that owns
its initialisation, configuration and events; pages use the facade. Examples: yasgui-component-facade,
graphwise-reactodia-facade.
The facade is the boundary: models, contracts with the backend and doc comments outside it don’t name the
wrapped library (@reactodia/workspace). Readers and the backend contract shouldn’t depend on what’s behind it.
Use the *appRestrictAccess structural directive (packages/workbench/src/app/directives/restrict-access.directive.ts):
<div *appRestrictAccess="['isAdmin', 'canWriteActiveRepo']; else noAccess">...</div>
<ng-template #noAccess>...</ng-template>
Available permissions are in the ViewPermissions enum in that same file.
Register callbacks via UnsavedChangesService.register(callback) (packages/workbench/src/app/services/unsaved-changes/unsaved-changes.service.ts). The returned Subscription unregisters the callback when called.
The workbench uses @jsverse/transloco. Bundles are loaded from the API layer via LanguageContextService and fed to TranslocoService at bootstrap (packages/workbench/src/app/bootstrap/transloco/transloco-bootstrap.ts).
In templates:
some.key
In unit tests, use the helper instead of configuring Transloco manually:
import { provideTranslocoForTesting } from '../../../testing-utils/transloco-utils';
// In TestBed.configureTestingModule:
imports: [provideTranslocoForTesting()]
provideTranslocoForTesting() stubs Transloco with the preloaded English (en.json) bundle. For adding/validating translations see i18n.