diff --git a/js/src/components/lineage/ActionTag.tsx b/js/src/components/lineage/ActionTag.tsx index 47e610b6..29b6371b 100644 --- a/js/src/components/lineage/ActionTag.tsx +++ b/js/src/components/lineage/ActionTag.tsx @@ -100,13 +100,7 @@ export const ActionTag = ({ node, action }: ActionTagProps) => { if (run.type === "row_count_diff") { const result = run.result as RowCountDiffResult; - return ( - - ); + return ; } return <>{run_id}; diff --git a/js/src/components/lineage/NodeFilter.tsx b/js/src/components/lineage/NodeFilter.tsx index 6289bb3f..bfad1504 100644 --- a/js/src/components/lineage/NodeFilter.tsx +++ b/js/src/components/lineage/NodeFilter.tsx @@ -318,7 +318,7 @@ const MoreActionMenu = (props: NodeFilterProps) => { - + Promise; + isFetching?: boolean; + error?: Error | null; } export function RowCountTag({ - rowCount: defaultRowCount, + rowCount: fetchedRowCount, node, - isInteractive, + onRefresh, + isFetching, }: RowCountTagProps) { const { runsAggregated, refetchRunsAggregated } = useLineageGraphContext(); const lastRowCount: RowCount | undefined = runsAggregated?.[node.id]?.["row_count_diff"]?.result; - const { - data: fetchedRowCount, - refetch: invokeRowCountQuery, - isFetching, - } = useQuery({ - queryKey: cacheKeys.rowCount(node.name), - queryFn: () => queryModelRowCount(node.name), - enabled: false, - initialData: defaultRowCount, - }); - - const rowCount = fetchedRowCount || defaultRowCount || lastRowCount; const icon = findByRunType("row_count_diff")?.icon; let label; + const rowCount = fetchedRowCount || lastRowCount; if (rowCount) { const base = rowCount?.base === null ? "N/A" : rowCount?.base; const current = rowCount?.curr === null ? "N/A" : rowCount?.curr; @@ -158,7 +150,7 @@ export function RowCountTag({ <>row count )} - {isInteractive && ( + {onRefresh && ( } size="xs" onClick={async () => { - await invokeRowCountQuery(); + await onRefresh(); refetchRunsAggregated?.(); }} /> diff --git a/js/src/components/lineage/NodeView.tsx b/js/src/components/lineage/NodeView.tsx index 8046a0ee..248a37c1 100644 --- a/js/src/components/lineage/NodeView.tsx +++ b/js/src/components/lineage/NodeView.tsx @@ -23,6 +23,9 @@ import { MenuButton, MenuList, MenuItem, + MenuDivider, + Icon, + MenuGroup, } from "@chakra-ui/react"; import { FaCode } from "react-icons/fa"; @@ -37,12 +40,18 @@ import { useRecceActionContext } from "@/lib/hooks/RecceActionContext"; import { useLineageGraphContext } from "@/lib/hooks/LineageGraphContext"; import useModelColumns from "@/lib/hooks/useModelColumns"; import { createSchemaDiffCheck } from "@/lib/api/schemacheck"; +import { findByRunType } from "../run/registry"; +import { cacheKeys } from "@/lib/api/cacheKeys"; +import { queryModelRowCount } from "@/lib/api/models"; +import { useQuery } from "@tanstack/react-query"; interface NodeViewProps { node: LineageGraphNode; onCloseNode: () => void; } +const EmptyIcon = () => ; + export function NodeView({ node, onCloseNode }: NodeViewProps) { const [, setLocation] = useLocation(); const { setSqlQuery, setPrimaryKeys } = useRecceQueryContext(); @@ -59,6 +68,16 @@ export function NodeView({ node, onCloseNode }: NodeViewProps) { const { runAction } = useRecceActionContext(); const { envInfo } = useLineageGraphContext(); const { primaryKey } = useModelColumns(node.name); + const { + data: rowCount, + refetch: refetchRowCount, + isFetching: isRowCountFetching, + error: rowCountError, + } = useQuery({ + queryKey: cacheKeys.rowCount(node.name), + queryFn: () => queryModelRowCount(node.name), + enabled: false, + }); const addSchemaCheck = useCallback(async () => { const nodeId = node.id; @@ -66,6 +85,9 @@ export function NodeView({ node, onCloseNode }: NodeViewProps) { setLocation(`/checks/${check.check_id}`); }, [node, setLocation]); + const isAddedOrRemoved = + node.changeStatus === "added" || node.changeStatus === "removed"; + return ( @@ -73,32 +95,131 @@ export function NodeView({ node, onCloseNode }: NodeViewProps) { {node.name} - {node.changeStatus === "modified" && ( - - - - - - Model Raw Code Diff - - - - - - - + {(node.resourceType === "model" || + node.resourceType === "seed" || + node.resourceType === "snapshot") && ( + + + Explore Diff + + + } + fontSize="14px" + onClick={() => { + if (envInfo?.adapterType === "dbt") { + setSqlQuery(`select * from {{ ref("${node.name}") }}`); + } else if (envInfo?.adapterType === "sqlmesh") { + setSqlQuery(`select * from ${node.name}`); + } + setPrimaryKeys( + primaryKey !== undefined ? [primaryKey] : undefined + ); + setLocation("/query"); + }} + > + Query + + + + {(node.resourceType === "model" || + node.resourceType === "snapshot") && ( + } + fontSize="14px" + > + Code Diff + + )} + } + fontSize="14px" + onClick={() => refetchRowCount()} + isDisabled={isRowCountFetching} + > + Row Count Diff + + } + fontSize="14px" + isDisabled={isAddedOrRemoved} + onClick={() => { + runAction( + "profile_diff", + { + model: node.name, + }, + { showForm: false, showLast: true } + ); + }} + > + Profile Diff + + } + fontSize="14px" + isDisabled={isAddedOrRemoved} + onClick={() => { + runAction( + "value_diff", + { + model: node.name, + }, + { showForm: true, showLast: true } + ); + }} + > + Value Diff + + } + fontSize="14px" + isDisabled={isAddedOrRemoved} + onClick={() => { + runAction( + "top_k_diff", + { model: node.name, column_name: "", k: 50 }, + { showForm: true } + ); + }} + > + Top-K Diff + + } + fontSize="14px" + isDisabled={isAddedOrRemoved} + onClick={() => { + runAction( + "histogram_diff", + { + model: node.name, + column_name: "", + column_type: "", + }, + { showForm: true } + ); + }} + > + Histogram Diff + + + + + } + fontSize="14px" + onClick={addSchemaCheck} + > + Schema Diff + + + + )} - + {/* )} */} + @@ -106,122 +227,40 @@ export function NodeView({ node, onCloseNode }: NodeViewProps) { {(node.resourceType === "model" || - node.resourceType === "snapshot") && ( - + node.resourceType === "snapshot" || + node.resourceType === "seed") && ( + )} {withColumns && ( - <> - - - Columns - - - - - - - - - - - Add check - - - Schema Check - - - - - {node.resourceType === "model" && ( - <> - {node.changeStatus !== "added" && - node.changeStatus !== "removed" && ( - <> - - - Advanced Diffs - - - { - runAction( - "profile_diff", - { - model: node.name, - }, - { showForm: false, showLast: true } - ); - }} - > - Profile Diff - - { - runAction( - "value_diff", - { - model: node.name, - }, - { showForm: true, showLast: true } - ); - }} - > - Value Diff - - { - runAction( - "top_k_diff", - { model: node.name, column_name: "", k: 50 }, - { showForm: true } - ); - }} - > - Top-K Diff - - { - runAction( - "histogram_diff", - { - model: node.name, - column_name: "", - column_type: "", - }, - { showForm: true } - ); - }} - > - Histogram Diff - - - - - )} - - - )} - - + + + Columns + + + + + + + )} + + + + Model Raw Code Diff + + + + + + ); } diff --git a/js/src/components/schema/SqlDiffView.tsx b/js/src/components/schema/SqlDiffView.tsx index 329dffd4..a878007c 100644 --- a/js/src/components/schema/SqlDiffView.tsx +++ b/js/src/components/schema/SqlDiffView.tsx @@ -9,7 +9,7 @@ interface SqlDiffProps { export function SqlDiffView({ base, current }: SqlDiffProps) { return (