@rebasepro/cms-types 0.17.0-canary.0
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/LICENSE +21 -0
- package/dist/admin_collection.d.ts +650 -0
- package/dist/augment.d.ts +81 -0
- package/dist/collections.d.ts +282 -0
- package/dist/controllers/analytics_controller.d.ts +7 -0
- package/dist/controllers/auth.d.ts +111 -0
- package/dist/controllers/customization_controller.d.ts +69 -0
- package/dist/controllers/dialogs_controller.d.ts +36 -0
- package/dist/controllers/index.d.ts +10 -0
- package/dist/controllers/local_config_persistence.d.ts +20 -0
- package/dist/controllers/navigation.d.ts +248 -0
- package/dist/controllers/registry.d.ts +96 -0
- package/dist/controllers/side_dialogs_controller.d.ts +67 -0
- package/dist/controllers/side_panel_controller.d.ts +97 -0
- package/dist/controllers/snackbar.d.ts +45 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.es.js +154 -0
- package/dist/index.es.js.map +1 -0
- package/dist/react_component_ref.d.ts +43 -0
- package/dist/rebase_context.d.ts +68 -0
- package/dist/types/breadcrumbs.d.ts +15 -0
- package/dist/types/builders.d.ts +15 -0
- package/dist/types/collection_views.d.ts +105 -0
- package/dist/types/component_overrides.d.ts +196 -0
- package/dist/types/entity_actions.d.ts +112 -0
- package/dist/types/entity_display.d.ts +148 -0
- package/dist/types/entity_link_builder.d.ts +7 -0
- package/dist/types/entity_views.d.ts +115 -0
- package/dist/types/export_import.d.ts +21 -0
- package/dist/types/form_layout.d.ts +126 -0
- package/dist/types/formex.d.ts +40 -0
- package/dist/types/index.d.ts +18 -0
- package/dist/types/locales.d.ts +4 -0
- package/dist/types/modify_collections.d.ts +5 -0
- package/dist/types/plugins.d.ts +277 -0
- package/dist/types/property_config.d.ts +74 -0
- package/dist/types/property_options.d.ts +255 -0
- package/dist/types/slots.d.ts +279 -0
- package/dist/types/translations.d.ts +989 -0
- package/dist/types/user_management_delegate.d.ts +22 -0
- package/package.json +103 -0
- package/src/admin_collection.ts +775 -0
- package/src/augment.ts +79 -0
- package/src/collections.ts +312 -0
- package/src/controllers/analytics_controller.tsx +57 -0
- package/src/controllers/auth.ts +122 -0
- package/src/controllers/customization_controller.tsx +81 -0
- package/src/controllers/dialogs_controller.tsx +37 -0
- package/src/controllers/index.ts +10 -0
- package/src/controllers/local_config_persistence.tsx +22 -0
- package/src/controllers/navigation.ts +288 -0
- package/src/controllers/registry.ts +114 -0
- package/src/controllers/side_dialogs_controller.tsx +82 -0
- package/src/controllers/side_panel_controller.tsx +112 -0
- package/src/controllers/snackbar.ts +51 -0
- package/src/index.ts +20 -0
- package/src/react_component_ref.ts +52 -0
- package/src/rebase_context.ts +81 -0
- package/src/types/breadcrumbs.ts +16 -0
- package/src/types/builders.ts +18 -0
- package/src/types/collection_views.tsx +125 -0
- package/src/types/component_overrides.ts +244 -0
- package/src/types/entity_actions.tsx +134 -0
- package/src/types/entity_display.ts +182 -0
- package/src/types/entity_link_builder.ts +8 -0
- package/src/types/entity_views.tsx +135 -0
- package/src/types/export_import.ts +26 -0
- package/src/types/form_layout.ts +137 -0
- package/src/types/formex.ts +45 -0
- package/src/types/index.ts +18 -0
- package/src/types/locales.ts +81 -0
- package/src/types/modify_collections.tsx +6 -0
- package/src/types/plugins.tsx +346 -0
- package/src/types/property_config.tsx +97 -0
- package/src/types/property_options.ts +300 -0
- package/src/types/slots.tsx +334 -0
- package/src/types/translations.ts +1104 -0
- package/src/types/user_management_delegate.ts +23 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The admin block, added back onto the core types by declaration merging.
|
|
3
|
+
*
|
|
4
|
+
* `@rebasepro/types` declares no `admin` field — not on `BaseCollectionConfig`, not on
|
|
5
|
+
* any property. A BaaS install therefore cannot write one: `admin: { … }` on a property
|
|
6
|
+
* there is a type error, which is the whole point. Installing this package is what makes
|
|
7
|
+
* the surface exist.
|
|
8
|
+
*
|
|
9
|
+
* This works because every target is an `interface`. Interfaces merge; `type` aliases do
|
|
10
|
+
* not, so `BaseProperty` and the ten concrete property types must stay interfaces in core
|
|
11
|
+
* for this file to be possible at all.
|
|
12
|
+
*
|
|
13
|
+
* Two consequences worth knowing:
|
|
14
|
+
*
|
|
15
|
+
* - The augmentation applies to the whole **program**, not to the files that import it.
|
|
16
|
+
* `config/` and `frontend/` are separate tsconfig programs, so a collection file needs
|
|
17
|
+
* this package in *its* program. The templates do that with one line in one file —
|
|
18
|
+
* `config/cms.d.ts`, holding `/// <reference types="@rebasepro/cms-types" />` —
|
|
19
|
+
* which is why no collection file has to import anything from here to write `admin`.
|
|
20
|
+
* That reference resolves through `typeRoots`, so the project must also depend on this
|
|
21
|
+
* package; `tooling/scripts/check-templates.mjs` asserts both halves.
|
|
22
|
+
* - Each concrete property narrows the block to its own options type
|
|
23
|
+
* (`AdminStringOptions` on `StringProperty`, and so on). That is legal because each
|
|
24
|
+
* extends `AdminPropertyOptions`, exactly as it was declared when these lived in core.
|
|
25
|
+
*/
|
|
26
|
+
import type { AdminArrayOptions, AdminDateOptions, AdminMapOptions, AdminNumberOptions, AdminPropertyOptions, AdminReferenceOptions, AdminRelationOptions, AdminStringOptions, AdminVectorOptions } from "./types/property_options.js";
|
|
27
|
+
import type { AdminCollectionOptions } from "./admin_collection.js";
|
|
28
|
+
import type { User } from "@rebasepro/types";
|
|
29
|
+
declare module "@rebasepro/types" {
|
|
30
|
+
/**
|
|
31
|
+
* Presentation and behaviour for a collection in the admin panel.
|
|
32
|
+
*
|
|
33
|
+
* The type parameters are repeated here verbatim because declaration
|
|
34
|
+
* merging requires an identical parameter list — and they have to be
|
|
35
|
+
* *forwarded* to `AdminCollectionOptions`, which is the part that was
|
|
36
|
+
* missing. Written as a bare `admin?: AdminCollectionOptions`, `M` fell
|
|
37
|
+
* back to its default `Record<string, unknown>`, so `Extract<keyof M,
|
|
38
|
+
* string>` widened to `string` and every key-shaped field in the block —
|
|
39
|
+
* `display`, `sort`, `propertiesOrder`, `listProperties` — silently
|
|
40
|
+
* accepted any string. The completion `defineCollection` advertises is
|
|
41
|
+
* derived from `M`, so it never appeared: the inference was computed,
|
|
42
|
+
* carried to this seam, and dropped one line short of the field that
|
|
43
|
+
* needed it.
|
|
44
|
+
*/
|
|
45
|
+
interface BaseCollectionConfig<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> {
|
|
46
|
+
admin?: AdminCollectionOptions<M, USER>;
|
|
47
|
+
}
|
|
48
|
+
interface BaseProperty<CustomProps = unknown> {
|
|
49
|
+
admin?: AdminPropertyOptions<CustomProps>;
|
|
50
|
+
}
|
|
51
|
+
interface StringProperty {
|
|
52
|
+
admin?: AdminStringOptions;
|
|
53
|
+
}
|
|
54
|
+
interface NumberProperty {
|
|
55
|
+
admin?: AdminNumberOptions;
|
|
56
|
+
}
|
|
57
|
+
interface BooleanProperty {
|
|
58
|
+
admin?: AdminPropertyOptions;
|
|
59
|
+
}
|
|
60
|
+
interface VectorProperty {
|
|
61
|
+
admin?: AdminVectorOptions;
|
|
62
|
+
}
|
|
63
|
+
interface DateProperty {
|
|
64
|
+
admin?: AdminDateOptions;
|
|
65
|
+
}
|
|
66
|
+
interface GeopointProperty {
|
|
67
|
+
admin?: AdminPropertyOptions;
|
|
68
|
+
}
|
|
69
|
+
interface ReferenceProperty {
|
|
70
|
+
admin?: AdminReferenceOptions;
|
|
71
|
+
}
|
|
72
|
+
interface RelationProperty {
|
|
73
|
+
admin?: AdminRelationOptions;
|
|
74
|
+
}
|
|
75
|
+
interface ArrayProperty {
|
|
76
|
+
admin?: AdminArrayOptions;
|
|
77
|
+
}
|
|
78
|
+
interface MapProperty {
|
|
79
|
+
admin?: AdminMapOptions;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin-panel view models for a collection.
|
|
3
|
+
*
|
|
4
|
+
* These twelve types came out of `collections.ts`, where they sat interleaved
|
|
5
|
+
* with the collection shape itself. None of them describes data: they are the
|
|
6
|
+
* table's controllers, the selection state, the kanban layout, the shape of a
|
|
7
|
+
* toolbar action's props. Every one names `React` or `RebaseContext`, and none is
|
|
8
|
+
* imported by a single backend package — checked across `server`,
|
|
9
|
+
* `server-postgres`, `server-mongo`, `client`, `common`, `utils`, `cli` and
|
|
10
|
+
* `codegen`.
|
|
11
|
+
*
|
|
12
|
+
* That is what made them safe to lift: they were never part of the BaaS surface,
|
|
13
|
+
* only stored next to it.
|
|
14
|
+
*/
|
|
15
|
+
import React from "react";
|
|
16
|
+
import type { Entity, EntityStatus, FilterValues, OrderByTuple, User } from "@rebasepro/types";
|
|
17
|
+
import type { RebaseContext } from "./rebase_context.js";
|
|
18
|
+
import type { AdminCollection, PropertyPath } from "@rebasepro/cms-types";
|
|
19
|
+
/**
|
|
20
|
+
* Configuration for Kanban board view mode.
|
|
21
|
+
* @group Collections
|
|
22
|
+
*/
|
|
23
|
+
export interface KanbanConfig<M extends Record<string, unknown> = Record<string, unknown>> {
|
|
24
|
+
/**
|
|
25
|
+
* Property key to use for Kanban board columns.
|
|
26
|
+
* Must reference a string property with `enum` values defined.
|
|
27
|
+
* Entities will be grouped into columns based on this property's value.
|
|
28
|
+
* The column order is determined by the order of `enum` values in the property.
|
|
29
|
+
*
|
|
30
|
+
* Left permissive on purpose, unlike the *optional* key fields on the admin
|
|
31
|
+
* block (`display`, `sort`, `propertiesOrder`, …), which are checked
|
|
32
|
+
* against `M`.
|
|
33
|
+
*
|
|
34
|
+
* This one is **required**, and that is the whole difference: a required
|
|
35
|
+
* generic-dependent property puts `Extract<keyof M, string>` in an invariant
|
|
36
|
+
* position, so `AdminCollection<M>` stops being assignable to
|
|
37
|
+
* `AdminCollection`. The admin package passes collections between those two
|
|
38
|
+
* forms in roughly fifteen places — `CollectionBoardViewBinding`, the
|
|
39
|
+
* collection editor, the view bindings — and every one of them breaks.
|
|
40
|
+
* Tightening this is a worthwhile change, but it is a refactor of those call
|
|
41
|
+
* sites rather than a type edit. Verified by trying it: `columnProperty:
|
|
42
|
+
* Extract<keyof M, string>` alone produced ~15 errors, and doing it alongside
|
|
43
|
+
* `entityViews`/`formView`/`Actions` produced 95.
|
|
44
|
+
*/
|
|
45
|
+
columnProperty: Extract<keyof M, string> | (string & {});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* View mode for displaying a collection.
|
|
49
|
+
* - "list": Simple, clean list view — the classic admin default
|
|
50
|
+
* - "table": Table with inline editing
|
|
51
|
+
* - "cards": Grid of visual cards with thumbnails
|
|
52
|
+
* - "kanban": Board view grouped by a property
|
|
53
|
+
*
|
|
54
|
+
* Any other string is the `key` of a custom view declared in
|
|
55
|
+
* `admin.customViews` or registered on `<RebaseCMS collectionViews={…}>`.
|
|
56
|
+
* The `(string & {})` arm is what keeps the four built-ins in autocomplete
|
|
57
|
+
* while still admitting those keys.
|
|
58
|
+
*
|
|
59
|
+
* @group Collections
|
|
60
|
+
*/
|
|
61
|
+
export type ViewMode = "list" | "table" | "cards" | "kanban" | (string & {});
|
|
62
|
+
/**
|
|
63
|
+
* Parameter passed to the `Actions` prop in the collection configuration.
|
|
64
|
+
* The component will receive this prop when it is rendered in the collection
|
|
65
|
+
* toolbar.
|
|
66
|
+
*
|
|
67
|
+
* @group Models
|
|
68
|
+
*/
|
|
69
|
+
export interface CollectionActionsProps<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User, EC extends AdminCollection<M> = AdminCollection<M>> {
|
|
70
|
+
/**
|
|
71
|
+
* Full collection path of this entity. This is the full path, like
|
|
72
|
+
* `users/1234/addresses`
|
|
73
|
+
*/
|
|
74
|
+
path: string;
|
|
75
|
+
/**
|
|
76
|
+
* Path of the last collection, like `addresses`
|
|
77
|
+
*/
|
|
78
|
+
relativePath: string;
|
|
79
|
+
/**
|
|
80
|
+
* Array of the parent path segments like `['users']`
|
|
81
|
+
*/
|
|
82
|
+
parentCollectionSlugs: string[];
|
|
83
|
+
parentEntityIds: string[];
|
|
84
|
+
/**
|
|
85
|
+
* The collection configuration
|
|
86
|
+
*/
|
|
87
|
+
collection: EC;
|
|
88
|
+
/**
|
|
89
|
+
* Use this controller to get the selected entities and to update the
|
|
90
|
+
* selected entities state.
|
|
91
|
+
*/
|
|
92
|
+
selectionController: SelectionController<M>;
|
|
93
|
+
/**
|
|
94
|
+
* Use this controller to get the table controller and to update the
|
|
95
|
+
* table controller state.
|
|
96
|
+
*/
|
|
97
|
+
tableController: EntityTableController<M>;
|
|
98
|
+
/**
|
|
99
|
+
* Context of the app status
|
|
100
|
+
*/
|
|
101
|
+
context: RebaseContext<USER>;
|
|
102
|
+
/**
|
|
103
|
+
* Count of the entities in this collection.
|
|
104
|
+
* undefined means the count is still loading.
|
|
105
|
+
*/
|
|
106
|
+
collectionEntitiesCount?: number;
|
|
107
|
+
/**
|
|
108
|
+
* Programmatically open the new-document form for this collection,
|
|
109
|
+
* optionally pre-populating it with initial field values.
|
|
110
|
+
* The form opens in the same mode configured for the collection
|
|
111
|
+
* (side panel, full screen, or split).
|
|
112
|
+
*
|
|
113
|
+
* This is the primary hook for workflows that need to create a document
|
|
114
|
+
* from external data — e.g. fetching content from a URL, importing from
|
|
115
|
+
* a third-party API, or duplicating from another system.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* // Inside a custom CollectionAction component:
|
|
119
|
+
* openNewDocument({ title: "Fetched title", body: "..." });
|
|
120
|
+
*/
|
|
121
|
+
openNewDocument: (defaultValues?: Record<string, unknown>) => void;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Use this controller to retrieve the selected entities or modify them in
|
|
125
|
+
* an {@link AdminCollection}
|
|
126
|
+
* @group Models
|
|
127
|
+
*/
|
|
128
|
+
export interface SelectionController<M extends Record<string, unknown> = Record<string, unknown>> {
|
|
129
|
+
selectedEntities: Entity<M>[];
|
|
130
|
+
setSelectedEntities(entities: Entity<M>[]): void;
|
|
131
|
+
setSelectedEntities(action: (prev: Entity<M>[]) => Entity<M>[]): void;
|
|
132
|
+
isEntitySelected(entity: Entity<M>): boolean;
|
|
133
|
+
toggleEntitySelection(entity: Entity<M>, newSelectedState?: boolean): void;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Used to indicate valid filter combinations (e.g. created in Firestore)
|
|
137
|
+
* If the user selects a specific filter/sort combination, the admin checks if it's
|
|
138
|
+
* valid, otherwise it reverts to the simpler valid case
|
|
139
|
+
* @group Models
|
|
140
|
+
*/
|
|
141
|
+
export type FilterCombination<Key extends string> = Partial<Record<Key, "asc" | "desc">>;
|
|
142
|
+
/**
|
|
143
|
+
* Sizes in which a collection can be rendered
|
|
144
|
+
* @group Models
|
|
145
|
+
*/
|
|
146
|
+
export type CollectionSize = "xs" | "s" | "m" | "l" | "xl";
|
|
147
|
+
export type AdditionalFieldDelegateProps<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> = {
|
|
148
|
+
entity: Entity<M>;
|
|
149
|
+
context: RebaseContext<USER>;
|
|
150
|
+
};
|
|
151
|
+
/**
|
|
152
|
+
* Use this interface for adding additional fields to entity collection views and forms.
|
|
153
|
+
*
|
|
154
|
+
* **Computed for display only. The server never sees it.**
|
|
155
|
+
*
|
|
156
|
+
* `value` is async and receives the whole {@link RebaseContext}, so it *can*
|
|
157
|
+
* read another collection, and its result is cached per record. That makes it
|
|
158
|
+
* read like a computed column, and it is not one: it runs in the browser, once
|
|
159
|
+
* per row, **after** the page has already been fetched and ordered. There is no
|
|
160
|
+
* point at which its result could take part in choosing which rows came back or
|
|
161
|
+
* in what order. So a derived value can be shown, and can never be filtered,
|
|
162
|
+
* sorted or paged on — no matter what it is derived from.
|
|
163
|
+
*
|
|
164
|
+
* To filter or sort on a derived value it has to exist in the database. Two
|
|
165
|
+
* ways, in order of preference:
|
|
166
|
+
*
|
|
167
|
+
* - if the value is an aggregate over a relation, ask for it in the query
|
|
168
|
+
* instead — `where: { "applications.status": ["in", [...]] }` and
|
|
169
|
+
* `orderBy: [[{ relation: "applications", field: "created_at", agg: "min" }, "asc"]]`
|
|
170
|
+
* are both compiled by the driver, which means they run before paging;
|
|
171
|
+
* - otherwise denormalise it onto the row — a generated column, or a
|
|
172
|
+
* trigger-maintained one — and it becomes an ordinary property.
|
|
173
|
+
*
|
|
174
|
+
* @group Models
|
|
175
|
+
*/
|
|
176
|
+
export interface AdditionalFieldDelegate<M extends Record<string, unknown> = Record<string, unknown>, USER extends User = User> {
|
|
177
|
+
/**
|
|
178
|
+
* ID of this column. You can use this id in the `properties` field of the
|
|
179
|
+
* collection in any order you want
|
|
180
|
+
*/
|
|
181
|
+
key: string;
|
|
182
|
+
/**
|
|
183
|
+
* Header of this column
|
|
184
|
+
*/
|
|
185
|
+
name: string;
|
|
186
|
+
/**
|
|
187
|
+
* Width of the generated column in pixels
|
|
188
|
+
*/
|
|
189
|
+
width?: number;
|
|
190
|
+
/**
|
|
191
|
+
* Builder for the custom field
|
|
192
|
+
*/
|
|
193
|
+
Builder?(props: {
|
|
194
|
+
entity: Entity<M>;
|
|
195
|
+
context: RebaseContext<USER>;
|
|
196
|
+
}): React.ReactNode;
|
|
197
|
+
/**
|
|
198
|
+
* If this column needs to update dynamically based on other properties,
|
|
199
|
+
* you can define an array of keys as strings with the
|
|
200
|
+
* `dependencies` prop.
|
|
201
|
+
* e.g. ["name", "surname"]
|
|
202
|
+
* This is a performance optimization, if you don't define dependencies
|
|
203
|
+
* it will be updated in every render.
|
|
204
|
+
*
|
|
205
|
+
* A key that is not a property of this collection can never change, so
|
|
206
|
+
* listing one is always a mistake — it silently pins the column to the
|
|
207
|
+
* "never re-render" path, which reads as a stale cell rather than a typo.
|
|
208
|
+
* The `NoInfer` wrappers keep these keys from participating in inference of
|
|
209
|
+
* `M`; the `(string & {})` arms they used to sit beside made the whole union
|
|
210
|
+
* `string`, so the wrappers had nothing to protect.
|
|
211
|
+
*/
|
|
212
|
+
dependencies?: NoInfer<PropertyPath<M>> | NoInfer<PropertyPath<M>>[];
|
|
213
|
+
/**
|
|
214
|
+
* Use this prop to define the value of the column as a string or number.
|
|
215
|
+
* This is the value that will be used for exporting the collection.
|
|
216
|
+
* If `Builder` is defined, this prop will be ignored in the collection
|
|
217
|
+
* view.
|
|
218
|
+
* @param entity
|
|
219
|
+
*/
|
|
220
|
+
value?(props: {
|
|
221
|
+
entity: Entity<M>;
|
|
222
|
+
context: RebaseContext;
|
|
223
|
+
}): string | number | Promise<string | number> | undefined;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Used in the {@link AdminCollection#defaultSelectedView} to define the default
|
|
227
|
+
* @group Models
|
|
228
|
+
*/
|
|
229
|
+
export type DefaultSelectedViewBuilder = (params: DefaultSelectedViewParams) => string | undefined;
|
|
230
|
+
/**
|
|
231
|
+
* Used in the {@link AdminCollection#defaultSelectedView} to define the default
|
|
232
|
+
* @group Models
|
|
233
|
+
*/
|
|
234
|
+
export type DefaultSelectedViewParams = {
|
|
235
|
+
status?: EntityStatus;
|
|
236
|
+
entityId?: string | number;
|
|
237
|
+
};
|
|
238
|
+
/**
|
|
239
|
+
* You can use this controller to control the table view of a collection.
|
|
240
|
+
*/
|
|
241
|
+
export type EntityTableController<M extends Record<string, unknown> = Record<string, unknown>> = {
|
|
242
|
+
data: Entity<M>[];
|
|
243
|
+
dataLoading: boolean;
|
|
244
|
+
noMoreToLoad: boolean;
|
|
245
|
+
dataLoadingError?: Error;
|
|
246
|
+
filterValues?: FilterValues<Extract<keyof M, string> | (string & {})>;
|
|
247
|
+
setFilterValues?: (filterValues: FilterValues<Extract<keyof M, string> | (string & {})>) => void;
|
|
248
|
+
/**
|
|
249
|
+
* The sort keys in order of significance, the second breaking ties on the
|
|
250
|
+
* first. A single key is a one-element list — this was a bare tuple, which
|
|
251
|
+
* could only ever express one, so `collection.sort` could not describe an
|
|
252
|
+
* order like "by role, newest first within each role" and the table had no
|
|
253
|
+
* state to hold one in.
|
|
254
|
+
*/
|
|
255
|
+
sortBy?: OrderByTuple<Extract<keyof M, string> | (string & {})>[];
|
|
256
|
+
setSortBy?: (sortBy?: OrderByTuple<Extract<keyof M, string> | (string & {})>[]) => void;
|
|
257
|
+
searchString?: string;
|
|
258
|
+
setSearchString?: (searchString?: string) => void;
|
|
259
|
+
clearFilter?: () => void;
|
|
260
|
+
itemCount?: number;
|
|
261
|
+
setItemCount?: (itemCount: number) => void;
|
|
262
|
+
initialScroll?: number;
|
|
263
|
+
onScroll?: (props: {
|
|
264
|
+
scrollDirection: "forward" | "backward";
|
|
265
|
+
scrollOffset: number;
|
|
266
|
+
scrollUpdateWasRequested: boolean;
|
|
267
|
+
}) => void;
|
|
268
|
+
paginationEnabled?: boolean;
|
|
269
|
+
pageSize?: number;
|
|
270
|
+
checkFilterCombination?: (filterValues: FilterValues<string>, sortBy?: OrderByTuple[]) => boolean;
|
|
271
|
+
popupCell?: SelectedCellProps<M>;
|
|
272
|
+
setPopupCell?: (popupCell?: SelectedCellProps<M>) => void;
|
|
273
|
+
onAddColumn?: (column: string) => void;
|
|
274
|
+
};
|
|
275
|
+
export type SelectedCellProps<M extends Record<string, unknown> = Record<string, unknown>> = {
|
|
276
|
+
propertyKey: Extract<keyof M, string> | (string & {});
|
|
277
|
+
cellRect: DOMRect;
|
|
278
|
+
width: number;
|
|
279
|
+
height: number;
|
|
280
|
+
entityPath: string;
|
|
281
|
+
entityId: string | number;
|
|
282
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type AnalyticsController = {
|
|
2
|
+
/**
|
|
3
|
+
* Callback used to get analytics events from the admin
|
|
4
|
+
*/
|
|
5
|
+
onAnalyticsEvent?: (event: AnalyticsEvent, data?: object) => void;
|
|
6
|
+
};
|
|
7
|
+
export type AnalyticsEvent = "entity_click" | "entity_click_from_reference" | "reference_selection_clear" | "reference_selection_toggle" | "reference_selected_single" | "reference_selection_new_entity" | "edit_entity_clicked" | "entity_edited" | "new_entity_click" | "new_entity_saved" | "copy_entity_click" | "entity_copied" | "single_delete_dialog_open" | "multiple_delete_dialog_open" | "single_entity_deleted" | "multiple_entities_deleted" | "drawer_navigate_to_home" | "drawer_navigate_to_collection" | "drawer_navigate_to_view" | "home_navigate_to_collection" | "home_favorite_navigate_to_collection" | "home_navigate_to_view" | "home_navigate_to_admin_view" | "home_favorite_navigate_to_view" | "home_move_card" | "home_move_group" | "home_drop_new_group" | "collection_inline_editing" | "view_mode_changed" | "kanban_card_moved" | "kanban_column_reorder" | "kanban_property_changed" | "kanban_new_entity_in_column" | "kanban_backfill_order" | "card_view_entity_click" | "unmapped_event";
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import type { User } from "@rebasepro/types";
|
|
2
|
+
/**
|
|
3
|
+
* Capabilities advertised by an auth provider.
|
|
4
|
+
* UI components use this to show/hide features dynamically
|
|
5
|
+
* (e.g. password reset, registration, session management).
|
|
6
|
+
* @group Hooks and utilities
|
|
7
|
+
*/
|
|
8
|
+
export interface AuthCapabilities {
|
|
9
|
+
emailPasswordLogin?: boolean;
|
|
10
|
+
googleLogin?: boolean;
|
|
11
|
+
/** Self-registration is open right now — the wire's `registrationEnabled`. */
|
|
12
|
+
registrationEnabled?: boolean;
|
|
13
|
+
/** Self-service password reset (emailing a reset link) is available. */
|
|
14
|
+
passwordReset?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* An admin can reset another user's password. Gates the "Reset Password"
|
|
17
|
+
* entity action in the admin UI. See `AuthAdapterCapabilities`.
|
|
18
|
+
*/
|
|
19
|
+
adminPasswordReset?: boolean;
|
|
20
|
+
sessionManagement?: boolean;
|
|
21
|
+
profileUpdate?: boolean;
|
|
22
|
+
emailVerification?: boolean;
|
|
23
|
+
/** List of enabled OAuth provider IDs (e.g. ["google", "github", "discord"]) */
|
|
24
|
+
enabledProviders?: string[];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Controller for retrieving the logged user or performing auth related operations.
|
|
28
|
+
* Note that if you are implementing your AuthController, you probably will want
|
|
29
|
+
* to do it as the result of a hook.
|
|
30
|
+
* @group Hooks and utilities
|
|
31
|
+
*/
|
|
32
|
+
export type AuthController<USER extends User = User, ExtraData = unknown> = {
|
|
33
|
+
/**
|
|
34
|
+
* The user currently logged in
|
|
35
|
+
* The values can be: the user object, null if they skipped login
|
|
36
|
+
*/
|
|
37
|
+
user: USER | null;
|
|
38
|
+
/**
|
|
39
|
+
* Initial loading flag. It is used not to display the login screen
|
|
40
|
+
* when the app first loads, and it has not been checked whether the user
|
|
41
|
+
* is logged in or not.
|
|
42
|
+
*/
|
|
43
|
+
initialLoading?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Loading flag. It is used to display a loading screen when the user is
|
|
46
|
+
* logging in or out.
|
|
47
|
+
*/
|
|
48
|
+
authLoading: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Sign out
|
|
51
|
+
*/
|
|
52
|
+
signOut: () => Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* Error initializing the authentication
|
|
55
|
+
*/
|
|
56
|
+
authError?: unknown;
|
|
57
|
+
/**
|
|
58
|
+
* Error dispatched by the auth provider
|
|
59
|
+
*/
|
|
60
|
+
authProviderError?: unknown;
|
|
61
|
+
/**
|
|
62
|
+
* You can use this method to retrieve the auth token for the current user.
|
|
63
|
+
*/
|
|
64
|
+
getAuthToken: () => Promise<string>;
|
|
65
|
+
/**
|
|
66
|
+
* Has the user skipped the login process
|
|
67
|
+
*/
|
|
68
|
+
loginSkipped: boolean;
|
|
69
|
+
extra: ExtraData;
|
|
70
|
+
setExtra: (extra: ExtraData) => void;
|
|
71
|
+
setUser?(user: USER | null): void;
|
|
72
|
+
setUserRoles?(roles: string[]): void;
|
|
73
|
+
/**
|
|
74
|
+
* Capabilities advertised by the auth provider.
|
|
75
|
+
* UI components use this to feature-detect what the backend supports.
|
|
76
|
+
*/
|
|
77
|
+
capabilities?: AuthCapabilities;
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Extended auth controller with common optional auth methods.
|
|
81
|
+
* Backend implementations (Rebase backend, Firebase, etc.)
|
|
82
|
+
* extend this with their own backend-specific extras.
|
|
83
|
+
* @group Hooks and utilities
|
|
84
|
+
*/
|
|
85
|
+
export interface AuthControllerExtended<USER extends User = User, ExtraData = unknown> extends AuthController<USER, ExtraData> {
|
|
86
|
+
/** Login with email and password */
|
|
87
|
+
emailPasswordLogin?(email: string, password: string): Promise<void>;
|
|
88
|
+
/** Login with Google — accepts an ID token, access token, or authorization code payload */
|
|
89
|
+
googleLogin?: (payload: {
|
|
90
|
+
idToken: string;
|
|
91
|
+
} | {
|
|
92
|
+
accessToken: string;
|
|
93
|
+
} | {
|
|
94
|
+
code: string;
|
|
95
|
+
redirectUri: string;
|
|
96
|
+
}) => Promise<void>;
|
|
97
|
+
/** Generic OAuth login — works with any provider. Posts payload to /auth/{providerId}. */
|
|
98
|
+
oauthLogin?: (providerId: string, payload: Record<string, unknown>) => Promise<void>;
|
|
99
|
+
/** Register a new user */
|
|
100
|
+
register?(email: string, password: string, displayName?: string): Promise<void>;
|
|
101
|
+
/** Skip login (for anonymous access if enabled) */
|
|
102
|
+
skipLogin?(): void;
|
|
103
|
+
/** Request password reset email */
|
|
104
|
+
forgotPassword?(email: string): Promise<void>;
|
|
105
|
+
/** Reset password using a token */
|
|
106
|
+
resetPassword?(token: string, password: string): Promise<void>;
|
|
107
|
+
/** Change password for the authenticated user */
|
|
108
|
+
changePassword?(oldPassword: string, newPassword: string): Promise<void>;
|
|
109
|
+
/** Update user profile */
|
|
110
|
+
updateProfile?(displayName?: string, photoURL?: string): Promise<USER>;
|
|
111
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { EntityLinkBuilder } from "../types/entity_link_builder.js";
|
|
2
|
+
import type { Locale } from "../types/locales.js";
|
|
3
|
+
import type { EntityAction } from "../types/entity_actions.js";
|
|
4
|
+
import type { EntityCustomView } from "../types/entity_views.js";
|
|
5
|
+
import type { CollectionCustomView } from "../types/collection_views.js";
|
|
6
|
+
import type { RebasePlugin } from "../types/plugins.js";
|
|
7
|
+
import type { PropertyConfig } from "../types/property_config.js";
|
|
8
|
+
import type { SlotContribution } from "../types/slots.js";
|
|
9
|
+
import type { ComponentOverrideMap } from "../types/component_overrides.js";
|
|
10
|
+
export type CustomizationController = {
|
|
11
|
+
/**
|
|
12
|
+
* Builder for generating utility links for entities
|
|
13
|
+
*/
|
|
14
|
+
entityLinkBuilder?: EntityLinkBuilder;
|
|
15
|
+
/**
|
|
16
|
+
* Use plugins to modify the behaviour of the admin.
|
|
17
|
+
*/
|
|
18
|
+
plugins?: RebasePlugin[];
|
|
19
|
+
/**
|
|
20
|
+
* Pre-merged slots from plugins + direct slot contributions.
|
|
21
|
+
*/
|
|
22
|
+
resolvedSlots: SlotContribution[];
|
|
23
|
+
/**
|
|
24
|
+
* List of additional custom views for entities.
|
|
25
|
+
* You can use the key to reference the custom view in
|
|
26
|
+
* the `entityViews` prop of a collection.
|
|
27
|
+
*
|
|
28
|
+
* You can also define a entity view from the UI.
|
|
29
|
+
*/
|
|
30
|
+
entityViews?: EntityCustomView[];
|
|
31
|
+
/**
|
|
32
|
+
* List of additional ways to render a collection's rows. You can use the
|
|
33
|
+
* key to reference the view in the `admin.customViews` prop of a
|
|
34
|
+
* collection, which is also what makes it selectable from the collection
|
|
35
|
+
* editor.
|
|
36
|
+
*/
|
|
37
|
+
collectionViews?: CollectionCustomView[];
|
|
38
|
+
/**
|
|
39
|
+
* List of actions that can be performed on entities.
|
|
40
|
+
* These actions are displayed in the entity view and in the collection view.
|
|
41
|
+
* You can later reuse these actions in the `entityActions` prop of a collection,
|
|
42
|
+
* by specifying the `key` of the action.
|
|
43
|
+
*/
|
|
44
|
+
entityActions?: EntityAction[];
|
|
45
|
+
/**
|
|
46
|
+
* Format of the dates in the admin.
|
|
47
|
+
* Defaults to 'MMMM dd, yyyy, HH:mm:ss'
|
|
48
|
+
*/
|
|
49
|
+
dateTimeFormat?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Locale of the admin, currently only affecting dates
|
|
52
|
+
*/
|
|
53
|
+
locale?: Locale;
|
|
54
|
+
/**
|
|
55
|
+
* Record of custom form fields to be used in the admin.
|
|
56
|
+
* You can use the key to reference the custom field in
|
|
57
|
+
* the `propertyConfig` prop of a property in a collection.
|
|
58
|
+
*/
|
|
59
|
+
propertyConfigs: Record<string, PropertyConfig>;
|
|
60
|
+
/**
|
|
61
|
+
* Global component overrides. Keys are component names from
|
|
62
|
+
* {@link OverridableComponentName}. Values replace the default
|
|
63
|
+
* implementation everywhere in the app.
|
|
64
|
+
*
|
|
65
|
+
* Collection-scoped overrides (set on individual collections)
|
|
66
|
+
* take precedence over global overrides.
|
|
67
|
+
*/
|
|
68
|
+
components?: ComponentOverrideMap;
|
|
69
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Controller to open the side dialog
|
|
4
|
+
* @group Hooks and utilities
|
|
5
|
+
*/
|
|
6
|
+
export interface DialogsController {
|
|
7
|
+
/**
|
|
8
|
+
* Close the last dialog
|
|
9
|
+
*/
|
|
10
|
+
close: () => void;
|
|
11
|
+
/**
|
|
12
|
+
* Open a dialog
|
|
13
|
+
* @param props
|
|
14
|
+
*/
|
|
15
|
+
open: <T extends object = object>(props: DialogControllerEntryProps<T>) => {
|
|
16
|
+
closeDialog: () => void;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Props used to open a side dialog
|
|
21
|
+
* @group Hooks and utilities
|
|
22
|
+
*/
|
|
23
|
+
export interface DialogControllerEntryProps<T extends object = object> {
|
|
24
|
+
key: string;
|
|
25
|
+
/**
|
|
26
|
+
* The component type that will be rendered
|
|
27
|
+
*/
|
|
28
|
+
Component: React.ComponentType<{
|
|
29
|
+
open: boolean;
|
|
30
|
+
closeDialog: () => void;
|
|
31
|
+
} & T>;
|
|
32
|
+
/**
|
|
33
|
+
* Props to pass to the dialog component
|
|
34
|
+
*/
|
|
35
|
+
props?: T;
|
|
36
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from "./analytics_controller.js";
|
|
2
|
+
export * from "./auth.js";
|
|
3
|
+
export * from "./customization_controller.js";
|
|
4
|
+
export * from "./dialogs_controller.js";
|
|
5
|
+
export * from "./local_config_persistence.js";
|
|
6
|
+
export * from "./navigation.js";
|
|
7
|
+
export * from "./registry.js";
|
|
8
|
+
export * from "./side_dialogs_controller.js";
|
|
9
|
+
export * from "./side_panel_controller.js";
|
|
10
|
+
export * from "./snackbar.js";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AdminCollection } from "@rebasepro/cms-types";
|
|
2
|
+
/**
|
|
3
|
+
* @group Models
|
|
4
|
+
*/
|
|
5
|
+
export type PartialCollectionConfig<M extends Record<string, unknown> = Record<string, unknown>> = Partial<AdminCollection<M>>;
|
|
6
|
+
/**
|
|
7
|
+
* This interface is in charge of defining the controller that persists
|
|
8
|
+
* modifications to a collection or collection, and retrieves them back from
|
|
9
|
+
* a data source, such as local storage or Firestore.
|
|
10
|
+
*/
|
|
11
|
+
export interface UserConfigurationPersistence {
|
|
12
|
+
onCollectionModified: <M extends Record<string, unknown> = Record<string, unknown>>(path: string, partialCollection: PartialCollectionConfig<M>) => void;
|
|
13
|
+
getCollectionConfig: <M extends Record<string, unknown> = Record<string, unknown>>(path: string) => PartialCollectionConfig<M>;
|
|
14
|
+
recentlyVisitedPaths: string[];
|
|
15
|
+
setRecentlyVisitedPaths: (paths: string[]) => void;
|
|
16
|
+
favouritePaths: string[];
|
|
17
|
+
setFavouritePaths: (paths: string[]) => void;
|
|
18
|
+
collapsedGroups: string[];
|
|
19
|
+
setCollapsedGroups: (paths: string[]) => void;
|
|
20
|
+
}
|