Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
"author": "amazon",
"type": "module",
"scripts": {
"prepare": "husky",
"lint": "oxlint --fix",
"check:lint": "oxlint",
"format": "oxfmt",
"check:format": "oxfmt --check",
"prepare": "husky install",
"precommit": "lint-staged && pnpm check:types",
"lint": "eslint --fix --concurrency=auto",
"check:lint": "eslint --concurrency=auto",
"format": "prettier --write .",
"check:format": "prettier --check .",
"test": "vitest run",
"test:watch": "vitest",
"coverage": "vitest run --coverage",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { unparse } from "papaparse";

import type { TabularColumnInstance } from "@/components/Tabular/helpers/tableInstanceToTabularInstance";

import { LABELS } from "@/utils/constants";

export function transformToCsv<T extends object>(
Expand Down Expand Up @@ -37,7 +35,9 @@ export function transformToCsv<T extends object>(
}),
);

const headers = columns.map(col => col.definition?.label || col.instance.id);
const headers = columns.map(
col => col.definition?.label || col.instance.id,
);

return unparse([headers, ...csvRows], { header: false });
}
169 changes: 93 additions & 76 deletions packages/graph-explorer/src/modules/GraphViewer/GraphViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -154,83 +154,100 @@ function GraphViewerContent({
const isEmpty = !nodes.length && !edges.length;

return (
<div className={cn("size-full min-h-0 grow", className)} {...props}>
<Panel>
<PanelHeader>
<PanelTitle>Graph View</PanelTitle>
<PanelHeaderActions>
<SelectLayout
className="max-w-64 min-w-auto"
layoutAtom={graphLayoutSelectionAtom}
/>
<RerunLayoutButton />
<ZoomToFitButton />
<div className="grow" />
<DownloadScreenshotButton />
<ExportGraphButton />
<ImportGraphButton />
<PanelHeaderDivider />
<ZoomInButton />
<ZoomOutButton />
<PanelHeaderDivider />
<ClearCanvasButton />
<Button
tooltip="Legend"
variant="ghost"
size="icon"
onClick={() => setLegendOpen(open => !open)}
>
<BadgeInfoIcon />
</Button>
</PanelHeaderActions>
</PanelHeader>
<PanelContent className="bg-background-secondary grid" ref={parentRef}>
<Graph
nodes={nodes}
edges={edges}
badgesEnabled={false}
getNodeBadges={getNodeBadges(nodesOutRenderedIds)}
selectedNodesIds={selectedVertices}
selectedEdgesIds={selectedEdges}
outOfFocusNodesIds={nodesOutRenderedIds}
outOfFocusEdgesIds={edgesOutRenderedIds}
onSelectedElementIdsChange={onSelectedElementIdsChange}
onNodeDoubleClick={onNodeDoubleClick}
onNodeRightClick={onNodeRightClick}
onEdgeRightClick={onEdgeRightClick}
onGraphRightClick={onGraphRightClick}
styles={styles}
layout={layout}
className="col-start-1 row-start-1 min-h-0 min-w-0"
onContextMenu={onContextMenu}
/>
{isContextOpen &&
renderContextLayer(
<div
{...contextLayerProps}
style={contextLayerProps.style}
className="z-menu"
>
<ContextMenu
onClose={clearAllLayers}
affectedNodesIds={contextNodeId ? [contextNodeId] : []}
affectedEdgesIds={contextEdgeId ? [contextEdgeId] : []}
/>
</div>,
)}
<div style={{ padding: 40 }}>
<ContextMenu
onClose={() => {}}
affectedNodesIds={[]}
affectedEdgesIds={[]}
/>
</div>
);

<Activity mode={isVisible(isEmpty)}>
<GraphViewerEmptyState className="col-start-1 row-start-1" />
</Activity>
<Activity mode={isVisible(legendOpen)}>
<div className="z-20 col-start-1 row-start-1 grid min-h-0 justify-self-end p-3">
<Legend onClose={() => setLegendOpen(false)} />
</div>
</Activity>
</PanelContent>
</Panel>
</div>
);

// return (
// <div className={cn("size-full min-h-0 grow", className)} {...props}>
// <Panel>
// <PanelHeader>
// <PanelTitle>Graph View</PanelTitle>
// <PanelHeaderActions>
// <SelectLayout
// className="max-w-64 min-w-auto"
// layoutAtom={graphLayoutSelectionAtom}
// />
// <RerunLayoutButton />
// <ZoomToFitButton />
// <div className="grow" />
// <DownloadScreenshotButton />
// <ExportGraphButton />
// <ImportGraphButton />
// <PanelHeaderDivider />
// <ZoomInButton />
// <ZoomOutButton />
// <PanelHeaderDivider />
// <ClearCanvasButton />
// <Button
// tooltip="Legend"
// variant="ghost"
// size="icon"
// onClick={() => setLegendOpen(open => !open)}
// >
// <BadgeInfoIcon />
// </Button>
// </PanelHeaderActions>
// </PanelHeader>
// <PanelContent className="bg-background-secondary grid" ref={parentRef}>
// <Graph
// nodes={nodes}
// edges={edges}
// badgesEnabled={false}
// getNodeBadges={getNodeBadges(nodesOutRenderedIds)}
// selectedNodesIds={selectedVertices}
// selectedEdgesIds={selectedEdges}
// outOfFocusNodesIds={nodesOutRenderedIds}
// outOfFocusEdgesIds={edgesOutRenderedIds}
// onSelectedElementIdsChange={onSelectedElementIdsChange}
// onNodeDoubleClick={onNodeDoubleClick}
// onNodeRightClick={onNodeRightClick}
// onEdgeRightClick={onEdgeRightClick}
// onGraphRightClick={onGraphRightClick}
// styles={styles}
// layout={layout}
// className="col-start-1 row-start-1 min-h-0 min-w-0"
// onContextMenu={onContextMenu}
// />
// {/* {isContextOpen &&
// renderContextLayer(
// <div
// {...contextLayerProps}
// style={contextLayerProps.style}
// className="z-menu"
// >
// <ContextMenu
// onClose={clearAllLayers}
// affectedNodesIds={contextNodeId ? [contextNodeId] : []}
// affectedEdgesIds={contextEdgeId ? [contextEdgeId] : []}
// />
// </div>,
// )} */}
// <ContextMenu
// onClose={() => {}}
// affectedNodesIds={[]}
// affectedEdgesIds={[]}
// />


// <Activity mode={isVisible(isEmpty)}>
// <GraphViewerEmptyState className="col-start-1 row-start-1" />
// </Activity>
// <Activity mode={isVisible(legendOpen)}>
// <div className="z-20 col-start-1 row-start-1 grid min-h-0 justify-self-end p-3">
// <Legend onClose={() => setLegendOpen(false)} />
// </div>
// </Activity>
// </PanelContent>
// </Panel>
// </div>
// );
}

