@compill/admin 1.0.106 → 1.0.108

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/dist/index.cjs DELETED
@@ -1,2054 +0,0 @@
1
- 'use strict';
2
-
3
- var jsxRuntime = require('@soperio/jsx-runtime');
4
- var api = require('@compill/api');
5
- var components = require('@compill/components');
6
- var js = require('@mdi/js');
7
- var ui = require('@valerya/ui');
8
- var compat = require('es-toolkit/compat');
9
- var Link = require('next/link');
10
- var reactRouterDom = require('react-router-dom');
11
- var React8 = require('react');
12
- var adminApi = require('@compill/admin-api');
13
- var formik = require('formik');
14
- var reactToastify = require('react-toastify');
15
- var reactHotkeysHook = require('react-hotkeys-hook');
16
- var form = require('@compill/form');
17
- var react = require('@soperio/react');
18
- var formEditor = require('@compill/form-editor');
19
- var editor = require('@compill/editor');
20
- var reactDom = require('react-dom');
21
- var router = require('next/router');
22
- var table = require('@compill/table');
23
- var esToolkit = require('es-toolkit');
24
- var hooks = require('@compill/hooks');
25
- var env = require('@compill/env');
26
- var reactTable = require('@tanstack/react-table');
27
- var reactQuery = require('@tanstack/react-query');
28
- var Image = require('next/image');
29
- var auth = require('@compill/auth');
30
-
31
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
32
-
33
- var Link__default = /*#__PURE__*/_interopDefault(Link);
34
- var React8__default = /*#__PURE__*/_interopDefault(React8);
35
- var Image__default = /*#__PURE__*/_interopDefault(Image);
36
-
37
- // src/lib/SectionTitle.tsx
38
- function SectionTitle({ children, ...props }) {
39
- return /* @__PURE__ */ jsxRuntime.jsx("h2", { textSize: "xl", fontWeight: "600", textColor: "slate-800", ...props, children });
40
- }
41
- function Breadcrumbs({ breadcrumbs, ...props }) {
42
- if (compat.isArray(breadcrumbs)) {
43
- return /* @__PURE__ */ jsxRuntime.jsx("div", { dflex: true, alignItems: "center", trait: "typo.h5", ...props, children: breadcrumbs.map((b, index) => /* @__PURE__ */ jsxRuntime.jsx(BreadcrumbItem, { breadcrumb: b, showSeparator: index > 0 }, index)) });
44
- }
45
- return /* @__PURE__ */ jsxRuntime.jsx(QueryBreadcrumbs, { queryFn: breadcrumbs.queryFn, queryField: breadcrumbs.queryField, generate: breadcrumbs.generate });
46
- }
47
- function QueryBreadcrumbs({ queryFn, queryField, generate, ...props }) {
48
- const params = reactRouterDom.useParams();
49
- const id = queryField ? params[queryField] : void 0;
50
- const { data, isLoading, isError } = api.useApiQuery([""], queryFn, id);
51
- if (isLoading || isError) {
52
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { dflex: true, alignItems: "center", children: [
53
- /* @__PURE__ */ jsxRuntime.jsx(components.Shimmer, { h: "8", w: "24" }),
54
- /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { path: js.mdiCircleSmall, mx: "1" }),
55
- /* @__PURE__ */ jsxRuntime.jsx(components.Shimmer, { h: "8", w: "20" })
56
- ] });
57
- }
58
- const breadcrumbs = generate(data);
59
- return /* @__PURE__ */ jsxRuntime.jsx("div", { dflex: true, alignItems: "center", trait: "typo.h5", ...props, children: breadcrumbs.map((b, index) => /* @__PURE__ */ jsxRuntime.jsx(BreadcrumbItem, { breadcrumb: b, showSeparator: index > 0 }, index)) });
60
- }
61
- function BreadcrumbItem({ breadcrumb, showSeparator }) {
62
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
63
- showSeparator && /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { path: js.mdiCircleSmall, mx: "1" }),
64
- /* @__PURE__ */ jsxRuntime.jsx(Link__default.default, { href: `/${breadcrumb.path || "#"}`, children: /* @__PURE__ */ jsxRuntime.jsx(
65
- "span",
66
- {
67
- hover_textDecoration: breadcrumb.path ? "underline" : void 0,
68
- cursor: breadcrumb.path ? "pointer" : void 0,
69
- children: breadcrumb.label
70
- }
71
- ) })
72
- ] });
73
- }
74
- function DialogButton({ buildDialog, ...props }) {
75
- const [showDialog, setShowDialog] = React8__default.default.useState(false);
76
- const onShowDialog = React8__default.default.useCallback((event) => {
77
- event?.preventDefault();
78
- event?.stopPropagation();
79
- setShowDialog(true);
80
- }, [setShowDialog]);
81
- const onCloseDialog = React8__default.default.useCallback(() => {
82
- setShowDialog(false);
83
- }, [setShowDialog]);
84
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
85
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { onClick: onShowDialog, ...props }),
86
- showDialog && buildDialog(onCloseDialog)
87
- ] });
88
- }
89
- function ButtonBar({ children, ...props }) {
90
- return /* @__PURE__ */ jsxRuntime.jsx("div", { dflex: true, border: "1px", borderColor: "zinc-200", divideX: "1px", divideColor: "zinc-200", rounded: "lg", overflow: "hidden", ...props, children });
91
- }
92
- var ButtonBarButton = React8__default.default.forwardRef(
93
- function({ icon, children, ...props }, ref) {
94
- return /* @__PURE__ */ jsxRuntime.jsxs(
95
- ui.Button,
96
- {
97
- scheme: "dark",
98
- size: "sm",
99
- aspectRatio: icon && !children ? "square" : void 0,
100
- variant: "borderless",
101
- dflex: true,
102
- alignItems: "center",
103
- placeContent: "center",
104
- corners: "square",
105
- gap: "2",
106
- ...props,
107
- ref,
108
- children: [
109
- icon && /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { path: icon }),
110
- children
111
- ]
112
- }
113
- );
114
- }
115
- );
116
- var ButtonBarSubmitButton = React8__default.default.forwardRef(
117
- function({ useDirty, disabled, icon, children, ...props }, ref) {
118
- const { dirty, handleSubmit } = formik.useFormikContext() ?? { dirty: false, handleSubmit: void 0};
119
- const onSubmit = React8__default.default.useCallback(() => handleSubmit(), [handleSubmit]);
120
- return /* @__PURE__ */ jsxRuntime.jsxs(
121
- ui.Button,
122
- {
123
- scheme: "dark",
124
- size: "sm",
125
- aspectRatio: icon && !children ? "square" : void 0,
126
- variant: "borderless",
127
- dflex: true,
128
- alignItems: "center",
129
- placeContent: "center",
130
- corners: "square",
131
- gap: "2",
132
- disabled: useDirty && !dirty || disabled,
133
- onClick: onSubmit,
134
- ...props,
135
- ref,
136
- children: [
137
- icon && /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { path: icon }),
138
- children
139
- ]
140
- }
141
- );
142
- }
143
- );
144
- function ButtonBarDialogButton({ icon, children, ...props }) {
145
- return /* @__PURE__ */ jsxRuntime.jsxs(
146
- DialogButton,
147
- {
148
- scheme: "dark",
149
- size: "sm",
150
- aspectRatio: icon && !children ? "square" : void 0,
151
- variant: "borderless",
152
- dflex: true,
153
- alignItems: "center",
154
- placeContent: "center",
155
- corners: "square",
156
- gap: "2",
157
- ...props,
158
- children: [
159
- icon && /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { path: icon }),
160
- children
161
- ]
162
- }
163
- );
164
- }
165
- function InvalidateButton({ pathOrPermalink, ...props }) {
166
- const api$1 = adminApi.INVALIDATE_API.new(pathOrPermalink);
167
- const mutation = api.useApiMutation(api$1.invalidate, api$1.queryKey);
168
- const invalidate = api.useMutate(mutation, { successMsg: "Page successfully invalidated" });
169
- return /* @__PURE__ */ jsxRuntime.jsx(
170
- ButtonBarButton,
171
- {
172
- title: "Regenerate",
173
- disabled: mutation.isLoading,
174
- onClick: invalidate,
175
- icon: js.mdiDatabaseRefreshOutline,
176
- ...props
177
- }
178
- );
179
- }
180
- function NavigateButton({ path, ...props }) {
181
- const navigate = reactRouterDom.useNavigate();
182
- const handleClick = React8__default.default.useCallback(() => {
183
- navigate(path);
184
- }, [navigate, path]);
185
- return /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { type: "submit", scheme: "dark", variant: "glass", corners: "pill", w: "10", h: "10", onClick: handleClick, ...props, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { path: js.mdiPost }) });
186
- }
187
- function PublishButton({
188
- status,
189
- queryId,
190
- api: api$1,
191
- ...props
192
- }) {
193
- const isDraft = status == "draft";
194
- const mutation = api.useInvalidateMutation(isDraft ? api$1.publish : api$1.unpublish, api$1.queryKey, queryId, { networkMode: "always" });
195
- const publish = React8__default.default.useCallback(() => {
196
- mutation.reset();
197
- mutation.mutateAsync(queryId).then(() => reactToastify.toast.success(isDraft ? "Published!" : "Unpublished!")).catch((error) => reactToastify.toast.error(`Error: ${error}`));
198
- }, [mutation, queryId]);
199
- return /* @__PURE__ */ jsxRuntime.jsx(
200
- ButtonBarButton,
201
- {
202
- disabled: mutation.isLoading,
203
- onClick: publish,
204
- icon: isDraft ? js.mdiEye : js.mdiEyeOff,
205
- ...props,
206
- children: isDraft ? "Publish" : "Switch to draft"
207
- }
208
- );
209
- }
210
- function UpdateButton({ ...props }) {
211
- const { dirty, handleSubmit } = formik.useFormikContext() ?? { dirty: false, handleSubmit: void 0};
212
- reactHotkeysHook.useHotkeys("ctrl+s", () => {
213
- if (dirty && !props.disabled) handleSubmit();
214
- }, { preventDefault: true }, [dirty, props, handleSubmit]);
215
- return /* @__PURE__ */ jsxRuntime.jsx(ButtonBarSubmitButton, { icon: js.mdiCloudUpload, ...props, children: "Update" });
216
- }
217
- function ViewButton({ label, path, icon, ...props }) {
218
- const openPage = React8__default.default.useCallback(() => {
219
- window.open(path, "_blank");
220
- }, [path]);
221
- return /* @__PURE__ */ jsxRuntime.jsx(
222
- ButtonBarButton,
223
- {
224
- onClick: openPage,
225
- dflex: true,
226
- alignItems: "center",
227
- gap: "2",
228
- icon: icon || js.mdiOpenInNew,
229
- ...props,
230
- children: label
231
- }
232
- );
233
- }
234
- function OrderCell({ api: api$1, postId, order }) {
235
- const mutationDown = api.useInvalidateMutation(api$1.moveDown, api$1.queryKey);
236
- const mutationUp = api.useInvalidateMutation(api$1.moveUp, api$1.queryKey);
237
- const moveDown = React8__default.default.useCallback((e) => {
238
- e.stopPropagation();
239
- mutationDown.mutateAsync(postId).catch((error) => {
240
- reactToastify.toast.error(`Error: ${error}`);
241
- });
242
- }, [mutationDown, postId]);
243
- const moveUp = React8__default.default.useCallback((e) => {
244
- e.stopPropagation();
245
- mutationUp.mutateAsync(postId).catch((error) => {
246
- reactToastify.toast.error(`Error: ${error}`);
247
- });
248
- }, [mutationUp, postId]);
249
- return /* @__PURE__ */ jsxRuntime.jsxs(components.FlexCenter, { placeContent: "start", numericFontVariant: "tabular-nums", children: [
250
- order,
251
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { ms: "3", variant: "borderless", scheme: "dark", onClick: moveUp, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { path: js.mdiArrowUpBoldBox }) }),
252
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "borderless", scheme: "dark", onClick: moveDown, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { path: js.mdiArrowDownBoldBox }) })
253
- ] });
254
- }
255
- function PageContainer({ children, ...props }) {
256
- return /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { center: true, dflex: true, flexCol: true, gap: "8", ...props, children });
257
- }
258
- function PageMain({ children, ...props }) {
259
- return /* @__PURE__ */ jsxRuntime.jsx(ui.Tile, { scheme: "light", p: "5", ...props, children });
260
- }
261
- function PageContentEditor({ name, ...props }) {
262
- const extensions = [editor.ImageExtension];
263
- return /* @__PURE__ */ jsxRuntime.jsx(PageMain, { h: "min", ...props, children: /* @__PURE__ */ jsxRuntime.jsx(
264
- formEditor.FormEditor,
265
- {
266
- minH: "128",
267
- minW: "144",
268
- maxW: props.maxW,
269
- name,
270
- placeHolder: "Write here...",
271
- extensions
272
- }
273
- ) });
274
- }
275
- function PageQueryStateContainerInner({ queryId, api: api$1, apiFn, loadingStyles, errorStyles, children, ...props }) {
276
- const { data, isLoading, isError } = apiFn == "getAll" ? api.useApiQuery(api$1.queryKey, api$1.getAll, props.apiParams) : api.useApiQuery(api$1.queryKey, api$1.get, queryId);
277
- const invalidate = api.useInvalidateQuery(api$1.queryKey, queryId);
278
- if (isLoading)
279
- return /* @__PURE__ */ jsxRuntime.jsx(components.QueryLoadingState, { w: "full", h: "100%", ...loadingStyles });
280
- if (isError)
281
- return /* @__PURE__ */ jsxRuntime.jsx(components.RetryOnError, { p: "0", onClick: invalidate, ...errorStyles });
282
- return /* @__PURE__ */ jsxRuntime.jsx(PageContainer, { ...props, children: apiFn == "get" ? children(data) : children(data) });
283
- }
284
- var PageQueryStateContainer = React8__default.default.forwardRef(PageQueryStateContainerInner);
285
- function PageSidebar({ children, ...props }) {
286
- return /* @__PURE__ */ jsxRuntime.jsx("div", { w: "112", minW: "112", minH: "100%", gap: "8", dflex: true, flexCol: true, ...props, children });
287
- }
288
- function PageSectionTitle({ children, ...props }) {
289
- return /* @__PURE__ */ jsxRuntime.jsx("div", { trait: "typo.h6", mb: "5", ...props, children });
290
- }
291
- function PageSidebarSection({ title, children, ...props }) {
292
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { w: "full", ...props, children: [
293
- title && /* @__PURE__ */ jsxRuntime.jsx(PageSectionTitle, { children: title }),
294
- children
295
- ] });
296
- }
297
- function PageTitle({ children, ...props }) {
298
- return /* @__PURE__ */ jsxRuntime.jsx("div", { trait: "typo.h5", ...props, children });
299
- }
300
- function PageTopBar({ title, breadcrumbs, children, ...props }) {
301
- return /* @__PURE__ */ jsxRuntime.jsxs(components.FlexCenter, { gap: "3", minH: "9", ...props, children: [
302
- title && /* @__PURE__ */ jsxRuntime.jsx(PageTitle, { children: title }),
303
- breadcrumbs && /* @__PURE__ */ jsxRuntime.jsx(Breadcrumbs, { breadcrumbs }),
304
- /* @__PURE__ */ jsxRuntime.jsx("div", { flexGrow: true }),
305
- children
306
- ] });
307
- }
308
- var [CP, usePageTabbedTopBarContext] = react.createContext();
309
- function PageTabbedTopBarProvider({ children }) {
310
- const [containerEl, setContainerEl] = React8__default.default.useState(null);
311
- React8__default.default.createRef();
312
- return /* @__PURE__ */ jsxRuntime.jsx(CP, { value: { containerEl, setContainerEl }, children });
313
- }
314
- function PageTabbedTopBar({ title, breadcrumbs, children, ...props }) {
315
- const ref = React8__default.default.createRef();
316
- const { setContainerEl } = usePageTabbedTopBarContext();
317
- const [isSet, setIsSet] = React8__default.default.useState(false);
318
- React8__default.default.useEffect(() => {
319
- if (!isSet && ref.current) {
320
- setContainerEl(ref.current);
321
- setIsSet(true);
322
- }
323
- return () => setContainerEl(null);
324
- }, []);
325
- return /* @__PURE__ */ jsxRuntime.jsx(components.FlexCenter, { gap: "3", minH: "9", ...props, children: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
326
- title && /* @__PURE__ */ jsxRuntime.jsx(PageTitle, { children: title }),
327
- breadcrumbs && /* @__PURE__ */ jsxRuntime.jsx(Breadcrumbs, { breadcrumbs }),
328
- /* @__PURE__ */ jsxRuntime.jsx("div", { flexGrow: true }),
329
- /* @__PURE__ */ jsxRuntime.jsx("div", { ref, dflex: true, flexRow: true, gap: "3" }),
330
- children
331
- ] }) });
332
- }
333
- function PageTopBarToolbar({ trackingRef, children }) {
334
- const { containerEl } = usePageTabbedTopBarContext();
335
- const [visible, setVisible] = React8__default.default.useState(false);
336
- const portal = React8__default.default.useMemo(() => {
337
- const node = containerEl;
338
- return node;
339
- }, [containerEl]);
340
- const host = containerEl ?? (typeof window !== "undefined" ? document.body : void 0);
341
- React8__default.default.useLayoutEffect(() => {
342
- if (!portal || !host)
343
- return;
344
- try {
345
- if (visible)
346
- host.appendChild(portal);
347
- else
348
- host.removeChild(portal);
349
- } catch (e) {
350
- }
351
- return () => {
352
- try {
353
- host.removeChild(portal);
354
- } catch (e) {
355
- }
356
- };
357
- }, [visible, portal, host]);
358
- const callback = React8__default.default.useCallback((entries) => {
359
- setVisible(entries[0].isVisible);
360
- }, [children]);
361
- React8__default.default.useEffect(() => {
362
- const opts = {
363
- root: null,
364
- rootMargin: "0px",
365
- threshold: 0,
366
- /* required options*/
367
- trackVisibility: true,
368
- delay: 100
369
- };
370
- const observerScroll = new IntersectionObserver(callback, opts);
371
- if (trackingRef)
372
- observerScroll.observe(trackingRef);
373
- return () => observerScroll.disconnect();
374
- }, [trackingRef, callback, children]);
375
- if (host && portal)
376
- return reactDom.createPortal(children, portal);
377
- return null;
378
- }
379
- function ScreenTopBar({ tabbed, breadcrumbs, api, item, isLoading, buttonBar, trackingRef }) {
380
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
381
- tabbed && /* @__PURE__ */ jsxRuntime.jsx(PageTopBarToolbar, { trackingRef, children: /* @__PURE__ */ jsxRuntime.jsx(Buttons, { api, item, isLoading, buttonBar }) }),
382
- !tabbed && /* @__PURE__ */ jsxRuntime.jsx(PageTopBar, { breadcrumbs, children: /* @__PURE__ */ jsxRuntime.jsx(Buttons, { api, item, isLoading, buttonBar }) })
383
- ] });
384
- }
385
- function Buttons({ api, item, isLoading, buttonBar }) {
386
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
387
- buttonBar && buttonBar.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(ButtonBar, { children: buttonBar.map((button, index) => /* @__PURE__ */ jsxRuntime.jsxs(React8__default.default.Fragment, { children: [
388
- button.type === "link" && /* @__PURE__ */ jsxRuntime.jsx(ViewButton, { label: button.label, path: button.path, icon: button.icon }),
389
- button.type === "invalidate" && /* @__PURE__ */ jsxRuntime.jsx(InvalidateButton, { pathOrPermalink: button.pathOrPermalink }),
390
- button.type == "custom" && button.render(item)
391
- ] }, index)) }),
392
- /* @__PURE__ */ jsxRuntime.jsxs(ButtonBar, { children: [
393
- api instanceof adminApi.API && /* @__PURE__ */ jsxRuntime.jsx(PublishButton, { api, queryId: item.id, status: item.status, disabled: isLoading }),
394
- /* @__PURE__ */ jsxRuntime.jsx(UpdateButton, { disabled: isLoading })
395
- ] })
396
- ] });
397
- }
398
- function useQueryField(queryField, useNextRouter) {
399
- if (useNextRouter) {
400
- const router$1 = router.useRouter();
401
- return router$1.query[queryField];
402
- }
403
- const { [queryField]: id } = reactRouterDom.useParams();
404
- return id;
405
- }
406
- function DetailsView({ queryField, api, useNextRouter, processInput, screen, tabbed, ...props }) {
407
- const id = useQueryField(queryField, useNextRouter);
408
- const ref = React8__default.default.useRef(null);
409
- return /* @__PURE__ */ jsxRuntime.jsx(PageQueryStateContainer, { api, apiFn: "get", queryId: id, ref, p: "5", ...props, children: (item) => /* @__PURE__ */ jsxRuntime.jsx(Internal, { item, screen, api, tabbed, processInput, containerRef: ref }) });
410
- }
411
- function Internal({ item, screen, api: api$1, processInput, tabbed, containerRef }) {
412
- const pScreen = react.runIfFn(screen, item);
413
- const { breadcrumbs, schema, initialValues, header, sections, buttonBar, type, invalidateParentQueryKey, invalidatePage } = pScreen;
414
- const mutation = api.useInvalidateParentMutation(api$1.update, invalidateParentQueryKey ?? api$1.queryKey, { networkMode: "always" });
415
- const invalidatePageFn = adminApi.useInvalidatePage(invalidatePage || "");
416
- const save = api.useMutate(mutation, {
417
- processInput,
418
- successMsg: (item2, values) => `${item2.title || item2.name} updated.`,
419
- errorMsg: (error, item2) => `Error updating ${item2.title || item2.name}: ${error}`,
420
- onSuccess: () => {
421
- if (invalidatePage)
422
- invalidatePageFn();
423
- }
424
- });
425
- let editorMaxW = void 0;
426
- if (!type || type == "post")
427
- editorMaxW = "calc(1280px - 28rem)";
428
- else if (type == "section")
429
- editorMaxW = "calc(1280px - 22rem)";
430
- return /* @__PURE__ */ jsxRuntime.jsxs(
431
- form.FormProvider,
432
- {
433
- initialValues: react.runIfFn(initialValues, item),
434
- validationSchema: schema,
435
- onSubmit: save,
436
- enableReinitialize: true,
437
- children: [
438
- /* @__PURE__ */ jsxRuntime.jsx(
439
- ScreenTopBar,
440
- {
441
- tabbed,
442
- api: api$1,
443
- breadcrumbs,
444
- buttonBar,
445
- item,
446
- isLoading: mutation.isLoading,
447
- trackingRef: containerRef?.current
448
- }
449
- ),
450
- type == "form" && sections?.map((section, index) => /* @__PURE__ */ jsxRuntime.jsx(Section, { section, item }, index)),
451
- (pScreen.type == "post" || pScreen.type == "section") && /* @__PURE__ */ jsxRuntime.jsx("div", { p: "5", bgColor: "slate-100", rounded: "lg", children: /* @__PURE__ */ jsxRuntime.jsxs(PageContainer, { w: editorMaxW ? "auto" : "full", size: "x2", id: "pagecontainer", children: [
452
- header,
453
- /* @__PURE__ */ jsxRuntime.jsxs("div", { dflex: true, gap: "5", children: [
454
- /* @__PURE__ */ jsxRuntime.jsxs("div", { dflex: true, flexCol: true, gap: "8", flexGrow: true, children: [
455
- pScreen.editor?.type != "textarea" && // TODO Find a way to make this editor shrink in width when resizing the window...
456
- /* @__PURE__ */ jsxRuntime.jsx(PageContentEditor, { name: "content", maxW: editorMaxW, minW: "144", shadow: true, rounded: "lg" }),
457
- pScreen.editor?.type == "textarea" && /* @__PURE__ */ jsxRuntime.jsx(
458
- form.TextArea,
459
- {
460
- name: pScreen.editor?.name,
461
- maxW: editorMaxW,
462
- minW: editorMaxW,
463
- w: editorMaxW,
464
- minH: "128",
465
- rows: 25,
466
- bgColor: "white",
467
- border: "0",
468
- shadow: true,
469
- p: "5",
470
- textColor: "slate-800"
471
- }
472
- ),
473
- pScreen.editorFooter
474
- ] }),
475
- /* @__PURE__ */ jsxRuntime.jsx(PageSidebar, { children: sections?.map((section, index) => /* @__PURE__ */ jsxRuntime.jsx(Section, { section, item, cardStyle: true }, index)) })
476
- ] })
477
- ] }) })
478
- ]
479
- }
480
- );
481
- }
482
- function Section({ section, item, cardStyle }) {
483
- if (section.type === "section") {
484
- const style = cardStyle ? {
485
- bgColor: "white",
486
- rounded: "lg",
487
- p: "5",
488
- textSize: "sm",
489
- shadow: true
490
- } : {};
491
- return /* @__PURE__ */ jsxRuntime.jsx(PageSidebarSection, { title: section.title, ...style, children: /* @__PURE__ */ jsxRuntime.jsx(form.FormRenderer, { form: react.runIfFn(section.form, item) }) });
492
- }
493
- if (section.type === "custom")
494
- return react.runIfFn(section.component, item);
495
- return null;
496
- }
497
- function useApi(api, queryField) {
498
- const params = reactRouterDom.useParams();
499
- if (queryField === void 0)
500
- return { id: void 0, api };
501
- const { [queryField]: id } = params;
502
- return { id, api: react.runIfFn(api, id) };
503
- }
504
- function QueryWrapper({
505
- api: api$1,
506
- queryField,
507
- fn,
508
- transformFn,
509
- config,
510
- tabbed,
511
- ...props
512
- }) {
513
- const { id, api: mApi } = useApi(api$1, queryField);
514
- const { data } = api.useApiQuery(mApi.queryKey, fn === "get" || fn === "getTransformed" ? mApi.get : mApi.getAll, react.isFunction(api$1) ? void 0 : id);
515
- const transformedData = React8__default.default.useMemo(() => {
516
- if (data && (fn === "getTransformed" || fn === "getAllTransformed")) {
517
- if (!transformFn)
518
- console.warn(`QueryWrapperDialog: you forgot to pass transformFn as parameter for fn ${fn}`);
519
- return transformFn?.(data);
520
- }
521
- return data;
522
- }, [data]);
523
- if (!data)
524
- return null;
525
- return /* @__PURE__ */ jsxRuntime.jsx(ScreenRenderer, { config: config(transformedData), tabbed, ...props });
526
- }
527
- function TabbedView({ queryField, api, screen, ...props }) {
528
- const { [queryField]: id } = reactRouterDom.useParams();
529
- return /* @__PURE__ */ jsxRuntime.jsx(
530
- PageQueryStateContainer,
531
- {
532
- queryId: id,
533
- api,
534
- apiFn: "get",
535
- p: "5",
536
- children: (city) => {
537
- const { breadcrumbs, tabs } = react.runIfFn(screen, city);
538
- return /* @__PURE__ */ jsxRuntime.jsxs(PageTabbedTopBarProvider, { children: [
539
- /* @__PURE__ */ jsxRuntime.jsx(PageTabbedTopBar, { breadcrumbs, mb: "-3" }),
540
- /* @__PURE__ */ jsxRuntime.jsx(
541
- components.TabContainer,
542
- {
543
- tabs: tabs.map((tab) => tab.label),
544
- saveKey: `tab-${id}`,
545
- mt: "-3",
546
- mb: "3",
547
- id: "fff",
548
- children: tabs.map((tab, index) => /* @__PURE__ */ jsxRuntime.jsx(TabView, { tab }, index))
549
- }
550
- )
551
- ] });
552
- }
553
- }
554
- );
555
- }
556
- function TabView({ tab }) {
557
- if (!tab.component && !tab.config)
558
- throw new Error(`Screen config for tabbed view: one of your tabs does not have a component or config declared: ${tab.label}`);
559
- if (tab.component)
560
- return tab.component();
561
- return /* @__PURE__ */ jsxRuntime.jsx(ScreenRenderer, { config: tab.config, tabbed: true, p: "0" });
562
- }
563
- var [provider, useContext] = react.createContext();
564
- function getColId(column) {
565
- return column.accessorKey ?? column.id;
566
- }
567
- function TableContainerContextProvider({ initialVisibleColumns, columns, children }) {
568
- const [showFilters, setShowFilters] = React8__default.default.useState(false);
569
- const [showMassActions, setShowMassActions] = React8__default.default.useState(false);
570
- const [visibleColumnIds, setVisibleColumnIds] = React8__default.default.useState(initialVisibleColumns ?? columns?.map((col) => getColId(col)) ?? []);
571
- const filteredColumns = columns?.filter((col) => visibleColumnIds.includes(getColId(col))) ?? [];
572
- const toggleColumnVisibility = React8__default.default.useCallback((id) => {
573
- const index = visibleColumnIds.indexOf(id);
574
- if (index > -1) {
575
- const newIds = visibleColumnIds.concat();
576
- newIds.splice(index, 1);
577
- setVisibleColumnIds(newIds);
578
- } else {
579
- setVisibleColumnIds(visibleColumnIds.concat(id));
580
- }
581
- }, [visibleColumnIds, setVisibleColumnIds]);
582
- const isColumnVisible = React8__default.default.useCallback((id) => {
583
- return visibleColumnIds.includes(id);
584
- }, [visibleColumnIds]);
585
- const Provider = provider;
586
- const value = {
587
- showFilters,
588
- setShowFilters,
589
- showMassActions,
590
- setShowMassActions,
591
- columns: columns ?? [],
592
- filteredColumns,
593
- toggleColumnVisibility,
594
- isColumnVisible
595
- };
596
- return /* @__PURE__ */ jsxRuntime.jsx(Provider, { value, children });
597
- }
598
- function TableContainer({ initialPageSize, initialVisibleColumns, columns, filtersMethod = "reactRouter", children, ...props }) {
599
- return /* @__PURE__ */ jsxRuntime.jsx("div", { w: "full", dflex: true, flexCol: true, ...props, children: /* @__PURE__ */ jsxRuntime.jsx(table.TableContextProvider, { initialPageSize, filtersMethod, children: /* @__PURE__ */ jsxRuntime.jsx(TableContainerContextProvider, { columns, initialVisibleColumns, children }) }) });
600
- }
601
- function TableCreateButton({ icon, children, ...props }) {
602
- return /* @__PURE__ */ jsxRuntime.jsxs(ButtonBarDialogButton, { ...props, children: [
603
- /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { path: icon ?? js.mdiPlusThick }),
604
- children
605
- ] });
606
- }
607
- function TableFilterButton({ ...props }) {
608
- return /* @__PURE__ */ jsxRuntime.jsxs(ui.Popover, { side: "bottom-end", modal: true, children: [
609
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { scheme: "dark", size: "sm", aspectRatio: "square", variant: "borderless", corners: "square", ...props, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { path: js.mdiFilter }) }),
610
- /* @__PURE__ */ jsxRuntime.jsxs("div", { bgColor: "white", rounded: true, shadow: true, children: [
611
- /* @__PURE__ */ jsxRuntime.jsx("div", { py: "3", hover_bgColor: "#ff0000", px: "5", hover_textColor: "white", children: "First Item" }),
612
- /* @__PURE__ */ jsxRuntime.jsx("div", { py: "3", hover_bgColor: "#ff0000", px: "5", hover_textColor: "white", children: "Second Item" }),
613
- /* @__PURE__ */ jsxRuntime.jsx("div", { py: "3", hover_bgColor: "#ff0000", px: "5", hover_textColor: "white", children: "Third Item" })
614
- ] })
615
- ] });
616
- }
617
- function TableTopBar({ title, breadcrumbs, children, ...props }) {
618
- return /* @__PURE__ */ jsxRuntime.jsxs(
619
- "div",
620
- {
621
- dflex: true,
622
- flexRow: true,
623
- alignItems: "center",
624
- gap: "3",
625
- p: "8",
626
- ...props,
627
- children: [
628
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
629
- title && /* @__PURE__ */ jsxRuntime.jsx("h2", { textSize: "x2", fontWeight: "600", textColor: "#3f4254", textTransform: "capitalize", children: title }),
630
- breadcrumbs && /* @__PURE__ */ jsxRuntime.jsx(Breadcrumbs, { breadcrumbs })
631
- ] }),
632
- /* @__PURE__ */ jsxRuntime.jsx("div", { flexGrow: true, children: "\xA0" }),
633
- children
634
- ]
635
- }
636
- );
637
- }
638
- function TableFilters({ form: form$1, initialValues, schema, processInput }) {
639
- const { showFilters } = useContext();
640
- const { getFilters, setFilters } = table.useTableContext();
641
- const handleSubmit = React8__default.default.useCallback((values, actions) => {
642
- const params = processInput?.(values) ?? values;
643
- if (!esToolkit.isEqual(params, getFilters()))
644
- setFilters(params);
645
- actions.setSubmitting(false);
646
- }, [setFilters, processInput]);
647
- const handleReset = React8__default.default.useCallback((resetForm) => {
648
- setFilters(initialValues);
649
- resetForm();
650
- }, [setFilters, initialValues]);
651
- React8__default.default.useEffect(() => setFilters(initialValues), []);
652
- return /* @__PURE__ */ jsxRuntime.jsx(ui.Collapse, { in: showFilters, style: { overflow: showFilters ? "initial" : "hidden" }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { p: "8", borderT: "px", borderB: "px", borderColor: "slate-100", children: /* @__PURE__ */ jsxRuntime.jsx(
653
- form.FormProvider,
654
- {
655
- initialValues: form.mergeInitialFormValues(getFilters(), initialValues),
656
- onSubmit: handleSubmit,
657
- validationSchema: schema,
658
- enableReinitialize: true,
659
- children: (props) => /* @__PURE__ */ jsxRuntime.jsxs("div", { dflex: true, gap: "3", placeContent: "start", children: [
660
- /* @__PURE__ */ jsxRuntime.jsx(form.FormRenderer, { flexRow: true, w: "auto", form: form$1 }),
661
- /* @__PURE__ */ jsxRuntime.jsx(Buttons2, { handleReset: () => handleReset(props.resetForm) })
662
- ] })
663
- }
664
- ) }) });
665
- }
666
- function Buttons2({ handleReset }) {
667
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { dflex: true, gap: "3", children: [
668
- /* @__PURE__ */ jsxRuntime.jsxs("div", { dflex: true, flexCol: true, children: [
669
- /* @__PURE__ */ jsxRuntime.jsx(form.FieldLabel, { name: "", label: "\xA0" }),
670
- /* @__PURE__ */ jsxRuntime.jsx(form.SubmitButton, { children: "Filter" })
671
- ] }),
672
- /* @__PURE__ */ jsxRuntime.jsxs("div", { dflex: true, flexCol: true, children: [
673
- /* @__PURE__ */ jsxRuntime.jsx(form.FieldLabel, { name: "", label: "\xA0" }),
674
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { scheme: "neutral", onClick: handleReset, children: "Reset" })
675
- ] })
676
- ] });
677
- }
678
- function ActionButton({
679
- label,
680
- buttonProps,
681
- icon,
682
- queryKey,
683
- queryFn,
684
- successMsg,
685
- errorMsg,
686
- invalidateParent
687
- }) {
688
- const mutation = invalidateParent ? api.useInvalidateParentMutation(queryFn, queryKey) : api.useApiMutation(queryFn, queryKey);
689
- const mutate = api.useMutate(
690
- mutation,
691
- {
692
- successMsg,
693
- errorMsg
694
- }
695
- );
696
- return /* @__PURE__ */ jsxRuntime.jsxs(
697
- ui.Button,
698
- {
699
- display: "flex",
700
- alignItems: "center",
701
- gap: "3",
702
- ...buttonProps,
703
- onClick: mutate,
704
- disabled: mutation.isLoading,
705
- children: [
706
- icon && /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { path: icon }),
707
- label
708
- ]
709
- }
710
- );
711
- }
712
- function TableMassActions({ actions }) {
713
- const { ids } = table.useTableContext();
714
- const showMassActions = ids && ids.length > 0;
715
- return /* @__PURE__ */ jsxRuntime.jsx(ui.Collapse, { in: showMassActions, style: { overflow: showMassActions ? "initial" : "hidden" }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { dflex: true, gap: "3", flexWrap: true, alignItems: "center", px: "8", pt: "5", children: actions.map((action, index) => /* @__PURE__ */ jsxRuntime.jsx("div", { children: action.type == "button" && !action.showConfirmationDialog && /* @__PURE__ */ jsxRuntime.jsx(ActionButton, { label: action.label, queryFn: action.queryFn, queryKey: action.queryKey, buttonProps: action.buttonProps }) }, index)) }) });
716
- }
717
- var defaultErrorMsg = "Oops, something went wrong...";
718
- function nonNullValues(data) {
719
- if (data) {
720
- const nonNullData = { ...data };
721
- for (const key in data)
722
- nonNullData[key] = nonNullData[key] ?? "";
723
- return nonNullData;
724
- }
725
- return data;
726
- }
727
- function ItemEditDialog({
728
- initialValues,
729
- itemLabel,
730
- queryId = "",
731
- api: api$1,
732
- queryFetchOptions,
733
- querySaveOptions,
734
- onSuccess,
735
- onFetchError,
736
- fetchErrorMsg = defaultErrorMsg,
737
- onSaveError,
738
- saveErrorMsg = defaultErrorMsg,
739
- fetchToFormData,
740
- formToQueryData,
741
- invalidateQueriesOnSuccess = true,
742
- invalidateQueryKey,
743
- retryText = "Retry",
744
- cancelLabel = "Cancel",
745
- saveLabel,
746
- size = "lg",
747
- title,
748
- form: form$1,
749
- show,
750
- onClose,
751
- formikProps,
752
- ...props
753
- }) {
754
- const { isInitialLoading, isFetching, data, isError, error, refetch } = api.useApiQuery(api$1.queryKey, api$1.get, queryId, {
755
- enabled: !/*queryId == 0 || */
756
- (queryId == "" || queryId == null || queryId == void 0),
757
- // means than this query is only enabled if the id is defined
758
- onError: onFetchError,
759
- ...queryFetchOptions
760
- });
761
- const mutation = invalidateQueriesOnSuccess ? api.useInvalidateParentMutation(api$1.upsert, invalidateQueryKey ?? api$1.queryKey, querySaveOptions) : api.useApiMutation(api$1.upsert, api$1.queryKey, queryId, querySaveOptions);
762
- const retry = React8__default.default.useCallback(() => refetch(), [refetch]);
763
- const saveItem = React8__default.default.useCallback(async (item, actions) => {
764
- mutation.reset();
765
- const formItem = formToQueryData ? formToQueryData(item) : { ...item };
766
- await mutation.mutateAsync(formItem).then((response) => {
767
- if (onSuccess)
768
- onSuccess(formItem, response);
769
- else
770
- reactToastify.toast.success(`${title ? title(formItem) : formItem.name ?? formItem.title} ${queryId ? "saved" : "created"}`);
771
- onClose?.();
772
- }).catch((error2) => {
773
- console.error("on error", error2);
774
- if (onSaveError)
775
- onSaveError(item);
776
- else
777
- reactToastify.toast.error(`Couldn't save ${title ? title(formItem) : formItem.name ?? formItem.title}`);
778
- actions.setSubmitting(false);
779
- });
780
- }, [mutation, formToQueryData, onSuccess, onSaveError, onClose]);
781
- return /* @__PURE__ */ jsxRuntime.jsxs(
782
- ui.Modal,
783
- {
784
- size,
785
- show,
786
- onClose,
787
- scheme: "light",
788
- transition: true,
789
- ...props,
790
- children: [
791
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Modal.Header, { children: [
792
- !isInitialLoading && queryId && `Edit ${title ? title(data) : data?.["name"] ?? data?.["title"] ?? data?.["name"] ?? ""}`,
793
- !queryId && `Create new ${itemLabel ?? "item"}`,
794
- Array.isArray(form$1) && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, {})
795
- ] }),
796
- isInitialLoading && /* @__PURE__ */ jsxRuntime.jsx(ui.Modal.Body, { children: /* @__PURE__ */ jsxRuntime.jsx(components.QueryLoadingState, { minW: "72" }) }),
797
- isError && /* @__PURE__ */ jsxRuntime.jsx(ui.Modal.Body, { children: /* @__PURE__ */ jsxRuntime.jsx(components.RetryOnError, { label: `${fetchErrorMsg} ${error}`, onClick: retry }) }),
798
- !isInitialLoading && !isError && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsx(
799
- formik.Formik,
800
- {
801
- initialValues: fetchToFormData && queryId && data ? fetchToFormData(nonNullValues(data)) : nonNullValues(initialValues(data)) ?? {},
802
- onSubmit: saveItem,
803
- ...formikProps,
804
- children: ({ setFieldValue, dirty, handleSubmit, isValid, values }) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
805
- /* @__PURE__ */ jsxRuntime.jsx(ui.Modal.Body, { pb: "6", children: /* @__PURE__ */ jsxRuntime.jsxs(formik.Form, { children: [
806
- React8__default.default.isValidElement(form$1) && form$1,
807
- Array.isArray(form$1) && /* @__PURE__ */ jsxRuntime.jsx(form.FormRenderer, { form: form$1 }),
808
- react.isFunction(form$1) && /* @__PURE__ */ jsxRuntime.jsx(form.FormRenderer, { form: form$1(data ?? values) })
809
- ] }) }),
810
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Modal.Footer, { dflex: true, placeContent: "end", spaceX: "3", children: [
811
- /* @__PURE__ */ jsxRuntime.jsx(
812
- ui.Button,
813
- {
814
- disabled: mutation.isLoading,
815
- onClick: onClose,
816
- variant: "borderless",
817
- me: "2",
818
- children: cancelLabel
819
- }
820
- ),
821
- /* @__PURE__ */ jsxRuntime.jsx(
822
- ui.Button,
823
- {
824
- type: "submit",
825
- disabled: !dirty || mutation.isLoading,
826
- onClick: () => handleSubmit(),
827
- children: saveLabel ? saveLabel : queryId ? "Update" : "Create"
828
- }
829
- )
830
- ] })
831
- ] })
832
- }
833
- ) }),
834
- mutation.isLoading && /* @__PURE__ */ jsxRuntime.jsx(components.ModalLoadingOverlay, {})
835
- ]
836
- }
837
- );
838
- }
839
- function QueryWrapperDialog({ api: api$1, fn, transformFn, config, onClose, queryId, invalidateQueryKey }) {
840
- const { data, isFetching } = api.useApiQuery(
841
- api$1.queryKey,
842
- fn === "get" || fn === "getTransformed" ? api$1.get : api$1.getAll,
843
- void 0,
844
- { retryOnMount: false, refetchOnMount: false, refetchOnWindowFocus: false }
845
- );
846
- const transformedData = React8__default.default.useMemo(() => {
847
- if (data && (fn === "getTransformed" || fn === "getAllTransformed")) {
848
- if (!transformFn)
849
- console.warn(`QueryWrapperDialog: you forgot to pass transformFn as parameter for fn ${fn}`);
850
- return transformFn?.(data);
851
- }
852
- return data;
853
- }, [data, fn, transformFn]);
854
- if (isFetching)
855
- return null;
856
- return /* @__PURE__ */ jsxRuntime.jsx(ItemEditDialog, { ...config(transformedData), queryId, invalidateQueryKey, show: true, onClose });
857
- }
858
- function MultiQueryWrapperDialog({ queries, config, onClose, queryId, invalidateQueryKey }) {
859
- const { data, isFetching, isError } = api.useApiQueries(queries.map((q) => ({
860
- queryKey: q.api.queryKey,
861
- queryFn: q.fn == "get" ? q.api.get : q.api.getAll,
862
- queryOptions: {
863
- cacheTime: q.cache === false ? 0 : void 0,
864
- staleTime: q.cache === false ? 0 : void 0
865
- }
866
- })));
867
- const transformedData = React8__default.default.useMemo(() => {
868
- return data?.map((d, index) => queries[index]?.transformFn ? queries[index]?.transformFn?.(d) : d);
869
- }, [data, queries]);
870
- return /* @__PURE__ */ jsxRuntime.jsx(ItemEditDialog, { isPreloading: isFetching, ...config(...transformedData), queryId, invalidateQueryKey, show: true, onClose });
871
- }
872
- function DialogRenderer({ config, onClose, invalidateQueryKey, queryId }) {
873
- const { type, ...props } = config;
874
- if (config.type === "dialog")
875
- return /* @__PURE__ */ jsxRuntime.jsx(ItemEditDialog, { ...props, queryId, invalidateQueryKey, show: true, onClose });
876
- if (config.type === "query")
877
- return /* @__PURE__ */ jsxRuntime.jsx(QueryWrapperDialog, { ...props, queryId, invalidateQueryKey, onClose });
878
- if (config.type === "multiQuery")
879
- return /* @__PURE__ */ jsxRuntime.jsx(MultiQueryWrapperDialog, { ...props, queryId, invalidateQueryKey, onClose });
880
- return null;
881
- }
882
- function RefreshButton({ queryKey }) {
883
- const invalidate = api.useInvalidateQuery(queryKey);
884
- reactHotkeysHook.useHotkeys("ctrl+r", () => invalidate(), { preventDefault: true }, [invalidate]);
885
- return /* @__PURE__ */ jsxRuntime.jsx(ButtonBarButton, { scheme: "dark", size: "sm", aspectRatio: "square", variant: "borderless", onClick: invalidate, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { path: js.mdiRefresh }) });
886
- }
887
- function ItemDeleteDialog({
888
- title,
889
- actionButtonLabel,
890
- closeActionButtonLabel = "Cancel",
891
- itemLabel,
892
- queryId = "",
893
- api: api$1,
894
- apiFn,
895
- invalidateQueriesOnSuccess = true,
896
- invalidateQueryKey,
897
- size = "lg",
898
- md_boxSizing,
899
- msg,
900
- show,
901
- onClose,
902
- onSuccess,
903
- ...props
904
- }) {
905
- const fn = apiFn ? api$1[apiFn] : api$1.delete;
906
- const mutation = invalidateQueriesOnSuccess ? api.useInvalidateParentMutation(fn, invalidateQueryKey ?? api$1.queryKey) : api.useApiMutation(fn, api$1.queryKey);
907
- const mutate = api.useMutate(mutation, { onSuccess: () => {
908
- onClose?.();
909
- onSuccess?.();
910
- } });
911
- const handleDelete = React8__default.default.useCallback(() => mutate(queryId), [mutate, queryId]);
912
- return /* @__PURE__ */ jsxRuntime.jsxs(
913
- ui.Modal,
914
- {
915
- size,
916
- show,
917
- onClose,
918
- scheme: "danger",
919
- variant: "glass",
920
- transition: true,
921
- ...props,
922
- children: [
923
- /* @__PURE__ */ jsxRuntime.jsx(ui.Modal.Header, { children: title || `Delete ${itemLabel}` }),
924
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Modal.Body, { pb: "6", children: [
925
- !msg && `Do you really want to delete ${itemLabel}?`,
926
- msg && react.runIfFn(msg, itemLabel)
927
- ] }),
928
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Modal.Footer, { dflex: true, placeContent: "end", spaceX: "3", children: [
929
- /* @__PURE__ */ jsxRuntime.jsx(
930
- ui.Button,
931
- {
932
- disabled: mutation.isPending,
933
- onClick: onClose,
934
- variant: "borderless",
935
- scheme: "dark",
936
- me: "2",
937
- children: closeActionButtonLabel
938
- }
939
- ),
940
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { scheme: "danger", disabled: mutation.isPending, onClick: handleDelete, children: actionButtonLabel || "Delete" })
941
- ] }),
942
- mutation.isPending && /* @__PURE__ */ jsxRuntime.jsx(components.ModalLoadingOverlay, {})
943
- ]
944
- }
945
- );
946
- }
947
- var [provider2, useContext2] = react.createContext();
948
- function TableViewProvider({ editView, deleteItem, queryKey, children }) {
949
- const openLink = hooks.useOpenLink();
950
- const navigate = reactRouterDom.useNavigate();
951
- const [dialog, setDialog] = React8__default.default.useState(null);
952
- const onCloseDialog = React8__default.default.useCallback(() => setDialog(null), [setDialog]);
953
- const onAction = React8__default.default.useCallback((action, item) => {
954
- switch (action.type) {
955
- case "view": {
956
- navigate(react.runIfFn(action.path, item));
957
- break;
958
- }
959
- case "link": {
960
- openLink(`${env.AppEnv.websiteUrl()}/${react.runIfFn(action.path, item)}`);
961
- break;
962
- }
963
- case "edit": {
964
- const editConfig = react.runIfFn(editView, item);
965
- if (editConfig) {
966
- if (editConfig.type == "customDialog") {
967
- setDialog(editConfig.render({ show: true, onClose: onCloseDialog }));
968
- } else {
969
- setDialog(
970
- /* @__PURE__ */ jsxRuntime.jsx(
971
- DialogRenderer,
972
- {
973
- onClose: onCloseDialog,
974
- config: editConfig,
975
- queryId: item.id,
976
- invalidateQueryKey: queryKey
977
- }
978
- )
979
- );
980
- }
981
- }
982
- break;
983
- }
984
- case "delete": {
985
- const deleteConfig = react.runIfFn(deleteItem, item);
986
- setDialog(
987
- /* @__PURE__ */ jsxRuntime.jsx(
988
- ItemDeleteDialog,
989
- {
990
- show: true,
991
- onClose: onCloseDialog,
992
- queryId: item.id,
993
- invalidateQueryKey: queryKey,
994
- msg: item.msg,
995
- ...deleteConfig,
996
- itemLabel: react.runIfFn(deleteConfig.itemLabel, item)
997
- }
998
- )
999
- );
1000
- break;
1001
- }
1002
- }
1003
- }, [navigate, editView, deleteItem]);
1004
- const Provider = provider2;
1005
- const value = {
1006
- dialog,
1007
- onAction
1008
- };
1009
- return /* @__PURE__ */ jsxRuntime.jsx(Provider, { value, children });
1010
- }
1011
- function TableRowPublishPostButton({ id, api: api$1, status, invalidateQueryKey, ...props }) {
1012
- const isDraft = status == "draft";
1013
- const mutation = api.useInvalidateParentMutation(isDraft ? api$1.publish : api$1.unpublish, invalidateQueryKey ?? api$1.queryKey, { networkMode: "always" });
1014
- const publish = React8__default.default.useCallback((event) => {
1015
- event?.preventDefault();
1016
- event?.stopPropagation();
1017
- mutation.reset();
1018
- mutation.mutateAsync(id).then(() => reactToastify.toast.success(isDraft ? "Published!" : "Unpublished!")).catch((error) => reactToastify.toast.error(`Error: ${error}`));
1019
- }, [mutation, id]);
1020
- return /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "borderless", corners: "square", scheme: "dark", onClick: publish, ...props, children: /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { path: isDraft ? js.mdiPublish : js.mdiPublishOff, size: "sm" }) });
1021
- }
1022
- function TableRowActionButton({ icon, children, ...props }) {
1023
- return /* @__PURE__ */ jsxRuntime.jsxs(
1024
- ui.Button,
1025
- {
1026
- dflex: true,
1027
- alignContent: "center",
1028
- placeContent: "center",
1029
- py: "2.5",
1030
- px: "3",
1031
- h: "full",
1032
- size: "lg",
1033
- variant: "borderless",
1034
- corners: "square",
1035
- gap: "2",
1036
- ...props,
1037
- children: [
1038
- icon && /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { path: icon, size: "sm" }),
1039
- children
1040
- ]
1041
- }
1042
- );
1043
- }
1044
- function TableRowActionsView({ row, onAction, rowActions, api, queryKey }) {
1045
- const item = row.original;
1046
- return /* @__PURE__ */ jsxRuntime.jsx("div", { dflex: true, w: "full", alignItems: "stretch", placeContent: "end", h: "full", children: react.runIfFn(rowActions, item)?.map(
1047
- (action, index) => /* @__PURE__ */ jsxRuntime.jsxs(React8__default.default.Fragment, { children: [
1048
- action.type === "publish" && /* @__PURE__ */ jsxRuntime.jsx(TableRowPublishPostButton, { id: item.id, api: action.api ?? api, status: item.status, invalidateQueryKey: queryKey }),
1049
- action.type == "custom" && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: action.component(item, queryKey, action.icon, action.label) }),
1050
- !["publish", "custom"].includes(action.type) && /* @__PURE__ */ jsxRuntime.jsx(ActionButton2, { onClick: () => onAction(action, item), scheme: schemes[action.type], children: /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { path: icons[action.type], size: "sm" }) })
1051
- ] }, index)
1052
- ) });
1053
- }
1054
- function ActionButton2({ onClick, ...props }) {
1055
- const handleClick = React8__default.default.useCallback((event) => {
1056
- event?.preventDefault();
1057
- event?.stopPropagation();
1058
- onClick?.(event);
1059
- }, [onClick]);
1060
- return /* @__PURE__ */ jsxRuntime.jsx(
1061
- TableRowActionButton,
1062
- {
1063
- onClick: handleClick,
1064
- ...props
1065
- }
1066
- );
1067
- }
1068
- var icons = {
1069
- "link": js.mdiOpenInNew,
1070
- "view": js.mdiEye,
1071
- "edit": js.mdiPencil,
1072
- "delete": js.mdiDelete,
1073
- "publish": js.mdiDelete,
1074
- "custom": ""
1075
- };
1076
- var schemes = {
1077
- "link": "dark",
1078
- "view": "dark",
1079
- "edit": "dark",
1080
- "delete": "dark",
1081
- "publish": "dark",
1082
- "custom": "dark"
1083
- };
1084
- function useTableProps(api, table, rowActions, queryParams) {
1085
- const navigate = reactRouterDom.useNavigate();
1086
- const nextRouter = router.useRouter();
1087
- const openLink = hooks.useOpenLink();
1088
- const { onAction } = useContext2();
1089
- const { onRowClick, columns: c, ...props } = table;
1090
- const onRowClickHandler = React8__default.default.useCallback((item) => {
1091
- const config = react.runIfFn(onRowClick, item);
1092
- if (config) {
1093
- switch (config.type) {
1094
- case "navigate": {
1095
- navigate(react.runIfFn(config.path, item) ?? "");
1096
- break;
1097
- }
1098
- case "nextpush": {
1099
- nextRouter.push(react.runIfFn(config.path, item));
1100
- break;
1101
- }
1102
- case "link": {
1103
- openLink(`${env.AppEnv.websiteUrl()}/${react.runIfFn(config.path, item)}`);
1104
- break;
1105
- }
1106
- }
1107
- }
1108
- }, [navigate, onRowClick]);
1109
- const columns = React8__default.default.useMemo(() => {
1110
- const columns2 = table.columns.concat([]);
1111
- if (rowActions) {
1112
- columns2.push(
1113
- reactTable.createColumnHelper().display(
1114
- {
1115
- id: "actions",
1116
- header: "Actions",
1117
- cell: (props2) => /* @__PURE__ */ jsxRuntime.jsx(TableRowActionsView, { row: props2.row, onAction, rowActions, api, queryKey: api.queryKey })
1118
- }
1119
- )
1120
- );
1121
- }
1122
- return columns2;
1123
- }, [table, onAction, rowActions, api]);
1124
- const tableProps = { ...props };
1125
- tableProps.columns = columns;
1126
- tableProps.onRowClick = onRowClickHandler;
1127
- tableProps.queryKey = api.queryKey;
1128
- tableProps.queryFilters = queryParams;
1129
- tableProps.queryFn = api.search;
1130
- return tableProps;
1131
- }
1132
- function useId(queryField) {
1133
- const params = reactRouterDom.useParams();
1134
- if (queryField === void 0)
1135
- return void 0;
1136
- const { [queryField]: id } = params;
1137
- return id;
1138
- }
1139
- function TableView({ queryField, title, subtitle, screen, ...props }) {
1140
- const id = useId(queryField);
1141
- const _screen = react.runIfFn(screen, id);
1142
- return /* @__PURE__ */ jsxRuntime.jsx(PageContainer, { bgColor: "white", ...props, children: /* @__PURE__ */ jsxRuntime.jsx(TableContainer, { columns: _screen.table.columns, initialVisibleColumns: _screen.table.initialVisibleColumns, filtersMethod: _screen.table.filtersMethod, children: /* @__PURE__ */ jsxRuntime.jsx(TT, { id, title, subtitle, screen: _screen }) }) });
1143
- }
1144
- function TT({ id, title, subtitle, screen }) {
1145
- const { setRowSelection } = table.useTableContext();
1146
- const { api, table: table$1, filters, massActions, buttonBar, rowActions, createView, editView, deleteItem, breadcrumbs } = screen;
1147
- const tableApi = react.runIfFn(api, id ?? "");
1148
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1149
- /* @__PURE__ */ jsxRuntime.jsx(TableTopBar, { title, breadcrumbs, children: /* @__PURE__ */ jsxRuntime.jsx(TableButtonBar, { buttonBar, createView, editView, api: tableApi, queryKey: tableApi.queryKey, children: filters && /* @__PURE__ */ jsxRuntime.jsx(TableFilterButton, {}) }) }),
1150
- filters && /* @__PURE__ */ jsxRuntime.jsx(
1151
- TableFilters,
1152
- {
1153
- form: filters.form,
1154
- initialValues: filters.initialValues,
1155
- schema: filters.schema,
1156
- processInput: filters.processInput
1157
- }
1158
- ),
1159
- massActions && /* @__PURE__ */ jsxRuntime.jsx(TableMassActions, { actions: massActions.items }),
1160
- /* @__PURE__ */ jsxRuntime.jsxs(TableViewProvider, { queryKey: tableApi.queryKey, editView, deleteItem, children: [
1161
- /* @__PURE__ */ jsxRuntime.jsx(TableWrapper, { table: { ...table$1, onSelectionChange: setRowSelection }, rowActions, api: tableApi, subtitle, queryParams: screen.queryParams }),
1162
- /* @__PURE__ */ jsxRuntime.jsx(TableDialogManager, {})
1163
- ] })
1164
- ] });
1165
- }
1166
- function TableButtonBar({ buttonBar, queryKey, createView, editView, api, children }) {
1167
- const createDialogFn = React8__default.default.useCallback((data) => {
1168
- return (onClose) => {
1169
- const view = react.runIfFn(createView, data) ?? react.runIfFn(editView, null);
1170
- if (view.type == "customDialog")
1171
- return view.render({ show: true, onClose });
1172
- else
1173
- return /* @__PURE__ */ jsxRuntime.jsx(DialogRenderer, { config: view, onClose, invalidateQueryKey: api.queryKey });
1174
- };
1175
- }, [createView, editView, api]);
1176
- return /* @__PURE__ */ jsxRuntime.jsxs(ButtonBar, { children: [
1177
- /* @__PURE__ */ jsxRuntime.jsx(RefreshButton, { queryKey }),
1178
- buttonBar && buttonBar.map(
1179
- (button, index) => /* @__PURE__ */ jsxRuntime.jsxs(React8__default.default.Fragment, { children: [
1180
- button.type === "create" && editView && /* @__PURE__ */ jsxRuntime.jsx(
1181
- TableCreateButton,
1182
- {
1183
- buildDialog: createDialogFn(button.data),
1184
- icon: button.icon,
1185
- children: button.label
1186
- }
1187
- ),
1188
- button.type === "invalidate" && /* @__PURE__ */ jsxRuntime.jsx(InvalidateButton, { pathOrPermalink: button.pathOrPermalink }),
1189
- button.type === "custom" && button.render()
1190
- ] }, index)
1191
- ),
1192
- children
1193
- ] });
1194
- }
1195
- function TableWrapper({ table: table$1, subtitle, rowActions, api, queryParams }) {
1196
- const tableProps = useTableProps(api, table$1, rowActions, queryParams);
1197
- const _subtitle = React8__default.default.useMemo(() => {
1198
- if (!subtitle)
1199
- return void 0;
1200
- return (data) => {
1201
- return /* @__PURE__ */ jsxRuntime.jsx("div", { textSize: "lg", textColor: "#475569", fontWeight: "600", children: react.isFunction(subtitle) ? subtitle(data) : subtitle });
1202
- };
1203
- }, [subtitle]);
1204
- return /* @__PURE__ */ jsxRuntime.jsx(table.Table, { ...tableProps, p: "8", title: _subtitle });
1205
- }
1206
- function TableDialogManager() {
1207
- const { dialog } = useContext2();
1208
- return dialog;
1209
- }
1210
- function useQueries(queries) {
1211
- const params = reactRouterDom.useParams();
1212
- const { data, isFetching, isError } = api.useApiQueries(queries.map((q) => {
1213
- if (!q.queryField) {
1214
- const api2 = react.runIfFn(q.api);
1215
- return {
1216
- queryKey: api2.queryKey,
1217
- queryFn: q.fn == "get" ? api2.get : api2.getAll,
1218
- queryParam: q.params
1219
- };
1220
- }
1221
- const id = params[q.queryField];
1222
- const api = react.runIfFn(q.api, id);
1223
- return {
1224
- queryKey: api.queryKey,
1225
- queryFn: q.fn == "get" ? api.get : api.getAll,
1226
- queryParam: q.fn == "getAll" ? q.params : react.isFunction(q.api) ? void 0 : id
1227
- };
1228
- }));
1229
- let transformedData = void 0;
1230
- if (!isFetching && !isError) {
1231
- transformedData = data?.map((d, index) => queries[index].transformFn ? queries[index].transformFn?.(d) : d);
1232
- }
1233
- return { data: transformedData, isFetching, isError };
1234
- }
1235
- function useInvalidate(queries) {
1236
- const queryClient = reactQuery.useQueryClient();
1237
- const params = reactRouterDom.useParams();
1238
- const invalidate = React8__default.default.useCallback(
1239
- () => {
1240
- const queryKeys = [];
1241
- queries.forEach((q) => {
1242
- if (!q.queryField || !react.isFunction(q.api)) {
1243
- queryKeys.push(q.api.queryKey);
1244
- } else {
1245
- const id = params[q.queryField];
1246
- const api = react.runIfFn(q.api, id);
1247
- queryKeys.push(api.queryKey);
1248
- }
1249
- });
1250
- queryClient.invalidateQueries({ predicate: (query) => queryKeys.includes(query.queryKey) });
1251
- },
1252
- [queries, queryClient, params]
1253
- );
1254
- return invalidate;
1255
- }
1256
- function MultiQueryWrapper({
1257
- queries,
1258
- config,
1259
- tabbed,
1260
- ...props
1261
- }) {
1262
- const { data, isFetching, isError } = useQueries(queries);
1263
- const invalidate = useInvalidate(queries);
1264
- if (isFetching)
1265
- return /* @__PURE__ */ jsxRuntime.jsx(components.QueryLoadingState, { w: "full", h: "100vh" });
1266
- if (isError || !data)
1267
- return /* @__PURE__ */ jsxRuntime.jsx(components.RetryOnError, { p: "0", w: "full", h: "100vh", onClick: invalidate });
1268
- return /* @__PURE__ */ jsxRuntime.jsx(ScreenRenderer, { config: config(...data), tabbed, ...props });
1269
- }
1270
- function ScreenRenderer({ config, tabbed, ...props }) {
1271
- if (config.type === "table")
1272
- return /* @__PURE__ */ jsxRuntime.jsx(TableView, { ...config, ...props });
1273
- if (config.type === "tabbed")
1274
- return /* @__PURE__ */ jsxRuntime.jsx(TabbedView, { ...config, ...props });
1275
- if (config.type === "details")
1276
- return /* @__PURE__ */ jsxRuntime.jsx(DetailsView, { ...config, tabbed, ...props });
1277
- if (config.type === "query")
1278
- return /* @__PURE__ */ jsxRuntime.jsx(QueryWrapper, { ...config, tabbed, ...props });
1279
- if (config.type === "multiQuery")
1280
- return /* @__PURE__ */ jsxRuntime.jsx(MultiQueryWrapper, { ...config, tabbed, ...props });
1281
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, {});
1282
- }
1283
- function Content({ ...props }) {
1284
- return /* @__PURE__ */ jsxRuntime.jsx("div", { w: "100%", h: "100%", overflowY: "auto", ...props, children: /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Outlet, {}) });
1285
- }
1286
- function SelectedIndicator({ darkMode }) {
1287
- return /* @__PURE__ */ jsxRuntime.jsx(
1288
- "div",
1289
- {
1290
- position: "absolute",
1291
- bgColor: darkMode ? "white" : "black",
1292
- bgOpacity: "90",
1293
- w: "0.5",
1294
- h: "6",
1295
- top: "1.5",
1296
- start: "-4"
1297
- }
1298
- );
1299
- }
1300
- function MenuButton({ depth, darkMode, icon, selected, children, ...props }) {
1301
- return /* @__PURE__ */ jsxRuntime.jsxs(
1302
- ui.Button,
1303
- {
1304
- as: "li",
1305
- minH: "8",
1306
- ms: `${(depth ?? 0) * 2}`,
1307
- p: "2",
1308
- font: "title",
1309
- textColor: darkMode ? "white" : "black",
1310
- fontWeight: "600",
1311
- rounded: "lg",
1312
- textSize: "sm",
1313
- variant: "borderless",
1314
- hover_bgColor: darkMode ? "white" : "black",
1315
- hover_bgOpacity: "10",
1316
- hover_textColor: darkMode ? "white" : "zinc-800",
1317
- cursor: "pointer",
1318
- dflex: true,
1319
- alignItems: "center",
1320
- gap: "3",
1321
- ...props,
1322
- children: [
1323
- icon && /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { path: icon, opacity: selected ? "100" : "60" }),
1324
- children
1325
- ]
1326
- }
1327
- );
1328
- }
1329
- function MenuItem({ icon, path, depth, darkMode, subMenu, ...props }) {
1330
- const location = reactRouterDom.useLocation();
1331
- const selected = path == "/" ? location.pathname == "/" : location.pathname.startsWith(path.startsWith("/") ? path : `/${path}`);
1332
- const match = reactRouterDom.useMatch("/" + path) != null;
1333
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1334
- /* @__PURE__ */ jsxRuntime.jsxs(reactRouterDom.Link, { to: path, style: { position: "relative" }, children: [
1335
- /* @__PURE__ */ jsxRuntime.jsx(
1336
- MenuButton,
1337
- {
1338
- depth,
1339
- darkMode,
1340
- icon,
1341
- selected,
1342
- ...props
1343
- }
1344
- ),
1345
- match && /* @__PURE__ */ jsxRuntime.jsx(SelectedIndicator, { darkMode })
1346
- ] }),
1347
- subMenu?.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx(
1348
- MenuItem,
1349
- {
1350
- icon: item.icon,
1351
- path: item.path,
1352
- depth: (depth ?? 0) + 1,
1353
- darkMode,
1354
- subMenu: item.children,
1355
- children: item.label
1356
- },
1357
- index
1358
- ))
1359
- ] });
1360
- }
1361
- function NextMenuItem({ icon, path, depth, darkMode, subMenu, ...props }) {
1362
- const { pathname } = router.useRouter();
1363
- const selected = path == "/" ? pathname == "/" : pathname.startsWith(path.startsWith("/") ? path : `/${path}`);
1364
- const match = path == "/" ? pathname == "/" : pathname == (path.startsWith("/") ? path : `/${path}`);
1365
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1366
- /* @__PURE__ */ jsxRuntime.jsxs(Link__default.default, { href: path, style: { position: "relative" }, children: [
1367
- /* @__PURE__ */ jsxRuntime.jsx(
1368
- MenuButton,
1369
- {
1370
- depth,
1371
- darkMode,
1372
- icon,
1373
- selected,
1374
- ...props
1375
- }
1376
- ),
1377
- match && /* @__PURE__ */ jsxRuntime.jsx(SelectedIndicator, { darkMode })
1378
- ] }),
1379
- subMenu?.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx(
1380
- NextMenuItem,
1381
- {
1382
- icon: item.icon,
1383
- path: item.path,
1384
- depth: (depth ?? 0) + 1,
1385
- darkMode,
1386
- subMenu: item.children,
1387
- children: item.label
1388
- },
1389
- index
1390
- ))
1391
- ] });
1392
- }
1393
- function Menu({ darkMode, config, useNextRouter, ...props }) {
1394
- const Comp = useNextRouter ? NextMenuItem : MenuItem;
1395
- return /* @__PURE__ */ jsxRuntime.jsx("ul", { ...props, children: config.map((item, index) => {
1396
- if (item.type == "divider")
1397
- return /* @__PURE__ */ jsxRuntime.jsx(Divider, { title: item.label }, index);
1398
- if (item.type == "item") {
1399
- return /* @__PURE__ */ jsxRuntime.jsx(
1400
- Comp,
1401
- {
1402
- icon: item.icon,
1403
- path: item.path,
1404
- depth: 0,
1405
- darkMode,
1406
- subMenu: item.children,
1407
- children: item.label
1408
- },
1409
- index
1410
- );
1411
- }
1412
- }) });
1413
- }
1414
- function Divider({ title }) {
1415
- return /* @__PURE__ */ jsxRuntime.jsx(
1416
- "div",
1417
- {
1418
- px: "2",
1419
- mt: "5",
1420
- mb: "2",
1421
- opacity: "75",
1422
- textTransform: "capitalize",
1423
- letterSpacing: "widest",
1424
- fontWeight: "700",
1425
- textSize: "xs",
1426
- children: title
1427
- }
1428
- );
1429
- }
1430
- function UserBlock({ color, darkMode, menuConfig, path }) {
1431
- const { isLoading, user } = auth.useSessionUser();
1432
- const navigate = reactRouterDom.useNavigate();
1433
- const handleClick = React8__default.default.useCallback(() => navigate(path), [navigate, path]);
1434
- if (isLoading)
1435
- return null;
1436
- return /* @__PURE__ */ jsxRuntime.jsxs(
1437
- "div",
1438
- {
1439
- dflex: true,
1440
- alignItems: "center",
1441
- border: "0.5",
1442
- borderColor: `${color}-${darkMode ? "800" : "200"}`,
1443
- ps: "3",
1444
- py: "1.5",
1445
- textSize: "md",
1446
- rounded: "lg",
1447
- hover_bgColor: `${color}-${darkMode ? "800" : "200"}`,
1448
- cursor: "pointer",
1449
- textColor: darkMode ? "white" : "slate-800",
1450
- onClick: handleClick,
1451
- children: [
1452
- /* @__PURE__ */ jsxRuntime.jsx(ui.Avatar, { size: "sm", src: user?.media?.url ?? "", name: `${user?.firstname} ${user?.lastname}` }),
1453
- /* @__PURE__ */ jsxRuntime.jsx("span", { flexGrow: true, ms: "2", children: `${esToolkit.capitalize(user?.firstname || user?.lastname || "")}` }),
1454
- /* @__PURE__ */ jsxRuntime.jsx(
1455
- ui.IconButton,
1456
- {
1457
- variant: "borderless",
1458
- corners: "pill",
1459
- scheme: "dark",
1460
- textColor: darkMode ? "white" : "slate-800",
1461
- hover_textColor: darkMode ? "white" : "slate-800",
1462
- hover_bgColor: `${color}-${darkMode ? "900" : "200"}`,
1463
- icon: js.mdiCog,
1464
- onClick: handleClick
1465
- }
1466
- ),
1467
- /* @__PURE__ */ jsxRuntime.jsx(OverflowMenu, { color, darkMode, menuConfig })
1468
- ]
1469
- }
1470
- );
1471
- }
1472
- function OverflowMenu({ color, darkMode, menuConfig }) {
1473
- const [showPopup, setShowPopup] = React8__default.default.useState(false);
1474
- const navigate = reactRouterDom.useNavigate();
1475
- const logout = auth.useSessionLogout(false);
1476
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsxs(
1477
- ui.Popup,
1478
- {
1479
- show: showPopup,
1480
- position: "relative",
1481
- side: "bottom-end",
1482
- onClick: (e) => {
1483
- e.preventDefault();
1484
- e.stopPropagation();
1485
- setShowPopup((show) => !show);
1486
- },
1487
- onHide: () => setShowPopup(false),
1488
- children: [
1489
- /* @__PURE__ */ jsxRuntime.jsx(
1490
- ui.IconButton,
1491
- {
1492
- icon: js.mdiDotsVertical,
1493
- variant: "borderless",
1494
- corners: "pill",
1495
- scheme: "dark",
1496
- textColor: darkMode ? "white" : "slate-800",
1497
- hover_textColor: darkMode ? "white" : "slate-800",
1498
- hover_bgColor: `${color}-${darkMode ? "900" : "200"}`
1499
- }
1500
- ),
1501
- /* @__PURE__ */ jsxRuntime.jsxs(
1502
- "div",
1503
- {
1504
- bgColor: "white",
1505
- rounded: "sm",
1506
- overflow: "hidden",
1507
- shadow: true,
1508
- mt: "1",
1509
- border: "px",
1510
- borderColor: "gray-200",
1511
- divideColor: "gray-200",
1512
- divideY: "px",
1513
- minW: "40",
1514
- children: [
1515
- menuConfig && menuConfig.length > 0 && menuConfig.map((item, index) => {
1516
- if (item.type == "item") {
1517
- return /* @__PURE__ */ jsxRuntime.jsx(MenuItem2, { icon: item.icon, onClick: () => navigate(item.path), children: item.label }, index);
1518
- }
1519
- return null;
1520
- }),
1521
- /* @__PURE__ */ jsxRuntime.jsx(MenuItem2, { icon: js.mdiLogout, onClick: logout, children: "Logout" })
1522
- ]
1523
- }
1524
- )
1525
- ]
1526
- }
1527
- ) });
1528
- }
1529
- function MenuItem2({ icon, onClick, children, ...props }) {
1530
- const handleClick = React8__default.default.useCallback((e) => {
1531
- e.preventDefault();
1532
- e.stopPropagation();
1533
- onClick?.(e);
1534
- }, []);
1535
- return /* @__PURE__ */ jsxRuntime.jsxs(
1536
- ui.Button,
1537
- {
1538
- variant: "borderless",
1539
- scheme: "dark",
1540
- size: "sm",
1541
- alignItems: "center",
1542
- dflex: true,
1543
- gap: "2",
1544
- px: "2",
1545
- py: "1.5",
1546
- w: "full",
1547
- onClick: handleClick,
1548
- textColor: "slate-700",
1549
- ...props,
1550
- children: [
1551
- icon && /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { path: icon, size: "md" }),
1552
- children
1553
- ]
1554
- }
1555
- );
1556
- }
1557
- function Sidebar({ show, logo, title, menuConfig, userMenuConfig, userSettingsPath, color, darkMode, ...props }) {
1558
- return /* @__PURE__ */ jsxRuntime.jsxs(
1559
- "div",
1560
- {
1561
- dflex: true,
1562
- flexCol: true,
1563
- w: "full",
1564
- md_w: "64",
1565
- minH: "screen",
1566
- p: "0",
1567
- textColor: darkMode ? "white" : "slate-800",
1568
- ...props,
1569
- children: [
1570
- /* @__PURE__ */ jsxRuntime.jsxs(
1571
- components.FlexCenter,
1572
- {
1573
- placeContent: "start",
1574
- p: "4",
1575
- font: "title",
1576
- gap: "3",
1577
- borderB: "px",
1578
- borderBColor: "slate-900",
1579
- borderOpacity: "5",
1580
- children: [
1581
- logo ?? /* @__PURE__ */ jsxRuntime.jsx(Logo, { width: 40, height: 40, darkMode }),
1582
- /* @__PURE__ */ jsxRuntime.jsx("h1", { textSize: "md", children: title || env.AppEnv.appName() })
1583
- ]
1584
- }
1585
- ),
1586
- /* @__PURE__ */ jsxRuntime.jsx(Menu, { overflowY: "auto", flexGrow: "1", p: "4", darkMode, config: menuConfig }),
1587
- /* @__PURE__ */ jsxRuntime.jsx("div", { p: "2", children: /* @__PURE__ */ jsxRuntime.jsx(UserBlock, { darkMode, color, menuConfig: userMenuConfig, path: userSettingsPath }) })
1588
- ]
1589
- }
1590
- );
1591
- }
1592
- function Logo({ width, height, darkMode, ...props }) {
1593
- return /* @__PURE__ */ jsxRuntime.jsx("div", { ...props, children: /* @__PURE__ */ jsxRuntime.jsx(
1594
- Image__default.default,
1595
- {
1596
- src: `/logo_${darkMode ? "light" : "dark"}.png`,
1597
- alt: env.AppEnv.appName() || "",
1598
- width,
1599
- height,
1600
- priority: true,
1601
- unoptimized: true
1602
- }
1603
- ) });
1604
- }
1605
- function AdminLayout({ color, darkMode, logo, title, menuConfig, userMenuConfig, userSettingsPath, ...props }) {
1606
- return /* @__PURE__ */ jsxRuntime.jsxs(
1607
- "div",
1608
- {
1609
- w: "full",
1610
- h: "screen",
1611
- dflex: true,
1612
- flexRow: true,
1613
- bgColor: `${color}-${darkMode ? "900" : "100"}`,
1614
- ...props,
1615
- children: [
1616
- /* @__PURE__ */ jsxRuntime.jsx(
1617
- LeftPanel,
1618
- {
1619
- color,
1620
- darkMode,
1621
- logo,
1622
- title,
1623
- menuConfig,
1624
- userMenuConfig,
1625
- userSettingsPath
1626
- }
1627
- ),
1628
- /* @__PURE__ */ jsxRuntime.jsx("div", { w: "screen", py: "2", pe: "2", children: /* @__PURE__ */ jsxRuntime.jsx(Content, { bgColor: "white", rounded: "lg", shadow: true }) })
1629
- ]
1630
- }
1631
- );
1632
- }
1633
- function LeftPanel({ color, darkMode, logo, title, menuConfig, userMenuConfig, userSettingsPath }) {
1634
- const [isOpen, __, toggle] = hooks.useBoolean(true);
1635
- reactHotkeysHook.useHotkeys("ctrl+t", () => toggle(), [toggle]);
1636
- return /* @__PURE__ */ jsxRuntime.jsxs(
1637
- "div",
1638
- {
1639
- ms: isOpen ? "0" : "-14.5rem",
1640
- transition: "all",
1641
- duration: "500",
1642
- transform: true,
1643
- children: [
1644
- /* @__PURE__ */ jsxRuntime.jsx(
1645
- Sidebar,
1646
- {
1647
- flexShrink: "0",
1648
- color,
1649
- darkMode,
1650
- logo,
1651
- title,
1652
- menuConfig,
1653
- userMenuConfig,
1654
- userSettingsPath
1655
- }
1656
- ),
1657
- /* @__PURE__ */ jsxRuntime.jsx(
1658
- ui.IconButton,
1659
- {
1660
- icon: js.mdiArrowLeft,
1661
- transition: "all",
1662
- duration: "500",
1663
- transform: true,
1664
- rotate: isOpen ? "0" : "180",
1665
- position: "absolute",
1666
- bottom: "14",
1667
- end: "-5",
1668
- size: "lg",
1669
- corners: "pill",
1670
- onClick: toggle,
1671
- z: "100"
1672
- }
1673
- )
1674
- ]
1675
- }
1676
- );
1677
- }
1678
- var defaultErrorMsg2 = "Oops, something went wrong...";
1679
- function AttachDialog({
1680
- queryId,
1681
- queryKey,
1682
- queryFetchFn,
1683
- queryFetchAllKey,
1684
- queryFetchAllFn,
1685
- querySaveFn,
1686
- matchKey,
1687
- size = "lg",
1688
- show,
1689
- onClose,
1690
- itemLabel,
1691
- onSuccess,
1692
- onFetchError,
1693
- fetchErrorMsg = defaultErrorMsg2,
1694
- onSaveError,
1695
- saveErrorMsg = defaultErrorMsg2,
1696
- invalidateQueriesOnSuccess = true,
1697
- retryText = "Retry",
1698
- cancelLabel = "Cancel",
1699
- saveLabel,
1700
- formikProps,
1701
- getItemName,
1702
- ...props
1703
- }) {
1704
- const queryClient = reactQuery.useQueryClient();
1705
- const { data: attached, isInitialLoading: fetchLoading, isError: fetchError, refetch, error } = api.useApiQuery(queryKey, queryFetchFn);
1706
- const { data, isInitialLoading: fetchAllLoading, isError: fetchAllError, refetch: refetchAll, error: errorAll } = api.useApiQuery(queryFetchAllKey, queryFetchAllFn);
1707
- const [selectedResources, setSelectedResources] = React8__default.default.useState([]);
1708
- const isLoading = fetchLoading || fetchAllLoading;
1709
- const isError = fetchError || fetchAllError;
1710
- const mutation = api.useApiMutation(querySaveFn, queryKey, queryId);
1711
- const handleClick = React8__default.default.useCallback((event) => {
1712
- const id = event?.currentTarget.dataset.id ?? "";
1713
- const arr = selectedResources.concat([]);
1714
- const i = selectedResources.indexOf(id);
1715
- if (i != -1)
1716
- arr.splice(i, 1);
1717
- else
1718
- arr.push(id);
1719
- setSelectedResources(arr);
1720
- }, [selectedResources, setSelectedResources]);
1721
- const retry = React8__default.default.useCallback(() => {
1722
- if (fetchError)
1723
- refetch();
1724
- if (fetchAllError)
1725
- refetchAll();
1726
- }, [refetch, refetchAll, fetchError, fetchAllError]);
1727
- const saveItem = React8__default.default.useCallback(() => {
1728
- mutation.reset();
1729
- mutation.mutateAsync({ resources: selectedResources }).then((response) => {
1730
- if (onSuccess)
1731
- onSuccess(response);
1732
- else
1733
- reactToastify.toast.success(`${itemLabel} saved`);
1734
- if (invalidateQueriesOnSuccess)
1735
- queryClient.invalidateQueries({ queryKey });
1736
- onClose?.();
1737
- }).catch((error2) => {
1738
- console.error("on error", error2);
1739
- if (onSaveError)
1740
- onSaveError();
1741
- else
1742
- reactToastify.toast.error(`Error adding ${itemLabel}`);
1743
- });
1744
- }, [mutation, queryId, onSuccess, queryClient, onSaveError, onClose]);
1745
- const resources = React8__default.default.useMemo(() => {
1746
- let r = [];
1747
- if (attached && data) {
1748
- r = [].concat(data);
1749
- attached.forEach((attachedItem) => r.splice(r.findIndex((item) => item.id == attachedItem[matchKey]), 1));
1750
- if (getItemName)
1751
- r = r.map((item) => {
1752
- return { ...item, name: getItemName(item) };
1753
- });
1754
- r = esToolkit.sortBy(r, ["name"]);
1755
- }
1756
- return r;
1757
- }, [attached, data]);
1758
- return /* @__PURE__ */ jsxRuntime.jsxs(
1759
- ui.Modal,
1760
- {
1761
- size,
1762
- show,
1763
- onClose,
1764
- scheme: "light",
1765
- transition: true,
1766
- ...props,
1767
- children: [
1768
- /* @__PURE__ */ jsxRuntime.jsx(ui.Modal.Header, { children: `Add ${itemLabel}` }),
1769
- isLoading && /* @__PURE__ */ jsxRuntime.jsx(ui.Modal.Body, { children: /* @__PURE__ */ jsxRuntime.jsx(components.QueryLoadingState, { minW: "72" }) }),
1770
- isError && /* @__PURE__ */ jsxRuntime.jsx(ui.Modal.Body, { children: /* @__PURE__ */ jsxRuntime.jsx(components.RetryOnError, { label: `${fetchErrorMsg} ${error}`, onClick: retry }) }),
1771
- !isLoading && !isError && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1772
- /* @__PURE__ */ jsxRuntime.jsx(ui.Modal.Body, { px: "0", pb: "6", maxH: "750px", overflow: "auto", children: /* @__PURE__ */ jsxRuntime.jsx("div", { dflex: true, flexCol: true, overflow: "auto", children: resources.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
1773
- ListItem,
1774
- {
1775
- label: item.name,
1776
- value: item.id,
1777
- "data-id": item.id,
1778
- checked: selectedResources.includes(`${item.id}`),
1779
- onClick: handleClick
1780
- },
1781
- item.id
1782
- )) }) }),
1783
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Modal.Footer, { dflex: true, placeContent: "end", spaceX: "3", children: [
1784
- /* @__PURE__ */ jsxRuntime.jsx(
1785
- ui.Button,
1786
- {
1787
- disabled: mutation.isLoading,
1788
- onClick: onClose,
1789
- variant: "borderless",
1790
- me: "2",
1791
- children: cancelLabel
1792
- }
1793
- ),
1794
- /* @__PURE__ */ jsxRuntime.jsx(
1795
- ui.Button,
1796
- {
1797
- type: "submit",
1798
- disabled: selectedResources.length == 0 || mutation.isLoading,
1799
- onClick: saveItem,
1800
- children: saveLabel ? saveLabel : queryId ? "Update" : "Create"
1801
- }
1802
- )
1803
- ] })
1804
- ] }),
1805
- mutation.isLoading && /* @__PURE__ */ jsxRuntime.jsx(components.ModalLoadingOverlay, {})
1806
- ]
1807
- }
1808
- );
1809
- }
1810
- function ListItem({ label, value, checked, ...props }) {
1811
- return /* @__PURE__ */ jsxRuntime.jsxs(
1812
- "div",
1813
- {
1814
- dflex: true,
1815
- alignItems: "center",
1816
- hover_bgColor: "slate-100",
1817
- px: "5",
1818
- py: "2",
1819
- cursor: "pointer",
1820
- ...props,
1821
- children: [
1822
- /* @__PURE__ */ jsxRuntime.jsx("span", { flexGrow: true, children: label }),
1823
- /* @__PURE__ */ jsxRuntime.jsx(ui.Checkbox, { name: `resources.${value}`, value, checked })
1824
- ]
1825
- }
1826
- );
1827
- }
1828
- function FormActionDialog({
1829
- initialValues,
1830
- itemLabel,
1831
- queryId = "",
1832
- queryKey,
1833
- queryFn,
1834
- queryOptions,
1835
- onSuccess,
1836
- successMsg,
1837
- showSuccessMsg,
1838
- onError,
1839
- errorMsg,
1840
- showErrorMsg,
1841
- processInput,
1842
- invalidateQueriesOnSuccess = true,
1843
- cancelLabel = "Cancel",
1844
- saveLabel = "Send",
1845
- size = "lg",
1846
- title,
1847
- form: form$1,
1848
- show,
1849
- onClose,
1850
- formikProps,
1851
- ...props
1852
- }) {
1853
- const mutation = invalidateQueriesOnSuccess ? api.useInvalidateParentMutation(queryFn, queryKey, queryOptions) : api.useApiMutation(queryFn, queryKey, queryId, queryOptions);
1854
- const mutate = api.useMutate(mutation, {
1855
- onSuccess,
1856
- successMsg,
1857
- showSuccessMsg,
1858
- onError,
1859
- errorMsg,
1860
- showErrorMsg,
1861
- processInput
1862
- });
1863
- return /* @__PURE__ */ jsxRuntime.jsxs(
1864
- ui.Modal,
1865
- {
1866
- size,
1867
- show,
1868
- onClose,
1869
- scheme: "light",
1870
- transition: true,
1871
- ...props,
1872
- children: [
1873
- /* @__PURE__ */ jsxRuntime.jsx(ui.Modal.Header, { children: title }),
1874
- /* @__PURE__ */ jsxRuntime.jsxs(
1875
- form.FormProvider,
1876
- {
1877
- initialValues: initialValues ?? {},
1878
- onSubmit: mutate,
1879
- ...formikProps,
1880
- children: [
1881
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Modal.Body, { pb: "6", children: [
1882
- React8__default.default.isValidElement(form$1) && form$1,
1883
- Array.isArray(form$1) && /* @__PURE__ */ jsxRuntime.jsx(form.FormRenderer, { form: form$1 })
1884
- ] }),
1885
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Modal.Footer, { dflex: true, placeContent: "end", spaceX: "3", children: [
1886
- /* @__PURE__ */ jsxRuntime.jsx(
1887
- ui.Button,
1888
- {
1889
- disabled: mutation.isLoading,
1890
- onClick: onClose,
1891
- variant: "borderless",
1892
- me: "2",
1893
- children: cancelLabel
1894
- }
1895
- ),
1896
- /* @__PURE__ */ jsxRuntime.jsx(form.SubmitButton, { disabled: mutation.isLoading, children: saveLabel })
1897
- ] })
1898
- ]
1899
- }
1900
- ),
1901
- mutation.isLoading && /* @__PURE__ */ jsxRuntime.jsx(components.ModalLoadingOverlay, {})
1902
- ]
1903
- }
1904
- );
1905
- }
1906
- var PageStateContainer = React8__default.default.forwardRef(({ loading = false, children, ...props }, ref) => {
1907
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1908
- loading && /* @__PURE__ */ jsxRuntime.jsx(components.QueryLoadingState, { w: "full", h: "100%" }),
1909
- !loading && /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { ref, center: true, size: "x2", dflex: true, flexCol: true, gap: "8", ...props, children })
1910
- ] });
1911
- });
1912
- function PageSubSectionTitle({ children, ...props }) {
1913
- return /* @__PURE__ */ jsxRuntime.jsx("div", { trait: "typo.h6", mb: "3", ...props, children });
1914
- }
1915
- var labels = {
1916
- draft: "Draft",
1917
- published: "Published",
1918
- pending: "Pending",
1919
- approved: "Approved",
1920
- partially_approved: "Partially Approved",
1921
- rejected: "Rejected"
1922
- };
1923
- var schemes2 = {
1924
- draft: "warning",
1925
- published: "success",
1926
- pending: "secondary",
1927
- approved: "success",
1928
- partially_approved: "warning",
1929
- rejected: "danger"
1930
- };
1931
- function StatusBadge({ status, ...props }) {
1932
- return /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "sm", variant: "glass", whiteSpace: "nowrap", rounded: "full", px: "3", scheme: schemes2[status], ...props, children: labels[status] });
1933
- }
1934
- function TableRowViewButton({ path, ...props }) {
1935
- const openPage = React8__default.default.useCallback((event) => {
1936
- event?.preventDefault();
1937
- event?.stopPropagation();
1938
- window.open(`${env.AppEnv.websiteUrl()}/${path}`, "_blank");
1939
- }, [path]);
1940
- return /* @__PURE__ */ jsxRuntime.jsx(TableRowActionButton, { icon: js.mdiOpenInNew, onClick: openPage, ...props });
1941
- }
1942
- function TableRowNavigateButton({ path, ...props }) {
1943
- const navigate = reactRouterDom.useNavigate();
1944
- const handleClick = React8__default.default.useCallback((event) => {
1945
- event?.preventDefault();
1946
- event?.stopPropagation();
1947
- navigate(`${path}`);
1948
- }, [navigate, path]);
1949
- return /* @__PURE__ */ jsxRuntime.jsx(TableRowActionButton, { icon: js.mdiEye, onClick: handleClick, ...props });
1950
- }
1951
- function TableRowActionDialogButton({ icon, children, ...props }) {
1952
- return /* @__PURE__ */ jsxRuntime.jsxs(
1953
- DialogButton,
1954
- {
1955
- dflex: true,
1956
- alignContent: "center",
1957
- placeContent: "center",
1958
- py: "2.5",
1959
- px: "3",
1960
- h: "full",
1961
- size: "lg",
1962
- variant: "borderless",
1963
- corners: "square",
1964
- gap: "2",
1965
- ...props,
1966
- children: [
1967
- icon && /* @__PURE__ */ jsxRuntime.jsx(ui.Icon, { path: icon, size: "sm" }),
1968
- children
1969
- ]
1970
- }
1971
- );
1972
- }
1973
- function TableRowEditButton({ children, ...props }) {
1974
- return /* @__PURE__ */ jsxRuntime.jsx(TableRowActionDialogButton, { icon: js.mdiPencil, ...props, children });
1975
- }
1976
- function TableRowDeleteButton({ children, ...props }) {
1977
- return /* @__PURE__ */ jsxRuntime.jsx(TableRowActionDialogButton, { icon: js.mdiDelete, ...props, children });
1978
- }
1979
- function TableRowActionBar({
1980
- publishId,
1981
- viewPath,
1982
- navigatePath,
1983
- editDialog,
1984
- deleteDialog,
1985
- children,
1986
- ...props
1987
- }) {
1988
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { dflex: true, spaceX: "1", placeContent: "end", ...props, children: [
1989
- viewPath && /* @__PURE__ */ jsxRuntime.jsx(TableRowViewButton, { path: viewPath }),
1990
- navigatePath && /* @__PURE__ */ jsxRuntime.jsx(TableRowNavigateButton, { path: navigatePath }),
1991
- editDialog && /* @__PURE__ */ jsxRuntime.jsx(TableRowEditButton, { buildDialog: editDialog }),
1992
- deleteDialog && /* @__PURE__ */ jsxRuntime.jsx(TableRowDeleteButton, { buildDialog: deleteDialog }),
1993
- children
1994
- ] });
1995
- }
1996
- function TableRowPublishPostButton2({ id, api: api$1, status, invalidateQueryKey, ...props }) {
1997
- const isDraft = status == "draft";
1998
- const mutation = api.useInvalidateParentMutation(isDraft ? api$1.publish : api$1.unpublish, invalidateQueryKey ?? api$1.queryKey, { networkMode: "always" });
1999
- const publish = React8__default.default.useCallback((event) => {
2000
- event?.preventDefault();
2001
- event?.stopPropagation();
2002
- mutation.reset();
2003
- mutation.mutateAsync(id).then(() => reactToastify.toast.success(isDraft ? "Published!" : "Unpublished!")).catch((error) => reactToastify.toast.error(`Error: ${error}`));
2004
- }, [mutation, id]);
2005
- return /* @__PURE__ */ jsxRuntime.jsx(TableRowActionButton, { icon: isDraft ? js.mdiPublish : js.mdiPublishOff, onClick: publish, ...props });
2006
- }
2007
-
2008
- exports.AdminLayout = AdminLayout;
2009
- exports.AttachDialog = AttachDialog;
2010
- exports.Breadcrumbs = Breadcrumbs;
2011
- exports.ButtonBar = ButtonBar;
2012
- exports.ButtonBarButton = ButtonBarButton;
2013
- exports.ButtonBarDialogButton = ButtonBarDialogButton;
2014
- exports.ButtonBarSubmitButton = ButtonBarSubmitButton;
2015
- exports.DialogButton = DialogButton;
2016
- exports.FormActionDialog = FormActionDialog;
2017
- exports.InvalidateButton = InvalidateButton;
2018
- exports.ItemDeleteDialog = ItemDeleteDialog;
2019
- exports.ItemEditDialog = ItemEditDialog;
2020
- exports.Menu = Menu;
2021
- exports.NavigateButton = NavigateButton;
2022
- exports.OrderCell = OrderCell;
2023
- exports.PageContainer = PageContainer;
2024
- exports.PageContentEditor = PageContentEditor;
2025
- exports.PageMain = PageMain;
2026
- exports.PageQueryStateContainer = PageQueryStateContainer;
2027
- exports.PageSectionTitle = PageSectionTitle;
2028
- exports.PageSidebar = PageSidebar;
2029
- exports.PageSidebarSection = PageSidebarSection;
2030
- exports.PageStateContainer = PageStateContainer;
2031
- exports.PageSubSectionTitle = PageSubSectionTitle;
2032
- exports.PageTabbedTopBar = PageTabbedTopBar;
2033
- exports.PageTabbedTopBarProvider = PageTabbedTopBarProvider;
2034
- exports.PageTitle = PageTitle;
2035
- exports.PageTopBar = PageTopBar;
2036
- exports.PageTopBarToolbar = PageTopBarToolbar;
2037
- exports.PublishButton = PublishButton;
2038
- exports.ScreenRenderer = ScreenRenderer;
2039
- exports.SectionTitle = SectionTitle;
2040
- exports.StatusBadge = StatusBadge;
2041
- exports.TableContainer = TableContainer;
2042
- exports.TableCreateButton = TableCreateButton;
2043
- exports.TableFilterButton = TableFilterButton;
2044
- exports.TableRowActionBar = TableRowActionBar;
2045
- exports.TableRowActionButton = TableRowActionButton;
2046
- exports.TableRowActionDialogButton = TableRowActionDialogButton;
2047
- exports.TableRowDeleteButton = TableRowDeleteButton;
2048
- exports.TableRowEditButton = TableRowEditButton;
2049
- exports.TableRowNavigateButton = TableRowNavigateButton;
2050
- exports.TableRowPublishPostButton = TableRowPublishPostButton2;
2051
- exports.TableRowViewButton = TableRowViewButton;
2052
- exports.TableTopBar = TableTopBar;
2053
- exports.UpdateButton = UpdateButton;
2054
- exports.ViewButton = ViewButton;