@navette-js/panels 1.0.0-beta.1 → 1.0.0-beta.3
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/README.md +2 -2
- package/THIRD-PARTY-NOTICES.md +2 -2
- package/lib/auth.d.ts +16 -16
- package/lib/auth.js +19 -21
- package/lib/calendar.d.ts +18 -18
- package/lib/calendar.js +10 -10
- package/lib/index.d.ts +333 -328
- package/lib/index.js +509 -464
- package/lib/notifications.d.ts +9 -9
- package/lib/notifications.js +12 -12
- package/lib/topbar.d.ts +11 -11
- package/lib/topbar.js +15 -16
- package/package.json +10 -11
- package/theme.css +3 -3
- package/views/components/logo.ejs +1 -1
- package/views/components/tenant-menu.ejs +1 -1
- package/views/components/user-menu.ejs +2 -2
- package/views/layout/base.ejs +2 -2
- package/views/layout/index.ejs +1 -1
- package/views/layout/simple.ejs +1 -1
- package/views/livewire/sidebar.ejs +2 -2
- package/views/livewire/topbar.ejs +1 -1
- package/views/pages/page.ejs +3 -3
- package/views/pages/simple.ejs +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ import type { DataAdapter } from '@navette-js/database';
|
|
|
14
14
|
import { Table, type ColumnState, type FilterState, type TableHost } from '@navette-js/tables';
|
|
15
15
|
import { Component, type WireRuntime } from '@navette-js/wire';
|
|
16
16
|
export declare const ASSET_VERSION = "5.11.2.0";
|
|
17
|
-
/**
|
|
17
|
+
/** The signed-in user. Your auth provider may add any field (role, team…): policies receive it as-is. */
|
|
18
18
|
export type User = {
|
|
19
19
|
id: string | number;
|
|
20
20
|
name: string;
|
|
@@ -22,18 +22,18 @@ export type User = {
|
|
|
22
22
|
[key: string]: unknown;
|
|
23
23
|
};
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
26
|
-
* (`viewAny`, `create`, `update`, `delete`, `deleteAny`, `restore`, `forceDelete`, `reorder`,
|
|
27
|
-
*
|
|
25
|
+
* Resource policy: one function per ability
|
|
26
|
+
* (`viewAny`, `create`, `update`, `delete`, `deleteAny`, `restore`, `forceDelete`, `reorder`, or your own names).
|
|
27
|
+
* A missing ability is allowed.
|
|
28
28
|
*/
|
|
29
29
|
export type Policy<R = any> = Partial<Record<string, (user: User, record: R | null) => boolean | Promise<boolean>>>;
|
|
30
|
-
/**
|
|
30
|
+
/** A reusable bundle of configuration. `register` receives the panel being built; `boot` is called when the router is mounted. */
|
|
31
31
|
export type Plugin = {
|
|
32
32
|
id: string;
|
|
33
33
|
register(panel: Panel): void;
|
|
34
34
|
boot?(panel: Panel): void;
|
|
35
35
|
};
|
|
36
|
-
/** Question
|
|
36
|
+
/** Question asked to the panel's authorization hook. `resource`, `page` or `widget` tells what it is about. */
|
|
37
37
|
export type AuthorizationCheck = {
|
|
38
38
|
user: User;
|
|
39
39
|
ability: string;
|
|
@@ -42,26 +42,26 @@ export type AuthorizationCheck = {
|
|
|
42
42
|
page: typeof Page | null;
|
|
43
43
|
widget: typeof Widget | null;
|
|
44
44
|
};
|
|
45
|
-
/**
|
|
45
|
+
/** Return `true` or `false` to decide, or `undefined` to let the resource policy (or `canAccess` / `canView`) answer. */
|
|
46
46
|
export type Authorizer = (check: AuthorizationCheck) => boolean | undefined | Promise<boolean | undefined>;
|
|
47
47
|
type MaybePromise<T> = T | Promise<T>;
|
|
48
48
|
/**
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* `knexAuthProvider(knex)`
|
|
49
|
+
* User provider. `attempt` and `find` are enough for login; the optional methods enable
|
|
50
|
+
* registration (`create`, `findByEmail`), password reset (`findByEmail`, `update`, `getPasswordFingerprint`),
|
|
51
|
+
* email verification (`hasVerifiedEmail`, `markEmailAsVerified`) and the profile page (`update`).
|
|
52
|
+
* `knexAuthProvider(knex)` implements all of them for a `users` table.
|
|
53
53
|
*/
|
|
54
54
|
export interface AuthProvider {
|
|
55
55
|
attempt(email: string, password: string): MaybePromise<User | null>;
|
|
56
56
|
find(id: string | number): MaybePromise<User | null>;
|
|
57
57
|
findByEmail?(email: string): MaybePromise<User | null>;
|
|
58
|
-
/**
|
|
58
|
+
/** Creates the user. The password is plain text; the provider must hash it. */
|
|
59
59
|
create?(data: {
|
|
60
60
|
name: string;
|
|
61
61
|
email: string;
|
|
62
62
|
password: string;
|
|
63
63
|
}): MaybePromise<User>;
|
|
64
|
-
/**
|
|
64
|
+
/** Updates name, email or password (plain text, to hash). Changing the email must reset its verification. */
|
|
65
65
|
update?(user: User, data: {
|
|
66
66
|
name?: string;
|
|
67
67
|
email?: string;
|
|
@@ -69,25 +69,25 @@ export interface AuthProvider {
|
|
|
69
69
|
}): MaybePromise<User>;
|
|
70
70
|
hasVerifiedEmail?(user: User): MaybePromise<boolean>;
|
|
71
71
|
markEmailAsVerified?(user: User): MaybePromise<void>;
|
|
72
|
-
/**
|
|
72
|
+
/** A value that changes with the stored password, so a used reset link becomes invalid. */
|
|
73
73
|
getPasswordFingerprint?(user: User): MaybePromise<string>;
|
|
74
74
|
}
|
|
75
75
|
/**
|
|
76
|
-
*
|
|
77
|
-
*
|
|
76
|
+
* Panel tenants (teams, organizations…). Every panel page then lives under
|
|
77
|
+
* `/<panel>/<tenant key>/…`, and only a member of the tenant can open it.
|
|
78
78
|
*/
|
|
79
79
|
export interface TenantProvider<T = any> {
|
|
80
|
-
/**
|
|
80
|
+
/** Tenants the user is a member of. */
|
|
81
81
|
getTenants(user: User): MaybePromise<T[]>;
|
|
82
|
-
/**
|
|
82
|
+
/** Tenant from its URL key (comes from the browser: validate it). */
|
|
83
83
|
find(key: string): MaybePromise<T | null>;
|
|
84
84
|
canAccess(user: User, tenant: T): MaybePromise<boolean>;
|
|
85
85
|
getKey(tenant: T): string;
|
|
86
86
|
getName(tenant: T): string;
|
|
87
|
-
/**
|
|
87
|
+
/** Text above the tenant name in the menu ("Current team"), or `null`. */
|
|
88
88
|
getCurrentTenantLabel?(tenant: T): string | null;
|
|
89
89
|
getAvatarUrl?(tenant: T): string | null;
|
|
90
|
-
/**
|
|
90
|
+
/** Creates a tenant (tenant registration page); the user becomes a member. */
|
|
91
91
|
create?(data: Record<string, unknown>, user: User): MaybePromise<T>;
|
|
92
92
|
update?(tenant: T, data: Record<string, unknown>): MaybePromise<T>;
|
|
93
93
|
}
|
|
@@ -100,8 +100,8 @@ export type PanelContext = {
|
|
|
100
100
|
tenant?: unknown;
|
|
101
101
|
};
|
|
102
102
|
/**
|
|
103
|
-
*
|
|
104
|
-
*
|
|
103
|
+
* Predefined panel theme: a set of colors (palettes or plain colors), optionally a font and some CSS.
|
|
104
|
+
* When a panel declares several, users pick theirs from the user menu; the choice is kept in a cookie.
|
|
105
105
|
*/
|
|
106
106
|
export type Theme = {
|
|
107
107
|
id: string;
|
|
@@ -111,7 +111,7 @@ export type Theme = {
|
|
|
111
111
|
family: string;
|
|
112
112
|
url?: string;
|
|
113
113
|
};
|
|
114
|
-
/** CSS
|
|
114
|
+
/** CSS added to the page for this theme (written by the panel developer, inserted as-is). */
|
|
115
115
|
css?: string;
|
|
116
116
|
};
|
|
117
117
|
export declare class NavigationItem {
|
|
@@ -130,7 +130,7 @@ export declare class NavigationItem {
|
|
|
130
130
|
group(group: string | null): this;
|
|
131
131
|
sort(sort: number): this;
|
|
132
132
|
badge(badge: string | number | null, color?: string): this;
|
|
133
|
-
/**
|
|
133
|
+
/** By default an item is active on its exact URL; this overrides the rule. */
|
|
134
134
|
isActiveWhen(fn: (path: string) => boolean): this;
|
|
135
135
|
isActive(path: string): boolean;
|
|
136
136
|
}
|
|
@@ -162,57 +162,57 @@ export declare class Panel {
|
|
|
162
162
|
brandLogo(url: string): this;
|
|
163
163
|
darkModeBrandLogo(url: string): this;
|
|
164
164
|
brandLogoHeight(height: string): this;
|
|
165
|
-
/**
|
|
165
|
+
/** Browser tab icon. */
|
|
166
166
|
favicon(url: string | null): this;
|
|
167
167
|
getFavicon(): string | null;
|
|
168
168
|
/**
|
|
169
|
-
*
|
|
170
|
-
*
|
|
169
|
+
* Theme stylesheet compiled by the application (Tailwind); it replaces the default stylesheet.
|
|
170
|
+
* The theme imports `@navette-js/panels/theme.css` and declares its own sources.
|
|
171
171
|
*/
|
|
172
172
|
theme(url: string | null): this;
|
|
173
173
|
getTheme(): string | null;
|
|
174
174
|
/**
|
|
175
|
-
*
|
|
176
|
-
*
|
|
175
|
+
* Navette's motion and loading indicators (springs, activity dot, spinner for deferred areas).
|
|
176
|
+
* `motion(false)` renders the plain interface without them.
|
|
177
177
|
*/
|
|
178
178
|
motion(enabled?: boolean): this;
|
|
179
179
|
hasMotion(): boolean;
|
|
180
|
-
/**
|
|
180
|
+
/** Themes offered to the user; the first one is the default. */
|
|
181
181
|
themes(themes: Theme[]): this;
|
|
182
182
|
getThemes(): Theme[];
|
|
183
|
-
/**
|
|
183
|
+
/** Theme for the request: the cookie's theme if declared, otherwise the first one. `null` if the panel has no themes. */
|
|
184
184
|
resolveTheme(req: Request): Theme | null;
|
|
185
185
|
rememberTheme(res: Response, theme: Theme): void;
|
|
186
|
-
/**
|
|
186
|
+
/** Runs a render with the colors of the request's theme. */
|
|
187
187
|
withTheme<T>(req: Request, fn: () => T): T;
|
|
188
188
|
setColors(colors: Record<string, Palette | string>): this;
|
|
189
|
-
/**
|
|
189
|
+
/** Panel font. Without a URL, it is loaded from Bunny Fonts. */
|
|
190
190
|
font(family: string, url?: string): this;
|
|
191
191
|
login(page?: typeof Login): this;
|
|
192
192
|
auth(provider: AuthProvider): this;
|
|
193
193
|
key(key: string): this;
|
|
194
194
|
pages(pages: (typeof Page)[]): this;
|
|
195
|
-
/**
|
|
195
|
+
/** Registers resources: their pages and navigation items. */
|
|
196
196
|
resources(resources: (typeof Resource)[]): this;
|
|
197
197
|
navigationItems(items: NavigationItem[]): this;
|
|
198
|
-
/**
|
|
198
|
+
/** Order of navigation groups. */
|
|
199
199
|
navigationGroups(groups: string[]): this;
|
|
200
200
|
private _plugins;
|
|
201
|
-
/**
|
|
201
|
+
/** Applies a plugin: an object that configures the panel (resources, pages, render hooks, themes…). */
|
|
202
202
|
plugin(plugin: Plugin): this;
|
|
203
203
|
plugins(plugins: Plugin[]): this;
|
|
204
204
|
getPlugins(): Plugin[];
|
|
205
205
|
private _renderHooks;
|
|
206
206
|
/**
|
|
207
|
-
*
|
|
208
|
-
* `scopes`
|
|
207
|
+
* Inserts HTML at a named location of this panel's UI (names: `PanelsRenderHook`, `TablesRenderHook`, `ActionsRenderHook`, `WidgetsRenderHook`).
|
|
208
|
+
* `scopes` limits the hook to some pages or resources (their class). The HTML is inserted as-is: escape any data with `e()`.
|
|
209
209
|
*/
|
|
210
210
|
renderHook(name: string, render: RenderHookCallback, scopes?: unknown | unknown[] | null): this;
|
|
211
211
|
getRenderHooks(): RenderHookRegistry;
|
|
212
212
|
private _authorizer;
|
|
213
|
-
/**
|
|
213
|
+
/** Plugs in your own permission system: consulted before any policy, for every ability, page and widget. */
|
|
214
214
|
authorizeUsing(authorizer: Authorizer | null): this;
|
|
215
|
-
/**
|
|
215
|
+
/** Authorization decision: the panel hook first, then the given rule. Always `false` without a user. */
|
|
216
216
|
authorize(user: User | null, ability: string, subject?: {
|
|
217
217
|
resource?: unknown;
|
|
218
218
|
record?: unknown;
|
|
@@ -220,10 +220,10 @@ export declare class Panel {
|
|
|
220
220
|
widget?: typeof Widget;
|
|
221
221
|
rule?: (() => boolean | Promise<boolean>) | null;
|
|
222
222
|
}): Promise<boolean>;
|
|
223
|
-
/**
|
|
223
|
+
/** Whether the user can open a page. List: `viewAny`; create: `create`; edit: checked against the record; custom page: `canAccess`. */
|
|
224
224
|
canAccessPage(PageClass: typeof Page, user: User | null): Promise<boolean>;
|
|
225
225
|
private _widgets;
|
|
226
|
-
/**
|
|
226
|
+
/** Panel widgets (dashboard, custom pages): registered as components, displayed through a page's `getHeaderWidgets()`. */
|
|
227
227
|
widgets(widgets: (typeof Widget)[]): this;
|
|
228
228
|
getWidgets(): (typeof Widget)[];
|
|
229
229
|
maxContentWidth(width: string): this;
|
|
@@ -237,27 +237,27 @@ export declare class Panel {
|
|
|
237
237
|
private _globalSearchKeyBindings;
|
|
238
238
|
private _globalSearchDebounce;
|
|
239
239
|
private _globalSearchSuffix;
|
|
240
|
-
/** `false`
|
|
240
|
+
/** `false` removes the global search field. It only appears when at least one resource is searchable. */
|
|
241
241
|
globalSearch(condition?: boolean): this;
|
|
242
|
-
/**
|
|
242
|
+
/** Keyboard shortcuts that focus the field: `['command+k', 'ctrl+k']`. */
|
|
243
243
|
globalSearchKeyBindings(keyBindings: string[]): this;
|
|
244
244
|
getGlobalSearchKeyBindings(): string[];
|
|
245
|
-
/**
|
|
245
|
+
/** Delay between typing and searching (`500ms` by default). */
|
|
246
246
|
globalSearchDebounce(debounce: string): this;
|
|
247
247
|
getGlobalSearchDebounce(): string;
|
|
248
248
|
globalSearchFieldSuffix(suffix: string | null): this;
|
|
249
|
-
/**
|
|
249
|
+
/** Shows the first shortcut in the field, written for the browser's platform (`command+k` shows as "META+K" outside macOS). */
|
|
250
250
|
globalSearchFieldKeyBindingSuffix(): this;
|
|
251
251
|
getGlobalSearchFieldSuffix(userAgent?: string): string | null;
|
|
252
252
|
hasGlobalSearch(): boolean;
|
|
253
|
-
/**
|
|
253
|
+
/** Results per resource, in registration order. Only resources the user can list are queried. */
|
|
254
254
|
getGlobalSearchResults(search: string, user: User | null): Promise<GlobalSearchCategory[]>;
|
|
255
255
|
private _databaseNotifications;
|
|
256
256
|
private _databaseNotificationsPolling;
|
|
257
|
-
/**
|
|
257
|
+
/** Enables the database notifications bell, read from and written to this store (`knexNotificationStore(knex)`). */
|
|
258
258
|
databaseNotifications(store: DatabaseNotificationStore | null): this;
|
|
259
259
|
getDatabaseNotifications(): DatabaseNotificationStore | null;
|
|
260
|
-
/**
|
|
260
|
+
/** Polling interval (`30s` by default); `null` disables polling. */
|
|
261
261
|
databaseNotificationsPolling(interval: string | null): this;
|
|
262
262
|
getDatabaseNotificationsPollingInterval(): string | null;
|
|
263
263
|
private _topbar;
|
|
@@ -266,22 +266,22 @@ export declare class Panel {
|
|
|
266
266
|
private _sidebarCollapsibleOnDesktop;
|
|
267
267
|
private _sidebarFullyCollapsibleOnDesktop;
|
|
268
268
|
private _positions;
|
|
269
|
-
/**
|
|
269
|
+
/** Topbar, shown by default. `topbar(false)` moves the logo, search, bell and user menu into the sidebar. */
|
|
270
270
|
topbar(condition?: boolean): this;
|
|
271
271
|
hasTopbar(): boolean;
|
|
272
|
-
/** Navigation
|
|
272
|
+
/** Navigation in the topbar (one dropdown per group) instead of the sidebar. */
|
|
273
273
|
topNavigation(condition?: boolean): this;
|
|
274
274
|
hasTopNavigation(): boolean;
|
|
275
|
-
/** `navigation(false)`
|
|
275
|
+
/** `navigation(false)` removes all navigation (no sidebar, no menus). */
|
|
276
276
|
navigation(condition?: boolean): this;
|
|
277
277
|
hasNavigation(): boolean;
|
|
278
|
-
/**
|
|
278
|
+
/** On desktop, the sidebar can collapse to a column of icons. */
|
|
279
279
|
sidebarCollapsibleOnDesktop(condition?: boolean): this;
|
|
280
280
|
isSidebarCollapsibleOnDesktop(): boolean;
|
|
281
|
-
/**
|
|
281
|
+
/** On desktop, the sidebar can be fully hidden. */
|
|
282
282
|
sidebarFullyCollapsibleOnDesktop(condition?: boolean): this;
|
|
283
283
|
isSidebarFullyCollapsibleOnDesktop(): boolean;
|
|
284
|
-
/**
|
|
284
|
+
/** Where the user menu goes; defaults to the topbar when there is one. */
|
|
285
285
|
userMenuPosition(position: 'topbar' | 'sidebar' | null): this;
|
|
286
286
|
getUserMenuPosition(): 'topbar' | 'sidebar';
|
|
287
287
|
globalSearchPosition(position: 'topbar' | 'sidebar' | null): this;
|
|
@@ -289,7 +289,7 @@ export declare class Panel {
|
|
|
289
289
|
databaseNotificationsPosition(position: 'topbar' | 'sidebar' | null): this;
|
|
290
290
|
getDatabaseNotificationsPosition(): 'topbar' | 'sidebar';
|
|
291
291
|
private _userMenuItems;
|
|
292
|
-
/**
|
|
292
|
+
/** Items added to the user menu (URL or modal actions). A negative `sort()` places them above the theme switcher. Keys `profile` and `logout` replace the defaults. */
|
|
293
293
|
userMenuItems(items: Record<string, Action> | Action[]): this;
|
|
294
294
|
getUserMenuItems(): Record<string, Action>;
|
|
295
295
|
private _registration;
|
|
@@ -297,37 +297,37 @@ export declare class Panel {
|
|
|
297
297
|
private _emailVerification;
|
|
298
298
|
private _profile;
|
|
299
299
|
private _mailer;
|
|
300
|
-
/**
|
|
300
|
+
/** Registration page (`/register`). The auth provider must implement `create` and `findByEmail`. */
|
|
301
301
|
registration(page?: typeof Register | null): this;
|
|
302
302
|
hasRegistration(): boolean;
|
|
303
303
|
getRegistrationPage(): typeof Register | null;
|
|
304
|
-
/**
|
|
304
|
+
/** Password reset: request page (`/password-reset/request`), then reset through a signed link sent by email. */
|
|
305
305
|
passwordReset(request?: typeof RequestPasswordReset, reset?: typeof ResetPassword): this;
|
|
306
306
|
hasPasswordReset(): boolean;
|
|
307
307
|
getPasswordResetPages(): {
|
|
308
308
|
request: typeof RequestPasswordReset;
|
|
309
309
|
reset: typeof ResetPassword;
|
|
310
310
|
};
|
|
311
|
-
/**
|
|
311
|
+
/** Email verification: a signed link is sent on registration. Until it is followed, only the verification prompt is accessible (`isRequired`). */
|
|
312
312
|
emailVerification(prompt?: typeof EmailVerificationPrompt, isRequired?: boolean): this;
|
|
313
313
|
hasEmailVerification(): boolean;
|
|
314
314
|
isEmailVerificationRequired(): boolean;
|
|
315
315
|
getEmailVerificationPrompt(): typeof EmailVerificationPrompt | null;
|
|
316
|
-
/**
|
|
316
|
+
/** Profile page (`/profile`): name, email, password. `isSimple`: simple layout (default) or full panel layout. */
|
|
317
317
|
profile(page?: typeof EditProfile, isSimple?: boolean): this;
|
|
318
318
|
hasProfile(): boolean;
|
|
319
319
|
getProfile(): {
|
|
320
320
|
page: typeof EditProfile;
|
|
321
321
|
isSimple: boolean;
|
|
322
322
|
};
|
|
323
|
-
/**
|
|
323
|
+
/** Mailer for password reset and verification emails. Defaults to the console. */
|
|
324
324
|
mailer(mailer: Mailer): this;
|
|
325
325
|
sendMail(message: MailMessage): Promise<void>;
|
|
326
326
|
getAuthKey(): string;
|
|
327
327
|
getRegistrationUrl(): string;
|
|
328
328
|
getRequestPasswordResetUrl(): string;
|
|
329
329
|
getResetPasswordUrl(user: User, fingerprint: string): string;
|
|
330
|
-
/**
|
|
330
|
+
/** Payload of a password reset token valid for this panel, otherwise `null`. */
|
|
331
331
|
readResetPasswordToken(token: unknown): {
|
|
332
332
|
uid: string | number;
|
|
333
333
|
fp: string;
|
|
@@ -336,7 +336,7 @@ export declare class Panel {
|
|
|
336
336
|
checkVerifyEmailUrl(id: string, hash: string, expires: unknown, signature: unknown): boolean;
|
|
337
337
|
getEmailVerificationPromptUrl(): string;
|
|
338
338
|
getProfileUrl(): string | null;
|
|
339
|
-
/**
|
|
339
|
+
/** Whether the user must still verify their email before using the panel. */
|
|
340
340
|
mustVerifyEmail(user: User | null): Promise<boolean>;
|
|
341
341
|
private _tenant;
|
|
342
342
|
private _tenantOwnershipColumn;
|
|
@@ -346,8 +346,8 @@ export declare class Panel {
|
|
|
346
346
|
private _tenantMenuItems;
|
|
347
347
|
private _tenantScope;
|
|
348
348
|
/**
|
|
349
|
-
*
|
|
350
|
-
*
|
|
349
|
+
* Makes the panel multi-tenant. `ownershipColumn` is the column linking a record to its tenant (`team_id`);
|
|
350
|
+
* the panel's resources then only read and write the current tenant's records (see `Resource.isScopedToTenant`).
|
|
351
351
|
*/
|
|
352
352
|
tenant(provider: TenantProvider | null, options?: {
|
|
353
353
|
ownershipColumn?: string;
|
|
@@ -355,54 +355,54 @@ export declare class Panel {
|
|
|
355
355
|
hasTenancy(): boolean;
|
|
356
356
|
getTenantProvider(): TenantProvider;
|
|
357
357
|
getTenantOwnershipColumn(): string | null;
|
|
358
|
-
/**
|
|
358
|
+
/** Tenant registration page (`/new`). */
|
|
359
359
|
tenantRegistration(page: typeof RegisterTenant | null): this;
|
|
360
360
|
getTenantRegistrationPage(): typeof RegisterTenant | null;
|
|
361
|
-
/**
|
|
361
|
+
/** Tenant profile page (`/<tenant>/profile`). */
|
|
362
362
|
tenantProfile(page: typeof EditTenantProfile | null): this;
|
|
363
363
|
getTenantProfilePage(): typeof EditTenantProfile | null;
|
|
364
364
|
tenantMenu(condition?: boolean): this;
|
|
365
365
|
hasTenantMenu(): boolean;
|
|
366
366
|
tenantMenuItems(items: Record<string, Action> | Action[]): this;
|
|
367
367
|
getTenantMenuItems(): Record<string, Action>;
|
|
368
|
-
/**
|
|
368
|
+
/** Runs `fn` for a tenant: generated URLs (`getUrl`) and resource queries are scoped to it. */
|
|
369
369
|
withTenant<T>(tenant: unknown, fn: () => T): T;
|
|
370
|
-
/**
|
|
370
|
+
/** Tenant of the current request, or `null`. */
|
|
371
371
|
getTenant<T = any>(): T | null;
|
|
372
372
|
getTenantUrlKey(tenant: unknown): string;
|
|
373
373
|
private _subNavigationPosition;
|
|
374
|
-
/**
|
|
374
|
+
/** Default position of page sub-navigation (`start`). */
|
|
375
375
|
subNavigationPosition(position: 'start' | 'end' | 'top'): this;
|
|
376
376
|
getSubNavigationPosition(): 'start' | 'end' | 'top';
|
|
377
377
|
private _appUrl;
|
|
378
|
-
/**
|
|
378
|
+
/** Public URL of the application (`https://example.com`), used in emailed links. Without it the request origin is used, which should be avoided in production (the `Host` header can be forged). */
|
|
379
379
|
appUrl(url: string | null): this;
|
|
380
380
|
getAppUrl(): string | null;
|
|
381
381
|
getMaxContentWidth(): string;
|
|
382
|
-
/**
|
|
382
|
+
/** URL inside the panel; in a multi-tenant panel, prefixed with the current (or given) tenant. */
|
|
383
383
|
getUrl(sub?: string, tenant?: unknown): string;
|
|
384
|
-
/**
|
|
384
|
+
/** URL outside any tenant (login, registration, profile, tenant registration). */
|
|
385
385
|
getBaseUrl(sub?: string): string;
|
|
386
386
|
getLoginUrl(): string;
|
|
387
387
|
getLogoutUrl(): string;
|
|
388
|
-
/**
|
|
388
|
+
/** Prefix of this panel's Livewire endpoint (`/livewire` or `/<path>/livewire`): each panel has its own. */
|
|
389
389
|
getLivewirePrefix(): string;
|
|
390
390
|
assetUrl(file: string): string;
|
|
391
391
|
getBrand(): Record<string, unknown>;
|
|
392
392
|
getFont(): typeof this._font;
|
|
393
|
-
/**
|
|
393
|
+
/** Default avatar: the name's initials from the external ui-avatars.com service. */
|
|
394
394
|
getUserAvatarUrl(user: User): string;
|
|
395
|
-
/**
|
|
395
|
+
/** Tenant avatar: from the tenant provider (`getAvatarUrl`), otherwise its initials. */
|
|
396
396
|
getTenantAvatarUrl(tenant: unknown): string;
|
|
397
397
|
private _spa;
|
|
398
|
-
/**
|
|
398
|
+
/** SPA mode: navigate between panel pages without full reloads (`wire:navigate`). */
|
|
399
399
|
spa(condition?: boolean): this;
|
|
400
400
|
hasSpaMode(): boolean;
|
|
401
401
|
getAvatarUrlFor(name: string): string;
|
|
402
|
-
/**
|
|
403
|
-
/**
|
|
402
|
+
/** Navigation groups: registered pages plus custom items, sorted, grouped in the declared order. */
|
|
403
|
+
/** Computed navigation badges: page URL → value. */
|
|
404
404
|
resolveNavigationBadges(): Promise<Map<string, string | number | null>>;
|
|
405
|
-
/**
|
|
405
|
+
/** URLs of menu pages this user cannot open. */
|
|
406
406
|
resolveInaccessiblePages(user: User | null): Promise<Set<string>>;
|
|
407
407
|
getNavigation(path: string, badges?: Map<string, string | number | null>, hidden?: Set<string>): {
|
|
408
408
|
label: string | null;
|
|
@@ -423,9 +423,7 @@ export declare class Panel {
|
|
|
423
423
|
user(req: Request): Promise<User | null>;
|
|
424
424
|
}
|
|
425
425
|
/**
|
|
426
|
-
*
|
|
427
|
-
* Ceux d'une brique pas encore portée (barre du haut, recherche globale, menu de locataire, sous-navigation, inscription,
|
|
428
|
-
* réinitialisation du mot de passe, enregistrements liés) sont déclarés mais ne sont rendus nulle part pour l'instant : voir `UNPLACED_RENDER_HOOKS`.
|
|
426
|
+
* Render hook locations of a panel. A few are declared but not rendered anywhere yet: see `UNPLACED_RENDER_HOOKS`.
|
|
429
427
|
*/
|
|
430
428
|
export declare const PanelsRenderHook: {
|
|
431
429
|
readonly AUTH_LOGIN_FORM_AFTER: "panels::auth.login.form.after";
|
|
@@ -465,7 +463,7 @@ export declare const PanelsRenderHook: {
|
|
|
465
463
|
readonly PAGE_HEADER_WIDGETS_END: "panels::page.header-widgets.end";
|
|
466
464
|
readonly PAGE_HEADER_WIDGETS_START: "panels::page.header-widgets.start";
|
|
467
465
|
readonly PAGE_START: "panels::page.start";
|
|
468
|
-
/**
|
|
466
|
+
/** The hook name says "module-menu", not "mobile-menu": kept for compatibility. */
|
|
469
467
|
readonly PAGE_SUB_NAVIGATION_MOBILE_MENU_AFTER: "panels::page.sub-navigation.module-menu.after";
|
|
470
468
|
readonly PAGE_SUB_NAVIGATION_MOBILE_MENU_BEFORE: "panels::page.sub-navigation.module-menu.before";
|
|
471
469
|
readonly PAGE_SUB_NAVIGATION_SIDEBAR_AFTER: "panels::page.sub-navigation.sidebar.after";
|
|
@@ -513,27 +511,26 @@ export declare const PanelsRenderHook: {
|
|
|
513
511
|
readonly USER_MENU_PROFILE_AFTER: "panels::user-menu.profile.after";
|
|
514
512
|
readonly USER_MENU_PROFILE_BEFORE: "panels::user-menu.profile.before";
|
|
515
513
|
};
|
|
516
|
-
/**
|
|
514
|
+
/** Widget render hook locations, rendered by `TableWidget`. */
|
|
517
515
|
export declare const WidgetsRenderHook: {
|
|
518
516
|
readonly TABLE_WIDGET_END: "widgets::table-widget.end";
|
|
519
517
|
readonly TABLE_WIDGET_START: "widgets::table-widget.start";
|
|
520
518
|
};
|
|
521
519
|
/**
|
|
522
|
-
*
|
|
523
|
-
* Les quatre « tabs » ne sont rendus par aucune vue de Filament 5.11.2 non plus.
|
|
520
|
+
* Hook locations that are declared but not rendered anywhere yet, with the reason.
|
|
524
521
|
*/
|
|
525
522
|
export declare const UNPLACED_RENDER_HOOKS: Record<string, string>;
|
|
526
|
-
/**
|
|
523
|
+
/** Common base: a stateful component hosting schemas (`<name>Schema(schema)`). */
|
|
527
524
|
declare abstract class BasePage extends Component implements SchemaHost {
|
|
528
525
|
get panel(): Panel;
|
|
529
526
|
getSchema(name: string): Schema;
|
|
530
527
|
contentSchema(schema: Schema): Schema;
|
|
531
|
-
/**
|
|
528
|
+
/** Render hook scopes of this page: its class (and its resource, for a resource page). */
|
|
532
529
|
getRenderHookScopes(): unknown[];
|
|
533
530
|
}
|
|
534
|
-
/**
|
|
531
|
+
/** A panel page, in the full layout (sidebar, header). */
|
|
535
532
|
export declare class Page extends BasePage {
|
|
536
|
-
/**
|
|
533
|
+
/** Methods the browser may call. A subclass adds its own: `static callable = ['approve']`. */
|
|
537
534
|
static callable: string[];
|
|
538
535
|
static slug: string;
|
|
539
536
|
static title: string | null;
|
|
@@ -544,11 +541,11 @@ export declare class Page extends BasePage {
|
|
|
544
541
|
static navigationBadge: string | number | null;
|
|
545
542
|
static navigationBadgeColor: string;
|
|
546
543
|
static shouldRegisterNavigation: boolean;
|
|
547
|
-
/**
|
|
544
|
+
/** Restricts the page to some users: returning `false` hides it from the menu and denies it (403). */
|
|
548
545
|
static canAccess(_user: User): boolean | Promise<boolean>;
|
|
549
546
|
static getTitle(): string;
|
|
550
547
|
static getNavigationLabel(): string;
|
|
551
|
-
/**
|
|
548
|
+
/** Every request, including browser updates, requires an authenticated user: a snapshot kept after logout is not enough. */
|
|
552
549
|
boot(): Promise<void>;
|
|
553
550
|
protected isAccessAuthorized(ctx: PanelContext): boolean | Promise<boolean>;
|
|
554
551
|
getTitle(): string;
|
|
@@ -559,27 +556,27 @@ export declare class Page extends BasePage {
|
|
|
559
556
|
}[];
|
|
560
557
|
getHeaderActions(): Action[];
|
|
561
558
|
getPageClasses(): string[];
|
|
562
|
-
/**
|
|
559
|
+
/** Page sub-navigation; empty by default. */
|
|
563
560
|
getSubNavigation(): SubNavigationItem[] | Promise<SubNavigationItem[]>;
|
|
564
|
-
/**
|
|
561
|
+
/** Sub-navigation position: `start` (column before the content), `end` (after) or `top` (tabs). Defaults to the resource's, then the panel's. */
|
|
565
562
|
static subNavigationPosition: 'start' | 'end' | 'top' | null;
|
|
566
563
|
getSubNavigationPosition(): 'start' | 'end' | 'top';
|
|
567
|
-
/** Widgets
|
|
564
|
+
/** Widgets shown below the page content. */
|
|
568
565
|
getFooterWidgets(): (typeof Widget)[];
|
|
569
566
|
getFooterWidgetsColumns(): number | Record<string, number>;
|
|
570
|
-
/**
|
|
567
|
+
/** Footer widget grid, in the page's `footerWidgets` schema. */
|
|
571
568
|
protected renderFooterWidgets(): Promise<string>;
|
|
572
|
-
/** Widgets
|
|
569
|
+
/** Widgets shown above the page content, with the data passed to each (widget properties). */
|
|
573
570
|
getHeaderWidgets(): (typeof Widget)[];
|
|
574
571
|
getHeaderWidgetsColumns(): number;
|
|
575
572
|
getWidgetData(): Record<string, unknown>;
|
|
576
|
-
/**
|
|
573
|
+
/** Header widget grid, in the page's `headerWidgets` schema. */
|
|
577
574
|
protected renderHeaderWidgets(): Promise<string>;
|
|
578
|
-
/** Widgets
|
|
575
|
+
/** Widgets the current user is allowed to see. */
|
|
579
576
|
protected filterVisibleWidgets(candidates: (typeof Widget)[]): Promise<(typeof Widget)[]>;
|
|
580
|
-
/**
|
|
577
|
+
/** Widget grid of a schema: each widget is a child component, lazy-loaded by default. */
|
|
581
578
|
protected renderWidgetsGrid(widgets: (typeof Widget)[], columns: number | Record<string, number>, schemaKey: string): Promise<string>;
|
|
582
|
-
/**
|
|
579
|
+
/** Page content: its `content` schema by default. */
|
|
583
580
|
protected renderContent(): Promise<string>;
|
|
584
581
|
mountedActions: {
|
|
585
582
|
name: string;
|
|
@@ -589,54 +586,54 @@ export declare class Page extends BasePage {
|
|
|
589
586
|
}[];
|
|
590
587
|
getActionMountContext(): Record<string, unknown>;
|
|
591
588
|
protected getActionRecord(): unknown;
|
|
592
|
-
/**
|
|
589
|
+
/** Record targeted by an action mounted in a given context (table row…). */
|
|
593
590
|
protected resolveActionRecord(_context: Record<string, unknown>): Promise<unknown>;
|
|
594
|
-
/** Actions
|
|
591
|
+
/** Actions that can be mounted in a given context (page header by default). */
|
|
595
592
|
protected getMountableActions(context: Record<string, unknown>): Action[] | Promise<Action[]>;
|
|
596
593
|
/**
|
|
597
|
-
* Actions
|
|
598
|
-
*
|
|
594
|
+
* Actions owned by a schema component (Repeater: add, delete, move; Section: header actions).
|
|
595
|
+
* The key comes from the browser: it must match a real component of the schema, or the schema itself.
|
|
599
596
|
*/
|
|
600
597
|
protected getSchemaComponentActions(key: string): Promise<Action[]>;
|
|
601
|
-
/**
|
|
598
|
+
/** Context kept for a mounted action: the server's, never the browser's as-is. */
|
|
602
599
|
protected resolveMountContext(clientContext: unknown): Record<string, unknown>;
|
|
603
600
|
private findMountableAction;
|
|
604
601
|
private actionContext;
|
|
605
|
-
/**
|
|
602
|
+
/** Form schema of a mounted action: key `mountedActionSchema<n>`, state under `mountedActions.<n>.data`. */
|
|
606
603
|
getMountedActionSchema(index: number): Promise<Schema | null>;
|
|
607
604
|
private renderActionModal;
|
|
608
|
-
/**
|
|
605
|
+
/** Cancels a partial modal render prepared by a live field when the same request then runs an action. */
|
|
609
606
|
private cancelModalPartialRender;
|
|
610
|
-
/**
|
|
607
|
+
/** Live field in a mounted action's form: runs `afterStateUpdated`, then only returns the affected modal. */
|
|
611
608
|
updatedMountedActions(_value: unknown, key: string | null): Promise<void>;
|
|
612
|
-
/**
|
|
609
|
+
/** Calls a method exposed by a field, from that field's JavaScript (e.g. Select search). Does not re-render. */
|
|
613
610
|
callSchemaComponentMethod(componentKey: unknown, method: unknown, args?: unknown): Promise<unknown>;
|
|
614
|
-
/**
|
|
611
|
+
/** A hidden action can be neither mounted nor run, even through a call forged by the browser. */
|
|
615
612
|
private assertActionVisible;
|
|
616
613
|
private syncActionModals;
|
|
617
|
-
/**
|
|
614
|
+
/** False for a table component: its modals are rendered inside the table. */
|
|
618
615
|
protected rendersActionModalsInPage(): boolean;
|
|
619
616
|
renderActionModals(): Promise<string>;
|
|
620
|
-
/**
|
|
617
|
+
/** Mounts an action: without a modal it runs immediately; with one, only the modals fragment is returned. */
|
|
621
618
|
mountAction(name: unknown, args?: unknown, _context?: unknown): Promise<void>;
|
|
622
619
|
unmountAction(_shouldCancelParentActions?: unknown): void;
|
|
623
620
|
callMountedAction(_args?: unknown): Promise<void>;
|
|
624
621
|
render(): Promise<string>;
|
|
625
622
|
}
|
|
626
623
|
/**
|
|
627
|
-
*
|
|
628
|
-
*
|
|
624
|
+
* Dashboard: a widget grid, preceded by a filters form when the page defines `filtersFormSchema(schema)`.
|
|
625
|
+
* The filters are passed to widgets as `pageFilters`.
|
|
629
626
|
*/
|
|
630
627
|
export declare class Dashboard extends Page {
|
|
631
628
|
static slug: string;
|
|
632
629
|
static title: string;
|
|
633
630
|
static navigationIcon: string;
|
|
634
631
|
static navigationSort: number;
|
|
635
|
-
/**
|
|
632
|
+
/** Filters form state. Stays `null` while the page has no filters. */
|
|
636
633
|
filters: Record<string, unknown> | null;
|
|
637
|
-
/**
|
|
634
|
+
/** Dashboard widgets. Defaults to the panel's (`panel.widgets([...])`). */
|
|
638
635
|
getWidgets(): (typeof Widget)[];
|
|
639
|
-
/**
|
|
636
|
+
/** Grid columns: a number (at the `lg` breakpoint), or one number per breakpoint. */
|
|
640
637
|
getColumns(): number | Record<string, number>;
|
|
641
638
|
hasFiltersForm(): boolean;
|
|
642
639
|
getSchema(name: string): Schema;
|
|
@@ -644,26 +641,26 @@ export declare class Dashboard extends Page {
|
|
|
644
641
|
getWidgetData(): Record<string, unknown>;
|
|
645
642
|
protected renderContent(): Promise<string>;
|
|
646
643
|
}
|
|
647
|
-
/**
|
|
644
|
+
/** In-memory rate limiter: `max` attempts per window, per key. Fine for a single instance; use a shared store when running several. */
|
|
648
645
|
export declare class Throttle {
|
|
649
646
|
private hits;
|
|
650
647
|
private max;
|
|
651
648
|
private windowMs;
|
|
652
649
|
constructor(max?: number, windowMs?: number);
|
|
653
|
-
/**
|
|
650
|
+
/** Records an attempt; returns 0 if allowed, otherwise the number of seconds to wait. */
|
|
654
651
|
hit(key: string, now?: number): number;
|
|
655
652
|
clear(key: string): void;
|
|
656
653
|
}
|
|
657
|
-
/** Page
|
|
654
|
+
/** Page with the simple layout (login, registration…). */
|
|
658
655
|
export declare abstract class SimplePage extends BasePage {
|
|
659
656
|
abstract getTitle(): string;
|
|
660
657
|
getHeading(): string | null;
|
|
661
|
-
/**
|
|
658
|
+
/** Subheading, as trusted HTML (built by the page, with data escaped). */
|
|
662
659
|
getSubheading(): string | null;
|
|
663
660
|
hasLogo(): boolean;
|
|
664
661
|
render(): Promise<string>;
|
|
665
662
|
}
|
|
666
|
-
/**
|
|
663
|
+
/** Registration page: name, email, confirmed password. The user is logged in, then asked to verify their email if the panel requires it. */
|
|
667
664
|
export declare class Register extends SimplePage {
|
|
668
665
|
static callable: string[];
|
|
669
666
|
data: Record<string, unknown>;
|
|
@@ -673,13 +670,13 @@ export declare class Register extends SimplePage {
|
|
|
673
670
|
getSubheading(): string | null;
|
|
674
671
|
formSchema(schema: Schema): Schema;
|
|
675
672
|
contentSchema(schema: Schema): Schema;
|
|
676
|
-
/**
|
|
673
|
+
/** Validated data, just before creation (add a value, normalize the email…). */
|
|
677
674
|
protected mutateFormDataBeforeRegister(data: Record<string, unknown>): Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
678
|
-
/**
|
|
675
|
+
/** Creates the user; defaults to the auth provider's `create()`. */
|
|
679
676
|
protected handleRegistration(data: Record<string, unknown>): Promise<User> | User;
|
|
680
677
|
register(): Promise<void>;
|
|
681
678
|
}
|
|
682
|
-
/**
|
|
679
|
+
/** Password reset request page: a signed link, valid for 60 minutes, is sent by email. */
|
|
683
680
|
export declare class RequestPasswordReset extends SimplePage {
|
|
684
681
|
static callable: string[];
|
|
685
682
|
data: Record<string, unknown>;
|
|
@@ -691,7 +688,7 @@ export declare class RequestPasswordReset extends SimplePage {
|
|
|
691
688
|
contentSchema(schema: Schema): Schema;
|
|
692
689
|
request(): Promise<void>;
|
|
693
690
|
}
|
|
694
|
-
/**
|
|
691
|
+
/** Sets a new password from the emailed link. The link works once: it dies with the old password. */
|
|
695
692
|
export declare class ResetPassword extends SimplePage {
|
|
696
693
|
static callable: string[];
|
|
697
694
|
static locked: string[];
|
|
@@ -700,7 +697,7 @@ export declare class ResetPassword extends SimplePage {
|
|
|
700
697
|
passwordConfirmation: string;
|
|
701
698
|
token: string | null;
|
|
702
699
|
mount(params: Record<string, unknown>): void;
|
|
703
|
-
/**
|
|
700
|
+
/** The form has no state path: its fields are page properties. */
|
|
704
701
|
getSchema(name: string): Schema;
|
|
705
702
|
getTitle(): string;
|
|
706
703
|
getHeading(): string;
|
|
@@ -708,17 +705,17 @@ export declare class ResetPassword extends SimplePage {
|
|
|
708
705
|
contentSchema(schema: Schema): Schema;
|
|
709
706
|
resetPassword(): Promise<void>;
|
|
710
707
|
}
|
|
711
|
-
/**
|
|
708
|
+
/** Email verification prompt, with a "Resend it." link. */
|
|
712
709
|
export declare class EmailVerificationPrompt extends SimplePage {
|
|
713
710
|
static callable: string[];
|
|
714
711
|
mount(): Promise<void>;
|
|
715
712
|
getTitle(): string;
|
|
716
713
|
getHeading(): string;
|
|
717
714
|
contentSchema(schema: Schema): Schema;
|
|
718
|
-
/**
|
|
715
|
+
/** The page's only action: resend the email (at most twice per minute). */
|
|
719
716
|
mountAction(name: unknown): Promise<void>;
|
|
720
717
|
}
|
|
721
|
-
/**
|
|
718
|
+
/** User profile page: name, email, new password. The current password is required to change the email or password. */
|
|
722
719
|
export declare class EditProfile extends SimplePage {
|
|
723
720
|
static callable: string[];
|
|
724
721
|
static slug: string;
|
|
@@ -732,13 +729,13 @@ export declare class EditProfile extends SimplePage {
|
|
|
732
729
|
contentSchema(schema: Schema): Schema;
|
|
733
730
|
save(): Promise<void>;
|
|
734
731
|
}
|
|
735
|
-
/**
|
|
732
|
+
/** Tenant registration page: the subclass provides its label and form (`formSchema`). */
|
|
736
733
|
export declare abstract class RegisterTenant extends SimplePage {
|
|
737
734
|
static callable: string[];
|
|
738
735
|
static slug: string;
|
|
739
736
|
data: Record<string, unknown>;
|
|
740
737
|
static getLabel(): string;
|
|
741
|
-
/**
|
|
738
|
+
/** Whether tenants can be created; by default, if the tenant provider implements `create`. */
|
|
742
739
|
static canView(panel: Panel, _user: User): boolean | Promise<boolean>;
|
|
743
740
|
boot(): Promise<void>;
|
|
744
741
|
mount(): void;
|
|
@@ -750,7 +747,7 @@ export declare abstract class RegisterTenant extends SimplePage {
|
|
|
750
747
|
protected handleRegistration(data: Record<string, unknown>): unknown;
|
|
751
748
|
register(): Promise<void>;
|
|
752
749
|
}
|
|
753
|
-
/**
|
|
750
|
+
/** Current tenant's profile page, in the full layout. */
|
|
754
751
|
export declare abstract class EditTenantProfile extends Page {
|
|
755
752
|
static callable: string[];
|
|
756
753
|
static slug: string;
|
|
@@ -775,9 +772,9 @@ export declare class Login extends SimplePage {
|
|
|
775
772
|
contentSchema(schema: Schema): Schema;
|
|
776
773
|
authenticate(): Promise<void>;
|
|
777
774
|
}
|
|
778
|
-
/**
|
|
775
|
+
/** Whether the host component's user has this ability on the component's resource (or relation manager). Use it in your actions' `authorize()`. */
|
|
779
776
|
export declare const can: (livewire: unknown, ability: string, record?: unknown) => Promise<boolean> | boolean;
|
|
780
|
-
/** Resource
|
|
777
|
+
/** Resource: a model with its pages, table and navigation. */
|
|
781
778
|
export declare abstract class Resource {
|
|
782
779
|
static panel: Panel;
|
|
783
780
|
static slug: string;
|
|
@@ -788,12 +785,12 @@ export declare abstract class Resource {
|
|
|
788
785
|
static navigationSort: number;
|
|
789
786
|
static navigationBadge: string | number | null;
|
|
790
787
|
static adapter: DataAdapter;
|
|
791
|
-
/**
|
|
788
|
+
/** In a multi-tenant panel, whether records belong to each tenant (`true` by default). */
|
|
792
789
|
static isScopedToTenant: boolean;
|
|
793
|
-
/**
|
|
790
|
+
/** Tenant column for this resource (defaults to the panel's: `panel.tenant(provider, { ownershipColumn })`). */
|
|
794
791
|
static tenantOwnershipColumn: string | null;
|
|
795
792
|
/**
|
|
796
|
-
*
|
|
793
|
+
* Resource pages; replace them with your subclasses to change their behavior:
|
|
797
794
|
* `static pages = { index: MyList, create: MyCreate, edit: MyEdit }`.
|
|
798
795
|
*/
|
|
799
796
|
static pages: {
|
|
@@ -802,64 +799,64 @@ export declare abstract class Resource {
|
|
|
802
799
|
edit?: typeof EditRecord;
|
|
803
800
|
view?: typeof ViewRecord;
|
|
804
801
|
};
|
|
805
|
-
/**
|
|
802
|
+
/** `true` adds a view page (`ViewRecord`) to the resource; table rows then link to it. */
|
|
806
803
|
static hasViewPage: boolean;
|
|
807
|
-
/**
|
|
804
|
+
/** Who can do what on this resource. Without a policy, any signed-in user can do everything. */
|
|
808
805
|
static policy: Policy | null;
|
|
809
|
-
/**
|
|
806
|
+
/** Whether the user has this ability (on this record, if any). */
|
|
810
807
|
static can(ability: string, user: User | null, record?: unknown): Promise<boolean>;
|
|
811
|
-
/**
|
|
808
|
+
/** Resource widgets, registered as components. */
|
|
812
809
|
static widgets: (typeof Widget)[];
|
|
813
|
-
/** Widgets
|
|
810
|
+
/** Widgets shown above the table on the list page. */
|
|
814
811
|
static headerWidgets: (typeof Widget)[];
|
|
815
|
-
/** Relation managers
|
|
812
|
+
/** Relation managers shown below the edit form. */
|
|
816
813
|
static relations: any[];
|
|
817
|
-
/**
|
|
814
|
+
/** Tabs of the list page. */
|
|
818
815
|
static tabs(): Record<string, Tab>;
|
|
819
|
-
/**
|
|
816
|
+
/** Simple resource: a single page, with create and edit in modals. */
|
|
820
817
|
static isSimple: boolean;
|
|
821
818
|
static getPluralModelLabel(): string;
|
|
822
819
|
static getTitleCasePluralModelLabel(): string;
|
|
823
820
|
static getUrl(page?: string, record?: string | number): string;
|
|
824
|
-
/**
|
|
821
|
+
/** Related records pages: `{ comments: ManagePostComments }` is served at `<slug>/{record}/comments`. */
|
|
825
822
|
static relatedPages: Record<string, typeof ManageRelatedRecords>;
|
|
826
|
-
/** Pages
|
|
823
|
+
/** Pages listed in a record's sub-navigation, in order: `['view', 'edit', 'comments']`. Empty: no sub-navigation. */
|
|
827
824
|
static recordSubNavigation: string[];
|
|
828
|
-
/**
|
|
825
|
+
/** Record sub-navigation: one tab per declared page, the current page's tab active. */
|
|
829
826
|
static getRecordSubNavigation(page: {
|
|
830
827
|
getRecordKey(): string | null;
|
|
831
828
|
constructor: Function;
|
|
832
829
|
}): SubNavigationItem[];
|
|
833
830
|
private static _registered;
|
|
834
|
-
/**
|
|
831
|
+
/** Page class actually registered under a name (pages are generated once per resource). */
|
|
835
832
|
static getRegisteredPage(name: string): typeof Page | undefined;
|
|
836
833
|
static table(table: Table): Table;
|
|
837
834
|
static form(schema: Schema): Schema;
|
|
838
|
-
/**
|
|
835
|
+
/** Schema of the view page. */
|
|
839
836
|
static infolist(schema: Schema): Schema;
|
|
840
|
-
/**
|
|
837
|
+
/** Columns searched by global search; defaults to the title attribute. Empty array: the resource is not searchable. */
|
|
841
838
|
static globallySearchableAttributes: string[] | null;
|
|
842
839
|
static getGloballySearchableAttributes(): string[];
|
|
843
840
|
static canGloballySearch(): boolean;
|
|
844
|
-
/**
|
|
841
|
+
/** Position of this resource's group in the results; without one, after the others in registration order. */
|
|
845
842
|
static globalSearchSort: number | null;
|
|
846
|
-
/**
|
|
843
|
+
/** Maximum results rendered per resource. */
|
|
847
844
|
static globalSearchResultsLimit: number;
|
|
848
845
|
static getGlobalSearchResultTitle(record: any): string;
|
|
849
|
-
/**
|
|
846
|
+
/** Details shown under the title: `{ Author: 'Jane' }`. Empty values are skipped. */
|
|
850
847
|
static getGlobalSearchResultDetails(_record: any): Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
851
|
-
/**
|
|
848
|
+
/** URL of a result: the view page, otherwise the edit page; for a simple resource, the list with the action open. `null` if the user has no access. */
|
|
852
849
|
static getGlobalSearchResultUrl(record: any, user: User | null): Promise<string | null>;
|
|
853
850
|
static getGlobalSearchResults(search: string, user: User | null): Promise<GlobalSearchResult[]>;
|
|
854
|
-
/**
|
|
851
|
+
/** Attribute used as a record's title. */
|
|
855
852
|
static recordTitleAttribute: string | null;
|
|
856
|
-
/**
|
|
853
|
+
/** Without a title attribute: the model label in title case ("Leave Request"). */
|
|
857
854
|
static getRecordTitle(record: any): string;
|
|
858
|
-
/**
|
|
855
|
+
/** Generated resource pages: list, create, edit. */
|
|
859
856
|
static getPages(): Record<string, typeof Page>;
|
|
860
857
|
private static buildPages;
|
|
861
858
|
}
|
|
862
|
-
/**
|
|
859
|
+
/** Sub-navigation tab of a page. */
|
|
863
860
|
export type SubNavigationItem = {
|
|
864
861
|
label: string;
|
|
865
862
|
icon: string | null;
|
|
@@ -867,85 +864,85 @@ export type SubNavigationItem = {
|
|
|
867
864
|
active: boolean;
|
|
868
865
|
};
|
|
869
866
|
type ColumnSpan = number | 'full';
|
|
870
|
-
/** Widget
|
|
867
|
+
/** Widget: a component displayed in a page's widget grid. */
|
|
871
868
|
export declare abstract class Widget extends Component {
|
|
872
869
|
static componentName: string;
|
|
873
|
-
/**
|
|
870
|
+
/** Width in the widget grid: a number of columns, or `'full'`. */
|
|
874
871
|
static columnSpan: ColumnSpan;
|
|
875
|
-
/**
|
|
872
|
+
/** Loaded when it becomes visible. */
|
|
876
873
|
static isLazy: boolean;
|
|
877
874
|
get panel(): Panel;
|
|
878
|
-
/**
|
|
875
|
+
/** Restricts the widget to some users: returning `false` removes it from the page and refuses to load it. */
|
|
879
876
|
static canView(_user: User): boolean | Promise<boolean>;
|
|
880
877
|
boot(): Promise<void>;
|
|
881
|
-
/**
|
|
878
|
+
/** Grid column classes and style, at the `lg` breakpoint. */
|
|
882
879
|
protected gridColumn(): {
|
|
883
880
|
classes: string[];
|
|
884
881
|
style: string;
|
|
885
882
|
};
|
|
886
883
|
placeholder(): string;
|
|
887
|
-
/**
|
|
884
|
+
/** Common widget wrapper. */
|
|
888
885
|
protected wrap(content: string, classes?: string[]): string;
|
|
889
886
|
}
|
|
890
887
|
/**
|
|
891
|
-
*
|
|
888
|
+
* Calendar widget: month, week and list views, server-rendered navigation, no JavaScript library.
|
|
892
889
|
*
|
|
893
|
-
*
|
|
890
|
+
* Minimal use: extend the class and return the events of the displayed period.
|
|
894
891
|
*
|
|
895
892
|
* class LeaveCalendar extends CalendarWidget {
|
|
896
893
|
* static heading = 'Leave';
|
|
897
894
|
* async getEvents({ start, end }) { return [{ id: 1, title: 'Ada — vacation', start: '2026-11-12', end: '2026-11-14', color: 'success' }]; }
|
|
898
895
|
* }
|
|
899
896
|
*
|
|
900
|
-
*
|
|
901
|
-
*
|
|
902
|
-
*
|
|
903
|
-
*
|
|
897
|
+
* Everything else can be overridden method by method: available views, first day of the week, locale, labels, events
|
|
898
|
+
* per cell, day clicks (`onDateClick`) and event clicks (`onEventClick`), event rendering (`renderEvent`), cell footer
|
|
899
|
+
* (`renderDayFooter`), toolbar buttons (`renderToolbarEnd`), and appearance through the `.nv-cal` CSS variables
|
|
900
|
+
* (`getExtraClasses`, `getStyle`).
|
|
904
901
|
*/
|
|
905
902
|
export declare abstract class CalendarWidget extends Widget {
|
|
906
903
|
static columnSpan: ColumnSpan;
|
|
907
|
-
/**
|
|
904
|
+
/** Heading shown before the period ("Leave — November 2026"). */
|
|
908
905
|
static heading: string | null;
|
|
909
906
|
static callable: string[];
|
|
910
|
-
/**
|
|
907
|
+
/** View and date only change through the methods below, which validate them. */
|
|
911
908
|
static locked: string[];
|
|
912
909
|
view: CalendarView;
|
|
913
|
-
/**
|
|
910
|
+
/** Anchor date (`YYYY-MM-DD`): the displayed month or week contains it. Empty: today. */
|
|
914
911
|
date: string;
|
|
915
|
-
/**
|
|
912
|
+
/** Events overlapping `start`–`end` (inclusive, `YYYY-MM-DD`). Called on every render: filter in the database. */
|
|
916
913
|
abstract getEvents(range: {
|
|
917
914
|
start: string;
|
|
918
915
|
end: string;
|
|
919
916
|
view: CalendarView;
|
|
920
917
|
}): CalendarEvent[] | Promise<CalendarEvent[]>;
|
|
921
|
-
/**
|
|
918
|
+
/** Available views; the first is the initial one. With a single view, the switcher is hidden. */
|
|
922
919
|
getViews(): CalendarView[];
|
|
923
|
-
/** 0 =
|
|
920
|
+
/** 0 = Sunday, 1 = Monday… */
|
|
924
921
|
getFirstDayOfWeek(): number;
|
|
925
|
-
/**
|
|
922
|
+
/** Locale for month and day names (`Intl`). */
|
|
926
923
|
getLocale(): string;
|
|
927
924
|
getLabels(): CalendarLabels;
|
|
928
|
-
/**
|
|
925
|
+
/** In month view, beyond this number the cell shows "+N more" (which opens the list on that day). */
|
|
929
926
|
getMaxEventsPerDay(): number;
|
|
930
927
|
getHeading(): string | null;
|
|
931
|
-
/**
|
|
928
|
+
/** Today's date, `YYYY-MM-DD` (UTC by default; override for another time zone). */
|
|
932
929
|
getToday(): string;
|
|
933
|
-
/**
|
|
930
|
+
/** Click on a day number. Overriding this makes days clickable: open a page (`this.redirect`), notify, switch view… */
|
|
934
931
|
onDateClick(_date: string): void | Promise<void>;
|
|
935
|
-
/**
|
|
932
|
+
/** Click on an event without a URL. The event is reloaded server-side, so `event.extra` is available. */
|
|
936
933
|
onEventClick(_event: CalendarEvent): void | Promise<void>;
|
|
937
|
-
/** HTML
|
|
934
|
+
/** Already-escaped HTML for an event, or `null` for the default rendering (`renderCalendarEvent`). */
|
|
938
935
|
renderEvent(_event: CalendarEvent, _context: {
|
|
939
936
|
day: string;
|
|
940
937
|
view: CalendarView;
|
|
941
938
|
}): string | null;
|
|
942
|
-
/** HTML
|
|
939
|
+
/** Already-escaped HTML appended to the bottom of each cell. */
|
|
943
940
|
renderDayFooter(_day: string, _events: CalendarEvent[]): string;
|
|
944
|
-
/** HTML
|
|
941
|
+
/** Already-escaped HTML at the end of the toolbar: a "New" link, a filter… */
|
|
945
942
|
renderToolbarEnd(): string;
|
|
946
|
-
/**
|
|
943
|
+
/** Extra classes on the calendar, to hook your styles or override its CSS variables. */
|
|
947
944
|
getExtraClasses(): string[];
|
|
948
|
-
/**
|
|
945
|
+
/** CSS variables set on the calendar: `{ '--nv-cal-day-min-height': '9rem' }`. */
|
|
949
946
|
getStyle(): Record<string, string>;
|
|
950
947
|
private anchor;
|
|
951
948
|
private currentView;
|
|
@@ -954,30 +951,30 @@ export declare abstract class CalendarWidget extends Widget {
|
|
|
954
951
|
nextPeriod(): void;
|
|
955
952
|
goToToday(): void;
|
|
956
953
|
setView(view: unknown): void;
|
|
957
|
-
/**
|
|
954
|
+
/** "+N more": the list view anchored on that day (or the week view if list is not available). */
|
|
958
955
|
showDay(date: unknown): void;
|
|
959
956
|
private datesClickable;
|
|
960
957
|
private eventsClickable;
|
|
961
958
|
selectDate(date: unknown): Promise<void>;
|
|
962
|
-
/**
|
|
959
|
+
/** The id comes from the browser: the event is looked up among those of the displayed period, never trusted as-is. */
|
|
963
960
|
selectEvent(id: unknown): Promise<void>;
|
|
964
961
|
render(): Promise<string>;
|
|
965
962
|
}
|
|
966
963
|
/**
|
|
967
|
-
*
|
|
968
|
-
*
|
|
964
|
+
* Calendar page: the same calendar as `CalendarWidget`, on a full page, with actions — so modals, forms,
|
|
965
|
+
* confirmations and slide-overs.
|
|
969
966
|
*
|
|
970
967
|
* class Planning extends CalendarPage {
|
|
971
968
|
* static slug = 'planning';
|
|
972
969
|
* async getEvents({ start, end }) { return db('shifts').where('day', '>=', start).where('day', '<=', end)… }
|
|
973
|
-
* //
|
|
970
|
+
* // Day click: a modal with a form, prefilled with the date.
|
|
974
971
|
* dateAction() {
|
|
975
972
|
* return Action.make('createShift').modalHeading('New shift')
|
|
976
973
|
* .schema([Select.make('employee_id').options(…).required(), DatePicker.make('day').required()])
|
|
977
974
|
* .fillForm(({ arguments: args }) => ({ day: CalendarPage.dateOf(args) }))
|
|
978
975
|
* .action(async ({ data }) => { await db('shifts').insert(data); Notification.make().success().title('Saved').send(); });
|
|
979
976
|
* }
|
|
980
|
-
* //
|
|
977
|
+
* // Event click: another action; the event is reloaded server-side.
|
|
981
978
|
* eventAction() {
|
|
982
979
|
* return Action.make('editShift').schema([…])
|
|
983
980
|
* .fillForm(async ({ livewire, arguments: args }) => (await livewire.findEvent(args.event))?.extra ?? {})
|
|
@@ -985,10 +982,10 @@ export declare abstract class CalendarWidget extends Widget {
|
|
|
985
982
|
* }
|
|
986
983
|
* }
|
|
987
984
|
*
|
|
988
|
-
*
|
|
989
|
-
*
|
|
990
|
-
*
|
|
991
|
-
* `getCalendarActions()`
|
|
985
|
+
* Three ways to handle a click: a **URL** on the event (`url`: dedicated page), an **action** (modal),
|
|
986
|
+
* or **custom code** by overriding `onDateClick()` / `onEventClick()` (redirect, notify, write to the database, mount any
|
|
987
|
+
* action with `this.mountAction(name, arguments)`). `getHeaderActions()` adds buttons to the page header, and
|
|
988
|
+
* `getCalendarActions()` declares other actions mountable from your own rendering (`renderEvent`, `renderToolbarEnd`).
|
|
992
989
|
*/
|
|
993
990
|
export declare abstract class CalendarPage extends Page {
|
|
994
991
|
static callable: string[];
|
|
@@ -1015,19 +1012,19 @@ export declare abstract class CalendarPage extends Page {
|
|
|
1015
1012
|
renderToolbarEnd(): string;
|
|
1016
1013
|
getExtraClasses(): string[];
|
|
1017
1014
|
getStyle(): Record<string, string>;
|
|
1018
|
-
/** Action
|
|
1015
|
+
/** Action opened on day click; it receives `arguments.date`. `null`: days are not clickable (unless `onDateClick` is overridden). */
|
|
1019
1016
|
dateAction(): Action | null;
|
|
1020
|
-
/** Action
|
|
1017
|
+
/** Action opened on click on an event without a URL; it receives `arguments.event` (an id, to resolve with `findEvent`). */
|
|
1021
1018
|
eventAction(): Action | null;
|
|
1022
|
-
/**
|
|
1019
|
+
/** Other actions mountable from your own HTML: `wire:click="mountAction('name', { … })"`. */
|
|
1023
1020
|
getCalendarActions(): Action[];
|
|
1024
|
-
/**
|
|
1021
|
+
/** Opens `dateAction()` by default. Override to do something else (e.g. redirect to a create page). */
|
|
1025
1022
|
onDateClick(date: string): Promise<void>;
|
|
1026
|
-
/**
|
|
1023
|
+
/** Opens `eventAction()` by default. The event has been resolved server-side before the call. */
|
|
1027
1024
|
onEventClick(event: CalendarEvent): Promise<void>;
|
|
1028
|
-
/**
|
|
1025
|
+
/** Clicked date, read from an action's arguments. They come from the browser: only a valid date is returned. */
|
|
1029
1026
|
static dateOf(args: Record<string, unknown> | null | undefined): string | null;
|
|
1030
|
-
/**
|
|
1027
|
+
/** Event of the displayed period with this id, or `null`. Never act on a received id without going through this. */
|
|
1031
1028
|
findEvent(id: unknown): Promise<CalendarEvent | null>;
|
|
1032
1029
|
protected getMountableActions(context: Record<string, unknown>): Promise<Action[]>;
|
|
1033
1030
|
private firstDay;
|
|
@@ -1045,12 +1042,12 @@ export declare abstract class CalendarPage extends Page {
|
|
|
1045
1042
|
selectEvent(id: unknown): Promise<void>;
|
|
1046
1043
|
protected renderContent(): Promise<string>;
|
|
1047
1044
|
}
|
|
1048
|
-
/**
|
|
1045
|
+
/** Signed-in user's account: avatar, name, logout. */
|
|
1049
1046
|
export declare class AccountWidget extends Widget {
|
|
1050
1047
|
static isLazy: boolean;
|
|
1051
1048
|
render(): string;
|
|
1052
1049
|
}
|
|
1053
|
-
/**
|
|
1050
|
+
/** Navette version and useful links. */
|
|
1054
1051
|
export declare class NavetteInfoWidget extends Widget {
|
|
1055
1052
|
static isLazy: boolean;
|
|
1056
1053
|
static homeUrl: string;
|
|
@@ -1059,7 +1056,7 @@ export declare class NavetteInfoWidget extends Widget {
|
|
|
1059
1056
|
static version: string;
|
|
1060
1057
|
render(): string;
|
|
1061
1058
|
}
|
|
1062
|
-
/**
|
|
1059
|
+
/** One stat of a StatsOverviewWidget. */
|
|
1063
1060
|
export declare class Stat {
|
|
1064
1061
|
private _description;
|
|
1065
1062
|
private _descriptionIcon;
|
|
@@ -1074,79 +1071,79 @@ export declare class Stat {
|
|
|
1074
1071
|
static make(label: string, value: string | number | null): Stat;
|
|
1075
1072
|
description(text: string | null): this;
|
|
1076
1073
|
descriptionIcon(name: string | null, position?: 'before' | 'after'): this;
|
|
1077
|
-
/**
|
|
1074
|
+
/** Color of the description and chart. */
|
|
1078
1075
|
color(color: string | null): this;
|
|
1079
1076
|
icon(name: string | null): this;
|
|
1080
|
-
/**
|
|
1077
|
+
/** Trend chart: a list of values, or values keyed by label. */
|
|
1081
1078
|
chart(values: Record<string, number> | number[] | null): this;
|
|
1082
1079
|
url(url: string | null): this;
|
|
1083
1080
|
hasChart(): boolean;
|
|
1084
1081
|
toHtml(panel: Panel, key: string): string;
|
|
1085
1082
|
}
|
|
1086
|
-
/**
|
|
1083
|
+
/** A row of stats. */
|
|
1087
1084
|
export declare abstract class StatsOverviewWidget extends Widget {
|
|
1088
1085
|
static columnSpan: ColumnSpan;
|
|
1089
|
-
/**
|
|
1086
|
+
/** Polling interval, or `null` to disable polling. */
|
|
1090
1087
|
static pollingInterval: string | null;
|
|
1091
1088
|
abstract getStats(): Stat[] | Promise<Stat[]>;
|
|
1092
|
-
/**
|
|
1089
|
+
/** Row columns: three, or four when the number of stats fits better. */
|
|
1093
1090
|
protected getColumns(count: number): number;
|
|
1094
1091
|
render(): Promise<string>;
|
|
1095
1092
|
}
|
|
1096
|
-
/**
|
|
1093
|
+
/** Chart data in Chart.js format: `{ datasets: [{ label, data, … }], labels: [...] }`. */
|
|
1097
1094
|
export type ChartData = {
|
|
1098
1095
|
datasets?: Record<string, unknown>[];
|
|
1099
1096
|
labels?: unknown[];
|
|
1100
1097
|
[key: string]: unknown;
|
|
1101
1098
|
};
|
|
1102
1099
|
/**
|
|
1103
|
-
*
|
|
1104
|
-
* `'
|
|
1105
|
-
*
|
|
1100
|
+
* Chart.js chart. A subclass provides `getType()` (`'line'`, `'bar'`, `'pie'`, `'doughnut'`, `'radar'`, `'polarArea'`,
|
|
1101
|
+
* `'scatter'`, `'bubble'`) and `getData()`. Rendering happens in the browser; the server only sends new data when it
|
|
1102
|
+
* has changed (checksum).
|
|
1106
1103
|
*/
|
|
1107
1104
|
export declare abstract class ChartWidget extends Widget {
|
|
1108
1105
|
static callable: string[];
|
|
1109
1106
|
static locked: string[];
|
|
1110
|
-
/**
|
|
1107
|
+
/** Polling interval, or `null` to disable polling. */
|
|
1111
1108
|
static pollingInterval: string | null;
|
|
1112
1109
|
static heading: string | null;
|
|
1113
1110
|
static description: string | null;
|
|
1114
|
-
/**
|
|
1111
|
+
/** Color of datasets that do not set one. */
|
|
1115
1112
|
static color: string;
|
|
1116
|
-
/**
|
|
1113
|
+
/** Maximum chart height (`'300px'`). */
|
|
1117
1114
|
static maxHeight: string | null;
|
|
1118
1115
|
static isCollapsible: boolean;
|
|
1119
1116
|
dataChecksum: string | null;
|
|
1120
|
-
/**
|
|
1117
|
+
/** Selected filter, one of `getFilters()`. */
|
|
1121
1118
|
filter: string | null;
|
|
1122
1119
|
private _cachedData;
|
|
1123
1120
|
abstract getType(): string;
|
|
1124
1121
|
getData(): ChartData | Promise<ChartData>;
|
|
1125
|
-
/**
|
|
1122
|
+
/** Chart.js options. */
|
|
1126
1123
|
getOptions(): Record<string, unknown> | null;
|
|
1127
|
-
/**
|
|
1124
|
+
/** Filters offered in the header: value → label. */
|
|
1128
1125
|
getFilters(): Record<string, string> | null;
|
|
1129
1126
|
getHeading(): string | null;
|
|
1130
1127
|
getDescription(): string | null;
|
|
1131
1128
|
getColor(): string;
|
|
1132
1129
|
getMaxHeight(): string | null;
|
|
1133
|
-
/**
|
|
1130
|
+
/** Text read by screen readers instead of the chart. */
|
|
1134
1131
|
getChartAssistiveContent(): string | null;
|
|
1135
1132
|
protected getCachedData(): Promise<ChartData>;
|
|
1136
1133
|
protected generateDataChecksum(): Promise<string>;
|
|
1137
1134
|
mount(): Promise<void>;
|
|
1138
|
-
/**
|
|
1135
|
+
/** Called by polling and before each render: only emits data when it has changed. */
|
|
1139
1136
|
updateChartData(): Promise<void>;
|
|
1140
1137
|
render(): Promise<string>;
|
|
1141
1138
|
}
|
|
1142
1139
|
/**
|
|
1143
|
-
* Table
|
|
1144
|
-
*
|
|
1140
|
+
* Table in a widget: search, sort, simple pagination (previous / next).
|
|
1141
|
+
* A subclass provides `table(table)` and `getDataAdapterForTable()`. No actions or filters yet.
|
|
1145
1142
|
*/
|
|
1146
1143
|
export declare abstract class TableWidget extends Widget implements TableHost {
|
|
1147
1144
|
static columnSpan: ColumnSpan;
|
|
1148
1145
|
static callable: string[];
|
|
1149
|
-
/**
|
|
1146
|
+
/** Table heading; derived from the class name by default (`FlaggedOrders` → "Flagged Orders"). */
|
|
1150
1147
|
static heading: string | null;
|
|
1151
1148
|
tableSearch: string;
|
|
1152
1149
|
tableSort: string | null;
|
|
@@ -1172,14 +1169,14 @@ export declare abstract class TableWidget extends Widget implements TableHost {
|
|
|
1172
1169
|
updatedTableSort(): void;
|
|
1173
1170
|
render(): Promise<string>;
|
|
1174
1171
|
}
|
|
1175
|
-
/**
|
|
1172
|
+
/** For widgets that receive the dashboard filters: `static reactive = PAGE_FILTERS` plus a `pageFilters` property. */
|
|
1176
1173
|
export declare const PAGE_FILTERS: string[];
|
|
1177
1174
|
/**
|
|
1178
|
-
*
|
|
1179
|
-
*
|
|
1175
|
+
* Stats widget bound to a list page's table: it receives the table state (search, filters, tab…)
|
|
1176
|
+
* and can aggregate exactly the records the table displays.
|
|
1180
1177
|
*/
|
|
1181
1178
|
export declare abstract class PageTableStatsWidget extends StatsOverviewWidget {
|
|
1182
|
-
/**
|
|
1179
|
+
/** List page whose table is observed. */
|
|
1183
1180
|
static tablePage: () => typeof ListRecords;
|
|
1184
1181
|
static reactive: string[];
|
|
1185
1182
|
activeTab: string | null;
|
|
@@ -1189,7 +1186,7 @@ export declare abstract class PageTableStatsWidget extends StatsOverviewWidget {
|
|
|
1189
1186
|
tableRecordsPerPage: number;
|
|
1190
1187
|
tableSearch: string;
|
|
1191
1188
|
tableSort: string | null;
|
|
1192
|
-
/**
|
|
1189
|
+
/** Aggregates over the table's current query. The received state goes through the same validation as on the page. */
|
|
1193
1190
|
protected aggregatePageTable(columns?: {
|
|
1194
1191
|
sum?: string[];
|
|
1195
1192
|
avg?: string[];
|
|
@@ -1198,7 +1195,7 @@ export declare abstract class PageTableStatsWidget extends StatsOverviewWidget {
|
|
|
1198
1195
|
sum: Record<string, number>;
|
|
1199
1196
|
avg: Record<string, number>;
|
|
1200
1197
|
}>;
|
|
1201
|
-
/**
|
|
1198
|
+
/** Monthly trend over the table's current query (see `ObjectionAdapter.trendPerMonth`). */
|
|
1202
1199
|
protected trendPageTable(options: {
|
|
1203
1200
|
start: Date;
|
|
1204
1201
|
end: Date;
|
|
@@ -1207,12 +1204,12 @@ export declare abstract class PageTableStatsWidget extends StatsOverviewWidget {
|
|
|
1207
1204
|
modify?: (query: any) => void;
|
|
1208
1205
|
}): Promise<number[]>;
|
|
1209
1206
|
}
|
|
1210
|
-
/**
|
|
1207
|
+
/** Schema component that embeds the host component's table. */
|
|
1211
1208
|
export declare class EmbeddedTable extends SchemaComponent {
|
|
1212
1209
|
static make(): EmbeddedTable;
|
|
1213
1210
|
toHtml(): Promise<string>;
|
|
1214
1211
|
}
|
|
1215
|
-
/**
|
|
1212
|
+
/** List page tab: restricts the table query and can show a badge. */
|
|
1216
1213
|
export declare class Tab {
|
|
1217
1214
|
private _label;
|
|
1218
1215
|
private _badge;
|
|
@@ -1221,7 +1218,7 @@ export declare class Tab {
|
|
|
1221
1218
|
private _query;
|
|
1222
1219
|
constructor(label?: string | null);
|
|
1223
1220
|
static make(label?: string | null): Tab;
|
|
1224
|
-
/**
|
|
1221
|
+
/** Badge computed after the page is displayed. */
|
|
1225
1222
|
badge(resolver: () => number | string | null | Promise<number | string | null>): this;
|
|
1226
1223
|
badgeColor(color: string): this;
|
|
1227
1224
|
query(modifier: (query: any) => void): this;
|
|
@@ -1229,11 +1226,11 @@ export declare class Tab {
|
|
|
1229
1226
|
hasBadge(): boolean;
|
|
1230
1227
|
getBadge(): Promise<number | string | null>;
|
|
1231
1228
|
getBadgeColor(): string;
|
|
1232
|
-
/**
|
|
1229
|
+
/** False until `badgeColor()` is called: a lazy-loaded badge then gets no color class. */
|
|
1233
1230
|
hasBadgeColor(): boolean;
|
|
1234
1231
|
getQuery(): ((query: any) => void) | null;
|
|
1235
1232
|
}
|
|
1236
|
-
/**
|
|
1233
|
+
/** Resource list page: table state and methods called by the browser. */
|
|
1237
1234
|
export declare class ListRecords extends Page implements TableHost {
|
|
1238
1235
|
static callable: string[];
|
|
1239
1236
|
static resource: typeof Resource;
|
|
@@ -1249,20 +1246,20 @@ export declare class ListRecords extends Page implements TableHost {
|
|
|
1249
1246
|
tableDeferredFilters: Record<string, FilterState>;
|
|
1250
1247
|
tableColumns: ColumnState[];
|
|
1251
1248
|
isTableReordering: boolean;
|
|
1252
|
-
/**
|
|
1249
|
+
/** Current table grouping (`id:direction`), chosen in the toolbar. */
|
|
1253
1250
|
tableGrouping: string | null;
|
|
1254
1251
|
updatedTableGrouping(): void;
|
|
1255
|
-
/**
|
|
1252
|
+
/** Toggles manual reordering mode. */
|
|
1256
1253
|
toggleTableReordering(): Promise<void>;
|
|
1257
|
-
/**
|
|
1254
|
+
/** Saves the new order: only keys belonging to the table are kept, each gets its position. */
|
|
1258
1255
|
reorderTable(order: unknown, _draggedRecordKey?: unknown): Promise<void>;
|
|
1259
1256
|
mount(_params?: Record<string, unknown>): Promise<void>;
|
|
1260
|
-
/**
|
|
1257
|
+
/** Filters form: one group per filter, bound to `tableDeferredFilters.<filter>`. */
|
|
1261
1258
|
tableFiltersFormSchema(schema: Schema): Schema;
|
|
1262
1259
|
applyTableFilters(): void;
|
|
1263
|
-
/**
|
|
1260
|
+
/** Removes an active filter indicator: the field is cleared from both the applied state and the form. */
|
|
1264
1261
|
removeTableFilter(filterName: unknown, field?: unknown): void;
|
|
1265
|
-
/**
|
|
1262
|
+
/** Live field in the filters form (e.g. a rule's operator changed): runs its `afterStateUpdated`. */
|
|
1266
1263
|
updatedTableDeferredFilters(_value: unknown, key: string | null): Promise<void>;
|
|
1267
1264
|
resetTableFiltersForm(): void;
|
|
1268
1265
|
removeTableFilters(): void;
|
|
@@ -1270,7 +1267,7 @@ export declare class ListRecords extends Page implements TableHost {
|
|
|
1270
1267
|
resetTableColumnManager(): void;
|
|
1271
1268
|
activeTab: string | null;
|
|
1272
1269
|
getTabs(): Record<string, Tab>;
|
|
1273
|
-
/**
|
|
1270
|
+
/** Active tab, coerced to a declared key (an unknown value from the browser means the default tab). */
|
|
1274
1271
|
getActiveTabKey(): string;
|
|
1275
1272
|
updatedActiveTab(): void;
|
|
1276
1273
|
modifyTableQuery(query: {
|
|
@@ -1278,27 +1275,27 @@ export declare class ListRecords extends Page implements TableHost {
|
|
|
1278
1275
|
}): void;
|
|
1279
1276
|
get resource(): typeof Resource;
|
|
1280
1277
|
getHeaderWidgets(): (typeof Widget)[];
|
|
1281
|
-
/**
|
|
1278
|
+
/** The table state is passed to widgets, which can rerun the same query. */
|
|
1282
1279
|
getWidgetData(): Record<string, unknown>;
|
|
1283
1280
|
protected rendersActionModalsInPage(): boolean;
|
|
1284
1281
|
getBulkActions(): Action[];
|
|
1285
|
-
/**
|
|
1282
|
+
/** Row actions declared by the table, with groups flattened. */
|
|
1286
1283
|
getRecordActions(): Action[];
|
|
1287
1284
|
protected getMountableActions(context: Record<string, unknown>): Action[] | Promise<Action[]>;
|
|
1288
|
-
/**
|
|
1285
|
+
/** Only known context shapes are kept; the record key is checked again in the database on mount. */
|
|
1289
1286
|
protected resolveMountContext(clientContext: unknown): Record<string, unknown>;
|
|
1290
1287
|
protected resolveActionRecord(context: Record<string, unknown>): Promise<unknown>;
|
|
1291
1288
|
/**
|
|
1292
|
-
*
|
|
1293
|
-
*
|
|
1289
|
+
* Writes an editable cell. Everything comes from the browser: the column must exist and be editable and visible, the record
|
|
1290
|
+
* must be in the table's scope and editable by the user, and the value must be valid.
|
|
1294
1291
|
*/
|
|
1295
1292
|
updateTableColumnState(columnName: unknown, recordKey: unknown, input: unknown): Promise<unknown>;
|
|
1296
|
-
/**
|
|
1293
|
+
/** Selected keys: the sent list, or, in "select all" mode, every record of the current query except deselected ones. */
|
|
1297
1294
|
getSelectedRecordKeys(): Promise<string[]>;
|
|
1298
1295
|
deselectAllTableRecords(): void;
|
|
1299
1296
|
getTable(): Table;
|
|
1300
1297
|
renderTable(): Promise<string>;
|
|
1301
|
-
/**
|
|
1298
|
+
/** Table header actions (none on a list page: they go in the page header). */
|
|
1302
1299
|
protected renderTableHeaderActions(ctx: any): Promise<string[]>;
|
|
1303
1300
|
sortTable(column?: string | null, direction?: string | null): void;
|
|
1304
1301
|
gotoPage(page: number, _pageName?: string): void;
|
|
@@ -1319,77 +1316,77 @@ export declare class ListRecords extends Page implements TableHost {
|
|
|
1319
1316
|
contentSchema(schema: Schema): Schema;
|
|
1320
1317
|
}
|
|
1321
1318
|
/**
|
|
1322
|
-
* Table
|
|
1323
|
-
*
|
|
1319
|
+
* Table of records related to another one: a child component of the edit page, loaded when it becomes visible.
|
|
1320
|
+
* Subclasses declare `relationship`, `adapterFor()`, `table()` and `form()`.
|
|
1324
1321
|
*/
|
|
1325
1322
|
export declare class RelationManager extends ListRecords {
|
|
1326
1323
|
static relationship: string;
|
|
1327
1324
|
static modelLabel: string;
|
|
1328
1325
|
static pluralModelLabel: string | null;
|
|
1329
1326
|
static recordTitleAttribute: string | null;
|
|
1330
|
-
/**
|
|
1327
|
+
/** Data adapter limited to records related to the given owner. */
|
|
1331
1328
|
static adapterFor(_ownerKey: string): DataAdapter;
|
|
1332
|
-
/**
|
|
1329
|
+
/** Policy for related records (same abilities as a resource policy). */
|
|
1333
1330
|
static policy: Policy | null;
|
|
1334
1331
|
protected isAccessAuthorized(ctx: PanelContext): Promise<boolean>;
|
|
1335
1332
|
static table(table: Table): Table;
|
|
1336
1333
|
static form(schema: Schema): Schema;
|
|
1337
1334
|
static getTitle(): string;
|
|
1338
|
-
/**
|
|
1335
|
+
/** Owner record key: set on mount by the page, never writable from the browser. */
|
|
1339
1336
|
ownerRecord: string;
|
|
1340
1337
|
static locked: string[];
|
|
1341
1338
|
_facade: any;
|
|
1342
|
-
/**
|
|
1339
|
+
/** What ListRecords expects from a resource, provided here by the relation manager. */
|
|
1343
1340
|
get resource(): any;
|
|
1344
1341
|
getTable(): Table;
|
|
1345
|
-
/**
|
|
1342
|
+
/** Attaches an existing record to the owner. */
|
|
1346
1343
|
static attach(_ownerKey: string, _recordKey: string): Promise<void>;
|
|
1347
|
-
/**
|
|
1344
|
+
/** Detaches records from the owner without deleting them. */
|
|
1348
1345
|
static detach(_ownerKey: string, _recordKeys: string[]): Promise<void>;
|
|
1349
|
-
/**
|
|
1346
|
+
/** Attachable records matching the search: [key, label]. */
|
|
1350
1347
|
static searchAttachable(_ownerKey: string, _search: string): Promise<[string, string][]>;
|
|
1351
|
-
/**
|
|
1348
|
+
/** Label of an attachable record, or `null` if it is not attachable (also used as validation). */
|
|
1352
1349
|
static attachableLabel(_ownerKey: string, _recordKey: string): Promise<string | null>;
|
|
1353
1350
|
getHeaderActions(): Action[];
|
|
1354
1351
|
placeholder(): string;
|
|
1355
|
-
/**
|
|
1352
|
+
/** A relation manager has its own render hook locations, not the list page's. */
|
|
1356
1353
|
contentSchema(schema: Schema): Schema;
|
|
1357
1354
|
render(): Promise<string>;
|
|
1358
1355
|
}
|
|
1359
1356
|
/**
|
|
1360
|
-
* Page
|
|
1361
|
-
*
|
|
1357
|
+
* Page listing records related to a record: a table, with create, view and edit in modals.
|
|
1358
|
+
* Declared in the owner resource's `static relatedPages`, it is served at `<slug>/{record}/<name>`.
|
|
1362
1359
|
*/
|
|
1363
1360
|
export declare class ManageRelatedRecords extends ListRecords {
|
|
1364
|
-
/**
|
|
1361
|
+
/** Owner resource: set when the page is registered. */
|
|
1365
1362
|
static parentResource: typeof Resource;
|
|
1366
1363
|
static relationship: string;
|
|
1367
1364
|
static modelLabel: string;
|
|
1368
1365
|
static pluralModelLabel: string | null;
|
|
1369
1366
|
static recordTitleAttribute: string | null;
|
|
1370
1367
|
static policy: Policy | null;
|
|
1371
|
-
/**
|
|
1368
|
+
/** Data adapter limited to records related to the given owner. */
|
|
1372
1369
|
static adapterFor(_ownerKey: string): DataAdapter;
|
|
1373
1370
|
static table(table: Table): Table;
|
|
1374
1371
|
static form(schema: Schema): Schema;
|
|
1375
1372
|
static infolist(schema: Schema): Schema;
|
|
1376
1373
|
static getTitle(): string;
|
|
1377
1374
|
static getNavigationLabel(): string;
|
|
1378
|
-
/**
|
|
1375
|
+
/** Owner record key: read from the URL on mount, never writable from the browser. */
|
|
1379
1376
|
recordKey: string;
|
|
1380
1377
|
static locked: string[];
|
|
1381
1378
|
_owner: any;
|
|
1382
1379
|
_facade: any;
|
|
1383
1380
|
private get related();
|
|
1384
1381
|
mount(params: Record<string, unknown>): Promise<void>;
|
|
1385
|
-
/**
|
|
1382
|
+
/** The owner is reloaded and access to it checked on every request. */
|
|
1386
1383
|
hydrate(): Promise<void>;
|
|
1387
1384
|
getRecordKey(): string | null;
|
|
1388
|
-
/**
|
|
1385
|
+
/** What ListRecords expects from a resource, provided here by the page. */
|
|
1389
1386
|
get resource(): any;
|
|
1390
1387
|
getTable(): Table;
|
|
1391
1388
|
getHeaderActions(): Action[];
|
|
1392
|
-
/**
|
|
1389
|
+
/** The page content is a group (tabs, if any, then the table). */
|
|
1393
1390
|
contentSchema(schema: Schema): Schema;
|
|
1394
1391
|
getTitle(): string;
|
|
1395
1392
|
getSubNavigation(): SubNavigationItem[];
|
|
@@ -1399,9 +1396,9 @@ export declare class ManageRelatedRecords extends ListRecords {
|
|
|
1399
1396
|
}[];
|
|
1400
1397
|
getPageClasses(): string[];
|
|
1401
1398
|
}
|
|
1402
|
-
/** Base
|
|
1399
|
+
/** Base class for a resource's form pages. */
|
|
1403
1400
|
declare abstract class ResourceFormPage extends Page {
|
|
1404
|
-
/**
|
|
1401
|
+
/** Live form field (`live()` + `afterStateUpdated()`): `set(name, value)` writes next to the updated field. */
|
|
1405
1402
|
updatedData(_value: unknown, key: string | null): Promise<void>;
|
|
1406
1403
|
static resource: typeof Resource;
|
|
1407
1404
|
data: Record<string, unknown>;
|
|
@@ -1412,26 +1409,26 @@ declare abstract class ResourceFormPage extends Page {
|
|
|
1412
1409
|
abstract getSubmitMethod(): string;
|
|
1413
1410
|
abstract getFormActions(): Action[];
|
|
1414
1411
|
protected getRecord(): unknown;
|
|
1415
|
-
/**
|
|
1412
|
+
/** Two columns from `lg` by default; the resource may decide otherwise. */
|
|
1416
1413
|
formSchema(schema: Schema): Schema;
|
|
1417
1414
|
/**
|
|
1418
|
-
*
|
|
1419
|
-
*
|
|
1415
|
+
* Wizard steps: as soon as this method returns some, the page shows its form step by step,
|
|
1416
|
+
* with "Back" / "Next" and the submit button on the last step.
|
|
1420
1417
|
*/
|
|
1421
1418
|
protected getSteps(): Step[] | null;
|
|
1422
|
-
/**
|
|
1419
|
+
/** `true`: steps can be visited in any order, without validation along the way. */
|
|
1423
1420
|
protected hasSkippableSteps(): boolean;
|
|
1424
|
-
/**
|
|
1421
|
+
/** Step shown on open (1-based). */
|
|
1425
1422
|
protected getStartStep(): number;
|
|
1426
1423
|
protected getWizardComponent(steps: Step[]): Wizard;
|
|
1427
1424
|
contentSchema(schema: Schema): Schema;
|
|
1428
|
-
/**
|
|
1425
|
+
/** Where "Cancel" goes when the browser has no history: the list page, unless the page decides otherwise. */
|
|
1429
1426
|
protected getCancelUrl(): string;
|
|
1430
1427
|
protected cancelAction(): Action;
|
|
1431
|
-
/**
|
|
1428
|
+
/** Validates the form; on error, sets the errors on the component and notifies the browser. */
|
|
1432
1429
|
protected validateForm(): Promise<boolean>;
|
|
1433
1430
|
}
|
|
1434
|
-
/**
|
|
1431
|
+
/** Record creation page. */
|
|
1435
1432
|
export declare class CreateRecord extends ResourceFormPage {
|
|
1436
1433
|
static callable: string[];
|
|
1437
1434
|
mount(): void;
|
|
@@ -1444,81 +1441,81 @@ export declare class CreateRecord extends ResourceFormPage {
|
|
|
1444
1441
|
}[];
|
|
1445
1442
|
getPageClasses(): string[];
|
|
1446
1443
|
getFormActions(): Action[];
|
|
1447
|
-
/**
|
|
1444
|
+
/** Transforms validated data before creation (add the author, compute a field…). */
|
|
1448
1445
|
protected mutateFormDataBeforeCreate(data: Record<string, unknown>): Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
1449
|
-
/**
|
|
1446
|
+
/** Right before creation; throwing cancels it. */
|
|
1450
1447
|
protected beforeCreate(_data: Record<string, unknown>): void | Promise<void>;
|
|
1451
|
-
/**
|
|
1448
|
+
/** The creation itself; defaults to the resource's data adapter. */
|
|
1452
1449
|
protected handleRecordCreation(data: Record<string, unknown>): Promise<any>;
|
|
1453
|
-
/**
|
|
1450
|
+
/** After creation (logging, sending a message…). */
|
|
1454
1451
|
protected afterCreate(_record: any): void | Promise<void>;
|
|
1455
|
-
/**
|
|
1452
|
+
/** Where to go next; defaults to the new record's edit page. */
|
|
1456
1453
|
protected getRedirectUrl(record: any): string;
|
|
1457
|
-
/**
|
|
1454
|
+
/** Success notification title; `null` to show nothing. */
|
|
1458
1455
|
protected getCreatedNotificationTitle(): string | null;
|
|
1459
1456
|
create(another?: boolean): Promise<void>;
|
|
1460
1457
|
createAnother(): Promise<void>;
|
|
1461
1458
|
}
|
|
1462
|
-
/**
|
|
1459
|
+
/** Delete action with confirmation. */
|
|
1463
1460
|
export declare class DeleteAction {
|
|
1464
|
-
/**
|
|
1461
|
+
/** On an edit page, deletes the page's record and returns to the list. On a table row, deletes the row. */
|
|
1465
1462
|
static make(): Action;
|
|
1466
1463
|
}
|
|
1467
|
-
/**
|
|
1464
|
+
/** Replicate action: an `Action` with a list of attributes not to copy. */
|
|
1468
1465
|
export type ReplicateActionInstance = Action & {
|
|
1469
1466
|
excludeAttributes(attributes: string[]): ReplicateActionInstance;
|
|
1470
1467
|
};
|
|
1471
|
-
/**
|
|
1468
|
+
/** Duplicates a table row: the copy takes the record's attributes, except its key, timestamps and excluded ones. */
|
|
1472
1469
|
export declare class ReplicateAction {
|
|
1473
1470
|
static make(): ReplicateActionInstance;
|
|
1474
1471
|
}
|
|
1475
|
-
/**
|
|
1472
|
+
/** Create in a modal with the resource form. */
|
|
1476
1473
|
export declare class CreateAction {
|
|
1477
|
-
/**
|
|
1474
|
+
/** Without an argument, the resource (or relation manager) is the host component's. */
|
|
1478
1475
|
static make(resource?: typeof Resource | null): Action;
|
|
1479
1476
|
}
|
|
1480
|
-
/**
|
|
1477
|
+
/** Edit a table row in a modal, with the resource form. */
|
|
1481
1478
|
export declare class EditAction {
|
|
1482
|
-
/**
|
|
1479
|
+
/** Without an argument, the resource (or relation manager) is the host component's. */
|
|
1483
1480
|
static make(resource?: typeof Resource | null): Action;
|
|
1484
1481
|
}
|
|
1485
|
-
/**
|
|
1482
|
+
/** Link to the record's view page (when the resource has one). */
|
|
1486
1483
|
export declare class ViewAction {
|
|
1487
1484
|
static make(resource?: typeof Resource | null): Action;
|
|
1488
1485
|
}
|
|
1489
|
-
/**
|
|
1486
|
+
/** Attaches an existing record to a relation manager's owner. */
|
|
1490
1487
|
export declare class AttachAction {
|
|
1491
1488
|
static make(): Action;
|
|
1492
1489
|
}
|
|
1493
|
-
/**
|
|
1490
|
+
/** Detaches a row from the owner without deleting it. */
|
|
1494
1491
|
export declare class DetachAction {
|
|
1495
1492
|
static make(): Action;
|
|
1496
1493
|
}
|
|
1497
|
-
/**
|
|
1494
|
+
/** Detaches the selected rows. */
|
|
1498
1495
|
export declare class DetachBulkAction {
|
|
1499
1496
|
static make(): Action;
|
|
1500
1497
|
}
|
|
1501
|
-
/**
|
|
1498
|
+
/** Restores a soft-deleted record. Only visible when the record is deleted. */
|
|
1502
1499
|
export declare class RestoreAction {
|
|
1503
1500
|
static make(): Action;
|
|
1504
1501
|
}
|
|
1505
|
-
/**
|
|
1502
|
+
/** Permanently deletes a soft-deleted record. Only visible when the record is deleted. */
|
|
1506
1503
|
export declare class ForceDeleteAction {
|
|
1507
1504
|
static make(): Action;
|
|
1508
1505
|
}
|
|
1509
|
-
/**
|
|
1506
|
+
/** Deletes the records selected in a table. */
|
|
1510
1507
|
export declare class DeleteBulkAction {
|
|
1511
1508
|
static make(): Action;
|
|
1512
1509
|
}
|
|
1513
|
-
/**
|
|
1510
|
+
/** Record edit page. */
|
|
1514
1511
|
export declare class EditRecord extends ResourceFormPage {
|
|
1515
1512
|
static callable: string[];
|
|
1516
1513
|
recordKey: string;
|
|
1517
|
-
/**
|
|
1514
|
+
/** Active relation manager tab (index in `Resource.relations`). */
|
|
1518
1515
|
activeRelationManager: string;
|
|
1519
1516
|
/**
|
|
1520
|
-
*
|
|
1521
|
-
*
|
|
1517
|
+
* Previous page, captured on first display from the Referer header: only a same-site URL is accepted,
|
|
1518
|
+
* and it cannot be changed afterwards.
|
|
1522
1519
|
*/
|
|
1523
1520
|
previousUrl: string;
|
|
1524
1521
|
protected getCancelUrl(): string;
|
|
@@ -1526,13 +1523,13 @@ export declare class EditRecord extends ResourceFormPage {
|
|
|
1526
1523
|
static locked: string[];
|
|
1527
1524
|
_record: any;
|
|
1528
1525
|
mount(params: Record<string, unknown>): Promise<void>;
|
|
1529
|
-
/**
|
|
1526
|
+
/** The record is reloaded on every request (no route model binding). */
|
|
1530
1527
|
hydrate(): Promise<void>;
|
|
1531
1528
|
protected getRecord(): unknown;
|
|
1532
1529
|
getRecordKey(): string | null;
|
|
1533
1530
|
getActionMountContext(): Record<string, unknown>;
|
|
1534
1531
|
protected getActionRecord(): unknown;
|
|
1535
|
-
/**
|
|
1532
|
+
/** Delete, plus restore and force-delete when the model uses soft deletes. */
|
|
1536
1533
|
getHeaderActions(): Action[];
|
|
1537
1534
|
getOperation(): 'edit';
|
|
1538
1535
|
getSubmitMethod(): string;
|
|
@@ -1544,41 +1541,41 @@ export declare class EditRecord extends ResourceFormPage {
|
|
|
1544
1541
|
getSubNavigation(): SubNavigationItem[];
|
|
1545
1542
|
getPageClasses(): string[];
|
|
1546
1543
|
getFormActions(): Action[];
|
|
1547
|
-
/**
|
|
1544
|
+
/** Transforms the record's values before filling the form. */
|
|
1548
1545
|
protected mutateFormDataBeforeFill(data: Record<string, unknown>): Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
1549
|
-
/**
|
|
1546
|
+
/** Transforms validated data before saving. */
|
|
1550
1547
|
protected mutateFormDataBeforeSave(data: Record<string, unknown>): Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
1551
|
-
/**
|
|
1548
|
+
/** Right before saving; throwing cancels it. */
|
|
1552
1549
|
protected beforeSave(_data: Record<string, unknown>): void | Promise<void>;
|
|
1553
|
-
/**
|
|
1550
|
+
/** The save itself; defaults to the resource's data adapter. */
|
|
1554
1551
|
protected handleRecordUpdate(record: any, data: Record<string, unknown>): Promise<any>;
|
|
1555
|
-
/**
|
|
1552
|
+
/** After saving. */
|
|
1556
1553
|
protected afterSave(_record: any): void | Promise<void>;
|
|
1557
|
-
/**
|
|
1554
|
+
/** URL to go to after saving; `null` (default) stays on the page. */
|
|
1558
1555
|
protected getRedirectUrl(_record: any): string | null;
|
|
1559
|
-
/**
|
|
1556
|
+
/** Success notification title; `null` to show nothing. */
|
|
1560
1557
|
protected getSavedNotificationTitle(): string | null;
|
|
1561
1558
|
save(): Promise<void>;
|
|
1562
1559
|
}
|
|
1563
|
-
/**
|
|
1560
|
+
/** Record view page: the resource's read-only `infolist()` schema. */
|
|
1564
1561
|
export declare class ViewRecord extends Page {
|
|
1565
1562
|
static resource: typeof Resource;
|
|
1566
1563
|
static locked: string[];
|
|
1567
1564
|
recordKey: string;
|
|
1568
|
-
/**
|
|
1565
|
+
/** Active relation manager tab (index in `Resource.relations`). */
|
|
1569
1566
|
activeRelationManager: string;
|
|
1570
1567
|
_record: any;
|
|
1571
1568
|
get resource(): typeof Resource;
|
|
1572
1569
|
getDataAdapter(): DataAdapter;
|
|
1573
1570
|
mount(params: Record<string, unknown>): Promise<void>;
|
|
1574
|
-
/**
|
|
1571
|
+
/** The record is reloaded on every request, as on the edit page. */
|
|
1575
1572
|
hydrate(): Promise<void>;
|
|
1576
1573
|
getRecordKey(): string | null;
|
|
1577
1574
|
getActionMountContext(): Record<string, unknown>;
|
|
1578
1575
|
protected getActionRecord(): unknown;
|
|
1579
1576
|
infolistSchema(schema: Schema): Schema;
|
|
1580
1577
|
contentSchema(schema: Schema): Schema;
|
|
1581
|
-
/**
|
|
1578
|
+
/** Defaults to a link to the edit page. */
|
|
1582
1579
|
getHeaderActions(): Action[];
|
|
1583
1580
|
protected editAction(): Action;
|
|
1584
1581
|
getTitle(): string;
|
|
@@ -1589,18 +1586,18 @@ export declare class ViewRecord extends Page {
|
|
|
1589
1586
|
getSubNavigation(): SubNavigationItem[];
|
|
1590
1587
|
getPageClasses(): string[];
|
|
1591
1588
|
}
|
|
1592
|
-
/** Sidebar
|
|
1589
|
+
/** Sidebar: logo, tenant menu, search, navigation and, without a topbar, the bell and user menu. */
|
|
1593
1590
|
export declare class Sidebar extends Component {
|
|
1594
1591
|
static callable: string[];
|
|
1595
1592
|
currentPath: string;
|
|
1596
1593
|
static locked: string[];
|
|
1597
1594
|
mount(params: Record<string, unknown>): void;
|
|
1598
|
-
/**
|
|
1595
|
+
/** A resource item stays active on its create and edit pages. */
|
|
1599
1596
|
render(): Promise<string>;
|
|
1600
|
-
/**
|
|
1597
|
+
/** Theme choice by the user: only a theme declared by the panel is accepted; the page reloads to apply it. */
|
|
1601
1598
|
setTheme(id: unknown): void;
|
|
1602
1599
|
}
|
|
1603
|
-
/**
|
|
1600
|
+
/** Topbar: logo, optional navigation, search, bell, user menu. */
|
|
1604
1601
|
export declare class Topbar extends Component {
|
|
1605
1602
|
static callable: string[];
|
|
1606
1603
|
currentPath: string;
|
|
@@ -1609,11 +1606,19 @@ export declare class Topbar extends Component {
|
|
|
1609
1606
|
render(): Promise<string>;
|
|
1610
1607
|
setTheme(id: unknown): void;
|
|
1611
1608
|
}
|
|
1612
|
-
/**
|
|
1609
|
+
/** User menu on simple pages for a signed-in user. */
|
|
1613
1610
|
export declare class SimpleUserMenu extends Component {
|
|
1614
1611
|
static callable: string[];
|
|
1615
1612
|
render(): Promise<string>;
|
|
1616
1613
|
setTheme(id: unknown): void;
|
|
1617
1614
|
}
|
|
1618
|
-
/**
|
|
1615
|
+
/** Resources defined in a folder: `.resources(await discoverResources(new URL('./resources/', import.meta.url)))`. New files are picked up on the next start. */
|
|
1616
|
+
export declare const discoverResources: (directory: string | URL) => Promise<(typeof Resource)[]>;
|
|
1617
|
+
/** Custom pages (and dashboards) defined in a folder. Resource and authentication pages are excluded. */
|
|
1618
|
+
export declare const discoverPages: (directory: string | URL) => Promise<(typeof Page)[]>;
|
|
1619
|
+
/** Widgets defined in a folder. */
|
|
1620
|
+
export declare const discoverWidgets: (directory: string | URL) => Promise<(typeof Widget)[]>;
|
|
1621
|
+
/** Panels default-exported (`export default Panel.make()…`) by a folder's modules. */
|
|
1622
|
+
export declare function discoverPanels(directory: string | URL): Promise<Panel[]>;
|
|
1623
|
+
/** Express router for a panel: assets, runtime endpoint, authentication, tenants, protected pages. */
|
|
1619
1624
|
export declare function panelRouter(panel: Panel, runtime: WireRuntime): Router;
|