@datarecce/ui 0.1.22 → 0.1.24
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-DNKi97uE.js → RecceCheckContext-Cb41gigE.js} +4 -3
- package/dist/RecceCheckContext-Cb41gigE.js.map +1 -0
- package/dist/{RecceCheckContext-BETsmiD5.mjs → RecceCheckContext-CzsuuXxT.mjs} +4 -3
- package/dist/RecceCheckContext-CzsuuXxT.mjs.map +1 -0
- package/dist/api.d.mts +2 -2
- package/dist/api.d.ts +2 -2
- package/dist/api.js +12 -37
- package/dist/api.mjs +3 -29
- package/dist/{components-C735_oqD.mjs → components-BHxcVq0D.mjs} +1353 -69
- package/dist/components-BHxcVq0D.mjs.map +1 -0
- package/dist/{components-DeA4kqxK.js → components-Bmc5X473.js} +1557 -248
- package/dist/components-Bmc5X473.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-Ba-AoxcK.mjs → hooks-B0XGswIh.mjs} +3 -3
- package/dist/{hooks-Ba-AoxcK.mjs.map → hooks-B0XGswIh.mjs.map} +1 -1
- package/dist/{hooks-D6xvNXEc.js → hooks-C99PZcmB.js} +3 -3
- package/dist/{hooks-D6xvNXEc.js.map → hooks-C99PZcmB.js.map} +1 -1
- package/dist/hooks.d.mts +2 -2
- package/dist/hooks.d.ts +2 -2
- package/dist/hooks.js +4 -3
- package/dist/hooks.mjs +4 -4
- package/dist/{index-Sj_wOmNH.d.mts → index-04n48ic2.d.mts} +129 -105
- package/dist/index-04n48ic2.d.mts.map +1 -0
- package/dist/{index-DYduBYD8.d.ts → index-CgyLTrll.d.ts} +129 -105
- package/dist/index-CgyLTrll.d.ts.map +1 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +20 -14
- package/dist/index.mjs +7 -7
- package/dist/{state-BjKRZMwY.js → state-Ct-DP81O.js} +108 -79
- package/dist/state-Ct-DP81O.js.map +1 -0
- package/dist/{state-BySLlIE7.mjs → state-CwepO01b.mjs} +91 -80
- package/dist/state-CwepO01b.mjs.map +1 -0
- package/dist/types.d.mts +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/{user-Dt_n5IJX.js → version-BgsW-hXj.js} +50 -10
- package/dist/version-BgsW-hXj.js.map +1 -0
- package/dist/version-Bz2CiMHD.mjs +93 -0
- package/dist/version-Bz2CiMHD.mjs.map +1 -0
- package/package.json +5 -4
- package/dist/RecceCheckContext-BETsmiD5.mjs.map +0 -1
- package/dist/RecceCheckContext-DNKi97uE.js.map +0 -1
- 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/state-BjKRZMwY.js.map +0 -1
- package/dist/state-BySLlIE7.mjs.map +0 -1
- package/dist/user-BHOgMaBf.mjs +0 -65
- 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
|
|
2
|
+
import { $t as trackLineageViewRender, At as createLineageDiffCheck, B as IconExport, Bn as darkTheme, Bt as submitRunFromCheck, Cn as selectUpstream, En as getCll, Et as ScreenshotDataGrid, Ft as cancelRun, G as deltaPercentageString, Gt as LINEAGE_SELECTION_ACTION, H as IconInfo, Hn as token, Ht as EXPLORE_ACTION, I as useRecceActionContext, J as mergeKeys, Jt as trackEnvironmentConfig, Kt as trackColumnLevelLineage, L as useAppLocation, Ln as toaster, Lt as listRuns, M as useLineageViewContext, Mn as axiosClient, Mt as submitQueryBase, N as useLineageViewContextSafe, Nt as submitQueryDiff, Qt as trackLineageSelection, Sn as selectDownstream, St as useApiConfig, Tn as union, Tt as EmptyRowsRenderer, U as IconSave, Vn as lightTheme, Vt as waitRun, W as IconSync, Wt as EXPLORE_SOURCE, Y as mergeKeysWithStatus, Yt as trackExploreAction, Zt as trackHistoryAction, _ as findByRunType, _n as isValueDiffRun, a as saveAs$1, an as trackSingleEnvironment, at as supportsHistogramDiff, bn as isLineageGraphNode, c as createCheckByRun, cn as isHistogramDiffRun, ct as useLineageGraphContext, d as getCheck, dn as isQueryDiffRun, en as trackMultiNodesAction, f as listChecks, fn as isQueryRun, ft as useIdleTimeout, g as useChecks, gn as isValueDiffDetailRun, gt as formatDuration, h as updateCheck, hn as isTopKDiffRun, i as rename, in as trackShareState, j as LineageViewContext, jt as submitQuery, k as createDataGridFromData, ln as isProfileDiffRun, lt as useRunsAggregated, mn as isRowCountRun, nn as trackPreviewChange, on as trackStateAction, ot as useModelColumns_default, p as markAsPresetCheck, pn as isRowCountDiffRun, q as useClipBoardToast, qt as trackCopyToClipboard, r as isStateSyncing, rn as trackPreviewChangeFeedback, s as syncState, t as exportState, tn as trackNavigation, u as deleteCheck, un as isQueryBaseRun, ut as useRecceServerFlag, v as runTypeHasRef, vn as COLUMN_HEIGHT, vt as useRecceInstanceContext, wn as toReactFlow, wt as cacheKeys, xn as layout, yn as isLineageGraphColumnNode, yt as useRecceInstanceInfo, z as IconEdit, zn as colors, zt as submitRun } from "./state-CwepO01b.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 connectToCloud, c as select, i as fetchUser, l as createSchemaDiffCheck, n as useVersionNumber, o as localStorageKeys, r as fetchGitHubAvatar, s as sessionStorageKeys } from "./version-Bz2CiMHD.mjs";
|
|
5
|
+
import { i as useValueDiffAlertDialog_default, l as defaultSqlQuery, n as useRecceCheckContext, o as useRecceShareStateContext, r as useCheckToast, u as useRecceQueryContext } from "./RecceCheckContext-CzsuuXxT.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";
|
|
@@ -19,7 +19,7 @@ import { ErrorBoundary, FallbackRender } from "@sentry/react";
|
|
|
19
19
|
import ReactSplit, { SplitProps } from "react-split";
|
|
20
20
|
import { Background, BackgroundVariant, BaseEdge, ControlButton, Controls, EdgeProps, Handle, MiniMap, Node, NodeProps, Panel, Position, ReactFlow, ReactFlowProvider, getBezierPath, getNodesBounds, useEdgesState, useNodesState, useReactFlow, useStore } from "@xyflow/react";
|
|
21
21
|
import Divider from "@mui/material/Divider";
|
|
22
|
-
import { AxiosError, AxiosResponse } from "axios";
|
|
22
|
+
import { AxiosError, AxiosInstance, AxiosResponse } from "axios";
|
|
23
23
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
24
24
|
import "@xyflow/react/dist/style.css";
|
|
25
25
|
import { FiArrowRight, FiCopy, FiFrown, FiInfo, FiPackage } from "react-icons/fi";
|
|
@@ -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";
|
|
@@ -223,7 +226,7 @@ const getHTMLElementFromRef = (refCurrent) => {
|
|
|
223
226
|
};
|
|
224
227
|
const IGNORE_SCREENSHOT_CLASS = "ignore-screenshot";
|
|
225
228
|
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 }) {
|
|
229
|
+
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
230
|
const [status, setStatus] = useState("idle");
|
|
228
231
|
const ref = useRef(null);
|
|
229
232
|
const { onOpen, setImgBlob, ImageDownloadModal } = useImageDownloadModal();
|
|
@@ -324,7 +327,7 @@ function useCopyToClipboard({ renderLibrary = "html2canvas", imageType = "png",
|
|
|
324
327
|
}
|
|
325
328
|
function useCopyToClipboardButton(options) {
|
|
326
329
|
const { successToast, failToast } = useClipBoardToast();
|
|
327
|
-
const { isLoading, copyToClipboard, ImageDownloadModal, ref } = useCopyToClipboard({
|
|
330
|
+
const { isLoading, copyToClipboard, ImageDownloadModal, ref } = useCopyToClipboard$1({
|
|
328
331
|
imageType: "png",
|
|
329
332
|
shadowEffect: true,
|
|
330
333
|
backgroundColor: options?.backgroundColor ?? colors.neutral[100],
|
|
@@ -478,13 +481,14 @@ function useImageDownloadModal() {
|
|
|
478
481
|
//#endregion
|
|
479
482
|
//#region recce-source/js/src/lib/hooks/useRun.tsx
|
|
480
483
|
const useRun = (runId) => {
|
|
484
|
+
const { apiClient } = useApiConfig();
|
|
481
485
|
const [isRunning, setIsRunning] = useState(false);
|
|
482
486
|
const [aborting, setAborting] = useState(false);
|
|
483
487
|
const [, refetchRunsAggregated] = useRunsAggregated();
|
|
484
488
|
const { error, data: run } = useQuery({
|
|
485
489
|
queryKey: cacheKeys.run(runId ?? ""),
|
|
486
490
|
queryFn: async () => {
|
|
487
|
-
return await waitRun(runId ?? "", isRunning ? 2 : 0);
|
|
491
|
+
return await waitRun(runId ?? "", isRunning ? 2 : 0, apiClient);
|
|
488
492
|
},
|
|
489
493
|
enabled: !!runId,
|
|
490
494
|
refetchInterval: isRunning ? 50 : false,
|
|
@@ -508,8 +512,8 @@ const useRun = (runId) => {
|
|
|
508
512
|
const onCancel = useCallback(async () => {
|
|
509
513
|
setAborting(true);
|
|
510
514
|
if (!runId) return;
|
|
511
|
-
await cancelRun(runId);
|
|
512
|
-
}, [runId]);
|
|
515
|
+
await cancelRun(runId, apiClient);
|
|
516
|
+
}, [runId, apiClient]);
|
|
513
517
|
let RunResultView;
|
|
514
518
|
if (run && runTypeHasRef(run.type)) RunResultView = findByRunType(run.type).RunResultView;
|
|
515
519
|
return {
|
|
@@ -4247,6 +4251,7 @@ const QueryForm = ({ defaultPrimaryKeys, onPrimaryKeysChange, ...props }) => {
|
|
|
4247
4251
|
//#region recce-source/js/src/components/AuthModal/AuthModal.tsx
|
|
4248
4252
|
function AuthModal({ handleParentClose, parentOpen = false, ignoreCookie = false, variant = "auth" }) {
|
|
4249
4253
|
const { authed } = useRecceInstanceContext();
|
|
4254
|
+
const { apiClient } = useApiConfig();
|
|
4250
4255
|
const [open, setOpen] = useState(parentOpen || !authed);
|
|
4251
4256
|
const authStateCookieValue = Cookies.get("authState") ?? "pending";
|
|
4252
4257
|
const [authState, setAuthState] = useState(ignoreCookie ? "pending" : authStateCookieValue);
|
|
@@ -4329,7 +4334,7 @@ function AuthModal({ handleParentClose, parentOpen = false, ignoreCookie = false
|
|
|
4329
4334
|
},
|
|
4330
4335
|
onClick: async () => {
|
|
4331
4336
|
setAuthState("authenticating");
|
|
4332
|
-
const { connection_url } = await connectToCloud();
|
|
4337
|
+
const { connection_url } = await connectToCloud(apiClient);
|
|
4333
4338
|
window.open(connection_url, "_blank");
|
|
4334
4339
|
},
|
|
4335
4340
|
children: [
|
|
@@ -5015,6 +5020,7 @@ function AddToCheckButton({ runId, viewOptions }) {
|
|
|
5015
5020
|
const { error, run } = useRun(runId);
|
|
5016
5021
|
const queryClient = useQueryClient();
|
|
5017
5022
|
const [, setLocation] = useAppLocation();
|
|
5023
|
+
const { apiClient } = useApiConfig();
|
|
5018
5024
|
const checkId = run?.check_id;
|
|
5019
5025
|
const handleGoToCheck = useCallback(() => {
|
|
5020
5026
|
if (!checkId) return;
|
|
@@ -5022,14 +5028,15 @@ function AddToCheckButton({ runId, viewOptions }) {
|
|
|
5022
5028
|
}, [checkId, setLocation]);
|
|
5023
5029
|
const handleAddToChecklist = useCallback(async () => {
|
|
5024
5030
|
if (!runId) return;
|
|
5025
|
-
const check = await createCheckByRun(runId, viewOptions);
|
|
5031
|
+
const check = await createCheckByRun(runId, viewOptions, apiClient);
|
|
5026
5032
|
await queryClient.invalidateQueries({ queryKey: cacheKeys.checks() });
|
|
5027
5033
|
setLocation(`/checks/?id=${check.check_id}`);
|
|
5028
5034
|
}, [
|
|
5029
5035
|
runId,
|
|
5030
5036
|
setLocation,
|
|
5031
5037
|
queryClient,
|
|
5032
|
-
viewOptions
|
|
5038
|
+
viewOptions,
|
|
5039
|
+
apiClient
|
|
5033
5040
|
]);
|
|
5034
5041
|
if (featureToggles.disableUpdateChecklist) return /* @__PURE__ */ jsx(Fragment$1, {});
|
|
5035
5042
|
if (run?.check_id) return /* @__PURE__ */ jsx(Button, {
|
|
@@ -5187,15 +5194,16 @@ function SandboxView({ isOpen, onClose, current }) {
|
|
|
5187
5194
|
const { showRunId, clearRunResult } = useRecceActionContext();
|
|
5188
5195
|
const { primaryKeys, setPrimaryKeys } = useRecceQueryContext();
|
|
5189
5196
|
const { data: flags, isLoading } = useRecceServerFlag();
|
|
5197
|
+
const { apiClient } = useApiConfig();
|
|
5190
5198
|
const queryFn = async () => {
|
|
5191
5199
|
const sqlTemplate = modifiedCode;
|
|
5192
5200
|
const { run_id } = await submitQueryDiff({
|
|
5193
5201
|
current_model: current?.name ?? "",
|
|
5194
5202
|
primary_keys: primaryKeys,
|
|
5195
5203
|
sql_template: sqlTemplate
|
|
5196
|
-
}, { nowait: true });
|
|
5204
|
+
}, { nowait: true }, apiClient);
|
|
5197
5205
|
showRunId(run_id);
|
|
5198
|
-
return await waitRun(run_id);
|
|
5206
|
+
return await waitRun(run_id, void 0, apiClient);
|
|
5199
5207
|
};
|
|
5200
5208
|
const { mutate: runQuery, isPending } = useMutation({
|
|
5201
5209
|
mutationFn: queryFn,
|
|
@@ -5673,12 +5681,17 @@ function ExploreChangeMenuButton({ node, baseColumns, currentColumns, disableRea
|
|
|
5673
5681
|
const { envInfo, isActionAvailable } = useLineageGraphContext();
|
|
5674
5682
|
const { featureToggles } = useRecceInstanceContext();
|
|
5675
5683
|
const { primaryKey } = useModelColumns_default(node.data.name);
|
|
5684
|
+
const { apiClient } = useApiConfig();
|
|
5676
5685
|
const metadataOnly = featureToggles.mode === "metadata only";
|
|
5677
5686
|
const isAddedOrRemoved = node.data.changeStatus === "added" || node.data.changeStatus === "removed";
|
|
5678
5687
|
const addSchemaCheck = useCallback(async () => {
|
|
5679
5688
|
const nodeId = node.id;
|
|
5680
|
-
setLocation(`/checks/?id=${(await createSchemaDiffCheck({ node_id: nodeId })).check_id}`);
|
|
5681
|
-
}, [
|
|
5689
|
+
setLocation(`/checks/?id=${(await createSchemaDiffCheck({ node_id: nodeId }, apiClient)).check_id}`);
|
|
5690
|
+
}, [
|
|
5691
|
+
node,
|
|
5692
|
+
setLocation,
|
|
5693
|
+
apiClient
|
|
5694
|
+
]);
|
|
5682
5695
|
const formattedColumns = formatSelectColumns(baseColumns, currentColumns);
|
|
5683
5696
|
let query = `select * from {{ ref("${node.data.name}") }}`;
|
|
5684
5697
|
if (formattedColumns.length) query = `select \n ${formattedColumns.join("\n ")}\nfrom {{ ref("${node.data.name}") }}`;
|
|
@@ -6145,6 +6158,7 @@ const initValue = {
|
|
|
6145
6158
|
actions: {}
|
|
6146
6159
|
};
|
|
6147
6160
|
const useMultiNodesAction = (nodes, { onActionStarted, onActionNodeUpdated, onActionCompleted }) => {
|
|
6161
|
+
const { apiClient } = useApiConfig();
|
|
6148
6162
|
const actionState = useRef({ ...initValue }).current;
|
|
6149
6163
|
const { showRunId } = useRecceActionContext();
|
|
6150
6164
|
const submitRunForNodes = async (type, skip, getParams) => {
|
|
@@ -6174,12 +6188,12 @@ const useMultiNodesAction = (nodes, { onActionStarted, onActionNodeUpdated, onAc
|
|
|
6174
6188
|
}
|
|
6175
6189
|
const params = getParams(candidates);
|
|
6176
6190
|
try {
|
|
6177
|
-
const { run_id } = await submitRun(type, params, { nowait: true });
|
|
6191
|
+
const { run_id } = await submitRun(type, params, { nowait: true }, apiClient);
|
|
6178
6192
|
showRunId(run_id);
|
|
6179
6193
|
actionState.currentRun = { run_id };
|
|
6180
6194
|
actionState.total = 1;
|
|
6181
6195
|
for (;;) {
|
|
6182
|
-
const run = await waitRun(run_id, 2);
|
|
6196
|
+
const run = await waitRun(run_id, 2, apiClient);
|
|
6183
6197
|
actionState.currentRun = run;
|
|
6184
6198
|
const status = run.error ? "failure" : run.result ? "success" : "running";
|
|
6185
6199
|
for (const node of candidates) {
|
|
@@ -6228,7 +6242,7 @@ const useMultiNodesAction = (nodes, { onActionStarted, onActionNodeUpdated, onAc
|
|
|
6228
6242
|
};
|
|
6229
6243
|
onActionNodeUpdated(node);
|
|
6230
6244
|
} else try {
|
|
6231
|
-
const { run_id } = await submitRun(type, params, { nowait: true });
|
|
6245
|
+
const { run_id } = await submitRun(type, params, { nowait: true }, apiClient);
|
|
6232
6246
|
actionState.currentRun = { run_id };
|
|
6233
6247
|
actions[node.id] = {
|
|
6234
6248
|
mode,
|
|
@@ -6236,7 +6250,7 @@ const useMultiNodesAction = (nodes, { onActionStarted, onActionNodeUpdated, onAc
|
|
|
6236
6250
|
};
|
|
6237
6251
|
onActionNodeUpdated(node);
|
|
6238
6252
|
for (;;) {
|
|
6239
|
-
const run = await waitRun(run_id, 2);
|
|
6253
|
+
const run = await waitRun(run_id, 2, apiClient);
|
|
6240
6254
|
actionState.currentRun = run;
|
|
6241
6255
|
const status = run.error ? "failure" : run.result ? "success" : "running";
|
|
6242
6256
|
actions[node.id] = {
|
|
@@ -6322,17 +6336,17 @@ const useMultiNodesAction = (nodes, { onActionStarted, onActionNodeUpdated, onAc
|
|
|
6322
6336
|
});
|
|
6323
6337
|
};
|
|
6324
6338
|
const addLineageDiffCheck = async () => {
|
|
6325
|
-
return await createLineageDiffCheck({ node_ids: nodes.map((node) => node.id) });
|
|
6339
|
+
return await createLineageDiffCheck({ node_ids: nodes.map((node) => node.id) }, apiClient);
|
|
6326
6340
|
};
|
|
6327
6341
|
const addSchemaDiffCheck = async () => {
|
|
6328
6342
|
let check;
|
|
6329
|
-
if (nodes.length === 1) check = await createSchemaDiffCheck({ node_id: nodes[0].id });
|
|
6330
|
-
else check = await createSchemaDiffCheck({ node_id: nodes.map((node) => node.id) });
|
|
6343
|
+
if (nodes.length === 1) check = await createSchemaDiffCheck({ node_id: nodes[0].id }, apiClient);
|
|
6344
|
+
else check = await createSchemaDiffCheck({ node_id: nodes.map((node) => node.id) }, apiClient);
|
|
6331
6345
|
return check;
|
|
6332
6346
|
};
|
|
6333
6347
|
const cancel = async () => {
|
|
6334
6348
|
actionState.status = "canceling";
|
|
6335
|
-
if (actionState.currentRun?.run_id) await cancelRun(actionState.currentRun.run_id);
|
|
6349
|
+
if (actionState.currentRun?.run_id) await cancelRun(actionState.currentRun.run_id, apiClient);
|
|
6336
6350
|
};
|
|
6337
6351
|
const reset = () => {
|
|
6338
6352
|
Object.assign(actionState, initValue);
|
|
@@ -6395,10 +6409,11 @@ const useNavToCheck = () => {
|
|
|
6395
6409
|
};
|
|
6396
6410
|
function PrivateLineageView({ interactive = false, ...props }, ref) {
|
|
6397
6411
|
const { isDark } = useThemeColors();
|
|
6412
|
+
const { apiClient } = useApiConfig();
|
|
6398
6413
|
const reactFlow = useReactFlow();
|
|
6399
6414
|
const refResize = useRef(null);
|
|
6400
6415
|
const { successToast, failToast } = useClipBoardToast();
|
|
6401
|
-
const { copyToClipboard, ImageDownloadModal, ref: refReactFlow } = useCopyToClipboard({
|
|
6416
|
+
const { copyToClipboard, ImageDownloadModal, ref: refReactFlow } = useCopyToClipboard$1({
|
|
6402
6417
|
renderLibrary: "html-to-image",
|
|
6403
6418
|
imageType: "png",
|
|
6404
6419
|
shadowEffect: true,
|
|
@@ -6442,7 +6457,7 @@ function PrivateLineageView({ interactive = false, ...props }, ref) {
|
|
|
6442
6457
|
}, []);
|
|
6443
6458
|
const cllHistory = useRef([]).current;
|
|
6444
6459
|
const [cll, setCll] = useState(void 0);
|
|
6445
|
-
const actionGetCll = useMutation({ mutationFn: getCll });
|
|
6460
|
+
const actionGetCll = useMutation({ mutationFn: (input) => getCll(input, apiClient) });
|
|
6446
6461
|
const [nodeColumnSetMap, setNodeColumSetMap] = useState({});
|
|
6447
6462
|
const findNodeByName = useCallback((name) => {
|
|
6448
6463
|
return nodes.filter(isLineageGraphNode).find((n) => n.data.name === name);
|
|
@@ -6545,7 +6560,7 @@ function PrivateLineageView({ interactive = false, ...props }, ref) {
|
|
|
6545
6560
|
exclude: newViewOptions.exclude,
|
|
6546
6561
|
packages: newViewOptions.packages,
|
|
6547
6562
|
view_mode: newViewOptions.view_mode
|
|
6548
|
-
})).nodes;
|
|
6563
|
+
}, apiClient)).nodes;
|
|
6549
6564
|
} catch (_$1) {
|
|
6550
6565
|
newViewOptions.view_mode = "all";
|
|
6551
6566
|
filteredNodeIds$1 = (await select({
|
|
@@ -6553,7 +6568,7 @@ function PrivateLineageView({ interactive = false, ...props }, ref) {
|
|
|
6553
6568
|
exclude: newViewOptions.exclude,
|
|
6554
6569
|
packages: newViewOptions.packages,
|
|
6555
6570
|
view_mode: newViewOptions.view_mode
|
|
6556
|
-
})).nodes;
|
|
6571
|
+
}, apiClient)).nodes;
|
|
6557
6572
|
}
|
|
6558
6573
|
setViewOptions(newViewOptions);
|
|
6559
6574
|
}
|
|
@@ -6674,7 +6689,7 @@ function PrivateLineageView({ interactive = false, ...props }, ref) {
|
|
|
6674
6689
|
exclude: newViewOptions.exclude,
|
|
6675
6690
|
packages: newViewOptions.packages,
|
|
6676
6691
|
view_mode: newViewOptions.view_mode
|
|
6677
|
-
});
|
|
6692
|
+
}, apiClient);
|
|
6678
6693
|
newViewOptions = {
|
|
6679
6694
|
...newViewOptions,
|
|
6680
6695
|
column_level_lineage: void 0
|
|
@@ -6956,7 +6971,7 @@ function PrivateLineageView({ interactive = false, ...props }, ref) {
|
|
|
6956
6971
|
selected: "multi"
|
|
6957
6972
|
});
|
|
6958
6973
|
} else if (!focusedNode) {
|
|
6959
|
-
check = await createLineageDiffCheck(viewOptions);
|
|
6974
|
+
check = await createLineageDiffCheck(viewOptions, apiClient);
|
|
6960
6975
|
trackMultiNodesAction({
|
|
6961
6976
|
type: "lineage_diff",
|
|
6962
6977
|
selected: "none"
|
|
@@ -6976,7 +6991,7 @@ function PrivateLineageView({ interactive = false, ...props }, ref) {
|
|
|
6976
6991
|
});
|
|
6977
6992
|
}
|
|
6978
6993
|
} else if (focusedNode) {
|
|
6979
|
-
check = await createSchemaDiffCheck({ node_id: focusedNode.id });
|
|
6994
|
+
check = await createSchemaDiffCheck({ node_id: focusedNode.id }, apiClient);
|
|
6980
6995
|
trackMultiNodesAction({
|
|
6981
6996
|
type: "schema_diff",
|
|
6982
6997
|
selected: "single"
|
|
@@ -6987,7 +7002,7 @@ function PrivateLineageView({ interactive = false, ...props }, ref) {
|
|
|
6987
7002
|
exclude: viewOptions.exclude,
|
|
6988
7003
|
packages: viewOptions.packages,
|
|
6989
7004
|
view_mode: viewOptions.view_mode
|
|
6990
|
-
});
|
|
7005
|
+
}, apiClient);
|
|
6991
7006
|
trackMultiNodesAction({
|
|
6992
7007
|
type: "schema_diff",
|
|
6993
7008
|
selected: "none"
|
|
@@ -7323,6 +7338,7 @@ const QueryPage = () => {
|
|
|
7323
7338
|
if (envInfo?.adapterType === "sqlmesh" && _sqlQuery === defaultSqlQuery) sqlQuery = `select * from db.mymodel`;
|
|
7324
7339
|
if (featureToggles.mode === "read only") sqlQuery = `--- Would like to do query here? Book a demo with us at ${RECCE_SUPPORT_CALENDAR_URL}\n${sqlQuery}`;
|
|
7325
7340
|
const { showRunId } = useRecceActionContext();
|
|
7341
|
+
const { apiClient } = useApiConfig();
|
|
7326
7342
|
const queryFn = async (type) => {
|
|
7327
7343
|
function queryFactory(type$1) {
|
|
7328
7344
|
switch (type$1) {
|
|
@@ -7340,9 +7356,9 @@ const QueryPage = () => {
|
|
|
7340
7356
|
params.primary_keys = primaryKeys;
|
|
7341
7357
|
if (isCustomQueries) params.base_sql_template = baseSqlQuery;
|
|
7342
7358
|
}
|
|
7343
|
-
const { run_id } = await runFn(params, options);
|
|
7359
|
+
const { run_id } = await runFn(params, options, apiClient);
|
|
7344
7360
|
showRunId(run_id);
|
|
7345
|
-
return await waitRun(run_id);
|
|
7361
|
+
return await waitRun(run_id, void 0, apiClient);
|
|
7346
7362
|
};
|
|
7347
7363
|
const { mutate: runQuery, isPending } = useMutation({ mutationFn: queryFn });
|
|
7348
7364
|
const currentSchema = useMemo(() => {
|
|
@@ -7497,9 +7513,10 @@ const ChecklistItem = ({ check, selected, onSelect, onMarkAsApproved }) => {
|
|
|
7497
7513
|
const isDark = useTheme().palette.mode === "dark";
|
|
7498
7514
|
const { featureToggles } = useRecceInstanceContext();
|
|
7499
7515
|
const queryClient = useQueryClient();
|
|
7516
|
+
const { apiClient } = useApiConfig();
|
|
7500
7517
|
const checkId = check.check_id;
|
|
7501
7518
|
const { mutate } = useMutation({
|
|
7502
|
-
mutationFn: (check$1) => updateCheck(checkId, check$1),
|
|
7519
|
+
mutationFn: (check$1) => updateCheck(checkId, check$1, apiClient),
|
|
7503
7520
|
onSuccess: async () => {
|
|
7504
7521
|
await queryClient.invalidateQueries({ queryKey: cacheKeys.check(checkId) });
|
|
7505
7522
|
await queryClient.invalidateQueries({ queryKey: cacheKeys.checks() });
|
|
@@ -7571,8 +7588,9 @@ const CheckList = ({ checks, selectedItem, onCheckSelected, onChecksReordered })
|
|
|
7571
7588
|
const [open, setOpen] = useState(false);
|
|
7572
7589
|
const [pendingApprovalCheckId, setPendingApprovalCheckId] = useState(null);
|
|
7573
7590
|
const queryClient = useQueryClient();
|
|
7591
|
+
const { apiClient } = useApiConfig();
|
|
7574
7592
|
const { mutate: markCheckedByID } = useMutation({
|
|
7575
|
-
mutationFn: (checkId) => updateCheck(checkId, { is_checked: true }),
|
|
7593
|
+
mutationFn: (checkId) => updateCheck(checkId, { is_checked: true }, apiClient),
|
|
7576
7594
|
onSuccess: async (_$1, checkId) => {
|
|
7577
7595
|
await queryClient.invalidateQueries({ queryKey: cacheKeys.check(checkId) });
|
|
7578
7596
|
await queryClient.invalidateQueries({ queryKey: cacheKeys.checks() });
|
|
@@ -7720,20 +7738,22 @@ const CheckList = ({ checks, selectedItem, onCheckSelected, onChecksReordered })
|
|
|
7720
7738
|
* List all events for a check in chronological order.
|
|
7721
7739
|
*
|
|
7722
7740
|
* @param checkId - The check ID
|
|
7741
|
+
* @param client - Optional axios instance for API configuration
|
|
7723
7742
|
* @returns Promise resolving to array of CheckEvent objects
|
|
7724
7743
|
*/
|
|
7725
|
-
async function listCheckEvents(checkId) {
|
|
7726
|
-
return (await
|
|
7744
|
+
async function listCheckEvents(checkId, client = axiosClient) {
|
|
7745
|
+
return (await client.get(`/api/checks/${checkId}/events`)).data;
|
|
7727
7746
|
}
|
|
7728
7747
|
/**
|
|
7729
7748
|
* Create a new comment on a check.
|
|
7730
7749
|
*
|
|
7731
7750
|
* @param checkId - The check ID
|
|
7732
7751
|
* @param content - The comment content (plain text for now, markdown later)
|
|
7752
|
+
* @param client - Optional axios instance for API configuration
|
|
7733
7753
|
* @returns Promise resolving to the created CheckEvent
|
|
7734
7754
|
*/
|
|
7735
|
-
async function createComment(checkId, content) {
|
|
7736
|
-
return (await
|
|
7755
|
+
async function createComment(checkId, content, client = axiosClient) {
|
|
7756
|
+
return (await client.post(`/api/checks/${checkId}/events`, { content })).data;
|
|
7737
7757
|
}
|
|
7738
7758
|
/**
|
|
7739
7759
|
* Update an existing comment.
|
|
@@ -7742,10 +7762,11 @@ async function createComment(checkId, content) {
|
|
|
7742
7762
|
* @param checkId - The check ID
|
|
7743
7763
|
* @param eventId - The event ID of the comment to update
|
|
7744
7764
|
* @param content - The new comment content
|
|
7765
|
+
* @param client - Optional axios instance for API configuration
|
|
7745
7766
|
* @returns Promise resolving to the updated CheckEvent
|
|
7746
7767
|
*/
|
|
7747
|
-
async function updateComment(checkId, eventId, content) {
|
|
7748
|
-
return (await
|
|
7768
|
+
async function updateComment(checkId, eventId, content, client = axiosClient) {
|
|
7769
|
+
return (await client.patch(`/api/checks/${checkId}/events/${eventId}`, { content })).data;
|
|
7749
7770
|
}
|
|
7750
7771
|
/**
|
|
7751
7772
|
* Delete a comment (soft delete).
|
|
@@ -7753,10 +7774,11 @@ async function updateComment(checkId, eventId, content) {
|
|
|
7753
7774
|
*
|
|
7754
7775
|
* @param checkId - The check ID
|
|
7755
7776
|
* @param eventId - The event ID of the comment to delete
|
|
7777
|
+
* @param client - Optional axios instance for API configuration
|
|
7756
7778
|
* @returns Promise resolving when deletion is complete
|
|
7757
7779
|
*/
|
|
7758
|
-
async function deleteComment(checkId, eventId) {
|
|
7759
|
-
await
|
|
7780
|
+
async function deleteComment(checkId, eventId, client = axiosClient) {
|
|
7781
|
+
await client.delete(`/api/checks/${checkId}/events/${eventId}`);
|
|
7760
7782
|
}
|
|
7761
7783
|
/**
|
|
7762
7784
|
* Get the appropriate icon name for an event type.
|
|
@@ -7786,27 +7808,28 @@ const POLLING_INTERVAL = 1e4;
|
|
|
7786
7808
|
function useCheckEvents(checkId, options = {}) {
|
|
7787
7809
|
const { enabled = true } = options;
|
|
7788
7810
|
const queryClient = useQueryClient();
|
|
7811
|
+
const { apiClient } = useApiConfig();
|
|
7789
7812
|
const { data: events, isLoading, error, refetch } = useQuery({
|
|
7790
7813
|
queryKey: cacheKeys.checkEvents(checkId),
|
|
7791
|
-
queryFn: () => listCheckEvents(checkId),
|
|
7814
|
+
queryFn: () => listCheckEvents(checkId, apiClient),
|
|
7792
7815
|
enabled,
|
|
7793
7816
|
refetchInterval: POLLING_INTERVAL,
|
|
7794
7817
|
refetchIntervalInBackground: false
|
|
7795
7818
|
});
|
|
7796
7819
|
const createCommentMutation = useMutation({
|
|
7797
|
-
mutationFn: (content) => createComment(checkId, content),
|
|
7820
|
+
mutationFn: (content) => createComment(checkId, content, apiClient),
|
|
7798
7821
|
onSuccess: async () => {
|
|
7799
7822
|
await queryClient.invalidateQueries({ queryKey: cacheKeys.checkEvents(checkId) });
|
|
7800
7823
|
}
|
|
7801
7824
|
});
|
|
7802
7825
|
const updateCommentMutation = useMutation({
|
|
7803
|
-
mutationFn: ({ eventId, content }) => updateComment(checkId, eventId, content),
|
|
7826
|
+
mutationFn: ({ eventId, content }) => updateComment(checkId, eventId, content, apiClient),
|
|
7804
7827
|
onSuccess: async () => {
|
|
7805
7828
|
await queryClient.invalidateQueries({ queryKey: cacheKeys.checkEvents(checkId) });
|
|
7806
7829
|
}
|
|
7807
7830
|
});
|
|
7808
7831
|
const deleteCommentMutation = useMutation({
|
|
7809
|
-
mutationFn: (eventId) => deleteComment(checkId, eventId),
|
|
7832
|
+
mutationFn: (eventId) => deleteComment(checkId, eventId, apiClient),
|
|
7810
7833
|
onSuccess: async () => {
|
|
7811
7834
|
await queryClient.invalidateQueries({ queryKey: cacheKeys.checkEvents(checkId) });
|
|
7812
7835
|
}
|
|
@@ -8663,10 +8686,11 @@ function TimelineEvent({ event, currentUserId, onEdit, onDelete }) {
|
|
|
8663
8686
|
*/
|
|
8664
8687
|
function CheckTimeline({ checkId }) {
|
|
8665
8688
|
const isDark = useTheme().palette.mode === "dark";
|
|
8689
|
+
const { apiClient } = useApiConfig();
|
|
8666
8690
|
const { events, isLoading, error, createComment: createComment$1, isCreatingComment, updateComment: updateComment$1, deleteComment: deleteComment$1 } = useCheckEvents(checkId);
|
|
8667
8691
|
const { data: currentUser } = useQuery({
|
|
8668
8692
|
queryKey: cacheKeys.user(),
|
|
8669
|
-
queryFn: fetchUser,
|
|
8693
|
+
queryFn: () => fetchUser(apiClient),
|
|
8670
8694
|
retry: false
|
|
8671
8695
|
});
|
|
8672
8696
|
const handleCreateComment = (content) => {
|
|
@@ -9051,6 +9075,7 @@ const NodelistItem = ({ node, selected, onSelect, schemaChanged, isDark }) => {
|
|
|
9051
9075
|
};
|
|
9052
9076
|
function PrivateSchemaDiffView({ check }, ref) {
|
|
9053
9077
|
const isDark = useTheme().palette.mode === "dark";
|
|
9078
|
+
const { apiClient } = useApiConfig();
|
|
9054
9079
|
const { lineageGraph } = useLineageGraphContext();
|
|
9055
9080
|
const params = check.params;
|
|
9056
9081
|
const { isLoading, error, data } = useQuery({
|
|
@@ -9060,7 +9085,7 @@ function PrivateSchemaDiffView({ check }, ref) {
|
|
|
9060
9085
|
exclude: params.exclude,
|
|
9061
9086
|
packages: params.packages,
|
|
9062
9087
|
view_mode: params.view_mode
|
|
9063
|
-
}),
|
|
9088
|
+
}, apiClient),
|
|
9064
9089
|
refetchOnMount: true,
|
|
9065
9090
|
enabled: !params.node_id
|
|
9066
9091
|
});
|
|
@@ -9172,6 +9197,7 @@ const SchemaDiffView = forwardRef(PrivateSchemaDiffView);
|
|
|
9172
9197
|
function CheckDetail({ checkId, refreshCheckList }) {
|
|
9173
9198
|
const theme = useTheme();
|
|
9174
9199
|
const isDark = theme.palette.mode === "dark";
|
|
9200
|
+
const { apiClient } = useApiConfig();
|
|
9175
9201
|
const { featureToggles, sessionId } = useRecceInstanceContext();
|
|
9176
9202
|
const { setLatestSelectedCheckId } = useRecceCheckContext();
|
|
9177
9203
|
const { cloudMode } = useLineageGraphContext();
|
|
@@ -9187,7 +9213,7 @@ function CheckDetail({ checkId, refreshCheckList }) {
|
|
|
9187
9213
|
const menuOpen = Boolean(menuAnchorEl);
|
|
9188
9214
|
const { isLoading, error, data: check } = useQuery({
|
|
9189
9215
|
queryKey: cacheKeys.check(checkId),
|
|
9190
|
-
queryFn: async () => getCheck(checkId),
|
|
9216
|
+
queryFn: async () => getCheck(checkId, apiClient),
|
|
9191
9217
|
refetchOnMount: true
|
|
9192
9218
|
});
|
|
9193
9219
|
const trackedRunId = submittedRunId ?? check?.last_run?.run_id;
|
|
@@ -9199,14 +9225,14 @@ function CheckDetail({ checkId, refreshCheckList }) {
|
|
|
9199
9225
|
const isPresetCheck = check?.is_preset ?? false;
|
|
9200
9226
|
const lineageViewRef = useRef(null);
|
|
9201
9227
|
const { mutate } = useMutation({
|
|
9202
|
-
mutationFn: (check$1) => updateCheck(checkId, check$1),
|
|
9228
|
+
mutationFn: (check$1) => updateCheck(checkId, check$1, apiClient),
|
|
9203
9229
|
onSuccess: async () => {
|
|
9204
9230
|
await queryClient.invalidateQueries({ queryKey: cacheKeys.check(checkId) });
|
|
9205
9231
|
await queryClient.invalidateQueries({ queryKey: cacheKeys.checks() });
|
|
9206
9232
|
}
|
|
9207
9233
|
});
|
|
9208
9234
|
const { mutate: handleDelete } = useMutation({
|
|
9209
|
-
mutationFn: () => deleteCheck(checkId),
|
|
9235
|
+
mutationFn: () => deleteCheck(checkId, apiClient),
|
|
9210
9236
|
onSuccess: async () => {
|
|
9211
9237
|
setLatestSelectedCheckId("");
|
|
9212
9238
|
await queryClient.invalidateQueries({ queryKey: cacheKeys.checks() });
|
|
@@ -9216,7 +9242,7 @@ function CheckDetail({ checkId, refreshCheckList }) {
|
|
|
9216
9242
|
const { mutate: handleMarkAsPresetCheck, isPending: isMarkingAsPreset } = useMutation({
|
|
9217
9243
|
mutationFn: async () => {
|
|
9218
9244
|
if (!check) throw new Error("Check not found");
|
|
9219
|
-
return await markAsPresetCheck(checkId);
|
|
9245
|
+
return await markAsPresetCheck(checkId, apiClient);
|
|
9220
9246
|
},
|
|
9221
9247
|
onSuccess: async () => {
|
|
9222
9248
|
successToast("Check marked as preset successfully");
|
|
@@ -9228,20 +9254,21 @@ function CheckDetail({ checkId, refreshCheckList }) {
|
|
|
9228
9254
|
});
|
|
9229
9255
|
const handleRerun = useCallback(async () => {
|
|
9230
9256
|
if (!check?.type) return;
|
|
9231
|
-
setSubmittedRunId((await submitRunFromCheck(checkId, { nowait: true })).run_id);
|
|
9257
|
+
setSubmittedRunId((await submitRunFromCheck(checkId, { nowait: true }, apiClient)).run_id);
|
|
9232
9258
|
await queryClient.invalidateQueries({ queryKey: cacheKeys.check(checkId) });
|
|
9233
9259
|
if (refreshCheckList) refreshCheckList();
|
|
9234
9260
|
}, [
|
|
9235
9261
|
check,
|
|
9236
9262
|
checkId,
|
|
9237
9263
|
queryClient,
|
|
9238
|
-
refreshCheckList
|
|
9264
|
+
refreshCheckList,
|
|
9265
|
+
apiClient
|
|
9239
9266
|
]);
|
|
9240
9267
|
const handleCancel = useCallback(async () => {
|
|
9241
9268
|
setAborting(true);
|
|
9242
9269
|
if (!trackedRunId) return;
|
|
9243
|
-
return await cancelRun(trackedRunId);
|
|
9244
|
-
}, [trackedRunId]);
|
|
9270
|
+
return await cancelRun(trackedRunId, apiClient);
|
|
9271
|
+
}, [trackedRunId, apiClient]);
|
|
9245
9272
|
const handleCopy = async () => {
|
|
9246
9273
|
if (!check) return;
|
|
9247
9274
|
const markdown = buildMarkdown(check);
|
|
@@ -9746,8 +9773,9 @@ function buildBody(check) {
|
|
|
9746
9773
|
const CheckEmptyState = () => {
|
|
9747
9774
|
const queryClient = useQueryClient();
|
|
9748
9775
|
const [, setLocation] = useAppLocation();
|
|
9776
|
+
const { apiClient } = useApiConfig();
|
|
9749
9777
|
const { mutate: createSchemaCheck, isPending } = useMutation({
|
|
9750
|
-
mutationFn: () => createSchemaDiffCheck({ select: "state:modified" }),
|
|
9778
|
+
mutationFn: () => createSchemaDiffCheck({ select: "state:modified" }, apiClient),
|
|
9751
9779
|
onSuccess: async (check) => {
|
|
9752
9780
|
await queryClient.invalidateQueries({ queryKey: cacheKeys.checks() });
|
|
9753
9781
|
setLocation(`/checks/?id=${check.check_id}`);
|
|
@@ -9830,9 +9858,10 @@ const CheckEmptyState = () => {
|
|
|
9830
9858
|
//#endregion
|
|
9831
9859
|
//#region recce-source/js/src/components/run/RunPage.tsx
|
|
9832
9860
|
const RunPage = ({ runId }) => {
|
|
9861
|
+
const { apiClient } = useApiConfig();
|
|
9833
9862
|
const { error, data: run } = useQuery({
|
|
9834
9863
|
queryKey: cacheKeys.run(runId),
|
|
9835
|
-
queryFn: async () => waitRun(runId)
|
|
9864
|
+
queryFn: async () => waitRun(runId, void 0, apiClient)
|
|
9836
9865
|
});
|
|
9837
9866
|
let RunResultView;
|
|
9838
9867
|
if (run && runTypeHasRef(run.type)) RunResultView = findByRunType(run.type).RunResultView;
|
|
@@ -9847,10 +9876,11 @@ const RunPage = ({ runId }) => {
|
|
|
9847
9876
|
//#region recce-source/js/src/components/run/RunList.tsx
|
|
9848
9877
|
const RunListItem = ({ run, isSelected, onSelectRun, onAddToChecklist, onGoToCheck }) => {
|
|
9849
9878
|
const { featureToggles } = useRecceInstanceContext();
|
|
9879
|
+
const { apiClient } = useApiConfig();
|
|
9850
9880
|
const { data: fetchedRun } = useQuery({
|
|
9851
9881
|
queryKey: cacheKeys.run(run.run_id),
|
|
9852
9882
|
queryFn: async () => {
|
|
9853
|
-
return await waitRun(run.run_id);
|
|
9883
|
+
return await waitRun(run.run_id, void 0, apiClient);
|
|
9854
9884
|
},
|
|
9855
9885
|
enabled: run.status === "running",
|
|
9856
9886
|
retry: false
|
|
@@ -9954,10 +9984,11 @@ const DateSegmentItem = ({ runAt }) => {
|
|
|
9954
9984
|
};
|
|
9955
9985
|
const RunList = () => {
|
|
9956
9986
|
const { closeHistory } = useRecceActionContext();
|
|
9987
|
+
const { apiClient } = useApiConfig();
|
|
9957
9988
|
const { data: runs, isLoading } = useQuery({
|
|
9958
9989
|
queryKey: cacheKeys.runs(),
|
|
9959
9990
|
queryFn: async () => {
|
|
9960
|
-
return await listRuns();
|
|
9991
|
+
return await listRuns(apiClient);
|
|
9961
9992
|
},
|
|
9962
9993
|
retry: false
|
|
9963
9994
|
});
|
|
@@ -10021,6 +10052,7 @@ const RunList = () => {
|
|
|
10021
10052
|
function DateDividedRunHistoryItem({ run, previousDate }) {
|
|
10022
10053
|
const [, setLocation] = useAppLocation();
|
|
10023
10054
|
const queryClient = useQueryClient();
|
|
10055
|
+
const { apiClient } = useApiConfig();
|
|
10024
10056
|
const { showRunId, runId } = useRecceActionContext();
|
|
10025
10057
|
const currentDate = new Date(run.run_at).toDateString();
|
|
10026
10058
|
const shouldRenderDateSegment = previousDate != null && previousDate !== currentDate;
|
|
@@ -10029,10 +10061,14 @@ function DateDividedRunHistoryItem({ run, previousDate }) {
|
|
|
10029
10061
|
showRunId(runId$1, false);
|
|
10030
10062
|
};
|
|
10031
10063
|
const handleAddToChecklist = useCallback(async (clickedRunId) => {
|
|
10032
|
-
const check = await createCheckByRun(clickedRunId);
|
|
10064
|
+
const check = await createCheckByRun(clickedRunId, void 0, apiClient);
|
|
10033
10065
|
await queryClient.invalidateQueries({ queryKey: cacheKeys.checks() });
|
|
10034
10066
|
setLocation(`/checks/?id=${check.check_id}`);
|
|
10035
|
-
}, [
|
|
10067
|
+
}, [
|
|
10068
|
+
setLocation,
|
|
10069
|
+
queryClient,
|
|
10070
|
+
apiClient
|
|
10071
|
+
]);
|
|
10036
10072
|
const handleGoToCheck = useCallback((checkId) => {
|
|
10037
10073
|
trackHistoryAction({ name: "go_to_check" });
|
|
10038
10074
|
setLocation(`/checks/?id=${checkId}`);
|
|
@@ -10397,6 +10433,125 @@ function SummaryView() {
|
|
|
10397
10433
|
}) });
|
|
10398
10434
|
}
|
|
10399
10435
|
|
|
10436
|
+
//#endregion
|
|
10437
|
+
//#region recce-source/js/src/components/app/AvatarDropdown.tsx
|
|
10438
|
+
function AvatarDropdown() {
|
|
10439
|
+
const { apiClient } = useApiConfig();
|
|
10440
|
+
const { data: user, isLoading, error } = useQuery({
|
|
10441
|
+
queryKey: cacheKeys.user(),
|
|
10442
|
+
queryFn: () => fetchUser(apiClient),
|
|
10443
|
+
retry: false
|
|
10444
|
+
});
|
|
10445
|
+
const { data: avatarUrl } = useQuery({
|
|
10446
|
+
queryKey: ["github-avatar", user?.id],
|
|
10447
|
+
queryFn: () => user ? fetchGitHubAvatar(user.id) : Promise.resolve(null),
|
|
10448
|
+
enabled: !!user?.id && user.login_type === "github",
|
|
10449
|
+
retry: false,
|
|
10450
|
+
staleTime: 300 * 1e3
|
|
10451
|
+
});
|
|
10452
|
+
const [anchorEl, setAnchorEl] = useState(null);
|
|
10453
|
+
const open = Boolean(anchorEl);
|
|
10454
|
+
const handleClick = (event) => {
|
|
10455
|
+
setAnchorEl(event.currentTarget);
|
|
10456
|
+
};
|
|
10457
|
+
const handleClose = () => {
|
|
10458
|
+
setAnchorEl(null);
|
|
10459
|
+
};
|
|
10460
|
+
const showUserInfo = !isLoading && !error && user;
|
|
10461
|
+
const getInitials = (name) => {
|
|
10462
|
+
if (!name) return "U";
|
|
10463
|
+
return name.charAt(0).toUpperCase();
|
|
10464
|
+
};
|
|
10465
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [isLoading ? /* @__PURE__ */ jsx(Box, {
|
|
10466
|
+
onClick: handleClick,
|
|
10467
|
+
sx: {
|
|
10468
|
+
width: 32,
|
|
10469
|
+
height: 32,
|
|
10470
|
+
borderRadius: "50%",
|
|
10471
|
+
bgcolor: "background.paper",
|
|
10472
|
+
color: "primary.main",
|
|
10473
|
+
display: "flex",
|
|
10474
|
+
alignItems: "center",
|
|
10475
|
+
justifyContent: "center",
|
|
10476
|
+
cursor: "pointer"
|
|
10477
|
+
},
|
|
10478
|
+
children: /* @__PURE__ */ jsx(CircularProgress, { size: 16 })
|
|
10479
|
+
}) : /* @__PURE__ */ jsx(MuiAvatar, {
|
|
10480
|
+
onClick: handleClick,
|
|
10481
|
+
src: avatarUrl || void 0,
|
|
10482
|
+
sx: {
|
|
10483
|
+
width: 28,
|
|
10484
|
+
height: 28,
|
|
10485
|
+
cursor: "pointer",
|
|
10486
|
+
outline: "1px solid white",
|
|
10487
|
+
fontSize: "0.875rem"
|
|
10488
|
+
},
|
|
10489
|
+
children: getInitials(user?.login)
|
|
10490
|
+
}), /* @__PURE__ */ jsxs(Menu, {
|
|
10491
|
+
anchorEl,
|
|
10492
|
+
open,
|
|
10493
|
+
onClose: handleClose,
|
|
10494
|
+
slotProps: { paper: { sx: {
|
|
10495
|
+
bgcolor: "background.paper",
|
|
10496
|
+
borderColor: "divider",
|
|
10497
|
+
boxShadow: 3,
|
|
10498
|
+
minWidth: 180
|
|
10499
|
+
} } },
|
|
10500
|
+
children: [
|
|
10501
|
+
/* @__PURE__ */ jsxs(Box, {
|
|
10502
|
+
sx: {
|
|
10503
|
+
px: 2,
|
|
10504
|
+
py: 1.5
|
|
10505
|
+
},
|
|
10506
|
+
children: [
|
|
10507
|
+
isLoading && /* @__PURE__ */ jsxs(Box, {
|
|
10508
|
+
sx: {
|
|
10509
|
+
display: "flex",
|
|
10510
|
+
alignItems: "center",
|
|
10511
|
+
gap: 1
|
|
10512
|
+
},
|
|
10513
|
+
children: [/* @__PURE__ */ jsx(Typography, {
|
|
10514
|
+
variant: "body2",
|
|
10515
|
+
color: "text.primary",
|
|
10516
|
+
children: "Loading..."
|
|
10517
|
+
}), /* @__PURE__ */ jsx(CircularProgress, { size: 16 })]
|
|
10518
|
+
}),
|
|
10519
|
+
error && /* @__PURE__ */ jsx(Typography, {
|
|
10520
|
+
variant: "caption",
|
|
10521
|
+
color: "error",
|
|
10522
|
+
children: "Failed to load user information"
|
|
10523
|
+
}),
|
|
10524
|
+
showUserInfo && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Typography, {
|
|
10525
|
+
variant: "body2",
|
|
10526
|
+
fontWeight: "600",
|
|
10527
|
+
color: "text.primary",
|
|
10528
|
+
children: user.login
|
|
10529
|
+
}), user.email && /* @__PURE__ */ jsx(Typography, {
|
|
10530
|
+
variant: "caption",
|
|
10531
|
+
color: "text.secondary",
|
|
10532
|
+
children: user.email
|
|
10533
|
+
})] })
|
|
10534
|
+
]
|
|
10535
|
+
}),
|
|
10536
|
+
/* @__PURE__ */ jsx(Divider, {}),
|
|
10537
|
+
/* @__PURE__ */ jsxs(MenuItem, {
|
|
10538
|
+
onClick: () => {
|
|
10539
|
+
window.open("https://cloud.datarecce.io/", "_blank");
|
|
10540
|
+
handleClose();
|
|
10541
|
+
},
|
|
10542
|
+
children: [/* @__PURE__ */ jsx(ListItemIcon, { children: /* @__PURE__ */ jsx(FaCloud, {}) }), /* @__PURE__ */ jsx(ListItemText, { children: "Recce Cloud" })]
|
|
10543
|
+
}),
|
|
10544
|
+
/* @__PURE__ */ jsxs(MenuItem, {
|
|
10545
|
+
onClick: () => {
|
|
10546
|
+
window.open(RECCE_SUPPORT_CALENDAR_URL, "_blank");
|
|
10547
|
+
handleClose();
|
|
10548
|
+
},
|
|
10549
|
+
children: [/* @__PURE__ */ jsx(ListItemIcon, { children: /* @__PURE__ */ jsx(FaUser, {}) }), /* @__PURE__ */ jsx(ListItemText, { children: "Get live support" })]
|
|
10550
|
+
})
|
|
10551
|
+
]
|
|
10552
|
+
})] });
|
|
10553
|
+
}
|
|
10554
|
+
|
|
10400
10555
|
//#endregion
|
|
10401
10556
|
//#region recce-source/js/src/components/timeout/IdleTimeoutBadge.tsx
|
|
10402
10557
|
/**
|
|
@@ -10434,5 +10589,1134 @@ function IdleTimeoutBadge() {
|
|
|
10434
10589
|
}
|
|
10435
10590
|
|
|
10436
10591
|
//#endregion
|
|
10437
|
-
|
|
10438
|
-
|
|
10592
|
+
//#region recce-source/js/app/(mainComponents)/DisplayModeToggle.tsx
|
|
10593
|
+
/**
|
|
10594
|
+
* Display Mode Toggle - switches between light and dark themes
|
|
10595
|
+
*
|
|
10596
|
+
* Uses next-themes to persist the user's preference.
|
|
10597
|
+
* Default is light theme, with future support for system preference.
|
|
10598
|
+
*/
|
|
10599
|
+
function DisplayModeToggle() {
|
|
10600
|
+
const { setTheme, resolvedTheme } = useTheme$1();
|
|
10601
|
+
const [mounted, setMounted] = useState(false);
|
|
10602
|
+
useEffect(() => {
|
|
10603
|
+
setMounted(true);
|
|
10604
|
+
}, []);
|
|
10605
|
+
const toggleTheme = () => {
|
|
10606
|
+
setTheme(resolvedTheme === "dark" ? "light" : "dark");
|
|
10607
|
+
};
|
|
10608
|
+
if (!mounted) return /* @__PURE__ */ jsx(IconButton, {
|
|
10609
|
+
size: "small",
|
|
10610
|
+
sx: {
|
|
10611
|
+
color: "rgba(255, 255, 255, 0.8)",
|
|
10612
|
+
"&:hover": { bgcolor: "rgba(255, 255, 255, 0.1)" }
|
|
10613
|
+
},
|
|
10614
|
+
disabled: true,
|
|
10615
|
+
children: /* @__PURE__ */ jsx(PiSun, { style: {
|
|
10616
|
+
width: 18,
|
|
10617
|
+
height: 18
|
|
10618
|
+
} })
|
|
10619
|
+
});
|
|
10620
|
+
const isDark = resolvedTheme === "dark";
|
|
10621
|
+
return /* @__PURE__ */ jsx(MuiTooltip, {
|
|
10622
|
+
title: isDark ? "Switch to light mode" : "Switch to dark mode",
|
|
10623
|
+
children: /* @__PURE__ */ jsx(IconButton, {
|
|
10624
|
+
size: "small",
|
|
10625
|
+
onClick: toggleTheme,
|
|
10626
|
+
sx: {
|
|
10627
|
+
color: "rgba(255, 255, 255, 0.8)",
|
|
10628
|
+
"&:hover": { bgcolor: "rgba(255, 255, 255, 0.1)" }
|
|
10629
|
+
},
|
|
10630
|
+
"aria-label": isDark ? "Switch to light mode" : "Switch to dark mode",
|
|
10631
|
+
children: isDark ? /* @__PURE__ */ jsx(PiSun, { style: {
|
|
10632
|
+
width: 18,
|
|
10633
|
+
height: 18
|
|
10634
|
+
} }) : /* @__PURE__ */ jsx(PiMoon, { style: {
|
|
10635
|
+
width: 18,
|
|
10636
|
+
height: 18
|
|
10637
|
+
} })
|
|
10638
|
+
})
|
|
10639
|
+
});
|
|
10640
|
+
}
|
|
10641
|
+
|
|
10642
|
+
//#endregion
|
|
10643
|
+
//#region recce-source/js/app/(mainComponents)/RecceVersionBadge.tsx
|
|
10644
|
+
function RecceVersionBadge() {
|
|
10645
|
+
const { version, latestVersion } = useVersionNumber();
|
|
10646
|
+
const versionFormatRegex = useMemo(() => /* @__PURE__ */ new RegExp("^\\d+\\.\\d+\\.\\d+$"), []);
|
|
10647
|
+
useEffect(() => {
|
|
10648
|
+
if (versionFormatRegex.test(version) && version !== latestVersion) {
|
|
10649
|
+
const storageKey = "recce-update-toast-shown";
|
|
10650
|
+
if (sessionStorage.getItem(storageKey)) return;
|
|
10651
|
+
setTimeout(() => {
|
|
10652
|
+
toaster.create({
|
|
10653
|
+
id: "recce-update-available",
|
|
10654
|
+
title: "Update available",
|
|
10655
|
+
description: /* @__PURE__ */ jsxs("span", { children: [
|
|
10656
|
+
"A new version of Recce (v",
|
|
10657
|
+
latestVersion,
|
|
10658
|
+
") is available.",
|
|
10659
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
10660
|
+
"Please run",
|
|
10661
|
+
" ",
|
|
10662
|
+
/* @__PURE__ */ jsx(Box, {
|
|
10663
|
+
component: "code",
|
|
10664
|
+
sx: {
|
|
10665
|
+
bgcolor: "grey.200",
|
|
10666
|
+
px: .5,
|
|
10667
|
+
py: .25,
|
|
10668
|
+
borderRadius: .5,
|
|
10669
|
+
fontFamily: "monospace",
|
|
10670
|
+
fontSize: "0.875em"
|
|
10671
|
+
},
|
|
10672
|
+
children: "pip install --upgrade recce"
|
|
10673
|
+
}),
|
|
10674
|
+
" ",
|
|
10675
|
+
"to update Recce.",
|
|
10676
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
10677
|
+
/* @__PURE__ */ jsx(Link, {
|
|
10678
|
+
sx: {
|
|
10679
|
+
color: "primary.main",
|
|
10680
|
+
fontWeight: "bold",
|
|
10681
|
+
"&:hover": { textDecoration: "underline" }
|
|
10682
|
+
},
|
|
10683
|
+
href: `https://github.com/DataRecce/recce/releases/tag/v${latestVersion}`,
|
|
10684
|
+
target: "_blank",
|
|
10685
|
+
children: "Click here to view the detail of latest release"
|
|
10686
|
+
})
|
|
10687
|
+
] }),
|
|
10688
|
+
duration: 60 * 1e3,
|
|
10689
|
+
closable: true
|
|
10690
|
+
});
|
|
10691
|
+
sessionStorage.setItem(storageKey, "true");
|
|
10692
|
+
}, 0);
|
|
10693
|
+
}
|
|
10694
|
+
}, [
|
|
10695
|
+
version,
|
|
10696
|
+
latestVersion,
|
|
10697
|
+
versionFormatRegex
|
|
10698
|
+
]);
|
|
10699
|
+
if (!versionFormatRegex.test(version)) return /* @__PURE__ */ jsx(Typography, {
|
|
10700
|
+
component: "span",
|
|
10701
|
+
sx: {
|
|
10702
|
+
fontSize: "sm",
|
|
10703
|
+
color: "rgba(255,255,255,0.8)",
|
|
10704
|
+
textTransform: "uppercase",
|
|
10705
|
+
borderWidth: 1,
|
|
10706
|
+
px: 1,
|
|
10707
|
+
borderRadius: .75
|
|
10708
|
+
},
|
|
10709
|
+
children: version
|
|
10710
|
+
});
|
|
10711
|
+
return /* @__PURE__ */ jsx(Link, {
|
|
10712
|
+
href: `https://github.com/DataRecce/recce/releases/tag/v${version}`,
|
|
10713
|
+
sx: {
|
|
10714
|
+
"&:hover": { textDecoration: "none" },
|
|
10715
|
+
fontSize: "sm",
|
|
10716
|
+
color: "rgba(255,255,255,0.8)",
|
|
10717
|
+
textTransform: "uppercase",
|
|
10718
|
+
borderWidth: 1,
|
|
10719
|
+
px: 1,
|
|
10720
|
+
borderRadius: .75
|
|
10721
|
+
},
|
|
10722
|
+
target: "_blank",
|
|
10723
|
+
children: version
|
|
10724
|
+
});
|
|
10725
|
+
}
|
|
10726
|
+
|
|
10727
|
+
//#endregion
|
|
10728
|
+
//#region recce-source/js/app/(mainComponents)/TopBar.tsx
|
|
10729
|
+
function LinkIcon({ icon: IconComponent, href, sx, ...props }) {
|
|
10730
|
+
const theme = useTheme();
|
|
10731
|
+
return /* @__PURE__ */ jsx(Link, {
|
|
10732
|
+
sx: {
|
|
10733
|
+
height: "20px",
|
|
10734
|
+
color: "common.white",
|
|
10735
|
+
...sx
|
|
10736
|
+
},
|
|
10737
|
+
href,
|
|
10738
|
+
target: "_blank",
|
|
10739
|
+
...props,
|
|
10740
|
+
children: /* @__PURE__ */ jsx(IconComponent, { style: {
|
|
10741
|
+
color: theme.palette.common.white,
|
|
10742
|
+
width: 20,
|
|
10743
|
+
height: 20
|
|
10744
|
+
} })
|
|
10745
|
+
});
|
|
10746
|
+
}
|
|
10747
|
+
function TopBar() {
|
|
10748
|
+
const { reviewMode, isDemoSite, envInfo, cloudMode } = useLineageGraphContext();
|
|
10749
|
+
const { featureToggles, authed } = useRecceInstanceContext();
|
|
10750
|
+
const { url: prURL, id: prID } = envInfo?.pullRequest ?? {};
|
|
10751
|
+
const demoPrId = prURL ? prURL.split("/").pop() : null;
|
|
10752
|
+
const brandLink = cloudMode || authed ? "https://cloud.datarecce.io/" : "https://reccehq.com/";
|
|
10753
|
+
const [showModal, setShowModal] = useState(false);
|
|
10754
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
10755
|
+
sx: {
|
|
10756
|
+
display: "flex",
|
|
10757
|
+
gap: "10px",
|
|
10758
|
+
minHeight: "40px",
|
|
10759
|
+
alignItems: "center",
|
|
10760
|
+
bgcolor: colors.brand[400]
|
|
10761
|
+
},
|
|
10762
|
+
children: [
|
|
10763
|
+
/* @__PURE__ */ jsx(Link, {
|
|
10764
|
+
href: brandLink,
|
|
10765
|
+
target: "_blank",
|
|
10766
|
+
sx: { "&:hover": { textDecoration: "none" } },
|
|
10767
|
+
children: /* @__PURE__ */ jsxs(Box, {
|
|
10768
|
+
sx: {
|
|
10769
|
+
display: "flex",
|
|
10770
|
+
gap: "10px",
|
|
10771
|
+
alignItems: "center"
|
|
10772
|
+
},
|
|
10773
|
+
children: [/* @__PURE__ */ jsx(Box, {
|
|
10774
|
+
component: "img",
|
|
10775
|
+
sx: {
|
|
10776
|
+
width: 20,
|
|
10777
|
+
height: 20,
|
|
10778
|
+
ml: "18px"
|
|
10779
|
+
},
|
|
10780
|
+
src: "/logo/recce-logo-white.png",
|
|
10781
|
+
alt: "recce-logo-white"
|
|
10782
|
+
}), /* @__PURE__ */ jsx(Typography, {
|
|
10783
|
+
variant: "h4",
|
|
10784
|
+
sx: {
|
|
10785
|
+
fontFamily: "\"Montserrat\", sans-serif",
|
|
10786
|
+
color: "common.white",
|
|
10787
|
+
fontSize: "1.25rem"
|
|
10788
|
+
},
|
|
10789
|
+
children: "RECCE"
|
|
10790
|
+
})]
|
|
10791
|
+
})
|
|
10792
|
+
}),
|
|
10793
|
+
/* @__PURE__ */ jsx(DisplayModeToggle, {}),
|
|
10794
|
+
/* @__PURE__ */ jsx(RecceVersionBadge, {}),
|
|
10795
|
+
(featureToggles.mode ?? reviewMode) && /* @__PURE__ */ jsx(Badge, {
|
|
10796
|
+
sx: {
|
|
10797
|
+
fontSize: "0.875rem",
|
|
10798
|
+
color: "rgba(255,255,255,0.8)",
|
|
10799
|
+
textTransform: "uppercase",
|
|
10800
|
+
borderWidth: 1,
|
|
10801
|
+
px: 1,
|
|
10802
|
+
borderRadius: .75,
|
|
10803
|
+
borderColor: "rgba(255,255,255,0.8)"
|
|
10804
|
+
},
|
|
10805
|
+
children: featureToggles.mode ?? "review mode"
|
|
10806
|
+
}),
|
|
10807
|
+
cloudMode && prID && /* @__PURE__ */ jsx(Badge, {
|
|
10808
|
+
sx: {
|
|
10809
|
+
fontSize: "0.875rem",
|
|
10810
|
+
color: "rgba(255,255,255,0.8)",
|
|
10811
|
+
textTransform: "uppercase",
|
|
10812
|
+
borderWidth: 1,
|
|
10813
|
+
px: 1,
|
|
10814
|
+
borderRadius: .75,
|
|
10815
|
+
borderColor: "rgba(255,255,255,0.8)"
|
|
10816
|
+
},
|
|
10817
|
+
children: /* @__PURE__ */ jsxs(Stack, {
|
|
10818
|
+
direction: "row",
|
|
10819
|
+
spacing: 1,
|
|
10820
|
+
alignItems: "center",
|
|
10821
|
+
children: [/* @__PURE__ */ jsx(Box, { children: "cloud mode" }), /* @__PURE__ */ jsx(Box, {
|
|
10822
|
+
sx: {
|
|
10823
|
+
borderLeft: "1px solid rgba(255,255,255,0.8)",
|
|
10824
|
+
pl: "8px"
|
|
10825
|
+
},
|
|
10826
|
+
children: /* @__PURE__ */ jsxs(Link, {
|
|
10827
|
+
href: prURL,
|
|
10828
|
+
sx: { "&:hover": { textDecoration: "none" } },
|
|
10829
|
+
target: "_blank",
|
|
10830
|
+
children: [/* @__PURE__ */ jsx(VscGitPullRequest, { style: {
|
|
10831
|
+
color: "rgba(255,255,255,0.8)",
|
|
10832
|
+
width: 12,
|
|
10833
|
+
height: 12,
|
|
10834
|
+
marginRight: 2,
|
|
10835
|
+
display: "inline",
|
|
10836
|
+
verticalAlign: "middle"
|
|
10837
|
+
} }), /* @__PURE__ */ jsx(Typography, {
|
|
10838
|
+
component: "span",
|
|
10839
|
+
sx: {
|
|
10840
|
+
color: "rgba(255,255,255,0.8)",
|
|
10841
|
+
display: "inline"
|
|
10842
|
+
},
|
|
10843
|
+
children: `#${String(prID)}`
|
|
10844
|
+
})]
|
|
10845
|
+
})
|
|
10846
|
+
})]
|
|
10847
|
+
})
|
|
10848
|
+
}),
|
|
10849
|
+
isDemoSite && prURL && demoPrId && /* @__PURE__ */ jsx(Badge, {
|
|
10850
|
+
sx: {
|
|
10851
|
+
fontSize: "0.875rem",
|
|
10852
|
+
color: "rgba(255,255,255,0.8)",
|
|
10853
|
+
textTransform: "uppercase",
|
|
10854
|
+
borderWidth: 1,
|
|
10855
|
+
px: 1,
|
|
10856
|
+
borderRadius: .75,
|
|
10857
|
+
borderColor: "rgba(255,255,255,0.8)"
|
|
10858
|
+
},
|
|
10859
|
+
children: /* @__PURE__ */ jsxs(Stack, {
|
|
10860
|
+
direction: "row",
|
|
10861
|
+
spacing: 1,
|
|
10862
|
+
alignItems: "center",
|
|
10863
|
+
children: [/* @__PURE__ */ jsx(Box, { children: "demo mode" }), /* @__PURE__ */ jsx(Box, {
|
|
10864
|
+
sx: {
|
|
10865
|
+
borderLeft: "1px solid rgba(255,255,255,0.8)",
|
|
10866
|
+
pl: "8px"
|
|
10867
|
+
},
|
|
10868
|
+
children: /* @__PURE__ */ jsxs(Link, {
|
|
10869
|
+
href: prURL,
|
|
10870
|
+
sx: { "&:hover": { textDecoration: "none" } },
|
|
10871
|
+
target: "_blank",
|
|
10872
|
+
children: [/* @__PURE__ */ jsx(VscGitPullRequest, { style: {
|
|
10873
|
+
color: "rgba(255,255,255,0.8)",
|
|
10874
|
+
width: 12,
|
|
10875
|
+
height: 12,
|
|
10876
|
+
marginRight: 2,
|
|
10877
|
+
display: "inline",
|
|
10878
|
+
verticalAlign: "middle"
|
|
10879
|
+
} }), /* @__PURE__ */ jsx(Typography, {
|
|
10880
|
+
component: "span",
|
|
10881
|
+
sx: {
|
|
10882
|
+
color: "rgba(255,255,255,0.8)",
|
|
10883
|
+
display: "inline"
|
|
10884
|
+
},
|
|
10885
|
+
children: `#${demoPrId}`
|
|
10886
|
+
})]
|
|
10887
|
+
})
|
|
10888
|
+
})]
|
|
10889
|
+
})
|
|
10890
|
+
}),
|
|
10891
|
+
/* @__PURE__ */ jsx(Box, { sx: { flex: 1 } }),
|
|
10892
|
+
(isDemoSite || featureToggles.mode === "read only") && /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
10893
|
+
/* @__PURE__ */ jsx(LinkIcon, {
|
|
10894
|
+
icon: FaGithub,
|
|
10895
|
+
href: "https://github.com/DataRecce/recce"
|
|
10896
|
+
}),
|
|
10897
|
+
/* @__PURE__ */ jsx(LinkIcon, {
|
|
10898
|
+
icon: FaSlack,
|
|
10899
|
+
href: "https://getdbt.slack.com/archives/C05C28V7CPP"
|
|
10900
|
+
}),
|
|
10901
|
+
/* @__PURE__ */ jsx(LinkIcon, {
|
|
10902
|
+
sx: { mr: 2 },
|
|
10903
|
+
icon: FaQuestionCircle,
|
|
10904
|
+
href: "https://docs.datarecce.io"
|
|
10905
|
+
})
|
|
10906
|
+
] }),
|
|
10907
|
+
!isDemoSite && featureToggles.mode !== "read only" && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(IdleTimeoutBadge, {}), authed || cloudMode ? /* @__PURE__ */ jsx(Box, {
|
|
10908
|
+
sx: { mr: 2 },
|
|
10909
|
+
children: /* @__PURE__ */ jsx(AvatarDropdown, {})
|
|
10910
|
+
}) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Box, {
|
|
10911
|
+
component: "button",
|
|
10912
|
+
sx: {
|
|
10913
|
+
color: "common.white",
|
|
10914
|
+
fontSize: "0.875rem",
|
|
10915
|
+
fontWeight: 600,
|
|
10916
|
+
bgcolor: "brand.700",
|
|
10917
|
+
borderRadius: 1,
|
|
10918
|
+
px: 3,
|
|
10919
|
+
py: 1,
|
|
10920
|
+
mr: 2,
|
|
10921
|
+
cursor: "pointer",
|
|
10922
|
+
border: "none"
|
|
10923
|
+
},
|
|
10924
|
+
onClick: () => {
|
|
10925
|
+
setShowModal(true);
|
|
10926
|
+
},
|
|
10927
|
+
children: "Connect to Cloud"
|
|
10928
|
+
}), showModal && /* @__PURE__ */ jsx(AuthModal, {
|
|
10929
|
+
parentOpen: showModal,
|
|
10930
|
+
handleParentClose: setShowModal,
|
|
10931
|
+
ignoreCookie: true,
|
|
10932
|
+
variant: "user-profile"
|
|
10933
|
+
})] })] })
|
|
10934
|
+
]
|
|
10935
|
+
});
|
|
10936
|
+
}
|
|
10937
|
+
|
|
10938
|
+
//#endregion
|
|
10939
|
+
//#region recce-source/js/src/components/app/Filename.tsx
|
|
10940
|
+
const useRecceToast = () => {
|
|
10941
|
+
const toastSuccess = (message) => {
|
|
10942
|
+
toaster.create({
|
|
10943
|
+
description: message,
|
|
10944
|
+
type: "success",
|
|
10945
|
+
duration: 5e3,
|
|
10946
|
+
closable: true
|
|
10947
|
+
});
|
|
10948
|
+
};
|
|
10949
|
+
const toastError = (message, error) => {
|
|
10950
|
+
let errorMessage = message;
|
|
10951
|
+
if (error != null) if (error instanceof AxiosError) errorMessage = `${message}. ${String(error.response?.data?.detail)}`;
|
|
10952
|
+
else errorMessage = `${message}. ${error}`;
|
|
10953
|
+
toaster.create({
|
|
10954
|
+
description: errorMessage,
|
|
10955
|
+
type: "error",
|
|
10956
|
+
duration: 5e3,
|
|
10957
|
+
closable: true
|
|
10958
|
+
});
|
|
10959
|
+
};
|
|
10960
|
+
return {
|
|
10961
|
+
toastSuccess,
|
|
10962
|
+
toastError
|
|
10963
|
+
};
|
|
10964
|
+
};
|
|
10965
|
+
const useClosePrompt = (prompt) => {
|
|
10966
|
+
useEffect(() => {
|
|
10967
|
+
const handleBeforeUnload = (e) => {
|
|
10968
|
+
e.preventDefault();
|
|
10969
|
+
};
|
|
10970
|
+
if (prompt) window.addEventListener("beforeunload", handleBeforeUnload);
|
|
10971
|
+
return () => {
|
|
10972
|
+
if (prompt) window.removeEventListener("beforeunload", handleBeforeUnload);
|
|
10973
|
+
};
|
|
10974
|
+
}, [prompt]);
|
|
10975
|
+
};
|
|
10976
|
+
const Filename = () => {
|
|
10977
|
+
const { featureToggles } = useRecceInstanceContext();
|
|
10978
|
+
const { fileName, cloudMode, isDemoSite, envInfo } = useLineageGraphContext();
|
|
10979
|
+
const { apiClient } = useApiConfig();
|
|
10980
|
+
const [modalOpen, setModalOpen] = useState(false);
|
|
10981
|
+
const [overwriteOpen, setOverwriteOpen] = useState(false);
|
|
10982
|
+
const isStateless = !fileName && !cloudMode && !isDemoSite;
|
|
10983
|
+
const { data: checks } = useChecks(isStateless);
|
|
10984
|
+
const hasNonPresetChecks = checks != void 0 && checks.filter((check) => !check.is_preset).length > 0;
|
|
10985
|
+
useClosePrompt(isStateless && hasNonPresetChecks);
|
|
10986
|
+
const [{ newFileName, errorMessage, modified, overwriteWithMethod, bypass }, setState] = useState({ newFileName: fileName ?? "recce_state.json" });
|
|
10987
|
+
const inputRef = useRef(null);
|
|
10988
|
+
const { toastSuccess, toastError } = useRecceToast();
|
|
10989
|
+
const queryClient = useQueryClient();
|
|
10990
|
+
const handleOpen = () => {
|
|
10991
|
+
setState({
|
|
10992
|
+
newFileName: fileName ?? "recce_state.json",
|
|
10993
|
+
modified: !fileName
|
|
10994
|
+
});
|
|
10995
|
+
setModalOpen(true);
|
|
10996
|
+
};
|
|
10997
|
+
const handleModalClose = () => setModalOpen(false);
|
|
10998
|
+
const handleOverwriteClose = () => setOverwriteOpen(false);
|
|
10999
|
+
const handleAction = async (method, overwrite) => {
|
|
11000
|
+
if (!newFileName) return;
|
|
11001
|
+
const bypassOverwrite = localStorage.getItem(localStorageKeys.bypassSaveOverwrite) === "true";
|
|
11002
|
+
try {
|
|
11003
|
+
if (method === "save") await saveAs$1({
|
|
11004
|
+
filename: newFileName,
|
|
11005
|
+
overwrite: overwrite ?? bypassOverwrite
|
|
11006
|
+
}, apiClient);
|
|
11007
|
+
else await rename({
|
|
11008
|
+
filename: newFileName,
|
|
11009
|
+
overwrite: overwrite ?? bypassOverwrite
|
|
11010
|
+
}, apiClient);
|
|
11011
|
+
toastSuccess(method === "save" ? "Save file successfully" : "Rename file successfully");
|
|
11012
|
+
await queryClient.invalidateQueries({ queryKey: cacheKeys.lineage() });
|
|
11013
|
+
if (bypass) localStorage.setItem(localStorageKeys.bypassSaveOverwrite, "true");
|
|
11014
|
+
} catch (error) {
|
|
11015
|
+
if (error instanceof AxiosError) {
|
|
11016
|
+
if (error.response?.status === 409) {
|
|
11017
|
+
setState((s) => ({
|
|
11018
|
+
...s,
|
|
11019
|
+
overwriteWithMethod: method
|
|
11020
|
+
}));
|
|
11021
|
+
setOverwriteOpen(true);
|
|
11022
|
+
return;
|
|
11023
|
+
}
|
|
11024
|
+
}
|
|
11025
|
+
toastError(method === "save" ? "Save file failed" : "Rename file failed", error);
|
|
11026
|
+
} finally {
|
|
11027
|
+
handleModalClose();
|
|
11028
|
+
}
|
|
11029
|
+
};
|
|
11030
|
+
const handleOvewriteBack = () => {
|
|
11031
|
+
handleOverwriteClose();
|
|
11032
|
+
setModalOpen(true);
|
|
11033
|
+
setState((s) => {
|
|
11034
|
+
return {
|
|
11035
|
+
...s,
|
|
11036
|
+
overwriteWithMethod: void 0
|
|
11037
|
+
};
|
|
11038
|
+
});
|
|
11039
|
+
};
|
|
11040
|
+
if (cloudMode || isDemoSite) return /* @__PURE__ */ jsx(Fragment$1, {});
|
|
11041
|
+
const titleNewInstance = "New Instance" + (hasNonPresetChecks ? " (unsaved)" : "");
|
|
11042
|
+
let titleReadOnlyState;
|
|
11043
|
+
if (featureToggles.disableSaveToFile && fileName) {
|
|
11044
|
+
const generatedAt = envInfo?.stateMetadata?.generated_at;
|
|
11045
|
+
const formattedDate = generatedAt ? formatRunDateTime(new Date(generatedAt)) : null;
|
|
11046
|
+
titleReadOnlyState = formattedDate ? `${fileName} (${formattedDate})` : null;
|
|
11047
|
+
}
|
|
11048
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
11049
|
+
/* @__PURE__ */ jsxs(Stack, {
|
|
11050
|
+
direction: "row",
|
|
11051
|
+
alignItems: "center",
|
|
11052
|
+
justifyContent: "center",
|
|
11053
|
+
children: [/* @__PURE__ */ jsx(Box, {
|
|
11054
|
+
sx: { fontWeight: 600 },
|
|
11055
|
+
children: titleReadOnlyState ?? fileName ?? titleNewInstance
|
|
11056
|
+
}), !featureToggles.disableSaveToFile && /* @__PURE__ */ jsx(MuiTooltip, {
|
|
11057
|
+
title: fileName ? "Change Filename" : "Save",
|
|
11058
|
+
enterDelay: 1e3,
|
|
11059
|
+
children: /* @__PURE__ */ jsx(IconButton, {
|
|
11060
|
+
onClick: handleOpen,
|
|
11061
|
+
"aria-label": fileName ? "Change Filename" : "Save",
|
|
11062
|
+
size: "small",
|
|
11063
|
+
children: /* @__PURE__ */ jsx(Box, {
|
|
11064
|
+
component: fileName ? IconEdit : IconSave,
|
|
11065
|
+
sx: {
|
|
11066
|
+
fontSize: 16,
|
|
11067
|
+
verticalAlign: "middle"
|
|
11068
|
+
}
|
|
11069
|
+
})
|
|
11070
|
+
})
|
|
11071
|
+
})]
|
|
11072
|
+
}),
|
|
11073
|
+
/* @__PURE__ */ jsxs(MuiDialog, {
|
|
11074
|
+
open: modalOpen,
|
|
11075
|
+
onClose: handleModalClose,
|
|
11076
|
+
children: [
|
|
11077
|
+
/* @__PURE__ */ jsxs(DialogTitle, {
|
|
11078
|
+
sx: {
|
|
11079
|
+
display: "flex",
|
|
11080
|
+
alignItems: "center"
|
|
11081
|
+
},
|
|
11082
|
+
children: [
|
|
11083
|
+
fileName ? "Change Filename" : "Save File",
|
|
11084
|
+
/* @__PURE__ */ jsx(Box, { sx: { flexGrow: 1 } }),
|
|
11085
|
+
/* @__PURE__ */ jsx(IconButton, {
|
|
11086
|
+
size: "small",
|
|
11087
|
+
onClick: handleModalClose,
|
|
11088
|
+
children: /* @__PURE__ */ jsx(IoClose, {})
|
|
11089
|
+
})
|
|
11090
|
+
]
|
|
11091
|
+
}),
|
|
11092
|
+
/* @__PURE__ */ jsx(DialogContent, {
|
|
11093
|
+
onKeyDown: (e) => {
|
|
11094
|
+
e.stopPropagation();
|
|
11095
|
+
},
|
|
11096
|
+
children: /* @__PURE__ */ jsx(TextField, {
|
|
11097
|
+
inputRef,
|
|
11098
|
+
value: newFileName,
|
|
11099
|
+
label: "File name",
|
|
11100
|
+
placeholder: "Enter filename",
|
|
11101
|
+
error: !!errorMessage,
|
|
11102
|
+
helperText: errorMessage,
|
|
11103
|
+
fullWidth: true,
|
|
11104
|
+
size: "small",
|
|
11105
|
+
sx: { mt: 1 },
|
|
11106
|
+
onChange: (e) => {
|
|
11107
|
+
const value = e.target.value;
|
|
11108
|
+
let newErrorMessage = void 0;
|
|
11109
|
+
if (!value) newErrorMessage = "Filename cannot be empty.";
|
|
11110
|
+
else if (!value.endsWith(".json")) newErrorMessage = "Filename must end with .json.";
|
|
11111
|
+
else if (!/^[a-zA-Z0-9 _-]+\.json$/.test(value)) newErrorMessage = "Invalid filename. Only alphanumeric, space, _ and - are allowed.";
|
|
11112
|
+
else if (fileName && value === fileName) newErrorMessage = "Filename is the same as the current one.";
|
|
11113
|
+
setState((s) => {
|
|
11114
|
+
return {
|
|
11115
|
+
...s,
|
|
11116
|
+
modified: true,
|
|
11117
|
+
newFileName: value,
|
|
11118
|
+
errorMessage: newErrorMessage
|
|
11119
|
+
};
|
|
11120
|
+
});
|
|
11121
|
+
},
|
|
11122
|
+
onKeyDown: (e) => {
|
|
11123
|
+
if (e.key === "Enter") {
|
|
11124
|
+
if (errorMessage) return;
|
|
11125
|
+
if (!fileName) handleAction("save");
|
|
11126
|
+
else handleAction("rename");
|
|
11127
|
+
} else if (e.key === "Escape") handleModalClose();
|
|
11128
|
+
}
|
|
11129
|
+
})
|
|
11130
|
+
}),
|
|
11131
|
+
/* @__PURE__ */ jsxs(DialogActions, {
|
|
11132
|
+
sx: { gap: "5px" },
|
|
11133
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
11134
|
+
size: "small",
|
|
11135
|
+
color: fileName ? "inherit" : "iochmara",
|
|
11136
|
+
variant: "contained",
|
|
11137
|
+
onClick: async () => {
|
|
11138
|
+
await handleAction("save");
|
|
11139
|
+
},
|
|
11140
|
+
disabled: !newFileName || !!errorMessage || !modified,
|
|
11141
|
+
children: fileName ? "Save as New File" : "Confirm"
|
|
11142
|
+
}), fileName && /* @__PURE__ */ jsx(Button, {
|
|
11143
|
+
size: "small",
|
|
11144
|
+
color: "iochmara",
|
|
11145
|
+
variant: "contained",
|
|
11146
|
+
onClick: async () => {
|
|
11147
|
+
await handleAction("rename");
|
|
11148
|
+
},
|
|
11149
|
+
disabled: !newFileName || !!errorMessage || !modified,
|
|
11150
|
+
children: "Rename"
|
|
11151
|
+
})]
|
|
11152
|
+
})
|
|
11153
|
+
]
|
|
11154
|
+
}),
|
|
11155
|
+
/* @__PURE__ */ jsxs(MuiDialog, {
|
|
11156
|
+
open: overwriteOpen,
|
|
11157
|
+
onClose: handleOverwriteClose,
|
|
11158
|
+
children: [
|
|
11159
|
+
/* @__PURE__ */ jsxs(DialogTitle, {
|
|
11160
|
+
sx: {
|
|
11161
|
+
display: "flex",
|
|
11162
|
+
alignItems: "center"
|
|
11163
|
+
},
|
|
11164
|
+
children: [
|
|
11165
|
+
"Overwrite File?",
|
|
11166
|
+
/* @__PURE__ */ jsx(Box, { sx: { flexGrow: 1 } }),
|
|
11167
|
+
/* @__PURE__ */ jsx(IconButton, {
|
|
11168
|
+
size: "small",
|
|
11169
|
+
onClick: handleOverwriteClose,
|
|
11170
|
+
children: /* @__PURE__ */ jsx(IoClose, {})
|
|
11171
|
+
})
|
|
11172
|
+
]
|
|
11173
|
+
}),
|
|
11174
|
+
/* @__PURE__ */ jsxs(DialogContent, {
|
|
11175
|
+
sx: {
|
|
11176
|
+
borderTop: "solid 1px",
|
|
11177
|
+
borderBottom: "solid 1px",
|
|
11178
|
+
borderColor: "divider"
|
|
11179
|
+
},
|
|
11180
|
+
onKeyDown: (e) => {
|
|
11181
|
+
e.stopPropagation();
|
|
11182
|
+
},
|
|
11183
|
+
children: [/* @__PURE__ */ jsx(Typography, {
|
|
11184
|
+
sx: { fontSize: "12pt" },
|
|
11185
|
+
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?"
|
|
11186
|
+
}), /* @__PURE__ */ jsx(FormControlLabel, {
|
|
11187
|
+
control: /* @__PURE__ */ jsx(Checkbox, {
|
|
11188
|
+
size: "small",
|
|
11189
|
+
checked: bypass,
|
|
11190
|
+
onChange: (e) => {
|
|
11191
|
+
setState((s) => ({
|
|
11192
|
+
...s,
|
|
11193
|
+
bypass: e.target.checked
|
|
11194
|
+
}));
|
|
11195
|
+
}
|
|
11196
|
+
}),
|
|
11197
|
+
label: /* @__PURE__ */ jsx(Typography, {
|
|
11198
|
+
sx: {
|
|
11199
|
+
fontWeight: "bold",
|
|
11200
|
+
pt: "8px"
|
|
11201
|
+
},
|
|
11202
|
+
children: "Don't show this again"
|
|
11203
|
+
})
|
|
11204
|
+
})]
|
|
11205
|
+
}),
|
|
11206
|
+
/* @__PURE__ */ jsxs(DialogActions, {
|
|
11207
|
+
sx: { gap: "5px" },
|
|
11208
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
11209
|
+
variant: "outlined",
|
|
11210
|
+
onClick: handleOvewriteBack,
|
|
11211
|
+
size: "small",
|
|
11212
|
+
children: "Back"
|
|
11213
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
11214
|
+
size: "small",
|
|
11215
|
+
color: "iochmara",
|
|
11216
|
+
variant: "contained",
|
|
11217
|
+
onClick: () => {
|
|
11218
|
+
if (!overwriteWithMethod) return;
|
|
11219
|
+
handleAction(overwriteWithMethod, true);
|
|
11220
|
+
handleOverwriteClose();
|
|
11221
|
+
},
|
|
11222
|
+
children: "Overwrite"
|
|
11223
|
+
})]
|
|
11224
|
+
})
|
|
11225
|
+
]
|
|
11226
|
+
})
|
|
11227
|
+
] });
|
|
11228
|
+
};
|
|
11229
|
+
|
|
11230
|
+
//#endregion
|
|
11231
|
+
//#region recce-source/js/src/components/app/StateExporter.tsx
|
|
11232
|
+
function StateExporter() {
|
|
11233
|
+
const { featureToggles } = useRecceInstanceContext();
|
|
11234
|
+
const { apiClient } = useApiConfig();
|
|
11235
|
+
const handleExport = async () => {
|
|
11236
|
+
try {
|
|
11237
|
+
const jsonData = await exportState(apiClient);
|
|
11238
|
+
const jsonString = JSON.stringify(jsonData, null, 2);
|
|
11239
|
+
saveAs(new Blob([jsonString], { type: "application/json" }), `recce-state-${format(/* @__PURE__ */ new Date(), "yyyy-MM-dd-HH-mm-ss")}.json`);
|
|
11240
|
+
} catch (error) {
|
|
11241
|
+
console.error("Export failed", error);
|
|
11242
|
+
toaster.create({
|
|
11243
|
+
title: "Export failed",
|
|
11244
|
+
description: String(error),
|
|
11245
|
+
type: "error",
|
|
11246
|
+
duration: 5e3,
|
|
11247
|
+
closable: true
|
|
11248
|
+
});
|
|
11249
|
+
}
|
|
11250
|
+
};
|
|
11251
|
+
return /* @__PURE__ */ jsx(MuiTooltip, {
|
|
11252
|
+
title: "Export",
|
|
11253
|
+
children: /* @__PURE__ */ jsx(IconButton, {
|
|
11254
|
+
size: "small",
|
|
11255
|
+
"aria-label": "Export state",
|
|
11256
|
+
onClick: async () => {
|
|
11257
|
+
await handleExport();
|
|
11258
|
+
trackStateAction({ name: "export" });
|
|
11259
|
+
},
|
|
11260
|
+
disabled: featureToggles.disableExportStateFile,
|
|
11261
|
+
children: /* @__PURE__ */ jsx(Box, {
|
|
11262
|
+
component: IconExport,
|
|
11263
|
+
sx: {
|
|
11264
|
+
verticalAlign: "middle",
|
|
11265
|
+
width: "16px",
|
|
11266
|
+
height: "16px"
|
|
11267
|
+
}
|
|
11268
|
+
})
|
|
11269
|
+
})
|
|
11270
|
+
});
|
|
11271
|
+
}
|
|
11272
|
+
|
|
11273
|
+
//#endregion
|
|
11274
|
+
//#region recce-source/js/src/components/app/StateSharing.tsx
|
|
11275
|
+
const LOADING_MESSAGES = [
|
|
11276
|
+
"Processing...",
|
|
11277
|
+
"Still processing, please wait...",
|
|
11278
|
+
"Almost there, thanks for your patience..."
|
|
11279
|
+
];
|
|
11280
|
+
function TopLevelShare() {
|
|
11281
|
+
const { successToast, failToast } = useClipBoardToast();
|
|
11282
|
+
const [, copyToClipboard] = useCopyToClipboard();
|
|
11283
|
+
const { authed } = useRecceInstanceContext();
|
|
11284
|
+
const { shareUrl, isLoading, error, handleShareClick } = useRecceShareStateContext();
|
|
11285
|
+
const [showModal, setShowModal] = useState(false);
|
|
11286
|
+
const [messageIndex, setMessageIndex] = useState(0);
|
|
11287
|
+
const [prevIsLoading, setPrevIsLoading] = useState(isLoading);
|
|
11288
|
+
if (isLoading !== prevIsLoading) {
|
|
11289
|
+
setPrevIsLoading(isLoading);
|
|
11290
|
+
if (isLoading) setMessageIndex(0);
|
|
11291
|
+
}
|
|
11292
|
+
useInterval(() => {
|
|
11293
|
+
setMessageIndex((prev) => Math.min(prev + 1, LOADING_MESSAGES.length - 1));
|
|
11294
|
+
}, isLoading ? 3e4 : null);
|
|
11295
|
+
useEffect(() => {
|
|
11296
|
+
if (error) failToast("Failed to share state", error);
|
|
11297
|
+
}, [error, failToast]);
|
|
11298
|
+
const handleCopy = async () => {
|
|
11299
|
+
try {
|
|
11300
|
+
await copyToClipboard(String(shareUrl));
|
|
11301
|
+
successToast("Copied the link to clipboard");
|
|
11302
|
+
} catch (error$1) {
|
|
11303
|
+
failToast("Failed to copy the link", error$1);
|
|
11304
|
+
}
|
|
11305
|
+
};
|
|
11306
|
+
if (!authed) return /* @__PURE__ */ jsxs(Stack, {
|
|
11307
|
+
direction: "row",
|
|
11308
|
+
sx: {
|
|
11309
|
+
flex: 1,
|
|
11310
|
+
alignItems: "center"
|
|
11311
|
+
},
|
|
11312
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
11313
|
+
size: "xsmall",
|
|
11314
|
+
color: "neutral",
|
|
11315
|
+
variant: "outlined",
|
|
11316
|
+
onClick: () => {
|
|
11317
|
+
setShowModal(true);
|
|
11318
|
+
},
|
|
11319
|
+
startIcon: /* @__PURE__ */ jsx(TbCloudUpload, {}),
|
|
11320
|
+
children: "Share"
|
|
11321
|
+
}), showModal && /* @__PURE__ */ jsx(AuthModal, {
|
|
11322
|
+
parentOpen: showModal,
|
|
11323
|
+
handleParentClose: setShowModal,
|
|
11324
|
+
ignoreCookie: true,
|
|
11325
|
+
variant: "enable-share"
|
|
11326
|
+
})]
|
|
11327
|
+
});
|
|
11328
|
+
return /* @__PURE__ */ jsxs(Stack, {
|
|
11329
|
+
direction: "row",
|
|
11330
|
+
sx: {
|
|
11331
|
+
flex: 1,
|
|
11332
|
+
alignItems: "center",
|
|
11333
|
+
gap: "5px"
|
|
11334
|
+
},
|
|
11335
|
+
children: [
|
|
11336
|
+
/* @__PURE__ */ jsx(Button, {
|
|
11337
|
+
size: "xsmall",
|
|
11338
|
+
variant: "outlined",
|
|
11339
|
+
color: "neutral",
|
|
11340
|
+
startIcon: /* @__PURE__ */ jsx(TbCloudUpload, {}),
|
|
11341
|
+
endIcon: shareUrl ? /* @__PURE__ */ jsx(Box, {
|
|
11342
|
+
component: PiCheckCircle,
|
|
11343
|
+
sx: { color: "success.main" }
|
|
11344
|
+
}) : void 0,
|
|
11345
|
+
onClick: async () => {
|
|
11346
|
+
await handleShareClick();
|
|
11347
|
+
trackShareState({ name: "create" });
|
|
11348
|
+
},
|
|
11349
|
+
disabled: isLoading,
|
|
11350
|
+
children: isLoading ? "Sharing..." : "Share"
|
|
11351
|
+
}),
|
|
11352
|
+
isLoading && /* @__PURE__ */ jsx(Typography, {
|
|
11353
|
+
sx: {
|
|
11354
|
+
fontSize: 14,
|
|
11355
|
+
color: "grey.500"
|
|
11356
|
+
},
|
|
11357
|
+
children: LOADING_MESSAGES[messageIndex]
|
|
11358
|
+
}),
|
|
11359
|
+
/* @__PURE__ */ jsx(Stack, {
|
|
11360
|
+
direction: "row",
|
|
11361
|
+
spacing: .5,
|
|
11362
|
+
alignItems: "center",
|
|
11363
|
+
children: shareUrl && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Box, {
|
|
11364
|
+
sx: {
|
|
11365
|
+
overflowX: "auto",
|
|
11366
|
+
whiteSpace: "nowrap",
|
|
11367
|
+
maxWidth: "350px"
|
|
11368
|
+
},
|
|
11369
|
+
children: /* @__PURE__ */ jsx(Typography, {
|
|
11370
|
+
sx: { fontSize: 14 },
|
|
11371
|
+
children: shareUrl
|
|
11372
|
+
})
|
|
11373
|
+
}), /* @__PURE__ */ jsx(IconButton, {
|
|
11374
|
+
size: "small",
|
|
11375
|
+
"aria-label": "Copy the share URL",
|
|
11376
|
+
onClick: async () => {
|
|
11377
|
+
await handleCopy();
|
|
11378
|
+
trackShareState({ name: "copy" });
|
|
11379
|
+
},
|
|
11380
|
+
children: /* @__PURE__ */ jsx(PiCopy, {})
|
|
11381
|
+
})] })
|
|
11382
|
+
})
|
|
11383
|
+
]
|
|
11384
|
+
});
|
|
11385
|
+
}
|
|
11386
|
+
|
|
11387
|
+
//#endregion
|
|
11388
|
+
//#region recce-source/js/src/components/app/StateSynchronizer.tsx
|
|
11389
|
+
function isCheckDetailPage(href) {
|
|
11390
|
+
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);
|
|
11391
|
+
}
|
|
11392
|
+
function StateSpinner() {
|
|
11393
|
+
return /* @__PURE__ */ jsx(MuiTooltip, {
|
|
11394
|
+
title: "Syncing",
|
|
11395
|
+
children: /* @__PURE__ */ jsx(Box, {
|
|
11396
|
+
sx: { mx: "10px" },
|
|
11397
|
+
children: /* @__PURE__ */ jsx(CircularProgress, { size: 20 })
|
|
11398
|
+
})
|
|
11399
|
+
});
|
|
11400
|
+
}
|
|
11401
|
+
function StateSynchronizer() {
|
|
11402
|
+
const [isSyncing, setSyncing] = useState(false);
|
|
11403
|
+
const queryClient = useQueryClient();
|
|
11404
|
+
const { apiClient } = useApiConfig();
|
|
11405
|
+
const [location, setLocation] = useAppLocation();
|
|
11406
|
+
const [open, setOpen] = useState(false);
|
|
11407
|
+
const [syncOption, setSyncOption] = useState("");
|
|
11408
|
+
const { data: instanceInfo } = useRecceInstanceInfo();
|
|
11409
|
+
const handleClose = () => setOpen(false);
|
|
11410
|
+
const handleSync = useCallback(async (input) => {
|
|
11411
|
+
setOpen(false);
|
|
11412
|
+
setSyncing(true);
|
|
11413
|
+
if ((await syncState(input, apiClient)).status === "conflict") {
|
|
11414
|
+
setOpen(true);
|
|
11415
|
+
setSyncing(false);
|
|
11416
|
+
return;
|
|
11417
|
+
}
|
|
11418
|
+
while (await isStateSyncing(apiClient)) await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
11419
|
+
toaster.create({
|
|
11420
|
+
description: "Sync Completed",
|
|
11421
|
+
type: "success",
|
|
11422
|
+
duration: 5e3,
|
|
11423
|
+
closable: true
|
|
11424
|
+
});
|
|
11425
|
+
setSyncing(false);
|
|
11426
|
+
setSyncOption("");
|
|
11427
|
+
await queryClient.invalidateQueries({ queryKey: cacheKeys.lineage() });
|
|
11428
|
+
await queryClient.invalidateQueries({ queryKey: cacheKeys.checks() });
|
|
11429
|
+
await queryClient.invalidateQueries({ queryKey: cacheKeys.runs() });
|
|
11430
|
+
if (isCheckDetailPage(location)) setLocation("/checks");
|
|
11431
|
+
}, [
|
|
11432
|
+
queryClient,
|
|
11433
|
+
location,
|
|
11434
|
+
setLocation,
|
|
11435
|
+
apiClient
|
|
11436
|
+
]);
|
|
11437
|
+
if (isSyncing) return /* @__PURE__ */ jsx(StateSpinner, {});
|
|
11438
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(MuiTooltip, {
|
|
11439
|
+
title: "Sync with Cloud",
|
|
11440
|
+
children: /* @__PURE__ */ jsx(IconButton, {
|
|
11441
|
+
size: "small",
|
|
11442
|
+
"aria-label": "Sync state",
|
|
11443
|
+
onClick: () => handleSync(instanceInfo?.session_id ? { method: "merge" } : {}),
|
|
11444
|
+
children: /* @__PURE__ */ jsx(Box, {
|
|
11445
|
+
component: IconSync,
|
|
11446
|
+
sx: {
|
|
11447
|
+
fontSize: 16,
|
|
11448
|
+
verticalAlign: "middle"
|
|
11449
|
+
}
|
|
11450
|
+
})
|
|
11451
|
+
})
|
|
11452
|
+
}), /* @__PURE__ */ jsxs(MuiDialog, {
|
|
11453
|
+
open,
|
|
11454
|
+
onClose: handleClose,
|
|
11455
|
+
children: [
|
|
11456
|
+
/* @__PURE__ */ jsxs(DialogTitle, {
|
|
11457
|
+
sx: {
|
|
11458
|
+
display: "flex",
|
|
11459
|
+
alignItems: "center",
|
|
11460
|
+
fontWeight: "bold"
|
|
11461
|
+
},
|
|
11462
|
+
children: [
|
|
11463
|
+
"Sync with Cloud",
|
|
11464
|
+
/* @__PURE__ */ jsx(Box, { sx: { flexGrow: 1 } }),
|
|
11465
|
+
/* @__PURE__ */ jsx(IconButton, {
|
|
11466
|
+
size: "small",
|
|
11467
|
+
onClick: handleClose,
|
|
11468
|
+
children: /* @__PURE__ */ jsx(IoClose, {})
|
|
11469
|
+
})
|
|
11470
|
+
]
|
|
11471
|
+
}),
|
|
11472
|
+
/* @__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, {
|
|
11473
|
+
sx: { mt: "5px" },
|
|
11474
|
+
children: /* @__PURE__ */ jsx(RadioGroup, {
|
|
11475
|
+
value: syncOption,
|
|
11476
|
+
onChange: (e) => {
|
|
11477
|
+
setSyncOption(e.target.value);
|
|
11478
|
+
},
|
|
11479
|
+
children: /* @__PURE__ */ jsxs(Stack, {
|
|
11480
|
+
direction: "column",
|
|
11481
|
+
children: [
|
|
11482
|
+
/* @__PURE__ */ jsx(FormControlLabel, {
|
|
11483
|
+
value: "merge",
|
|
11484
|
+
control: /* @__PURE__ */ jsx(Radio, {}),
|
|
11485
|
+
label: /* @__PURE__ */ jsxs(Stack, {
|
|
11486
|
+
direction: "row",
|
|
11487
|
+
alignItems: "center",
|
|
11488
|
+
children: ["Merge", /* @__PURE__ */ jsx(MuiTooltip, {
|
|
11489
|
+
title: "This will merge the local and remote states.",
|
|
11490
|
+
children: /* @__PURE__ */ jsx(Box, {
|
|
11491
|
+
component: PiInfo,
|
|
11492
|
+
sx: {
|
|
11493
|
+
ml: 2,
|
|
11494
|
+
cursor: "pointer"
|
|
11495
|
+
}
|
|
11496
|
+
})
|
|
11497
|
+
})]
|
|
11498
|
+
})
|
|
11499
|
+
}),
|
|
11500
|
+
/* @__PURE__ */ jsx(FormControlLabel, {
|
|
11501
|
+
value: "overwrite",
|
|
11502
|
+
control: /* @__PURE__ */ jsx(Radio, {}),
|
|
11503
|
+
label: /* @__PURE__ */ jsxs(Stack, {
|
|
11504
|
+
direction: "row",
|
|
11505
|
+
alignItems: "center",
|
|
11506
|
+
children: ["Overwrite", /* @__PURE__ */ jsx(MuiTooltip, {
|
|
11507
|
+
title: "This will overwrite the remote state file with the local state.",
|
|
11508
|
+
children: /* @__PURE__ */ jsx(Box, {
|
|
11509
|
+
component: PiInfo,
|
|
11510
|
+
sx: {
|
|
11511
|
+
ml: 2,
|
|
11512
|
+
cursor: "pointer"
|
|
11513
|
+
}
|
|
11514
|
+
})
|
|
11515
|
+
})]
|
|
11516
|
+
})
|
|
11517
|
+
}),
|
|
11518
|
+
/* @__PURE__ */ jsx(FormControlLabel, {
|
|
11519
|
+
value: "revert",
|
|
11520
|
+
control: /* @__PURE__ */ jsx(Radio, {}),
|
|
11521
|
+
label: /* @__PURE__ */ jsxs(Stack, {
|
|
11522
|
+
direction: "row",
|
|
11523
|
+
alignItems: "center",
|
|
11524
|
+
children: ["Revert", /* @__PURE__ */ jsx(MuiTooltip, {
|
|
11525
|
+
title: "This will discard local changes and revert to the cloud state.",
|
|
11526
|
+
children: /* @__PURE__ */ jsx(Box, {
|
|
11527
|
+
component: PiInfo,
|
|
11528
|
+
sx: {
|
|
11529
|
+
ml: 2,
|
|
11530
|
+
cursor: "pointer"
|
|
11531
|
+
}
|
|
11532
|
+
})
|
|
11533
|
+
})]
|
|
11534
|
+
})
|
|
11535
|
+
})
|
|
11536
|
+
]
|
|
11537
|
+
})
|
|
11538
|
+
})
|
|
11539
|
+
})] }),
|
|
11540
|
+
/* @__PURE__ */ jsxs(DialogActions, { children: [/* @__PURE__ */ jsx(Button, {
|
|
11541
|
+
onClick: handleClose,
|
|
11542
|
+
sx: { mr: 1 },
|
|
11543
|
+
children: "Cancel"
|
|
11544
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
11545
|
+
color: "iochmara",
|
|
11546
|
+
variant: "contained",
|
|
11547
|
+
onClick: () => handleSync({ method: syncOption || void 0 }),
|
|
11548
|
+
disabled: !syncOption,
|
|
11549
|
+
children: "Sync"
|
|
11550
|
+
})] })
|
|
11551
|
+
]
|
|
11552
|
+
})] });
|
|
11553
|
+
}
|
|
11554
|
+
|
|
11555
|
+
//#endregion
|
|
11556
|
+
//#region recce-source/js/app/(mainComponents)/NavBar.tsx
|
|
11557
|
+
/**
|
|
11558
|
+
* Route configuration for tabs
|
|
11559
|
+
*/
|
|
11560
|
+
const ROUTE_CONFIG = [
|
|
11561
|
+
{
|
|
11562
|
+
path: "/lineage",
|
|
11563
|
+
name: "Lineage"
|
|
11564
|
+
},
|
|
11565
|
+
{
|
|
11566
|
+
path: "/query",
|
|
11567
|
+
name: "Query"
|
|
11568
|
+
},
|
|
11569
|
+
{
|
|
11570
|
+
path: "/checks",
|
|
11571
|
+
name: "Checklist"
|
|
11572
|
+
}
|
|
11573
|
+
];
|
|
11574
|
+
function TabBadge({ queryKey, fetchCallback, selectCallback }) {
|
|
11575
|
+
const { data: count, isLoading, error } = useQuery({
|
|
11576
|
+
queryKey,
|
|
11577
|
+
queryFn: fetchCallback,
|
|
11578
|
+
select: selectCallback
|
|
11579
|
+
});
|
|
11580
|
+
if (isLoading || error || count === 0) return /* @__PURE__ */ jsx(Fragment$1, {});
|
|
11581
|
+
return /* @__PURE__ */ jsx(Box, {
|
|
11582
|
+
bgcolor: "brand.main",
|
|
11583
|
+
display: "flex",
|
|
11584
|
+
justifyContent: "center",
|
|
11585
|
+
alignItems: "center",
|
|
11586
|
+
p: 1,
|
|
11587
|
+
borderRadius: "100%",
|
|
11588
|
+
color: "white",
|
|
11589
|
+
fontWeight: 700,
|
|
11590
|
+
fontSize: "0.75rem",
|
|
11591
|
+
children: /* @__PURE__ */ jsx("span", { children: count })
|
|
11592
|
+
});
|
|
11593
|
+
}
|
|
11594
|
+
function ChecklistBadge() {
|
|
11595
|
+
return /* @__PURE__ */ jsx(TabBadge, {
|
|
11596
|
+
queryKey: cacheKeys.checks(),
|
|
11597
|
+
fetchCallback: listChecks,
|
|
11598
|
+
selectCallback: (checks) => {
|
|
11599
|
+
return checks.filter((check) => !check.is_checked).length;
|
|
11600
|
+
}
|
|
11601
|
+
});
|
|
11602
|
+
}
|
|
11603
|
+
function NavBar() {
|
|
11604
|
+
const pathname = usePathname();
|
|
11605
|
+
const { isDemoSite, isLoading, cloudMode } = useLineageGraphContext();
|
|
11606
|
+
const { featureToggles } = useRecceInstanceContext();
|
|
11607
|
+
const { data: flag, isLoading: isFlagLoading } = useRecceServerFlag();
|
|
11608
|
+
const prevPathnameRef = useRef(null);
|
|
11609
|
+
useEffect(() => {
|
|
11610
|
+
if (prevPathnameRef.current && prevPathnameRef.current !== pathname) trackNavigation({
|
|
11611
|
+
from: prevPathnameRef.current,
|
|
11612
|
+
to: pathname
|
|
11613
|
+
});
|
|
11614
|
+
prevPathnameRef.current = pathname;
|
|
11615
|
+
}, [pathname]);
|
|
11616
|
+
return /* @__PURE__ */ jsx(Box, {
|
|
11617
|
+
sx: {
|
|
11618
|
+
borderBottom: "1px solid lightgray",
|
|
11619
|
+
px: "12px"
|
|
11620
|
+
},
|
|
11621
|
+
children: /* @__PURE__ */ jsxs(Box, {
|
|
11622
|
+
sx: {
|
|
11623
|
+
display: "grid",
|
|
11624
|
+
gridTemplateColumns: "1fr auto 1fr",
|
|
11625
|
+
width: "100%",
|
|
11626
|
+
alignItems: "center"
|
|
11627
|
+
},
|
|
11628
|
+
children: [
|
|
11629
|
+
/* @__PURE__ */ jsx(Tabs, {
|
|
11630
|
+
value: useMemo(() => {
|
|
11631
|
+
if (pathname.startsWith("/checks")) return "/checks";
|
|
11632
|
+
if (pathname.startsWith("/query")) return "/query";
|
|
11633
|
+
if (pathname.startsWith("/runs")) return "/runs";
|
|
11634
|
+
return "/lineage";
|
|
11635
|
+
}, [pathname]),
|
|
11636
|
+
sx: {
|
|
11637
|
+
borderBottom: "none",
|
|
11638
|
+
minHeight: "auto"
|
|
11639
|
+
},
|
|
11640
|
+
children: ROUTE_CONFIG.map(({ path, name }) => {
|
|
11641
|
+
if (name === "Query" && flag?.single_env_onboarding) return null;
|
|
11642
|
+
if (name === "Checklist" && ChecklistBadge) return /* @__PURE__ */ jsx(Tab, {
|
|
11643
|
+
value: path,
|
|
11644
|
+
disabled: isLoading || isFlagLoading,
|
|
11645
|
+
sx: { p: 0 },
|
|
11646
|
+
label: /* @__PURE__ */ jsx(Box, {
|
|
11647
|
+
sx: {
|
|
11648
|
+
display: "flex",
|
|
11649
|
+
alignItems: "center",
|
|
11650
|
+
gap: "4px"
|
|
11651
|
+
},
|
|
11652
|
+
children: /* @__PURE__ */ jsxs(NextLink, {
|
|
11653
|
+
href: path,
|
|
11654
|
+
style: {
|
|
11655
|
+
textDecoration: "none",
|
|
11656
|
+
color: "inherit",
|
|
11657
|
+
padding: "0.875rem 1.1875rem",
|
|
11658
|
+
display: "flex",
|
|
11659
|
+
gap: 3,
|
|
11660
|
+
alignItems: "center"
|
|
11661
|
+
},
|
|
11662
|
+
children: [
|
|
11663
|
+
name,
|
|
11664
|
+
" ",
|
|
11665
|
+
/* @__PURE__ */ jsx(ChecklistBadge, {})
|
|
11666
|
+
]
|
|
11667
|
+
})
|
|
11668
|
+
})
|
|
11669
|
+
}, path);
|
|
11670
|
+
return /* @__PURE__ */ jsx(Tab, {
|
|
11671
|
+
value: path,
|
|
11672
|
+
disabled: isLoading || isFlagLoading,
|
|
11673
|
+
sx: { p: 0 },
|
|
11674
|
+
label: /* @__PURE__ */ jsx(Box, {
|
|
11675
|
+
sx: {
|
|
11676
|
+
display: "flex",
|
|
11677
|
+
alignItems: "center",
|
|
11678
|
+
gap: "4px"
|
|
11679
|
+
},
|
|
11680
|
+
children: /* @__PURE__ */ jsx(NextLink, {
|
|
11681
|
+
href: path,
|
|
11682
|
+
style: {
|
|
11683
|
+
textDecoration: "none",
|
|
11684
|
+
color: "inherit",
|
|
11685
|
+
padding: "0.875rem 1.1875rem"
|
|
11686
|
+
},
|
|
11687
|
+
children: name
|
|
11688
|
+
})
|
|
11689
|
+
})
|
|
11690
|
+
}, path);
|
|
11691
|
+
})
|
|
11692
|
+
}),
|
|
11693
|
+
/* @__PURE__ */ jsxs(Box, {
|
|
11694
|
+
sx: {
|
|
11695
|
+
display: "flex",
|
|
11696
|
+
alignItems: "center",
|
|
11697
|
+
gap: "12px",
|
|
11698
|
+
justifyContent: "center"
|
|
11699
|
+
},
|
|
11700
|
+
children: [!isLoading && !isDemoSite && /* @__PURE__ */ jsx(Filename, {}), !isLoading && !isDemoSite && !flag?.single_env_onboarding && !featureToggles.disableShare && /* @__PURE__ */ jsx(TopLevelShare, {})]
|
|
11701
|
+
}),
|
|
11702
|
+
!isLoading && /* @__PURE__ */ jsxs(Box, {
|
|
11703
|
+
sx: {
|
|
11704
|
+
display: "flex",
|
|
11705
|
+
justifyContent: "right",
|
|
11706
|
+
alignItems: "center",
|
|
11707
|
+
mr: "8px"
|
|
11708
|
+
},
|
|
11709
|
+
children: [
|
|
11710
|
+
/* @__PURE__ */ jsx(EnvInfo, {}),
|
|
11711
|
+
cloudMode && /* @__PURE__ */ jsx(StateSynchronizer, {}),
|
|
11712
|
+
/* @__PURE__ */ jsx(StateExporter, {})
|
|
11713
|
+
]
|
|
11714
|
+
})
|
|
11715
|
+
]
|
|
11716
|
+
})
|
|
11717
|
+
});
|
|
11718
|
+
}
|
|
11719
|
+
|
|
11720
|
+
//#endregion
|
|
11721
|
+
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, DisplayModeToggle as i, DiffEditor_default as j, EnvInfo as k, RunList as l, LineageDiffView as m, TopBar as n, SummaryView as o, SchemaDiffView as p, RecceVersionBadge as r, SchemaSummary as s, NavBar as t, RunPage as u, QueryPage as v, RunResultPane as w, LineageView as x, SetupConnectionGuide as y, RowCountDiffTag as z };
|
|
11722
|
+
//# sourceMappingURL=components-BHxcVq0D.mjs.map
|