@datawheel/bespoke 0.1.13 → 0.1.15

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.
Files changed (3) hide show
  1. package/dist/index.js +1150 -943
  2. package/dist/server.js +1770 -137
  3. package/package.json +5 -3
package/dist/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ import axios from 'axios';
2
+ import yn3 from 'yn';
1
3
  import * as d3Array from 'd3-array';
2
4
  import * as d3Collection from 'd3-collection';
3
5
  import * as d3Format from 'd3-format';
@@ -6,20 +8,18 @@ import { formatAbbreviate } from 'd3plus-format';
6
8
  import { date } from 'd3plus-axis';
7
9
  import { assign, closest, merge, isObject } from 'd3plus-common';
8
10
  import { strip, titleCase } from 'd3plus-text';
9
- import yn3 from 'yn';
10
- import axios from 'axios';
11
11
  import { schema, normalize } from 'normalizr';
12
12
  import { createSlice, configureStore } from '@reduxjs/toolkit';
13
13
  import { HYDRATE, createWrapper } from 'next-redux-wrapper';
14
14
  import { NotificationsProvider, showNotification } from '@mantine/notifications';
15
- import React, { forwardRef, useMemo, useState, useCallback, useContext, useEffect, createContext, useRef, createElement, Fragment as Fragment$1 } from 'react';
15
+ import React, { forwardRef, useMemo, useState, useCallback, useContext, useEffect, createContext, useRef, Fragment as Fragment$1, createElement } from 'react';
16
16
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
17
17
  import { useDispatch, useSelector } from 'react-redux';
18
- import { Stack, Text, Badge, Group, Tooltip, ActionIcon, Center, useMantineTheme, Modal, Button, Title, Select, MultiSelect, Skeleton, Container, TextInput, Loader, LoadingOverlay, Alert, Autocomplete, Chip, Menu, Avatar, Card, Space, Code, Divider, SegmentedControl, Overlay, Flex, MantineProvider, Burger, Navbar, ScrollArea, Box, AppShell, UnstyledButton, Popover, Checkbox, Radio, Switch, Drawer, Header, Input, Grid, ThemeIcon, Textarea, Tabs, Image, Accordion, NumberInput, SimpleGrid, FileInput, CopyButton, Col } from '@mantine/core';
19
- import { IconInfoCircle, IconSearch, IconTrash, IconUserCircle, IconLogout, IconDatabase, IconServer, IconPencil, IconAlertCircle, IconCircleCheck, IconPlayerPlay, IconCirclePlus, IconFileAnalytics, IconBoxMargin, IconTable, IconMathFunction, IconUsers, IconChevronLeft, IconSettings, IconAlignLeft, IconAlignCenter, IconAlignRight, IconPlus, IconMenu, IconCircleX, IconCircleDashed, IconLogin, IconWorld, IconEyeOff, IconCamera, IconShare, IconRefresh, IconPolaroid, IconCircleMinus, IconVariable, IconArrowRightCircle, IconPalette, IconCode, IconExternalLink, IconDownload, IconTemplate, IconChartBar, IconUpload, IconLink, IconClipboardCheck, IconClipboardCopy, IconEye, IconRss, IconGlobe } from '@tabler/icons';
18
+ import { Stack, Text, Badge, Group, Tooltip, ActionIcon, Center, useMantineTheme, Modal, Button, Title, Select, MultiSelect, MantineProvider, Divider, Burger, Navbar, ScrollArea, Avatar, Box, AppShell, UnstyledButton, ThemeIcon, Skeleton, Container, TextInput, Loader, LoadingOverlay, Alert, Autocomplete, Chip, Menu, Card, Space, Code, SegmentedControl, Textarea, Overlay, Grid, Flex, Popover, Checkbox, Radio, Switch, Drawer, Input, Header, Tabs, FileInput, SimpleGrid, Image, Accordion, NumberInput, CopyButton, Col } from '@mantine/core';
19
+ import { IconInfoCircle, IconBoxMargin, IconTable, IconMathFunction, IconUsers, IconLogout, IconSearch, IconTrash, IconUserCircle, IconDatabase, IconServer, IconPencil, IconAlertCircle, IconCircleCheck, IconPlayerPlay, IconCirclePlus, IconCircleX, IconFileAnalytics, IconPlus, IconCircleDashed, IconSettings, IconAlignLeft, IconAlignCenter, IconAlignRight, IconMenu, IconRefresh, IconPolaroid, IconCircleMinus, IconEyeOff, IconLogin, IconWorld, IconCamera, IconShare, IconVariable, IconArrowRightCircle, IconUpload, IconPalette, IconCode, IconExternalLink, IconDownload, IconTemplate, IconChartBar, IconLink, IconClipboardCheck, IconClipboardCopy, IconEye, IconRss, IconGlobe } from '@tabler/icons';
20
20
  import { dataConcat } from 'd3plus-viz';
21
21
  import * as d3plus from 'd3plus-react';
22
- import { useDebouncedValue, useMediaQuery, useDisclosure, useHotkeys, useUncontrolled, getHotkeyHandler } from '@mantine/hooks';
22
+ import { useDisclosure, useDebouncedValue, useMediaQuery, useHotkeys, useUncontrolled, getHotkeyHandler } from '@mantine/hooks';
23
23
  import Link from 'next/link';
24
24
  import Router, { useRouter } from 'next/router';
25
25
  import { UserProvider, withPageAuthRequired, useUser } from '@auth0/nextjs-auth0/client';
@@ -56,328 +56,212 @@ var init_esm_shims = __esm({
56
56
  }
57
57
  });
58
58
 
