@datawheel/bespoke 0.1.29 → 0.1.31

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 CHANGED
@@ -1,5 +1,5 @@
1
1
  import axios from 'axios';
2
- import yn3 from 'yn';
2
+ import yn4 from 'yn';
3
3
  import * as d3Array from 'd3-array';
4
4
  import * as d3Collection from 'd3-collection';
5
5
  import * as d3Format from 'd3-format';
@@ -16,11 +16,11 @@ import { Notifications, notifications } from '@mantine/notifications';
16
16
  import React, { forwardRef, useMemo, useState, useCallback, useContext, useEffect, createContext, useRef, Fragment as Fragment$1, createElement } from 'react';
17
17
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
18
18
  import { useDispatch, useSelector } from 'react-redux';
19
- import { Stack, Text, Badge, Group, useMantineTheme, Flex, packSx, Tooltip, ActionIcon, Center, Modal, Button, SegmentedControl, Select, MultiSelect, Title, Box, List, Menu, Anchor, MantineProvider, Divider, Burger, Navbar, ScrollArea, Avatar, AppShell, UnstyledButton, ThemeIcon, LoadingOverlay, Skeleton, Container, TextInput, Loader, Alert, Collapse, Card, Space, Code, Textarea, rem, Paper, Grid, Input, Popover, Checkbox, Radio, Switch, Drawer, Overlay, SimpleGrid, Autocomplete, Tabs, Header, px, Image, FileInput, Accordion, HoverCard, CopyButton, NumberInput, Col } from '@mantine/core';
19
+ import { Stack, Text, Badge, Group, useMantineTheme, Flex, packSx, Tooltip, ActionIcon, Center, Modal, Button, SegmentedControl, Select, MultiSelect, Title, TextInput, Switch, Box, List, Menu, Anchor, MantineProvider, Divider, Burger, Navbar, ScrollArea, Avatar, AppShell, UnstyledButton, ThemeIcon, LoadingOverlay, Skeleton, Container, Loader, Alert, Collapse, Card, Space, Code, Textarea, rem, Paper, Grid, Input, Popover, Checkbox, Radio, Drawer, Overlay, SimpleGrid, Autocomplete, Tabs, Header, px, Image, FileInput, Accordion, HoverCard, CopyButton, NumberInput, Col } from '@mantine/core';
20
20
  import { dataConcat } from 'd3plus-viz';
21
21
  import * as d3plus from 'd3plus-react';
22
22
  import Router, { useRouter } from 'next/router';
23
- import { IconInfoCircle, IconSearch, IconAlignLeft, IconAlignCenter, IconAlignRight, IconBoxMargin, IconTable, IconMathFunction, IconUsers, IconLogout, IconTrash, IconUserCircle, IconEdit, IconDatabase, IconServer, IconPencil, IconAlertCircle, IconCircleCheck, IconPlayerPlay, IconAlarmFilled, IconBox, IconLink, IconCircleX, IconFlag, IconCirclePlus, IconFileAnalytics, IconPlus, IconX, IconChevronDown, IconCamera, IconShare, IconCircleDashed, IconListSearch, IconExternalLink, IconSettings, IconFileOff, IconFilesOff, IconHierarchy3, IconMenu, IconRefresh, IconPolaroid, IconCircleMinus, IconEyeOff, IconChevronLeft, IconChevronRight, IconLogin, IconWorld, IconLock, IconVariable, IconArrowRightCircle, IconDownload, IconTemplate, IconChartBar, IconCode, IconUpload, IconCodePlus, IconClipboardCheck, IconClipboardCopy, IconPalette, IconEye, IconMinimize, IconMaximize, IconRss, IconGlobe } from '@tabler/icons-react';
23
+ import { IconInfoCircle, IconRefresh, IconSearch, IconAlignLeft, IconAlignCenter, IconAlignRight, IconBoxMargin, IconTable, IconMathFunction, IconUsers, IconLogout, IconTrash, IconUserCircle, IconEdit, IconDatabase, IconServer, IconPencil, IconAlertCircle, IconCircleCheck, IconPlayerPlay, IconAlarmFilled, IconBox, IconLink, IconCircleX, IconFlag, IconCirclePlus, IconFileAnalytics, IconPlus, IconX, IconChevronDown, IconCamera, IconShare, IconCircleDashed, IconListSearch, IconExternalLink, IconSettings, IconFileOff, IconFilesOff, IconHierarchy3, IconMenu, IconPolaroid, IconCircleMinus, IconEyeOff, IconChevronLeft, IconChevronRight, IconLogin, IconWorld, IconLock, IconVariable, IconArrowRightCircle, IconDownload, IconTemplate, IconChartBar, IconCode, IconUpload, IconCodePlus, IconClipboardCheck, IconClipboardCopy, IconPalette, IconEye, IconMinimize, IconMaximize, IconRss, IconGlobe } from '@tabler/icons-react';
24
24
  import { useMediaQuery, useDisclosure, useDebouncedValue, useHotkeys, useFullscreen, getHotkeyHandler } from '@mantine/hooks';
25
25
  import dynamic from 'next/dynamic';
26
26
  import Link from 'next/link';
@@ -354,8 +354,9 @@ var init_cms = __esm({
354
354
  STAT: "stat",
355
355
  SUBTITLE: "subtitle",
356
356
  TITLE: "title",
357
- NAV: "nav"
357
+ NAV: "nav",
358
358
  // todo1.0, how to put custom blocks in here?
359
+ RESET_BUTTON: "reset_button"
359
360
  };
360
361
  BLOCK_LOGIC_TYPES = {
361
362
  GENERATOR: "generator",
@@ -472,7 +473,7 @@ var getLogging_default;
472
473
  var init_getLogging = __esm({
473
474
  "libs/configs/getLogging.ts"() {
474
475
  init_esm_shims();
475
- getLogging_default = (env = process.env) => yn3(env.REPORTS_LOGGING);
476
+ getLogging_default = (env = process.env) => yn4(env.REPORTS_LOGGING);
476
477
  }
477
478
  });
478
479
 
@@ -740,7 +741,7 @@ var init_mortarEval = __esm({
740
741
  init_esm_shims();
741
742
  init_block();
742
743
  init_libs();
743
- verbose = yn3(process.env.REPORTS_LOGGING);
744
+ verbose = yn4(process.env.REPORTS_LOGGING);
744
745
  mortarEval_default = mortarEval;
745
746
  }
746
747
  });
@@ -969,7 +970,7 @@ function getRootBlocksForSection(sid, blocks) {
969
970
  blockList.filter((block) => block.section_id === sid && // leave blocks belonging to this section
970
971
  // that don't depend on any other blocks OR
971
972
  (block.inputs.length === 0 || // that depend only on blocks from other sections
972
- block.inputs.every((id) => nonNativeBlocks.includes(id)))).map((block) => [block.id, block])
973
+ block.inputs.some((id) => nonNativeBlocks.includes(id)))).map((block) => [block.id, block])
973
974
  // then convert them to entries
