Skip to content

Commit

Permalink
Rollback serialized id type (#773)
Browse files Browse the repository at this point in the history
* Pass request to query key

* Make blank nodes map keyed on VertexId

* Make sure updatePrefixes is sent string

* Allow entity ID to be number or string
  • Loading branch information
kmcginnes authored Jan 31, 2025
1 parent 1c30d87 commit 1e5972d
Show file tree
Hide file tree
Showing 19 changed files with 467 additions and 165 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useEffect, useRef } from "react";
import { Vertex } from "@/core";
import { RenderedVertex } from "@/core";
import { DrawBoxWithAdornmentOptions } from "@/components/utils";
import drawBoxWithAdornment from "@/components/utils/canvas/drawBoxWithAdornment";
import type {
Expand All @@ -17,7 +17,7 @@ export type Badge = DrawBoxWithAdornmentOptions & {
};

export type BadgeRenderer = (
nodeData: Vertex,
nodeData: RenderedVertex["data"],
boundingBox: BoundingBox,
options: {
context: CanvasRenderingContext2D;
Expand Down Expand Up @@ -113,7 +113,7 @@ const useRenderBadges = ({
// Draw model elements
cy.nodes().forEach(node => {
const zoomLevel = getZoomLevel(cy);
const nodeData = node.data() as Vertex;
const nodeData = node.data() as RenderedVertex["data"];

if (
node.style("display") === "none" ||
Expand Down
25 changes: 13 additions & 12 deletions packages/graph-explorer/src/connector/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ export function searchQuery(
});
}

export type NeighborCountsQueryRequest = {
vertexId: VertexId;
};

export type NeighborCountsQueryResponse = {
nodeId: VertexId;
totalCount: number;
Expand All @@ -53,16 +57,15 @@ export type NeighborCountsQueryResponse = {
* @returns The count of neighbors for the given node as a total and per type.
*/
export function neighborsCountQuery(
vertexId: VertexId,
request: NeighborCountsQueryRequest,
explorer: Explorer | null
) {
return queryOptions({
queryKey: ["neighborsCount", vertexId, explorer],
enabled: Boolean(explorer),
queryKey: ["neighborsCount", request, explorer],
queryFn: async (): Promise<NeighborCountsQueryResponse> => {
if (!explorer) {
return {
nodeId: vertexId,
nodeId: request.vertexId,
totalCount: 0,
counts: {},
};
Expand All @@ -71,12 +74,12 @@ export function neighborsCountQuery(
const limit = explorer.connection.nodeExpansionLimit;

const result = await explorer.fetchNeighborsCount({
vertexId,
vertexId: request.vertexId,
limit,
});

return {
nodeId: vertexId,
nodeId: request.vertexId,
totalCount: result.totalCount,
counts: result.counts,
};
Expand Down Expand Up @@ -108,14 +111,13 @@ export function vertexDetailsQuery(
request: VertexDetailsRequest,
explorer: Explorer | null
) {
const vertexId = request.vertexId;
return queryOptions({
queryKey: ["db", "vertex", "details", vertexId, explorer],
queryKey: ["db", "vertex", "details", request, explorer],
queryFn: async ({ signal }): Promise<VertexDetailsResponse> => {
if (!explorer) {
return { vertex: null };
}
return await explorer.vertexDetails({ vertexId }, { signal });
return await explorer.vertexDetails(request, { signal });
},
});
}
Expand All @@ -124,14 +126,13 @@ export function edgeDetailsQuery(
request: EdgeDetailsRequest,
explorer: Explorer | null
) {
const edgeId = request.edgeId;
return queryOptions({
queryKey: ["db", "edge", "details", edgeId, explorer],
queryKey: ["db", "edge", "details", request, explorer],
queryFn: async ({ signal }): Promise<EdgeDetailsResponse> => {
if (!explorer) {
return { edge: null };
}
return await explorer.edgeDetails({ edgeId }, { signal });
return await explorer.edgeDetails(request, { signal });
},
});
}
Expand Down
5 changes: 2 additions & 3 deletions packages/graph-explorer/src/connector/sparql/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
createEdgeId,
createVertexId,
Edge,
EdgeId,
Expand Down Expand Up @@ -169,7 +168,7 @@ export type BlankNodeItem = {
};
};

export type BlankNodesMap = Map<string, BlankNodeItem>;
export type BlankNodesMap = Map<VertexId, BlankNodeItem>;

export type GraphSummary = {
numDistinctSubjects: number;
Expand Down Expand Up @@ -256,7 +255,7 @@ export function parseEdgeId(edgeId: EdgeId): {

return {
source: createVertexId(match[1].trim()),
predicate: createEdgeId(match[2].trim()),
predicate: match[2].trim(),
target: createVertexId(match[3].trim()),
};
}
41 changes: 40 additions & 1 deletion packages/graph-explorer/src/core/StateProvider/edges.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { atom, selector, selectorFamily } from "recoil";
import type { Edge, EdgeId } from "@/core";
import {
createRenderedEdgeId,
getEdgeIdFromRenderedEdgeId,
type Edge,
type EdgeId,
} from "@/core";
import isDefaultValue from "./isDefaultValue";
import { nodesFilteredIdsAtom, nodesTypesFilteredAtom } from "./nodes";

Expand Down Expand Up @@ -59,11 +64,45 @@ export const edgesSelectedIdsAtom = atom<Set<EdgeId>>({
default: new Set(),
});

export const edgesSelectedRenderedIdsAtom = selector({
key: "edges-selected-rendered-ids",
get: ({ get }) =>
new Set(get(edgesSelectedIdsAtom).values().map(createRenderedEdgeId)),
set: ({ set }, newValue) => {
if (isDefaultValue(newValue)) {
set(edgesSelectedIdsAtom, newValue);
return;
}

set(
edgesSelectedIdsAtom,
new Set(newValue.values().map(getEdgeIdFromRenderedEdgeId))
);
},
});

export const edgesOutOfFocusIdsAtom = atom<Set<EdgeId>>({
key: "edges-out-of-focus-ids",
default: new Set(),
});

export const edgesOutOfFocusRenderedIdsAtom = selector({
key: "edges-out-of-focus-rendered-ids",
get: ({ get }) =>
new Set(get(edgesOutOfFocusIdsAtom).values().map(createRenderedEdgeId)),
set: ({ set }, newValue) => {
if (isDefaultValue(newValue)) {
set(edgesOutOfFocusIdsAtom, newValue);
return;
}

set(
edgesOutOfFocusIdsAtom,
new Set(newValue.values().map(getEdgeIdFromRenderedEdgeId))
);
},
});

export const edgesFilteredIdsAtom = atom<Set<EdgeId>>({
key: "edges-filtered-ids",
default: new Set(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export function useNeighborsCallback() {
);
const explorer = await snapshot.getPromise(explorerSelector);
const response = await queryClient.ensureQueryData(
neighborsCountQuery(vertexId, explorer)
neighborsCountQuery({ vertexId }, explorer)
);

const neighbors = calculateNeighbors(
Expand Down
41 changes: 40 additions & 1 deletion packages/graph-explorer/src/core/StateProvider/nodes.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { atom, selector, selectorFamily, useRecoilValue } from "recoil";
import type { Vertex, VertexId } from "@/core";
import {
createRenderedVertexId,
getVertexIdFromRenderedVertexId,
type Vertex,
type VertexId,
} from "@/core";
import isDefaultValue from "./isDefaultValue";

export function toNodeMap(nodes: Vertex[]): Map<VertexId, Vertex> {
Expand Down Expand Up @@ -55,11 +60,45 @@ export const nodesSelectedIdsAtom = atom<Set<VertexId>>({
default: new Set(),
});

export const nodesSelectedRenderedIdsAtom = selector({
key: "nodes-selected-rendered-ids",
get: ({ get }) =>
new Set(get(nodesSelectedIdsAtom).values().map(createRenderedVertexId)),
set: ({ set }, newValue) => {
if (isDefaultValue(newValue)) {
set(nodesSelectedIdsAtom, newValue);
return;
}

set(
nodesSelectedIdsAtom,
new Set(newValue.values().map(getVertexIdFromRenderedVertexId))
);
},
});

export const nodesOutOfFocusIdsAtom = atom<Set<VertexId>>({
key: "nodes-out-of-focus-ids",
default: new Set(),
});

export const nodesOutOfFocusRenderedIdsAtom = selector({
key: "nodes-out-of-focus-rendered-ids",
get: ({ get }) =>
new Set(get(nodesOutOfFocusIdsAtom).values().map(createRenderedVertexId)),
set: ({ set }, newValue) => {
if (isDefaultValue(newValue)) {
set(nodesOutOfFocusIdsAtom, newValue);
return;
}

set(
nodesOutOfFocusIdsAtom,
new Set(newValue.values().map(getVertexIdFromRenderedVertexId))
);
},
});

export const nodesFilteredIdsAtom = atom<Set<VertexId>>({
key: "nodes-filtered-ids",
default: new Set(),
Expand Down
4 changes: 2 additions & 2 deletions packages/graph-explorer/src/core/entities.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Branded } from "@/utils";

export type EdgeId = Branded<string, "EdgeId">;
export type VertexId = Branded<string, "VertexId">;
export type EdgeId = Branded<string | number, "EdgeId">;
export type VertexId = Branded<string | number, "VertexId">;

export type Vertex = {
/**
Expand Down
12 changes: 6 additions & 6 deletions packages/graph-explorer/src/core/entityIdType.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,35 @@ import { createEdgeId, createVertexId, getRawId } from "./entityIdType";
describe("createVertexId", () => {
it("should create a vertex id out of a string", () => {
const id = createVertexId("123");
expect(id).toBe("(str)123");
expect(id).toBe("123");
});

it("should create a vertex id out of a number", () => {
const id = createVertexId(123);
expect(id).toBe("(num)123");
expect(id).toBe(123);
});
});

describe("createEdgeId", () => {
it("should create an edge id out of a string", () => {
const id = createEdgeId("123");
expect(id).toBe("(str)123");
expect(id).toBe("123");
});

it("should create an edge id out of a number", () => {
const id = createEdgeId(123);
expect(id).toBe("(num)123");
expect(id).toBe(123);
});
});

describe("getRawId", () => {
it("should return the raw string id without the prefix", () => {
const id = getRawId("(str)123" as VertexId);
const id = getRawId(createVertexId("123"));
expect(id).toBe("123");
});

it("should return the raw number id without the prefix", () => {
const id = getRawId("(num)123" as VertexId);
const id = getRawId(createVertexId(123));
expect(id).toBe(123);
});

Expand Down
45 changes: 4 additions & 41 deletions packages/graph-explorer/src/core/entityIdType.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
import { VertexId, EdgeId } from "@/core";

/**
* Creates a VertexId that is a string prefixed with the ID type.
* Creates a VertexId from the given database ID.
* @param id The original database ID
* @returns A VertexId that is a string prefixed with the ID type
*/
export function createVertexId(id: string | number): VertexId {
return prefixIdWithType(id) as VertexId;
return id as VertexId;
}

/**
* Creates an EdgeId that is a string prefixed with the ID type.
* Creates an EdgeId from the given database ID.
* @param id The original database ID
* @returns An EdgeId that is a string prefixed with the ID type
*/
export function createEdgeId(id: string | number): EdgeId {
return prefixIdWithType(id) as EdgeId;
return id as EdgeId;
}

/**
Expand All @@ -24,40 +22,5 @@ export function createEdgeId(id: string | number): EdgeId {
* @returns The original database ID without the ID type prefix
*/
export function getRawId(id: VertexId | EdgeId): string | number {
if (isIdNumber(id)) {
return parseInt(stripIdTypePrefix(id));
}
if (isIdString(id)) {
return stripIdTypePrefix(id);
}
return id;
}

const ID_TYPE_NUM_PREFIX = "(num)";
const ID_TYPE_STR_PREFIX = "(str)";

function prefixIdWithType(id: string | number): string {
if (typeof id === "number") {
return `${ID_TYPE_NUM_PREFIX}${id}`;
}

return `${ID_TYPE_STR_PREFIX}${id}`;
}

function isIdNumber(id: string): boolean {
return id.startsWith(ID_TYPE_NUM_PREFIX);
}

function isIdString(id: string): boolean {
return id.startsWith(ID_TYPE_STR_PREFIX);
}

function stripIdTypePrefix(id: string): string {
if (isIdNumber(id)) {
return id.slice(ID_TYPE_NUM_PREFIX.length);
}
if (isIdString(id)) {
return id.slice(ID_TYPE_STR_PREFIX.length);
}
return id;
}
1 change: 1 addition & 0 deletions packages/graph-explorer/src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from "./StateProvider";
export * from "./connector";
export * from "./entityIdType";
export * from "./entities";
export * from "./renderedEntities";
Loading

0 comments on commit 1e5972d

Please sign in to comment.