59
- // models/report.ts
60
- var ID, MODEL_NAME;
61
- var init_report = __esm({
62
- "models/report.ts"() {
59
+ // api/http/lib.ts
60
+ function http(axios6, config) {
61
+ return axios6.request(config).then((response) => {
62
+ const { status, data } = response;
63
+ return "error" in data ? { ok: false, status, error: data.error } : { ok: true, status, data: data.data };
64
+ }, (err) => {
65
+ if ("isAxiosError" in err) {
66
+ const { status, data } = err.response || { status: 500 };
67
+ return { ok: false, status, error: data?.error ?? err.message };
68
+ }
69
+ return { ok: false, status: 500, error: err.message };
70
+ });
71
+ }
72
+ function httpGET(axios6, request, transformParams) {
73
+ const config = typeof request === "string" ? { url: request } : request;
74
+ return (params) => http(axios6, {
75
+ ...config,
76
+ method: "GET",
77
+ params: transformParams ? transformParams(params) : params
78
+ });
79
+ }
80
+ function httpPOST(axios6, request, transformPayload) {
81
+ const config = typeof request === "string" ? { url: request } : request;
82
+ return (payload) => http(axios6, {
83
+ ...config,
84
+ method: "POST",
85
+ data: transformPayload ? transformPayload(payload) : payload
86
+ });
87
+ }
88
+ function httpDELETE(axios6, request, transformPayload) {
89
+ const config = typeof request === "string" ? { url: request } : request;
90
+ return (payload) => http(axios6, {
91
+ ...config,
92
+ method: "DELETE",
93
+ data: transformPayload ? transformPayload(payload) : payload
94
+ });
95
+ }
96
+ var init_lib = __esm({
97
+ "api/http/lib.ts"() {
63
98
  init_esm_shims();
64
- ID = "report";
65
- MODEL_NAME = "Report";
66
99
  }
67
100
  });
68
101
 
69
- // models/section.ts
70
- var ID2, MODEL_NAME2;
71
- var init_section = __esm({
72
- "models/section.ts"() {
102
+ // api/http/image/imageSave.ts
103
+ function httpImageSaveFactory(axios6, provider) {
104
+ return (params) => http(axios6, {
105
+ method: "GET",
106
+ url: `search/images/${provider}`,
107
+ params: { prompt: params.prompt, provider }
108
+ });
109
+ }
110
+ var init_imageSave = __esm({
111
+ "api/http/image/imageSave.ts"() {
73
112
  init_esm_shims();
74
- init_report();
75
- ID2 = "section";
76
- MODEL_NAME2 = "Section";
113
+ init_lib();
77
114
  }
78
115
  });
79
116
 
80
- // libs/configs/getLocales.ts
81
- var getLocales_default;
82
- var init_getLocales = __esm({
83
- "libs/configs/getLocales.ts"() {
117
+ // api/http/image/imageSearch.ts
118
+ function httpImageSearchFactory(axios6, provider) {
119
+ return (params) => http(axios6, {
120
+ method: "GET",
121
+ url: `search/images/${provider}`,
122
+ params: { prompt: params.prompt, provider }
123
+ });
124
+ }
125
+ var init_imageSearch = __esm({
126
+ "api/http/image/imageSearch.ts"() {
84
127
  init_esm_shims();
85
- getLocales_default = () => {
86
- const localeDefault9 = process.env.NEXT_PUBLIC_REPORTS_LOCALE_DEFAULT || "en";
87
- const locales3 = process.env.NEXT_PUBLIC_REPORTS_LOCALES?.split(",") || [localeDefault9];
88
- if (!locales3.includes(localeDefault9))
89
- locales3.push(localeDefault9);
90
- return { localeDefault: localeDefault9, locales: locales3 };
91
- };
128
+ init_lib();
92
129
  }
93
130
  });
94
-
95
- // models/block.ts
96
- function parseBlockContext(context) {
131
+ function apiFactory(baseURL) {
132
+ const axios6 = axios.create({ baseURL });
97
133
  return {
98
- variables: context.variables || {},
99
- query: context.query || {},
100
- locale: context.locale || localeDefault
134
+ createBlock: httpPOST(axios6, "create/block"),
135
+ createDimension: httpPOST(axios6, "create/dimension"),
136
+ createFormatter: httpPOST(axios6, "create/formatter"),
137
+ createReport: httpPOST(axios6, "create/report"),
138
+ createSection: httpPOST(axios6, "create/section"),
139
+ createVariant: httpPOST(axios6, "create/variant"),
140
+ deleteBlock: httpDELETE(axios6, "delete/block", transformDeletePayload),
141
+ deleteDimension: httpDELETE(axios6, "delete/dimension", transformDeletePayload),
142
+ deleteFormatter: httpDELETE(axios6, "delete/formatter", transformDeletePayload),
143
+ deleteReport: httpDELETE(axios6, "delete/report", transformDeletePayload),
144
+ deleteSection: httpDELETE(axios6, "delete/section", transformDeletePayload),
145
+ deleteVariant: httpDELETE(axios6, "delete/variant", transformDeletePayload),
146
+ readBlock: httpGET(axios6, "read/block"),
147
+ readDimension: httpGET(axios6, "read/dimension"),
148
+ readFormatter: httpGET(axios6, "read/formatter"),
149
+ readReport: httpGET(axios6, "read/report"),
150
+ readSection: httpGET(axios6, "read/section"),
151
+ readVariant: httpGET(axios6, "read/variant"),
152
+ updateBlock: httpPOST(axios6, "update/block"),
153
+ updateDimension: httpPOST(axios6, "update/dimension"),
154
+ updateFormatter: httpPOST(axios6, "update/formatter"),
155
+ updateReport: httpPOST(axios6, "update/report"),
156
+ updateSection: httpPOST(axios6, "update/section"),
157
+ updateVariant: httpPOST(axios6, "update/variant"),
158
+ searchReport: httpGET(axios6, "search/reports"),
159
+ validateVariantSlug: httpGET(axios6, "validate/variant"),
160
+ readMember: httpGET(axios6, "read/members", transformReadMembers),
161
+ readMemberImage: httpGET(axios6, {
162
+ url: "member/image.png",
163
+ responseType: "blob"
164
+ }),
165
+ searchMember: httpGET(axios6, "search/members"),
166
+ updateMember: httpGET(axios6, "update/members"),
167
+ imageLocalSearch: httpImageSearchFactory(axios6, "local"),
168
+ imageLocalSave: httpImageSaveFactory(axios6, "local"),
169
+ imageFlickrSearch: httpImageSearchFactory(axios6, "flickr"),
170
+ imageFlickrSave: httpImageSaveFactory(axios6, "flickr"),
171
+ imageUnsplashSearch: httpImageSearchFactory(axios6, "unsplash"),
172
+ imageUnsplashSave: httpImageSaveFactory(axios6, "unsplash"),
173
+ imageUploadSave: httpImageSaveFactory(axios6, "upload"),
174
+ readMetadata: httpGET(axios6, "read/metadata"),
175
+ regenerateSearch: httpPOST(axios6, "search/regenerate"),
176
+ urlProxy: httpGET(axios6, "url/proxy"),
177
+ searchRole: httpGET(axios6, "auth/search/roles"),
178
+ searchUser: httpGET(axios6, "auth/search/users"),
179
+ readUser: httpGET(axios6, "auth/read/user"),
180
+ updateUser: httpPOST(axios6, "auth/update/user"),
181
+ addNewReportToCurrentUser: httpPOST(axios6, "auth/update/me")
101
182
  };
102
183
  }
103
- var localeDefault, ID3, MODEL_NAME3;
104
- var init_block = __esm({
105
- "models/block.ts"() {
184
+ var transformDeletePayload, transformReadMembers;
185
+ var init_http = __esm({
186
+ "api/http/index.ts"() {
106
187
  init_esm_shims();
107
- init_section();
108
- init_getLocales();
109
- ({ localeDefault } = getLocales_default());
110
- ID3 = "block";
111
- MODEL_NAME3 = "Block";
188
+ init_imageSave();
189
+ init_imageSearch();
190
+ init_lib();
191
+ transformDeletePayload = (id) => ({ id });
192
+ transformReadMembers = (params) => {
193
+ if (params.mode === "slugs") {
194
+ const slugs = params.slugs.map(
195
+ (slug) => [slug.variantSlug, slug.memberSlug].join("/")
196
+ ).join(",");
197
+ return { ...params, slugs };
198
+ }
199
+ return { ...params, [params.mode]: params[params.mode].join(",") };
200
+ };
112
201
  }
113
202
  });
114
203
 
115
- // libs/stats.js
116
- function logGamma(Z) {
117
- const S = 1 + 76.18009173 / Z - 86.50532033 / (Z + 1) + 24.01409822 / (Z + 2) - 1.231739516 / (Z + 3) + 0.00120858003 / (Z + 4) - 536382e-11 / (Z + 5);
118
- return (Z - 0.5) * Math.log(Z + 4.5) - (Z + 4.5) + Math.log(S * 2.50662827465);
119
- }
120
- function betinc(X, A, B) {
121
- let A0 = 0;
122
- let B0 = 1;
123
- let A1 = 1;
124
- let B1 = 1;
125
- let M9 = 0;
126
- let A2 = 0;
127
- let C9;
128
- while (Math.abs((A1 - A2) / A1) > 1e-5) {
129
- A2 = A1;
130
- C9 = -(A + M9) * (A + B + M9) * X / (A + 2 * M9) / (A + 2 * M9 + 1);
131
- A0 = A1 + C9 * A0;
132
- B0 = B1 + C9 * B0;
133
- M9 += 1;
134
- C9 = M9 * (B - M9) * X / (A + 2 * M9 - 1) / (A + 2 * M9);
135
- A1 = A0 + C9 * A1;
136
- B1 = B0 + C9 * B1;
137
- A0 /= B1;
138
- B0 /= B1;
139
- A1 /= B1;
140
- B1 = 1;
141
- }
142
- return A1 / A;
143
- }
144
- function binomialCdf(X, N, P) {
145
- let betacdf;
146
- let bincdf;
147
- if (X < 0)
148
- bincdf = 0;
149
- else if (X >= N)
150
- bincdf = 1;
151
- else {
152
- X = Math.floor(X);
153
- const Z = P;
154
- const A = X + 1;
155
- const B = N - X;
156
- const S = A + B;
157
- const BT = Math.exp(logGamma(S) - logGamma(B) - logGamma(A) + A * Math.log(Z) + B * Math.log(1 - Z));
158
- if (Z < (A + 1) / (S + 2)) {
159
- betacdf = BT * betinc(Z, A, B);
160
- } else {
161
- betacdf = 1 - BT * betinc(1 - Z, B, A);
162
- }
163
- bincdf = 1 - betacdf;
164
- }
165
- return Math.round(bincdf * 1e5) / 1e5;
166
- }
167
- function criticalValue(confLevel) {
168
- const critMap = {
169
- 0.99999: 15.137,
170
- 0.99: 6.635,
171
- 0.95: 3.841,
172
- 0.9: 2.706
173
- };
174
- return critMap[confLevel];
175
- }
176
- function binP(N, p, x1, x2) {
177
- const q = p / (1 - p);
178
- let k = 0;
179
- let v = 1;
180
- let s = 0;
181
- let tot = 0;
182
- while (k <= N) {
183
- tot += v;
184
- if (k >= x1 & k <= x2) {
185
- s += v;
186
- }
187
- if (tot > 1e30) {
188
- s /= 1e30;
189
- tot /= 1e30;
190
- v /= 1e30;
191
- }
192
- k += 1;
193
- v = v * q * (N + 1 - k) / k;
194
- }
195
- return s / tot;
196
- }
197
- function computeMidP(vx, vN, confLevel) {
198
- const vP = vx / vN;
199
- const prob = confLevel * 100;
200
- const vTL = (100 - prob) / 2;
201
- let T1;
202
- let T2;
203
- if (vx === 0) {
204
- T1 = 0;
205
- } else {
206
- let v = vP / 2;
207
- let vsL = 0;
208
- let vsH = vP;
209
- const p = vTL / 100;
210
- while (vsH - vsL > 1e-5) {
211
- if (binP(vN, v, vx, vx) * 0.5 + binP(vN, v, vx + 1, vN) > p) {
212
- vsH = v;
213
- v = (vsL + v) / 2;
214
- } else {
215
- vsL = v;
216
- v = (vsH + v) / 2;
217
- }
218
- }
219
- T1 = v;
220
- }
221
- if (vx === vN) {
222
- T2 = 0;
223
- } else {
224
- let v = (1 + vP) / 2;
225
- let vsL = vP;
226
- let vsH = 1;
227
- const p = vTL / 100;
228
- while (vsH - vsL > 1e-5) {
229
- if (binP(vN, v, vx, vx) * 0.5 + binP(vN, v, 0, vx - 1) < p) {
230
- vsH = v;
231
- v = (vsL + v) / 2;
232
- } else {
233
- vsL = v;
234
- v = (vsH + v) / 2;
235
- }
236
- }
237
- T2 = v;
238
- }
239
- return { lci: T1, uci: T2 };
240
- }
241
- function smr(observedVal, expectedVal) {
242
- const vx = observedVal;
243
- const vN = expectedVal;
244
- const Obs = vx;
245
- const Exp = vN;
246
- const ci = 95;
247
- let v = 0.5;
248
- let dv = 0.5;
249
- const vTL = (100 - ci) / 2;
250
- let p = vTL / 100;
251
- const vZ = Obs;
252
- while (dv > 1e-5) {
253
- dv /= 2;
254
- if (poisP((1 + vZ) * v / (1 - v), vZ + 1, 1e10) + 0.5 * poisP((1 + vZ) * v / (1 - v), vZ, vZ) > p) {
255
- v -= dv;
256
- } else {
257
- v += dv;
258
- }
259
- }
260
- const QL = (1 + vZ) * v / (1 - v) / Exp;
261
- v = 0.5;
262
- dv = 0.5;
263
- const vTU = (100 - ci) / 2;
264
- p = vTU / 100;
265
- while (dv > 1e-5) {
266
- dv /= 2;
267
- if (poisP((1 + vZ) * v / (1 - v), 0, vZ - 1) + 0.5 * poisP((1 + vZ) * v / (1 - v), vZ, vZ) < p) {
268
- v -= dv;
269
- } else {
270
- v += dv;
271
- }
272
- }
273
- const QU = (1 + vZ) * v / (1 - v) / Exp;
274
- return { lci: QL, uci: QU };
275
- }
276
- function poisP(Z, x1, x2) {
277
- let q = 1;
278
- let tot = 0;
279
- let s = 0;
280
- let k = 0;
281
- while (k < Z || q > tot * 1e-10) {
282
- tot += q;
283
- if (k >= x1 & k <= x2) {
284
- s += q;
285
- }
286
- if (tot > 1e30) {
287
- s /= 1e30;
288
- tot /= 1e30;
289
- q /= 1e30;
290
- }
291
- k += 1;
292
- q = q * Z / k;
204
+ // api/index.ts
205
+ var init_api = __esm({
206
+ "api/index.ts"() {
207
+ init_esm_shims();
208
+ init_http();
293
209
  }
294
- return s / tot;
295
- }
296
- var stats_default;
297
- var init_stats = __esm({
298
- "libs/stats.js"() {
210
+ });
211
+
212
+ // models/report.ts
213
+ var ID, MODEL_NAME;
214
+ var init_report = __esm({
215
+ "models/report.ts"() {
299
216
  init_esm_shims();
300
- stats_default = {
301
- binomialCdf,
302
- binP,
303
- computeMidP,
304
- criticalValue,
305
- smr
306
- };
217
+ ID = "report";
218
+ MODEL_NAME = "Report";
307
219
  }
308
220
  });
309
- var libraries;
310
- var init_libs = __esm({
311
- "libs/libs.ts"() {
221
+
222
+ // models/section.ts
223
+ var ID2, MODEL_NAME2;
224
+ var init_section = __esm({
225
+ "models/section.ts"() {
312
226
  init_esm_shims();
313
- init_stats();
314
- libraries = {
315
- d3: {
316
- ...d3Array,
317
- ...d3Collection,
318
- ...d3Format,
319
- ...d3TimeFormat
320
- },
321
- d3plus: {
322
- assign,
323
- closest,
324
- date,
325
- formatAbbreviate,
326
- merge,
327
- strip,
328
- titleCase
329
- },
330
- stats: stats_default
227
+ init_report();
228
+ ID2 = "section";
229
+ MODEL_NAME2 = "Section";
230
+ }
231
+ });
232
+
233
+ // libs/configs/getLocales.ts
234
+ var getLocales_default;
235
+ var init_getLocales = __esm({
236
+ "libs/configs/getLocales.ts"() {
237
+ init_esm_shims();
238
+ getLocales_default = () => {
239
+ const localeDefault9 = process.env.NEXT_PUBLIC_REPORTS_LOCALE_DEFAULT || "en";
240
+ const locales3 = process.env.NEXT_PUBLIC_REPORTS_LOCALES?.split(",") || [localeDefault9];
241
+ if (!locales3.includes(localeDefault9))
242
+ locales3.push(localeDefault9);
243
+ return { localeDefault: localeDefault9, locales: locales3 };
331
244
  };
332
245
  }
333
246
  });
334
- function mortarEval(varInnerName, varOuterValue, logic, formatterFunctions, attributes = void 0, blockContext) {
335
- const vars = {};
336
- const { locale } = parseBlockContext(blockContext);
337
- try {
338
- if (varOuterValue) {
339
- const log = [];
340
- const pConsole = new Proxy(console, {
341
- get(target, prop) {
342
- if (isInSet(prop, "log", "debug", "info", "warn", "error")) {
343
- return (...args) => {
344
- log.push(`${prop} ${Date.now()} - ${args.join(" ")}`);
345
- if (verbose)
346
- target[prop](...args);
347
- };
348
- }
349
- return target[prop];
350
- }
351
- });
352
- let output;
353
- if (attributes) {
354
- const fn = new Function(varInnerName, "console", "libs", "formatters", "locale", "variables", logic);
355
- output = fn(varOuterValue, pConsole, libraries, formatterFunctions, locale, attributes);
356
- } else {
357
- const fn = new Function(varInnerName, "console", "libs", "formatters", "locale", logic);
358
- output = fn(varOuterValue, pConsole, libraries, formatterFunctions, locale);
359
- }
360
- if (typeof output === "object" && Object.keys(output).length > 0) {
361
- Object.assign(vars, output);
362
- }
363
- return { vars, error: null, log };
364
- }
365
- return { vars, error: "Invalid API Link" };
366
- } catch (err) {
367
- return { vars, error: err.message };
368
- }
369
- }
370
- function isInSet(value, ...args) {
371
- return args.includes(value);
247
+
248
+ // models/block.ts
249
+ function parseBlockContext(context) {
250
+ return {
251
+ variables: context.variables || {},
252
+ query: context.query || {},
253
+ locale: context.locale || localeDefault
254
+ };
372
255
  }
373
- var verbose, mortarEval_default;
374
- var init_mortarEval = __esm({
375
- "libs/variables/mortarEval.ts"() {
256
+ var localeDefault, ID3, MODEL_NAME3;
257
+ var init_block = __esm({
258
+ "models/block.ts"() {
376
259
  init_esm_shims();
377
- init_block();
378
- init_libs();
379
- verbose = yn3(process.env.REPORTS_LOGGING);
380
- mortarEval_default = mortarEval;
260
+ init_section();
261
+ init_getLocales();
262
+ ({ localeDefault } = getLocales_default());
263
+ ID3 = "block";
264
+ MODEL_NAME3 = "Block";
381
265
  }
382
266
  });
383
267
 
@@ -444,12 +328,16 @@ var init_cms = __esm({
444
328
  ...ALLOWED
445
329
  });
446
330
  BLOCK_CONTENT_TYPES = {
331
+ // AUTHOR: "author",
332
+ // FOOTNOTE: "footnote",
447
333
  IMAGE: "image",
448
334
  PARAGRAPH: "paragraph",
449
335
  SELECTOR: "selector",
336
+ // todo1.0 - move to logic types
450
337
  STAT: "stat",
451
338
  SUBTITLE: "subtitle",
452
339
  TITLE: "title"
340
+ // todo1.0, how to put custom blocks in here?
453
341
  };
454
342
  BLOCK_LOGIC_TYPES = {
455
343
  GENERATOR: "generator",
@@ -491,6 +379,17 @@ var init_cms = __esm({
491
379
  BLOCK_FIELDS.SIMPLE_ENABLED
492
380
  ];
493
381
  BLOCK_MAP = {
382
+ /*
383
+ [BLOCK_TYPES.AUTHOR]: [
384
+ BLOCK_FIELDS.AUTHOR,
385
+ BLOCK_FIELDS.BIO,
386
+ BLOCK_FIELDS.IMAGE,
387
+ BLOCK_FIELDS.TITLE,
388
+ ],
389
+ [BLOCK_TYPES.FOOTNOTE]: [
390
+ BLOCK_FIELDS.FOOTNOTE,
391
+ ],
392
+ */
494
393
  [BLOCK_TYPES.IMAGE]: [
495
394
  BLOCK_FIELDS.SRC,
496
395
  BLOCK_FIELDS.ALT
@@ -542,14 +441,290 @@ var init_cms = __esm({
542
441
  OBJECT: "object",
543
442
  DATE: "date"
544
443
  };
545
- FORMATTER_INPUT_TYPES_NAMES = {
546
- [FORMATTER_INPUT_TYPES.STRING]: "String",
547
- [FORMATTER_INPUT_TYPES.NUMBER]: "Number",
548
- [FORMATTER_INPUT_TYPES.OBJECT]: "Object/Array",
549
- [FORMATTER_INPUT_TYPES.DATE]: "Date"
444
+ FORMATTER_INPUT_TYPES_NAMES = {
445
+ [FORMATTER_INPUT_TYPES.STRING]: "String",
446
+ [FORMATTER_INPUT_TYPES.NUMBER]: "Number",
447
+ [FORMATTER_INPUT_TYPES.OBJECT]: "Object/Array",
448
+ [FORMATTER_INPUT_TYPES.DATE]: "Date"
449
+ };
450
+ }
451
+ });
452
+ var getLogging_default;
453
+ var init_getLogging = __esm({
454
+ "libs/configs/getLogging.ts"() {
455
+ init_esm_shims();
456
+ getLogging_default = (env = process.env) => yn3(env.REPORTS_LOGGING);
457
+ }
458
+ });
459
+
460
+ // libs/stats.js
461
+ function logGamma(Z) {
462
+ const S = 1 + 76.18009173 / Z - 86.50532033 / (Z + 1) + 24.01409822 / (Z + 2) - 1.231739516 / (Z + 3) + 0.00120858003 / (Z + 4) - 536382e-11 / (Z + 5);
463
+ return (Z - 0.5) * Math.log(Z + 4.5) - (Z + 4.5) + Math.log(S * 2.50662827465);
464
+ }
465
+ function betinc(X, A, B) {
466
+ let A0 = 0;
467
+ let B0 = 1;
468
+ let A1 = 1;
469
+ let B1 = 1;
470
+ let M9 = 0;
471
+ let A2 = 0;
472
+ let C9;
473
+ while (Math.abs((A1 - A2) / A1) > 1e-5) {
474
+ A2 = A1;
475
+ C9 = -(A + M9) * (A + B + M9) * X / (A + 2 * M9) / (A + 2 * M9 + 1);
476
+ A0 = A1 + C9 * A0;
477
+ B0 = B1 + C9 * B0;
478
+ M9 += 1;
479
+ C9 = M9 * (B - M9) * X / (A + 2 * M9 - 1) / (A + 2 * M9);
480
+ A1 = A0 + C9 * A1;
481
+ B1 = B0 + C9 * B1;
482
+ A0 /= B1;
483
+ B0 /= B1;
484
+ A1 /= B1;
485
+ B1 = 1;
486
+ }
487
+ return A1 / A;
488
+ }
489
+ function binomialCdf(X, N, P) {
490
+ let betacdf;
491
+ let bincdf;
492
+ if (X < 0)
493
+ bincdf = 0;
494
+ else if (X >= N)
495
+ bincdf = 1;
496
+ else {
497
+ X = Math.floor(X);
498
+ const Z = P;
499
+ const A = X + 1;
500
+ const B = N - X;
501
+ const S = A + B;
502
+ const BT = Math.exp(logGamma(S) - logGamma(B) - logGamma(A) + A * Math.log(Z) + B * Math.log(1 - Z));
503
+ if (Z < (A + 1) / (S + 2)) {
504
+ betacdf = BT * betinc(Z, A, B);
505
+ } else {
506
+ betacdf = 1 - BT * betinc(1 - Z, B, A);
507
+ }
508
+ bincdf = 1 - betacdf;
509
+ }
510
+ return Math.round(bincdf * 1e5) / 1e5;
511
+ }
512
+ function criticalValue(confLevel) {
513
+ const critMap = {
514
+ 0.99999: 15.137,
515
+ 0.99: 6.635,
516
+ 0.95: 3.841,
517
+ 0.9: 2.706
518
+ };
519
+ return critMap[confLevel];
520
+ }
521
+ function binP(N, p, x1, x2) {
522
+ const q = p / (1 - p);
523
+ let k = 0;
524
+ let v = 1;
525
+ let s = 0;
526
+ let tot = 0;
527
+ while (k <= N) {
528
+ tot += v;
529
+ if (k >= x1 & k <= x2) {
530
+ s += v;
531
+ }
532
+ if (tot > 1e30) {
533
+ s /= 1e30;
534
+ tot /= 1e30;
535
+ v /= 1e30;
536
+ }
537
+ k += 1;
538
+ v = v * q * (N + 1 - k) / k;
539
+ }
540
+ return s / tot;
541
+ }
542
+ function computeMidP(vx, vN, confLevel) {
543
+ const vP = vx / vN;
544
+ const prob = confLevel * 100;
545
+ const vTL = (100 - prob) / 2;
546
+ let T1;
547
+ let T2;
548
+ if (vx === 0) {
549
+ T1 = 0;
550
+ } else {
551
+ let v = vP / 2;
552
+ let vsL = 0;
553
+ let vsH = vP;
554
+ const p = vTL / 100;
555
+ while (vsH - vsL > 1e-5) {
556
+ if (binP(vN, v, vx, vx) * 0.5 + binP(vN, v, vx + 1, vN) > p) {
557
+ vsH = v;
558
+ v = (vsL + v) / 2;
559
+ } else {
560
+ vsL = v;
561
+ v = (vsH + v) / 2;
562
+ }
563
+ }
564
+ T1 = v;
565
+ }
566
+ if (vx === vN) {
567
+ T2 = 0;
568
+ } else {
569
+ let v = (1 + vP) / 2;
570
+ let vsL = vP;
571
+ let vsH = 1;
572
+ const p = vTL / 100;
573
+ while (vsH - vsL > 1e-5) {
574
+ if (binP(vN, v, vx, vx) * 0.5 + binP(vN, v, 0, vx - 1) < p) {
575
+ vsH = v;
576
+ v = (vsL + v) / 2;
577
+ } else {
578
+ vsL = v;
579
+ v = (vsH + v) / 2;
580
+ }
581
+ }
582
+ T2 = v;
583
+ }
584
+ return { lci: T1, uci: T2 };
585
+ }
586
+ function smr(observedVal, expectedVal) {
587
+ const vx = observedVal;
588
+ const vN = expectedVal;
589
+ const Obs = vx;
590
+ const Exp = vN;
591
+ const ci = 95;
592
+ let v = 0.5;
593
+ let dv = 0.5;
594
+ const vTL = (100 - ci) / 2;
595
+ let p = vTL / 100;
596
+ const vZ = Obs;
597
+ while (dv > 1e-5) {
598
+ dv /= 2;
599
+ if (poisP((1 + vZ) * v / (1 - v), vZ + 1, 1e10) + 0.5 * poisP((1 + vZ) * v / (1 - v), vZ, vZ) > p) {
600
+ v -= dv;
601
+ } else {
602
+ v += dv;
603
+ }
604
+ }
605
+ const QL = (1 + vZ) * v / (1 - v) / Exp;
606
+ v = 0.5;
607
+ dv = 0.5;
608
+ const vTU = (100 - ci) / 2;
609
+ p = vTU / 100;
610
+ while (dv > 1e-5) {
611
+ dv /= 2;
612
+ if (poisP((1 + vZ) * v / (1 - v), 0, vZ - 1) + 0.5 * poisP((1 + vZ) * v / (1 - v), vZ, vZ) < p) {
613
+ v -= dv;
614
+ } else {
615
+ v += dv;
616
+ }
617
+ }
618
+ const QU = (1 + vZ) * v / (1 - v) / Exp;
619
+ return { lci: QL, uci: QU };
620
+ }
621
+ function poisP(Z, x1, x2) {
622
+ let q = 1;
623
+ let tot = 0;
624
+ let s = 0;
625
+ let k = 0;
626
+ while (k < Z || q > tot * 1e-10) {
627
+ tot += q;
628
+ if (k >= x1 & k <= x2) {
629
+ s += q;
630
+ }
631
+ if (tot > 1e30) {
632
+ s /= 1e30;
633
+ tot /= 1e30;
634
+ q /= 1e30;
635
+ }
636
+ k += 1;
637
+ q = q * Z / k;
638
+ }
639
+ return s / tot;
640
+ }
641
+ var stats_default;
642
+ var init_stats = __esm({
643
+ "libs/stats.js"() {
644
+ init_esm_shims();
645
+ stats_default = {
646
+ binomialCdf,
647
+ binP,
648
+ computeMidP,
649
+ criticalValue,
650
+ smr
651
+ };
652
+ }
653
+ });
654
+ var libraries;
655
+ var init_libs = __esm({
656
+ "libs/libs.ts"() {
657
+ init_esm_shims();
658
+ init_stats();
659
+ libraries = {
660
+ d3: {
661
+ ...d3Array,
662
+ ...d3Collection,
663
+ ...d3Format,
664
+ ...d3TimeFormat
665
+ },
666
+ d3plus: {
667
+ assign,
668
+ closest,
669
+ date,
670
+ formatAbbreviate,
671
+ merge,
672
+ strip,
673
+ titleCase
674
+ },
675
+ stats: stats_default
550
676
  };
551
677
  }
552
678
  });
679
+ function mortarEval(varInnerName, varOuterValue, logic, formatterFunctions, attributes = void 0, blockContext) {
680
+ const vars = {};
681
+ const log = [];
682
+ const { locale } = parseBlockContext(blockContext);
683
+ try {
684
+ if (varOuterValue) {
685
+ const pConsole = new Proxy(console, {
686
+ get(target, prop) {
687
+ if (isInSet(prop, "log", "debug", "info", "warn", "error")) {
688
+ return (...args) => {
689
+ log.push(`${prop} ${Date.now()} - ${args.join(" ")}`);
690
+ if (verbose)
691
+ target[prop](...args);
692
+ };
693
+ }
694
+ return target[prop];
695
+ }
696
+ });
697
+ let output;
698
+ if (attributes) {
699
+ const fn = new Function(varInnerName, "console", "libs", "formatters", "locale", "variables", logic);
700
+ output = fn(varOuterValue, pConsole, libraries, formatterFunctions, locale, attributes);
701
+ } else {
702
+ const fn = new Function(varInnerName, "console", "libs", "formatters", "locale", logic);
703
+ output = fn(varOuterValue, pConsole, libraries, formatterFunctions, locale);
704
+ }
705
+ if (typeof output === "object" && Object.keys(output).length > 0) {
706
+ Object.assign(vars, output);
707
+ }
708
+ return { vars, error: null, log };
709
+ }
710
+ return { vars, error: "Invalid API Link", log };
711
+ } catch (err) {
712
+ return { vars, error: err.message, log };
713
+ }
714
+ }
715
+ function isInSet(value, ...args) {
716
+ return args.includes(value);
717
+ }
718
+ var verbose, mortarEval_default;
719
+ var init_mortarEval = __esm({
720
+ "libs/variables/mortarEval.ts"() {
721
+ init_esm_shims();
722
+ init_block();
723
+ init_libs();
724
+ verbose = yn3(process.env.REPORTS_LOGGING);
725
+ mortarEval_default = mortarEval;
726
+ }
727
+ });
553
728
 
554
729
  // libs/js/list.ts
555
730
  function list(n) {
@@ -760,191 +935,143 @@ var init_getBlockContent = __esm({
760
935
  if (!block)
761
936
  return {};
762
937
  const locale = getLocaleDerived(block, _locale);
763
- return block.contentByLocale?.[locale]?.content;
764
- };
765
- }
766
- });
767
-
768
- // libs/blocks/getRootBlocksForSection.ts
769
- function getRootBlocksForSection(sid, blocks) {
770
- const blockList = Object.values(blocks);
771
- const nonNativeBlocks = blockList.filter((block) => block.shared && block.section_id !== sid).map((block) => block.id);
772
- return Object.fromEntries(
773
- blockList.filter((block) => block.section_id === sid && (block.inputs.length === 0 || block.inputs.every((id) => nonNativeBlocks.includes(id)))).map((block) => [block.id, block])
774
- );
775
- }
776
- var getRootBlocksForSection_default;
777
- var init_getRootBlocksForSection = __esm({
778
- "libs/blocks/getRootBlocksForSection.ts"() {
779
- init_esm_shims();
780
- getRootBlocksForSection_default = getRootBlocksForSection;
781
- }
782
- });
783
- var getLogging_default;
784
- var init_getLogging = __esm({
785
- "libs/configs/getLogging.ts"() {
786
- init_esm_shims();
787
- getLogging_default = (env = process.env) => yn3(env.REPORTS_LOGGING);
788
- }
789
- });
790
-
791
- // api/http/lib.ts
792
- function http(axios6, config) {
793
- return axios6.request(config).then((response) => {
794
- const { status, data } = response;
795
- return "error" in data ? { ok: false, status, error: data.error } : { ok: true, status, data: data.data };
796
- }, (err) => {
797
- if ("isAxiosError" in err) {
798
- const { status, data } = err.response || { status: 500 };
799
- return { ok: false, status, error: data?.error ?? err.message };
800
- }
801
- return { ok: false, status: 500, error: err.message };
802
- });
803
- }
804
- function httpGET(axios6, request, transformParams) {
805
- const config = typeof request === "string" ? { url: request } : request;
806
- return (params) => http(axios6, {
807
- ...config,
808
- method: "GET",
809
- params: transformParams ? transformParams(params) : params
810
- });
811
- }
812
- function httpPOST(axios6, request, transformPayload) {
813
- const config = typeof request === "string" ? { url: request } : request;
814
- return (payload) => http(axios6, {
815
- ...config,
816
- method: "POST",
817
- data: transformPayload ? transformPayload(payload) : payload
818
- });
819
- }
820
- function httpDELETE(axios6, request, transformPayload) {
821
- const config = typeof request === "string" ? { url: request } : request;
822
- return (payload) => http(axios6, {
823
- ...config,
824
- method: "DELETE",
825
- data: transformPayload ? transformPayload(payload) : payload
826
- });
827
- }
828
- var init_lib = __esm({
829
- "api/http/lib.ts"() {
830
- init_esm_shims();
831
- }
832
- });
833
-
834
- // api/http/image/imageSave.ts
835
- function httpImageSaveFactory(axios6, provider) {
836
- return (params) => http(axios6, {
837
- method: "GET",
838
- url: `search/images/${provider}`,
839
- params: { prompt: params.prompt, provider }
840
- });
841
- }
842
- var init_imageSave = __esm({
843
- "api/http/image/imageSave.ts"() {
844
- init_esm_shims();
845
- init_lib();
846
- }
847
- });
848
-
849
- // api/http/image/imageSearch.ts
850
- function httpImageSearchFactory(axios6, provider) {
851
- return (params) => http(axios6, {
852
- method: "GET",
853
- url: `search/images/${provider}`,
854
- params: { prompt: params.prompt, provider }
855
- });
856
- }
857
- var init_imageSearch = __esm({
858
- "api/http/image/imageSearch.ts"() {
859
- init_esm_shims();
860
- init_lib();
861
- }
862
- });
863
- function apiFactory(baseURL) {
864
- const axios6 = axios.create({ baseURL });
865
- return {
866
- createBlock: httpPOST(axios6, "create/block"),
867
- createDimension: httpPOST(axios6, "create/dimension"),
868
- createFormatter: httpPOST(axios6, "create/formatter"),
869
- createReport: httpPOST(axios6, "create/report"),
870
- createSection: httpPOST(axios6, "create/section"),
871
- createVariant: httpPOST(axios6, "create/variant"),
872
- deleteBlock: httpDELETE(axios6, "delete/block", transformDeletePayload),
873
- deleteDimension: httpDELETE(axios6, "delete/dimension", transformDeletePayload),
874
- deleteFormatter: httpDELETE(axios6, "delete/formatter", transformDeletePayload),
875
- deleteReport: httpDELETE(axios6, "delete/report", transformDeletePayload),
876
- deleteSection: httpDELETE(axios6, "delete/section", transformDeletePayload),
877
- deleteVariant: httpDELETE(axios6, "delete/variant", transformDeletePayload),
878
- readBlock: httpGET(axios6, "read/block"),
879
- readDimension: httpGET(axios6, "read/dimension"),
880
- readFormatter: httpGET(axios6, "read/formatter"),
881
- readReport: httpGET(axios6, "read/report"),
882
- readSection: httpGET(axios6, "read/section"),
883
- readVariant: httpGET(axios6, "read/variant"),
884
- updateBlock: httpPOST(axios6, "update/block"),
885
- updateDimension: httpPOST(axios6, "update/dimension"),
886
- updateFormatter: httpPOST(axios6, "update/formatter"),
887
- updateReport: httpPOST(axios6, "update/report"),
888
- updateSection: httpPOST(axios6, "update/section"),
889
- updateVariant: httpPOST(axios6, "update/variant"),
890
- searchReport: httpGET(axios6, "search/reports"),
891
- validateVariantSlug: httpGET(axios6, "validate/variant"),
892
- readMember: httpGET(axios6, "read/members"),
893
- readMemberImage: httpGET(axios6, {
894
- url: "member/image.png",
895
- responseType: "blob"
896
- }),
897
- searchMember: httpGET(axios6, "search/members"),
898
- updateMember: httpGET(axios6, "update/members"),
899
- imageLocalSearch: httpImageSearchFactory(axios6, "local"),
900
- imageLocalSave: httpImageSaveFactory(axios6, "local"),
901
- imageFlickrSearch: httpImageSearchFactory(axios6, "flickr"),
902
- imageFlickrSave: httpImageSaveFactory(axios6, "flickr"),
903
- imageUnsplashSearch: httpImageSearchFactory(axios6, "unsplash"),
904
- imageUnsplashSave: httpImageSaveFactory(axios6, "unsplash"),
905
- imageUploadSave: httpImageSaveFactory(axios6, "upload"),
906
- readMetadata: httpGET(axios6, "read/metadata"),
907
- regenerateSearch: httpPOST(axios6, "search/regenerate"),
908
- urlProxy: httpGET(axios6, "url/proxy"),
909
- searchRole: httpGET(axios6, "auth/search/roles"),
910
- searchUser: httpGET(axios6, "auth/search/users"),
911
- readUser: httpGET(axios6, "auth/read/user"),
912
- updateUser: httpPOST(axios6, "auth/update/user"),
913
- addNewReportToCurrentUser: httpPOST(axios6, "auth/update/me")
914
- };
915
- }
916
- var transformDeletePayload;
917
- var init_http = __esm({
918
- "api/http/index.ts"() {
919
- init_esm_shims();
920
- init_imageSave();
921
- init_imageSearch();
922
- init_lib();
923
- transformDeletePayload = (id) => ({ id });
938
+ return block.contentByLocale?.[locale]?.content;
939
+ };
924
940
  }
925
941
  });
926
942
 
927
- // api/index.ts
928
- var init_api = __esm({
929
- "api/index.ts"() {
943
+ // libs/blocks/getRootBlocksForSection.ts
944
+ function getRootBlocksForSection(sid, blocks) {
945
+ const blockList = Object.values(blocks);
946
+ const nonNativeBlocks = blockList.filter((block) => block.shared && block.section_id !== sid).map((block) => block.id);
947
+ return Object.fromEntries(
948
+ blockList.filter((block) => block.section_id === sid && // leave blocks belonging to this section
949
+ // that don't depend on any other blocks OR
950
+ (block.inputs.length === 0 || // that depend only on blocks from other sections
951
+ block.inputs.every((id) => nonNativeBlocks.includes(id)))).map((block) => [block.id, block])
952
+ // then convert them to entries
953
+ );
954
+ }
955
+ var getRootBlocksForSection_default;
956
+ var init_getRootBlocksForSection = __esm({
957
+ "libs/blocks/getRootBlocksForSection.ts"() {
930
958
  init_esm_shims();
931
- init_http();
959
+ getRootBlocksForSection_default = getRootBlocksForSection;
932
960
  }
933
961
  });
934
- var verbose2, ORIGIN, swapAPI, urlProxy, apiFetch, runSingleBlock, runConsumers;
962
+ async function apiFetch(url) {
963
+ const start = Date.now();
964
+ if (typeof window === "object") {
965
+ const result = await urlProxy({ url });
966
+ return {
967
+ data: result.ok === true ? result.data : result.error,
968
+ requestDuration: Date.now() - start
969
+ };
970
+ } else {
971
+ const response = await axios({ url });
972
+ return {
973
+ data: response.data,
974
+ requestDuration: Date.now() - start
975
+ };
976
+ }
977
+ }
978
+ async function runSingleBlock(block, formatterFunctions, blockContext) {
979
+ const { locale, variables, query } = parseBlockContext(blockContext);
980
+ let resp = null;
981
+ const unswappedAPI = block.contentByLocale?.logic?.content?.api;
982
+ let apiResponse;
983
+ let duration = null;
984
+ let api = null;
985
+ if (unswappedAPI) {
986
+ api = swapAPI(unswappedAPI, formatterFunctions, blockContext);
987
+ apiResponse = await apiFetch(api).then((result) => {
988
+ if (verbose2)
989
+ console.log("Variable loaded:", api);
990
+ return result;
991
+ }, (e) => {
992
+ if (verbose2)
993
+ console.error(`Error fetching ${api}: ${e.message}`);
994
+ return { data: {}, requestDuration: 0 };
995
+ });
996
+ resp = apiResponse.data;
997
+ duration = apiResponse.requestDuration;
998
+ }
999
+ if (block.type === BLOCK_TYPES.SELECTOR) {
1000
+ const { config, log: log2, error: error2 } = runSelector_default(
1001
+ block.contentByLocale[locale].content.logic,
1002
+ formatterFunctions,
1003
+ blockContext
1004
+ );
1005
+ return {
1006
+ outputVariables: selectorQueryToVariable_default(block.id, query, config),
1007
+ renderVariables: config,
1008
+ status: {
1009
+ api: null,
1010
+ duration: null,
1011
+ resp: null,
1012
+ log: log2,
1013
+ error: error2
1014
+ }
1015
+ };
1016
+ }
1017
+ if (block.type === BLOCK_TYPES.VIZ) {
1018
+ return {
1019
+ outputVariables: {},
1020
+ // todo1.0 this will have to be materialized click-variables
1021
+ renderVariables: block.contentByLocale.logic.content,
1022
+ status: {
1023
+ api: null,
1024
+ duration: null,
1025
+ resp: null,
1026
+ log: [],
1027
+ error: null
1028
+ }
1029
+ };
1030
+ }
1031
+ const { logic } = getBlockContent(block, locale);
1032
+ const swappedLogic = varSwap_default(logic, formatterFunctions, blockContext);
1033
+ const evalResults = mortarEval_default("resp", resp || {}, swappedLogic, formatterFunctions, variables, blockContext);
1034
+ const { vars, error, log } = evalResults;
1035
+ if (typeof vars !== "object") {
1036
+ return {
1037
+ outputVariables: {},
1038
+ renderVariables: {},
1039
+ status: {
1040
+ error: "Configuration did not return an object",
1041
+ log,
1042
+ duration,
1043
+ resp,
1044
+ api
1045
+ }
1046
+ };
1047
+ }
1048
+ const nsVars = Object.keys(vars).reduce((acc, d) => ({ ...acc, [`${block.type}${block.id}${d}`]: vars[d] }), {});
1049
+ return {
1050
+ renderVariables: vars,
1051
+ outputVariables: block.type === BLOCK_TYPES.GENERATOR ? vars : nsVars,
1052
+ status: {
1053
+ log,
1054
+ error,
1055
+ duration,
1056
+ resp,
1057
+ api
1058
+ }
1059
+ };
1060
+ }
1061
+ var verbose2, ORIGIN, swapAPI, urlProxy, runConsumers;
935
1062
  var init_runConsumers = __esm({
936
1063
  "libs/blocks/runConsumers.ts"() {
937
1064
  init_esm_shims();
938
- init_mortarEval();
1065
+ init_api();
1066
+ init_block();
939
1067
  init_cms();
940
- init_varSwap();
1068
+ init_getLogging();
941
1069
  init_runSelector();
942
1070
  init_selectorQueryToVariable();
1071
+ init_mortarEval();
1072
+ init_varSwap();
943
1073
  init_getBlockContent();
944
1074
  init_getRootBlocksForSection();
945
- init_getLogging();
946
- init_block();
947
- init_api();
948
1075
  verbose2 = getLogging_default();
949
1076
  ORIGIN = process.env.REPORTS_ORIGIN || "";
950
1077
  axios.interceptors.request.use((config) => ({
@@ -953,7 +1080,7 @@ var init_runConsumers = __esm({
953
1080
  }));
954
1081
  axios.interceptors.response.use((d) => ({
955
1082
  ...d,
956
- requestDuration: new Date().getTime() - d.config.requestStart
1083
+ requestDuration: (/* @__PURE__ */ new Date()).getTime() - d.config.requestStart
957
1084
  }), (e) => Promise.reject(e));
958
1085
  swapAPI = (api, formatterFunctions, blockContext) => {
959
1086
  let url = varSwap_default(api, formatterFunctions, blockContext);
@@ -962,89 +1089,6 @@ var init_runConsumers = __esm({
962
1089
  return url;
963
1090
  };
964
1091
  ({ urlProxy } = apiFactory("/api/cms"));
965
- apiFetch = async (api) => {
966
- const stub = { data: {}, requestDuration: 0 };
967
- const resp = await urlProxy({ url: api }).catch((e) => {
968
- if (verbose2)
969
- console.log(`API Error for ${api}: ${e.message}`);
970
- return stub;
971
- });
972
- if (resp) {
973
- if (verbose2)
974
- console.log(`Variable loaded: ${api}`);
975
- return resp;
976
- }
977
- return stub;
978
- };
979
- runSingleBlock = async (block, formatterFunctions, blockContext) => {
980
- const { locale, variables, query } = parseBlockContext(blockContext);
981
- let resp;
982
- const unswappedAPI = block.contentByLocale?.logic?.content?.api;
983
- let apiResponse;
984
- let duration;
985
- let api;
986
- if (unswappedAPI) {
987
- api = swapAPI(unswappedAPI, formatterFunctions, blockContext);
988
- apiResponse = await apiFetch(api).catch((e) => {
989
- if (verbose2)
990
- console.error(`Error fetching ${api}: ${e.message}`);
991
- return { data: {}, requestDuration: 0 };
992
- });
993
- resp = apiResponse.data;
994
- duration = apiResponse.requestDuration;
995
- }
996
- if (block.type === BLOCK_TYPES.SELECTOR) {
997
- const { config, log: log2, error: error2 } = runSelector_default(
998
- block.contentByLocale[locale].content.logic,
999
- formatterFunctions,
1000
- blockContext
1001
- );
1002
- return {
1003
- outputVariables: selectorQueryToVariable_default(block.id, query, config),
1004
- renderVariables: config,
1005
- status: {
1006
- log: log2,
1007
- error: error2
1008
- }
1009
- };
1010
- }
1011
- if (block.type === BLOCK_TYPES.VIZ) {
1012
- return {
1013
- outputVariables: {},
1014
- renderVariables: block.contentByLocale.logic.content,
1015
- status: {}
1016
- };
1017
- }
1018
- const { logic } = getBlockContent(block, locale);
1019
- const swappedLogic = varSwap_default(logic, formatterFunctions, blockContext);
1020
- const evalResults = mortarEval_default("resp", resp || {}, swappedLogic, formatterFunctions, variables, blockContext);
1021
- const { vars, error, log } = evalResults;
1022
- if (typeof vars !== "object") {
1023
- return {
1024
- outputVariables: {},
1025
- renderVariables: {},
1026
- status: {
1027
- error: "Configuration did not return an object",
1028
- log,
1029
- duration,
1030
- resp,
1031
- api
1032
- }
1033
- };
1034
- }
1035
- const nsVars = Object.keys(vars).reduce((acc, d) => ({ ...acc, [`${block.type}${block.id}${d}`]: vars[d] }), {});
1036
- return {
1037
- renderVariables: vars,
1038
- outputVariables: block.type === BLOCK_TYPES.GENERATOR ? vars : nsVars,
1039
- status: {
1040
- log,
1041
- error,
1042
- duration,
1043
- resp,
1044
- api
1045
- }
1046
- };
1047
- };
1048
1092
  runConsumers = async (blocks, sid, bid, formatterFunctions, blockContext) => {
1049
1093
  const rootBlocks = bid ? { [bid]: blocks[bid] } : getRootBlocksForSection_default(sid, blocks);
1050
1094
  const parsedBlockContext = parseBlockContext(blockContext);
@@ -1145,24 +1189,25 @@ var init_runConsumers = __esm({
1145
1189
  });
1146
1190
 
1147
1191
  // libs/variables/previewsToAttributes.ts
1148
- var previewsToAttributes, previewsToAttributes_default;
1149
- var init_previewsToAttributes = __esm({
1150
- "libs/variables/previewsToAttributes.ts"() {
1151
- init_esm_shims();
1152
- previewsToAttributes = (previews = []) => {
1153
- const attributes = {};
1154
- previews.forEach((preview, index) => {
1155
- if (!preview)
1156
- return;
1157
- const i = index + 1;
1158
- attributes[`id${i}`] = preview.id;
1159
- attributes[`name${i}`] = preview.name;
1192
+ function previewsToAttributes(previews = []) {
1193
+ return previews.reduce((attributes, preview, index) => {
1194
+ if (preview) {
1195
+ const i = index + 1;
1196
+ attributes[`id${i}`] = preview.id;
1197
+ attributes[`name${i}`] = preview.name;
1198
+ if ("attributes" in preview) {
1160
1199
  Object.keys(preview.attributes).forEach((key) => {
1161
1200
  attributes[`attr_${key}${i}`] = preview.attributes[key];
1162
1201
  });
1163
- });
1164
- return attributes;
1165
- };
1202
+ }
1203
+ }
1204
+ return attributes;
1205
+ }, {});
1206
+ }
1207
+ var previewsToAttributes_default;
1208
+ var init_previewsToAttributes = __esm({
1209
+ "libs/variables/previewsToAttributes.ts"() {
1210
+ init_esm_shims();
1166
1211
  previewsToAttributes_default = previewsToAttributes;
1167
1212
  }
1168
1213
  });
@@ -1428,7 +1473,7 @@ var init_lib2 = __esm({
1428
1473
  }
1429
1474
  if (previews.length > 0) {
1430
1475
  activePreviews = previews;
1431
- statusPayload.previews = activePreviews;
1476
+ statusPayload.previews = activePreviews.filter(Boolean);
1432
1477
  } else {
1433
1478
  activePreviews = status.previews;
1434
1479
  }
@@ -1449,6 +1494,81 @@ var init_lib2 = __esm({
1449
1494
  }, {});
1450
1495
  }
1451
1496
  });
1497
+ var initialState, statusSlice, statusActions;
1498
+ var init_statusSlice = __esm({
1499
+ "store/statusSlice.ts"() {
1500
+ init_esm_shims();
1501
+ init_envvars();
1502
+ initialState = {
1503
+ localeDefault: localeDefault3,
1504
+ locales,
1505
+ showToolbar: false,
1506
+ activeSection: null,
1507
+ previews: [],
1508
+ query: {}
1509
+ };
1510
+ statusSlice = createSlice({
1511
+ name: "status",
1512
+ initialState,
1513
+ reducers: {
1514
+ setStatus: (state, action) => {
1515
+ Object.assign(state, action.payload);
1516
+ },
1517
+ setPreviews(state, action) {
1518
+ state.previews = action.payload;
1519
+ }
1520
+ },
1521
+ extraReducers: {
1522
+ /**
1523
+ * next-redux-wrapper implementation
1524
+ * This reducer is in charge of merging the server and client's states.
1525
+ * This is needed as some navigation operations will make requests to the
1526
+ * server for data, and the server may try to involve the store to calculate
1527
+ * properties for the client's components.
1528
+ */
1529
+ [HYDRATE]: (_state, _action) => initialState
1530
+ }
1531
+ });
1532
+ statusActions = statusSlice.actions;
1533
+ }
1534
+ });
1535
+ var initialState2, variablesSlice, variablesActions;
1536
+ var init_variablesSlice = __esm({
1537
+ "store/variablesSlice.ts"() {
1538
+ init_esm_shims();
1539
+ initialState2 = {
1540
+ attributes: {},
1541
+ variables: {},
1542
+ status: {}
1543
+ };
1544
+ variablesSlice = createSlice({
1545
+ name: "variables",
1546
+ initialState: initialState2,
1547
+ reducers: {
1548
+ setVariableChange: (state, action) => {
1549
+ state.attributes = { ...state.attributes, ...action.payload.attributes };
1550
+ state.variables = { ...state.variables, ...action.payload.variables };
1551
+ state.status = { ...state.status, ...action.payload.status };
1552
+ }
1553
+ },
1554
+ extraReducers: {
1555
+ /**
1556
+ * next-redux-wrapper implementation
1557
+ * This reducer is in charge of merging the server and client's states.
1558
+ * This is needed as some navigation operations will make requests to the
1559
+ * server for data, and the server may try to involve the store to calculate
1560
+ * properties for the client's components.
1561
+ */
1562
+ [HYDRATE]: (state, action) => ({
1563
+ attributes: { ...state.attributes, ...action.payload.variables.attributes },
1564
+ status: { ...state.status, ...action.payload.variables.status },
1565
+ variables: { ...state.variables, ...action.payload.variables.variables }
1566
+ })
1567
+ }
1568
+ });
1569
+ variablesActions = variablesSlice.actions;
1570
+ }
1571
+ });
1452
1572
 
1453
1573
  // api/lib.ts
1454
1574
  function failureResult(err) {
@@ -1495,13 +1615,13 @@ function arrayRemove(list2, item) {
1495
1615
  list2.splice(index, 1);
1496
1616
  }
1497
1617
  }
1498
- var initialState, recordsSlice, FetchStatus;
1618
+ var initialState3, recordsSlice;
1499
1619
  var init_recordsSlice = __esm({
1500
1620
  "store/recordsSlice.ts"() {
1501
1621
  init_esm_shims();
1502
1622
  init_ordering();
1503
1623
  init_lib2();
1504
- initialState = {
1624
+ initialState3 = {
1505
1625
  tree: [],
1506
1626
  reports: null,
1507
1627
  entities: {
@@ -1523,7 +1643,7 @@ var init_recordsSlice = __esm({
1523
1643
  };
1524
1644
  recordsSlice = createSlice({
1525
1645
  name: "records",
1526
- initialState,
1646
+ initialState: initialState3,
1527
1647
  reducers: {
1528
1648
  set: (state, action) => {
1529
1649
  const nextState = action.payload;
@@ -1534,14 +1654,24 @@ var init_recordsSlice = __esm({
1534
1654
  tree: nextState.tree || state.tree
1535
1655
  };
1536
1656
  },
1657
+ /**
1658
+ * Reducer to save intermediate request updates.
1659
+ * Will only save the request status to inform all subscribed components.
1660
+ */
1537
1661
  setRequest: (state, action) => {
1538
1662
  const req = action.payload;
1539
1663
  state.requests[req.type][req.key] = req;
1540
1664
  },
1665
+ /**
1666
+ * Reducer to save the results of a CREATE operation.
1667
+ * Besides saving the new elements:
1668
+ * - If entity is a report, saves the reference ID in the state.reports list
1669
+ * - Else, adds the reference ID of the new entity to its parent's array
1670
+ */
1541
1671
  setCreateRequest(state, action) {
1542
1672
  const req = action.payload;
1543
1673
  state.requests[req.type][req.key] = req;
1544
- if (req.status === FetchStatus.SUCCESS) {
1674
+ if (req.status === "SUCCESS" /* SUCCESS */) {
1545
1675
  const newEntities = normalizeEntity(req.type, [req.data]);
1546
1676
  const nextEntities = combineRecords(state.entities, newEntities);
1547
1677
  state.entities = nextEntities;
@@ -1567,10 +1697,16 @@ var init_recordsSlice = __esm({
1567
1697
  }
1568
1698
  }
1569
1699
  },
1700
+ /**
1701
+ * Reducer to save the results of a READ operation.
1702
+ * Besides saving the new elements:
1703
+ * - If entity is a report, saves the nested report in the tree,
1704
+ * and updates the normalized reference list.
1705
+ */
1570
1706
  setReadRequest(state, action) {
1571
1707
  const req = action.payload;
1572
1708
  state.requests[req.type][req.key] = req;
1573
- if (req.status === FetchStatus.SUCCESS) {
1709
+ if (req.status === "SUCCESS" /* SUCCESS */) {
1574
1710
  const newEntities = normalizeEntity(req.type, req.data);
1575
1711
  const nextEntities = combineRecords(state.entities, newEntities);
1576
1712
  state.entities = nextEntities;
@@ -1580,10 +1716,15 @@ var init_recordsSlice = __esm({
1580
1716
  }
1581
1717
  }
1582
1718
  },
1719
+ /**
1720
+ * Reducer to save the results of a UPDATE operation.
1721
+ * Besides saving the new elements:
1722
+ * - Updates the order of the reference IDs in the parent's array
1723
+ */
1583
1724
  setUpdateRequest(state, action) {
1584
1725
  const req = action.payload;
1585
1726
  state.requests[req.type][req.key] = req;
1586
- if (req.status === FetchStatus.SUCCESS) {
1727
+ if (req.status === "SUCCESS" /* SUCCESS */) {
1587
1728
  const currEntities = normalizeEntity(req.type, [req.data]);
1588
1729
  let isInputUpdate;
1589
1730
  let targetId;
@@ -1628,10 +1769,15 @@ var init_recordsSlice = __esm({
1628
1769
  }
1629
1770
  }
1630
1771
  },
1772
+ /**
1773
+ * Reducer to save the results of a DELETE operation.
1774
+ * Removes the incumbent item from the records, and if said item had a
1775
+ * parent, remove the reference ID from its children.
1776
+ */
1631
1777
  setDeleteRequest(state, action) {
1632
1778
  const req = action.payload;
1633
1779
  state.requests[req.type][req.key] = req;
1634
- if (req.status === FetchStatus.SUCCESS) {
1780
+ if (req.status === "SUCCESS" /* SUCCESS */) {
1635
1781
  const { id, parentId, parentType } = req.data;
1636
1782
  delete state.entities[req.type][id];
1637
1783
  if (parentType && parentId != null) {
@@ -1642,27 +1788,33 @@ var init_recordsSlice = __esm({
1642
1788
  }
1643
1789
  },
1644
1790
  extraReducers: {
1791
+ /**
1792
+ * next-redux-wrapper implementation
1793
+ * This reducer is in charge of merging the server and client's states.
1794
+ * This is needed as some navigation operations will make requests to the
1795
+ * server for data, and the server may try to involve the store to calculate
1796
+ * properties for the client's components.
1797
+ */
1645
1798
  [HYDRATE]: (state, action) => {
1646
1799
  const nextState = action.payload.records;
1647
- console.log("cms:HYDRATE", nextState);
1648
1800
  const entities = combineRecords(state.entities, nextState.entities);
1649
1801
  return {
1650
1802
  entities,
1651
1803
  reports: Object.values(entities.report).map((item) => item.id),
1652
- requests: state.requests,
1804
+ requests: {
1805
+ block: {},
1806
+ dimension: {},
1807
+ report: {},
1808
+ section: {},
1809
+ variant: {},
1810
+ formatter: {}
1811
+ },
1812
+ // requests: combineRecords(state.requests, nextState.requests),
1653
1813
  tree: nextState.tree
1654
1814
  };
1655
1815
  }
1656
1816
  }
1657
1817
  });
1658
- FetchStatus = /* @__PURE__ */ ((FetchStatus2) => {
1659
- FetchStatus2["UNINITIALIZED"] = "UNINITIALIZED";
1660
- FetchStatus2["LOADING"] = "LOADING";
1661
- FetchStatus2["SUCCESS"] = "SUCCESS";
1662
- FetchStatus2["FAILURE"] = "FAILURE";
1663
- FetchStatus2["FETCHING"] = "FETCHING";
1664
- return FetchStatus2;
1665
- })(FetchStatus || {});
1666
1818
  }
1667
1819
  });
1668
1820
  function entityActionFactory(entitySet) {
@@ -1857,58 +2009,6 @@ var init_recordsActions = __esm({
1857
2009
  });
1858
2010
  }
1859
2011
  });
1860
- var initialState2, statusSlice;
1861
- var init_statusSlice = __esm({
1862
- "store/statusSlice.ts"() {
1863
- init_esm_shims();
1864
- init_envvars();
1865
- initialState2 = {
1866
- localeDefault: localeDefault3,
1867
- locales,
1868
- showToolbar: false,
1869
- activeSection: null,
1870
- previews: [],
1871
- query: {}
1872
- };
1873
- statusSlice = createSlice({
1874
- name: "status",
1875
- initialState: initialState2,
1876
- reducers: {
1877
- setStatus: (state, action) => {
1878
- Object.assign(state, action.payload);
1879
- }
1880
- },
1881
- extraReducers: {
1882
- [HYDRATE]: (_state, _action) => initialState2
1883
- }
1884
- });
1885
- }
1886
- });
1887
- var initialState3, variablesSlice;
1888
- var init_variablesSlice = __esm({
1889
- "store/variablesSlice.ts"() {
1890
- init_esm_shims();
1891
- initialState3 = {
1892
- attributes: {},
1893
- variables: {},
1894
- status: {}
1895
- };
1896
- variablesSlice = createSlice({
1897
- name: "variables",
1898
- initialState: initialState3,
1899
- reducers: {
1900
- setVariableChange: (state, action) => {
1901
- state.attributes = { ...state.attributes, ...action.payload.attributes };
1902
- state.variables = { ...state.variables, ...action.payload.variables };
1903
- state.status = { ...state.status, ...action.payload.status };
1904
- }
1905
- },
1906
- extraReducers: {
1907
- [HYDRATE]: (state, action) => initialState3
1908
- }
1909
- });
1910
- }
1911
- });
1912
2012
 
1913
2013
  // store/actions.ts
1914
2014
  var actions_exports = {};
@@ -1917,7 +2017,6 @@ __export(actions_exports, {
1917
2017
  createEntity: () => createEntity,
1918
2018
  deleteEntity: () => deleteEntity,
1919
2019
  deleteQueryParam: () => deleteQueryParam,
1920
- initialize: () => initialize,
1921
2020
  readEntity: () => readEntity,
1922
2021
  readMember: () => readMember,
1923
2022
  readMetadata: () => readMetadata,
@@ -1928,18 +2027,14 @@ __export(actions_exports, {
1928
2027
  searchRegenerate: () => searchRegenerate,
1929
2028
  searchRole: () => searchRole,
1930
2029
  searchUser: () => searchUser,
2030
+ setPreviews: () => setPreviews,
1931
2031
  setQueryParam: () => setQueryParam,
2032
+ setStatus: () => setStatus,
1932
2033
  updateEntity: () => updateEntity,
1933
2034
  updateUser: () => updateUser,
1934
2035
  urlProxy: () => urlProxy2,
1935
2036
  variantValidateSlug: () => variantValidateSlug
1936
2037
  });
1937
- function initialize() {
1938
- return (dispatch) => Promise.all([
1939
- dispatch(readEntity("report", { include: true })),
1940
- dispatch(readEntity("formatter", {}))
1941
- ]);
1942
- }
1943
2038
  function variantValidateSlug(dimension, slug) {
1944
2039
  return async (_, __, api) => {
1945
2040
  const result = await api.validateVariantSlug({ dimension, slug });
@@ -1990,7 +2085,7 @@ async function setStatusQuery(resource, dispatch, getState, status) {
1990
2085
  const newQuery = { ...oldStatus.query, ...status.query };
1991
2086
  Object.keys(newQuery).forEach((key) => newQuery[key] === void 0 && delete newQuery[key]);
1992
2087
  const payload = { ...newStatus, query: newQuery };
1993
- dispatch(statusSlice.actions.setStatus(payload));
2088
+ dispatch(setStatus(payload));
1994
2089
  if (oldStatus.activeSection) {
1995
2090
  dispatch(recalculateVariables(resource, { query: newQuery }));
1996
2091
  }
@@ -2014,11 +2109,13 @@ function recalculateVariables(resource, params) {
2014
2109
  query
2015
2110
  } = parsedParams;
2016
2111
  if (Object.keys(statusPayload).length)
2017
- dispatch(statusSlice.actions.setStatus(statusPayload));
2112
+ dispatch(statusActions.setStatus(statusPayload));
2018
2113
  const attributes = previewsToAttributes_default(previews);
2019
2114
  const blockContext = {
2020
2115
  variables: attributes,
2021
- query
2116
+ query,
2117
+ locale: localeDefault3
2118
+ //TODO: locale is variable
2022
2119
  };
2023
2120
  const data = await runConsumers(
2024
2121
  blocks,
@@ -2028,7 +2125,7 @@ function recalculateVariables(resource, params) {
2028
2125
  blockContext
2029
2126
  );
2030
2127
  const { variables } = data;
2031
- dispatch(variablesSlice.actions.setVariableChange({ attributes, variables, status: data.status }));
2128
+ dispatch(variablesActions.setVariableChange({ attributes, variables, status: {} }));
2032
2129
  };
2033
2130
  }
2034
2131
  function readMetadata(filters) {
@@ -2094,6 +2191,7 @@ function addNewReportToCurrentUser(params) {
2094
2191
  return result.data;
2095
2192
  };
2096
2193
  }
2194
+ var setStatus, setPreviews;
2097
2195
  var init_actions = __esm({
2098
2196
  "store/actions.ts"() {
2099
2197
  init_esm_shims();
@@ -2101,10 +2199,10 @@ var init_actions = __esm({
2101
2199
  init_previewsToAttributes();
2102
2200
  init_envvars();
2103
2201
  init_lib2();
2104
- init_recordsActions();
2105
2202
  init_statusSlice();
2106
2203
  init_variablesSlice();
2107
2204
  init_recordsActions();
2205
+ ({ setStatus, setPreviews } = statusActions);
2108
2206
  }
2109
2207
  });
2110
2208
  function ResourceProvider(props) {
@@ -2141,7 +2239,7 @@ var init_ResourceProvider = __esm({
2141
2239
  ResourceContext = createContext(initialContext);
2142
2240
  }
2143
2241
  });
2144
- function useEntityListFactory(entity) {
2242
+ function entityListHookFactory(entity) {
2145
2243
  return (id) => {
2146
2244
  const dispatch = useAppDispatch();
2147
2245
  const key = useMemo(() => crudKeyMaker.read(entity, { include: true }), []);
@@ -2164,7 +2262,7 @@ function useEntityListFactory(entity) {
2164
2262
  return value;
2165
2263
  };
2166
2264
  }
2167
- function useEntityRefFactory(entity) {
2265
+ function entityRefHookFactory(entity) {
2168
2266
  return (id) => {
2169
2267
  const dispatch = useAppDispatch();
2170
2268
  const key = useMemo(() => crudKeyMaker.read(entity, { id, include: true }), [id]);
@@ -2225,15 +2323,15 @@ var init_hooks = __esm({
2225
2323
  ({ localeDefault: localeDefault5 } = getLocales_default());
2226
2324
  useAppDispatch = useDispatch;
2227
2325
  useAppSelector = useSelector;
2228
- useReportList = useEntityListFactory("report");
2229
- useVariantList = useEntityListFactory("variant");
2230
- useFormatterList = useEntityListFactory("formatter");
2231
- useReportRef = useEntityRefFactory("report");
2232
- useSectionRef = useEntityRefFactory("section");
2233
- useBlockRef = useEntityRefFactory("block");
2234
- useDimensionRef = useEntityRefFactory("dimension");
2235
- useVariantRef = useEntityRefFactory("variant");
2236
- useFormatterRef = useEntityRefFactory("formatter");
2326
+ useReportList = entityListHookFactory("report");
2327
+ useVariantList = entityListHookFactory("variant");
2328
+ useFormatterList = entityListHookFactory("formatter");
2329
+ useReportRef = entityRefHookFactory("report");
2330
+ useSectionRef = entityRefHookFactory("section");
2331
+ useBlockRef = entityRefHookFactory("block");
2332
+ useDimensionRef = entityRefHookFactory("dimension");
2333
+ useVariantRef = entityRefHookFactory("variant");
2334
+ useFormatterRef = entityRefHookFactory("formatter");
2237
2335
  useInputVariablesFlat = (id) => {
2238
2336
  if (!id)
2239
2337
  return {};
@@ -2327,7 +2425,7 @@ var init_store = __esm({
2327
2425
  storeWrapper = createWrapper(storeFactory);
2328
2426
  }
2329
2427
  });
2330
- function withFetcher(Component, useRef7) {
2428
+ function withFetcher(Component, useRef6) {
2331
2429
  const ComponentWithFetcher = (props) => {
2332
2430
  const {
2333
2431
  id,
@@ -2335,7 +2433,7 @@ function withFetcher(Component, useRef7) {
2335
2433
  skelWidth,
2336
2434
  ...otherProps
2337
2435
  } = props;
2338
- const ref = useRef7(id);
2436
+ const ref = useRef6(id);
2339
2437
  if (ref.isUninitialized || ref.isFetching) {
2340
2438
  return /* @__PURE__ */ jsx(Skeleton, { width: skelWidth, height: skelHeight });
2341
2439
  }
@@ -3275,19 +3373,19 @@ var UserProvider_default = UserProvider;
3275
3373
 
3276
3374
  // frontend/components/auth/withPageRoleAuthRequired.tsx
3277
3375
  init_esm_shims();
3278
- var withPageRoleAuthRequired = (Success, allowedRoles, Err, options) => {
3279
- function hoc({ user }) {
3280
- function arrContains(arr1, arr2) {
3281
- return arr1.some((item) => arr2.includes(item));
3282
- }
3283
- const usersRoles = user?.bespoke_roles;
3284
- if (!usersRoles || allowedRoles.length > 0 && !arrContains(allowedRoles, usersRoles)) {
3285
- return /* @__PURE__ */ jsx(Err, {});
3286
- }
3287
- return /* @__PURE__ */ jsx(Success, { user });
3288
- }
3289
- return withPageAuthRequired(hoc, options);
3290
- };
3376
+ function withPageRoleAuthRequired(params) {
3377
+ const { SuccessComponent, FailureComponent, options } = params;
3378
+ const allowedRoles = new Set(params.allowedRoles);
3379
+ return withPageAuthRequired(({ user }) => {
3380
+ return useMemo(() => {
3381
+ const userRoles = user.bespoke_roles || [];
3382
+ if (allowedRoles.size === 0 || userRoles.some((role) => allowedRoles.has(role))) {
3383
+ return /* @__PURE__ */ jsx(SuccessComponent, { user });
3384
+ }
3385
+ return /* @__PURE__ */ jsx(FailureComponent, {});
3386
+ }, [user]);
3387
+ }, options);
3388
+ }
3291
3389
 
3292
3390
  // frontend/components/auth/useUser.tsx
3293
3391
  init_esm_shims();
@@ -3327,7 +3425,10 @@ function BespokeLogo(props) {
3327
3425
  ) });
3328
3426
  }
3329
3427
 
3330
- // components/commons/useLocation.tsx
3428
+ // views/BespokeManager.tsx
3429
+ init_ResourceProvider();
3430
+
3431
+ // hooks/useManagerLocation.tsx
3331
3432
  init_esm_shims();
3332
3433
  init_ResourceProvider();
3333
3434
  function useManagerLocation() {
@@ -3347,8 +3448,18 @@ function useManagerLocation() {
3347
3448
  router,
3348
3449
  page,
3349
3450
  params,
3451
+ query: router.query,
3350
3452
  basePath,
3351
3453
  href,
3454
+ setSearchParam(key, value) {
3455
+ const query = { ...router.query };
3456
+ if (value == null || value === "") {
3457
+ delete query[key];
3458
+ } else {
3459
+ query[key] = [].concat(value).join("!");
3460
+ }
3461
+ router.push({ pathname: router.pathname, query });
3462
+ },
3352
3463
  matches(...pathTokens) {
3353
3464
  return router.asPath === href(...pathTokens);
3354
3465
  },
@@ -3364,16 +3475,12 @@ function useManagerLocation() {
3364
3475
  }, [router.asPath]);
3365
3476
  }
3366
3477
 
3367
- // views/BespokeManager.tsx
3368
- init_ResourceProvider();
3369
-
3370
3478
  // views/EditReport.tsx
3371
3479
  init_esm_shims();
3372
3480
 
3373
3481
  // components/builder/CMSHeader.tsx
3374
3482
  init_esm_shims();
3375
3483
  init_store2();
3376
- init_actions();
3377
3484
 
3378
3485
  // components/builder/DimensionAutocomplete.tsx
3379
3486
  init_esm_shims();
@@ -3435,27 +3542,37 @@ var CMS_ROLES = {
3435
3542
  // api/endpoints/member.ts
3436
3543
  var { localeDefault: localeDefault7 } = getLocales_default();
3437
3544
  function parseReadMemberParams(query) {
3438
- let ids = normalizeList(query.ids);
3439
- if (ids.length === 0) {
3440
- ids = normalizeList(query["ids[]"]);
3545
+ const locale = normalizeList(query.locale)[0] || localeDefault7 || "en";
3546
+ const all = locale === "all" || yn3(query.all);
3547
+ const mode = normalizeList(query.mode)[0];
3548
+ if (mode === "ids") {
3549
+ return {
3550
+ all,
3551
+ mode,
3552
+ locale: all ? localeDefault7 : stripHTML(locale),
3553
+ ids: normalizeList(query.ids || query["ids[]"])
3554
+ };
3441
3555
  }
3442
- let content_ids = normalizeList(query.content_ids).map(parseFiniteNumber);
3443
- if (content_ids.length === 0) {
3444
- content_ids = normalizeList(query["content_ids[]"]).map(parseFiniteNumber);
3556
+ if (mode === "content_ids") {
3557
+ return {
3558
+ all,
3559
+ mode,
3560
+ locale: all ? localeDefault7 : stripHTML(locale),
3561
+ content_ids: normalizeList(query.content_ids || query["content_ids[]"]).map(parseFiniteNumber)
3562
+ };
3445
3563
  }
3446
- const locale = normalizeList(query.locale)[0] || localeDefault7 || "en";
3447
- const localeIsAll = locale === "all";
3448
- return {
3449
- all: localeIsAll,
3450
- locale: localeIsAll ? localeDefault7 : stripHTML(locale),
3451
- mode: ids.length > 0 ? "ids" : content_ids.length > 0 ? "content_ids" : "slugs",
3452
- ids,
3453
- content_ids,
3454
- slugs: normalizeList(query.slugs).map((token) => {
3455
- const [variantSlug, memberSlug] = token.split("/");
3456
- return { variantSlug, memberSlug };
3457
- })
3458
- };
3564
+ if (mode === "slugs") {
3565
+ return {
3566
+ all,
3567
+ mode,
3568
+ locale: all ? localeDefault7 : stripHTML(locale),
3569
+ slugs: normalizeList(query.slugs || query["slugs[]"]).map((token) => {
3570
+ const [variantSlug, memberSlug] = token.split("/");
3571
+ return { variantSlug, memberSlug };
3572
+ })
3573
+ };
3574
+ }
3575
+ throw new BackendError(400, `Invalid mode: '${mode}'`);
3459
3576
  }
3460
3577
  function parseSearchMemberParams(query) {
3461
3578
  const locale = normalizeList(query.locale)[0] || localeDefault7 || "en";
@@ -3546,10 +3663,10 @@ function DimensionAutocomplete({ id, locale, onSelect, initialSelection = void 0
3546
3663
  parseReadMemberParams(
3547
3664
  {
3548
3665
  locale,
3549
- content_ids: `${memberId}`,
3550
- slugs: [],
3666
+ content_ids: [`${memberId}`],
3551
3667
  all: "false",
3552
- mode: "ids"
3668
+ //as string
3669
+ mode: "content_ids"
3553
3670
  }
3554
3671
  )
3555
3672
  ));
@@ -3836,10 +3953,16 @@ function slugify(str) {
3836
3953
  stripEntities(stripHTML(str)),
3837
3954
  {
3838
3955
  replacement: "-",
3956
+ // replace spaces with replacement character, defaults to `-`
3839
3957
  remove: /[*+~.()'"!:@]/g,
3958
+ // remove characters that match regex, defaults to `undefined`
3840
3959
  lower: true,
3960
+ // convert to lower case, defaults to `false`
3841
3961
  strict: true,
3962
+ // strip special characters except replacement, defaults to `false`
3963
+ // locale: locale, // language code of the locale to use
3842
3964
  trim: true
3965
+ // trim leading and trailing replacement chars, defaults to `true`
3843
3966
  }
3844
3967
  );
3845
3968
  }
@@ -4726,18 +4849,73 @@ function ReportEditor({ id, onClose: closeHandler }) {
4726
4849
  }
4727
4850
  );
4728
4851
  }
4729
-
4730
- // components/builder/CMSHeader.tsx
4731
- init_ResourceProvider();
4852
+
4853
+ // components/builder/CMSHeader.tsx
4854
+ init_ResourceProvider();
4855
+
4856
+ // hooks/index.ts
4857
+ init_esm_shims();
4858
+
4859
+ // hooks/useMemberRef.ts
4860
+ init_esm_shims();
4861
+ init_store2();
4862
+ function usePreviewMembers(locale) {
4863
+ const dispatch = useAppDispatch();
4864
+ const location = useManagerLocation();
4865
+ const previews = useAppSelector((state) => state.status.previews);
4866
+ const param = location.query.preview;
4867
+ const slugs = Array.isArray(param) ? param.join("!") : param || "";
4868
+ useEffect(() => {
4869
+ const currentSlugs = slugs.split("!").filter(Boolean);
4870
+ const currentPreviews = previews.map(stringifyPreview);
4871
+ const matches = currentSlugs.join("\n") === currentPreviews.join("\n");
4872
+ if (currentSlugs.length > 0 && !matches) {
4873
+ dispatch(
4874
+ actions_exports.readMember({
4875
+ mode: "slugs",
4876
+ slugs: currentSlugs.map((slug) => {
4877
+ const [variantSlug, memberSlug] = slug.split("/");
4878
+ return { variantSlug, memberSlug };
4879
+ }),
4880
+ locale
4881
+ })
4882
+ ).then((res) => {
4883
+ dispatch(actions_exports.setPreviews(res.results));
4884
+ });
4885
+ }
4886
+ }, [slugs]);
4887
+ useEffect(() => {
4888
+ const nextParam = previews.map(stringifyPreview).join("!");
4889
+ if (nextParam && slugs !== nextParam) {
4890
+ location.setSearchParam("preview", nextParam);
4891
+ }
4892
+ }, [previews]);
4893
+ return previews;
4894
+ }
4895
+ function stringifyPreview(member) {
4896
+ const variant = "variant_slug" in member ? member.variant_slug : member.variant.slug;
4897
+ return `${variant}/${member.slug}`;
4898
+ }
4899
+
4900
+ // components/builder/HeaderLayout.tsx
4901
+ init_esm_shims();
4902
+ function HeaderLayout(props) {
4903
+ const { left, center, right } = props;
4904
+ return /* @__PURE__ */ jsx(Header, { fixed: true, height: 50, p: "xs", children: /* @__PURE__ */ jsxs(Group, { position: "apart", children: [
4905
+ /* @__PURE__ */ jsx("div", { className: "left", children: left }),
4906
+ /* @__PURE__ */ jsx("div", { className: "center", children: center }),
4907
+ /* @__PURE__ */ jsx("div", { className: "right", children: right })
4908
+ ] }) });
4909
+ }
4732
4910
  function CMSHeader(props) {
4733
- const { id } = props;
4911
+ const { report: currentReport } = props;
4912
+ const { id } = currentReport;
4734
4913
  const location = useManagerLocation();
4735
4914
  const dispatch = useAppDispatch();
4736
4915
  const resource = useContext(ResourceContext);
4737
4916
  const localeDefault9 = useAppSelector((state) => state.status.localeDefault);
4738
4917
  const localeOptions = useAppSelector(selectLocaleOptions);
4739
4918
  const reportList = useReportList();
4740
- const reportRef = useReportRef(id);
4741
4919
  const [opened, handlers] = useDisclosure(false);
4742
4920
  const [currentLocale, setCurrentLocale] = useUncontrolled({
4743
4921
  defaultValue: localeDefault9
@@ -4749,46 +4927,43 @@ function CMSHeader(props) {
4749
4927
  return [];
4750
4928
  return reportList.data.map((d) => ({ value: `${d.id}`, label: d.name }));
4751
4929
  }, [reportList.status]);
4752
- const currentReport = useMemo(() => {
4753
- if (!reportRef.isSuccess)
4754
- return void 0;
4755
- return reportRef.data;
4756
- }, [reportRef.status]);
4757
4930
  const dimensions = useMemo(() => {
4758
4931
  return currentReport && currentReport.dimensions ? currentReport.dimensions : [];
4759
4932
  }, [currentReport]);
4760
4933
  const showPreviewSelector = useMemo(() => {
4761
4934
  return dimensions.length > 0;
4762
4935
  }, [dimensions]);
4763
- const [previewMembers, setPreviewMembers] = useState(dimensions.map(() => void 0));
4936
+ const [previewMembers, setPreviewMembers] = useState([]);
4764
4937
  const [initialFavorites, setInitialFavorites] = useState([]);
4765
4938
  const onChangeReport = useCallback((value) => {
4766
4939
  location.push(`/reports/${value}`);
4767
4940
  }, [location]);
4768
4941
  const onSelectPreview = (previewMember) => {
4769
- if (currentReport) {
4770
- const newPreviews = currentReport.dimensions.map((dId) => {
4771
- let member;
4772
- if (previewMember) {
4773
- if (previewMember.dimension_id === dId) {
4774
- member = previewMember;
4775
- } else {
4776
- const anotherMember = previewMembers.find((m) => m ? m.dimension_id === dId : false);
4777
- if (anotherMember) {
4778
- member = anotherMember;
4779
- }
4942
+ const newPreviews = currentReport.dimensions.map((dId) => {
4943
+ let member;
4944
+ if (previewMember) {
4945
+ if (previewMember.dimension_id === dId) {
4946
+ member = previewMember;
4947
+ } else {
4948
+ const anotherMember = previewMembers.find((m) => m ? m.dimension_id === dId : false);
4949
+ if (anotherMember) {
4950
+ member = anotherMember;
4780
4951
  }
4781
4952
  }
4782
- return member;
4783
- });
4784
- setPreviewMembers(newPreviews);
4785
- }
4953
+ }
4954
+ return member;
4955
+ });
4956
+ setPreviewMembers(newPreviews);
4786
4957
  };
4787
4958
  useEffect(() => {
4788
- setPreviewMembers(dimensions.map(() => void 0));
4959
+ setPreviewMembers([]);
4789
4960
  }, [dimensions]);
4790
4961
  useEffect(() => {
4791
- dispatch(recalculateVariables(resource, { previews: previewMembers }));
4962
+ if (previewMembers.length > 0) {
4963
+ dispatch(actions_exports.recalculateVariables(resource, {
4964
+ previews: previewMembers
4965
+ }));
4966
+ }
4792
4967
  }, [previewMembers]);
4793
4968
  useEffect(() => {
4794
4969
  if (castedUser) {
@@ -4800,21 +4975,6 @@ function CMSHeader(props) {
4800
4975
  }
4801
4976
  }
4802
4977
  }, [castedUser, id, previewMembers]);
4803
- if (reportRef.isUninitialized || reportRef.isFetching) {
4804
- return /* @__PURE__ */ jsx(
4805
- HeaderLayout,
4806
- {
4807
- left: /* @__PURE__ */ jsx(ActionIcon, { component: Link, href: location.href(), color: "blue", variant: "filled", children: /* @__PURE__ */ jsx(IconChevronLeft, { size: 24 }) }),
4808
- center: /* @__PURE__ */ jsxs(Group, { spacing: "xs", children: [
4809
- /* @__PURE__ */ jsx(Skeleton, { height: 30, width: 100 }),
4810
- /* @__PURE__ */ jsx(Skeleton, { height: 30, width: 200 })
4811
- ] })
4812
- }
4813
- );
4814
- }
4815
- if (reportRef.isError) {
4816
- return null;
4817
- }
4818
4978
  return /* @__PURE__ */ jsx(
4819
4979
  HeaderLayout,
4820
4980
  {
@@ -4839,7 +4999,7 @@ function CMSHeader(props) {
4839
4999
  onChange: onChangeReport
4840
5000
  }
4841
5001
  ),
4842
- showPreviewSelector && currentReport && currentReport.dimensions.map((dId, ix) => /* @__PURE__ */ jsx(
5002
+ showPreviewSelector && dimensions.map((dId, ix) => /* @__PURE__ */ jsx(
4843
5003
  DimensionAutocomplete,
4844
5004
  {
4845
5005
  id: dId,
@@ -4877,14 +5037,6 @@ function CMSHeader(props) {
4877
5037
  }
4878
5038
  );
4879
5039
  }
4880
- function HeaderLayout(props) {
4881
- const { left, center, right } = props;
4882
- return /* @__PURE__ */ jsx(Header, { fixed: true, height: 50, p: "xs", children: /* @__PURE__ */ jsxs(Group, { position: "apart", children: [
4883
- /* @__PURE__ */ jsx("div", { className: "left", children: left }),
4884
- /* @__PURE__ */ jsx("div", { className: "center", children: center }),
4885
- /* @__PURE__ */ jsx("div", { className: "right", children: right })
4886
- ] }) });
4887
- }
4888
5040
  var selectLocaleOptions = (state) => state.status.locales.map((d) => ({ value: d, label: d.toUpperCase() }));
4889
5041
 
4890
5042
  // components/sections/Section.tsx
@@ -5794,22 +5946,28 @@ init_hooks();
5794
5946
  init_runConsumers();
5795
5947
  init_varSwap();
5796
5948
  init_mortarEval();
5949
+ var emptyStatus = {
5950
+ api: null,
5951
+ duration: null,
5952
+ error: null,
5953
+ log: [],
5954
+ resp: null
5955
+ };
5797
5956
  function BlockPreview(props) {
5798
5957
  const {
5799
5958
  active,
5800
5959
  allowed,
5801
5960
  blockStateContent,
5802
5961
  debug,
5803
- id,
5962
+ for: block,
5804
5963
  locale
5805
5964
  } = props;
5806
- const variables = useInputVariablesFlat(id);
5807
- const block = useBlockRef(id).data;
5965
+ const variables = useInputVariablesFlat(block.id);
5808
5966
  const formatterFunctions = useFormatterFunctionsForLocale();
5809
- const blockContext = useBlockContext(id, locale);
5967
+ const blockContext = useBlockContext(block.id, locale);
5810
5968
  const blockContent = types_default[block.type].renderPreviewOnEdit && blockStateContent ? blockStateContent : getBlockContent(block, locale);
5811
5969
  const [content, setContent] = useState(null);
5812
- const [status, setStatus] = useState({});
5970
+ const [status, setStatus2] = useState(emptyStatus);
5813
5971
  useEffect(() => {
5814
5972
  const fetch = async () => {
5815
5973
  if (block.type === BLOCK_TYPES.VIZ) {
@@ -5820,27 +5978,27 @@ function BlockPreview(props) {
5820
5978
  active
5821
5979
  };
5822
5980
  setContent(config);
5823
- setStatus({ error: void 0, log: [] });
5981
+ setStatus2(emptyStatus);
5824
5982
  return;
5825
5983
  }
5826
5984
  if (!active && !types_default[block.type].evalWhenNonActive) {
5827
5985
  const { nonActiveAdapter } = types_default[block.type];
5828
5986
  const config = nonActiveAdapter && typeof nonActiveAdapter === "function" ? nonActiveAdapter() : {};
5829
5987
  setContent(config);
5830
- setStatus({ error: void 0, log: [] });
5988
+ setStatus2(emptyStatus);
5831
5989
  return;
5832
5990
  }
5833
5991
  if (block.type === BLOCK_TYPES.GENERATOR) {
5834
5992
  const { outputVariables, status: status2 } = await runSingleBlock(block, formatterFunctions, blockContext);
5835
5993
  setContent({ outputVariables });
5836
- setStatus(status2);
5994
+ setStatus2(status2);
5837
5995
  return;
5838
5996
  }
5839
5997
  if (block.type === BLOCK_TYPES.SELECTOR) {
5840
5998
  const { renderVariables, status: status2 } = await runSingleBlock(block, formatterFunctions, blockContext);
5841
- const content3 = adapters_default[block.type] && typeof adapters_default[block.type] === "function" ? adapters_default[block.type](renderVariables, id) : renderVariables;
5999
+ const content3 = adapters_default[block.type] && typeof adapters_default[block.type] === "function" ? adapters_default[block.type](renderVariables, block.id) : renderVariables;
5842
6000
  setContent(content3);
5843
- setStatus(status2);
6001
+ setStatus2(status2);
5844
6002
  return;
5845
6003
  }
5846
6004
  const swappedLogic = varSwap_default(blockContent?.logic, formatterFunctions, blockContext);
@@ -5852,9 +6010,9 @@ function BlockPreview(props) {
5852
6010
  void 0,
5853
6011
  blockContext
5854
6012
  );
5855
- const content2 = adapters_default[block.type] && typeof adapters_default[block.type] === "function" ? adapters_default[block.type](vars, id) : vars;
6013
+ const content2 = adapters_default[block.type] && typeof adapters_default[block.type] === "function" ? adapters_default[block.type](vars, block.id) : vars;
5856
6014
  setContent(content2);
5857
- setStatus({ error: error2, log: log2 });
6015
+ setStatus2({ ...emptyStatus, error: error2, log: log2 });
5858
6016
  };
5859
6017
  fetch();
5860
6018
  }, [blockContent, variables]);
@@ -5890,7 +6048,7 @@ function BlockPreview(props) {
5890
6048
  debug && error && /* @__PURE__ */ jsx(Textarea, { label: "Error", readOnly: true, minRows: 3, value: error })
5891
6049
  ] });
5892
6050
  }
5893
- var BlockPreview_default = BlockPreview;
6051
+ var BlockPreview_default = withFetcher(BlockPreview, useBlockRef);
5894
6052
 
5895
6053
  // components/blocks/BlockSettings.tsx
5896
6054
  init_esm_shims();
@@ -6122,6 +6280,18 @@ function MCEWrapper({
6122
6280
  menubar: false,
6123
6281
  toolbar: false,
6124
6282
  statusbar: false,
6283
+ /*
6284
+ plugins: [
6285
+ "advlist autolink lists link image charmap print preview anchor",
6286
+ "searchreplace visualblocks code fullscreen",
6287
+ "insertdatetime media table paste code help wordcount",
6288
+ ],
6289
+
6290
+ toolbar: "undo redo | formatselect | "
6291
+ + "bold italic backcolor | alignleft aligncenter "
6292
+ + "alignright alignjustify | bullist numlist outdent indent | "
6293
+ + "removeformat | help",
6294
+ */
6125
6295
  content_style: "body { font-family:Helvetica,Arial,sans-serif; font-size:14px }"
6126
6296
  }
6127
6297
  }
@@ -6995,6 +7165,7 @@ function DataTab(props) {
6995
7165
  wb,
6996
7166
  utils.json_to_sheet(selectedSource.data),
6997
7167
  filename.substring(0, 30)
7168
+ // Sheet name max length
6998
7169
  );
6999
7170
  const xls = write(wb, { bookType: "xlsx", bookSST: true, type: "binary" });
7000
7171
  zipFile.file(filename, xls, { binary: true });
@@ -7137,7 +7308,9 @@ function ImageTab(props) {
7137
7308
  }
7138
7309
  return true;
7139
7310
  },
7140
- style: {}
7311
+ style: {
7312
+ // background: "green",
7313
+ }
7141
7314
  }
7142
7315
  ).then((dataUrl) => {
7143
7316
  const link = document.createElement("a");
@@ -7770,7 +7943,7 @@ function SectionEditor({
7770
7943
  Overlay,
7771
7944
  {
7772
7945
  className: "cms-section-overlay",
7773
- onClick: onActivate,
7946
+ onClick: () => onActivate(section.id),
7774
7947
  color: theme.black,
7775
7948
  opacity: 0.5,
7776
7949
  style: { cursor: "pointer" }
@@ -7795,71 +7968,63 @@ function SectionEditor({
7795
7968
  var SectionEditorWithFetcher = withFetcher(SectionEditor, useSectionRef);
7796
7969
 
7797
7970
  // views/EditReport.tsx
7971
+ init_ResourceProvider();
7798
7972
  init_ordering();
7799
7973
  init_store2();
7800
7974
  init_actions();
7801
- init_ResourceProvider();
7802
7975
 
7803
- // libs/auth/utils.ts
7976
+ // store/recordsSelectors.ts
7804
7977
  init_esm_shims();
7805
- var getReportAccess = (user) => {
7806
- const reportsMetadata = user && user.bespoke_app_metadata && user.bespoke_app_metadata.reports && Array.isArray(user.bespoke_app_metadata.reports) ? user.bespoke_app_metadata.reports : [];
7807
- return reportsMetadata.map((rm) => rm.reportId);
7808
- };
7809
- function ReportEditor2(props) {
7810
- const { id } = props;
7811
- const ref = useReportRef(id);
7812
- const { user } = useUser();
7813
- const reportAccess = getReportAccess(user);
7814
- const location = useManagerLocation();
7815
- if (reportAccess.length !== 0 && !reportAccess.includes(id)) {
7816
- location.replace("/unauthorize");
7817
- }
7818
- if (ref.isError) {
7819
- return /* @__PURE__ */ jsx(Center, { style: { height: 300 }, children: /* @__PURE__ */ jsx(Alert, { icon: /* @__PURE__ */ jsx(IconCircleX, { size: 20 }), title: `Error ${ref.error.code}`, color: "red", children: ref.error.message }) });
7820
- }
7821
- if (ref.isUninitialized || !ref.data) {
7822
- return /* @__PURE__ */ jsx(Loader, {});
7823
- }
7824
- return /* @__PURE__ */ jsx(InteractiveReport, { for: ref.data, isLoading: ref.isFetching });
7978
+ var selectSectionRecords = (state) => state.records.entities.section;
7979
+ function BuilderEditor(props) {
7980
+ const reportRef = useReportRef(props.id);
7981
+ return useMemo(() => {
7982
+ if (reportRef.isError) {
7983
+ return /* @__PURE__ */ jsx(Center, { style: { height: 300 }, children: /* @__PURE__ */ jsx(Alert, { icon: /* @__PURE__ */ jsx(IconCircleX, { size: 20 }), title: `Error ${reportRef.error.code}`, color: "red", children: reportRef.error.message }) });
7984
+ }
7985
+ if (reportRef.isUninitialized || !reportRef.data) {
7986
+ return /* @__PURE__ */ jsx(Loader, {});
7987
+ }
7988
+ return /* @__PURE__ */ jsx(
7989
+ InteractiveReport,
7990
+ {
7991
+ report: reportRef.data,
7992
+ locale: props.locale,
7993
+ isLoading: reportRef.isFetching
7994
+ }
7995
+ );
7996
+ }, [reportRef.status]);
7825
7997
  }
7826
- function InteractiveReport({ for: report, isLoading }) {
7998
+ function InteractiveReport(props) {
7999
+ const { report, isLoading } = props;
7827
8000
  const theme = useMantineTheme();
7828
8001
  const dispatch = useAppDispatch();
7829
8002
  const resource = useContext(ResourceContext);
7830
8003
  const { newConfirmation } = useDialog();
7831
- const sectionMap = useAppSelector((state) => state.records.entities.section);
7832
- const previews = useAppSelector((state) => state.status.previews);
7833
- const previewRef = useRef([]);
7834
- useEffect(() => {
7835
- previewRef.current = previews;
7836
- }, [previews]);
8004
+ const previews = usePreviewMembers(props.locale);
8005
+ const sectionMap = useAppSelector(selectSectionRecords);
7837
8006
  const [activeSection, setActiveSection] = useState(null);
7838
8007
  const [sectionOrder, setSectionOrder] = useState(report.sections);
7839
8008
  useEffect(() => {
7840
8009
  setSectionOrder(report.sections);
7841
8010
  }, [report.sections]);
7842
- const maybeActivate = async (sectionId) => {
7843
- if (previewRef.current.length < report.dimensions.length) {
7844
- try {
7845
- await newConfirmation({
7846
- title: "You haven't chosen a member!",
7847
- message: "You may want to choose a member before editing this section.",
7848
- cancelText: "OK, I'll choose one.",
7849
- confirmText: "Don't tell me what to do!"
7850
- }).then(() => {
7851
- onActivate(sectionId);
7852
- });
7853
- } catch {
7854
- }
8011
+ const maybeActivate = useCallback((sectionId) => {
8012
+ const onActivate = () => {
8013
+ setActiveSection(sectionId);
8014
+ dispatch(recalculateVariables(resource, { sid: sectionId }));
8015
+ };
8016
+ if (previews.length < report.dimensions.length) {
8017
+ newConfirmation({
8018
+ title: "You haven't chosen a member!",
8019
+ message: "You may want to choose a member before editing this section.",
8020
+ cancelText: "OK, I'll choose one.",
8021
+ confirmText: "Don't tell me what to do!"
8022
+ }).then(onActivate, () => {
8023
+ });
7855
8024
  } else {
7856
- onActivate(sectionId);
8025
+ onActivate();
7857
8026
  }
7858
- };
7859
- const onActivate = useCallback((sectionId) => {
7860
- setActiveSection(sectionId);
7861
- dispatch(recalculateVariables(resource, { sid: sectionId }));
7862
- }, [report.id]);
8027
+ }, [report.dimensions, previews]);
7863
8028
  const onDragEnd = useCallback((result) => {
7864
8029
  if (!result.destination || result.source.index === result.destination.index)
7865
8030
  return;
@@ -7898,7 +8063,7 @@ function InteractiveReport({ for: report, isLoading }) {
7898
8063
  id: sectionId,
7899
8064
  isActive: sectionId === activeSection,
7900
8065
  isDragging: snapshot.isDragging,
7901
- onActivate: () => maybeActivate(sectionId),
8066
+ onActivate: maybeActivate,
7902
8067
  dragHandleProps: draggableProvided.dragHandleProps
7903
8068
  }
7904
8069
  ),
@@ -7910,15 +8075,14 @@ function InteractiveReport({ for: report, isLoading }) {
7910
8075
  droppableProvided.placeholder
7911
8076
  ]
7912
8077
  }
7913
- ), [sectionOrder, activeSection]);
8078
+ ), [sectionOrder, activeSection, maybeActivate]);
7914
8079
  return /* @__PURE__ */ jsxs(Stack, { styles: { backgroundColor: theme.colors.gray[2] }, children: [
7915
- /* @__PURE__ */ jsx(CMSHeader, { id: report.id }),
8080
+ /* @__PURE__ */ jsx(CMSHeader, { report }),
7916
8081
  /* @__PURE__ */ jsx(LoadingOverlay, { visible: isLoading }),
7917
8082
  report.sections.length === 0 && /* @__PURE__ */ jsx(CreateSectionButton, { index: 0, report }),
7918
8083
  /* @__PURE__ */ jsx(DragDropContext, { onDragEnd, children: /* @__PURE__ */ jsx(Droppable, { droppableId: "sections", children: droppableChild }) })
7919
8084
  ] });
7920
8085
  }
7921
- withFetcher(InteractiveReport, useReportRef);
7922
8086
  function CreateSectionButton({ index, report }) {
7923
8087
  const theme = useMantineTheme();
7924
8088
  const dispatch = useAppDispatch();
@@ -8453,6 +8617,31 @@ function FormatterEditor() {
8453
8617
  ] });
8454
8618
  }
8455
8619
 
8620
+ // views/HelloView.tsx
8621
+ init_esm_shims();
8622
+ function HelloView() {
8623
+ const { user } = useUser();
8624
+ return /* @__PURE__ */ jsxs(
8625
+ Flex,
8626
+ {
8627
+ mih: "100vh",
8628
+ gap: "md",
8629
+ justify: "center",
8630
+ align: "center",
8631
+ direction: "column",
8632
+ wrap: "wrap",
8633
+ children: [
8634
+ /* @__PURE__ */ jsxs(Title, { children: [
8635
+ "Hi, ",
8636
+ user.name,
8637
+ "!"
8638
+ ] }),
8639
+ /* @__PURE__ */ jsx(Text, { children: "Welcome to Bespoke CMS. Have fun creating some amazing automated reports here!" })
8640
+ ]
8641
+ }
8642
+ );
8643
+ }
8644
+
8456
8645
  // views/MetadataEditor.tsx
8457
8646
  init_esm_shims();
8458
8647
 
@@ -8866,7 +9055,7 @@ function ImagePreview2({
8866
9055
  }) {
8867
9056
  let extraParam = "";
8868
9057
  if (forceRefreshTimestamp) {
8869
- extraParam = `&t=${new Date().getTime()}`;
9058
+ extraParam = `&t=${( new Date()).getTime()}`;
8870
9059
  }
8871
9060
  const imageUrl = member && member.image_id ? `/api/cms/member/image.png?member=${member.content_id}&size=${size}${extraParam}` : "https://placehold.jp/cccccc/ffffff/900x600.png?text=None";
8872
9061
  return /* @__PURE__ */ jsx(Image, { height, width, radius: "md", src: imageUrl });
@@ -8899,7 +9088,7 @@ function MemberForm({ memberId, onEditEnd }) {
8899
9088
  const memberRecord = await dispatch(actions_exports.readMember(
8900
9089
  {
8901
9090
  locale: "all",
8902
- content_ids: memberId,
9091
+ content_ids: [memberId],
8903
9092
  all: false,
8904
9093
  mode: "content_ids"
8905
9094
  }
@@ -9381,6 +9570,33 @@ function MetadataEditor() {
9381
9570
  ] });
9382
9571
  }
9383
9572
 
9573
+ // views/NotFoundView.tsx
9574
+ init_esm_shims();
9575
+ function NotFoundView() {
9576
+ const { user } = useUser();
9577
+ return /* @__PURE__ */ jsxs(
9578
+ Flex,
9579
+ {
9580
+ mih: "100vh",
9581
+ gap: "md",
9582
+ justify: "center",
9583
+ align: "center",
9584
+ direction: "column",
9585
+ wrap: "wrap",
9586
+ children: [
9587
+ /* @__PURE__ */ jsx(Title, { children: "Not found." }),
9588
+ /* @__PURE__ */ jsxs(Title, { order: 2, children: [
9589
+ "Sorry, ",
9590
+ user?.name,
9591
+ "!"
9592
+ ] }),
9593
+ /* @__PURE__ */ jsx(Text, { children: "The page you are looking for is not here." }),
9594
+ /* @__PURE__ */ jsx(Button, { component: "a", href: "/", children: "Back to homepage" })
9595
+ ]
9596
+ }
9597
+ );
9598
+ }
9599
+
9384
9600
  // views/PickReport.tsx
9385
9601
  init_esm_shims();
9386
9602
 
@@ -9414,6 +9630,13 @@ withFetcher(ReportCard, useReportRef);
9414
9630
  // views/PickReport.tsx
9415
9631
  init_store2();
9416
9632
  init_hooks();
9633
+
9634
+ // libs/auth/utils.ts
9635
+ init_esm_shims();
9636
+ var getReportAccess = (user) => {
9637
+ const reportsMetadata = user && user.bespoke_app_metadata && user.bespoke_app_metadata.reports && Array.isArray(user.bespoke_app_metadata.reports) ? user.bespoke_app_metadata.reports : [];
9638
+ return reportsMetadata.map((rm) => rm.reportId);
9639
+ };
9417
9640
  function ReportPicker() {
9418
9641
  const dispatch = useAppDispatch();
9419
9642
  const [createLoading, setCreateLoading] = useState(false);
@@ -9504,33 +9727,6 @@ function UnauthorizeView() {
9504
9727
  );
9505
9728
  }
9506
9729
 
9507
- // views/NotFoundView.tsx
9508
- init_esm_shims();
9509
- function NotFoundView() {
9510
- const { user } = useUser();
9511
- return /* @__PURE__ */ jsxs(
9512
- Flex,
9513
- {
9514
- mih: "100vh",
9515
- gap: "md",
9516
- justify: "center",
9517
- align: "center",
9518
- direction: "column",
9519
- wrap: "wrap",
9520
- children: [
9521
- /* @__PURE__ */ jsx(Title, { children: "Not found." }),
9522
- /* @__PURE__ */ jsxs(Title, { order: 2, children: [
9523
- "Sorry, ",
9524
- user?.name,
9525
- "!"
9526
- ] }),
9527
- /* @__PURE__ */ jsx(Text, { children: "The page you are looking for is not here." }),
9528
- /* @__PURE__ */ jsx(Button, { component: "a", href: "/", children: "Back to homepage" })
9529
- ]
9530
- }
9531
- );
9532
- }
9533
-
9534
9730
  // views/UsersEditor.tsx
9535
9731
  init_esm_shims();
9536
9732
  init_store2();
@@ -9991,6 +10187,38 @@ function UsersTable({ response, onClickEdit, onSort, onPageChange }) {
9991
10187
  title: "Email",
9992
10188
  accessor: "email"
9993
10189
  },
10190
+ /*{
10191
+ title: `Keywords ${localeDefault.toUpperCase()}`,
10192
+ accessor: "keywords",
10193
+ render: ({contentByLocale}) => {
10194
+ const defaultLocalized = contentByLocale.find((item) => item.locale === localeDefault);
10195
+ const othersLocalized = contentByLocale.filter((item) => item.locale !== localeDefault);
10196
+ const keywords = (defaultLocalized.keywords ? defaultLocalized.keywords : [])
10197
+ .map((k) => <Badge key={k}>{k}</Badge>);
10198
+ const keywordsTooltipContent = othersLocalized.reduce((acc, item) => {
10199
+ const otherKeywords = item.keywords || [];
10200
+ const extraKeywords = `${item.locale.toUpperCase()}: ${otherKeywords.length > 0
10201
+ ? otherKeywords.join(",")
10202
+ : "None"
10203
+ }`;
10204
+ const newLine = acc !== "" ? "\n" : "";
10205
+ return `${acc}${newLine}${extraKeywords}`;
10206
+ }, "");
10207
+ return (
10208
+ <Group>
10209
+ <span>{keywords.length > 0 ? keywords : <Badge color="gray">None</Badge>}</span>
10210
+ {othersLocalized.length > 0 && (
10211
+ <Tooltip label={keywordsTooltipContent}>
10212
+ <Avatar size="sm" color="pink" radius="xl">
10213
+ +
10214
+ {othersLocalized.length}
10215
+ </Avatar>
10216
+ </Tooltip>
10217
+ )}
10218
+ </Group>
10219
+ );
10220
+ },
10221
+ },*/
9994
10222
  {
9995
10223
  title: "",
9996
10224
  accessor: "actions",
@@ -10089,75 +10317,31 @@ function UsersEditor() {
10089
10317
  editingId && /* @__PURE__ */ jsx(UserForm, { userId: editingId, onEditEnd: onEditClose, roles })
10090
10318
  ] });
10091
10319
  }
10092
-
10093
- // views/HelloView.tsx
10094
- init_esm_shims();
10095
- function HelloView() {
10096
- const { user } = useUser();
10097
- return /* @__PURE__ */ jsxs(
10098
- Flex,
10099
- {
10100
- mih: "100vh",
10101
- gap: "md",
10102
- justify: "center",
10103
- align: "center",
10104
- direction: "column",
10105
- wrap: "wrap",
10106
- children: [
10107
- /* @__PURE__ */ jsxs(Title, { children: [
10108
- "Hi, ",
10109
- user.name,
10110
- "!"
10111
- ] }),
10112
- /* @__PURE__ */ jsx(Text, { children: "Welcome to Bespoke CMS. Have fun creating some amazing automated reports here!" })
10113
- ]
10114
- }
10115
- );
10116
- }
10117
- function BespokeManagerPanel(options) {
10320
+ init_envvars();
10321
+ function BespokeManager(options) {
10118
10322
  const {
10119
10323
  title = "Bespoke CMS",
10120
- pathSegment = "path"
10324
+ pathSegment = "bespoke",
10325
+ locale = localeDefault3
10121
10326
  } = options;
10122
10327
  const notifications = {
10123
10328
  position: "bottom-center",
10124
10329
  ...options.notifications
10125
10330
  };
10126
- return BespokeManagerPage;
10331
+ return withPageRoleAuthRequired({
10332
+ allowedRoles: [CMS_ROLES.ADMIN, CMS_ROLES.EDITOR, CMS_ROLES.WRITER],
10333
+ SuccessComponent: BespokeManagerPage,
10334
+ FailureComponent: UnauthorizeView
10335
+ });
10127
10336
  function BespokeManagerPage() {
10128
10337
  return /* @__PURE__ */ jsxs(ResourceProvider, { pathSegment, children: [
10129
10338
  /* @__PURE__ */ jsx(Head, { children: /* @__PURE__ */ jsx("title", { children: title }) }),
10130
- /* @__PURE__ */ jsx(MantineProvider, { children: /* @__PURE__ */ jsx(NotificationsProvider, { ...notifications, children: /* @__PURE__ */ jsx(DialogProvider, { children: /* @__PURE__ */ jsx(BespokeManagerShell, {}) }) }) })
10339
+ /* @__PURE__ */ jsx(MantineProvider, { children: /* @__PURE__ */ jsx(NotificationsProvider, { ...notifications, children: /* @__PURE__ */ jsx(DialogProvider, { children: /* @__PURE__ */ jsx(BespokeManagerShell, { locale }) }) }) })
10131
10340
  ] });
10132
10341
  }
10133
10342
  }
10134
- function MainLink({ item, disabled }) {
10135
- const { page } = useManagerLocation();
10136
- return /* @__PURE__ */ jsx(Link, { href: item.href, passHref: true, children: /* @__PURE__ */ jsx(
10137
- UnstyledButton,
10138
- {
10139
- disabled,
10140
- mt: "xs",
10141
- sx: (theme) => ({
10142
- border: "1px solid white",
10143
- borderColor: page && page.includes(item.href) ? "#ccc" : "transparent",
10144
- backgroundColor: "transparent",
10145
- display: "block",
10146
- width: "100%",
10147
- padding: theme.spacing.xs,
10148
- borderRadius: theme.radius.sm,
10149
- "&:hover": {
10150
- backgroundColor: "#f9f9f9"
10151
- }
10152
- }),
10153
- children: /* @__PURE__ */ jsxs(Group, { children: [
10154
- /* @__PURE__ */ jsx(ThemeIcon, { color: disabled ? "gray" : item.color, variant: "light", children: item.icon }),
10155
- /* @__PURE__ */ jsx(Text, { size: "sm", children: item.label })
10156
- ] })
10157
- }
10158
- ) }, item.label);
10159
- }
10160
10343
  function BespokeManagerShell(props) {
10344
+ const { locale } = props;
10161
10345
  const [opened, { toggle: toggleOpened }] = useDisclosure(true);
10162
10346
  const { user, error, isLoading } = useUser();
10163
10347
  const location = useManagerLocation();
@@ -10198,7 +10382,9 @@ function BespokeManagerShell(props) {
10198
10382
  const menuLinks = [];
10199
10383
  links.forEach((link) => {
10200
10384
  if (pastRole !== link.roleRequired) {
10201
- menuLinks.push(/* @__PURE__ */ jsx(Divider, { my: "xs", label: link.roleRequired, labelPosition: "center" }, link.roleRequired));
10385
+ menuLinks.push(
10386
+ /* @__PURE__ */ jsx(Divider, { my: "xs", label: link.roleRequired, labelPosition: "center" }, link.roleRequired)
10387
+ );
10202
10388
  }
10203
10389
  menuLinks.push(
10204
10390
  /* @__PURE__ */ jsx(MainLink, { item: link, disabled: !user2.bespoke_roles.includes(link.roleRequired) }, link.label)
@@ -10268,48 +10454,69 @@ function BespokeManagerShell(props) {
10268
10454
  }, [location, opened, user]);
10269
10455
  const route = useMemo(() => {
10270
10456
  const item = links.find((page) => page.href.includes(location.page));
10271
- if (location.page === void 0) {
10457
+ if (location.page === "welcome") {
10272
10458
  return /* @__PURE__ */ jsx(HelloView, {});
10273
10459
  }
10274
- if (item) {
10275
- if (user && Array.isArray(user.bespoke_roles) && user.bespoke_roles.includes(item.roleRequired)) {
10276
- if (location.page === "metadata") {
10277
- return /* @__PURE__ */ jsx(MetadataEditor, {});
10278
- }
10279
- if (location.page === "formatters") {
10280
- return /* @__PURE__ */ jsx(FormatterEditor, {});
10281
- }
10282
- if (location.page === "reports") {
10283
- if (location.params.length > 0) {
10284
- const report_id = Number.parseInt(location.params[0]);
10285
- return /* @__PURE__ */ jsx(ReportEditor2, { id: report_id });
10286
- }
10287
- return /* @__PURE__ */ jsx(ReportPicker, {});
10288
- }
10289
- if (location.page === "users") {
10290
- return /* @__PURE__ */ jsx(UsersEditor, {});
10460
+ if (user && Array.isArray(user.bespoke_roles) && user.bespoke_roles.includes(item.roleRequired)) {
10461
+ if (location.page === "metadata") {
10462
+ return /* @__PURE__ */ jsx(MetadataEditor, {});
10463
+ }
10464
+ if (location.page === "formatters") {
10465
+ return /* @__PURE__ */ jsx(FormatterEditor, {});
10466
+ }
10467
+ if (location.page === "reports") {
10468
+ if (location.params.length > 0) {
10469
+ const reportId = Number.parseInt(location.params[0]);
10470
+ return /* @__PURE__ */ jsx(BuilderEditor, { id: reportId, locale });
10291
10471
  }
10292
- } else {
10293
- return /* @__PURE__ */ jsx(UnauthorizeView, {});
10472
+ return /* @__PURE__ */ jsx(ReportPicker, {});
10473
+ }
10474
+ if (location.page === "users") {
10475
+ return /* @__PURE__ */ jsx(UsersEditor, {});
10294
10476
  }
10477
+ } else {
10478
+ return /* @__PURE__ */ jsx(UnauthorizeView, {});
10295
10479
  }
10296
10480
  return /* @__PURE__ */ jsx(NotFoundView, {});
10297
10481
  }, [location, user]);
10298
10482
  return /* @__PURE__ */ jsx(AppShell, { fixed: true, padding: 0, navbar, children: route });
10299
10483
  }
10300
- function BespokeManager(params) {
10301
- return withPageRoleAuthRequired(
10302
- BespokeManagerPanel(params),
10303
- [CMS_ROLES.ADMIN, CMS_ROLES.EDITOR, CMS_ROLES.WRITER],
10304
- () => /* @__PURE__ */ jsx(UnauthorizeView, {}),
10305
- {}
10306
- );
10484
+ function MainLink({ item, disabled }) {
10485
+ const { page } = useManagerLocation();
10486
+ return /* @__PURE__ */ jsx(Link, { href: item.href, passHref: true, children: /* @__PURE__ */ jsx(
10487
+ UnstyledButton,
10488
+ {
10489
+ disabled,
10490
+ mt: "xs",
10491
+ sx: (theme) => ({
10492
+ border: "1px solid white",
10493
+ borderColor: page && page.includes(item.href) ? "#ccc" : "transparent",
10494
+ backgroundColor: "transparent",
10495
+ display: "block",
10496
+ width: "100%",
10497
+ padding: theme.spacing.xs,
10498
+ borderRadius: theme.radius.sm,
10499
+ "&:hover": {
10500
+ backgroundColor: "#f9f9f9"
10501
+ }
10502
+ }),
10503
+ children: /* @__PURE__ */ jsxs(Group, { children: [
10504
+ /* @__PURE__ */ jsx(ThemeIcon, { color: disabled ? "gray" : item.color, variant: "light", children: item.icon }),
10505
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: item.label })
10506
+ ] })
10507
+ }
10508
+ ) }, item.label);
10307
10509
  }
10308
10510
 
10309
10511
  // views/BespokeRenderer.tsx
10310
10512
  init_esm_shims();
10311
- function BespokeRenderer() {
10312
- return /* @__PURE__ */ jsx("div", { children: "Report COMING SOON" });
10513
+ init_store2();
10514
+ function BespokeRenderer(props) {
10515
+ const state = useAppSelector((state2) => state2);
10516
+ return /* @__PURE__ */ jsxs("div", { children: [
10517
+ /* @__PURE__ */ jsx("h1", { children: "Report COMING SOON" }),
10518
+ /* @__PURE__ */ jsx("pre", { children: JSON.stringify(state, null, 2) })
10519
+ ] });
10313
10520
  }
10314
10521
 
10315
10522
  export { Explore_default as BespokeExplore, ExploreModal_default as BespokeExploreModal, LoginButton_default as BespokeLoginBtn, BespokeManager, BespokeRenderer, Report_default as BespokeReport, Search_default as BespokeSearch, UserProvider_default as BespokeUserProvider, withPageRoleAuthRequired as BespokeWithPageRoleAuthRequired, CMS_ROLES, DialogProvider, actions_exports as actions, storeWrapper, useAppDispatch as useBespokeDispatch, useAppSelector as useBespokeSelector, useUser_default as useBespokeUser, useDialog };