@malloy-publisher/sdk 0.0.228 → 0.0.229

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 (62) hide show
  1. package/dist/{ServerProvider-BnQo3hhW.es.js → ServerProvider-BdQK_q3C.es.js} +780 -715
  2. package/dist/ServerProvider-n4SO1thp.cjs.js +1 -0
  3. package/dist/client/api.d.ts +79 -1
  4. package/dist/client/index.cjs.js +1 -1
  5. package/dist/client/index.es.js +1 -1
  6. package/dist/components/Materializations/CreateEnvMaterializationDialog.d.ts +14 -0
  7. package/dist/components/Materializations/EnvironmentMaterializations.d.ts +7 -0
  8. package/dist/components/Materializations/MaterializationDetailDialog.d.ts +2 -1
  9. package/dist/components/Materializations/MaterializationRunsList.d.ts +5 -1
  10. package/dist/components/Materializations/ScheduleCard.d.ts +20 -0
  11. package/dist/components/Materializations/SectionLabel.d.ts +10 -0
  12. package/dist/components/Materializations/SetScheduleDialog.d.ts +11 -0
  13. package/dist/components/Materializations/TriggerChip.d.ts +10 -0
  14. package/dist/components/Materializations/cron.d.ts +23 -0
  15. package/dist/components/Materializations/index.d.ts +1 -0
  16. package/dist/components/Materializations/utils.d.ts +9 -0
  17. package/dist/components/Notebook/Notebook.d.ts +6 -1
  18. package/dist/components/Notebook/NotebookCell.d.ts +3 -1
  19. package/dist/components/RenderedResult/ResultContainer.d.ts +3 -1
  20. package/dist/components/RenderedResult/renderLogs.d.ts +6 -0
  21. package/dist/components/ResultsDialog.d.ts +3 -1
  22. package/dist/constants/docLinks.d.ts +6 -0
  23. package/dist/{core-DYlbkyc-.cjs.js → core-BJUrppec.cjs.js} +1 -1
  24. package/dist/{core-CEDZMHV1.es.js → core-Coi3caGs.es.js} +1 -1
  25. package/dist/index-DWcuaQOW.cjs.js +309 -0
  26. package/dist/{index-DC7gIcJX.es.js → index-mbDUet0T.es.js} +34625 -25301
  27. package/dist/index.cjs.js +1 -1
  28. package/dist/index.d.ts +1 -0
  29. package/dist/index.es.js +54 -52
  30. package/dist/utils/queryClient.d.ts +5 -0
  31. package/package.json +3 -1
  32. package/src/components/Environment/AddPackageDialog.tsx +2 -1
  33. package/src/components/Environment/Environment.tsx +8 -0
  34. package/src/components/Home/Home.tsx +5 -4
  35. package/src/components/Materializations/CreateEnvMaterializationDialog.tsx +176 -0
  36. package/src/components/Materializations/EnvironmentMaterializations.tsx +264 -0
  37. package/src/components/Materializations/ManifestView.tsx +2 -3
  38. package/src/components/Materializations/MaterializationDetailDialog.tsx +121 -95
  39. package/src/components/Materializations/MaterializationRunsList.tsx +37 -0
  40. package/src/components/Materializations/Materializations.tsx +86 -1
  41. package/src/components/Materializations/ScheduleCard.tsx +228 -0
  42. package/src/components/Materializations/SectionLabel.tsx +27 -0
  43. package/src/components/Materializations/SetScheduleDialog.tsx +159 -0
  44. package/src/components/Materializations/TriggerChip.tsx +41 -0
  45. package/src/components/Materializations/cron.ts +121 -0
  46. package/src/components/Materializations/index.ts +1 -0
  47. package/src/components/Materializations/utils.ts +14 -0
  48. package/src/components/Model/ModelCell.tsx +4 -0
  49. package/src/components/Notebook/Notebook.tsx +14 -1
  50. package/src/components/Notebook/NotebookCell.tsx +103 -2
  51. package/src/components/Package/Package.tsx +14 -3
  52. package/src/components/QueryResult/QueryResult.tsx +7 -1
  53. package/src/components/RenderedResult/RenderedResult.tsx +153 -51
  54. package/src/components/RenderedResult/ResultContainer.tsx +40 -1
  55. package/src/components/RenderedResult/renderLogs.spec.ts +55 -0
  56. package/src/components/RenderedResult/renderLogs.ts +40 -0
  57. package/src/components/ResultsDialog.tsx +4 -0
  58. package/src/constants/docLinks.ts +17 -0
  59. package/src/index.ts +1 -0
  60. package/src/utils/queryClient.ts +14 -0
  61. package/dist/ServerProvider-CCKhmHeT.cjs.js +0 -1
  62. package/dist/index-DO6Y8XP_.cjs.js +0 -307