974
975
  );
975
976
  }
@@ -1095,14 +1096,7 @@ async function runSingleBlock(block, formatterFunctions, blockContext, readMembe
1095
1096
  return {
1096
1097
  outputVariables: {},
1097
1098
  renderVariables: {},
1098
- status: {
1099
- api: null,
1100
- duration: null,
1101
- resp: null,
1102
- log: [],
1103
- error: null,
1104
- allowed: false
1105
- }
1099
+ status: { allowed: false }
1106
1100
  };
1107
1101
  }
1108
1102
  if (unswappedAPI) {
@@ -1133,9 +1127,6 @@ async function runSingleBlock(block, formatterFunctions, blockContext, readMembe
1133
1127
  outputVariables: selectorQueryToVariable_default(block.id, query, config),
1134
1128
  renderVariables: config,
1135
1129
  status: {
1136
- api: null,
1137
- duration: null,
1138
- resp: null,
1139
1130
  log: log2,
1140
1131
  error: error2,
1141
1132
  allowed
@@ -1148,11 +1139,8 @@ async function runSingleBlock(block, formatterFunctions, blockContext, readMembe
1148
1139
  // todo1.0 this will have to be materialized click-variables
1149
1140
  renderVariables: block.contentByLocale.logic.content,
1150
1141
  status: {
1151
- api: null,
1152
- duration: null,
1153
- resp: null,
1154
1142
  log: [],
1155
- error: null,
1143
+ // todo: see if we can remove this safely
1156
1144
  allowed
1157
1145
  }
1158
1146
  };
@@ -1189,7 +1177,7 @@ async function runSingleBlock(block, formatterFunctions, blockContext, readMembe
1189
1177
  }
1190
1178
  };
1191
1179
  }
1192
- var verbose2, ORIGIN, swapAPI, urlProxy, getDependencies, isBlockAllowed, runConsumersV2, getDurationColor, getSizeColor;
1180
+ var verbose2, debug, ORIGIN, swapAPI, urlProxy, getDependencies, isBlockAllowed, runConsumersV2, getDurationColor, getSizeColor;
1193
1181
  var init_runConsumers = __esm({
1194
1182
  "libs/blocks/runConsumers.ts"() {
1195
1183
  init_esm_shims();
@@ -1205,6 +1193,7 @@ var init_runConsumers = __esm({
1205
1193
  init_getRootBlocksForSection();
1206
1194
  init_arrayUtils();
1207
1195
  verbose2 = getLogging_default();
1196
+ debug = yn4(process.env.NEXT_PUBLIC_REPORTS_DEBUG);
1208
1197
  ORIGIN = process.env.REPORTS_ORIGIN || "";
1209
1198
  axios.interceptors.request.use((config) => ({
1210
1199
  ...config,
@@ -1229,17 +1218,19 @@ var init_runConsumers = __esm({
1229
1218
  if (rootBlock.inputs.length && crawlUp) {
1230
1219
  rootBlock.inputs.forEach((iid) => {
1231
1220
  const rel = `${iid}-${bid}`;
1232
- if (!acc.includes(rel))
1221
+ if (!acc.includes(rel)) {
1233
1222
  acc.push(rel);
1223
+ }
1234
1224
  rootBlock.inputs.forEach((iid2) => getDependencies(iid2, blocks, acc, crawlUp, false, withinSection, visited));
1235
1225
  });
1236
1226
  }
1237
1227
  if (rootBlock.consumers.length && crawlDown) {
1238
1228
  rootBlock.consumers.forEach((cid) => {
1239
1229
  const rel = `${bid}-${cid}`;
1240
- if (!acc.includes(rel) && (blocks[cid].section_id === blocks[bid].section_id || !withinSection))
1230
+ if (!acc.includes(rel) && (blocks[cid].section_id === blocks[bid].section_id || !withinSection)) {
1241
1231
  acc.push(rel);
1242
- rootBlock.consumers.filter((cid2) => blocks[cid2].section_id === blocks[bid].section_id || !withinSection).forEach((cid2) => getDependencies(cid2, blocks, acc, crawlUp, crawlDown, withinSection, visited));
1232
+ }
1233
+ rootBlock.consumers.filter((cid2) => blocks[cid2].section_id === blocks[bid].section_id || !withinSection).forEach((cid2) => getDependencies(cid2, blocks, acc, false, crawlDown, withinSection, visited));
1243
1234
  });
1244
1235
  }
1245
1236
  return acc;
@@ -1272,16 +1263,31 @@ var init_runConsumers = __esm({
1272
1263
  const statusById = { ...initialState4.status ?? {} };
1273
1264
  const parsedBlockContext = parseBlockContext(blockContext);
1274
1265
  const attributes = parsedBlockContext.variables;
1275
- const rootBlocks = bid ? { [bid]: blocks[bid] } : sections.reduce((rootBlocks2, { id }) => ({ ...rootBlocks2, ...getRootBlocksForSection_default(id, blocks) }), {});
1266
+ const rootBlocks = bid ? { [bid]: blocks[bid] } : (sections ?? []).reduce((rootBlocks2, { id }) => ({ ...rootBlocks2, ...getRootBlocksForSection_default(id, blocks) }), {});
1267
+ if (debug)
1268
+ console.log("%crunConsumers: running root blocks", "color:purple", Object.keys(rootBlocks));
1276
1269
  const withinSection = mode === "section";
1277
1270
  const blockDeps = Object.keys(rootBlocks).reduce((deps, id) => {
1271
+ const start = /* @__PURE__ */ new Date();
1278
1272
  const dependencies = getDependencies(Number(id), blocks, [], !bid, true, withinSection).map((rel) => rel.split("-"));
1273
+ const end = /* @__PURE__ */ new Date();
1274
+ const elapsedTime = (end.getTime() - start.getTime()) / 1e3;
1275
+ if (debug)
1276
+ console.log(
1277
+ `%cResolved dependencies for ${id} (${elapsedTime.toFixed(2)}s)`,
1278
+ "color:blue"
1279
+ );
1279
1280
  return [...deps, ...dependencies];
1280
1281
  }, []);
1282
+ const startToposort = /* @__PURE__ */ new Date();
1281
1283
  const orderedDAG = Object.keys(rootBlocks).reduce(
1282
1284
  (orderedDAG2, bid2) => orderedDAG2.includes(bid2) ? [...orderedDAG2] : [bid2, ...orderedDAG2],
1283
1285
  toposort(blockDeps)
1284
1286
  );
1287
+ const endToposort = /* @__PURE__ */ new Date();
1288
+ const toposortTime = (endToposort.getTime() - startToposort.getTime()) / 1e3;
1289
+ if (debug)
1290
+ console.log(`%cResolved DAG (${toposortTime.toFixed(2)}s): `, "color:green", orderedDAG);
1285
1291
  async function runTasksInParallel(executionOrder, blocks2) {
1286
1292
  const runningBlocks = /* @__PURE__ */ new Map();
1287
1293
  for (const bid2 of executionOrder) {
@@ -1289,22 +1295,21 @@ var init_runConsumers = __esm({
1289
1295
  const dependenciesDone = Promise.all(
1290
1296
  block.inputs.filter((iid) => executionOrder.includes(String(iid))).map((iid) => runningBlocks.get(Number(iid)))
1291
1297
  );
1292
- const runningTask = dependenciesDone.then(() => {
1298
+ const runningTask = dependenciesDone.then(async () => {
1293
1299
  const variables = block.inputs.reduce((acc, d) => ({ ...acc, ...variablesById[d] }), attributes);
1294
- const inputNotAllowed = block.inputs.find((iid) => !statusById[iid].allowed || statusById[iid].hiddenByCascade);
1300
+ const inputNotAllowed = block.inputs.find(
1301
+ (iid) => !statusById[iid].allowed || statusById[iid].hiddenByCascade
1302
+ );
1295
1303
  if (inputNotAllowed) {
1296
1304
  statusById[bid2] = {
1297
- api: null,
1298
- duration: null,
1299
- resp: null,
1300
1305
  log: [],
1301
- error: null,
1302
1306
  allowed: false,
1303
1307
  hiddenByCascade: statusById[inputNotAllowed].hiddenByCascade || inputNotAllowed
1304
1308
  };
1305
1309
  return;
1306
1310
  }
1307
- return runSingleBlock(
1311
+ const startBlock = /* @__PURE__ */ new Date();
1312
+ const blockResult = await runSingleBlock(
1308
1313
  block,
1309
1314
  formatterFunctions,
1310
1315
  {
@@ -1316,12 +1321,25 @@ var init_runConsumers = __esm({
1316
1321
  variablesById[bid2] = outputVariables;
1317
1322
  statusById[bid2] = status;
1318
1323
  });
1324
+ const endBlock = /* @__PURE__ */ new Date();
1325
+ const blockTime = (endBlock.getTime() - startBlock.getTime()) / 1e3;
1326
+ if (debug)
1327
+ console.log(
1328
+ `%cBlock ${block.id} resolved in ${blockTime.toFixed(3)}s`,
1329
+ blockTime > 500 ? "color:red" : "color:green"
1330
+ );
1331
+ return blockResult;
1319
1332
  });
1320
1333
  runningBlocks.set(Number(bid2), runningTask);
1321
1334
  }
1322
1335
  await Promise.all(Array.from(runningBlocks.values()));
1323
1336
  }
1337
+ const startVariables = /* @__PURE__ */ new Date();
1324
1338
  await runTasksInParallel(orderedDAG, blocks);
1339
+ const endVariables = /* @__PURE__ */ new Date();
1340
+ const variablesTime = (endVariables.getTime() - startVariables.getTime()) / 1e3;
1341
+ if (debug)
1342
+ console.log(`%cResolved Variables (${variablesTime.toFixed(2)}s): `, "color:green");
1325
1343
  return {
1326
1344
  variables: { ...initialState4.variables ?? {}, ...variablesById },
1327
1345
  status: { ...initialState4.status ?? {}, ...statusById }
@@ -2889,6 +2907,7 @@ function Viz(config) {
2889
2907
  const blockContext = { variables };
2890
2908
  const router = useRouter();
2891
2909
  const { sectionVariables, setSectionVariables, resetSectionVariables } = useSectionVariables(block.section_id);
2910
+ const sectionVariablesStr = JSON.stringify(sectionVariables);
2892
2911
  const vizProps = useMemo(() => {
2893
2912
  if (!content?.logic)
2894
2913
  return { error: "Add a Configuration" };
@@ -2902,7 +2921,7 @@ function Viz(config) {
2902
2921
  }
2903
2922
  };
2904
2923
  return d3plusPropify_default(transpiledLogic, formatterFunctions, variables, locale, block.id, {}, globals);
2905
- }, [block, active, variables, sectionVariables]);
2924
+ }, [block, active, variables, sectionVariablesStr]);
2906
2925
  const { type } = vizProps.config || {};
2907
2926
  const fallbackType = type && vizTypes[type] ? type : "Treemap";
2908
2927
  if (!vizTypes[type])
@@ -2936,7 +2955,7 @@ function Viz(config) {
2936
2955
  linksFormat: vizProps.linksFormat,
2937
2956
  nodesFormat: vizProps.nodesFormat,
2938
2957
  topojsonFormat: vizProps.topojsonFormat,
2939
- config: { ...defaultConfig_default, ...vizConfig }
2958
+ config: { ...defaultConfig_default, ...vizConfig, sectionVariables: sectionVariablesStr }
2940
2959
  },
2941
2960
  "viz-key"
2942
2961
  ) })
@@ -3102,7 +3121,7 @@ function Viz2({
3102
3121
  active,
3103
3122
  locale,
3104
3123
  variables,
3105
- debug,
3124
+ debug: debug2,
3106
3125
  configOverride = {}
3107
3126
  }) {
3108
3127
  const context = useAppContext();
@@ -3472,6 +3491,7 @@ function BespokeExplore({
3472
3491
  const [metadata, setMetadata] = useState();
3473
3492
  const inputRef = useRef();
3474
3493
  useEffect(() => {
3494
+ setLoading(true);
3475
3495
  dispatch(actions_exports.readMetadata({})).then((resp) => {
3476
3496
  setMetadata(resp.data);
3477
3497
  }, (err) => {
@@ -4332,6 +4352,30 @@ function NavView({ headings, settings }) {
4332
4352
  return smallerThanMd ? /* @__PURE__ */ jsx(MobileNav, { contentOutline }) : /* @__PURE__ */ jsx(DesktopNav, { contentOutline });
4333
4353
  }
4334
4354
 
4355
+ // frontend/components/report/blocks/ResetButton.tsx
4356
+ init_esm_shims();
4357
+ init_hooks();
4358
+ init_hooks();
4359
+ function ResetButtonView({ id, label, showIcon, fullWidth, showWhenDisabled }) {
4360
+ const block = useBlockRef(id).data;
4361
+ const { sectionVariables, resetSectionVariables } = useSectionVariables(block?.section_id);
4362
+ const hasVariables = Boolean(Object.keys(sectionVariables).length);
4363
+ if (!hasVariables && !showWhenDisabled)
4364
+ return null;
4365
+ return /* @__PURE__ */ jsx(
4366
+ Button,
4367
+ {
4368
+ onClick: () => resetSectionVariables(),
4369
+ disabled: !hasVariables,
4370
+ fullWidth,
4371
+ children: /* @__PURE__ */ jsxs(Group, { align: "center", children: [
4372
+ label,
4373
+ showIcon && /* @__PURE__ */ jsx(IconRefresh, {})
4374
+ ] })
4375
+ }
4376
+ );
4377
+ }
4378
+
4335
4379
  // frontend/components/report/blocks/index.tsx
4336
4380
  var VizView = dynamic(
4337
4381
  () => Promise.resolve().then(() => (init_Viz(), Viz_exports)),
@@ -4346,7 +4390,8 @@ var TypeRenderers = {
4346
4390
  [BLOCK_TYPES.VIZ]: VizView,
4347
4391
  [BLOCK_TYPES.GENERATOR]: Generator,
4348
4392
  [BLOCK_TYPES.IMAGE]: ImageView,
4349
- [BLOCK_TYPES.NAV]: NavView
4393
+ [BLOCK_TYPES.NAV]: NavView,
4394
+ [BLOCK_TYPES.RESET_BUTTON]: ResetButtonView
4350
4395
  };
4351
4396
  var blocks_default = TypeRenderers;
4352
4397
 
@@ -4778,10 +4823,67 @@ function NavUI() {
4778
4823
  return /* @__PURE__ */ jsx(Title, { order: 4, children: "Nav UI" });
4779
4824
  }
4780
4825
 
4826
+ // components/blocks/types/simpleEditors/ResetButtonUI.tsx
4827
+ init_esm_shims();
4828
+ function ResetButtonUI({ id, locale, executeButton, onChange, simpleState }) {
4829
+ const [label, setLabel] = useState(simpleState?.label ?? "");
4830
+ const [showIcon, setShowIcon] = useState(simpleState?.showIcon ?? true);
4831
+ const [fullWidth, setFullwidth] = useState(simpleState?.fullWidth ?? false);
4832
+ const [showWhenDisabled, setShowWhenDisabled] = useState(simpleState?.showWhenDisabled ?? false);
4833
+ useEffect(() => {
4834
+ const simpleState2 = {
4835
+ label,
4836
+ showIcon,
4837
+ fullWidth,
4838
+ showWhenDisabled
4839
+ };
4840
+ onChange(simpleState2);
4841
+ }, [label, showIcon, fullWidth, showWhenDisabled, onChange]);
4842
+ return /* @__PURE__ */ jsxs(Stack, { children: [
4843
+ /* @__PURE__ */ jsx(
4844
+ TextInput,
4845
+ {
4846
+ placeholder: "Label for reset section state button",
4847
+ value: label,
4848
+ onChange: (e) => setLabel(e.target.value),
4849
+ label: "Label"
4850
+ }
4851
+ ),
4852
+ /* @__PURE__ */ jsxs(Group, { children: [
4853
+ /* @__PURE__ */ jsx(
4854
+ Switch,
4855
+ {
4856
+ checked: showIcon,
4857
+ label: "Show icon",
4858
+ onChange: (e) => setShowIcon(e.currentTarget.checked)
4859
+ }
4860
+ ),
4861
+ /* @__PURE__ */ jsx(
4862
+ Switch,
4863
+ {
4864
+ checked: fullWidth,
4865
+ label: "Full width",
4866
+ onChange: (e) => setFullwidth(e.currentTarget.checked)
4867
+ }
4868
+ ),
4869
+ /* @__PURE__ */ jsx(
4870
+ Switch,
4871
+ {
4872
+ checked: showWhenDisabled,
4873
+ label: "Show when disabled",
4874
+ onChange: (e) => setShowWhenDisabled(e.currentTarget.checked)
4875
+ }
4876
+ )
4877
+ ] }),
4878
+ executeButton
4879
+ ] });
4880
+ }
4881
+
4781
4882
  // components/blocks/types/simpleEditors/index.js
4782
4883
  var simpleEditors_default = {
4783
4884
  [BLOCK_TYPES.SELECTOR]: SelectorUI_default,
4784
- [BLOCK_TYPES.NAV]: NavUI
4885
+ [BLOCK_TYPES.NAV]: NavUI,
4886
+ [BLOCK_TYPES.RESET_BUTTON]: ResetButtonUI
4785
4887
  };
4786
4888
 
4787
4889
  // components/blocks/types/renderers/index.tsx
@@ -5062,8 +5164,8 @@ function InputMenuItem({
5062
5164
  ] }) }) });
5063
5165
  }
5064
5166
  var InputMenuItem_default = InputMenuItem;
5065
- function Generator2({ outputVariables, debug }) {
5066
- return debug ? /* @__PURE__ */ jsxs(Fragment, { children: [
5167
+ function Generator2({ outputVariables, debug: debug2 }) {
5168
+ return debug2 ? /* @__PURE__ */ jsxs(Fragment, { children: [
5067
5169
  /* @__PURE__ */ jsx(Divider, { label: "Output Variables", labelPosition: "center" }),
5068
5170
  /* @__PURE__ */ jsx(InputMenuItem_default, { variables: outputVariables })
5069
5171
  ] }) : /* @__PURE__ */ jsx(Center, { children: /* @__PURE__ */ jsx(Badge, { color: "gray", variant: "outline", children: "GENERATOR" }, "type") });
@@ -5222,6 +5324,31 @@ function NavPreview({ headings, settings }) {
5222
5324
  ] });
5223
5325
  }
5224
5326
 
5327
+ // components/blocks/types/renderers/ResetButton.tsx
5328
+ init_esm_shims();
5329
+ init_hooks();
5330
+ init_hooks();
5331
+ function ResetButtonPreview({ id, label, showIcon, fullWidth, showWhenDisabled }) {
5332
+ const block = useBlockRef(id).data;
5333
+ const { sectionVariables, resetSectionVariables } = useSectionVariables(block?.section_id);
5334
+ const hasVariables = Boolean(Object.keys(sectionVariables).length);
5335
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
5336
+ !hasVariables && !showWhenDisabled && /* @__PURE__ */ jsx(Text, { size: "xs", children: "Reset button will not be shown on its disabled state" }),
5337
+ /* @__PURE__ */ jsx(
5338
+ Button,
5339
+ {
5340
+ onClick: () => resetSectionVariables(),
5341
+ disabled: !hasVariables,
5342
+ fullWidth,
5343
+ children: /* @__PURE__ */ jsxs(Group, { align: "center", children: [
5344
+ label,
5345
+ showIcon && /* @__PURE__ */ jsx(IconRefresh, {})
5346
+ ] })
5347
+ }
5348
+ )
5349
+ ] });
5350
+ }
5351
+
5225
5352
  // components/blocks/types/renderers/index.tsx
5226
5353
  var VizPreview = dynamic(
5227
5354
  () => Promise.resolve().then(() => (init_Viz2(), Viz_exports2)),
@@ -5236,7 +5363,8 @@ var renderersMap = {
5236
5363
  [BLOCK_TYPES.VIZ]: VizPreview,
5237
5364
  [BLOCK_TYPES.GENERATOR]: Generator_default,
5238
5365
  [BLOCK_TYPES.IMAGE]: ImagePreview,
5239
- [BLOCK_TYPES.NAV]: NavPreview
5366
+ [BLOCK_TYPES.NAV]: NavPreview,
5367
+ [BLOCK_TYPES.RESET_BUTTON]: ResetButtonPreview
5240
5368
  };
5241
5369
  var renderers_default = renderersMap;
5242
5370
 
@@ -5300,6 +5428,12 @@ var allBlocks = {
5300
5428
  renderer: renderers_default[BLOCK_TYPES.NAV],
5301
5429
  renderPreviewOnEdit: true,
5302
5430
  evalWhenNonActive: true
5431
+ },
5432
+ [BLOCK_TYPES.RESET_BUTTON]: {
5433
+ type: BLOCK_TYPES.RESET_BUTTON,
5434
+ renderer: renderers_default[BLOCK_TYPES.RESET_BUTTON],
5435
+ renderPreviewOnEdit: true,
5436
+ evalWhenNonActive: true
5303
5437
  }
5304
5438
  };
5305
5439
  var types_default = allBlocks;
@@ -5385,6 +5519,10 @@ function Block({ blockId, active = true }) {
5385
5519
  });
5386
5520
  return;
5387
5521
  }
5522
+ if (block.type === BLOCK_TYPES.RESET_BUTTON) {
5523
+ setContent({ id: block.id, ...blockContent.simple });
5524
+ return;
5525
+ }
5388
5526
  const swappedLogic = varSwap_default(blockContent?.logic, formatterFunctions, blockContext);
5389
5527
  const { vars } = mortarEval_default(
5390
5528
  "variables",
@@ -6434,7 +6572,7 @@ var SectionResetButton = ({ id }) => {
6434
6572
  const hasVariables = Boolean(Object.keys(sectionVariables).length);
6435
6573
  if (!hasVariables)
6436
6574
  return null;
6437
- return /* @__PURE__ */ jsx(ActionIcon, { disabled: !hasVariables, onClick: resetSectionVariables, children: /* @__PURE__ */ jsx(IconRefresh, { size: 20 }) });
6575
+ return /* @__PURE__ */ jsx(ActionIcon, { disabled: !hasVariables, onClick: resetSectionVariables, variant: "filled", size: "xs", children: /* @__PURE__ */ jsx(IconRefresh, { size: 20 }) });
6438
6576
  };
6439
6577
  function SectionMenu({ sectionId }) {
6440
6578
  const theme = useMantineTheme();
@@ -6443,8 +6581,7 @@ function SectionMenu({ sectionId }) {
6443
6581
  borderRadius: theme.radius.sm
6444
6582
  }, children: [
6445
6583
  /* @__PURE__ */ jsx(DesignSectionMenu, { sectionId }),
6446
- /* @__PURE__ */ jsx(EntityDeleteButton, { type: "section", id: sectionId }),
6447
- /* @__PURE__ */ jsx(SectionResetButton, { id: sectionId })
6584
+ /* @__PURE__ */ jsx(EntityDeleteButton, { type: "section", id: sectionId })
6448
6585
  ] });
6449
6586
  }
6450
6587
  var SectionMenu_default = SectionMenu;
@@ -6948,14 +7085,9 @@ function Section({ section }) {
6948
7085
  id: `section-${id}`,
6949
7086
  pos: "relative",
6950
7087
  children: [
6951
- /* @__PURE__ */ jsxs("div", { style: {
6952
- position: "absolute",
6953
- right: 10,
6954
- top: 10,
6955
- zIndex: 3
6956
- }, children: [
6957
- sectionSettings2.optionsMenu && /* @__PURE__ */ jsx(Options, { sectionId: section.id }),
6958
- /* @__PURE__ */ jsx(SectionResetButton, { id: section.id })
7088
+ /* @__PURE__ */ jsxs(Group, { position: "right", mb: "xs", children: [
7089
+ /* @__PURE__ */ jsx(SectionResetButton, { id: section.id }),
7090
+ sectionSettings2.optionsMenu && /* @__PURE__ */ jsx(Options, { sectionId: section.id })
6959
7091
  ] }),
6960
7092
  /* @__PURE__ */ jsx(StyleWrapper, { className: "bespoke-section-content", settings: sectionSettings2, styles: sectionStyles?.content, children: /* @__PURE__ */ jsx(ColumnsWrapper, { children: Object.keys(columns).sort((a, b) => orderSort(a, b, "blockcol")).map((columnIndex) => {
6961
7093
  const column = columns[columnIndex];
@@ -7247,7 +7379,7 @@ function normalizeList(value) {
7247
7379
  var { localeDefault: localeDefault8 } = getLocales_default();
7248
7380
  function parseReadMemberParams(query) {
7249
7381
  const locale = normalizeList(query.locale)[0] || localeDefault8 || "en";
7250
- const all = locale === "all" || yn3(query.all);
7382
+ const all = locale === "all" || yn4(query.all);
7251
7383
  const mode = normalizeList(query.mode)[0];
7252
7384
  const outputParam = normalizeList(query.output)[0] || "full";
7253
7385
  const output = outputParam === "lite" ? "lite" : "full";
@@ -7312,9 +7444,9 @@ function parseSearchMemberParams(query) {
7312
7444
  locale: localeIsAll ? localeDefault8 : locale,
7313
7445
  limit: normalizeList(query.limit).map(parseFiniteNumber)[0] ?? 5,
7314
7446
  format: formatIsNested ? "nested" : "plain",
7315
- includes: yn3(query.includes, { default: true }),
7316
- visible: yn3(query.visible, { default: true }),
7317
- noImage: yn3(query.noImage, { default: false }),
7447
+ includes: yn4(query.includes, { default: true }),
7448
+ visible: yn4(query.visible, { default: true }),
7449
+ noImage: yn4(query.noImage, { default: false }),
7318
7450
  variant,
7319
7451
  dimension,
7320
7452
  report,
@@ -8896,7 +9028,7 @@ function BlockPreview(props) {
8896
9028
  active,
8897
9029
  allowed,
8898
9030
  blockStateContent,
8899
- debug,
9031
+ debug: debug2,
8900
9032
  for: block,
8901
9033
  locale
8902
9034
  } = props;
@@ -8965,6 +9097,10 @@ function BlockPreview(props) {
8965
9097
  setContent({ headings: block.inputs, settings: block.settings });
8966
9098
  return;
8967
9099
  }
9100
+ if (block.type === BLOCK_TYPES.RESET_BUTTON) {
9101
+ setContent(blockContent.simple);
9102
+ return;
9103
+ }
8968
9104
  const swappedLogic = varSwap_default(blockContent?.logic, formatterFunctions, blockContext);
8969
9105
  const { vars, error: error2, log: log2 } = mortarEval_default(
8970
9106
  "variables",
@@ -9004,8 +9140,8 @@ function BlockPreview(props) {
9004
9140
  style: { width: "100%", minHeight: block.type === BLOCK_TYPES.VIZ ? 400 : "auto" },
9005
9141
  children: [
9006
9142
  !allowed && allowedOverlay,
9007
- Renderer ? /* @__PURE__ */ jsx(Fragment$1, { children: /* @__PURE__ */ jsx(Renderer, { id: block.id, debug, ...content, settings: block.settings }) }, "renderer") : /* @__PURE__ */ jsx(Center, { style: { minHeight: 100 }, children: /* @__PURE__ */ jsx(Badge, { color: "gray", variant: "outline", children: block.type }, "type") }),
9008
- debug && textLog && /* @__PURE__ */ jsx(
9143
+ Renderer ? /* @__PURE__ */ jsx(Fragment$1, { children: /* @__PURE__ */ jsx(Renderer, { id: block.id, debug: debug2, ...content, settings: block.settings }) }, "renderer") : /* @__PURE__ */ jsx(Center, { style: { minHeight: 100 }, children: /* @__PURE__ */ jsx(Badge, { color: "gray", variant: "outline", children: block.type }, "type") }),
9144
+ debug2 && textLog && /* @__PURE__ */ jsx(
9009
9145
  Textarea,
9010
9146
  {
9011
9147
  label: "Console",
@@ -9015,7 +9151,7 @@ function BlockPreview(props) {
9015
9151
  error
9016
9152
  }
9017
9153
  ),
9018
- debug && error && /* @__PURE__ */ jsx(Textarea, { label: "Error", readOnly: true, minRows: 3, value: error }),
9154
+ debug2 && error && /* @__PURE__ */ jsx(Textarea, { label: "Error", readOnly: true, minRows: 3, value: error }),
9019
9155
  block.type === BLOCK_TYPES.GENERATOR && /* @__PURE__ */ jsxs(Fragment, { children: [
9020
9156
  /* @__PURE__ */ jsxs(Group, { spacing: "xs", my: "xs", children: [
9021
9157
  status.duration && /* @__PURE__ */ jsxs(
@@ -10411,7 +10547,10 @@ function SectionEditor({
10411
10547
  }
10412
10548
  ),
10413
10549
  memberImageBg && /* @__PURE__ */ jsx(SectionBackground, {}),
10414
- optionsMenu && /* @__PURE__ */ jsx(Flex, { justify: "flex-end", mx: 16, children: /* @__PURE__ */ jsx(Options, { sectionId: section.id }) }),
10550
+ optionsMenu && /* @__PURE__ */ jsxs(Flex, { justify: "flex-end", mx: 16, align: "center", gap: "xs", children: [
10551
+ /* @__PURE__ */ jsx(SectionResetButton, { id: section.id }),
10552
+ /* @__PURE__ */ jsx(Options, { sectionId: section.id })
10553
+ ] }),
10415
10554
  /* @__PURE__ */ jsx(
10416
10555
  GeneratorsPanel,
10417
10556
  {
package/dist/server.js CHANGED
@@ -500,8 +500,9 @@ var BLOCK_CONTENT_TYPES = {
500
500
  STAT: "stat",
501
501
  SUBTITLE: "subtitle",
502
502
  TITLE: "title",
503
- NAV: "nav"
503
+ NAV: "nav",
504
504
  // todo1.0, how to put custom blocks in here?
505
+ RESET_BUTTON: "reset_button"
505
506
  };
506
507
  var BLOCK_LOGIC_TYPES = {
507
508
  GENERATOR: "generator",
@@ -2115,20 +2116,26 @@ var whitelist = [
2115
2116
  "vi",
2116
2117
  "zh"
2117
2118
  ];
2118
- getLogging_default();
2119
+ var verbose3 = getLogging_default();
2119
2120
  var { locales } = getLocales_default();
2120
2121
  var enabledLocales = locales.filter((d) => whitelist.includes(d));
2121
2122
  var initializing = false;
2122
2123
  var getSearchIndexByLocale = async (db, forceRegenerate = false) => {
2123
2124
  if (forceRegenerate) {
2125
+ if (verbose3)
2126
+ console.log("0\uFE0F\u20E3 CLEARING SEARCH INDEX");
2124
2127
  global.lunrsearch = void 0;
2125
2128
  initializing = false;
2126
2129
  }
2127
2130
  if (global.lunrsearch) {
2131
+ if (verbose3)
2132
+ console.log("\u{1F501} RE-UTILIZING SEARCH INDEX");
2128
2133
  return global.lunrsearch;
2129
2134
  }
2130
2135
  try {
2131
2136
  if (!initializing) {
2137
+ if (verbose3)
2138
+ console.log("1\uFE0F\u20E3 INITIALIZING SEARCH INDEX");
2132
2139
  initializing = true;
2133
2140
  global.lunrsearch = await newSearchIndex(db);
2134
2141
  }
@@ -2146,34 +2153,46 @@ async function newSearchIndex(db) {
2146
2153
  include: [{ association: "contentByLocale" }]
2147
2154
  });
2148
2155
  const setups = enabledLocales.map(async (locale) => {
2149
- if (!lunr[locale] && whitelist.includes(locale) && locale !== "en") {
2156
+ if (!lunr[locale] && locale !== "en") {
2150
2157
  const lunrLang = (await import(`lunr-languages/lunr.${locale}`)).default;
2151
2158
  lunrLang(lunr);
2159
+ lunrStemmer(lunr);
2160
+ if (verbose3)
2161
+ console.log(`\u{1F3F3}\uFE0F INITIALIZING SEARCH ${locale} LOCALE`);
2152
2162
  }
2153
- return [locale, lunr(function() {
2154
- if (locale && locale !== "en")
2155
- this.use(lunr[locale]);
2156
- this.ref("content_id");
2157
- this.field("id");
2158
- this.field("name");
2159
- this.field("keywords");
2160
- this.field("attr");
2161
- this.pipeline.reset();
2162
- this.searchPipeline.reset();
2163
- results.forEach((result) => {
2164
- const content = result.contentByLocale.find((d) => d.locale === locale);
2165
- if (content) {
2166
- const payload = {
2167
- id: result.id,
2168
- content_id: result.content_id,
2169
- name: content.name,
2170
- keywords: content.keywords,
2171
- attributes: content.attributes
2172
- };
2173
- this.add(payload, { boost: result.zvalue });
2174
- }
2175
- }, this);
2176
- })];
2163
+ return [
2164
+ locale,
2165
+ {
2166
+ tokenizer: lunr.tokenizer,
2167
+ query: lunr.Query,
2168
+ index: await lunr(
2169
+ function() {
2170
+ if (locale && locale !== "en")
2171
+ this.use(lunr[locale]);
2172
+ this.ref("content_id");
2173
+ this.field("id");
2174
+ this.field("name");
2175
+ this.field("keywords");
2176
+ this.field("attributes");
2177
+ this.pipeline.reset();
2178
+ this.searchPipeline.reset();
2179
+ results.forEach((result) => {
2180
+ const content = result.contentByLocale.find((d) => d.locale === locale);
2181
+ if (content) {
2182
+ const payload = {
2183
+ id: result.id,
2184
+ content_id: result.content_id,
2185
+ name: content.name,
2186
+ keywords: content.keywords,
2187
+ attributes: content.attributes
2188
+ };
2189
+ this.add(payload, { boost: result.zvalue });
2190
+ }
2191
+ }, this);
2192
+ }
2193
+ )
2194
+ }
2195
+ ];
2177
2196
  });
2178
2197
  return Object.fromEntries(
2179
2198
  await Promise.all(setups)
@@ -2205,8 +2224,10 @@ function dbSearchMemberFactory(db) {
2205
2224
  direction = "ASC"
2206
2225
  } = params;
2207
2226
  if (query && query !== "" && searchIndexByLocale[locale]) {
2208
- const terms = query.split(" ").map((d) => `+${d}*`).join(" ");
2209
- const lunrResults = searchIndexByLocale[locale].search(terms);
2227
+ const terms = query.split(" ").filter((d) => d.trim() !== "").map((d) => {
2228
+ return `+${d}~2*`;
2229
+ }).join(" ");
2230
+ const lunrResults = searchIndexByLocale[locale].index.search(terms);
2210
2231
  resultsIds = lunrResults.map((d) => parseInt(d.ref, 10));
2211
2232
  }
2212
2233
  const whereClause = {
@@ -4612,12 +4633,13 @@ function getRootBlocksForSection(sid, blocks) {
4612
4633
  blockList.filter((block) => block.section_id === sid && // leave blocks belonging to this section
4613
4634
  // that don't depend on any other blocks OR
4614
4635
  (block.inputs.length === 0 || // that depend only on blocks from other sections
4615
- block.inputs.every((id) => nonNativeBlocks.includes(id)))).map((block) => [block.id, block])
4636
+ block.inputs.some((id) => nonNativeBlocks.includes(id)))).map((block) => [block.id, block])
4616
4637
  // then convert them to entries
4617
4638
  );
4618
4639
  }
4619
4640
  var getRootBlocksForSection_default = getRootBlocksForSection;
4620
4641
  var verbose7 = getLogging_default();
4642
+ var debug = yn3(process.env.NEXT_PUBLIC_REPORTS_DEBUG);
4621
4643
  var ORIGIN = process.env.REPORTS_ORIGIN || "";
4622
4644
  axios5.interceptors.request.use((config) => ({
4623
4645
  ...config,
@@ -4721,14 +4743,7 @@ async function runSingleBlock(block, formatterFunctions, blockContext, readMembe
4721
4743
  return {
4722
4744
  outputVariables: {},
4723
4745
  renderVariables: {},
4724
- status: {
4725
- api: null,
4726
- duration: null,
4727
- resp: null,
4728
- log: [],
4729
- error: null,
4730
- allowed: false
4731
- }
4746
+ status: { allowed: false }
4732
4747
  };
4733
4748
  }
4734
4749
  if (unswappedAPI) {
@@ -4759,9 +4774,6 @@ async function runSingleBlock(block, formatterFunctions, blockContext, readMembe
4759
4774
  outputVariables: selectorQueryToVariable_default(block.id, query, config),
4760
4775
  renderVariables: config,
4761
4776
  status: {
4762
- api: null,
4763
- duration: null,
4764
- resp: null,
4765
4777
  log: log2,
4766
4778
  error: error2,
4767
4779
  allowed
@@ -4774,11 +4786,8 @@ async function runSingleBlock(block, formatterFunctions, blockContext, readMembe
4774
4786
  // todo1.0 this will have to be materialized click-variables
4775
4787
  renderVariables: block.contentByLocale.logic.content,
4776
4788
  status: {
4777
- api: null,
4778
- duration: null,
4779
- resp: null,
4780
4789
  log: [],
4781
- error: null,
4790
+ // todo: see if we can remove this safely
4782
4791
  allowed
4783
4792
  }
4784
4793
  };
@@ -4823,17 +4832,19 @@ var getDependencies = (bid, blocks, acc = [], crawlUp = true, crawlDown2 = true,
4823
4832
  if (rootBlock.inputs.length && crawlUp) {
4824
4833
  rootBlock.inputs.forEach((iid) => {
4825
4834
  const rel = `${iid}-${bid}`;
4826
- if (!acc.includes(rel))
4835
+ if (!acc.includes(rel)) {
4827
4836
  acc.push(rel);
4837
+ }
4828
4838
  rootBlock.inputs.forEach((iid2) => getDependencies(iid2, blocks, acc, crawlUp, false, withinSection, visited));
4829
4839
  });
4830
4840
  }
4831
4841
  if (rootBlock.consumers.length && crawlDown2) {
4832
4842
  rootBlock.consumers.forEach((cid) => {
4833
4843
  const rel = `${bid}-${cid}`;
4834
- if (!acc.includes(rel) && (blocks[cid].section_id === blocks[bid].section_id || !withinSection))
4844
+ if (!acc.includes(rel) && (blocks[cid].section_id === blocks[bid].section_id || !withinSection)) {
4835
4845
  acc.push(rel);
4836
- rootBlock.consumers.filter((cid2) => blocks[cid2].section_id === blocks[bid].section_id || !withinSection).forEach((cid2) => getDependencies(cid2, blocks, acc, crawlUp, crawlDown2, withinSection, visited));
4846
+ }
4847
+ rootBlock.consumers.filter((cid2) => blocks[cid2].section_id === blocks[bid].section_id || !withinSection).forEach((cid2) => getDependencies(cid2, blocks, acc, false, crawlDown2, withinSection, visited));
4837
4848
  });
4838
4849
  }
4839
4850
  return acc;
@@ -4866,16 +4877,31 @@ var runConsumersV2 = async (blocks, sections, bid, formatterFunctions, blockCont
4866
4877
  const statusById = { ...initialState4.status ?? {} };
4867
4878
  const parsedBlockContext = parseBlockContext(blockContext);
4868
4879
  const attributes = parsedBlockContext.variables;
4869
- const rootBlocks = bid ? { [bid]: blocks[bid] } : sections.reduce((rootBlocks2, { id }) => ({ ...rootBlocks2, ...getRootBlocksForSection_default(id, blocks) }), {});
4880
+ const rootBlocks = bid ? { [bid]: blocks[bid] } : (sections ?? []).reduce((rootBlocks2, { id }) => ({ ...rootBlocks2, ...getRootBlocksForSection_default(id, blocks) }), {});
4881
+ if (debug)
4882
+ console.log("%crunConsumers: running root blocks", "color:purple", Object.keys(rootBlocks));
4870
4883
  const withinSection = mode === "section";
4871
4884
  const blockDeps = Object.keys(rootBlocks).reduce((deps, id) => {
4885
+ const start = /* @__PURE__ */ new Date();
4872
4886
  const dependencies = getDependencies(Number(id), blocks, [], !bid, true, withinSection).map((rel) => rel.split("-"));
4887
+ const end = /* @__PURE__ */ new Date();
4888
+ const elapsedTime = (end.getTime() - start.getTime()) / 1e3;
4889
+ if (debug)
4890
+ console.log(
4891
+ `%cResolved dependencies for ${id} (${elapsedTime.toFixed(2)}s)`,
4892
+ "color:blue"
4893
+ );
4873
4894
  return [...deps, ...dependencies];
4874
4895
  }, []);
4896
+ const startToposort = /* @__PURE__ */ new Date();
4875
4897
  const orderedDAG = Object.keys(rootBlocks).reduce(
4876
4898
  (orderedDAG2, bid2) => orderedDAG2.includes(bid2) ? [...orderedDAG2] : [bid2, ...orderedDAG2],
4877
4899
  toposort(blockDeps)
4878
4900
  );
4901
+ const endToposort = /* @__PURE__ */ new Date();
4902
+ const toposortTime = (endToposort.getTime() - startToposort.getTime()) / 1e3;
4903
+ if (debug)
4904
+ console.log(`%cResolved DAG (${toposortTime.toFixed(2)}s): `, "color:green", orderedDAG);
4879
4905
  async function runTasksInParallel(executionOrder, blocks2) {
4880
4906
  const runningBlocks = /* @__PURE__ */ new Map();
4881
4907
  for (const bid2 of executionOrder) {
@@ -4883,22 +4909,21 @@ var runConsumersV2 = async (blocks, sections, bid, formatterFunctions, blockCont
4883
4909
  const dependenciesDone = Promise.all(
4884
4910
  block.inputs.filter((iid) => executionOrder.includes(String(iid))).map((iid) => runningBlocks.get(Number(iid)))
4885
4911
  );
4886
- const runningTask = dependenciesDone.then(() => {
4912
+ const runningTask = dependenciesDone.then(async () => {
4887
4913
  const variables = block.inputs.reduce((acc, d) => ({ ...acc, ...variablesById[d] }), attributes);
4888
- const inputNotAllowed = block.inputs.find((iid) => !statusById[iid].allowed || statusById[iid].hiddenByCascade);
4914
+ const inputNotAllowed = block.inputs.find(
4915
+ (iid) => !statusById[iid].allowed || statusById[iid].hiddenByCascade
4916
+ );
4889
4917
  if (inputNotAllowed) {
4890
4918
  statusById[bid2] = {
4891
- api: null,
4892
- duration: null,
4893
- resp: null,
4894
4919
  log: [],
4895
- error: null,
4896
4920
  allowed: false,
4897
4921
  hiddenByCascade: statusById[inputNotAllowed].hiddenByCascade || inputNotAllowed
4898
4922
  };
4899
4923
  return;
4900
4924
  }
4901
- return runSingleBlock(
4925
+ const startBlock = /* @__PURE__ */ new Date();
4926
+ const blockResult = await runSingleBlock(
4902
4927
  block,
4903
4928
  formatterFunctions,
4904
4929
  {
@@ -4910,12 +4935,25 @@ var runConsumersV2 = async (blocks, sections, bid, formatterFunctions, blockCont
4910
4935
  variablesById[bid2] = outputVariables;
4911
4936
  statusById[bid2] = status;
4912
4937
  });
4938
+ const endBlock = /* @__PURE__ */ new Date();
4939
+ const blockTime = (endBlock.getTime() - startBlock.getTime()) / 1e3;
4940
+ if (debug)
4941
+ console.log(
4942
+ `%cBlock ${block.id} resolved in ${blockTime.toFixed(3)}s`,
4943
+ blockTime > 500 ? "color:red" : "color:green"
4944
+ );
4945
+ return blockResult;
4913
4946
  });
4914
4947
  runningBlocks.set(Number(bid2), runningTask);
4915
4948
  }
4916
4949
  await Promise.all(Array.from(runningBlocks.values()));
4917
4950
  }
4951
+ const startVariables = /* @__PURE__ */ new Date();
4918
4952
  await runTasksInParallel(orderedDAG, blocks);
4953
+ const endVariables = /* @__PURE__ */ new Date();
4954
+ const variablesTime = (endVariables.getTime() - startVariables.getTime()) / 1e3;
4955
+ if (debug)
4956
+ console.log(`%cResolved Variables (${variablesTime.toFixed(2)}s): `, "color:green");
4919
4957
  return {
4920
4958
  variables: { ...initialState4.variables ?? {}, ...variablesById },
4921
4959
  status: { ...initialState4.status ?? {}, ...statusById }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datawheel/bespoke",
3
- "version": "0.1.29",
3
+ "version": "0.1.31",
4
4
  "description": "Content management system for creating automated data reports",
5
5
  "exports": {
6
6
  ".": {
@@ -103,7 +103,7 @@
103
103
  "slugify": "^1.6.5",
104
104
  "toposort": "^2.0.2",
105
105
  "unsplash-js": "^7.0.15",
106
- "xlsx": "^0.18.5",
106
+ "xlsx": "https://cdn.sheetjs.com/xlsx-0.19.3/xlsx-0.19.3.tgz",
107
107
  "yn": "^5.0.0"
108
108
  },
109
109
  "devDependencies": {