Utility Reference
The small shared building blocks live in two places, and the split is historical rather than principled:
|
Left over from the Metronic admin template the project was scaffolded from. Layout services, generic CRUD primitives, pipes and directives. |
|
Payability-authored helpers. |
Nothing here holds business rules. When a helper starts encoding product
behaviour it belongs in a service under core/pyb/services/ instead — see
Service Reference.
Subscriber — the subscription base class
core/pyb/utils/subscriber.class.ts
@Component({ selector: 'subscriber', template: '' })
export abstract class Subscriber implements OnDestroy {
protected subscriptions: Subscription[] = [];
ngOnDestroy() {
this.subscriptions.forEach(subscription => subscription.unsubscribe());
}
addSubscription(sub: Subscription): Subscriber { /* … */ }
addSubscriptions(...sub: Subscription[]): Subscriber { /* … */ }
}
This is the most-extended class in the codebase — around 109 classes inherit from it. Subclasses push their subscriptions in and get teardown for free.
|
A subclass that declares its own |
Components that manage their own teardown instead use a Subject plus
takeUntil, usually named unsubscribe. Both patterns are common; follow
whichever the surrounding file uses.
String, object and date helpers — core/pyb/utils/utils.ts
|
Turns a |
|
Case conversion between API ( |
|
Walks an object and formats every |
|
Single date to |
|
JWT payload as |
|
Comparator factory for |
|
Strips non-digits — phone numbers, account numbers. |
|
Template-literal concatenation. Exists so |
|
Appends a |
|
|
Two more single-purpose helpers sit alongside:
|
The same JWT payload decode as |
|
Recursively drops |
|
Returns |
|
Thrown by unimplemented base-class methods such as |
PybDate
core/pyb/utils/pyb-date.ts
A thin wrapper over date-fns with a Moment-like fluent API, introduced when
Moment was removed. It supports only three units of time:
export type PybDateType = string | Date | number;
export type PybUnitOfTime = 'days' | 'week' | 'year';
|
Defaults to now. Any input is stringified then run through |
|
Epoch milliseconds. |
|
Today at UTC midnight — used for date-picker minimums so the boundary does not shift by timezone. |
|
Delegates to |
|
Difference in days, weeks or years. |
|
Mutate the instance and return |
|
Instant comparison. |
|
|
|
Unwrap. |
|
Three sharp edges:
|
Generic CRUD primitives — core/_base/crud/
Exported from core/_base/crud/index.ts.
|
Template scaffolding: |
|
The template’s data source. Superseded — see the warning below. |
|
|
|
|
|
In-memory |
|
Wraps |
|
Number padding and |
|
There are two classes named
New code wants the second one. Check the import path when reading report code. See Reports for the data source lifecycle. |
HttpUtilsService and TypesUtilsService are provided in AppModule but have
no injection sites left. They are safe to delete once someone confirms no
external consumer imports them.
Pipes — core/_base/layout/pipes/
Each pipe ships with its own NgModule that both declares and provides it, so a
feature module imports JoinModule rather than declaring JoinPipe.
| Pipe | Module | Behaviour |
|---|---|---|
|
|
|
|
|
Space-joins an array; passes non-arrays through unchanged. |
|
|
|
|
|
Initials: splits on spaces and takes the first character of each word, uppercased. Used for avatar placeholders. |
|
|
Appends |
|
|
Renders |
|
|
|
core/pyb/pipes/filter-by.pipe.ts adds filterBy. Currency formatting comes
from PybCurrencyAccountingModule in @payability/pyb-ngx-components.
Directives — core/_base/layout/directives/
ktContentAnimate
Fades and slides content in on every NavigationEnd. It skips the animation
when the URL contains the string content-animation-blocked. A route that
should not re-animate navigates with contentAnimationBlockerParam
(core/_base/layout/models/content-animate-blocker.model.ts) in its query
params, which puts the key in the URL:
export const contentAnimationBlockerKey = 'content-animation-blocked';
export const contentAnimationBlockerParam = { [contentAnimationBlockerKey]: true };
The two-factor setup page uses this so stepping through its sub-states does not replay the page transition.
pybDisabled
Not styling — it toggles the form control’s disabled state, which keeps the
control out of form.value and out of validation:
@Directive({ selector: '([formControlName], [formControl])[pybDisabled]' })
export class PybDisabledDirective implements OnInit {
@Input() set pybDisabled(disabled: boolean) {
this.disabled = disabled;
this.setDisabled();
}
// resolves the control from the host ControlContainer, then calls
// control.disable() / control.enable()
}
The selector requires a formControlName or formControl on the same element.
Without a resolvable control the directive logs a console.warn and does
nothing. Non-boolean values are ignored, so [pybDisabled]="someString" fails
silently.
Use this instead of the disabled attribute on reactive-form inputs — Angular
warns about mixing disabled with formControlName, and this directive is the
project’s answer to that.
ktSticky
An extended fork of
angular-sticky-things. Throttles
scroll and resize to animationFrameScheduler, then sets position: sticky
plus inline top, width, z-index and background-color on the host,
toggling the is-sticky and boundary-reached host classes.
|
Selector or element to observe instead of |
|
A sibling whose height absorbs the host when it goes sticky. Omitting it logs a dev-mode warning and the page will jump. |
|
Element the sticky region may not scroll past. |
|
Offsets, in pixels. |
|
Turns stickiness off, emitting once more so the element un-sticks. |
|
Public; call after layout changes that move the element. |
|
|
Animations — core/pyb/animations/
One trigger, parameterised by height:
export const collapseExpandAnimation = (height: number, duration = '500ms') =>
trigger('inOutAnimation', [
transition(':enter', [style({ height: 0 }), animate(`${duration} ease-out`, style({ height }))]),
transition(':leave', [style({ height }), animate(`${duration} ease-in`, style({ height: 0 }))]),
]);
Because the trigger name is fixed at inOutAnimation, a component can register
it only once. The caller supplies the expanded height, so the animation cannot
adapt to content that measures itself.
Constants — core/pyb/constants/
|
|
|
|
|
Zendesk article URLs, currently just |
|
|
|
Which suspension reasons are supported, which are Amazon-only, and |
|
Banner copy keys for the 2FA nudge. See Two-Factor Authentication. |
|
Banner copy keys for the re-sign prompt. |
APP_CONFIG
core/_config/app-config/app-config.ts — the one place support contact details
are declared. Phone numbers are stored once in display form and derived into
dial-able form at module load:
[PybDepartments.CUSTOMER_EXPERIENCE]: {
VIEW: PhoneNumbers.CUSTOMER_EXPERIENCE,
ONLY_NUMBER: addPrefix(PhoneNumbersPrefixes.US, returnOnlyNumbersFromString(PhoneNumbers.CUSTOMER_EXPERIENCE)),
},
EMAILS holds CUSTOMER_EXPERIENCE, SALES, SUPPORT_API, PARTNERS,
ACCOUNTS and SUSPENSION. The suspension address is an individual’s mailbox
rather than a group alias, which is worth revisiting.
Shared interfaces
core/pyb/interfaces/ holds the cross-feature shapes that are not API DTOs —
Banner and BannerOptions, Action, Tooltip, AdCard,
AuthTokenDecoded, DocusignHandlerParams, ApprovedProducts,
InstantAdvanceTerms, UnifiedSupplierCard and others. Field-level detail
lives with the feature that owns each one; see
Model Reference and
Domain Model.
Two type helpers are worth knowing:
core/pyb/utils/generic-form-group.interface.ts-
GenericFormGroup<V>narrowsFormGroupsovalueis typedVandcontrolsisRecord<keyof V, FormControl>. Use it on form-heavy components to get compile-time checking of control names. See Forms and Fields. core/_base/interfaces/-
BreadcrumbTitle, plus theCountryCode,PcardStatusandPcardTypeIndicatorenums. Enum values are catalogued in Enum Reference.