package/dist/index.cjs.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-DO6Y8XP_.cjs.js"),r=require("./ServerProvider-CCKhmHeT.cjs.js");exports.AnalyzePackageButton=e.AnalyzePackageButton;exports.BrowserWorkbookStorage=e.BrowserWorkbookStorage;exports.ConnectionExplorer=e.ConnectionExplorer;exports.DimensionFilter=e.DimensionFilter;exports.EmbeddedQueryResult=e.EmbeddedQueryResult;exports.Environment=e.Environment;exports.Home=e.Home;exports.Loading=e.Loading;exports.Materializations=e.Materializations;exports.Model=e.Model;exports.ModelExplorer=e.ModelExplorer;exports.ModelExplorerDialog=e.ModelExplorerDialog;exports.Models=e.Models;exports.Notebook=e.Notebook;exports.Package=e.Package;exports.Packages=e.Packages;exports.PageViewer=e.PageViewer;exports.QueryResult=e.QueryResult;exports.RenderedResult=e.RenderedResult;exports.ResultContainer=e.ResultContainer;exports.SourceExplorerComponent=e.SourceExplorerComponent;exports.SourcesExplorer=e.SourcesExplorer;exports.Workbook=e.Workbook;exports.WorkbookList=e.WorkbookList;exports.WorkbookManager=e.WorkbookManager;exports.WorkbookStorageProvider=e.WorkbookStorageProvider;exports.buildMalloyExplicitTheme=e.buildMalloyExplicitTheme;exports.buildTableCssVars=e.buildTableCssVars;exports.buildVegaThemeOverride=e.buildVegaThemeOverride;exports.createEmbeddedQueryResult=e.createEmbeddedQueryResult;exports.encodeResourceUri=e.encodeResourceUri;exports.extractDimensionSpecs=e.extractDimensionSpecs;exports.extractSourceFromQuery=e.extractSourceFromQuery;exports.generateFilterClause=e.generateFilterClause;exports.getDimensionKey=e.getDimensionKey;exports.getJoinedSources=e.getJoinedSources;exports.injectWhereClause=e.injectWhereClause;exports.makeDimensionKey=e.makeDimensionKey;exports.parseAllSourceInfos=e.parseAllSourceInfos;exports.parseDimensionFilterAnnotation=e.parseDimensionFilterAnnotation;exports.parseNotebookFilterAnnotation=e.parseNotebookFilterAnnotation;exports.parseResourceUri=e.parseResourceUri;exports.readChartAnnotations=e.readChartAnnotations;exports.useDimensionFilters=e.useDimensionFilters;exports.useDimensionFiltersFromSpec=e.useDimensionFiltersFromSpec;exports.useDimensionFiltersQuery=e.useDimensionFiltersQuery;exports.useDimensionalFilterRangeData=e.useDimensionalFilterRangeData;exports.useGivensForm=e.useGivensForm;exports.useModelData=e.useModelData;exports.useModelGivens=e.useModelGivens;exports.useRawQueryData=e.useRawQueryData;exports.useRouterClickHandler=e.useRouterClickHandler;exports.DEFAULT_THEME=r.DEFAULT_THEME;exports.ServerProvider=r.ServerProvider;exports.ThemeProvider=r.ThemeProvider;exports.resolveMode=r.resolveMode;exports.resolveTheme=r.resolveTheme;exports.usePublisherTheme=r.usePublisherTheme;exports.useServer=r.useServer;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-DWcuaQOW.cjs.js"),r=require("./ServerProvider-n4SO1thp.cjs.js");exports.AnalyzePackageButton=e.AnalyzePackageButton;exports.BrowserWorkbookStorage=e.BrowserWorkbookStorage;exports.ConnectionExplorer=e.ConnectionExplorer;exports.DOC_LINKS=e.DOC_LINKS;exports.DimensionFilter=e.DimensionFilter;exports.EmbeddedQueryResult=e.EmbeddedQueryResult;exports.Environment=e.Environment;exports.EnvironmentMaterializations=e.EnvironmentMaterializations;exports.Home=e.Home;exports.Loading=e.Loading;exports.Materializations=e.Materializations;exports.Model=e.Model;exports.ModelExplorer=e.ModelExplorer;exports.ModelExplorerDialog=e.ModelExplorerDialog;exports.Models=e.Models;exports.Notebook=e.Notebook;exports.Package=e.Package;exports.Packages=e.Packages;exports.PageViewer=e.PageViewer;exports.QueryResult=e.QueryResult;exports.RenderedResult=e.RenderedResult;exports.ResultContainer=e.ResultContainer;exports.SourceExplorerComponent=e.SourceExplorerComponent;exports.SourcesExplorer=e.SourcesExplorer;exports.Workbook=e.Workbook;exports.WorkbookList=e.WorkbookList;exports.WorkbookManager=e.WorkbookManager;exports.WorkbookStorageProvider=e.WorkbookStorageProvider;exports.buildMalloyExplicitTheme=e.buildMalloyExplicitTheme;exports.buildTableCssVars=e.buildTableCssVars;exports.buildVegaThemeOverride=e.buildVegaThemeOverride;exports.createEmbeddedQueryResult=e.createEmbeddedQueryResult;exports.encodeResourceUri=e.encodeResourceUri;exports.extractDimensionSpecs=e.extractDimensionSpecs;exports.extractSourceFromQuery=e.extractSourceFromQuery;exports.generateFilterClause=e.generateFilterClause;exports.getDimensionKey=e.getDimensionKey;exports.getJoinedSources=e.getJoinedSources;exports.injectWhereClause=e.injectWhereClause;exports.makeDimensionKey=e.makeDimensionKey;exports.parseAllSourceInfos=e.parseAllSourceInfos;exports.parseDimensionFilterAnnotation=e.parseDimensionFilterAnnotation;exports.parseNotebookFilterAnnotation=e.parseNotebookFilterAnnotation;exports.parseResourceUri=e.parseResourceUri;exports.readChartAnnotations=e.readChartAnnotations;exports.useDimensionFilters=e.useDimensionFilters;exports.useDimensionFiltersFromSpec=e.useDimensionFiltersFromSpec;exports.useDimensionFiltersQuery=e.useDimensionFiltersQuery;exports.useDimensionalFilterRangeData=e.useDimensionalFilterRangeData;exports.useGivensForm=e.useGivensForm;exports.useModelData=e.useModelData;exports.useModelGivens=e.useModelGivens;exports.useRawQueryData=e.useRawQueryData;exports.useRouterClickHandler=e.useRouterClickHandler;exports.DEFAULT_THEME=r.DEFAULT_THEME;exports.ServerProvider=r.ServerProvider;exports.ThemeProvider=r.ThemeProvider;exports.resolveMode=r.resolveMode;exports.resolveTheme=r.resolveTheme;exports.usePublisherTheme=r.usePublisherTheme;exports.useServer=r.useServer;
package/dist/index.d.ts CHANGED
@@ -5,3 +5,4 @@ export * from './hooks';
5
5
  export { useRawQueryData } from './hooks/useRawQueryData';
