@datarecce/ui 0.1.22 → 0.1.23
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/{RecceCheckContext-BETsmiD5.mjs → RecceCheckContext-DIQjrvH8.mjs} +2 -2
- package/dist/{RecceCheckContext-BETsmiD5.mjs.map → RecceCheckContext-DIQjrvH8.mjs.map} +1 -1
- package/dist/{RecceCheckContext-DNKi97uE.js → RecceCheckContext-_xzNlnbJ.js} +2 -2
- package/dist/{RecceCheckContext-DNKi97uE.js.map → RecceCheckContext-_xzNlnbJ.js.map} +1 -1
- package/dist/api.d.mts +1 -1
- package/dist/api.d.ts +1 -1
- package/dist/api.js +11 -37
- package/dist/api.mjs +3 -29
- package/dist/{components-C735_oqD.mjs → components-CfY72Lq2.mjs} +1259 -11
- package/dist/components-CfY72Lq2.mjs.map +1 -0
- package/dist/{components-DeA4kqxK.js → components-DXbVq9Cw.js} +1310 -35
- package/dist/components-DXbVq9Cw.js.map +1 -0
- package/dist/components.d.mts +2 -2
- package/dist/components.d.ts +2 -2
- package/dist/components.js +8 -4
- package/dist/components.mjs +5 -5
- package/dist/{hooks-D6xvNXEc.js → hooks-C4jkoryM.js} +3 -3
- package/dist/{hooks-D6xvNXEc.js.map → hooks-C4jkoryM.js.map} +1 -1
- package/dist/{hooks-Ba-AoxcK.mjs → hooks-C8pyX9m_.mjs} +3 -3
- package/dist/{hooks-Ba-AoxcK.mjs.map → hooks-C8pyX9m_.mjs.map} +1 -1
- package/dist/hooks.d.mts +1 -1
- package/dist/hooks.d.ts +1 -1
- package/dist/hooks.js +3 -3
- package/dist/hooks.mjs +3 -3
- package/dist/{index-DYduBYD8.d.ts → index-CVPmrztP.d.ts} +20 -2
- package/dist/index-CVPmrztP.d.ts.map +1 -0
- package/dist/{index-Sj_wOmNH.d.mts → index-DIHuswfP.d.mts} +85 -67
- package/dist/index-DIHuswfP.d.mts.map +1 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +18 -14
- package/dist/index.mjs +7 -7
- package/dist/{state-BjKRZMwY.js → state-AeoqV9ja.js} +19 -1
- package/dist/{state-BjKRZMwY.js.map → state-AeoqV9ja.js.map} +1 -1
- package/dist/{state-BySLlIE7.mjs → state-BbgVwFV2.mjs} +8 -2
- package/dist/{state-BySLlIE7.mjs.map → state-BbgVwFV2.mjs.map} +1 -1
- package/dist/types.d.mts +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/{user-BHOgMaBf.mjs → version-C2NU3xyx.mjs} +27 -3
- package/dist/version-C2NU3xyx.mjs.map +1 -0
- package/dist/{user-Dt_n5IJX.js → version-MxW9vrDY.js} +32 -2
- package/dist/version-MxW9vrDY.js.map +1 -0
- package/package.json +4 -4
- package/dist/api.js.map +0 -1
- package/dist/api.mjs.map +0 -1
- package/dist/components-C735_oqD.mjs.map +0 -1
- package/dist/components-DeA4kqxK.js.map +0 -1
- package/dist/index-DYduBYD8.d.ts.map +0 -1
- package/dist/index-Sj_wOmNH.d.mts.map +0 -1
- package/dist/user-BHOgMaBf.mjs.map +0 -1
- package/dist/user-Dt_n5IJX.js.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client"
|
|
2
|
-
import { $t as trackMultiNodesAction, At as submitQuery, Bt as waitRun, Cn as
|
|
2
|
+
import { $t as trackMultiNodesAction, At as submitQuery, Bn as lightTheme, Bt as waitRun, Cn as toReactFlow, Ct as cacheKeys, F as useRecceActionContext, Gt as trackColumnLevelLineage, H as IconSave, I as useAppLocation, In as toaster, It as listRuns, J as mergeKeysWithStatus, Jt as trackExploreAction, K as useClipBoardToast, Kt as trackCopyToClipboard, M as useLineageViewContext, Mt as submitQueryDiff, N as useLineageViewContextSafe, Pt as cancelRun, Qt as trackLineageViewRender, R as IconEdit, Rn as colors, Rt as submitRun, Sn as selectUpstream, Tn as getCll, Tt as ScreenshotDataGrid, U as IconSync, Ut as EXPLORE_SOURCE, V as IconInfo, Vn as token, Vt as EXPLORE_ACTION, W as deltaPercentageString, Wt as LINEAGE_SELECTION_ACTION, Xt as trackHistoryAction, Zt as trackLineageSelection, _ as findByRunType, _n as COLUMN_HEIGHT, _t as useRecceInstanceContext, a as saveAs$1, an as trackStateAction, at as useModelColumns_default, bn as layout, c as createCheckByRun, cn as isProfileDiffRun, ct as useRunsAggregated, d as getCheck, dn as isQueryRun, dt as useIdleTimeout, en as trackNavigation, f as listChecks, fn as isRowCountDiffRun, g as useChecks, gn as isValueDiffRun, h as updateCheck, hn as isValueDiffDetailRun, ht as formatDuration, i as rename, in as trackSingleEnvironment, it as supportsHistogramDiff, j as LineageViewContext, jn as axiosClient, jt as submitQueryBase, k as createDataGridFromData, kt as createLineageDiffCheck, ln as isQueryBaseRun, lt as useRecceServerFlag, mn as isTopKDiffRun, nn as trackPreviewChangeFeedback, p as markAsPresetCheck, pn as isRowCountRun, q as mergeKeys, qt as trackEnvironmentConfig, r as isStateSyncing, rn as trackShareState, s as syncState, sn as isHistogramDiffRun, st as useLineageGraphContext, t as exportState, tn as trackPreviewChange, u as deleteCheck, un as isQueryDiffRun, v as runTypeHasRef, vn as isLineageGraphColumnNode, vt as useRecceInstanceInfo, wn as union, wt as EmptyRowsRenderer, xn as selectDownstream, yn as isLineageGraphNode, z as IconExport, zn as darkTheme, zt as submitRunFromCheck } from "./state-BbgVwFV2.mjs";
|
|
3
3
|
import { t as RECCE_SUPPORT_CALENDAR_URL } from "./urls-D7PrPolY.mjs";
|
|
4
|
-
import { a as
|
|
5
|
-
import { i as useValueDiffAlertDialog_default, l as defaultSqlQuery, n as useRecceCheckContext, o as useRecceShareStateContext, r as useCheckToast, u as useRecceQueryContext } from "./RecceCheckContext-
|
|
4
|
+
import { a as localStorageKeys, c as createSchemaDiffCheck, i as connectToCloud, n as fetchGitHubAvatar, o as sessionStorageKeys, r as fetchUser, s as select, t as useVersionNumber } from "./version-C2NU3xyx.mjs";
|
|
5
|
+
import { i as useValueDiffAlertDialog_default, l as defaultSqlQuery, n as useRecceCheckContext, o as useRecceShareStateContext, r as useCheckToast, u as useRecceQueryContext } from "./RecceCheckContext-DIQjrvH8.mjs";
|
|
6
6
|
import { t as DisableTooltipMessages } from "./tooltipMessage-CrXjOmVM.mjs";
|
|
7
7
|
import CssBaseline from "@mui/material/CssBaseline";
|
|
8
8
|
import { ThemeProvider, alpha, useTheme } from "@mui/material/styles";
|
|
@@ -27,27 +27,30 @@ import { IconType } from "react-icons";
|
|
|
27
27
|
import { LuExternalLink } from "react-icons/lu";
|
|
28
28
|
import { TbChecklist, TbCloudUpload, TbPlus } from "react-icons/tb";
|
|
29
29
|
import _, { isEmpty } from "lodash";
|
|
30
|
-
import { PiBookmarkSimple, PiCaretDown, PiChatText, PiCheck, PiCheckCircle, PiCircle, PiCopy, PiInfo, PiInfoFill, PiNotePencil, PiPencilSimple, PiPlusCircle, PiRepeat, PiTrashFill, PiTrashSimple, PiWarning, PiX } from "react-icons/pi";
|
|
30
|
+
import { PiBookmarkSimple, PiCaretDown, PiChatText, PiCheck, PiCheckCircle, PiCircle, PiCopy, PiInfo, PiInfoFill, PiMoon, PiNotePencil, PiPencilSimple, PiPlusCircle, PiRepeat, PiSun, PiTrashFill, PiTrashSimple, PiWarning, PiX } from "react-icons/pi";
|
|
31
31
|
import MuiDialog from "@mui/material/Dialog";
|
|
32
32
|
import DialogActions from "@mui/material/DialogActions";
|
|
33
33
|
import DialogContent from "@mui/material/DialogContent";
|
|
34
34
|
import DialogTitle from "@mui/material/DialogTitle";
|
|
35
35
|
import IconButton from "@mui/material/IconButton";
|
|
36
36
|
import { IoBookmarksOutline, IoClose, IoWarning } from "react-icons/io5";
|
|
37
|
+
import NextLink from "next/link";
|
|
37
38
|
import Checkbox from "@mui/material/Checkbox";
|
|
38
39
|
import FormControlLabel from "@mui/material/FormControlLabel";
|
|
39
40
|
import TextField from "@mui/material/TextField";
|
|
40
41
|
import Menu from "@mui/material/Menu";
|
|
41
42
|
import MenuItem from "@mui/material/MenuItem";
|
|
42
|
-
import { VscCircleLarge, VscDiffAdded, VscDiffModified, VscDiffRemoved, VscFeedback, VscHistory, VscKebabVertical } from "react-icons/vsc";
|
|
43
|
+
import { VscCircleLarge, VscDiffAdded, VscDiffModified, VscDiffRemoved, VscFeedback, VscGitPullRequest, VscHistory, VscKebabVertical } from "react-icons/vsc";
|
|
43
44
|
import MuiTooltip from "@mui/material/Tooltip";
|
|
45
|
+
import { useCopyToClipboard, useInterval } from "usehooks-ts";
|
|
44
46
|
import ListSubheader from "@mui/material/ListSubheader";
|
|
47
|
+
import { usePathname } from "next/navigation";
|
|
45
48
|
import Link from "@mui/material/Link";
|
|
46
49
|
import MuiPopover from "@mui/material/Popover";
|
|
47
50
|
import { format, formatDistance, formatDistanceToNow, parseISO } from "date-fns";
|
|
48
51
|
import saveAs from "file-saver";
|
|
49
52
|
import { toCanvas } from "html-to-image";
|
|
50
|
-
import { FaCamera, FaCheckCircle, FaCheckSquare, FaCube, FaDatabase, FaExpandArrowsAlt, FaRegCheckCircle, FaRegDotCircle, FaRegSquare, FaSeedling } from "react-icons/fa";
|
|
53
|
+
import { FaCamera, FaCheckCircle, FaCheckSquare, FaCloud, FaCube, FaDatabase, FaExpandArrowsAlt, FaGithub, FaQuestionCircle, FaRegCheckCircle, FaRegDotCircle, FaRegSquare, FaSeedling, FaSlack, FaUser } from "react-icons/fa";
|
|
51
54
|
import { FaBookmark, FaChartSimple, FaCircleNodes, FaGauge, FaPlay } from "react-icons/fa6";
|
|
52
55
|
import Chip from "@mui/material/Chip";
|
|
53
56
|
import Skeleton from "@mui/material/Skeleton";
|
|
@@ -94,6 +97,8 @@ import Card from "@mui/material/Card";
|
|
|
94
97
|
import CardContent from "@mui/material/CardContent";
|
|
95
98
|
import CardHeader from "@mui/material/CardHeader";
|
|
96
99
|
import Badge from "@mui/material/Badge";
|
|
100
|
+
import DisplayModeToggle from "app/(mainComponents)/DisplayModeToggle";
|
|
101
|
+
import RecceVersionBadge from "app/(mainComponents)/RecceVersionBadge";
|
|
97
102
|
|
|
98
103
|
//#region recce-source/js/src/components/ui/mui-provider.tsx
|
|
99
104
|
/**
|
|
@@ -223,7 +228,7 @@ const getHTMLElementFromRef = (refCurrent) => {
|
|
|
223
228
|
};
|
|
224
229
|
const IGNORE_SCREENSHOT_CLASS = "ignore-screenshot";
|
|
225
230
|
const highlightBoxShadow = "rgba(0, 0, 0, 0.25) 0px 54px 55px, rgba(0, 0, 0, 0.12) 0px -12px 30px, rgba(0, 0, 0, 0.12) 0px 4px 6px, rgba(0, 0, 0, 0.17) 0px 12px 13px, rgba(0, 0, 0, 0.09) 0px -3px 5px";
|
|
226
|
-
function useCopyToClipboard({ renderLibrary = "html2canvas", imageType = "png", backgroundColor = null, boardEffect = true, shadowEffect = false, borderStyle = `solid 1px ${colors.neutral[300]}`, borderRadius = "10px", onSuccess, onError, ignoreElements }) {
|
|
231
|
+
function useCopyToClipboard$1({ renderLibrary = "html2canvas", imageType = "png", backgroundColor = null, boardEffect = true, shadowEffect = false, borderStyle = `solid 1px ${colors.neutral[300]}`, borderRadius = "10px", onSuccess, onError, ignoreElements }) {
|
|
227
232
|
const [status, setStatus] = useState("idle");
|
|
228
233
|
const ref = useRef(null);
|
|
229
234
|
const { onOpen, setImgBlob, ImageDownloadModal } = useImageDownloadModal();
|
|
@@ -324,7 +329,7 @@ function useCopyToClipboard({ renderLibrary = "html2canvas", imageType = "png",
|
|
|
324
329
|
}
|
|
325
330
|
function useCopyToClipboardButton(options) {
|
|
326
331
|
const { successToast, failToast } = useClipBoardToast();
|
|
327
|
-
const { isLoading, copyToClipboard, ImageDownloadModal, ref } = useCopyToClipboard({
|
|
332
|
+
const { isLoading, copyToClipboard, ImageDownloadModal, ref } = useCopyToClipboard$1({
|
|
328
333
|
imageType: "png",
|
|
329
334
|
shadowEffect: true,
|
|
330
335
|
backgroundColor: options?.backgroundColor ?? colors.neutral[100],
|
|
@@ -6398,7 +6403,7 @@ function PrivateLineageView({ interactive = false, ...props }, ref) {
|
|
|
6398
6403
|
const reactFlow = useReactFlow();
|
|
6399
6404
|
const refResize = useRef(null);
|
|
6400
6405
|
const { successToast, failToast } = useClipBoardToast();
|
|
6401
|
-
const { copyToClipboard, ImageDownloadModal, ref: refReactFlow } = useCopyToClipboard({
|
|
6406
|
+
const { copyToClipboard, ImageDownloadModal, ref: refReactFlow } = useCopyToClipboard$1({
|
|
6402
6407
|
renderLibrary: "html-to-image",
|
|
6403
6408
|
imageType: "png",
|
|
6404
6409
|
shadowEffect: true,
|
|
@@ -10397,6 +10402,124 @@ function SummaryView() {
|
|
|
10397
10402
|
}) });
|
|
10398
10403
|
}
|
|
10399
10404
|
|
|
10405
|
+
//#endregion
|
|
10406
|
+
//#region recce-source/js/src/components/app/AvatarDropdown.tsx
|
|
10407
|
+
function AvatarDropdown() {
|
|
10408
|
+
const { data: user, isLoading, error } = useQuery({
|
|
10409
|
+
queryKey: cacheKeys.user(),
|
|
10410
|
+
queryFn: fetchUser,
|
|
10411
|
+
retry: false
|
|
10412
|
+
});
|
|
10413
|
+
const { data: avatarUrl } = useQuery({
|
|
10414
|
+
queryKey: ["github-avatar", user?.id],
|
|
10415
|
+
queryFn: () => user ? fetchGitHubAvatar(user.id) : Promise.resolve(null),
|
|
10416
|
+
enabled: !!user?.id && user.login_type === "github",
|
|
10417
|
+
retry: false,
|
|
10418
|
+
staleTime: 300 * 1e3
|
|
10419
|
+
});
|
|
10420
|
+
const [anchorEl, setAnchorEl] = useState(null);
|
|
10421
|
+
const open = Boolean(anchorEl);
|
|
10422
|
+
const handleClick = (event) => {
|
|
10423
|
+
setAnchorEl(event.currentTarget);
|
|
10424
|
+
};
|
|
10425
|
+
const handleClose = () => {
|
|
10426
|
+
setAnchorEl(null);
|
|
10427
|
+
};
|
|
10428
|
+
const showUserInfo = !isLoading && !error && user;
|
|
10429
|
+
const getInitials = (name) => {
|
|
10430
|
+
if (!name) return "U";
|
|
10431
|
+
return name.charAt(0).toUpperCase();
|
|
10432
|
+
};
|
|
10433
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [isLoading ? /* @__PURE__ */ jsx(Box, {
|
|
10434
|
+
onClick: handleClick,
|
|
10435
|
+
sx: {
|
|
10436
|
+
width: 32,
|
|
10437
|
+
height: 32,
|
|
10438
|
+
borderRadius: "50%",
|
|
10439
|
+
bgcolor: "background.paper",
|
|
10440
|
+
color: "primary.main",
|
|
10441
|
+
display: "flex",
|
|
10442
|
+
alignItems: "center",
|
|
10443
|
+
justifyContent: "center",
|
|
10444
|
+
cursor: "pointer"
|
|
10445
|
+
},
|
|
10446
|
+
children: /* @__PURE__ */ jsx(CircularProgress, { size: 16 })
|
|
10447
|
+
}) : /* @__PURE__ */ jsx(MuiAvatar, {
|
|
10448
|
+
onClick: handleClick,
|
|
10449
|
+
src: avatarUrl || void 0,
|
|
10450
|
+
sx: {
|
|
10451
|
+
width: 28,
|
|
10452
|
+
height: 28,
|
|
10453
|
+
cursor: "pointer",
|
|
10454
|
+
outline: "1px solid white",
|
|
10455
|
+
fontSize: "0.875rem"
|
|
10456
|
+
},
|
|
10457
|
+
children: getInitials(user?.login)
|
|
10458
|
+
}), /* @__PURE__ */ jsxs(Menu, {
|
|
10459
|
+
anchorEl,
|
|
10460
|
+
open,
|
|
10461
|
+
onClose: handleClose,
|
|
10462
|
+
slotProps: { paper: { sx: {
|
|
10463
|
+
bgcolor: "background.paper",
|
|
10464
|
+
borderColor: "divider",
|
|
10465
|
+
boxShadow: 3,
|
|
10466
|
+
minWidth: 180
|
|
10467
|
+
} } },
|
|
10468
|
+
children: [
|
|
10469
|
+
/* @__PURE__ */ jsxs(Box, {
|
|
10470
|
+
sx: {
|
|
10471
|
+
px: 2,
|
|
10472
|
+
py: 1.5
|
|
10473
|
+
},
|
|
10474
|
+
children: [
|
|
10475
|
+
isLoading && /* @__PURE__ */ jsxs(Box, {
|
|
10476
|
+
sx: {
|
|
10477
|
+
display: "flex",
|
|
10478
|
+
alignItems: "center",
|
|
10479
|
+
gap: 1
|
|
10480
|
+
},
|
|
10481
|
+
children: [/* @__PURE__ */ jsx(Typography, {
|
|
10482
|
+
variant: "body2",
|
|
10483
|
+
color: "text.primary",
|
|
10484
|
+
children: "Loading..."
|
|
10485
|
+
}), /* @__PURE__ */ jsx(CircularProgress, { size: 16 })]
|
|
10486
|
+
}),
|
|
10487
|
+
error && /* @__PURE__ */ jsx(Typography, {
|
|
10488
|
+
variant: "caption",
|
|
10489
|
+
color: "error",
|
|
10490
|
+
children: "Failed to load user information"
|
|
10491
|
+
}),
|
|
10492
|
+
showUserInfo && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Typography, {
|
|
10493
|
+
variant: "body2",
|
|
10494
|
+
fontWeight: "600",
|
|
10495
|
+
color: "text.primary",
|
|
10496
|
+
children: user.login
|
|
10497
|
+
}), user.email && /* @__PURE__ */ jsx(Typography, {
|
|
10498
|
+
variant: "caption",
|
|
10499
|
+
color: "text.secondary",
|
|
10500
|
+
children: user.email
|
|
10501
|
+
})] })
|
|
10502
|
+
]
|
|
10503
|
+
}),
|
|
10504
|
+
/* @__PURE__ */ jsx(Divider, {}),
|
|
10505
|
+
/* @__PURE__ */ jsxs(MenuItem, {
|
|
10506
|
+
onClick: () => {
|
|
10507
|
+
window.open("https://cloud.datarecce.io/", "_blank");
|
|
10508
|
+
handleClose();
|
|
10509
|
+
},
|
|
10510
|
+
children: [/* @__PURE__ */ jsx(ListItemIcon, { children: /* @__PURE__ */ jsx(FaCloud, {}) }), /* @__PURE__ */ jsx(ListItemText, { children: "Recce Cloud" })]
|
|
10511
|
+
}),
|
|
10512
|
+
/* @__PURE__ */ jsxs(MenuItem, {
|
|
10513
|
+
onClick: () => {
|
|
10514
|
+
window.open(RECCE_SUPPORT_CALENDAR_URL, "_blank");
|
|
10515
|
+
handleClose();
|
|
10516
|
+
},
|
|
10517
|
+
children: [/* @__PURE__ */ jsx(ListItemIcon, { children: /* @__PURE__ */ jsx(FaUser, {}) }), /* @__PURE__ */ jsx(ListItemText, { children: "Get live support" })]
|
|
10518
|
+
})
|
|
10519
|
+
]
|
|
10520
|
+
})] });
|
|
10521
|
+
}
|
|
10522
|
+
|
|
10400
10523
|
//#endregion
|
|
10401
10524
|
//#region recce-source/js/src/components/timeout/IdleTimeoutBadge.tsx
|
|
10402
10525
|
/**
|
|
@@ -10434,5 +10557,1130 @@ function IdleTimeoutBadge() {
|
|
|
10434
10557
|
}
|
|
10435
10558
|
|
|
10436
10559
|
//#endregion
|
|
10437
|
-
|
|
10438
|
-
|
|
10560
|
+
//#region recce-source/js/app/(mainComponents)/TopBar.tsx
|
|
10561
|
+
function LinkIcon({ icon: IconComponent, href, sx, ...props }) {
|
|
10562
|
+
const theme = useTheme();
|
|
10563
|
+
return /* @__PURE__ */ jsx(Link, {
|
|
10564
|
+
sx: {
|
|
10565
|
+
height: "20px",
|
|
10566
|
+
color: "common.white",
|
|
10567
|
+
...sx
|
|
10568
|
+
},
|
|
10569
|
+
href,
|
|
10570
|
+
target: "_blank",
|
|
10571
|
+
...props,
|
|
10572
|
+
children: /* @__PURE__ */ jsx(IconComponent, { style: {
|
|
10573
|
+
color: theme.palette.common.white,
|
|
10574
|
+
width: 20,
|
|
10575
|
+
height: 20
|
|
10576
|
+
} })
|
|
10577
|
+
});
|
|
10578
|
+
}
|
|
10579
|
+
function TopBar() {
|
|
10580
|
+
const { reviewMode, isDemoSite, envInfo, cloudMode } = useLineageGraphContext();
|
|
10581
|
+
const { featureToggles, authed } = useRecceInstanceContext();
|
|
10582
|
+
const { url: prURL, id: prID } = envInfo?.pullRequest ?? {};
|
|
10583
|
+
const demoPrId = prURL ? prURL.split("/").pop() : null;
|
|
10584
|
+
const brandLink = cloudMode || authed ? "https://cloud.datarecce.io/" : "https://reccehq.com/";
|
|
10585
|
+
const [showModal, setShowModal] = useState(false);
|
|
10586
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
10587
|
+
sx: {
|
|
10588
|
+
display: "flex",
|
|
10589
|
+
gap: "10px",
|
|
10590
|
+
minHeight: "40px",
|
|
10591
|
+
alignItems: "center",
|
|
10592
|
+
bgcolor: colors.brand[400]
|
|
10593
|
+
},
|
|
10594
|
+
children: [
|
|
10595
|
+
/* @__PURE__ */ jsx(Link, {
|
|
10596
|
+
href: brandLink,
|
|
10597
|
+
target: "_blank",
|
|
10598
|
+
sx: { "&:hover": { textDecoration: "none" } },
|
|
10599
|
+
children: /* @__PURE__ */ jsxs(Box, {
|
|
10600
|
+
sx: {
|
|
10601
|
+
display: "flex",
|
|
10602
|
+
gap: "10px",
|
|
10603
|
+
alignItems: "center"
|
|
10604
|
+
},
|
|
10605
|
+
children: [/* @__PURE__ */ jsx(Box, {
|
|
10606
|
+
component: "img",
|
|
10607
|
+
sx: {
|
|
10608
|
+
width: 20,
|
|
10609
|
+
height: 20,
|
|
10610
|
+
ml: "18px"
|
|
10611
|
+
},
|
|
10612
|
+
src: "/logo/recce-logo-white.png",
|
|
10613
|
+
alt: "recce-logo-white"
|
|
10614
|
+
}), /* @__PURE__ */ jsx(Typography, {
|
|
10615
|
+
variant: "h4",
|
|
10616
|
+
sx: {
|
|
10617
|
+
fontFamily: "\"Montserrat\", sans-serif",
|
|
10618
|
+
color: "common.white",
|
|
10619
|
+
fontSize: "1.25rem"
|
|
10620
|
+
},
|
|
10621
|
+
children: "RECCE"
|
|
10622
|
+
})]
|
|
10623
|
+
})
|
|
10624
|
+
}),
|
|
10625
|
+
/* @__PURE__ */ jsx(DisplayModeToggle, {}),
|
|
10626
|
+
/* @__PURE__ */ jsx(RecceVersionBadge, {}),
|
|
10627
|
+
(featureToggles.mode ?? reviewMode) && /* @__PURE__ */ jsx(Badge, {
|
|
10628
|
+
sx: {
|
|
10629
|
+
fontSize: "0.875rem",
|
|
10630
|
+
color: "rgba(255,255,255,0.8)",
|
|
10631
|
+
textTransform: "uppercase",
|
|
10632
|
+
borderWidth: 1,
|
|
10633
|
+
px: 1,
|
|
10634
|
+
borderRadius: .75,
|
|
10635
|
+
borderColor: "rgba(255,255,255,0.8)"
|
|
10636
|
+
},
|
|
10637
|
+
children: featureToggles.mode ?? "review mode"
|
|
10638
|
+
}),
|
|
10639
|
+
cloudMode && prID && /* @__PURE__ */ jsx(Badge, {
|
|
10640
|
+
sx: {
|
|
10641
|
+
fontSize: "0.875rem",
|
|
10642
|
+
color: "rgba(255,255,255,0.8)",
|
|
10643
|
+
textTransform: "uppercase",
|
|
10644
|
+
borderWidth: 1,
|
|
10645
|
+
px: 1,
|
|
10646
|
+
borderRadius: .75,
|
|
10647
|
+
borderColor: "rgba(255,255,255,0.8)"
|
|
10648
|
+
},
|
|
10649
|
+
children: /* @__PURE__ */ jsxs(Stack, {
|
|
10650
|
+
direction: "row",
|
|
10651
|
+
spacing: 1,
|
|
10652
|
+
alignItems: "center",
|
|
10653
|
+
children: [/* @__PURE__ */ jsx(Box, { children: "cloud mode" }), /* @__PURE__ */ jsx(Box, {
|
|
10654
|
+
sx: {
|
|
10655
|
+
borderLeft: "1px solid rgba(255,255,255,0.8)",
|
|
10656
|
+
pl: "8px"
|
|
10657
|
+
},
|
|
10658
|
+
children: /* @__PURE__ */ jsxs(Link, {
|
|
10659
|
+
href: prURL,
|
|
10660
|
+
sx: { "&:hover": { textDecoration: "none" } },
|
|
10661
|
+
target: "_blank",
|
|
10662
|
+
children: [/* @__PURE__ */ jsx(VscGitPullRequest, { style: {
|
|
10663
|
+
color: "rgba(255,255,255,0.8)",
|
|
10664
|
+
width: 12,
|
|
10665
|
+
height: 12,
|
|
10666
|
+
marginRight: 2,
|
|
10667
|
+
display: "inline",
|
|
10668
|
+
verticalAlign: "middle"
|
|
10669
|
+
} }), /* @__PURE__ */ jsx(Typography, {
|
|
10670
|
+
component: "span",
|
|
10671
|
+
sx: {
|
|
10672
|
+
color: "rgba(255,255,255,0.8)",
|
|
10673
|
+
display: "inline"
|
|
10674
|
+
},
|
|
10675
|
+
children: `#${String(prID)}`
|
|
10676
|
+
})]
|
|
10677
|
+
})
|
|
10678
|
+
})]
|
|
10679
|
+
})
|
|
10680
|
+
}),
|
|
10681
|
+
isDemoSite && prURL && demoPrId && /* @__PURE__ */ jsx(Badge, {
|
|
10682
|
+
sx: {
|
|
10683
|
+
fontSize: "0.875rem",
|
|
10684
|
+
color: "rgba(255,255,255,0.8)",
|
|
10685
|
+
textTransform: "uppercase",
|
|
10686
|
+
borderWidth: 1,
|
|
10687
|
+
px: 1,
|
|
10688
|
+
borderRadius: .75,
|
|
10689
|
+
borderColor: "rgba(255,255,255,0.8)"
|
|
10690
|
+
},
|
|
10691
|
+
children: /* @__PURE__ */ jsxs(Stack, {
|
|
10692
|
+
direction: "row",
|
|
10693
|
+
spacing: 1,
|
|
10694
|
+
alignItems: "center",
|
|
10695
|
+
children: [/* @__PURE__ */ jsx(Box, { children: "demo mode" }), /* @__PURE__ */ jsx(Box, {
|
|
10696
|
+
sx: {
|
|
10697
|
+
borderLeft: "1px solid rgba(255,255,255,0.8)",
|
|
10698
|
+
pl: "8px"
|
|
10699
|
+
},
|
|
10700
|
+
children: /* @__PURE__ */ jsxs(Link, {
|
|
10701
|
+
href: prURL,
|
|
10702
|
+
sx: { "&:hover": { textDecoration: "none" } },
|
|
10703
|
+
target: "_blank",
|
|
10704
|
+
children: [/* @__PURE__ */ jsx(VscGitPullRequest, { style: {
|
|
10705
|
+
color: "rgba(255,255,255,0.8)",
|
|
10706
|
+
width: 12,
|
|
10707
|
+
height: 12,
|
|
10708
|
+
marginRight: 2,
|
|
10709
|
+
display: "inline",
|
|
10710
|
+
verticalAlign: "middle"
|
|
10711
|
+
} }), /* @__PURE__ */ jsx(Typography, {
|
|
10712
|
+
component: "span",
|
|
10713
|
+
sx: {
|
|
10714
|
+
color: "rgba(255,255,255,0.8)",
|
|
10715
|
+
display: "inline"
|
|
10716
|
+
},
|
|
10717
|
+
children: `#${demoPrId}`
|
|
10718
|
+
})]
|
|
10719
|
+
})
|
|
10720
|
+
})]
|
|
10721
|
+
})
|
|
10722
|
+
}),
|
|
10723
|
+
/* @__PURE__ */ jsx(Box, { sx: { flex: 1 } }),
|
|
10724
|
+
(isDemoSite || featureToggles.mode === "read only") && /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
10725
|
+
/* @__PURE__ */ jsx(LinkIcon, {
|
|
10726
|
+
icon: FaGithub,
|
|
10727
|
+
href: "https://github.com/DataRecce/recce"
|
|
10728
|
+
}),
|
|
10729
|
+
/* @__PURE__ */ jsx(LinkIcon, {
|
|
10730
|
+
icon: FaSlack,
|
|
10731
|
+
href: "https://getdbt.slack.com/archives/C05C28V7CPP"
|
|
10732
|
+
}),
|
|
10733
|
+
/* @__PURE__ */ jsx(LinkIcon, {
|
|
10734
|
+
sx: { mr: 2 },
|
|
10735
|
+
icon: FaQuestionCircle,
|
|
10736
|
+
href: "https://docs.datarecce.io"
|
|
10737
|
+
})
|
|
10738
|
+
] }),
|
|
10739
|
+
!isDemoSite && featureToggles.mode !== "read only" && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(IdleTimeoutBadge, {}), authed || cloudMode ? /* @__PURE__ */ jsx(Box, {
|
|
10740
|
+
sx: { mr: 2 },
|
|
10741
|
+
children: /* @__PURE__ */ jsx(AvatarDropdown, {})
|
|
10742
|
+
}) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Box, {
|
|
10743
|
+
component: "button",
|
|
10744
|
+
sx: {
|
|
10745
|
+
color: "common.white",
|
|
10746
|
+
fontSize: "0.875rem",
|
|
10747
|
+
fontWeight: 600,
|
|
10748
|
+
bgcolor: "brand.700",
|
|
10749
|
+
borderRadius: 1,
|
|
10750
|
+
px: 3,
|
|
10751
|
+
py: 1,
|
|
10752
|
+
mr: 2,
|
|
10753
|
+
cursor: "pointer",
|
|
10754
|
+
border: "none"
|
|
10755
|
+
},
|
|
10756
|
+
onClick: () => {
|
|
10757
|
+
setShowModal(true);
|
|
10758
|
+
},
|
|
10759
|
+
children: "Connect to Cloud"
|
|
10760
|
+
}), showModal && /* @__PURE__ */ jsx(AuthModal, {
|
|
10761
|
+
parentOpen: showModal,
|
|
10762
|
+
handleParentClose: setShowModal,
|
|
10763
|
+
ignoreCookie: true,
|
|
10764
|
+
variant: "user-profile"
|
|
10765
|
+
})] })] })
|
|
10766
|
+
]
|
|
10767
|
+
});
|
|
10768
|
+
}
|
|
10769
|
+
|
|
10770
|
+
//#endregion
|
|
10771
|
+
//#region recce-source/js/src/components/app/Filename.tsx
|
|
10772
|
+
const useRecceToast = () => {
|
|
10773
|
+
const toastSuccess = (message) => {
|
|
10774
|
+
toaster.create({
|
|
10775
|
+
description: message,
|
|
10776
|
+
type: "success",
|
|
10777
|
+
duration: 5e3,
|
|
10778
|
+
closable: true
|
|
10779
|
+
});
|
|
10780
|
+
};
|
|
10781
|
+
const toastError = (message, error) => {
|
|
10782
|
+
let errorMessage = message;
|
|
10783
|
+
if (error != null) if (error instanceof AxiosError) errorMessage = `${message}. ${String(error.response?.data?.detail)}`;
|
|
10784
|
+
else errorMessage = `${message}. ${error}`;
|
|
10785
|
+
toaster.create({
|
|
10786
|
+
description: errorMessage,
|
|
10787
|
+
type: "error",
|
|
10788
|
+
duration: 5e3,
|
|
10789
|
+
closable: true
|
|
10790
|
+
});
|
|
10791
|
+
};
|
|
10792
|
+
return {
|
|
10793
|
+
toastSuccess,
|
|
10794
|
+
toastError
|
|
10795
|
+
};
|
|
10796
|
+
};
|
|
10797
|
+
const useClosePrompt = (prompt) => {
|
|
10798
|
+
useEffect(() => {
|
|
10799
|
+
const handleBeforeUnload = (e) => {
|
|
10800
|
+
e.preventDefault();
|
|
10801
|
+
};
|
|
10802
|
+
if (prompt) window.addEventListener("beforeunload", handleBeforeUnload);
|
|
10803
|
+
return () => {
|
|
10804
|
+
if (prompt) window.removeEventListener("beforeunload", handleBeforeUnload);
|
|
10805
|
+
};
|
|
10806
|
+
}, [prompt]);
|
|
10807
|
+
};
|
|
10808
|
+
const Filename = () => {
|
|
10809
|
+
const { featureToggles } = useRecceInstanceContext();
|
|
10810
|
+
const { fileName, cloudMode, isDemoSite, envInfo } = useLineageGraphContext();
|
|
10811
|
+
const [modalOpen, setModalOpen] = useState(false);
|
|
10812
|
+
const [overwriteOpen, setOverwriteOpen] = useState(false);
|
|
10813
|
+
const isStateless = !fileName && !cloudMode && !isDemoSite;
|
|
10814
|
+
const { data: checks } = useChecks(isStateless);
|
|
10815
|
+
const hasNonPresetChecks = checks != void 0 && checks.filter((check) => !check.is_preset).length > 0;
|
|
10816
|
+
useClosePrompt(isStateless && hasNonPresetChecks);
|
|
10817
|
+
const [{ newFileName, errorMessage, modified, overwriteWithMethod, bypass }, setState] = useState({ newFileName: fileName ?? "recce_state.json" });
|
|
10818
|
+
const inputRef = useRef(null);
|
|
10819
|
+
const { toastSuccess, toastError } = useRecceToast();
|
|
10820
|
+
const queryClient = useQueryClient();
|
|
10821
|
+
const handleOpen = () => {
|
|
10822
|
+
setState({
|
|
10823
|
+
newFileName: fileName ?? "recce_state.json",
|
|
10824
|
+
modified: !fileName
|
|
10825
|
+
});
|
|
10826
|
+
setModalOpen(true);
|
|
10827
|
+
};
|
|
10828
|
+
const handleModalClose = () => setModalOpen(false);
|
|
10829
|
+
const handleOverwriteClose = () => setOverwriteOpen(false);
|
|
10830
|
+
const handleAction = async (method, overwrite) => {
|
|
10831
|
+
if (!newFileName) return;
|
|
10832
|
+
const bypassOverwrite = localStorage.getItem(localStorageKeys.bypassSaveOverwrite) === "true";
|
|
10833
|
+
try {
|
|
10834
|
+
if (method === "save") await saveAs$1({
|
|
10835
|
+
filename: newFileName,
|
|
10836
|
+
overwrite: overwrite ?? bypassOverwrite
|
|
10837
|
+
});
|
|
10838
|
+
else await rename({
|
|
10839
|
+
filename: newFileName,
|
|
10840
|
+
overwrite: overwrite ?? bypassOverwrite
|
|
10841
|
+
});
|
|
10842
|
+
toastSuccess(method === "save" ? "Save file successfully" : "Rename file successfully");
|
|
10843
|
+
await queryClient.invalidateQueries({ queryKey: cacheKeys.lineage() });
|
|
10844
|
+
if (bypass) localStorage.setItem(localStorageKeys.bypassSaveOverwrite, "true");
|
|
10845
|
+
} catch (error) {
|
|
10846
|
+
if (error instanceof AxiosError) {
|
|
10847
|
+
if (error.response?.status === 409) {
|
|
10848
|
+
setState((s) => ({
|
|
10849
|
+
...s,
|
|
10850
|
+
overwriteWithMethod: method
|
|
10851
|
+
}));
|
|
10852
|
+
setOverwriteOpen(true);
|
|
10853
|
+
return;
|
|
10854
|
+
}
|
|
10855
|
+
}
|
|
10856
|
+
toastError(method === "save" ? "Save file failed" : "Rename file failed", error);
|
|
10857
|
+
} finally {
|
|
10858
|
+
handleModalClose();
|
|
10859
|
+
}
|
|
10860
|
+
};
|
|
10861
|
+
const handleOvewriteBack = () => {
|
|
10862
|
+
handleOverwriteClose();
|
|
10863
|
+
setModalOpen(true);
|
|
10864
|
+
setState((s) => {
|
|
10865
|
+
return {
|
|
10866
|
+
...s,
|
|
10867
|
+
overwriteWithMethod: void 0
|
|
10868
|
+
};
|
|
10869
|
+
});
|
|
10870
|
+
};
|
|
10871
|
+
if (cloudMode || isDemoSite) return /* @__PURE__ */ jsx(Fragment$1, {});
|
|
10872
|
+
const titleNewInstance = "New Instance" + (hasNonPresetChecks ? " (unsaved)" : "");
|
|
10873
|
+
let titleReadOnlyState;
|
|
10874
|
+
if (featureToggles.disableSaveToFile && fileName) {
|
|
10875
|
+
const generatedAt = envInfo?.stateMetadata?.generated_at;
|
|
10876
|
+
const formattedDate = generatedAt ? formatRunDateTime(new Date(generatedAt)) : null;
|
|
10877
|
+
titleReadOnlyState = formattedDate ? `${fileName} (${formattedDate})` : null;
|
|
10878
|
+
}
|
|
10879
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
10880
|
+
/* @__PURE__ */ jsxs(Stack, {
|
|
10881
|
+
direction: "row",
|
|
10882
|
+
alignItems: "center",
|
|
10883
|
+
justifyContent: "center",
|
|
10884
|
+
children: [/* @__PURE__ */ jsx(Box, {
|
|
10885
|
+
sx: { fontWeight: 600 },
|
|
10886
|
+
children: titleReadOnlyState ?? fileName ?? titleNewInstance
|
|
10887
|
+
}), !featureToggles.disableSaveToFile && /* @__PURE__ */ jsx(MuiTooltip, {
|
|
10888
|
+
title: fileName ? "Change Filename" : "Save",
|
|
10889
|
+
enterDelay: 1e3,
|
|
10890
|
+
children: /* @__PURE__ */ jsx(IconButton, {
|
|
10891
|
+
onClick: handleOpen,
|
|
10892
|
+
"aria-label": fileName ? "Change Filename" : "Save",
|
|
10893
|
+
size: "small",
|
|
10894
|
+
children: /* @__PURE__ */ jsx(Box, {
|
|
10895
|
+
component: fileName ? IconEdit : IconSave,
|
|
10896
|
+
sx: {
|
|
10897
|
+
fontSize: 16,
|
|
10898
|
+
verticalAlign: "middle"
|
|
10899
|
+
}
|
|
10900
|
+
})
|
|
10901
|
+
})
|
|
10902
|
+
})]
|
|
10903
|
+
}),
|
|
10904
|
+
/* @__PURE__ */ jsxs(MuiDialog, {
|
|
10905
|
+
open: modalOpen,
|
|
10906
|
+
onClose: handleModalClose,
|
|
10907
|
+
children: [
|
|
10908
|
+
/* @__PURE__ */ jsxs(DialogTitle, {
|
|
10909
|
+
sx: {
|
|
10910
|
+
display: "flex",
|
|
10911
|
+
alignItems: "center"
|
|
10912
|
+
},
|
|
10913
|
+
children: [
|
|
10914
|
+
fileName ? "Change Filename" : "Save File",
|
|
10915
|
+
/* @__PURE__ */ jsx(Box, { sx: { flexGrow: 1 } }),
|
|
10916
|
+
/* @__PURE__ */ jsx(IconButton, {
|
|
10917
|
+
size: "small",
|
|
10918
|
+
onClick: handleModalClose,
|
|
10919
|
+
children: /* @__PURE__ */ jsx(IoClose, {})
|
|
10920
|
+
})
|
|
10921
|
+
]
|
|
10922
|
+
}),
|
|
10923
|
+
/* @__PURE__ */ jsx(DialogContent, {
|
|
10924
|
+
onKeyDown: (e) => {
|
|
10925
|
+
e.stopPropagation();
|
|
10926
|
+
},
|
|
10927
|
+
children: /* @__PURE__ */ jsx(TextField, {
|
|
10928
|
+
inputRef,
|
|
10929
|
+
value: newFileName,
|
|
10930
|
+
label: "File name",
|
|
10931
|
+
placeholder: "Enter filename",
|
|
10932
|
+
error: !!errorMessage,
|
|
10933
|
+
helperText: errorMessage,
|
|
10934
|
+
fullWidth: true,
|
|
10935
|
+
size: "small",
|
|
10936
|
+
sx: { mt: 1 },
|
|
10937
|
+
onChange: (e) => {
|
|
10938
|
+
const value = e.target.value;
|
|
10939
|
+
let newErrorMessage = void 0;
|
|
10940
|
+
if (!value) newErrorMessage = "Filename cannot be empty.";
|
|
10941
|
+
else if (!value.endsWith(".json")) newErrorMessage = "Filename must end with .json.";
|
|
10942
|
+
else if (!/^[a-zA-Z0-9 _-]+\.json$/.test(value)) newErrorMessage = "Invalid filename. Only alphanumeric, space, _ and - are allowed.";
|
|
10943
|
+
else if (fileName && value === fileName) newErrorMessage = "Filename is the same as the current one.";
|
|
10944
|
+
setState((s) => {
|
|
10945
|
+
return {
|
|
10946
|
+
...s,
|
|
10947
|
+
modified: true,
|
|
10948
|
+
newFileName: value,
|
|
10949
|
+
errorMessage: newErrorMessage
|
|
10950
|
+
};
|
|
10951
|
+
});
|
|
10952
|
+
},
|
|
10953
|
+
onKeyDown: (e) => {
|
|
10954
|
+
if (e.key === "Enter") {
|
|
10955
|
+
if (errorMessage) return;
|
|
10956
|
+
if (!fileName) handleAction("save");
|
|
10957
|
+
else handleAction("rename");
|
|
10958
|
+
} else if (e.key === "Escape") handleModalClose();
|
|
10959
|
+
}
|
|
10960
|
+
})
|
|
10961
|
+
}),
|
|
10962
|
+
/* @__PURE__ */ jsxs(DialogActions, {
|
|
10963
|
+
sx: { gap: "5px" },
|
|
10964
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
10965
|
+
size: "small",
|
|
10966
|
+
color: fileName ? "inherit" : "iochmara",
|
|
10967
|
+
variant: "contained",
|
|
10968
|
+
onClick: async () => {
|
|
10969
|
+
await handleAction("save");
|
|
10970
|
+
},
|
|
10971
|
+
disabled: !newFileName || !!errorMessage || !modified,
|
|
10972
|
+
children: fileName ? "Save as New File" : "Confirm"
|
|
10973
|
+
}), fileName && /* @__PURE__ */ jsx(Button, {
|
|
10974
|
+
size: "small",
|
|
10975
|
+
color: "iochmara",
|
|
10976
|
+
variant: "contained",
|
|
10977
|
+
onClick: async () => {
|
|
10978
|
+
await handleAction("rename");
|
|
10979
|
+
},
|
|
10980
|
+
disabled: !newFileName || !!errorMessage || !modified,
|
|
10981
|
+
children: "Rename"
|
|
10982
|
+
})]
|
|
10983
|
+
})
|
|
10984
|
+
]
|
|
10985
|
+
}),
|
|
10986
|
+
/* @__PURE__ */ jsxs(MuiDialog, {
|
|
10987
|
+
open: overwriteOpen,
|
|
10988
|
+
onClose: handleOverwriteClose,
|
|
10989
|
+
children: [
|
|
10990
|
+
/* @__PURE__ */ jsxs(DialogTitle, {
|
|
10991
|
+
sx: {
|
|
10992
|
+
display: "flex",
|
|
10993
|
+
alignItems: "center"
|
|
10994
|
+
},
|
|
10995
|
+
children: [
|
|
10996
|
+
"Overwrite File?",
|
|
10997
|
+
/* @__PURE__ */ jsx(Box, { sx: { flexGrow: 1 } }),
|
|
10998
|
+
/* @__PURE__ */ jsx(IconButton, {
|
|
10999
|
+
size: "small",
|
|
11000
|
+
onClick: handleOverwriteClose,
|
|
11001
|
+
children: /* @__PURE__ */ jsx(IoClose, {})
|
|
11002
|
+
})
|
|
11003
|
+
]
|
|
11004
|
+
}),
|
|
11005
|
+
/* @__PURE__ */ jsxs(DialogContent, {
|
|
11006
|
+
sx: {
|
|
11007
|
+
borderTop: "solid 1px",
|
|
11008
|
+
borderBottom: "solid 1px",
|
|
11009
|
+
borderColor: "divider"
|
|
11010
|
+
},
|
|
11011
|
+
onKeyDown: (e) => {
|
|
11012
|
+
e.stopPropagation();
|
|
11013
|
+
},
|
|
11014
|
+
children: [/* @__PURE__ */ jsx(Typography, {
|
|
11015
|
+
sx: { fontSize: "12pt" },
|
|
11016
|
+
children: overwriteWithMethod === "save" ? "Saving a file with this name will overwrite the existing file. Are you sure you wish to continue?" : "Renaming the file with this name will overwrite the existing file. Are you sure you wish to continue?"
|
|
11017
|
+
}), /* @__PURE__ */ jsx(FormControlLabel, {
|
|
11018
|
+
control: /* @__PURE__ */ jsx(Checkbox, {
|
|
11019
|
+
size: "small",
|
|
11020
|
+
checked: bypass,
|
|
11021
|
+
onChange: (e) => {
|
|
11022
|
+
setState((s) => ({
|
|
11023
|
+
...s,
|
|
11024
|
+
bypass: e.target.checked
|
|
11025
|
+
}));
|
|
11026
|
+
}
|
|
11027
|
+
}),
|
|
11028
|
+
label: /* @__PURE__ */ jsx(Typography, {
|
|
11029
|
+
sx: {
|
|
11030
|
+
fontWeight: "bold",
|
|
11031
|
+
pt: "8px"
|
|
11032
|
+
},
|
|
11033
|
+
children: "Don't show this again"
|
|
11034
|
+
})
|
|
11035
|
+
})]
|
|
11036
|
+
}),
|
|
11037
|
+
/* @__PURE__ */ jsxs(DialogActions, {
|
|
11038
|
+
sx: { gap: "5px" },
|
|
11039
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
11040
|
+
variant: "outlined",
|
|
11041
|
+
onClick: handleOvewriteBack,
|
|
11042
|
+
size: "small",
|
|
11043
|
+
children: "Back"
|
|
11044
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
11045
|
+
size: "small",
|
|
11046
|
+
color: "iochmara",
|
|
11047
|
+
variant: "contained",
|
|
11048
|
+
onClick: () => {
|
|
11049
|
+
if (!overwriteWithMethod) return;
|
|
11050
|
+
handleAction(overwriteWithMethod, true);
|
|
11051
|
+
handleOverwriteClose();
|
|
11052
|
+
},
|
|
11053
|
+
children: "Overwrite"
|
|
11054
|
+
})]
|
|
11055
|
+
})
|
|
11056
|
+
]
|
|
11057
|
+
})
|
|
11058
|
+
] });
|
|
11059
|
+
};
|
|
11060
|
+
|
|
11061
|
+
//#endregion
|
|
11062
|
+
//#region recce-source/js/src/components/app/StateExporter.tsx
|
|
11063
|
+
function StateExporter() {
|
|
11064
|
+
const { featureToggles } = useRecceInstanceContext();
|
|
11065
|
+
const handleExport = async () => {
|
|
11066
|
+
try {
|
|
11067
|
+
const jsonData = await exportState();
|
|
11068
|
+
const jsonString = JSON.stringify(jsonData, null, 2);
|
|
11069
|
+
saveAs(new Blob([jsonString], { type: "application/json" }), `recce-state-${format(/* @__PURE__ */ new Date(), "yyyy-MM-dd-HH-mm-ss")}.json`);
|
|
11070
|
+
} catch (error) {
|
|
11071
|
+
console.error("Export failed", error);
|
|
11072
|
+
toaster.create({
|
|
11073
|
+
title: "Export failed",
|
|
11074
|
+
description: String(error),
|
|
11075
|
+
type: "error",
|
|
11076
|
+
duration: 5e3,
|
|
11077
|
+
closable: true
|
|
11078
|
+
});
|
|
11079
|
+
}
|
|
11080
|
+
};
|
|
11081
|
+
return /* @__PURE__ */ jsx(MuiTooltip, {
|
|
11082
|
+
title: "Export",
|
|
11083
|
+
children: /* @__PURE__ */ jsx(IconButton, {
|
|
11084
|
+
size: "small",
|
|
11085
|
+
"aria-label": "Export state",
|
|
11086
|
+
onClick: async () => {
|
|
11087
|
+
await handleExport();
|
|
11088
|
+
trackStateAction({ name: "export" });
|
|
11089
|
+
},
|
|
11090
|
+
disabled: featureToggles.disableExportStateFile,
|
|
11091
|
+
children: /* @__PURE__ */ jsx(Box, {
|
|
11092
|
+
component: IconExport,
|
|
11093
|
+
sx: {
|
|
11094
|
+
verticalAlign: "middle",
|
|
11095
|
+
width: "16px",
|
|
11096
|
+
height: "16px"
|
|
11097
|
+
}
|
|
11098
|
+
})
|
|
11099
|
+
})
|
|
11100
|
+
});
|
|
11101
|
+
}
|
|
11102
|
+
|
|
11103
|
+
//#endregion
|
|
11104
|
+
//#region recce-source/js/src/components/app/StateSharing.tsx
|
|
11105
|
+
const LOADING_MESSAGES = [
|
|
11106
|
+
"Processing...",
|
|
11107
|
+
"Still processing, please wait...",
|
|
11108
|
+
"Almost there, thanks for your patience..."
|
|
11109
|
+
];
|
|
11110
|
+
function TopLevelShare() {
|
|
11111
|
+
const { successToast, failToast } = useClipBoardToast();
|
|
11112
|
+
const [, copyToClipboard] = useCopyToClipboard();
|
|
11113
|
+
const { authed } = useRecceInstanceContext();
|
|
11114
|
+
const { shareUrl, isLoading, error, handleShareClick } = useRecceShareStateContext();
|
|
11115
|
+
const [showModal, setShowModal] = useState(false);
|
|
11116
|
+
const [messageIndex, setMessageIndex] = useState(0);
|
|
11117
|
+
const [prevIsLoading, setPrevIsLoading] = useState(isLoading);
|
|
11118
|
+
if (isLoading !== prevIsLoading) {
|
|
11119
|
+
setPrevIsLoading(isLoading);
|
|
11120
|
+
if (isLoading) setMessageIndex(0);
|
|
11121
|
+
}
|
|
11122
|
+
useInterval(() => {
|
|
11123
|
+
setMessageIndex((prev) => Math.min(prev + 1, LOADING_MESSAGES.length - 1));
|
|
11124
|
+
}, isLoading ? 3e4 : null);
|
|
11125
|
+
useEffect(() => {
|
|
11126
|
+
if (error) failToast("Failed to share state", error);
|
|
11127
|
+
}, [error, failToast]);
|
|
11128
|
+
const handleCopy = async () => {
|
|
11129
|
+
try {
|
|
11130
|
+
await copyToClipboard(String(shareUrl));
|
|
11131
|
+
successToast("Copied the link to clipboard");
|
|
11132
|
+
} catch (error$1) {
|
|
11133
|
+
failToast("Failed to copy the link", error$1);
|
|
11134
|
+
}
|
|
11135
|
+
};
|
|
11136
|
+
if (!authed) return /* @__PURE__ */ jsxs(Stack, {
|
|
11137
|
+
direction: "row",
|
|
11138
|
+
sx: {
|
|
11139
|
+
flex: 1,
|
|
11140
|
+
alignItems: "center"
|
|
11141
|
+
},
|
|
11142
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
11143
|
+
size: "xsmall",
|
|
11144
|
+
color: "neutral",
|
|
11145
|
+
variant: "outlined",
|
|
11146
|
+
onClick: () => {
|
|
11147
|
+
setShowModal(true);
|
|
11148
|
+
},
|
|
11149
|
+
startIcon: /* @__PURE__ */ jsx(TbCloudUpload, {}),
|
|
11150
|
+
children: "Share"
|
|
11151
|
+
}), showModal && /* @__PURE__ */ jsx(AuthModal, {
|
|
11152
|
+
parentOpen: showModal,
|
|
11153
|
+
handleParentClose: setShowModal,
|
|
11154
|
+
ignoreCookie: true,
|
|
11155
|
+
variant: "enable-share"
|
|
11156
|
+
})]
|
|
11157
|
+
});
|
|
11158
|
+
return /* @__PURE__ */ jsxs(Stack, {
|
|
11159
|
+
direction: "row",
|
|
11160
|
+
sx: {
|
|
11161
|
+
flex: 1,
|
|
11162
|
+
alignItems: "center",
|
|
11163
|
+
gap: "5px"
|
|
11164
|
+
},
|
|
11165
|
+
children: [
|
|
11166
|
+
/* @__PURE__ */ jsx(Button, {
|
|
11167
|
+
size: "xsmall",
|
|
11168
|
+
variant: "outlined",
|
|
11169
|
+
color: "neutral",
|
|
11170
|
+
startIcon: /* @__PURE__ */ jsx(TbCloudUpload, {}),
|
|
11171
|
+
endIcon: shareUrl ? /* @__PURE__ */ jsx(Box, {
|
|
11172
|
+
component: PiCheckCircle,
|
|
11173
|
+
sx: { color: "success.main" }
|
|
11174
|
+
}) : void 0,
|
|
11175
|
+
onClick: async () => {
|
|
11176
|
+
await handleShareClick();
|
|
11177
|
+
trackShareState({ name: "create" });
|
|
11178
|
+
},
|
|
11179
|
+
disabled: isLoading,
|
|
11180
|
+
children: isLoading ? "Sharing..." : "Share"
|
|
11181
|
+
}),
|
|
11182
|
+
isLoading && /* @__PURE__ */ jsx(Typography, {
|
|
11183
|
+
sx: {
|
|
11184
|
+
fontSize: 14,
|
|
11185
|
+
color: "grey.500"
|
|
11186
|
+
},
|
|
11187
|
+
children: LOADING_MESSAGES[messageIndex]
|
|
11188
|
+
}),
|
|
11189
|
+
/* @__PURE__ */ jsx(Stack, {
|
|
11190
|
+
direction: "row",
|
|
11191
|
+
spacing: .5,
|
|
11192
|
+
alignItems: "center",
|
|
11193
|
+
children: shareUrl && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Box, {
|
|
11194
|
+
sx: {
|
|
11195
|
+
overflowX: "auto",
|
|
11196
|
+
whiteSpace: "nowrap",
|
|
11197
|
+
maxWidth: "350px"
|
|
11198
|
+
},
|
|
11199
|
+
children: /* @__PURE__ */ jsx(Typography, {
|
|
11200
|
+
sx: { fontSize: 14 },
|
|
11201
|
+
children: shareUrl
|
|
11202
|
+
})
|
|
11203
|
+
}), /* @__PURE__ */ jsx(IconButton, {
|
|
11204
|
+
size: "small",
|
|
11205
|
+
"aria-label": "Copy the share URL",
|
|
11206
|
+
onClick: async () => {
|
|
11207
|
+
await handleCopy();
|
|
11208
|
+
trackShareState({ name: "copy" });
|
|
11209
|
+
},
|
|
11210
|
+
children: /* @__PURE__ */ jsx(PiCopy, {})
|
|
11211
|
+
})] })
|
|
11212
|
+
})
|
|
11213
|
+
]
|
|
11214
|
+
});
|
|
11215
|
+
}
|
|
11216
|
+
|
|
11217
|
+
//#endregion
|
|
11218
|
+
//#region recce-source/js/src/components/app/StateSynchronizer.tsx
|
|
11219
|
+
function isCheckDetailPage(href) {
|
|
11220
|
+
return /^\/checks\/([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$/.test(href);
|
|
11221
|
+
}
|
|
11222
|
+
function StateSpinner() {
|
|
11223
|
+
return /* @__PURE__ */ jsx(MuiTooltip, {
|
|
11224
|
+
title: "Syncing",
|
|
11225
|
+
children: /* @__PURE__ */ jsx(Box, {
|
|
11226
|
+
sx: { mx: "10px" },
|
|
11227
|
+
children: /* @__PURE__ */ jsx(CircularProgress, { size: 20 })
|
|
11228
|
+
})
|
|
11229
|
+
});
|
|
11230
|
+
}
|
|
11231
|
+
function StateSynchronizer() {
|
|
11232
|
+
const [isSyncing, setSyncing] = useState(false);
|
|
11233
|
+
const queryClient = useQueryClient();
|
|
11234
|
+
const [location, setLocation] = useAppLocation();
|
|
11235
|
+
const [open, setOpen] = useState(false);
|
|
11236
|
+
const [syncOption, setSyncOption] = useState("");
|
|
11237
|
+
const { data: instanceInfo } = useRecceInstanceInfo();
|
|
11238
|
+
const handleClose = () => setOpen(false);
|
|
11239
|
+
const handleSync = useCallback(async (input) => {
|
|
11240
|
+
setOpen(false);
|
|
11241
|
+
setSyncing(true);
|
|
11242
|
+
if ((await syncState(input)).status === "conflict") {
|
|
11243
|
+
setOpen(true);
|
|
11244
|
+
setSyncing(false);
|
|
11245
|
+
return;
|
|
11246
|
+
}
|
|
11247
|
+
while (await isStateSyncing()) await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
11248
|
+
toaster.create({
|
|
11249
|
+
description: "Sync Completed",
|
|
11250
|
+
type: "success",
|
|
11251
|
+
duration: 5e3,
|
|
11252
|
+
closable: true
|
|
11253
|
+
});
|
|
11254
|
+
setSyncing(false);
|
|
11255
|
+
setSyncOption("");
|
|
11256
|
+
await queryClient.invalidateQueries({ queryKey: cacheKeys.lineage() });
|
|
11257
|
+
await queryClient.invalidateQueries({ queryKey: cacheKeys.checks() });
|
|
11258
|
+
await queryClient.invalidateQueries({ queryKey: cacheKeys.runs() });
|
|
11259
|
+
if (isCheckDetailPage(location)) setLocation("/checks");
|
|
11260
|
+
}, [
|
|
11261
|
+
queryClient,
|
|
11262
|
+
location,
|
|
11263
|
+
setLocation
|
|
11264
|
+
]);
|
|
11265
|
+
if (isSyncing) return /* @__PURE__ */ jsx(StateSpinner, {});
|
|
11266
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(MuiTooltip, {
|
|
11267
|
+
title: "Sync with Cloud",
|
|
11268
|
+
children: /* @__PURE__ */ jsx(IconButton, {
|
|
11269
|
+
size: "small",
|
|
11270
|
+
"aria-label": "Sync state",
|
|
11271
|
+
onClick: () => handleSync(instanceInfo?.session_id ? { method: "merge" } : {}),
|
|
11272
|
+
children: /* @__PURE__ */ jsx(Box, {
|
|
11273
|
+
component: IconSync,
|
|
11274
|
+
sx: {
|
|
11275
|
+
fontSize: 16,
|
|
11276
|
+
verticalAlign: "middle"
|
|
11277
|
+
}
|
|
11278
|
+
})
|
|
11279
|
+
})
|
|
11280
|
+
}), /* @__PURE__ */ jsxs(MuiDialog, {
|
|
11281
|
+
open,
|
|
11282
|
+
onClose: handleClose,
|
|
11283
|
+
children: [
|
|
11284
|
+
/* @__PURE__ */ jsxs(DialogTitle, {
|
|
11285
|
+
sx: {
|
|
11286
|
+
display: "flex",
|
|
11287
|
+
alignItems: "center",
|
|
11288
|
+
fontWeight: "bold"
|
|
11289
|
+
},
|
|
11290
|
+
children: [
|
|
11291
|
+
"Sync with Cloud",
|
|
11292
|
+
/* @__PURE__ */ jsx(Box, { sx: { flexGrow: 1 } }),
|
|
11293
|
+
/* @__PURE__ */ jsx(IconButton, {
|
|
11294
|
+
size: "small",
|
|
11295
|
+
onClick: handleClose,
|
|
11296
|
+
children: /* @__PURE__ */ jsx(IoClose, {})
|
|
11297
|
+
})
|
|
11298
|
+
]
|
|
11299
|
+
}),
|
|
11300
|
+
/* @__PURE__ */ jsxs(DialogContent, { children: [/* @__PURE__ */ jsx(Typography, { children: "New changes have been detected in the cloud. Please choose a method to sync your state" }), /* @__PURE__ */ jsx(Box, {
|
|
11301
|
+
sx: { mt: "5px" },
|
|
11302
|
+
children: /* @__PURE__ */ jsx(RadioGroup, {
|
|
11303
|
+
value: syncOption,
|
|
11304
|
+
onChange: (e) => {
|
|
11305
|
+
setSyncOption(e.target.value);
|
|
11306
|
+
},
|
|
11307
|
+
children: /* @__PURE__ */ jsxs(Stack, {
|
|
11308
|
+
direction: "column",
|
|
11309
|
+
children: [
|
|
11310
|
+
/* @__PURE__ */ jsx(FormControlLabel, {
|
|
11311
|
+
value: "merge",
|
|
11312
|
+
control: /* @__PURE__ */ jsx(Radio, {}),
|
|
11313
|
+
label: /* @__PURE__ */ jsxs(Stack, {
|
|
11314
|
+
direction: "row",
|
|
11315
|
+
alignItems: "center",
|
|
11316
|
+
children: ["Merge", /* @__PURE__ */ jsx(MuiTooltip, {
|
|
11317
|
+
title: "This will merge the local and remote states.",
|
|
11318
|
+
children: /* @__PURE__ */ jsx(Box, {
|
|
11319
|
+
component: PiInfo,
|
|
11320
|
+
sx: {
|
|
11321
|
+
ml: 2,
|
|
11322
|
+
cursor: "pointer"
|
|
11323
|
+
}
|
|
11324
|
+
})
|
|
11325
|
+
})]
|
|
11326
|
+
})
|
|
11327
|
+
}),
|
|
11328
|
+
/* @__PURE__ */ jsx(FormControlLabel, {
|
|
11329
|
+
value: "overwrite",
|
|
11330
|
+
control: /* @__PURE__ */ jsx(Radio, {}),
|
|
11331
|
+
label: /* @__PURE__ */ jsxs(Stack, {
|
|
11332
|
+
direction: "row",
|
|
11333
|
+
alignItems: "center",
|
|
11334
|
+
children: ["Overwrite", /* @__PURE__ */ jsx(MuiTooltip, {
|
|
11335
|
+
title: "This will overwrite the remote state file with the local state.",
|
|
11336
|
+
children: /* @__PURE__ */ jsx(Box, {
|
|
11337
|
+
component: PiInfo,
|
|
11338
|
+
sx: {
|
|
11339
|
+
ml: 2,
|
|
11340
|
+
cursor: "pointer"
|
|
11341
|
+
}
|
|
11342
|
+
})
|
|
11343
|
+
})]
|
|
11344
|
+
})
|
|
11345
|
+
}),
|
|
11346
|
+
/* @__PURE__ */ jsx(FormControlLabel, {
|
|
11347
|
+
value: "revert",
|
|
11348
|
+
control: /* @__PURE__ */ jsx(Radio, {}),
|
|
11349
|
+
label: /* @__PURE__ */ jsxs(Stack, {
|
|
11350
|
+
direction: "row",
|
|
11351
|
+
alignItems: "center",
|
|
11352
|
+
children: ["Revert", /* @__PURE__ */ jsx(MuiTooltip, {
|
|
11353
|
+
title: "This will discard local changes and revert to the cloud state.",
|
|
11354
|
+
children: /* @__PURE__ */ jsx(Box, {
|
|
11355
|
+
component: PiInfo,
|
|
11356
|
+
sx: {
|
|
11357
|
+
ml: 2,
|
|
11358
|
+
cursor: "pointer"
|
|
11359
|
+
}
|
|
11360
|
+
})
|
|
11361
|
+
})]
|
|
11362
|
+
})
|
|
11363
|
+
})
|
|
11364
|
+
]
|
|
11365
|
+
})
|
|
11366
|
+
})
|
|
11367
|
+
})] }),
|
|
11368
|
+
/* @__PURE__ */ jsxs(DialogActions, { children: [/* @__PURE__ */ jsx(Button, {
|
|
11369
|
+
onClick: handleClose,
|
|
11370
|
+
sx: { mr: 1 },
|
|
11371
|
+
children: "Cancel"
|
|
11372
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
11373
|
+
color: "iochmara",
|
|
11374
|
+
variant: "contained",
|
|
11375
|
+
onClick: () => handleSync({ method: syncOption || void 0 }),
|
|
11376
|
+
disabled: !syncOption,
|
|
11377
|
+
children: "Sync"
|
|
11378
|
+
})] })
|
|
11379
|
+
]
|
|
11380
|
+
})] });
|
|
11381
|
+
}
|
|
11382
|
+
|
|
11383
|
+
//#endregion
|
|
11384
|
+
//#region recce-source/js/app/(mainComponents)/NavBar.tsx
|
|
11385
|
+
/**
|
|
11386
|
+
* Route configuration for tabs
|
|
11387
|
+
*/
|
|
11388
|
+
const ROUTE_CONFIG = [
|
|
11389
|
+
{
|
|
11390
|
+
path: "/lineage",
|
|
11391
|
+
name: "Lineage"
|
|
11392
|
+
},
|
|
11393
|
+
{
|
|
11394
|
+
path: "/query",
|
|
11395
|
+
name: "Query"
|
|
11396
|
+
},
|
|
11397
|
+
{
|
|
11398
|
+
path: "/checks",
|
|
11399
|
+
name: "Checklist"
|
|
11400
|
+
}
|
|
11401
|
+
];
|
|
11402
|
+
function TabBadge({ queryKey, fetchCallback, selectCallback }) {
|
|
11403
|
+
const { data: count, isLoading, error } = useQuery({
|
|
11404
|
+
queryKey,
|
|
11405
|
+
queryFn: fetchCallback,
|
|
11406
|
+
select: selectCallback
|
|
11407
|
+
});
|
|
11408
|
+
if (isLoading || error || count === 0) return /* @__PURE__ */ jsx(Fragment$1, {});
|
|
11409
|
+
return /* @__PURE__ */ jsx(Box, {
|
|
11410
|
+
bgcolor: "brand.main",
|
|
11411
|
+
display: "flex",
|
|
11412
|
+
justifyContent: "center",
|
|
11413
|
+
alignItems: "center",
|
|
11414
|
+
p: 1,
|
|
11415
|
+
borderRadius: "100%",
|
|
11416
|
+
color: "white",
|
|
11417
|
+
fontWeight: 700,
|
|
11418
|
+
fontSize: "0.75rem",
|
|
11419
|
+
children: /* @__PURE__ */ jsx("span", { children: count })
|
|
11420
|
+
});
|
|
11421
|
+
}
|
|
11422
|
+
function ChecklistBadge() {
|
|
11423
|
+
return /* @__PURE__ */ jsx(TabBadge, {
|
|
11424
|
+
queryKey: cacheKeys.checks(),
|
|
11425
|
+
fetchCallback: listChecks,
|
|
11426
|
+
selectCallback: (checks) => {
|
|
11427
|
+
return checks.filter((check) => !check.is_checked).length;
|
|
11428
|
+
}
|
|
11429
|
+
});
|
|
11430
|
+
}
|
|
11431
|
+
function NavBar() {
|
|
11432
|
+
const pathname = usePathname();
|
|
11433
|
+
const { isDemoSite, isLoading, cloudMode } = useLineageGraphContext();
|
|
11434
|
+
const { featureToggles } = useRecceInstanceContext();
|
|
11435
|
+
const { data: flag, isLoading: isFlagLoading } = useRecceServerFlag();
|
|
11436
|
+
const prevPathnameRef = useRef(null);
|
|
11437
|
+
useEffect(() => {
|
|
11438
|
+
if (prevPathnameRef.current && prevPathnameRef.current !== pathname) trackNavigation({
|
|
11439
|
+
from: prevPathnameRef.current,
|
|
11440
|
+
to: pathname
|
|
11441
|
+
});
|
|
11442
|
+
prevPathnameRef.current = pathname;
|
|
11443
|
+
}, [pathname]);
|
|
11444
|
+
return /* @__PURE__ */ jsx(Box, {
|
|
11445
|
+
sx: {
|
|
11446
|
+
borderBottom: "1px solid lightgray",
|
|
11447
|
+
px: "12px"
|
|
11448
|
+
},
|
|
11449
|
+
children: /* @__PURE__ */ jsxs(Box, {
|
|
11450
|
+
sx: {
|
|
11451
|
+
display: "grid",
|
|
11452
|
+
gridTemplateColumns: "1fr auto 1fr",
|
|
11453
|
+
width: "100%",
|
|
11454
|
+
alignItems: "center"
|
|
11455
|
+
},
|
|
11456
|
+
children: [
|
|
11457
|
+
/* @__PURE__ */ jsx(Tabs, {
|
|
11458
|
+
value: useMemo(() => {
|
|
11459
|
+
if (pathname.startsWith("/checks")) return "/checks";
|
|
11460
|
+
if (pathname.startsWith("/query")) return "/query";
|
|
11461
|
+
if (pathname.startsWith("/runs")) return "/runs";
|
|
11462
|
+
return "/lineage";
|
|
11463
|
+
}, [pathname]),
|
|
11464
|
+
sx: {
|
|
11465
|
+
borderBottom: "none",
|
|
11466
|
+
minHeight: "auto"
|
|
11467
|
+
},
|
|
11468
|
+
children: ROUTE_CONFIG.map(({ path, name }) => {
|
|
11469
|
+
if (name === "Query" && flag?.single_env_onboarding) return null;
|
|
11470
|
+
if (name === "Checklist" && ChecklistBadge) return /* @__PURE__ */ jsx(Tab, {
|
|
11471
|
+
value: path,
|
|
11472
|
+
disabled: isLoading || isFlagLoading,
|
|
11473
|
+
sx: { p: 0 },
|
|
11474
|
+
label: /* @__PURE__ */ jsx(Box, {
|
|
11475
|
+
sx: {
|
|
11476
|
+
display: "flex",
|
|
11477
|
+
alignItems: "center",
|
|
11478
|
+
gap: "4px"
|
|
11479
|
+
},
|
|
11480
|
+
children: /* @__PURE__ */ jsxs(NextLink, {
|
|
11481
|
+
href: path,
|
|
11482
|
+
style: {
|
|
11483
|
+
textDecoration: "none",
|
|
11484
|
+
color: "inherit",
|
|
11485
|
+
padding: "0.875rem 1.1875rem",
|
|
11486
|
+
display: "flex",
|
|
11487
|
+
gap: 3,
|
|
11488
|
+
alignItems: "center"
|
|
11489
|
+
},
|
|
11490
|
+
children: [
|
|
11491
|
+
name,
|
|
11492
|
+
" ",
|
|
11493
|
+
/* @__PURE__ */ jsx(ChecklistBadge, {})
|
|
11494
|
+
]
|
|
11495
|
+
})
|
|
11496
|
+
})
|
|
11497
|
+
}, path);
|
|
11498
|
+
return /* @__PURE__ */ jsx(Tab, {
|
|
11499
|
+
value: path,
|
|
11500
|
+
disabled: isLoading || isFlagLoading,
|
|
11501
|
+
sx: { p: 0 },
|
|
11502
|
+
label: /* @__PURE__ */ jsx(Box, {
|
|
11503
|
+
sx: {
|
|
11504
|
+
display: "flex",
|
|
11505
|
+
alignItems: "center",
|
|
11506
|
+
gap: "4px"
|
|
11507
|
+
},
|
|
11508
|
+
children: /* @__PURE__ */ jsx(NextLink, {
|
|
11509
|
+
href: path,
|
|
11510
|
+
style: {
|
|
11511
|
+
textDecoration: "none",
|
|
11512
|
+
color: "inherit",
|
|
11513
|
+
padding: "0.875rem 1.1875rem"
|
|
11514
|
+
},
|
|
11515
|
+
children: name
|
|
11516
|
+
})
|
|
11517
|
+
})
|
|
11518
|
+
}, path);
|
|
11519
|
+
})
|
|
11520
|
+
}),
|
|
11521
|
+
/* @__PURE__ */ jsxs(Box, {
|
|
11522
|
+
sx: {
|
|
11523
|
+
display: "flex",
|
|
11524
|
+
alignItems: "center",
|
|
11525
|
+
gap: "12px",
|
|
11526
|
+
justifyContent: "center"
|
|
11527
|
+
},
|
|
11528
|
+
children: [!isLoading && !isDemoSite && /* @__PURE__ */ jsx(Filename, {}), !isLoading && !isDemoSite && !flag?.single_env_onboarding && !featureToggles.disableShare && /* @__PURE__ */ jsx(TopLevelShare, {})]
|
|
11529
|
+
}),
|
|
11530
|
+
!isLoading && /* @__PURE__ */ jsxs(Box, {
|
|
11531
|
+
sx: {
|
|
11532
|
+
display: "flex",
|
|
11533
|
+
justifyContent: "right",
|
|
11534
|
+
alignItems: "center",
|
|
11535
|
+
mr: "8px"
|
|
11536
|
+
},
|
|
11537
|
+
children: [
|
|
11538
|
+
/* @__PURE__ */ jsx(EnvInfo, {}),
|
|
11539
|
+
cloudMode && /* @__PURE__ */ jsx(StateSynchronizer, {}),
|
|
11540
|
+
/* @__PURE__ */ jsx(StateExporter, {})
|
|
11541
|
+
]
|
|
11542
|
+
})
|
|
11543
|
+
]
|
|
11544
|
+
})
|
|
11545
|
+
});
|
|
11546
|
+
}
|
|
11547
|
+
|
|
11548
|
+
//#endregion
|
|
11549
|
+
//#region recce-source/js/app/(mainComponents)/DisplayModeToggle.tsx
|
|
11550
|
+
/**
|
|
11551
|
+
* Display Mode Toggle - switches between light and dark themes
|
|
11552
|
+
*
|
|
11553
|
+
* Uses next-themes to persist the user's preference.
|
|
11554
|
+
* Default is light theme, with future support for system preference.
|
|
11555
|
+
*/
|
|
11556
|
+
function DisplayModeToggle$1() {
|
|
11557
|
+
const { setTheme, resolvedTheme } = useTheme$1();
|
|
11558
|
+
const [mounted, setMounted] = useState(false);
|
|
11559
|
+
useEffect(() => {
|
|
11560
|
+
setMounted(true);
|
|
11561
|
+
}, []);
|
|
11562
|
+
const toggleTheme = () => {
|
|
11563
|
+
setTheme(resolvedTheme === "dark" ? "light" : "dark");
|
|
11564
|
+
};
|
|
11565
|
+
if (!mounted) return /* @__PURE__ */ jsx(IconButton, {
|
|
11566
|
+
size: "small",
|
|
11567
|
+
sx: {
|
|
11568
|
+
color: "rgba(255, 255, 255, 0.8)",
|
|
11569
|
+
"&:hover": { bgcolor: "rgba(255, 255, 255, 0.1)" }
|
|
11570
|
+
},
|
|
11571
|
+
disabled: true,
|
|
11572
|
+
children: /* @__PURE__ */ jsx(PiSun, { style: {
|
|
11573
|
+
width: 18,
|
|
11574
|
+
height: 18
|
|
11575
|
+
} })
|
|
11576
|
+
});
|
|
11577
|
+
const isDark = resolvedTheme === "dark";
|
|
11578
|
+
return /* @__PURE__ */ jsx(MuiTooltip, {
|
|
11579
|
+
title: isDark ? "Switch to light mode" : "Switch to dark mode",
|
|
11580
|
+
children: /* @__PURE__ */ jsx(IconButton, {
|
|
11581
|
+
size: "small",
|
|
11582
|
+
onClick: toggleTheme,
|
|
11583
|
+
sx: {
|
|
11584
|
+
color: "rgba(255, 255, 255, 0.8)",
|
|
11585
|
+
"&:hover": { bgcolor: "rgba(255, 255, 255, 0.1)" }
|
|
11586
|
+
},
|
|
11587
|
+
"aria-label": isDark ? "Switch to light mode" : "Switch to dark mode",
|
|
11588
|
+
children: isDark ? /* @__PURE__ */ jsx(PiSun, { style: {
|
|
11589
|
+
width: 18,
|
|
11590
|
+
height: 18
|
|
11591
|
+
} }) : /* @__PURE__ */ jsx(PiMoon, { style: {
|
|
11592
|
+
width: 18,
|
|
11593
|
+
height: 18
|
|
11594
|
+
} })
|
|
11595
|
+
})
|
|
11596
|
+
});
|
|
11597
|
+
}
|
|
11598
|
+
|
|
11599
|
+
//#endregion
|
|
11600
|
+
//#region recce-source/js/app/(mainComponents)/RecceVersionBadge.tsx
|
|
11601
|
+
function RecceVersionBadge$1() {
|
|
11602
|
+
const { version, latestVersion } = useVersionNumber();
|
|
11603
|
+
const versionFormatRegex = useMemo(() => /* @__PURE__ */ new RegExp("^\\d+\\.\\d+\\.\\d+$"), []);
|
|
11604
|
+
useEffect(() => {
|
|
11605
|
+
if (versionFormatRegex.test(version) && version !== latestVersion) {
|
|
11606
|
+
const storageKey = "recce-update-toast-shown";
|
|
11607
|
+
if (sessionStorage.getItem(storageKey)) return;
|
|
11608
|
+
setTimeout(() => {
|
|
11609
|
+
toaster.create({
|
|
11610
|
+
id: "recce-update-available",
|
|
11611
|
+
title: "Update available",
|
|
11612
|
+
description: /* @__PURE__ */ jsxs("span", { children: [
|
|
11613
|
+
"A new version of Recce (v",
|
|
11614
|
+
latestVersion,
|
|
11615
|
+
") is available.",
|
|
11616
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
11617
|
+
"Please run",
|
|
11618
|
+
" ",
|
|
11619
|
+
/* @__PURE__ */ jsx(Box, {
|
|
11620
|
+
component: "code",
|
|
11621
|
+
sx: {
|
|
11622
|
+
bgcolor: "grey.200",
|
|
11623
|
+
px: .5,
|
|
11624
|
+
py: .25,
|
|
11625
|
+
borderRadius: .5,
|
|
11626
|
+
fontFamily: "monospace",
|
|
11627
|
+
fontSize: "0.875em"
|
|
11628
|
+
},
|
|
11629
|
+
children: "pip install --upgrade recce"
|
|
11630
|
+
}),
|
|
11631
|
+
" ",
|
|
11632
|
+
"to update Recce.",
|
|
11633
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
11634
|
+
/* @__PURE__ */ jsx(Link, {
|
|
11635
|
+
sx: {
|
|
11636
|
+
color: "primary.main",
|
|
11637
|
+
fontWeight: "bold",
|
|
11638
|
+
"&:hover": { textDecoration: "underline" }
|
|
11639
|
+
},
|
|
11640
|
+
href: `https://github.com/DataRecce/recce/releases/tag/v${latestVersion}`,
|
|
11641
|
+
target: "_blank",
|
|
11642
|
+
children: "Click here to view the detail of latest release"
|
|
11643
|
+
})
|
|
11644
|
+
] }),
|
|
11645
|
+
duration: 60 * 1e3,
|
|
11646
|
+
closable: true
|
|
11647
|
+
});
|
|
11648
|
+
sessionStorage.setItem(storageKey, "true");
|
|
11649
|
+
}, 0);
|
|
11650
|
+
}
|
|
11651
|
+
}, [
|
|
11652
|
+
version,
|
|
11653
|
+
latestVersion,
|
|
11654
|
+
versionFormatRegex
|
|
11655
|
+
]);
|
|
11656
|
+
if (!versionFormatRegex.test(version)) return /* @__PURE__ */ jsx(Typography, {
|
|
11657
|
+
component: "span",
|
|
11658
|
+
sx: {
|
|
11659
|
+
fontSize: "sm",
|
|
11660
|
+
color: "rgba(255,255,255,0.8)",
|
|
11661
|
+
textTransform: "uppercase",
|
|
11662
|
+
borderWidth: 1,
|
|
11663
|
+
px: 1,
|
|
11664
|
+
borderRadius: .75
|
|
11665
|
+
},
|
|
11666
|
+
children: version
|
|
11667
|
+
});
|
|
11668
|
+
return /* @__PURE__ */ jsx(Link, {
|
|
11669
|
+
href: `https://github.com/DataRecce/recce/releases/tag/v${version}`,
|
|
11670
|
+
sx: {
|
|
11671
|
+
"&:hover": { textDecoration: "none" },
|
|
11672
|
+
fontSize: "sm",
|
|
11673
|
+
color: "rgba(255,255,255,0.8)",
|
|
11674
|
+
textTransform: "uppercase",
|
|
11675
|
+
borderWidth: 1,
|
|
11676
|
+
px: 1,
|
|
11677
|
+
borderRadius: .75
|
|
11678
|
+
},
|
|
11679
|
+
target: "_blank",
|
|
11680
|
+
children: version
|
|
11681
|
+
});
|
|
11682
|
+
}
|
|
11683
|
+
|
|
11684
|
+
//#endregion
|
|
11685
|
+
export { NodeSqlView as A, GraphEdge as B, NodeView as C, SqlEditor_default as D, RunStatusAndDate as E, HistoryToggle as F, MuiProvider as G, HSplit as H, GraphNode as I, mui_provider_default as K, ModelRowCount as L, CodeEditor_default as M, SchemaView as N, QueryForm as O, LineageViewTopBar as P, ResourceTypeTag as R, SetupConnectionBanner as S, RunView as T, VSplit as U, GraphColumnNode as V, ErrorBoundary$1 as W, CheckList as _, IdleTimeoutBadge as a, LineagePage as b, ChangeSummary as c, CheckEmptyState as d, CheckDetail as f, CheckBreadcrumb as g, CheckDescription as h, TopBar as i, DiffEditor_default as j, EnvInfo as k, RunList as l, LineageDiffView as m, DisplayModeToggle$1 as n, SummaryView as o, SchemaDiffView as p, NavBar as r, SchemaSummary as s, RecceVersionBadge$1 as t, RunPage as u, QueryPage as v, RunResultPane as w, LineageView as x, SetupConnectionGuide as y, RowCountDiffTag as z };
|
|
11686
|
+
//# sourceMappingURL=components-CfY72Lq2.mjs.map
|