function Legend({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ import { cn } from "@/utils";

import { useGraphSelection } from "../useGraphSelection";

import { useRenderedVertices, useRenderedEdges } from "@/core";
import { getVertexIdFromRenderedVertexId, getEdgeIdFromRenderedEdgeId } from "@/core";

type ContextMenuProps = {
affectedNodesIds: VertexId[];
affectedEdgesIds: EdgeId[];
Expand Down Expand Up @@ -290,39 +293,100 @@ function MultipleEntitiesMenu({
}

function NoTargetMenu() {
const vertices = useRenderedVertices();
const edges = useRenderedEdges();

const {
onFitAllToCanvas,
onCenterGraph,
onSaveScreenshot,
onZoomIn,
onZoomOut,
} = useGraphGlobalActions();

const clearGraph = useClearGraph();
const { replaceGraphSelection } = useGraphSelection();

// 🔹 Select all nodes
const handleSelectAllNodes = () => {
replaceGraphSelection({
vertices: vertices.map(v =>
getVertexIdFromRenderedVertexId(v.data.id),
),
edges: [],
});
};

// 🔹 Select all edges
const handleSelectAllEdges = () => {
replaceGraphSelection({
vertices: [],
edges: edges.map(e =>
getEdgeIdFromRenderedEdgeId(e.data.id),
),
});
};

// 🔹 Select all nodes + edges
const handleSelectAll = () => {
replaceGraphSelection({
vertices: vertices.map(v =>
getVertexIdFromRenderedVertexId(v.data.id),
),
edges: edges.map(e =>
getEdgeIdFromRenderedEdgeId(e.data.id),
),
});
};

return (
<ContextMenuContent>
<ContextMenuItem onClick={onFitAllToCanvas}>
<FullscreenIcon />
Fit to frame
</ContextMenuItem>

<ContextMenuItem onClick={onCenterGraph}>
<CenterGraphIcon />
Center
</ContextMenuItem>

<ContextMenuItem onClick={onSaveScreenshot}>
<ImageDownIcon />
Download screenshot
</ContextMenuItem>

<Divider />

<ContextMenuItem onClick={onZoomIn}>
<ZoomInIcon />
Zoom in
</ContextMenuItem>

<ContextMenuItem onClick={onZoomOut}>
<ZoomOutIcon />
Zoom out
</ContextMenuItem>

<Divider />

<ContextMenuItem onClick={handleSelectAllNodes}>
<GraphIcon />
Select all nodes
</ContextMenuItem>

<ContextMenuItem onClick={handleSelectAllEdges}>
<EdgeIcon />
Select all edges
</ContextMenuItem>

<ContextMenuItem onClick={handleSelectAll}>
<GraphIcon />
Select all
</ContextMenuItem>

<Divider />

<ContextMenuItem onClick={clearGraph}>
<CircleSlash2 color="red" />
Clear canvas
Expand Down