6
6
  export * from './theme';
7
7
  export * from './utils/formatting';
8
+ export * from './constants/docLinks';
package/dist/index.es.js CHANGED
@@ -1,63 +1,65 @@
1
- import { A as s, O as o, C as r, D as i, F as n, E as t, H as l, L as u, M as d, o as m, q as c, r as k, y as p, N as D, x as g, P as b, B as E, Q as F, R as S, I as v, t as M, S as R, W as x, J as y, T as C, K as P, a1 as T, a2 as h, a3 as A, G as Q, a6 as W, g as B, i as H, j as L, Z as U, k as V, l as f, _ as w, p as G, m as K, n as N, a5 as j, a4 as z, U as I, V as J, X as O, Y as _, a0 as q, v as X, $ as Y, u as Z, e as $ } from "./index-DC7gIcJX.es.js";
2
- import { aB as ae, S as se, aD as oe, aC as re, aA as ie, an as ne, u as te } from "./ServerProvider-BnQo3hhW.es.js";
1
+ import { A as s, T as o, C as r, a8 as i, D as n, G as t, E as l, o as u, H as d, L as m, M as c, q as k, r as D, t as p, B as g, N as E, y as b, P as S, F as v, Q as F, R as M, J as R, v as x, S as y, W as C, K as P, U as T, O as h, a2 as A, a3 as Q, a4 as W, I as L, a7 as B, g as H, i as K, j as N, _ as U, k as V, l as f, $ as w, p as z, m as G, n as I, a6 as O, a5 as _, V as j, X as J, Y as q, Z as X, a1 as Y, x as Z, a0 as $, u as ee, e as ae } from "./index-mbDUet0T.es.js";
2
+ import { aC as oe, S as re, aE as ie, aD as ne, aB as te, an as le, u as ue } from "./ServerProvider-BdQK_q3C.es.js";
3
3
  export {
4
4
  s as AnalyzePackageButton,
5
5
  o as BrowserWorkbookStorage,
6
6
  r as ConnectionExplorer,
7
- ae as DEFAULT_THEME,
8
- i as DimensionFilter,
9
- n as EmbeddedQueryResult,
10
- t as Environment,
11
- l as Home,
12
- u as Loading,
13
- d as Materializations,
14
- m as Model,
15
- c as ModelExplorer,
16
- k as ModelExplorerDialog,
17
- p as Models,
18
- D as Notebook,
19
- g as Package,
20
- b as Packages,
21
- E as PageViewer,
7
+ oe as DEFAULT_THEME,
8
+ i as DOC_LINKS,
9
+ n as DimensionFilter,
10
+ t as EmbeddedQueryResult,
11
+ l as Environment,
12
+ u as EnvironmentMaterializations,
13
+ d as Home,
14
+ m as Loading,
15
+ c as Materializations,
16
+ k as Model,
17
+ D as ModelExplorer,
18
+ p as ModelExplorerDialog,
19
+ g as Models,
20
+ E as Notebook,
21
+ b as Package,
22
+ S as Packages,
23
+ v as PageViewer,
22
24
  F as QueryResult,
23
- S as RenderedResult,
24
- v as ResultContainer,
25
- se as ServerProvider,
26
- M as SourceExplorerComponent,
27
- R as SourcesExplorer,
28
- oe as ThemeProvider,
29
- x as Workbook,
30
- y as WorkbookList,
31
- C as WorkbookManager,
32
- P as WorkbookStorageProvider,
33
- T as buildMalloyExplicitTheme,
34
- h as buildTableCssVars,
35
- A as buildVegaThemeOverride,
36
- Q as createEmbeddedQueryResult,
37
- W as encodeResourceUri,
38
- B as extractDimensionSpecs,
39
- H as extractSourceFromQuery,
40
- L as generateFilterClause,
25
+ M as RenderedResult,
26
+ R as ResultContainer,
27
+ re as ServerProvider,
28
+ x as SourceExplorerComponent,
29
+ y as SourcesExplorer,
30
+ ie as ThemeProvider,
31
+ C as Workbook,
32
+ P as WorkbookList,
33
+ T as WorkbookManager,
34
+ h as WorkbookStorageProvider,
35
+ A as buildMalloyExplicitTheme,
36
+ Q as buildTableCssVars,
37
+ W as buildVegaThemeOverride,
38
+ L as createEmbeddedQueryResult,
39
+ B as encodeResourceUri,
40
+ H as extractDimensionSpecs,
41
+ K as extractSourceFromQuery,
42
+ N as generateFilterClause,
41
43
  U as getDimensionKey,
42
44
  V as getJoinedSources,
43
45
  f as injectWhereClause,
44
46
  w as makeDimensionKey,
45
- G as parseAllSourceInfos,
46
- K as parseDimensionFilterAnnotation,
47
- N as parseNotebookFilterAnnotation,
48
- j as parseResourceUri,
49
- z as readChartAnnotations,
50
- re as resolveMode,
51
- ie as resolveTheme,
52
- I as useDimensionFilters,
47
+ z as parseAllSourceInfos,
48
+ G as parseDimensionFilterAnnotation,
49
+ I as parseNotebookFilterAnnotation,
50
+ O as parseResourceUri,
51
+ _ as readChartAnnotations,
52
+ ne as resolveMode,
53
+ te as resolveTheme,
54
+ j as useDimensionFilters,
53
55
  J as useDimensionFiltersFromSpec,
54
- O as useDimensionFiltersQuery,
55
- _ as useDimensionalFilterRangeData,
56
- q as useGivensForm,
57
- X as useModelData,
58
- Y as useModelGivens,
59
- ne as usePublisherTheme,
60
- Z as useRawQueryData,
61
- $ as useRouterClickHandler,
62
- te as useServer
56
+ q as useDimensionFiltersQuery,
57
+ X as useDimensionalFilterRangeData,
58
+ Y as useGivensForm,
59
+ Z as useModelData,
60
+ $ as useModelGivens,
61
+ le as usePublisherTheme,
62
+ ee as useRawQueryData,
63
+ ae as useRouterClickHandler,
64
+ ue as useServer
63
65
  };
