@openmfp/ngx 0.18.10 → 0.18.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/openmfp-ngx.mjs +2350 -2184
- package/fesm2022/openmfp-ngx.mjs.map +1 -1
- package/package.json +1 -1
- package/types/openmfp-ngx.d.ts +610 -540
package/types/openmfp-ngx.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import * as _angular_core from '@angular/core';
|
|
2
|
-
import { OnInit, OnDestroy, Type } from '@angular/core';
|
|
3
|
-
import { FormGroup, FormControl } from '@angular/forms';
|
|
4
1
|
import * as _openmfp_ngx from '@openmfp/ngx';
|
|
5
2
|
import * as gridstack from 'gridstack';
|
|
6
3
|
import { Breakpoint, GridStackOptions } from 'gridstack';
|
|
4
|
+
import * as _angular_core from '@angular/core';
|
|
5
|
+
import { OnInit, OnDestroy, Type, PipeTransform } from '@angular/core';
|
|
7
6
|
import { GridStackEngine } from 'gridstack/dist/gridstack-engine';
|
|
8
7
|
import { SafeHtml } from '@angular/platform-browser';
|
|
8
|
+
import { FormGroup, FormControl } from '@angular/forms';
|
|
9
9
|
|
|
10
10
|
/** Subset of fields of a generic resource that the table/form components rely on. */
|
|
11
11
|
interface GenericResource extends Record<string, unknown> {
|
|
@@ -136,241 +136,574 @@ interface FieldDefinition {
|
|
|
136
136
|
* column/input of an entry. Mirrors `propertyField` naming for consistency.
|
|
137
137
|
*/
|
|
138
138
|
propertyCollection?: FieldDefinition[];
|
|
139
|
+
/** Verb required to render this field (e.g. 'update', 'delete').
|
|
140
|
+
* Evaluated against the row's granted actions. Absent → always render. */
|
|
141
|
+
requirePermission?: string;
|
|
139
142
|
}
|
|
140
143
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
type ProcessedGroup = GroupBase & {
|
|
158
|
-
fields?: TableFieldDefinition[];
|
|
159
|
-
};
|
|
160
|
-
type ProcessedTableFieldDefinition = Omit<TableFieldDefinition, 'group'> & {
|
|
161
|
-
group?: ProcessedGroup;
|
|
144
|
+
type DashboardLanguage = 'en' | 'de';
|
|
145
|
+
declare const DASHBOARD_I18N_KEYS: {
|
|
146
|
+
readonly UNSAVED_CHANGES: "unsavedChanges";
|
|
147
|
+
readonly EDIT_CARDS: "editCards";
|
|
148
|
+
readonly EDIT_VIEW: "editView";
|
|
149
|
+
readonly ACTIONS: "actions";
|
|
150
|
+
readonly SAVE: "save";
|
|
151
|
+
readonly CANCEL: "cancel";
|
|
152
|
+
readonly DISCARD: "discard";
|
|
153
|
+
readonly DISCARD_CHANGES: "discardChanges";
|
|
154
|
+
readonly DISCARD_CONFIRM_BODY: "discardConfirmBody";
|
|
155
|
+
readonly UNSAVED_NAV_BODY: "unsavedNavBody";
|
|
156
|
+
readonly NO_CARDS_AVAILABLE: "noCardsAvailable";
|
|
157
|
+
readonly REMOVE_SECTION: "removeSection";
|
|
158
|
+
readonly REMOVE_CARD: "removeCard";
|
|
159
|
+
readonly RESIZABLE: "resizable";
|
|
162
160
|
};
|
|
161
|
+
type DashboardI18nKey = (typeof DASHBOARD_I18N_KEYS)[keyof typeof DASHBOARD_I18N_KEYS];
|
|
163
162
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
readonly loadMoreResources: _angular_core.OutputEmitterRef<void>;
|
|
178
|
-
readonly paginationLimitChanged: _angular_core.OutputEmitterRef<number>;
|
|
179
|
-
readonly pageChange: _angular_core.OutputEmitterRef<number>;
|
|
180
|
-
columnTrackBy: (column: TableFieldDefinition, index: number) => string | number | string[];
|
|
181
|
-
rowTrackBy: (_index: number, item: T) => unknown;
|
|
182
|
-
viewColumns: _angular_core.Signal<ProcessedTableFieldDefinition[]>;
|
|
183
|
-
onRowClick(item: T): void;
|
|
184
|
-
isPagerMode: _angular_core.Signal<boolean>;
|
|
185
|
-
knowsTotal: _angular_core.Signal<boolean>;
|
|
186
|
-
hasResults: _angular_core.Signal<boolean>;
|
|
187
|
-
totalPages: _angular_core.Signal<number>;
|
|
188
|
-
canPrev: _angular_core.Signal<boolean>;
|
|
189
|
-
canNext: _angular_core.Signal<boolean>;
|
|
190
|
-
goToPage(page: number): void;
|
|
191
|
-
firstPage: () => void;
|
|
192
|
-
prevPage: () => void;
|
|
193
|
-
nextPage: () => void;
|
|
194
|
-
lastPage: () => void;
|
|
195
|
-
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DeclarativeTable<any>, never>;
|
|
196
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DeclarativeTable<any>, "mfp-declarative-table", never, { "columns": { "alias": "columns"; "required": true; "isSignal": true; }; "resources": { "alias": "resources"; "required": true; "isSignal": true; }; "trackByPath": { "alias": "trackByPath"; "required": false; "isSignal": true; }; "totalItemsCount": { "alias": "totalItemsCount"; "required": false; "isSignal": true; }; "paginationLimit": { "alias": "paginationLimit"; "required": false; "isSignal": true; }; "hasMore": { "alias": "hasMore"; "required": false; "isSignal": true; }; "loadMode": { "alias": "loadMode"; "required": false; "isSignal": true; }; "loadMoreButtonText": { "alias": "loadMoreButtonText"; "required": false; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; "currentPage": { "alias": "currentPage"; "required": false; "isSignal": true; }; }, { "buttonClick": "buttonClick"; "tableRowClicked": "tableRowClicked"; "loadMoreResources": "loadMoreResources"; "paginationLimitChanged": "paginationLimitChanged"; "pageChange": "pageChange"; }, never, never, true, never>;
|
|
163
|
+
/**
|
|
164
|
+
* Holds the dashboard's current language and resolves translation keys for
|
|
165
|
+
* the dashboard chrome (toolbar buttons, dialogs, a11y labels). Provided at
|
|
166
|
+
* the `Dashboard` component level so every nested dashboard component shares
|
|
167
|
+
* the same language signal — child components inject the same instance and
|
|
168
|
+
* react to language changes automatically because `getTranslation` reads the
|
|
169
|
+
* signal on every call.
|
|
170
|
+
*/
|
|
171
|
+
declare class DashboardI18nService {
|
|
172
|
+
readonly language: _angular_core.WritableSignal<DashboardLanguage>;
|
|
173
|
+
getTranslation(key: DashboardI18nKey): string;
|
|
174
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DashboardI18nService, never>;
|
|
175
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<DashboardI18nService>;
|
|
197
176
|
}
|
|
198
177
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
|
|
178
|
+
declare const CARD_TYPES: {
|
|
179
|
+
readonly WC: "wc";
|
|
180
|
+
readonly ANGULAR: "angular";
|
|
181
|
+
readonly SAP_UI: "sap-ui";
|
|
182
|
+
};
|
|
183
|
+
type CardsType = (typeof CARD_TYPES)[keyof typeof CARD_TYPES];
|
|
184
|
+
/** Configuration for a single card placed in the dashboard grid or a section. */
|
|
185
|
+
interface CardConfig {
|
|
186
|
+
/** Unique identifier for this card. Used as a stable key for position persistence. */
|
|
187
|
+
id: string;
|
|
188
|
+
/** Column span (1–12). Defaults to 12 when omitted. */
|
|
189
|
+
w?: number;
|
|
190
|
+
/** Row span — number of CSS grid rows occupied (1 row = 10 px by default). Defaults to 100 when omitted. */
|
|
191
|
+
h?: number;
|
|
192
|
+
/** Starting column index (0-based). Omit to let the grid auto-place the card. */
|
|
193
|
+
x?: number;
|
|
194
|
+
/** Starting row index (0-based). Omit to let the grid auto-place the card. */
|
|
195
|
+
y?: number;
|
|
196
|
+
/** Maximum row span in edit mode. */
|
|
197
|
+
maxH?: number;
|
|
198
|
+
/** Maximum column span in edit mode. */
|
|
199
|
+
maxW?: number;
|
|
200
|
+
/** Minimum row span in edit mode. */
|
|
201
|
+
minH?: number;
|
|
202
|
+
/** Minimum column span in edit mode. */
|
|
203
|
+
minW?: number;
|
|
204
|
+
/** ID of the parent section. Omit to place the card in the loose-card grid. */
|
|
205
|
+
sectionId?: string;
|
|
213
206
|
/**
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
* When set, this field represents an array of objects; the form renders it
|
|
217
|
-
* as a stack of expandable/collapsible cards. Each card is a nested
|
|
218
|
-
* `mfp-declarative-form` whose `fields` are the entries in
|
|
219
|
-
* `propertyCollection`; an inline Add button appends entries and a trash
|
|
220
|
-
* button removes them. Editing is live — no per-card Save/Cancel.
|
|
221
|
-
*
|
|
222
|
-
* The submitted value at this field's path is `Array<Record<string, unknown>>`,
|
|
223
|
-
* with each entry keyed by the sub-fields' `name`s. When `required` is
|
|
224
|
-
* `true`, the host is expected to require at least one entry in the array.
|
|
207
|
+
* Custom-element tag name (for `'wc'`/omitted), Angular component selector (for `'angular'`),
|
|
208
|
+
* or SAP UI5 component name (for `'sap-ui'`).
|
|
225
209
|
*/
|
|
226
|
-
|
|
227
|
-
}
|
|
228
|
-
/** Event payload emitted each time a single form field value changes. */
|
|
229
|
-
interface FormFieldChangeEvent {
|
|
230
|
-
/** The `name` (JSON-path key) of the field that changed. */
|
|
231
|
-
fieldProperty: string;
|
|
232
|
-
/** The new value entered by the user. */
|
|
233
|
-
value: unknown;
|
|
234
|
-
}
|
|
235
|
-
/** Map of field names to their current validation error messages (`null` = no error). */
|
|
236
|
-
type FormFieldErrors = Record<string, string | null>;
|
|
237
|
-
|
|
238
|
-
declare class DeclarativeForm<T extends GenericResource> {
|
|
239
|
-
readonly fields: _angular_core.InputSignal<FormFieldDefinition[]>;
|
|
240
|
-
readonly initialValues: _angular_core.InputSignal<T>;
|
|
241
|
-
readonly fieldErrors: _angular_core.InputSignal<FormFieldErrors>;
|
|
242
|
-
readonly fieldChange: _angular_core.OutputEmitterRef<FormFieldChangeEvent>;
|
|
243
|
-
readonly formSubmit: _angular_core.OutputEmitterRef<T>;
|
|
244
|
-
readonly formValueChange: _angular_core.OutputEmitterRef<Record<string, unknown>>;
|
|
245
|
-
readonly form: FormGroup;
|
|
246
|
-
protected readonly collectionSeeds: _angular_core.WritableSignal<Record<string, Record<string, unknown>[]>>;
|
|
247
|
-
private readonly fb;
|
|
248
|
-
constructor();
|
|
249
|
-
setFormControlValue($event: Event, field: FormFieldDefinition): void;
|
|
250
|
-
onCollectionValueChange(field: FormFieldDefinition, entries: Record<string, unknown>[]): void;
|
|
251
|
-
getError(name: string): string | null;
|
|
252
|
-
getValueState(name: string): 'None' | 'Negative';
|
|
253
|
-
onFieldBlur(field: FormFieldDefinition): void;
|
|
254
|
-
submit(): void;
|
|
255
|
-
clear(): void;
|
|
256
|
-
collectionEntries(field: FormFieldDefinition): Record<string, unknown>[];
|
|
257
|
-
private rebuildControls;
|
|
258
|
-
private setInitialValues;
|
|
259
|
-
private buildOutputValue;
|
|
260
|
-
private buildEntryGroup;
|
|
261
|
-
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DeclarativeForm<any>, never>;
|
|
262
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DeclarativeForm<any>, "mfp-declarative-form", never, { "fields": { "alias": "fields"; "required": true; "isSignal": true; }; "initialValues": { "alias": "initialValues"; "required": false; "isSignal": true; }; "fieldErrors": { "alias": "fieldErrors"; "required": false; "isSignal": true; }; }, { "fieldChange": "fieldChange"; "formSubmit": "formSubmit"; "formValueChange": "formValueChange"; }, never, never, true, never>;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/** Configuration for the create/edit resource form rendered inside the table card dialogs. */
|
|
266
|
-
interface ResourceFormConfig {
|
|
210
|
+
component: string;
|
|
267
211
|
/**
|
|
268
|
-
*
|
|
269
|
-
*
|
|
270
|
-
*
|
|
271
|
-
*
|
|
212
|
+
* Render strategy for the card.
|
|
213
|
+
* - `'wc'` (default) — creates a custom element and sets `componentInputs` as DOM properties.
|
|
214
|
+
* - `'angular'` — looks up the Angular registry; warns and renders nothing if not found.
|
|
215
|
+
* - `'sap-ui'` — mounts via `window.sap.ui.require` + `ComponentContainer`.
|
|
272
216
|
*/
|
|
273
|
-
|
|
274
|
-
/**
|
|
217
|
+
type?: CardsType;
|
|
218
|
+
/** Key/value pairs passed to the rendered card. Behaviour depends on `type`. */
|
|
219
|
+
componentInputs?: Record<string, unknown>;
|
|
220
|
+
/** Human-readable label shown in the "Edit Cards" dialog. */
|
|
221
|
+
label?: string;
|
|
222
|
+
}
|
|
223
|
+
type MountCfg = Pick<CardConfig, 'type' | 'component' | 'componentInputs'>;
|
|
224
|
+
/** Configuration for a named horizontal section that groups cards. */
|
|
225
|
+
interface SectionConfig {
|
|
226
|
+
/** Unique identifier for this section. */
|
|
227
|
+
id: string;
|
|
228
|
+
/** Column span (1–12). Defaults to 12 when omitted. */
|
|
229
|
+
w?: number;
|
|
230
|
+
/** Section heading displayed in the UI. */
|
|
275
231
|
title?: string;
|
|
276
|
-
/**
|
|
277
|
-
|
|
278
|
-
/** Label for the cancel button. */
|
|
279
|
-
cancelLabel?: string;
|
|
232
|
+
/** When `false`, the section and its cards are excluded from edit mode. Defaults to `true` when omitted. */
|
|
233
|
+
editable?: boolean;
|
|
280
234
|
}
|
|
281
|
-
/**
|
|
282
|
-
interface
|
|
283
|
-
/**
|
|
284
|
-
|
|
235
|
+
/** Overrides for the two built-in dashboard toolbar buttons. */
|
|
236
|
+
interface DashboardButtonsSettings {
|
|
237
|
+
/** Partial override merged on top of the Edit View button defaults. */
|
|
238
|
+
editViewButton?: Partial<ButtonSettings>;
|
|
239
|
+
/** Partial override merged on top of the Edit Cards button defaults. */
|
|
240
|
+
editCardsButton?: Partial<ButtonSettings>;
|
|
285
241
|
}
|
|
286
|
-
/**
|
|
287
|
-
interface
|
|
288
|
-
/**
|
|
289
|
-
title
|
|
290
|
-
/**
|
|
291
|
-
|
|
292
|
-
/**
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
|
|
242
|
+
/** Top-level configuration for the `<mfp-dashboard>` component. */
|
|
243
|
+
interface DashboardConfig {
|
|
244
|
+
/** Dashboard title rendered in the toolbar. */
|
|
245
|
+
title: string;
|
|
246
|
+
/** Optional subtitle shown below the title. */
|
|
247
|
+
description?: string;
|
|
248
|
+
/** URL of the background image applied to the dashboard host element. */
|
|
249
|
+
backgroundImageUrl?: string;
|
|
250
|
+
/** Overrides for the built-in Edit View and Edit Cards toolbar buttons. */
|
|
251
|
+
buttonsSettings?: DashboardButtonsSettings;
|
|
252
|
+
/** Extra action buttons rendered in the toolbar alongside the built-in ones. */
|
|
253
|
+
customActions?: ButtonSettings[];
|
|
254
|
+
/** When `true`, shows the Edit View button in the toolbar, allowing the user to enter edit mode. */
|
|
255
|
+
editable?: boolean;
|
|
256
|
+
/** When `true`, the Edit View button is rendered before the custom actions instead of after. Defaults to `false`. */
|
|
257
|
+
editButtonFirst?: boolean;
|
|
258
|
+
/** When provided, enable z-flow layout. */
|
|
259
|
+
zFlow?: {
|
|
260
|
+
/** Sets the height of each card in the z-flow layout. */
|
|
261
|
+
cardHeight: number;
|
|
262
|
+
};
|
|
296
263
|
}
|
|
264
|
+
|
|
297
265
|
/**
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
* selected definition via the `filterTabChanged` output and is responsible for
|
|
301
|
-
* applying the filter to its data set.
|
|
302
|
-
*
|
|
303
|
-
* The strip renders exactly the array of `FieldFilterDefinition` it receives
|
|
304
|
-
* — no extra "All" / no-filter tab is auto-added. If the host wants such an
|
|
305
|
-
* option it must author it as a regular filter entry.
|
|
266
|
+
* Layout strategy applied at each breakpoint when Gridstack changes column
|
|
267
|
+
* count. See ColumnOptions in gridstack/dist/types.d.ts:27 for the full set.
|
|
306
268
|
*/
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
269
|
+
type LayoutStrategy = 'compact' | 'list' | 'none';
|
|
270
|
+
type DashboardBreakpoint = Readonly<Required<Pick<Breakpoint, 'w' | 'c'>> & {
|
|
271
|
+
layout: LayoutStrategy;
|
|
272
|
+
}>;
|
|
273
|
+
|
|
274
|
+
interface EngineProfile {
|
|
275
|
+
/** GridStack engine class, or undefined to use GridStack's native engine. */
|
|
276
|
+
engineClass: typeof GridStackEngine | undefined;
|
|
277
|
+
/** Column breakpoint table fed to GridStack columnOpts. */
|
|
278
|
+
breakpoints: readonly DashboardBreakpoint[];
|
|
279
|
+
/** Column counts for [sm, md, lg, xl] page size. Pushed to CSS vars so the section grids match. */
|
|
280
|
+
sectionColumns: readonly [number, number, number, number];
|
|
281
|
+
/** When true, all loose cards get a fixed h/maxH from the engine's config. */
|
|
282
|
+
fixedCardHeight: boolean;
|
|
283
|
+
/** When true, the XL-page width swap (3↔4) runs. */
|
|
284
|
+
xlWidthSwap: boolean;
|
|
285
|
+
/** When true, the origin position is rendered. */
|
|
286
|
+
renderOriginPosition: boolean;
|
|
316
287
|
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
288
|
+
|
|
289
|
+
declare class Dashboard implements OnInit, OnDestroy {
|
|
290
|
+
static registerAngularComponents(componentTypes: Type<unknown>[]): void;
|
|
291
|
+
private readonly hostEl;
|
|
292
|
+
private readonly injector;
|
|
293
|
+
private readonly sanitizer;
|
|
294
|
+
protected readonly i18n: DashboardI18nService;
|
|
295
|
+
config: _angular_core.InputSignal<DashboardConfig>;
|
|
296
|
+
sections: _angular_core.ModelSignal<SectionConfig[]>;
|
|
297
|
+
cards: _angular_core.ModelSignal<CardConfig[]>;
|
|
298
|
+
availableCards: _angular_core.InputSignal<CardConfig[]>;
|
|
299
|
+
language: _angular_core.InputSignal<DashboardLanguage>;
|
|
300
|
+
readonly saved: _angular_core.OutputEmitterRef<{
|
|
301
|
+
sections: SectionConfig[];
|
|
302
|
+
cards: CardConfig[];
|
|
303
|
+
}>;
|
|
304
|
+
readonly actionButtonClick: _angular_core.OutputEmitterRef<{
|
|
305
|
+
event: MouseEvent;
|
|
306
|
+
action: ButtonSettings;
|
|
307
|
+
}>;
|
|
308
|
+
readonly unsavedChangesChange: _angular_core.OutputEmitterRef<boolean>;
|
|
309
|
+
protected readonly i18nKeys: {
|
|
310
|
+
readonly UNSAVED_CHANGES: "unsavedChanges";
|
|
311
|
+
readonly EDIT_CARDS: "editCards";
|
|
312
|
+
readonly EDIT_VIEW: "editView";
|
|
313
|
+
readonly ACTIONS: "actions";
|
|
314
|
+
readonly SAVE: "save";
|
|
315
|
+
readonly CANCEL: "cancel";
|
|
316
|
+
readonly DISCARD: "discard";
|
|
317
|
+
readonly DISCARD_CHANGES: "discardChanges";
|
|
318
|
+
readonly DISCARD_CONFIRM_BODY: "discardConfirmBody";
|
|
319
|
+
readonly UNSAVED_NAV_BODY: "unsavedNavBody";
|
|
320
|
+
readonly NO_CARDS_AVAILABLE: "noCardsAvailable";
|
|
321
|
+
readonly REMOVE_SECTION: "removeSection";
|
|
322
|
+
readonly REMOVE_CARD: "removeCard";
|
|
323
|
+
readonly RESIZABLE: "resizable";
|
|
324
|
+
};
|
|
325
|
+
/** True once the user has dragged/resized any grid item while in edit mode. */
|
|
326
|
+
private gridDirty;
|
|
327
|
+
private isXLPage;
|
|
328
|
+
editMode: _angular_core.WritableSignal<boolean>;
|
|
329
|
+
compactToolbar: _angular_core.WritableSignal<boolean>;
|
|
330
|
+
toolbarMenuOpen: _angular_core.WritableSignal<boolean>;
|
|
331
|
+
cardDialogOpen: _angular_core.WritableSignal<boolean>;
|
|
332
|
+
discardDialogOpen: _angular_core.WritableSignal<boolean>;
|
|
333
|
+
unsavedNavDialogOpen: _angular_core.WritableSignal<boolean>;
|
|
334
|
+
backgroundImageHeight: _angular_core.WritableSignal<number | null>;
|
|
335
|
+
dragOriginStyle: _angular_core.WritableSignal<{
|
|
336
|
+
top: string;
|
|
337
|
+
left: string;
|
|
338
|
+
width: string;
|
|
339
|
+
height: string;
|
|
340
|
+
} | null>;
|
|
341
|
+
protected hasUnsavedChanges: _angular_core.Signal<boolean>;
|
|
342
|
+
protected safeTitle: _angular_core.Signal<SafeHtml>;
|
|
343
|
+
protected safeDescription: _angular_core.Signal<SafeHtml | null>;
|
|
344
|
+
protected engineProfile: _angular_core.Signal<EngineProfile>;
|
|
345
|
+
protected gridStackEngine: _angular_core.Signal<typeof gridstack.GridStackEngine | undefined>;
|
|
346
|
+
protected gridBreakpoints: _angular_core.Signal<Readonly<Required<Pick<gridstack.Breakpoint, "w" | "c">> & {
|
|
347
|
+
layout: "compact" | "list" | "none";
|
|
348
|
+
}>[]>;
|
|
349
|
+
protected columnVars: _angular_core.Signal<{
|
|
350
|
+
'--dashboard-cols-sm': number;
|
|
351
|
+
'--dashboard-cols-md': number;
|
|
352
|
+
'--dashboard-cols-lg': number;
|
|
353
|
+
'--dashboard-cols-xl': number;
|
|
354
|
+
}>;
|
|
355
|
+
protected customActions: _angular_core.Signal<ButtonSettings[]>;
|
|
356
|
+
protected addedCardsIds: _angular_core.Signal<Set<string>>;
|
|
357
|
+
protected editViewButton: _angular_core.Signal<{
|
|
358
|
+
text: string;
|
|
359
|
+
icon: string;
|
|
360
|
+
endIcon?: string;
|
|
361
|
+
design: "Default" | "Positive" | "Negative" | "Transparent" | "Emphasized" | "Attention";
|
|
362
|
+
tooltip: string;
|
|
363
|
+
action?: (("openInModal" | "navigate" | "edit" | "delete") | (string & {})) | undefined;
|
|
364
|
+
modalSettings?: _openmfp_ngx.ModalSettings;
|
|
365
|
+
}>;
|
|
366
|
+
protected editCardsButton: _angular_core.Signal<{
|
|
367
|
+
text: string;
|
|
368
|
+
icon: string;
|
|
369
|
+
endIcon?: string;
|
|
370
|
+
design: "Default" | "Positive" | "Negative" | "Transparent" | "Emphasized" | "Attention";
|
|
371
|
+
tooltip: string;
|
|
372
|
+
action?: (("openInModal" | "navigate" | "edit" | "delete") | (string & {})) | undefined;
|
|
373
|
+
modalSettings?: _openmfp_ngx.ModalSettings;
|
|
374
|
+
}>;
|
|
375
|
+
protected sectionCards: _angular_core.Signal<(sectionId: string) => CardConfig[]>;
|
|
376
|
+
protected looseCards: _angular_core.WritableSignal<CardConfig[]>;
|
|
377
|
+
protected gridOptions: _angular_core.Signal<GridStackOptions>;
|
|
378
|
+
/** JSON snapshots of sections/cards taken on entering edit mode, used to detect changes. */
|
|
379
|
+
private sectionsSnapshotJson;
|
|
380
|
+
private cardsSnapshotJson;
|
|
381
|
+
private sectionsSnapshot;
|
|
382
|
+
private cardsSnapshot;
|
|
383
|
+
private gridStack;
|
|
384
|
+
private addCardBtn;
|
|
385
|
+
private resizeObserver?;
|
|
386
|
+
private cardsPosition;
|
|
387
|
+
/** Callback that resumes the intercepted navigation once the user resolves the dialog. */
|
|
388
|
+
private pendingNavigation;
|
|
389
|
+
/** beforeunload handler kept on instance so add/removeEventListener pair up. */
|
|
390
|
+
private readonly beforeUnloadHandler;
|
|
391
|
+
constructor();
|
|
392
|
+
ngOnInit(): void;
|
|
393
|
+
ngOnDestroy(): void;
|
|
394
|
+
onMenuItemClick(actionId: string, event: Event): void;
|
|
395
|
+
enterEditMode(): void;
|
|
396
|
+
saveEdit(): void;
|
|
397
|
+
cancelEdit(): void;
|
|
398
|
+
confirmDiscard(): void;
|
|
399
|
+
cancelDiscard(): void;
|
|
330
400
|
/**
|
|
331
|
-
*
|
|
332
|
-
*
|
|
333
|
-
*
|
|
401
|
+
* Public framework-agnostic navigation guard. Consumer apps (Angular Router
|
|
402
|
+
* CanDeactivate guard, Luigi navigation listener, plain `<a>` click handler,
|
|
403
|
+
* window history listener — anything) call this before performing their
|
|
404
|
+
* navigation:
|
|
405
|
+
*
|
|
406
|
+
* if (dashboard.requestNavigation(() => router.navigateByUrl(target))) {
|
|
407
|
+
* // already navigated synchronously — clean state
|
|
408
|
+
* } else {
|
|
409
|
+
* // dashboard popped the unsaved-changes dialog; the navigation will
|
|
410
|
+
* // resume from the user's choice (Save → proceed, Discard → proceed,
|
|
411
|
+
* // Cancel → drop the request entirely).
|
|
412
|
+
* }
|
|
413
|
+
*
|
|
414
|
+
* Returns `true` when navigation may proceed immediately (no unsaved
|
|
415
|
+
* changes — `proceed` was invoked synchronously). Returns `false` when the
|
|
416
|
+
* dialog has been opened and the caller must NOT navigate; the dashboard
|
|
417
|
+
* will run the callback later if the user picks Save or Discard.
|
|
418
|
+
*
|
|
419
|
+
* If a previous navigation is already pending, that one is dropped in
|
|
420
|
+
* favour of the new request — Cancel always means "stay here", so losing
|
|
421
|
+
* the older queued navigation is the correct outcome.
|
|
334
422
|
*/
|
|
335
|
-
|
|
336
|
-
/**
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
423
|
+
requestNavigation(proceed: () => void): boolean;
|
|
424
|
+
/** Save → persist changes, close the dialog, then resume navigation. */
|
|
425
|
+
onUnsavedNavSave(): void;
|
|
426
|
+
/** Discard → revert to snapshot, close the dialog, then resume navigation. */
|
|
427
|
+
onUnsavedNavDiscard(): void;
|
|
428
|
+
/** Cancel → drop the queued navigation and stay in edit mode. */
|
|
429
|
+
onUnsavedNavCancel(): void;
|
|
430
|
+
private runPendingNavigation;
|
|
431
|
+
private discardEdit;
|
|
432
|
+
removeSection(id: string): void;
|
|
433
|
+
removeCard(id: string): void;
|
|
434
|
+
openCardPanel(): void;
|
|
435
|
+
closeCardPanel(): void;
|
|
436
|
+
onCardsEdited(event: {
|
|
437
|
+
added: CardConfig[];
|
|
438
|
+
removed: string[];
|
|
439
|
+
}): void;
|
|
440
|
+
onDragStart(event: {
|
|
441
|
+
el: Element;
|
|
442
|
+
}): void;
|
|
443
|
+
onDragStop(): void;
|
|
444
|
+
onGridChange(): void;
|
|
445
|
+
private saveCardsPosition;
|
|
446
|
+
private updateCardsPositions;
|
|
447
|
+
private getZFlowEngine;
|
|
448
|
+
private updateCardsForBreakpoint;
|
|
449
|
+
private changeCardSettingsForXlPage;
|
|
450
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<Dashboard, never>;
|
|
451
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<Dashboard, "mfp-dashboard", never, { "config": { "alias": "config"; "required": true; "isSignal": true; }; "sections": { "alias": "sections"; "required": false; "isSignal": true; }; "cards": { "alias": "cards"; "required": false; "isSignal": true; }; "availableCards": { "alias": "availableCards"; "required": false; "isSignal": true; }; "language": { "alias": "language"; "required": false; "isSignal": true; }; }, { "sections": "sectionsChange"; "cards": "cardsChange"; "saved": "saved"; "actionButtonClick": "actionButtonClick"; "unsavedChangesChange": "unsavedChangesChange"; }, never, ["[slot=dashboard-subheader]"], true, never>;
|
|
349
452
|
}
|
|
453
|
+
|
|
350
454
|
/**
|
|
351
|
-
*
|
|
352
|
-
*
|
|
353
|
-
*
|
|
455
|
+
* `createCustomElement` only proxies `@Input()`/`output()` — public methods on
|
|
456
|
+
* the component class are NOT reachable from the DOM. This forwards the
|
|
457
|
+
* dashboard's public methods onto the custom-element prototype so that
|
|
458
|
+
* non-Angular consumers (UI5, plain JS, Luigi, etc.) can call them directly on
|
|
459
|
+
* the `<mfp-wc-dashboard>` DOM node.
|
|
354
460
|
*
|
|
355
|
-
* `
|
|
356
|
-
*
|
|
357
|
-
*
|
|
358
|
-
*
|
|
461
|
+
* `requestNavigation` needs a synchronous fallback when the Angular component
|
|
462
|
+
* isn't created yet: run the navigation immediately (returning `true`) rather
|
|
463
|
+
* than silently blocking the user — this preserves the original, pre-guard
|
|
464
|
+
* behaviour. The remaining handlers no-op until the component exists.
|
|
359
465
|
*/
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
466
|
+
declare function defineDashboardElementMethods(elementCtor: CustomElementConstructor): void;
|
|
467
|
+
|
|
468
|
+
/** Definition for a single form field rendered by `mfp-declarative-form`. */
|
|
469
|
+
interface FormFieldDefinition {
|
|
470
|
+
/** JSON-path key used to read and write the field value (e.g. `metadata.name`). */
|
|
471
|
+
name: string;
|
|
472
|
+
/** Display label shown above the input. */
|
|
473
|
+
label: string;
|
|
474
|
+
/** When `true`, passes the `required` attribute to the UI5 input — shows a visual required indicator. Validation itself is the host's responsibility via `FormFieldErrors`. */
|
|
475
|
+
required?: boolean;
|
|
476
|
+
/** Fixed list of options rendered as a select/dropdown. */
|
|
477
|
+
values?: string[];
|
|
478
|
+
/** When `true`, the field is disabled (not interactive). */
|
|
479
|
+
disabled?: boolean;
|
|
480
|
+
/** Controls when `fieldChange` is emitted for this field. When omitted, `fieldChange` is never emitted. */
|
|
481
|
+
validation?: 'onBlur' | 'onChange';
|
|
372
482
|
/**
|
|
373
|
-
*
|
|
483
|
+
* Nested field definitions describing one item of an object collection.
|
|
484
|
+
*
|
|
485
|
+
* When set, this field represents an array of objects; the form renders it
|
|
486
|
+
* as a stack of expandable/collapsible cards. Each card is a nested
|
|
487
|
+
* `mfp-declarative-form` whose `fields` are the entries in
|
|
488
|
+
* `propertyCollection`; an inline Add button appends entries and a trash
|
|
489
|
+
* button removes them. Editing is live — no per-card Save/Cancel.
|
|
490
|
+
*
|
|
491
|
+
* The submitted value at this field's path is `Array<Record<string, unknown>>`,
|
|
492
|
+
* with each entry keyed by the sub-fields' `name`s. When `required` is
|
|
493
|
+
* `true`, the host is expected to require at least one entry in the array.
|
|
494
|
+
*/
|
|
495
|
+
propertyCollection?: FormFieldDefinition[];
|
|
496
|
+
}
|
|
497
|
+
/** Event payload emitted each time a single form field value changes. */
|
|
498
|
+
interface FormFieldChangeEvent {
|
|
499
|
+
/** The `name` (JSON-path key) of the field that changed. */
|
|
500
|
+
fieldProperty: string;
|
|
501
|
+
/** The new value entered by the user. */
|
|
502
|
+
value: unknown;
|
|
503
|
+
}
|
|
504
|
+
/** Map of field names to their current validation error messages (`null` = no error). */
|
|
505
|
+
type FormFieldErrors = Record<string, string | null>;
|
|
506
|
+
|
|
507
|
+
declare class DeclarativeForm<T extends GenericResource> {
|
|
508
|
+
readonly fields: _angular_core.InputSignal<FormFieldDefinition[]>;
|
|
509
|
+
readonly initialValues: _angular_core.InputSignal<T>;
|
|
510
|
+
readonly fieldErrors: _angular_core.InputSignal<FormFieldErrors>;
|
|
511
|
+
readonly fieldChange: _angular_core.OutputEmitterRef<FormFieldChangeEvent>;
|
|
512
|
+
readonly formSubmit: _angular_core.OutputEmitterRef<T>;
|
|
513
|
+
readonly formValueChange: _angular_core.OutputEmitterRef<Record<string, unknown>>;
|
|
514
|
+
readonly form: FormGroup;
|
|
515
|
+
protected readonly collectionSeeds: _angular_core.WritableSignal<Record<string, Record<string, unknown>[]>>;
|
|
516
|
+
private readonly fb;
|
|
517
|
+
constructor();
|
|
518
|
+
setFormControlValue($event: Event, field: FormFieldDefinition): void;
|
|
519
|
+
onCollectionValueChange(field: FormFieldDefinition, entries: Record<string, unknown>[]): void;
|
|
520
|
+
getError(name: string): string | null;
|
|
521
|
+
getValueState(name: string): 'None' | 'Negative';
|
|
522
|
+
onFieldBlur(field: FormFieldDefinition): void;
|
|
523
|
+
submit(): void;
|
|
524
|
+
clear(): void;
|
|
525
|
+
collectionEntries(field: FormFieldDefinition): Record<string, unknown>[];
|
|
526
|
+
private rebuildControls;
|
|
527
|
+
private setInitialValues;
|
|
528
|
+
private buildOutputValue;
|
|
529
|
+
private buildEntryGroup;
|
|
530
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DeclarativeForm<any>, never>;
|
|
531
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DeclarativeForm<any>, "mfp-declarative-form", never, { "fields": { "alias": "fields"; "required": true; "isSignal": true; }; "initialValues": { "alias": "initialValues"; "required": false; "isSignal": true; }; "fieldErrors": { "alias": "fieldErrors"; "required": false; "isSignal": true; }; }, { "fieldChange": "fieldChange"; "formSubmit": "formSubmit"; "formValueChange": "formValueChange"; }, never, never, true, never>;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
/** Table column definition — extends `FieldDefinition` with optional column grouping. */
|
|
535
|
+
interface TableFieldDefinition extends FieldDefinition {
|
|
536
|
+
/** Groups this column visually with adjacent columns that share the same `name`. */
|
|
537
|
+
group?: {
|
|
538
|
+
/** Logical group identifier. */
|
|
539
|
+
name: string;
|
|
540
|
+
/** Group header label shown above the grouped cells. */
|
|
541
|
+
label?: string;
|
|
542
|
+
/** Separator placed between values in the same group cell. */
|
|
543
|
+
delimiter?: string;
|
|
544
|
+
/** When `true`, each value is rendered on its own line. */
|
|
545
|
+
multiline?: boolean;
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
type GroupBase = NonNullable<TableFieldDefinition['group']>;
|
|
550
|
+
type ProcessedGroup = GroupBase & {
|
|
551
|
+
fields?: TableFieldDefinition[];
|
|
552
|
+
};
|
|
553
|
+
type ProcessedTableFieldDefinition = Omit<TableFieldDefinition, 'group'> & {
|
|
554
|
+
group?: ProcessedGroup;
|
|
555
|
+
};
|
|
556
|
+
|
|
557
|
+
declare class DeclarativeTable<T extends GenericResource> {
|
|
558
|
+
columns: _angular_core.InputSignal<TableFieldDefinition[]>;
|
|
559
|
+
resources: _angular_core.InputSignal<T[]>;
|
|
560
|
+
trackByPath: _angular_core.InputSignal<string>;
|
|
561
|
+
permissions: _angular_core.InputSignal<Record<string, string[]> | undefined>;
|
|
562
|
+
totalItemsCount: _angular_core.InputSignal<number | undefined>;
|
|
563
|
+
paginationLimit: _angular_core.InputSignal<number>;
|
|
564
|
+
hasMore: _angular_core.InputSignal<boolean>;
|
|
565
|
+
loadMode: _angular_core.InputSignal<"button" | "scroll" | "pager">;
|
|
566
|
+
loadMoreButtonText: _angular_core.InputSignal<string>;
|
|
567
|
+
height: _angular_core.InputSignal<number | undefined>;
|
|
568
|
+
currentPage: _angular_core.InputSignal<number>;
|
|
569
|
+
readonly buttonClick: _angular_core.OutputEmitterRef<ResourceFieldButtonClickEvent<T>>;
|
|
570
|
+
readonly tableRowClicked: _angular_core.OutputEmitterRef<T>;
|
|
571
|
+
readonly loadMoreResources: _angular_core.OutputEmitterRef<void>;
|
|
572
|
+
readonly paginationLimitChanged: _angular_core.OutputEmitterRef<number>;
|
|
573
|
+
readonly pageChange: _angular_core.OutputEmitterRef<number>;
|
|
574
|
+
columnTrackBy: (column: TableFieldDefinition, index: number) => string | number | string[];
|
|
575
|
+
rowTrackBy: (_index: number, item: T) => unknown;
|
|
576
|
+
viewColumns: _angular_core.Signal<ProcessedTableFieldDefinition[]>;
|
|
577
|
+
onRowClick(item: T): void;
|
|
578
|
+
isPagerMode: _angular_core.Signal<boolean>;
|
|
579
|
+
knowsTotal: _angular_core.Signal<boolean>;
|
|
580
|
+
hasResults: _angular_core.Signal<boolean>;
|
|
581
|
+
totalPages: _angular_core.Signal<number>;
|
|
582
|
+
canPrev: _angular_core.Signal<boolean>;
|
|
583
|
+
canNext: _angular_core.Signal<boolean>;
|
|
584
|
+
goToPage(page: number): void;
|
|
585
|
+
firstPage: () => void;
|
|
586
|
+
prevPage: () => void;
|
|
587
|
+
nextPage: () => void;
|
|
588
|
+
lastPage: () => void;
|
|
589
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DeclarativeTable<any>, never>;
|
|
590
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DeclarativeTable<any>, "mfp-declarative-table", never, { "columns": { "alias": "columns"; "required": true; "isSignal": true; }; "resources": { "alias": "resources"; "required": true; "isSignal": true; }; "trackByPath": { "alias": "trackByPath"; "required": false; "isSignal": true; }; "permissions": { "alias": "permissions"; "required": false; "isSignal": true; }; "totalItemsCount": { "alias": "totalItemsCount"; "required": false; "isSignal": true; }; "paginationLimit": { "alias": "paginationLimit"; "required": false; "isSignal": true; }; "hasMore": { "alias": "hasMore"; "required": false; "isSignal": true; }; "loadMode": { "alias": "loadMode"; "required": false; "isSignal": true; }; "loadMoreButtonText": { "alias": "loadMoreButtonText"; "required": false; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; "currentPage": { "alias": "currentPage"; "required": false; "isSignal": true; }; }, { "buttonClick": "buttonClick"; "tableRowClicked": "tableRowClicked"; "loadMoreResources": "loadMoreResources"; "paginationLimitChanged": "paginationLimitChanged"; "pageChange": "pageChange"; }, never, never, true, never>;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
/** Configuration for the create/edit resource form rendered inside the table card dialogs. */
|
|
594
|
+
interface ResourceFormConfig {
|
|
595
|
+
/**
|
|
596
|
+
* Ordered list of fields to render in the form. May be a plain array, or a
|
|
597
|
+
* thunk returning a promise of the fields — the thunk form is resolved lazily
|
|
598
|
+
* when the dialog opens (e.g. to fetch dynamic select options on demand
|
|
599
|
+
* rather than prefetching them on render).
|
|
600
|
+
*/
|
|
601
|
+
fields: FormFieldDefinition[] | (() => Promise<FormFieldDefinition[]>);
|
|
602
|
+
/** Dialog title shown in the header. May contain HTML, which is sanitized before rendering. */
|
|
603
|
+
title?: string;
|
|
604
|
+
/** Label for the confirm/submit button. */
|
|
605
|
+
confirmLabel?: string;
|
|
606
|
+
/** Label for the cancel button. */
|
|
607
|
+
cancelLabel?: string;
|
|
608
|
+
}
|
|
609
|
+
/** Runtime validation and submit state passed to the table card from the host. */
|
|
610
|
+
interface TableCardFormState {
|
|
611
|
+
/** Map of field names to their current error messages. Any truthy error in the map disables the submit button. */
|
|
612
|
+
fieldErrors?: FormFieldErrors;
|
|
613
|
+
}
|
|
614
|
+
/** Configuration for the delete-confirmation dialog. */
|
|
615
|
+
interface DeleteResourceConfirmationConfig {
|
|
616
|
+
/** Dialog title. May contain HTML, which is sanitized before rendering. */
|
|
617
|
+
title?: string;
|
|
618
|
+
/** Explanatory message shown below the title. May contain HTML, which is sanitized before rendering. */
|
|
619
|
+
message?: string;
|
|
620
|
+
/**
|
|
621
|
+
* When set, the dialog renders a text input and keeps the confirm button
|
|
622
|
+
* disabled until the typed value matches this text (case-insensitive,
|
|
623
|
+
* trimmed). Use it to require the user to type e.g. the resource name before
|
|
624
|
+
* deleting. Omit to allow immediate confirmation.
|
|
625
|
+
*/
|
|
626
|
+
confirmationText?: string;
|
|
627
|
+
/** Placeholder for the confirmation input. Defaults to `Type to confirm`. Only used when {@link confirmationText} is set. */
|
|
628
|
+
confirmationPlaceholder?: string;
|
|
629
|
+
/** Label for the confirm/delete button. */
|
|
630
|
+
confirmLabel?: string;
|
|
631
|
+
/** Label for the cancel button. */
|
|
632
|
+
cancelLabel?: string;
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* One entry in the {@link TableCardSearchConfig.filterTabs} strip rendered
|
|
636
|
+
* above the table. Clicking a tab activates that filter; the host receives the
|
|
637
|
+
* selected definition via the `filterTabChanged` output and is responsible for
|
|
638
|
+
* applying the filter to its data set.
|
|
639
|
+
*
|
|
640
|
+
* The strip renders exactly the array of `FieldFilterDefinition` it receives
|
|
641
|
+
* — no extra "All" / no-filter tab is auto-added. If the host wants such an
|
|
642
|
+
* option it must author it as a regular filter entry.
|
|
643
|
+
*/
|
|
644
|
+
interface FieldFilterDefinition {
|
|
645
|
+
/** Visible label rendered as the tab text. */
|
|
646
|
+
label: string;
|
|
647
|
+
/** Name of the property the value applies to. Passed through to the host. */
|
|
648
|
+
property: string;
|
|
649
|
+
/** Value compared against `property` when the host applies the filter. */
|
|
650
|
+
value: string;
|
|
651
|
+
/** When `true`, this tab is selected on initial render; otherwise the first tab is. */
|
|
652
|
+
default?: boolean;
|
|
653
|
+
}
|
|
654
|
+
/** Configuration for the inner `mfp-declarative-table`. */
|
|
655
|
+
interface TableConfig {
|
|
656
|
+
/** Column definitions. */
|
|
657
|
+
fields: TableFieldDefinition[];
|
|
658
|
+
/** Total number of items on the server (used by pagination). */
|
|
659
|
+
totalItemsCount?: number;
|
|
660
|
+
/** Page size in `pager` mode; batch size for the grow modes otherwise. */
|
|
661
|
+
paginationLimit?: number;
|
|
662
|
+
/** 1-based current page. Only used when `loadMode` is `'pager'`. */
|
|
663
|
+
currentPage?: number;
|
|
664
|
+
/** When `true`, the "Load More" control is shown. Grow modes only. */
|
|
665
|
+
hasMore?: boolean;
|
|
666
|
+
height?: number;
|
|
667
|
+
/**
|
|
668
|
+
* How additional rows are presented:
|
|
669
|
+
* - `'scroll'` / `'button'` — grow the list in place via `ui5-table-growing`.
|
|
670
|
+
* - `'pager'` — classic arrow pager (first/prev/next/last) emitting `pageChange`.
|
|
671
|
+
*/
|
|
672
|
+
loadMode?: 'scroll' | 'button' | 'pager';
|
|
673
|
+
/** Text on the grow "Load More" button. Grow modes only. */
|
|
674
|
+
loadMoreButtonText?: string;
|
|
675
|
+
}
|
|
676
|
+
/** Overrides for the table card's built-in action buttons. */
|
|
677
|
+
interface TableCardButtonSettings {
|
|
678
|
+
/** Partial override for the "Create" button. */
|
|
679
|
+
createButton?: Partial<ButtonSettings>;
|
|
680
|
+
/** Partial override for the search toggle button. */
|
|
681
|
+
searchButton?: Partial<ButtonSettings>;
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
684
|
+
* Groups all search/filter concerns for `<mfp-declarative-table-card>`. Passing
|
|
685
|
+
* this object opts the card into showing the search input and (if `filterTabs`
|
|
686
|
+
* is set) the filter-tab strip. Omit the whole object to hide both.
|
|
687
|
+
*
|
|
688
|
+
* `initialSearch` and `initialFilter` are **one-shot seeds** — read once when
|
|
689
|
+
* the card mounts (or when they first appear) and never re-applied afterwards.
|
|
690
|
+
* User-driven updates continue to flow through the `searchChanged` and
|
|
691
|
+
* `filterTabChanged` outputs; the host is expected to keep its own state.
|
|
692
|
+
*/
|
|
693
|
+
interface TableCardSearchConfig {
|
|
694
|
+
/**
|
|
695
|
+
* One-shot seed for the search input. Applied to the internal `searchControl`
|
|
696
|
+
* on first render (or the first time `searchConfig` appears), without
|
|
697
|
+
* emitting `searchChanged`. Later changes to this value have no effect.
|
|
698
|
+
*/
|
|
699
|
+
initialSearch?: string;
|
|
700
|
+
/**
|
|
701
|
+
* Placeholder text shown in the always-visible search input to prompt
|
|
702
|
+
* searching. Defaults to `Search` when omitted.
|
|
703
|
+
*/
|
|
704
|
+
placeholder?: string;
|
|
705
|
+
/**
|
|
706
|
+
* Predefined filters rendered as a horizontal tab strip above the table.
|
|
374
707
|
* Omit (or pass an empty array) to hide the strip while keeping the search
|
|
375
708
|
* input visible.
|
|
376
709
|
*/
|
|
@@ -384,7 +717,7 @@ interface TableCardSearchConfig {
|
|
|
384
717
|
initialFilter?: FieldFilterDefinition;
|
|
385
718
|
}
|
|
386
719
|
/** Top-level configuration for `<mfp-declarative-table-card>`. */
|
|
387
|
-
interface TableCardConfig {
|
|
720
|
+
interface TableCardConfig<T extends GenericResource = GenericResource> {
|
|
388
721
|
/** Card heading. */
|
|
389
722
|
header?: string;
|
|
390
723
|
/** Tooltip shown on hover of the card heading. */
|
|
@@ -402,39 +735,61 @@ interface TableCardConfig {
|
|
|
402
735
|
/** When set, enables the "Create" button and create dialog. */
|
|
403
736
|
createResourceFormConfig?: ResourceFormConfig;
|
|
404
737
|
/** When set, enables per-row "Edit" button and edit dialog. */
|
|
405
|
-
editResourceFormConfig?: ResourceFormConfig;
|
|
738
|
+
editResourceFormConfig?: (resource: T) => ResourceFormConfig;
|
|
406
739
|
/** When set, enables per-row "Delete" button and confirmation dialog. */
|
|
407
|
-
deleteResourceConfirmationConfig?: DeleteResourceConfirmationConfig;
|
|
740
|
+
deleteResourceConfirmationConfig?: (resource: T) => DeleteResourceConfirmationConfig;
|
|
408
741
|
}
|
|
409
742
|
|
|
410
|
-
declare class
|
|
411
|
-
|
|
412
|
-
config: _angular_core.InputSignal<
|
|
743
|
+
declare class DeleteConfirmationDialog {
|
|
744
|
+
readonly open: _angular_core.InputSignal<boolean>;
|
|
745
|
+
readonly config: _angular_core.InputSignal<DeleteResourceConfirmationConfig | undefined>;
|
|
746
|
+
readonly confirmed: _angular_core.OutputEmitterRef<void>;
|
|
747
|
+
readonly cancelled: _angular_core.OutputEmitterRef<void>;
|
|
748
|
+
/** Input used to confirm deletion by typing `confirmationText`. */
|
|
749
|
+
protected readonly confirmationControl: FormControl<string>;
|
|
750
|
+
/** True when the config requires typing a confirmation phrase before deleting. */
|
|
751
|
+
protected readonly requiresConfirmation: _angular_core.Signal<boolean>;
|
|
752
|
+
/** Recomputes whenever the control's validity changes. */
|
|
753
|
+
private readonly status;
|
|
754
|
+
/** Disables the confirm button while the confirmation input is invalid. */
|
|
755
|
+
protected readonly confirmDisabled: _angular_core.Signal<boolean>;
|
|
756
|
+
constructor();
|
|
757
|
+
protected onConfirm(): void;
|
|
758
|
+
/** Passes only when the trimmed, case-insensitive control value equals `expected`. */
|
|
759
|
+
private matchValidator;
|
|
760
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DeleteConfirmationDialog, never>;
|
|
761
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DeleteConfirmationDialog, "mfp-delete-confirmation-dialog", never, { "open": { "alias": "open"; "required": false; "isSignal": true; }; "config": { "alias": "config"; "required": false; "isSignal": true; }; }, { "confirmed": "confirmed"; "cancelled": "cancelled"; }, never, never, true, never>;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
declare class DeclarativeTableCard<R extends GenericResource> {
|
|
765
|
+
resources: _angular_core.InputSignal<R[]>;
|
|
766
|
+
permissions: _angular_core.InputSignal<Record<string, string[]> | undefined>;
|
|
767
|
+
config: _angular_core.InputSignal<TableCardConfig<R>>;
|
|
413
768
|
createFormState: _angular_core.InputSignal<TableCardFormState>;
|
|
414
769
|
editFormState: _angular_core.InputSignal<TableCardFormState>;
|
|
415
|
-
readonly actionButtonClick: _angular_core.OutputEmitterRef<ResourceFieldButtonClickEvent<
|
|
416
|
-
readonly tableRowClicked: _angular_core.OutputEmitterRef<
|
|
770
|
+
readonly actionButtonClick: _angular_core.OutputEmitterRef<ResourceFieldButtonClickEvent<R>>;
|
|
771
|
+
readonly tableRowClicked: _angular_core.OutputEmitterRef<R>;
|
|
417
772
|
readonly loadMoreResources: _angular_core.OutputEmitterRef<void>;
|
|
418
773
|
readonly paginationLimitChanged: _angular_core.OutputEmitterRef<number>;
|
|
419
774
|
readonly pageChange: _angular_core.OutputEmitterRef<number>;
|
|
420
775
|
readonly searchChanged: _angular_core.OutputEmitterRef<string>;
|
|
421
776
|
readonly createFieldChange: _angular_core.OutputEmitterRef<FormFieldChangeEvent>;
|
|
422
777
|
readonly editFieldChange: _angular_core.OutputEmitterRef<{
|
|
423
|
-
resource:
|
|
778
|
+
resource: R;
|
|
424
779
|
formChangeEvent: FormFieldChangeEvent;
|
|
425
780
|
}>;
|
|
426
|
-
readonly createSubmit: _angular_core.OutputEmitterRef<
|
|
781
|
+
readonly createSubmit: _angular_core.OutputEmitterRef<R>;
|
|
427
782
|
readonly editSubmit: _angular_core.OutputEmitterRef<{
|
|
428
|
-
resource:
|
|
783
|
+
resource: R;
|
|
429
784
|
value: Record<string, unknown>;
|
|
430
785
|
}>;
|
|
431
|
-
readonly deleteSubmit: _angular_core.OutputEmitterRef<
|
|
786
|
+
readonly deleteSubmit: _angular_core.OutputEmitterRef<R>;
|
|
432
787
|
readonly filterTabChanged: _angular_core.OutputEmitterRef<FieldFilterDefinition | undefined>;
|
|
433
788
|
protected searchControl: FormControl<string | null>;
|
|
434
789
|
protected createDialogOpen: _angular_core.WritableSignal<boolean>;
|
|
435
790
|
protected editDialogOpen: _angular_core.WritableSignal<boolean>;
|
|
436
791
|
protected deleteDialogOpen: _angular_core.WritableSignal<boolean>;
|
|
437
|
-
protected pendingResource: _angular_core.WritableSignal<
|
|
792
|
+
protected pendingResource: _angular_core.WritableSignal<R | null>;
|
|
438
793
|
protected resolvedCreateFields: _angular_core.WritableSignal<FormFieldDefinition[]>;
|
|
439
794
|
protected resolvedEditFields: _angular_core.WritableSignal<FormFieldDefinition[]>;
|
|
440
795
|
protected tableConfig: _angular_core.Signal<_openmfp_ngx.TableConfig>;
|
|
@@ -445,7 +800,7 @@ declare class DeclarativeTableCard<T extends GenericResource> {
|
|
|
445
800
|
protected deleteConfirmationConfig: _angular_core.Signal<_openmfp_ngx.DeleteResourceConfirmationConfig | undefined>;
|
|
446
801
|
protected createButtonConfig: _angular_core.Signal<Partial<_openmfp_ngx.ButtonSettings> | undefined>;
|
|
447
802
|
protected searchButtonConfig: _angular_core.Signal<Partial<_openmfp_ngx.ButtonSettings> | undefined>;
|
|
448
|
-
protected effectiveColumns: _angular_core.Signal<TableFieldDefinition[]>;
|
|
803
|
+
protected effectiveColumns: _angular_core.Signal<_openmfp_ngx.TableFieldDefinition[]>;
|
|
449
804
|
protected editInitialValue: _angular_core.Signal<Record<string, unknown>>;
|
|
450
805
|
protected searchConfig: _angular_core.Signal<_openmfp_ngx.TableCardSearchConfig | undefined>;
|
|
451
806
|
protected resourcesSearchable: _angular_core.Signal<boolean>;
|
|
@@ -455,7 +810,7 @@ declare class DeclarativeTableCard<T extends GenericResource> {
|
|
|
455
810
|
constructor();
|
|
456
811
|
protected onFilterTabChanged(tab: FieldFilterDefinition | undefined): void;
|
|
457
812
|
submitSearch(): void;
|
|
458
|
-
onButtonClick(event: ResourceFieldButtonClickEvent<
|
|
813
|
+
onButtonClick(event: ResourceFieldButtonClickEvent<R>): void;
|
|
459
814
|
openCreateDialog(): Promise<void>;
|
|
460
815
|
private openEditDialog;
|
|
461
816
|
private resolveFormFields;
|
|
@@ -464,329 +819,43 @@ declare class DeclarativeTableCard<T extends GenericResource> {
|
|
|
464
819
|
closeDeleteDialog(): void;
|
|
465
820
|
onCreateFieldChange(event: FormFieldChangeEvent): void;
|
|
466
821
|
onEditFieldChange(event: FormFieldChangeEvent): void;
|
|
467
|
-
onCreateSubmit(value:
|
|
822
|
+
onCreateSubmit(value: Record<string, unknown>): void;
|
|
468
823
|
onEditSubmit(value: Record<string, unknown>): void;
|
|
469
824
|
onDeleteSubmit(): void;
|
|
470
|
-
protected hasErrors(state: TableCardFormState): boolean;
|
|
471
|
-
private addActionsColumn;
|
|
472
825
|
private buildInitialValues;
|
|
473
826
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DeclarativeTableCard<any>, never>;
|
|
474
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DeclarativeTableCard<any>, "mfp-declarative-table-card", never, { "resources": { "alias": "resources"; "required": true; "isSignal": true; }; "config": { "alias": "config"; "required": true; "isSignal": true; }; "createFormState": { "alias": "createFormState"; "required": false; "isSignal": true; }; "editFormState": { "alias": "editFormState"; "required": false; "isSignal": true; }; }, { "actionButtonClick": "actionButtonClick"; "tableRowClicked": "tableRowClicked"; "loadMoreResources": "loadMoreResources"; "paginationLimitChanged": "paginationLimitChanged"; "pageChange": "pageChange"; "searchChanged": "searchChanged"; "createFieldChange": "createFieldChange"; "editFieldChange": "editFieldChange"; "createSubmit": "createSubmit"; "editSubmit": "editSubmit"; "deleteSubmit": "deleteSubmit"; "filterTabChanged": "filterTabChanged"; }, never, never, true, never>;
|
|
827
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DeclarativeTableCard<any>, "mfp-declarative-table-card", never, { "resources": { "alias": "resources"; "required": true; "isSignal": true; }; "permissions": { "alias": "permissions"; "required": false; "isSignal": true; }; "config": { "alias": "config"; "required": true; "isSignal": true; }; "createFormState": { "alias": "createFormState"; "required": false; "isSignal": true; }; "editFormState": { "alias": "editFormState"; "required": false; "isSignal": true; }; }, { "actionButtonClick": "actionButtonClick"; "tableRowClicked": "tableRowClicked"; "loadMoreResources": "loadMoreResources"; "paginationLimitChanged": "paginationLimitChanged"; "pageChange": "pageChange"; "searchChanged": "searchChanged"; "createFieldChange": "createFieldChange"; "editFieldChange": "editFieldChange"; "createSubmit": "createSubmit"; "editSubmit": "editSubmit"; "deleteSubmit": "deleteSubmit"; "filterTabChanged": "filterTabChanged"; }, never, never, true, never>;
|
|
475
828
|
}
|
|
476
829
|
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
readonly
|
|
480
|
-
readonly
|
|
481
|
-
readonly
|
|
482
|
-
readonly
|
|
483
|
-
readonly
|
|
484
|
-
readonly
|
|
485
|
-
readonly
|
|
486
|
-
readonly
|
|
487
|
-
readonly
|
|
488
|
-
readonly
|
|
489
|
-
readonly
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
};
|
|
494
|
-
type DashboardI18nKey = (typeof DASHBOARD_I18N_KEYS)[keyof typeof DASHBOARD_I18N_KEYS];
|
|
495
|
-
|
|
496
|
-
/**
|
|
497
|
-
* Holds the dashboard's current language and resolves translation keys for
|
|
498
|
-
* the dashboard chrome (toolbar buttons, dialogs, a11y labels). Provided at
|
|
499
|
-
* the `Dashboard` component level so every nested dashboard component shares
|
|
500
|
-
* the same language signal — child components inject the same instance and
|
|
501
|
-
* react to language changes automatically because `getTranslation` reads the
|
|
502
|
-
* signal on every call.
|
|
503
|
-
*/
|
|
504
|
-
declare class DashboardI18nService {
|
|
505
|
-
readonly language: _angular_core.WritableSignal<DashboardLanguage>;
|
|
506
|
-
getTranslation(key: DashboardI18nKey): string;
|
|
507
|
-
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DashboardI18nService, never>;
|
|
508
|
-
static ɵprov: _angular_core.ɵɵInjectableDeclaration<DashboardI18nService>;
|
|
830
|
+
declare class ResourceFormDialog {
|
|
831
|
+
readonly open: _angular_core.InputSignal<boolean>;
|
|
832
|
+
readonly config: _angular_core.InputSignal<ResourceFormConfig | undefined>;
|
|
833
|
+
readonly fields: _angular_core.InputSignal<FormFieldDefinition[]>;
|
|
834
|
+
readonly fieldErrors: _angular_core.InputSignal<FormFieldErrors>;
|
|
835
|
+
readonly initialValues: _angular_core.InputSignal<Record<string, unknown>>;
|
|
836
|
+
readonly defaultTitle: _angular_core.InputSignal<string>;
|
|
837
|
+
readonly defaultConfirmLabel: _angular_core.InputSignal<string>;
|
|
838
|
+
readonly defaultCancelLabel: _angular_core.InputSignal<string>;
|
|
839
|
+
readonly dataTestidPrefix: _angular_core.InputSignal<string>;
|
|
840
|
+
readonly fieldChange: _angular_core.OutputEmitterRef<FormFieldChangeEvent>;
|
|
841
|
+
readonly submitted: _angular_core.OutputEmitterRef<Record<string, unknown>>;
|
|
842
|
+
readonly cancelled: _angular_core.OutputEmitterRef<void>;
|
|
843
|
+
protected hasErrors: _angular_core.Signal<boolean>;
|
|
844
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ResourceFormDialog, never>;
|
|
845
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ResourceFormDialog, "mfp-resource-form-dialog", never, { "open": { "alias": "open"; "required": false; "isSignal": true; }; "config": { "alias": "config"; "required": false; "isSignal": true; }; "fields": { "alias": "fields"; "required": false; "isSignal": true; }; "fieldErrors": { "alias": "fieldErrors"; "required": false; "isSignal": true; }; "initialValues": { "alias": "initialValues"; "required": false; "isSignal": true; }; "defaultTitle": { "alias": "defaultTitle"; "required": false; "isSignal": true; }; "defaultConfirmLabel": { "alias": "defaultConfirmLabel"; "required": false; "isSignal": true; }; "defaultCancelLabel": { "alias": "defaultCancelLabel"; "required": false; "isSignal": true; }; "dataTestidPrefix": { "alias": "dataTestidPrefix"; "required": false; "isSignal": true; }; }, { "fieldChange": "fieldChange"; "submitted": "submitted"; "cancelled": "cancelled"; }, never, never, true, never>;
|
|
509
846
|
}
|
|
510
847
|
|
|
511
|
-
declare
|
|
512
|
-
readonly WC: "wc";
|
|
513
|
-
readonly ANGULAR: "angular";
|
|
514
|
-
readonly SAP_UI: "sap-ui";
|
|
515
|
-
};
|
|
516
|
-
type CardsType = (typeof CARD_TYPES)[keyof typeof CARD_TYPES];
|
|
517
|
-
/** Configuration for a single card placed in the dashboard grid or a section. */
|
|
518
|
-
interface CardConfig {
|
|
519
|
-
/** Unique identifier for this card. Used as a stable key for position persistence. */
|
|
520
|
-
id: string;
|
|
521
|
-
/** Column span (1–12). Defaults to 12 when omitted. */
|
|
522
|
-
w?: number;
|
|
523
|
-
/** Row span — number of CSS grid rows occupied (1 row = 10 px by default). Defaults to 100 when omitted. */
|
|
524
|
-
h?: number;
|
|
525
|
-
/** Starting column index (0-based). Omit to let the grid auto-place the card. */
|
|
526
|
-
x?: number;
|
|
527
|
-
/** Starting row index (0-based). Omit to let the grid auto-place the card. */
|
|
528
|
-
y?: number;
|
|
529
|
-
/** Maximum row span in edit mode. */
|
|
530
|
-
maxH?: number;
|
|
531
|
-
/** Maximum column span in edit mode. */
|
|
532
|
-
maxW?: number;
|
|
533
|
-
/** Minimum row span in edit mode. */
|
|
534
|
-
minH?: number;
|
|
535
|
-
/** Minimum column span in edit mode. */
|
|
536
|
-
minW?: number;
|
|
537
|
-
/** ID of the parent section. Omit to place the card in the loose-card grid. */
|
|
538
|
-
sectionId?: string;
|
|
539
|
-
/**
|
|
540
|
-
* Custom-element tag name (for `'wc'`/omitted), Angular component selector (for `'angular'`),
|
|
541
|
-
* or SAP UI5 component name (for `'sap-ui'`).
|
|
542
|
-
*/
|
|
543
|
-
component: string;
|
|
544
|
-
/**
|
|
545
|
-
* Render strategy for the card.
|
|
546
|
-
* - `'wc'` (default) — creates a custom element and sets `componentInputs` as DOM properties.
|
|
547
|
-
* - `'angular'` — looks up the Angular registry; warns and renders nothing if not found.
|
|
548
|
-
* - `'sap-ui'` — mounts via `window.sap.ui.require` + `ComponentContainer`.
|
|
549
|
-
*/
|
|
550
|
-
type?: CardsType;
|
|
551
|
-
/** Key/value pairs passed to the rendered card. Behaviour depends on `type`. */
|
|
552
|
-
componentInputs?: Record<string, unknown>;
|
|
553
|
-
/** Human-readable label shown in the "Add Card" dialog. */
|
|
554
|
-
label?: string;
|
|
555
|
-
}
|
|
556
|
-
type MountCfg = Pick<CardConfig, 'type' | 'component' | 'componentInputs'>;
|
|
557
|
-
/** Configuration for a named horizontal section that groups cards. */
|
|
558
|
-
interface SectionConfig {
|
|
559
|
-
/** Unique identifier for this section. */
|
|
560
|
-
id: string;
|
|
561
|
-
/** Column span (1–12). Defaults to 12 when omitted. */
|
|
562
|
-
w?: number;
|
|
563
|
-
/** Section heading displayed in the UI. */
|
|
564
|
-
title?: string;
|
|
565
|
-
/** When `false`, the section and its cards are excluded from edit mode. Defaults to `true` when omitted. */
|
|
566
|
-
editable?: boolean;
|
|
567
|
-
}
|
|
568
|
-
/** Overrides for the two built-in dashboard toolbar buttons. */
|
|
569
|
-
interface DashboardButtonsSettings {
|
|
570
|
-
/** Partial override merged on top of the Edit View button defaults. */
|
|
571
|
-
editViewButton?: Partial<ButtonSettings>;
|
|
572
|
-
/** Partial override merged on top of the Edit Cards button defaults. */
|
|
573
|
-
editCardsButton?: Partial<ButtonSettings>;
|
|
574
|
-
}
|
|
575
|
-
/** Top-level configuration for the `<mfp-dashboard>` component. */
|
|
576
|
-
interface DashboardConfig {
|
|
577
|
-
/** Dashboard title rendered in the toolbar. */
|
|
578
|
-
title: string;
|
|
579
|
-
/** Optional subtitle shown below the title. */
|
|
580
|
-
description?: string;
|
|
581
|
-
/** URL of the background image applied to the dashboard host element. */
|
|
582
|
-
backgroundImageUrl?: string;
|
|
583
|
-
/** Overrides for the built-in Edit View and Add Card toolbar buttons. */
|
|
584
|
-
buttonsSettings?: DashboardButtonsSettings;
|
|
585
|
-
/** Extra action buttons rendered in the toolbar alongside the built-in ones. */
|
|
586
|
-
customActions?: ButtonSettings[];
|
|
587
|
-
/** When `true`, shows the Edit View button in the toolbar, allowing the user to enter edit mode. */
|
|
588
|
-
editable?: boolean;
|
|
589
|
-
/** When `true`, the Edit View button is rendered before the custom actions instead of after. Defaults to `false`. */
|
|
590
|
-
editButtonFirst?: boolean;
|
|
591
|
-
/** When provided, enable z-flow layout. */
|
|
592
|
-
zFlow?: {
|
|
593
|
-
/** Sets the height of each card in the z-flow layout. */
|
|
594
|
-
cardHeight: number;
|
|
595
|
-
};
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
/**
|
|
599
|
-
* Layout strategy applied at each breakpoint when Gridstack changes column
|
|
600
|
-
* count. See ColumnOptions in gridstack/dist/types.d.ts:27 for the full set.
|
|
601
|
-
*/
|
|
602
|
-
type LayoutStrategy = 'compact' | 'list' | 'none';
|
|
603
|
-
type DashboardBreakpoint = Readonly<Required<Pick<Breakpoint, 'w' | 'c'>> & {
|
|
604
|
-
layout: LayoutStrategy;
|
|
605
|
-
}>;
|
|
606
|
-
|
|
607
|
-
interface EngineProfile {
|
|
608
|
-
/** GridStack engine class, or undefined to use GridStack's native engine. */
|
|
609
|
-
engineClass: typeof GridStackEngine | undefined;
|
|
610
|
-
/** Column breakpoint table fed to GridStack columnOpts. */
|
|
611
|
-
breakpoints: readonly DashboardBreakpoint[];
|
|
612
|
-
/** Column counts for [sm, md, lg, xl] page size. Pushed to CSS vars so the section grids match. */
|
|
613
|
-
sectionColumns: readonly [number, number, number, number];
|
|
614
|
-
/** When true, all loose cards get a fixed h/maxH from the engine's config. */
|
|
615
|
-
fixedCardHeight: boolean;
|
|
616
|
-
/** When true, the XL-page width swap (3↔4) runs. */
|
|
617
|
-
xlWidthSwap: boolean;
|
|
618
|
-
/** When true, the origin position is rendered. */
|
|
619
|
-
renderOriginPosition: boolean;
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
declare class Dashboard implements OnInit, OnDestroy {
|
|
623
|
-
static registerAngularComponents(componentTypes: Type<unknown>[]): void;
|
|
624
|
-
private readonly hostEl;
|
|
625
|
-
private readonly injector;
|
|
848
|
+
declare class SanitizeHtmlPipe implements PipeTransform {
|
|
626
849
|
private readonly sanitizer;
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
cards: _angular_core.ModelSignal<CardConfig[]>;
|
|
631
|
-
availableCards: _angular_core.InputSignal<CardConfig[]>;
|
|
632
|
-
language: _angular_core.InputSignal<DashboardLanguage>;
|
|
633
|
-
readonly saved: _angular_core.OutputEmitterRef<{
|
|
634
|
-
sections: SectionConfig[];
|
|
635
|
-
cards: CardConfig[];
|
|
636
|
-
}>;
|
|
637
|
-
readonly actionButtonClick: _angular_core.OutputEmitterRef<{
|
|
638
|
-
event: MouseEvent;
|
|
639
|
-
action: ButtonSettings;
|
|
640
|
-
}>;
|
|
641
|
-
readonly unsavedChangesChange: _angular_core.OutputEmitterRef<boolean>;
|
|
642
|
-
protected readonly i18nKeys: {
|
|
643
|
-
readonly UNSAVED_CHANGES: "unsavedChanges";
|
|
644
|
-
readonly EDIT_CARDS: "editCards";
|
|
645
|
-
readonly EDIT_VIEW: "editView";
|
|
646
|
-
readonly ACTIONS: "actions";
|
|
647
|
-
readonly SAVE: "save";
|
|
648
|
-
readonly CANCEL: "cancel";
|
|
649
|
-
readonly DISCARD: "discard";
|
|
650
|
-
readonly DISCARD_CHANGES: "discardChanges";
|
|
651
|
-
readonly DISCARD_CONFIRM_BODY: "discardConfirmBody";
|
|
652
|
-
readonly UNSAVED_NAV_BODY: "unsavedNavBody";
|
|
653
|
-
readonly NO_CARDS_AVAILABLE: "noCardsAvailable";
|
|
654
|
-
readonly REMOVE_SECTION: "removeSection";
|
|
655
|
-
readonly REMOVE_CARD: "removeCard";
|
|
656
|
-
readonly RESIZABLE: "resizable";
|
|
657
|
-
};
|
|
658
|
-
/** True once the user has dragged/resized any grid item while in edit mode. */
|
|
659
|
-
private gridDirty;
|
|
660
|
-
private isXLPage;
|
|
661
|
-
editMode: _angular_core.WritableSignal<boolean>;
|
|
662
|
-
compactToolbar: _angular_core.WritableSignal<boolean>;
|
|
663
|
-
toolbarMenuOpen: _angular_core.WritableSignal<boolean>;
|
|
664
|
-
cardDialogOpen: _angular_core.WritableSignal<boolean>;
|
|
665
|
-
discardDialogOpen: _angular_core.WritableSignal<boolean>;
|
|
666
|
-
unsavedNavDialogOpen: _angular_core.WritableSignal<boolean>;
|
|
667
|
-
backgroundImageHeight: _angular_core.WritableSignal<number | null>;
|
|
668
|
-
dragOriginStyle: _angular_core.WritableSignal<{
|
|
669
|
-
top: string;
|
|
670
|
-
left: string;
|
|
671
|
-
width: string;
|
|
672
|
-
height: string;
|
|
673
|
-
} | null>;
|
|
674
|
-
protected hasUnsavedChanges: _angular_core.Signal<boolean>;
|
|
675
|
-
protected safeTitle: _angular_core.Signal<SafeHtml>;
|
|
676
|
-
protected safeDescription: _angular_core.Signal<SafeHtml | null>;
|
|
677
|
-
protected engineProfile: _angular_core.Signal<EngineProfile>;
|
|
678
|
-
protected gridStackEngine: _angular_core.Signal<typeof gridstack.GridStackEngine | undefined>;
|
|
679
|
-
protected gridBreakpoints: _angular_core.Signal<Readonly<Required<Pick<gridstack.Breakpoint, "w" | "c">> & {
|
|
680
|
-
layout: "compact" | "list" | "none";
|
|
681
|
-
}>[]>;
|
|
682
|
-
protected columnVars: _angular_core.Signal<{
|
|
683
|
-
'--dashboard-cols-sm': number;
|
|
684
|
-
'--dashboard-cols-md': number;
|
|
685
|
-
'--dashboard-cols-lg': number;
|
|
686
|
-
'--dashboard-cols-xl': number;
|
|
687
|
-
}>;
|
|
688
|
-
protected customActions: _angular_core.Signal<ButtonSettings[]>;
|
|
689
|
-
protected addedCardsIds: _angular_core.Signal<Set<string>>;
|
|
690
|
-
protected editViewButton: _angular_core.Signal<{
|
|
691
|
-
text: string;
|
|
692
|
-
icon: string;
|
|
693
|
-
endIcon?: string;
|
|
694
|
-
design: "Default" | "Positive" | "Negative" | "Transparent" | "Emphasized" | "Attention";
|
|
695
|
-
tooltip: string;
|
|
696
|
-
action?: (("openInModal" | "navigate" | "edit" | "delete") | (string & {})) | undefined;
|
|
697
|
-
modalSettings?: _openmfp_ngx.ModalSettings;
|
|
698
|
-
}>;
|
|
699
|
-
protected editCardsButton: _angular_core.Signal<{
|
|
700
|
-
text: string;
|
|
701
|
-
icon: string;
|
|
702
|
-
endIcon?: string;
|
|
703
|
-
design: "Default" | "Positive" | "Negative" | "Transparent" | "Emphasized" | "Attention";
|
|
704
|
-
tooltip: string;
|
|
705
|
-
action?: (("openInModal" | "navigate" | "edit" | "delete") | (string & {})) | undefined;
|
|
706
|
-
modalSettings?: _openmfp_ngx.ModalSettings;
|
|
707
|
-
}>;
|
|
708
|
-
protected sectionCards: _angular_core.Signal<(sectionId: string) => CardConfig[]>;
|
|
709
|
-
protected looseCards: _angular_core.WritableSignal<CardConfig[]>;
|
|
710
|
-
protected gridOptions: _angular_core.Signal<GridStackOptions>;
|
|
711
|
-
/** JSON snapshots of sections/cards taken on entering edit mode, used to detect changes. */
|
|
712
|
-
private sectionsSnapshotJson;
|
|
713
|
-
private cardsSnapshotJson;
|
|
714
|
-
private sectionsSnapshot;
|
|
715
|
-
private cardsSnapshot;
|
|
716
|
-
private gridStack;
|
|
717
|
-
private addCardBtn;
|
|
718
|
-
private resizeObserver?;
|
|
719
|
-
private cardsPosition;
|
|
720
|
-
/** Callback that resumes the intercepted navigation once the user resolves the dialog. */
|
|
721
|
-
private pendingNavigation;
|
|
722
|
-
/** beforeunload handler kept on instance so add/removeEventListener pair up. */
|
|
723
|
-
private readonly beforeUnloadHandler;
|
|
724
|
-
constructor();
|
|
725
|
-
ngOnInit(): void;
|
|
726
|
-
ngOnDestroy(): void;
|
|
727
|
-
onMenuItemClick(actionId: string, event: Event): void;
|
|
728
|
-
enterEditMode(): void;
|
|
729
|
-
saveEdit(): void;
|
|
730
|
-
cancelEdit(): void;
|
|
731
|
-
confirmDiscard(): void;
|
|
732
|
-
cancelDiscard(): void;
|
|
733
|
-
/**
|
|
734
|
-
* Public framework-agnostic navigation guard. Consumer apps (Angular Router
|
|
735
|
-
* CanDeactivate guard, Luigi navigation listener, plain `<a>` click handler,
|
|
736
|
-
* window history listener — anything) call this before performing their
|
|
737
|
-
* navigation:
|
|
738
|
-
*
|
|
739
|
-
* if (dashboard.requestNavigation(() => router.navigateByUrl(target))) {
|
|
740
|
-
* // already navigated synchronously — clean state
|
|
741
|
-
* } else {
|
|
742
|
-
* // dashboard popped the unsaved-changes dialog; the navigation will
|
|
743
|
-
* // resume from the user's choice (Save → proceed, Discard → proceed,
|
|
744
|
-
* // Cancel → drop the request entirely).
|
|
745
|
-
* }
|
|
746
|
-
*
|
|
747
|
-
* Returns `true` when navigation may proceed immediately (no unsaved
|
|
748
|
-
* changes — `proceed` was invoked synchronously). Returns `false` when the
|
|
749
|
-
* dialog has been opened and the caller must NOT navigate; the dashboard
|
|
750
|
-
* will run the callback later if the user picks Save or Discard.
|
|
751
|
-
*
|
|
752
|
-
* If a previous navigation is already pending, that one is dropped in
|
|
753
|
-
* favour of the new request — Cancel always means "stay here", so losing
|
|
754
|
-
* the older queued navigation is the correct outcome.
|
|
755
|
-
*/
|
|
756
|
-
requestNavigation(proceed: () => void): boolean;
|
|
757
|
-
/** Save → persist changes, close the dialog, then resume navigation. */
|
|
758
|
-
onUnsavedNavSave(): void;
|
|
759
|
-
/** Discard → revert to snapshot, close the dialog, then resume navigation. */
|
|
760
|
-
onUnsavedNavDiscard(): void;
|
|
761
|
-
/** Cancel → drop the queued navigation and stay in edit mode. */
|
|
762
|
-
onUnsavedNavCancel(): void;
|
|
763
|
-
private runPendingNavigation;
|
|
764
|
-
private discardEdit;
|
|
765
|
-
removeSection(id: string): void;
|
|
766
|
-
removeCard(id: string): void;
|
|
767
|
-
openCardPanel(): void;
|
|
768
|
-
closeCardPanel(): void;
|
|
769
|
-
onCardsEdited(event: {
|
|
770
|
-
added: CardConfig[];
|
|
771
|
-
removed: string[];
|
|
772
|
-
}): void;
|
|
773
|
-
onDragStart(event: {
|
|
774
|
-
el: Element;
|
|
775
|
-
}): void;
|
|
776
|
-
onDragStop(): void;
|
|
777
|
-
onGridChange(): void;
|
|
778
|
-
private saveCardsPosition;
|
|
779
|
-
private updateCardsPositions;
|
|
780
|
-
private getZFlowEngine;
|
|
781
|
-
private updateCardsForBreakpoint;
|
|
782
|
-
private changeCardSettingsForXlPage;
|
|
783
|
-
static ɵfac: _angular_core.ɵɵFactoryDeclaration<Dashboard, never>;
|
|
784
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<Dashboard, "mfp-dashboard", never, { "config": { "alias": "config"; "required": true; "isSignal": true; }; "sections": { "alias": "sections"; "required": false; "isSignal": true; }; "cards": { "alias": "cards"; "required": false; "isSignal": true; }; "availableCards": { "alias": "availableCards"; "required": false; "isSignal": true; }; "language": { "alias": "language"; "required": false; "isSignal": true; }; }, { "sections": "sectionsChange"; "cards": "cardsChange"; "saved": "saved"; "actionButtonClick": "actionButtonClick"; "unsavedChangesChange": "unsavedChangesChange"; }, never, ["[slot=dashboard-subheader]"], true, never>;
|
|
850
|
+
transform(value: string | null | undefined): string;
|
|
851
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SanitizeHtmlPipe, never>;
|
|
852
|
+
static ɵpipe: _angular_core.ɵɵPipeDeclaration<SanitizeHtmlPipe, "sanitizeHtml", true>;
|
|
785
853
|
}
|
|
786
854
|
|
|
787
855
|
declare class ResourceField<T extends GenericResource, F extends FieldDefinition> {
|
|
788
856
|
fieldDefinition: _angular_core.InputSignal<F>;
|
|
789
857
|
resource: _angular_core.InputSignal<T | undefined>;
|
|
858
|
+
permissions: _angular_core.InputSignal<Record<string, string[]> | undefined>;
|
|
790
859
|
readonly buttonClick: _angular_core.OutputEmitterRef<ResourceFieldButtonClickEvent<T>>;
|
|
791
860
|
value: _angular_core.Signal<any>;
|
|
792
861
|
uiSettings: _angular_core.Signal<_openmfp_ngx.UiSettings | undefined>;
|
|
@@ -1325,6 +1394,7 @@ declare class ResourceField<T extends GenericResource, F extends FieldDefinition
|
|
|
1325
1394
|
isVisible: _angular_core.WritableSignal<boolean>;
|
|
1326
1395
|
copySuccess: _angular_core.WritableSignal<boolean>;
|
|
1327
1396
|
isCollection: _angular_core.Signal<boolean>;
|
|
1397
|
+
protected canRenderField: _angular_core.Signal<boolean>;
|
|
1328
1398
|
toggleVisibility(e: Event): void;
|
|
1329
1399
|
private normalizeBoolean;
|
|
1330
1400
|
private normalizeString;
|
|
@@ -1333,7 +1403,7 @@ declare class ResourceField<T extends GenericResource, F extends FieldDefinition
|
|
|
1333
1403
|
copyValue(event: Event): void;
|
|
1334
1404
|
protected buttonClicked(event: MouseEvent): void;
|
|
1335
1405
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ResourceField<any, any>, never>;
|
|
1336
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ResourceField<any, any>, "mfp-resource-field", never, { "fieldDefinition": { "alias": "fieldDefinition"; "required": true; "isSignal": true; }; "resource": { "alias": "resource"; "required": false; "isSignal": true; }; }, { "buttonClick": "buttonClick"; }, never, never, true, never>;
|
|
1406
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ResourceField<any, any>, "mfp-resource-field", never, { "fieldDefinition": { "alias": "fieldDefinition"; "required": true; "isSignal": true; }; "resource": { "alias": "resource"; "required": false; "isSignal": true; }; "permissions": { "alias": "permissions"; "required": false; "isSignal": true; }; }, { "buttonClick": "buttonClick"; }, never, never, true, never>;
|
|
1337
1407
|
}
|
|
1338
1408
|
|
|
1339
1409
|
declare const ICON_DESIGN_POSITIVE = "Positive";
|
|
@@ -1433,5 +1503,5 @@ declare class MockCard {
|
|
|
1433
1503
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<MockCard, "mfp-mock-card", never, { "title": { "alias": "title"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
1434
1504
|
}
|
|
1435
1505
|
|
|
1436
|
-
export { BooleanValue, CARD_TYPES, Dashboard, DeclarativeForm, DeclarativeTable, DeclarativeTableCard, Favorites, LinkValue, MockCard, ResourceField, SecretValue, ServiceStatusCard, TagListValue, VisitedServiceCard, WhatsNew };
|
|
1506
|
+
export { BooleanValue, CARD_TYPES, Dashboard, DeclarativeForm, DeclarativeTable, DeclarativeTableCard, DeleteConfirmationDialog, Favorites, LinkValue, MockCard, ResourceField, ResourceFormDialog, SanitizeHtmlPipe, SecretValue, ServiceStatusCard, TagListValue, VisitedServiceCard, WhatsNew, defineDashboardElementMethods };
|
|
1437
1507
|
export type { ButtonSettings, CardConfig, CardsType, CssRule, DashboardButtonsSettings, DashboardConfig, DeleteResourceConfirmationConfig, FieldDefinition, FieldFilterDefinition, FormFieldChangeEvent, FormFieldDefinition, FormFieldErrors, GenericResource, IconDesignType, ModalSettings, MountCfg, PropertyField, ResourceFieldButtonClickEvent, ResourceFormConfig, RuleCondition, SectionConfig, ServiceStatusItem, ServiceStatusValue, TableCardButtonSettings, TableCardConfig, TableCardFormState, TableCardSearchConfig, TableConfig, TableFieldDefinition, TagSettings, TransformType, UiSettings, ValueRule };
|