@datawheel/bespoke 0.1.17 → 0.1.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +128 -86
- package/dist/server.js +77 -6
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -18,7 +18,7 @@ import { useDispatch, useSelector } from 'react-redux';
|
|
|
18
18
|
import { Stack, Text, Badge, Group, Tooltip, ActionIcon, Center, useMantineTheme, Modal, Button, Flex, Title, Select, MultiSelect, MantineProvider, Divider, Burger, Navbar, ScrollArea, Avatar, Box, AppShell, UnstyledButton, ThemeIcon, Skeleton, Container, TextInput, Loader, LoadingOverlay, Alert, Autocomplete, Menu, Card, Space, Code, SegmentedControl, Textarea, Overlay, Grid, Input, Popover, Checkbox, Radio, Switch, Drawer, Header, Tabs, FileInput, SimpleGrid, Image, Accordion, NumberInput, CopyButton, Col } from '@mantine/core';
|
|
19
19
|
import { dataConcat } from 'd3plus-viz';
|
|
20
20
|
import * as d3plus from 'd3plus-react';
|
|
21
|
-
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';
|
|
21
|
+
import { IconInfoCircle, IconBoxMargin, IconTable, IconMathFunction, IconUsers, IconLogout, IconSearch, IconTrash, IconUserCircle, IconDatabase, IconServer, IconPencil, IconAlertCircle, IconCircleCheck, IconPlayerPlay, IconCirclePlus, IconCircleX, IconFileAnalytics, IconPlus, IconCircleDashed, IconRefreshAlert, 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';
|
|
22
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';
|
|
@@ -57,8 +57,8 @@ var init_esm_shims = __esm({
|
|
|
57
57
|
});
|
|
58
58
|
|
|
59
59
|
// api/http/lib.ts
|
|
60
|
-
function http(
|
|
61
|
-
return
|
|
60
|
+
function http(axios7, config) {
|
|
61
|
+
return axios7.request(config).then((response) => {
|
|
62
62
|
const { status, data } = response;
|
|
63
63
|
return "error" in data ? { ok: false, status, error: data.error } : { ok: true, status, data: data.data };
|
|
64
64
|
}, (err) => {
|
|
@@ -69,25 +69,25 @@ function http(axios6, config) {
|
|
|
69
69
|
return { ok: false, status: 500, error: err.message };
|
|
70
70
|
});
|
|
71
71
|
}
|
|
72
|
-
function httpGET(
|
|
72
|
+
function httpGET(axios7, request, transformParams) {
|
|
73
73
|
const config = typeof request === "string" ? { url: request } : request;
|
|
74
|
-
return (params) => http(
|
|
74
|
+
return (params) => http(axios7, {
|
|
75
75
|
...config,
|
|
76
76
|
method: "GET",
|
|
77
77
|
params: transformParams ? transformParams(params) : params
|
|
78
78
|
});
|
|
79
79
|
}
|
|
80
|
-
function httpPOST(
|
|
80
|
+
function httpPOST(axios7, request, transformPayload) {
|
|
81
81
|
const config = typeof request === "string" ? { url: request } : request;
|
|
82
|
-
return (payload) => http(
|
|
82
|
+
return (payload) => http(axios7, {
|
|
83
83
|
...config,
|
|
84
84
|
method: "POST",
|
|
85
85
|
data: transformPayload ? transformPayload(payload) : payload
|
|
86
86
|
});
|
|
87
87
|
}
|
|
88
|
-
function httpDELETE(
|
|
88
|
+
function httpDELETE(axios7, request, transformPayload) {
|
|
89
89
|
const config = typeof request === "string" ? { url: request } : request;
|
|
90
|
-
return (payload) => http(
|
|
90
|
+
return (payload) => http(axios7, {
|
|
91
91
|
...config,
|
|
92
92
|
method: "DELETE",
|
|
93
93
|
data: transformPayload ? transformPayload(payload) : payload
|
|
@@ -100,8 +100,8 @@ var init_lib = __esm({
|
|
|
100
100
|
});
|
|
101
101
|
|
|
102
102
|
// api/http/image/imageSave.ts
|
|
103
|
-
function httpImageSaveFactory(
|
|
104
|
-
return (params) => http(
|
|
103
|
+
function httpImageSaveFactory(axios7, provider) {
|
|
104
|
+
return (params) => http(axios7, {
|
|
105
105
|
method: "GET",
|
|
106
106
|
url: `search/images/${provider}`,
|
|
107
107
|
params: { prompt: params.prompt, provider }
|
|
@@ -115,8 +115,8 @@ var init_imageSave = __esm({
|
|
|
115
115
|
});
|
|
116
116
|
|
|
117
117
|
// api/http/image/imageSearch.ts
|
|
118
|
-
function httpImageSearchFactory(
|
|
119
|
-
return (params) => http(
|
|
118
|
+
function httpImageSearchFactory(axios7, provider) {
|
|
119
|
+
return (params) => http(axios7, {
|
|
120
120
|
method: "GET",
|
|
121
121
|
url: `search/images/${provider}`,
|
|
122
122
|
params: { prompt: params.prompt, provider }
|
|
@@ -129,56 +129,57 @@ var init_imageSearch = __esm({
|
|
|
129
129
|
}
|
|
130
130
|
});
|
|
131
131
|
function apiFactory(baseURL) {
|
|
132
|
-
const
|
|
132
|
+
const axios7 = axios.create({ baseURL });
|
|
133
133
|
return {
|
|
134
|
-
createBlock: httpPOST(
|
|
135
|
-
createDimension: httpPOST(
|
|
136
|
-
createFormatter: httpPOST(
|
|
137
|
-
createReport: httpPOST(
|
|
138
|
-
createSection: httpPOST(
|
|
139
|
-
createVariant: httpPOST(
|
|
140
|
-
deleteBlock: httpDELETE(
|
|
141
|
-
deleteDimension: httpDELETE(
|
|
142
|
-
deleteFormatter: httpDELETE(
|
|
143
|
-
deleteReport: httpDELETE(
|
|
144
|
-
deleteSection: httpDELETE(
|
|
145
|
-
deleteVariant: httpDELETE(
|
|
146
|
-
readBlock: httpGET(
|
|
147
|
-
readDimension: httpGET(
|
|
148
|
-
readFormatter: httpGET(
|
|
149
|
-
readReport: httpGET(
|
|
150
|
-
readSection: httpGET(
|
|
151
|
-
readVariant: httpGET(
|
|
152
|
-
updateBlock: httpPOST(
|
|
153
|
-
updateDimension: httpPOST(
|
|
154
|
-
updateFormatter: httpPOST(
|
|
155
|
-
updateReport: httpPOST(
|
|
156
|
-
updateSection: httpPOST(
|
|
157
|
-
updateVariant: httpPOST(
|
|
158
|
-
searchReport: httpGET(
|
|
159
|
-
validateVariantSlug: httpGET(
|
|
160
|
-
readMember: httpGET(
|
|
161
|
-
readMemberImage: httpGET(
|
|
134
|
+
createBlock: httpPOST(axios7, "create/block"),
|
|
135
|
+
createDimension: httpPOST(axios7, "create/dimension"),
|
|
136
|
+
createFormatter: httpPOST(axios7, "create/formatter"),
|
|
137
|
+
createReport: httpPOST(axios7, "create/report"),
|
|
138
|
+
createSection: httpPOST(axios7, "create/section"),
|
|
139
|
+
createVariant: httpPOST(axios7, "create/variant"),
|
|
140
|
+
deleteBlock: httpDELETE(axios7, "delete/block", transformDeletePayload),
|
|
141
|
+
deleteDimension: httpDELETE(axios7, "delete/dimension", transformDeletePayload),
|
|
142
|
+
deleteFormatter: httpDELETE(axios7, "delete/formatter", transformDeletePayload),
|
|
143
|
+
deleteReport: httpDELETE(axios7, "delete/report", transformDeletePayload),
|
|
144
|
+
deleteSection: httpDELETE(axios7, "delete/section", transformDeletePayload),
|
|
145
|
+
deleteVariant: httpDELETE(axios7, "delete/variant", transformDeletePayload),
|
|
146
|
+
readBlock: httpGET(axios7, "read/block"),
|
|
147
|
+
readDimension: httpGET(axios7, "read/dimension"),
|
|
148
|
+
readFormatter: httpGET(axios7, "read/formatter"),
|
|
149
|
+
readReport: httpGET(axios7, "read/report"),
|
|
150
|
+
readSection: httpGET(axios7, "read/section"),
|
|
151
|
+
readVariant: httpGET(axios7, "read/variant"),
|
|
152
|
+
updateBlock: httpPOST(axios7, "update/block"),
|
|
153
|
+
updateDimension: httpPOST(axios7, "update/dimension"),
|
|
154
|
+
updateFormatter: httpPOST(axios7, "update/formatter"),
|
|
155
|
+
updateReport: httpPOST(axios7, "update/report"),
|
|
156
|
+
updateSection: httpPOST(axios7, "update/section"),
|
|
157
|
+
updateVariant: httpPOST(axios7, "update/variant"),
|
|
158
|
+
searchReport: httpGET(axios7, "search/reports"),
|
|
159
|
+
validateVariantSlug: httpGET(axios7, "validate/variant"),
|
|
160
|
+
readMember: httpGET(axios7, "read/members", transformReadMembers),
|
|
161
|
+
readMemberImage: httpGET(axios7, {
|
|
162
162
|
url: "member/image.png",
|
|
163
163
|
responseType: "blob"
|
|
164
164
|
}),
|
|
165
|
-
searchMember: httpGET(
|
|
166
|
-
updateMember: httpGET(
|
|
167
|
-
imageLocalSearch: httpImageSearchFactory(
|
|
168
|
-
imageLocalSave: httpImageSaveFactory(
|
|
169
|
-
imageFlickrSearch: httpImageSearchFactory(
|
|
170
|
-
imageFlickrSave: httpImageSaveFactory(
|
|
171
|
-
imageUnsplashSearch: httpImageSearchFactory(
|
|
172
|
-
imageUnsplashSave: httpImageSaveFactory(
|
|
173
|
-
imageUploadSave: httpImageSaveFactory(
|
|
174
|
-
readMetadata: httpGET(
|
|
175
|
-
regenerateSearch: httpPOST(
|
|
176
|
-
urlProxy: httpGET(
|
|
177
|
-
searchRole: httpGET(
|
|
178
|
-
searchUser: httpGET(
|
|
179
|
-
readUser: httpGET(
|
|
180
|
-
updateUser: httpPOST(
|
|
181
|
-
addNewReportToCurrentUser: httpPOST(
|
|
165
|
+
searchMember: httpGET(axios7, "search/members"),
|
|
166
|
+
updateMember: httpGET(axios7, "update/members"),
|
|
167
|
+
imageLocalSearch: httpImageSearchFactory(axios7, "local"),
|
|
168
|
+
imageLocalSave: httpImageSaveFactory(axios7, "local"),
|
|
169
|
+
imageFlickrSearch: httpImageSearchFactory(axios7, "flickr"),
|
|
170
|
+
imageFlickrSave: httpImageSaveFactory(axios7, "flickr"),
|
|
171
|
+
imageUnsplashSearch: httpImageSearchFactory(axios7, "unsplash"),
|
|
172
|
+
imageUnsplashSave: httpImageSaveFactory(axios7, "unsplash"),
|
|
173
|
+
imageUploadSave: httpImageSaveFactory(axios7, "upload"),
|
|
174
|
+
readMetadata: httpGET(axios7, "read/metadata"),
|
|
175
|
+
regenerateSearch: httpPOST(axios7, "search/regenerate"),
|
|
176
|
+
urlProxy: httpGET(axios7, "url/proxy"),
|
|
177
|
+
searchRole: httpGET(axios7, "auth/search/roles"),
|
|
178
|
+
searchUser: httpGET(axios7, "auth/search/users"),
|
|
179
|
+
readUser: httpGET(axios7, "auth/read/user"),
|
|
180
|
+
updateUser: httpPOST(axios7, "auth/update/user"),
|
|
181
|
+
addNewReportToCurrentUser: httpPOST(axios7, "auth/update/me"),
|
|
182
|
+
revalidate: httpGET(axios7, "revalidate/report")
|
|
182
183
|
};
|
|
183
184
|
}
|
|
184
185
|
var transformDeletePayload, transformReadMembers;
|
|
@@ -3067,7 +3068,7 @@ function ExploreTile({ profile, profilePrefix }) {
|
|
|
3067
3068
|
{
|
|
3068
3069
|
src: `/api/cms/member/image.png?member=${m.id}&size=thumb`,
|
|
3069
3070
|
height: 160,
|
|
3070
|
-
alt:
|
|
3071
|
+
alt: m.name
|
|
3071
3072
|
},
|
|
3072
3073
|
m.id
|
|
3073
3074
|
));
|
|
@@ -5948,8 +5949,9 @@ function HeaderLayout(props) {
|
|
|
5948
5949
|
] }) });
|
|
5949
5950
|
}
|
|
5950
5951
|
function CMSHeader(props) {
|
|
5951
|
-
const { report: currentReport } = props;
|
|
5952
|
+
const { report: currentReport, profilePrefix } = props;
|
|
5952
5953
|
const { id } = currentReport;
|
|
5954
|
+
const { newConfirmation } = useDialog();
|
|
5953
5955
|
const location = useManagerLocation();
|
|
5954
5956
|
const dispatch = useAppDispatch();
|
|
5955
5957
|
const resource = useContext(ResourceContext);
|
|
@@ -5995,6 +5997,37 @@ function CMSHeader(props) {
|
|
|
5995
5997
|
});
|
|
5996
5998
|
setPreviewMembers(newPreviews);
|
|
5997
5999
|
};
|
|
6000
|
+
const maybeRevalidate = useCallback(async () => {
|
|
6001
|
+
try {
|
|
6002
|
+
await newConfirmation({
|
|
6003
|
+
title: "Are you sure?",
|
|
6004
|
+
message: "Revalidate action will force to regenerate all the cached instances of this report type.",
|
|
6005
|
+
confirmText: "Revalidate now!"
|
|
6006
|
+
});
|
|
6007
|
+
const revalidateUrl = `/api/cms/revalidate/report?profilePrefix=${profilePrefix}&reportId=${id}`;
|
|
6008
|
+
await axios.get(revalidateUrl).then((response) => {
|
|
6009
|
+
const resp = response.data.data.data;
|
|
6010
|
+
const message = `Revalidated ${resp.revalidated} pages of report ID ${resp.reportId}, like ${resp.samples.join(", ")}.`;
|
|
6011
|
+
showNotification({
|
|
6012
|
+
autoClose: false,
|
|
6013
|
+
color: "green",
|
|
6014
|
+
id: "revalidate-results",
|
|
6015
|
+
message,
|
|
6016
|
+
title: "Revalidate Results"
|
|
6017
|
+
});
|
|
6018
|
+
}).catch((error) => {
|
|
6019
|
+
showNotification({
|
|
6020
|
+
autoClose: false,
|
|
6021
|
+
color: "red",
|
|
6022
|
+
id: "revalidate-error",
|
|
6023
|
+
message: error.message,
|
|
6024
|
+
title: "Revalidate Error"
|
|
6025
|
+
});
|
|
6026
|
+
});
|
|
6027
|
+
} catch {
|
|
6028
|
+
console.debug("Revalidate edition.");
|
|
6029
|
+
}
|
|
6030
|
+
}, []);
|
|
5998
6031
|
useEffect(() => {
|
|
5999
6032
|
setPreviewMembers([]);
|
|
6000
6033
|
}, [dimensions]);
|
|
@@ -6059,20 +6092,23 @@ function CMSHeader(props) {
|
|
|
6059
6092
|
}
|
|
6060
6093
|
)
|
|
6061
6094
|
] }),
|
|
6062
|
-
right: /* @__PURE__ */ jsxs(
|
|
6063
|
-
/* @__PURE__ */ jsx(
|
|
6064
|
-
/* @__PURE__ */
|
|
6065
|
-
|
|
6066
|
-
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
|
|
6070
|
-
|
|
6071
|
-
|
|
6072
|
-
|
|
6073
|
-
|
|
6074
|
-
|
|
6075
|
-
|
|
6095
|
+
right: /* @__PURE__ */ jsxs(Group, { children: [
|
|
6096
|
+
/* @__PURE__ */ jsx(ActionIcon, { onClick: maybeRevalidate, color: "blue", variant: "filled", children: /* @__PURE__ */ jsx(IconRefreshAlert, { size: 20 }) }),
|
|
6097
|
+
/* @__PURE__ */ jsxs(ActionIcon, { color: "blue", variant: "filled", children: [
|
|
6098
|
+
/* @__PURE__ */ jsx(IconSettings, { onClick: handlers.open, size: 20 }),
|
|
6099
|
+
/* @__PURE__ */ jsx(
|
|
6100
|
+
Drawer,
|
|
6101
|
+
{
|
|
6102
|
+
opened,
|
|
6103
|
+
onClose: handlers.close,
|
|
6104
|
+
title: /* @__PURE__ */ jsx(IconTitle, { icon: /* @__PURE__ */ jsx(IconFileAnalytics, { size: 24 }), children: `Editing Report: ${currentReport ? currentReport.name : ""}` }),
|
|
6105
|
+
size: "50%",
|
|
6106
|
+
padding: "xl",
|
|
6107
|
+
position: "right",
|
|
6108
|
+
children: /* @__PURE__ */ jsx(ReportEditor, { id, onClose: handlers.close })
|
|
6109
|
+
}
|
|
6110
|
+
)
|
|
6111
|
+
] })
|
|
6076
6112
|
] })
|
|
6077
6113
|
}
|
|
6078
6114
|
);
|
|
@@ -8348,7 +8384,8 @@ init_ordering();
|
|
|
8348
8384
|
init_store2();
|
|
8349
8385
|
init_actions();
|
|
8350
8386
|
function BuilderEditor(props) {
|
|
8351
|
-
const
|
|
8387
|
+
const { profilePrefix, id } = props;
|
|
8388
|
+
const reportRef = useReportRef(id);
|
|
8352
8389
|
return useMemo(() => {
|
|
8353
8390
|
if (reportRef.isError) {
|
|
8354
8391
|
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 }) });
|
|
@@ -8361,13 +8398,14 @@ function BuilderEditor(props) {
|
|
|
8361
8398
|
{
|
|
8362
8399
|
report: reportRef.data,
|
|
8363
8400
|
locale: props.locale,
|
|
8364
|
-
isLoading: reportRef.isFetching
|
|
8401
|
+
isLoading: reportRef.isFetching,
|
|
8402
|
+
profilePrefix
|
|
8365
8403
|
}
|
|
8366
8404
|
);
|
|
8367
8405
|
}, [reportRef.status]);
|
|
8368
8406
|
}
|
|
8369
8407
|
function InteractiveReport(props) {
|
|
8370
|
-
const { report, isLoading } = props;
|
|
8408
|
+
const { report, isLoading, profilePrefix } = props;
|
|
8371
8409
|
const theme = useMantineTheme();
|
|
8372
8410
|
const dispatch = useAppDispatch();
|
|
8373
8411
|
const resource = useContext(ResourceContext);
|
|
@@ -8448,7 +8486,7 @@ function InteractiveReport(props) {
|
|
|
8448
8486
|
}
|
|
8449
8487
|
), [sectionOrder, activeSection, maybeActivate]);
|
|
8450
8488
|
return /* @__PURE__ */ jsxs(Stack, { styles: { backgroundColor: theme.colors.gray[2] }, children: [
|
|
8451
|
-
/* @__PURE__ */ jsx(CMSHeader, { report }),
|
|
8489
|
+
/* @__PURE__ */ jsx(CMSHeader, { report, profilePrefix }),
|
|
8452
8490
|
/* @__PURE__ */ jsx(LoadingOverlay, { visible: isLoading }),
|
|
8453
8491
|
report.sections.length === 0 && /* @__PURE__ */ jsx(CreateSectionButton, { index: 0, report }),
|
|
8454
8492
|
/* @__PURE__ */ jsx(DragDropContext, { onDragEnd, children: /* @__PURE__ */ jsx(Droppable, { droppableId: "sections", children: droppableChild }) })
|
|
@@ -10693,7 +10731,8 @@ function BespokeManager(options) {
|
|
|
10693
10731
|
const {
|
|
10694
10732
|
title = "Bespoke CMS",
|
|
10695
10733
|
pathSegment = "bespoke",
|
|
10696
|
-
locale = localeDefault3
|
|
10734
|
+
locale = localeDefault3,
|
|
10735
|
+
profilePrefix
|
|
10697
10736
|
} = options;
|
|
10698
10737
|
const notifications = {
|
|
10699
10738
|
position: "bottom-center",
|
|
@@ -10707,12 +10746,12 @@ function BespokeManager(options) {
|
|
|
10707
10746
|
function BespokeManagerPage() {
|
|
10708
10747
|
return /* @__PURE__ */ jsxs(ResourceProvider, { pathSegment, children: [
|
|
10709
10748
|
/* @__PURE__ */ jsx(Head, { children: /* @__PURE__ */ jsx("title", { children: title }) }),
|
|
10710
|
-
/* @__PURE__ */ jsx(MantineProvider, { children: /* @__PURE__ */ jsx(NotificationsProvider, { ...notifications, children: /* @__PURE__ */ jsx(DialogProvider, { children: /* @__PURE__ */ jsx(BespokeManagerShell, { locale }) }) }) })
|
|
10749
|
+
/* @__PURE__ */ jsx(MantineProvider, { children: /* @__PURE__ */ jsx(NotificationsProvider, { ...notifications, children: /* @__PURE__ */ jsx(DialogProvider, { children: /* @__PURE__ */ jsx(BespokeManagerShell, { locale, profilePrefix }) }) }) })
|
|
10711
10750
|
] });
|
|
10712
10751
|
}
|
|
10713
10752
|
}
|
|
10714
10753
|
function BespokeManagerShell(props) {
|
|
10715
|
-
const { locale } = props;
|
|
10754
|
+
const { locale, profilePrefix } = props;
|
|
10716
10755
|
const [opened, { toggle: toggleOpened }] = useDisclosure(true);
|
|
10717
10756
|
const { user, error, isLoading } = useUser();
|
|
10718
10757
|
const location = useManagerLocation();
|
|
@@ -10828,7 +10867,7 @@ function BespokeManagerShell(props) {
|
|
|
10828
10867
|
if (location.page === "welcome") {
|
|
10829
10868
|
return /* @__PURE__ */ jsx(HelloView, {});
|
|
10830
10869
|
}
|
|
10831
|
-
if (user && Array.isArray(user.bespoke_roles) && user.bespoke_roles.includes(item
|
|
10870
|
+
if (user && Array.isArray(user.bespoke_roles) && user.bespoke_roles.includes(item?.roleRequired)) {
|
|
10832
10871
|
if (location.page === "metadata") {
|
|
10833
10872
|
return /* @__PURE__ */ jsx(MetadataEditor, {});
|
|
10834
10873
|
}
|
|
@@ -10838,7 +10877,7 @@ function BespokeManagerShell(props) {
|
|
|
10838
10877
|
if (location.page === "reports") {
|
|
10839
10878
|
if (location.params.length > 0) {
|
|
10840
10879
|
const reportId = Number.parseInt(location.params[0]);
|
|
10841
|
-
return /* @__PURE__ */ jsx(BuilderEditor, { id: reportId, locale });
|
|
10880
|
+
return /* @__PURE__ */ jsx(BuilderEditor, { id: reportId, locale, profilePrefix });
|
|
10842
10881
|
}
|
|
10843
10882
|
return /* @__PURE__ */ jsx(ReportPicker, {});
|
|
10844
10883
|
}
|
|
@@ -10923,11 +10962,14 @@ function useInitialState(pathSegmentsKey) {
|
|
|
10923
10962
|
}, []);
|
|
10924
10963
|
return loaded;
|
|
10925
10964
|
}
|
|
10926
|
-
function BespokeRenderer({ pathSegmentsKey = "bespoke" }) {
|
|
10965
|
+
function BespokeRenderer({ pathSegmentsKey = "bespoke", buildTime }) {
|
|
10927
10966
|
const stateLoaded = useInitialState(pathSegmentsKey);
|
|
10928
10967
|
if (!stateLoaded)
|
|
10929
10968
|
return /* @__PURE__ */ jsx("div", { children: "Loading..." });
|
|
10930
|
-
return /* @__PURE__ */
|
|
10969
|
+
return /* @__PURE__ */ jsxs(ResourceProvider, { pathSegment: "bespoke", children: [
|
|
10970
|
+
/* @__PURE__ */ jsx(Report_default, {}),
|
|
10971
|
+
/* @__PURE__ */ jsx("small", { children: buildTime })
|
|
10972
|
+
] });
|
|
10931
10973
|
}
|
|
10932
10974
|
|
|
10933
10975
|
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 };
|
package/dist/server.js
CHANGED
|
@@ -22,6 +22,7 @@ import fs from 'fs';
|
|
|
22
22
|
import auth0 from 'auth0';
|
|
23
23
|
import NextCors from 'nextjs-cors';
|
|
24
24
|
import formidable from 'formidable';
|
|
25
|
+
import glob from 'fast-glob';
|
|
25
26
|
import { schema, normalize } from 'normalizr';
|
|
26
27
|
import { createSlice, configureStore } from '@reduxjs/toolkit';
|
|
27
28
|
import { HYDRATE, createWrapper } from 'next-redux-wrapper';
|
|
@@ -3366,7 +3367,7 @@ function dbReadMetadataFactory(db) {
|
|
|
3366
3367
|
|
|
3367
3368
|
// api/db/regenerateSearch.ts
|
|
3368
3369
|
function dbRegenerateSearchFactory(db) {
|
|
3369
|
-
return async (
|
|
3370
|
+
return async () => {
|
|
3370
3371
|
await search_default2(db, true);
|
|
3371
3372
|
return { error: false };
|
|
3372
3373
|
};
|
|
@@ -3481,6 +3482,26 @@ function dbUrlProxyFactory() {
|
|
|
3481
3482
|
}
|
|
3482
3483
|
};
|
|
3483
3484
|
}
|
|
3485
|
+
|
|
3486
|
+
// api/db/revalidate.ts
|
|
3487
|
+
function dbRevalidateFactory(db) {
|
|
3488
|
+
return async (request) => {
|
|
3489
|
+
const { reportId, qty, samples } = request;
|
|
3490
|
+
try {
|
|
3491
|
+
return {
|
|
3492
|
+
ok: true,
|
|
3493
|
+
status: 200,
|
|
3494
|
+
data: {
|
|
3495
|
+
reportId,
|
|
3496
|
+
revalidated: qty,
|
|
3497
|
+
samples
|
|
3498
|
+
}
|
|
3499
|
+
};
|
|
3500
|
+
} catch (err) {
|
|
3501
|
+
throw new BackendError(err.response?.status || 500, err.message);
|
|
3502
|
+
}
|
|
3503
|
+
};
|
|
3504
|
+
}
|
|
3484
3505
|
var auth0ConfigObject = {
|
|
3485
3506
|
domain: new URL(process.env.AUTH0_ISSUER_BASE_URL || "").host,
|
|
3486
3507
|
clientId: process.env.AUTH0_CLIENT_ID,
|
|
@@ -3620,7 +3641,8 @@ function apiFactory(dbModels) {
|
|
|
3620
3641
|
searchUser: resultWrapper(dbSearchUser()),
|
|
3621
3642
|
readUser: resultWrapper(dbReadUser()),
|
|
3622
3643
|
updateUser: resultWrapper(dbUpdateUser()),
|
|
3623
|
-
addNewReportToCurrentUser: resultWrapper(dbAddNewReportToCurrentUser())
|
|
3644
|
+
addNewReportToCurrentUser: resultWrapper(dbAddNewReportToCurrentUser()),
|
|
3645
|
+
revalidate: resultWrapper(dbRevalidateFactory())
|
|
3624
3646
|
};
|
|
3625
3647
|
}
|
|
3626
3648
|
async function parseBody(req) {
|
|
@@ -3751,6 +3773,48 @@ function endpointUrlProxyFactory(operations) {
|
|
|
3751
3773
|
});
|
|
3752
3774
|
});
|
|
3753
3775
|
}
|
|
3776
|
+
function endpointRevalidateFactory(operations) {
|
|
3777
|
+
const { readMetadata: readMetadata2, revalidate } = operations;
|
|
3778
|
+
return endpoint("GET", "revalidate/report", async (req, res) => {
|
|
3779
|
+
const { reportId, profilePrefix } = req.query;
|
|
3780
|
+
if (!reportId || !profilePrefix) {
|
|
3781
|
+
throw new BackendError(400, "Missing URL parameter in revalidate factory: reportId or profilePrefix");
|
|
3782
|
+
}
|
|
3783
|
+
try {
|
|
3784
|
+
const reportIdInt = parseInt(`${reportId}`, 10);
|
|
3785
|
+
const profilePrefixClean = `${profilePrefix}`.split("/").filter((p) => p !== "").join("/");
|
|
3786
|
+
const initialPathSelector = [
|
|
3787
|
+
".next",
|
|
3788
|
+
"server",
|
|
3789
|
+
"pages"
|
|
3790
|
+
];
|
|
3791
|
+
const pathSelector = [
|
|
3792
|
+
...initialPathSelector,
|
|
3793
|
+
profilePrefixClean
|
|
3794
|
+
];
|
|
3795
|
+
const paths = [];
|
|
3796
|
+
const report = await readMetadata2({}).then((metadata) => metadata.ok ? metadata.data.data.find((r) => r.id === reportIdInt) : []);
|
|
3797
|
+
if (report && report.mode === REPORT_MODES.UNILATERAL) {
|
|
3798
|
+
report.dimensions.forEach((d) => {
|
|
3799
|
+
d.variants.forEach((v) => {
|
|
3800
|
+
paths.push([
|
|
3801
|
+
...pathSelector,
|
|
3802
|
+
v.slug,
|
|
3803
|
+
"*.html"
|
|
3804
|
+
].join("/"));
|
|
3805
|
+
});
|
|
3806
|
+
});
|
|
3807
|
+
}
|
|
3808
|
+
const files = await glob(paths);
|
|
3809
|
+
const urls = files.map((file) => `${file.replace(initialPathSelector.join("/"), "").replace(".html", "")}`);
|
|
3810
|
+
await Promise.all(urls.map((path) => res.revalidate(path)));
|
|
3811
|
+
return revalidate({ reportId: reportIdInt, qty: urls.length, samples: urls.slice(0, 5) });
|
|
3812
|
+
} catch (err) {
|
|
3813
|
+
console.log(err);
|
|
3814
|
+
throw new BackendError(500, "Error revalidating");
|
|
3815
|
+
}
|
|
3816
|
+
});
|
|
3817
|
+
}
|
|
3754
3818
|
|
|
3755
3819
|
// api/endpoints/users/auth0.ts
|
|
3756
3820
|
function endpointGetRolesFactory(operations) {
|
|
@@ -3874,7 +3938,8 @@ function getEndpointMap(db) {
|
|
|
3874
3938
|
endpointGetUsersFactory(api),
|
|
3875
3939
|
endpointGetUserDataFactory(api),
|
|
3876
3940
|
endpointUpdateUserDataFactory(api),
|
|
3877
|
-
endpointAddNewReportToCurrentUserFactory(api)
|
|
3941
|
+
endpointAddNewReportToCurrentUserFactory(api),
|
|
3942
|
+
endpointRevalidateFactory(api)
|
|
3878
3943
|
].map(({ handler, method, path, roleRequired }) => [endpointKey(method, path), { handler, roleRequired }]));
|
|
3879
3944
|
}
|
|
3880
3945
|
var endpointMap = getDB().then(getEndpointMap);
|
|
@@ -4074,7 +4139,8 @@ function apiFactory2(baseURL) {
|
|
|
4074
4139
|
searchUser: httpGET(axios6, "auth/search/users"),
|
|
4075
4140
|
readUser: httpGET(axios6, "auth/read/user"),
|
|
4076
4141
|
updateUser: httpPOST(axios6, "auth/update/user"),
|
|
4077
|
-
addNewReportToCurrentUser: httpPOST(axios6, "auth/update/me")
|
|
4142
|
+
addNewReportToCurrentUser: httpPOST(axios6, "auth/update/me"),
|
|
4143
|
+
revalidate: httpGET(axios6, "revalidate/report")
|
|
4078
4144
|
};
|
|
4079
4145
|
}
|
|
4080
4146
|
var transformDeletePayload = (id) => ({ id });
|
|
@@ -5425,6 +5491,7 @@ function BespokeRendererStaticProps(options) {
|
|
|
5425
5491
|
const { dispatch } = store;
|
|
5426
5492
|
return async (context) => {
|
|
5427
5493
|
await dispatch(useDatabaseApi);
|
|
5494
|
+
const buildTime = (/* @__PURE__ */ new Date()).toISOString();
|
|
5428
5495
|
console.log("StaticProps", context);
|
|
5429
5496
|
const {
|
|
5430
5497
|
locale = localeDefault7,
|
|
@@ -5438,7 +5505,9 @@ function BespokeRendererStaticProps(options) {
|
|
|
5438
5505
|
dispatch(readEntity("report", { include: true }))
|
|
5439
5506
|
]);
|
|
5440
5507
|
return {
|
|
5441
|
-
props: {
|
|
5508
|
+
props: {
|
|
5509
|
+
buildTime
|
|
5510
|
+
}
|
|
5442
5511
|
};
|
|
5443
5512
|
}
|
|
5444
5513
|
const members = await dispatch(
|
|
@@ -5468,7 +5537,9 @@ function BespokeRendererStaticProps(options) {
|
|
|
5468
5537
|
})
|
|
5469
5538
|
));
|
|
5470
5539
|
return {
|
|
5471
|
-
props: {
|
|
5540
|
+
props: {
|
|
5541
|
+
buildTime
|
|
5542
|
+
}
|
|
5472
5543
|
};
|
|
5473
5544
|
};
|
|
5474
5545
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datawheel/bespoke",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.18",
|
|
4
4
|
"description": "Content management system for creating automated data reports",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -70,6 +70,7 @@
|
|
|
70
70
|
"d3plus-react": "^1.1.1",
|
|
71
71
|
"d3plus-text": "^1.0.2",
|
|
72
72
|
"d3plus-viz": "^1.2.2",
|
|
73
|
+
"fast-glob": "^3.2.12",
|
|
73
74
|
"file-loader": "^6.2.0",
|
|
74
75
|
"file-saver": "^1.3.3",
|
|
75
76
|
"flickr-sdk": "^6.0.0",
|