@@ -1,2 +1,7 @@
1
1
  import { QueryClient } from '@tanstack/react-query';
2
2
  export declare const globalQueryClient: QueryClient;
3
+ export declare const CHART_RESULT_QUERY_OPTIONS: {
4
+ readonly staleTime: number;
5
+ readonly refetchOnWindowFocus: false;
6
+ readonly refetchOnReconnect: false;
7
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@malloy-publisher/sdk",
3
3
  "description": "Malloy Publisher SDK",
4
- "version": "0.0.228",
4
+ "version": "0.0.229",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs.js",
7
7
  "module": "dist/index.es.js",
@@ -87,6 +87,8 @@
87
87
  "@emotion/styled": "^11.14.0",
88
88
  "@react-spring/web": "^10.0.1",
89
89
  "@uiw/react-md-editor": "^4.0.6",
90
+ "cron-parser": "^5.6.2",
91
+ "cronstrue": "^2.50.0",
90
92
  "markdown-to-jsx": "^7.7.6",
91
93
  "dayjs": "^1.11.13"
92
94
  },
@@ -16,6 +16,7 @@ import React, { useState } from "react";
16
16
  import { Package } from "../../client";
17
17
  import { useMutationWithApiError } from "../../hooks/useQueryWithApiError";
18
18
  import { parseResourceUri } from "../../utils/formatting";
19
+ import { DOC_LINKS } from "../../constants/docLinks";
19
20
  import { useServer } from "../ServerProvider";
20
21
 
21
22
  interface AddPackageDialogProps {
@@ -117,7 +118,7 @@ export default function AddPackageDialog({
117
118
  Make sure to conform to the{" "}
118
119
  <Box
119
120
  component="a"
120
- href="https://github.com/malloydata/publisher/blob/main/docs/architecture.md"
121
+ href={DOC_LINKS.publishing}
121
122
  target="_blank"
122
123
  rel="noopener noreferrer"
123
124
  sx={{
@@ -1,6 +1,7 @@
1
1
  import { Box, Container, Stack, Typography } from "@mui/material";
2
2
  import { useEffect } from "react";
3
3
  import { parseResourceUri } from "../../utils/formatting";
4
+ import { EnvironmentMaterializations } from "../Materializations";
4
5
  import { useServer } from "../ServerProvider";
5
6
  import About from "./About";
6
7
  import AddPackageDialog from "./AddPackageDialog";
@@ -72,6 +73,13 @@ export default function Environment({
72
73
  <Connections resourceUri={resourceUri} />
73
74
  </Box>
74
75
 
76
+ <Box sx={{ mb: 5 }}>
77
+ <EnvironmentMaterializations
78
+ resourceUri={resourceUri}
79
+ onClickPackageFile={onSelectPackage}
80
+ />
81
+ </Box>
82
+
75
83
  <About resourceUri={resourceUri} />
76
84
  </Container>
77
85
  );
@@ -18,6 +18,7 @@ import { useState } from "react";
18
18
  import { Environment } from "../../client";
19
19
  import { useQueryWithApiError } from "../../hooks/useQueryWithApiError";
20
20
  import { getEnvironmentDescription } from "../../utils/parsing";
21
+ import { DOC_LINKS } from "../../constants/docLinks";
21
22
  import { ApiErrorDisplay } from "../ApiErrorDisplay";
22
23
  import { Loading } from "../Loading";
23
24
  import { useServer } from "../ServerProvider";
@@ -33,17 +34,17 @@ const FEATURES: Array<{ title: string; body: string; href: string }> = [
33
34
  {
34
35
  title: "Ad-hoc analysis",
35
36
  body: "Browse semantic sources, build queries, and run nested logic in Explorer — no code.",
36
- href: "https://github.com/malloydata/publisher/blob/main/README.md#ad-hoc-data-analysis",
37
+ href: DOC_LINKS.explorer,
37
38
  },
38
39
  {
39
40
  title: "Notebook dashboards",
40
41
  body: "Code-first dashboards using Malloy notebooks. Versioned alongside your models.",
41
- href: "https://github.com/malloydata/publisher/blob/main/README.md#notebook-based-dashboards",
42
+ href: DOC_LINKS.publishing,
42
43
  },
43
44
  {
44
45
  title: "AI data agents",
45
46
  body: "Expose models via MCP so agents can discover sources and ask well-formed questions.",
46
- href: "https://github.com/malloydata/publisher/blob/main/README.md#mcp-based-ai-data-agents",
47
+ href: DOC_LINKS.mcpAgents,
47
48
  },
48
49
  ];
49
50
 
@@ -185,7 +186,7 @@ export default function Home({ onClickEnvironment }: HomeProps) {
185
186
  <Button
186
187
  variant="contained"
187
188
  color="primary"
188
- href="https://github.com/malloydata/publisher/blob/main/README.md#server-configuration"
189
+ href={DOC_LINKS.publishing}
189
190
  target="_blank"
190
191
  rel="noopener noreferrer"
191
192
  >
@@ -0,0 +1,176 @@
1
+ import AddIcon from "@mui/icons-material/Add";
2
+ import {
3
+ Box,
4
+ Button,
5
+ Checkbox,
6
+ Dialog,
7
+ DialogActions,
8
+ DialogContent,
9
+ DialogContentText,
10
+ DialogTitle,
11
+ FormControlLabel,
12
+ FormGroup,
13
+ Switch,
14
+ Typography,
15
+ } from "@mui/material";
16
+ import { useState } from "react";
17
+
18
+ type CreateEnvMaterializationDialogProps = {
19
+ /** Packages in the environment the user can materialize. */
20
+ packages: { name: string }[];
21
+ onSubmit: (opts: {
22
+ packageNames: string[];
23
+ forceRefresh: boolean;
24
+ }) => Promise<unknown>;
25
+ isSubmitting: boolean;
26
+ disabled?: boolean;
27
+ };
28
+
29
+ export default function CreateEnvMaterializationDialog({
30
+ packages,
31
+ onSubmit,
32
+ isSubmitting,
33
+ disabled,
34
+ }: CreateEnvMaterializationDialogProps) {
35
+ const [open, setOpen] = useState(false);
36
+ const [selected, setSelected] = useState<Record<string, boolean>>({});
37
+ const [forceRefresh, setForceRefresh] = useState(false);
38
+
39
+ const handleOpen = () => {
40
+ setSelected({});
41
+ setForceRefresh(false);
42
+ setOpen(true);
43
+ };
44
+ const handleClose = () => setOpen(false);
45
+
46
+ const selectedNames = packages
47
+ .map((p) => p.name)
48
+ .filter((name) => selected[name]);
49
+
50
+ const toggle = (name: string) =>
51
+ setSelected((prev) => ({ ...prev, [name]: !prev[name] }));
52
+
53
+ const allSelected =
54
+ packages.length > 0 && selectedNames.length === packages.length;
55
+
56
+ const handleRun = async () => {
57
+ try {
58
+ await onSubmit({ packageNames: selectedNames, forceRefresh });
59
+ setOpen(false);
60
+ } catch {
61
+ // The caller surfaces the error through its Snackbar; keep the dialog
62
+ // open so the user can retry or adjust the selection.
63
+ }
64
+ };
65
+
66
+ return (
67
+ <>
68
+ <Button
69
+ variant="contained"
70
+ startIcon={<AddIcon />}
71
+ onClick={handleOpen}
72
+ disabled={disabled}
73
+ aria-label="New materialization"
74
+ >
75
+ New materialization
76
+ </Button>
77
+
78
+ <Dialog
79
+ open={open}
80
+ onClose={handleClose}
81
+ maxWidth="xs"
82
+ fullWidth
83
+ aria-labelledby="create-env-materialization-title"
84
+ >
85
+ <DialogTitle id="create-env-materialization-title">
86
+ New materialization
87
+ </DialogTitle>
88
+ <DialogContent>
89
+ <DialogContentText sx={{ mb: 1 }}>
90
+ Pick the packages to materialize. Each runs an independent
91
+ build of every persist source in that package.
92
+ </DialogContentText>
93
+
94
+ {packages.length === 0 ? (
95
+ <Typography variant="body2" color="text.secondary">
96
+ No packages in this environment.
97
+ </Typography>
98
+ ) : (
99
+ <>
100
+ <FormControlLabel
101
+ control={
102
+ <Checkbox
103
+ checked={allSelected}
104
+ indeterminate={
105
+ selectedNames.length > 0 && !allSelected
106
+ }
107
+ onChange={(event) => {
108
+ const next: Record<string, boolean> = {};
109
+ if (event.target.checked) {
110
+ packages.forEach(
111
+ (p) => (next[p.name] = true),
112
+ );
113
+ }
114
+ setSelected(next);
115
+ }}
116
+ />
117
+ }
118
+ label={
119
+ <Typography variant="body2">Select all</Typography>
120
+ }
121
+ />
122
+ <Box
123
+ sx={{
124
+ maxHeight: 240,
125
+ overflowY: "auto",
126
+ pl: 1,
127
+ borderLeft: "2px solid",
128
+ borderColor: "divider",
129
+ }}
130
+ >
131
+ <FormGroup>
132
+ {packages.map((p) => (
133
+ <FormControlLabel
134
+ key={p.name}
135
+ control={
136
+ <Checkbox
137
+ checked={!!selected[p.name]}
138
+ onChange={() => toggle(p.name)}
139
+ />
140
+ }
141
+ label={p.name}
142
+ />
143
+ ))}
144
+ </FormGroup>
145
+ </Box>
146
+ <FormControlLabel
147
+ sx={{ mt: 1 }}
148
+ control={
149
+ <Switch
150
+ checked={forceRefresh}
151
+ onChange={(event) =>
152
+ setForceRefresh(event.target.checked)
153
+ }
154
+ />
155
+ }
156
+ label="Force refresh (rebuild even if unchanged)"
157
+ />
158
+ </>
159
+ )}
160
+ </DialogContent>
161
+ <DialogActions>
162
+ <Button onClick={handleClose}>Cancel</Button>
163
+ <Button
164
+ variant="contained"
165
+ loading={isSubmitting}
166
+ disabled={selectedNames.length === 0}
167
+ onClick={handleRun}
168
+ >
169
+ Materialize
170
+ {selectedNames.length > 0 ? ` (${selectedNames.length})` : ""}
171
+ </Button>
172
+ </DialogActions>
173
+ </Dialog>
174
+ </>
175
+ );
176
+ }