Skip to content

Commit

Permalink
conseqential fixes in type-graph-visualizer
Browse files Browse the repository at this point in the history
  • Loading branch information
CiaranMn committed Oct 8, 2024
1 parent c7c435a commit 33c5aea
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,17 @@ interface EditEntitySlideOverProps {
*/
entityId?: EntityId;
/**
* If a modal container ref is provided, the modal will be attached to it (defaults to the MUI default, the body)
* If a container ref is provided, the slide will be attached to it (defaults to the MUI default, the body)
*/
modalContainerRef?: RefObject<HTMLDivElement>;
slideContainerRef?: RefObject<HTMLDivElement>;
}

/**
* @todo move this to a shared location (it's also used in the Flows output and draft entities views)
*/
export const EditEntitySlideOver = ({
hideOpenInNew,
modalContainerRef,
slideContainerRef,
open,
onClose,
onSubmit,
Expand Down Expand Up @@ -284,7 +284,7 @@ export const EditEntitySlideOver = ({
onClose={onClose}
anchor="right"
ModalProps={{
container: modalContainerRef?.current ?? undefined,
container: slideContainerRef?.current ?? undefined,
}}
PaperProps={{
sx: (theme) => ({
Expand Down
21 changes: 12 additions & 9 deletions apps/hash-frontend/src/pages/shared/entities-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,10 @@ export const EntitiesTable: FunctionComponent<{
});
const [showSearch, setShowSearch] = useState<boolean>(false);

const [selectedEntityTypeId, setSelectedEntityTypeId] =
useState<VersionedUrl | null>(null);
const [selectedEntityType, setSelectedEntityType] = useState<{
entityTypeId: VersionedUrl;
slideContainerRef?: RefObject<HTMLDivElement>;
} | null>(null);

const {
entityTypeBaseUrl,
Expand Down Expand Up @@ -224,7 +226,7 @@ export const EntitiesTable: FunctionComponent<{

const [selectedEntity, setSelectedEntity] = useState<{
entityId: EntityId;
modalContainerRef?: RefObject<HTMLDivElement>;
slideContainerRef?: RefObject<HTMLDivElement>;
subgraph: Subgraph<EntityRootType>;
} | null>(null);

Expand All @@ -241,7 +243,7 @@ export const EntitiesTable: FunctionComponent<{

setSelectedEntity({
entityId,
modalContainerRef,
slideContainerRef: modalContainerRef,
subgraph: entitySubgraph,
});
}
Expand Down Expand Up @@ -317,7 +319,7 @@ export const EntitiesTable: FunctionComponent<{
if (columnId === "web") {
void router.push(`/${cellValue}`);
} else {
setSelectedEntityTypeId(row.entityTypeId);
setSelectedEntityType({ entityTypeId: row.entityTypeId });
}
},
},
Expand Down Expand Up @@ -680,10 +682,11 @@ export const EntitiesTable: FunctionComponent<{

return (
<>
{selectedEntityTypeId && (
{selectedEntityType && (
<TypeSlideOverStack
rootTypeId={selectedEntityTypeId}
onClose={() => setSelectedEntityTypeId(null)}
rootTypeId={selectedEntityType.entityTypeId}
onClose={() => setSelectedEntityType(null)}
slideContainerRef={selectedEntityType.slideContainerRef}
/>
)}
{selectedEntity ? (
Expand All @@ -702,7 +705,7 @@ export const EntitiesTable: FunctionComponent<{
If we've been given a specific DOM element to contain the modal, pass it here.
This is for use when attaching to the body is not suitable (e.g. a specific DOM element is full-screened).
*/
modalContainerRef={selectedEntity.modalContainerRef}
slideContainerRef={selectedEntity.slideContainerRef}
open
onClose={() => setSelectedEntity(null)}
readonly
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import type { VersionedUrl } from "@blockprotocol/type-system";
import { Backdrop } from "@mui/material";
import type { FunctionComponent } from "react";
import type { FunctionComponent, RefObject } from "react";
import { useCallback, useState } from "react";

import { TypeSlideOverSlide } from "./type-slide-over-stack/type-slide-over-slide";

export const TypeSlideOverStack: FunctionComponent<{
rootTypeId: VersionedUrl;
onClose: () => void;
}> = ({ rootTypeId, onClose }) => {
/**
* If a container ref is provided, the slide will be attached to it (defaults to the MUI default, the body)
*/
slideContainerRef?: RefObject<HTMLDivElement>;
}> = ({ rootTypeId, onClose, slideContainerRef }) => {
const [animateOut, setAnimateOut] = useState(false);
const [items, setItems] = useState<VersionedUrl[]>([rootTypeId]);
const [currentIndex, setCurrentIndex] = useState<number>(0);
Expand Down Expand Up @@ -59,6 +63,7 @@ export const TypeSlideOverStack: FunctionComponent<{
onForward={index < items.length - 1 ? handleForward : undefined}
onClose={handleClose}
onNavigateToType={handleNavigateToType}
slideContainerRef={slideContainerRef}
typeUrl={typeId}
stackPosition={index}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
import type { EntityTypeWithMetadata } from "@local/hash-graph-types/ontology";
import { componentsFromVersionedUrl } from "@local/hash-subgraph/type-system-patch";
import { Box, ButtonBase, Slide, Tooltip } from "@mui/material";
import type { FunctionComponent } from "react";
import type { FunctionComponent, RefObject } from "react";
import { useCallback, useMemo, useState } from "react";

import { useEntityTypesContextRequired } from "../../../../shared/entity-types-context/hooks/use-entity-types-context-required";
Expand Down Expand Up @@ -109,6 +109,10 @@ interface TypeSlideOverSlideProps {
onForward?: () => void;
onClose: () => void;
onNavigateToType: (url: VersionedUrl) => void;
/**
* If a container ref is provided, the slide will be attached to it (defaults to the MUI default, the body)
*/
slideContainerRef?: RefObject<HTMLDivElement>;
typeUrl: VersionedUrl;
}

Expand All @@ -120,6 +124,7 @@ export const TypeSlideOverSlide: FunctionComponent<TypeSlideOverSlideProps> = ({
onBack,
onClose,
onForward,
slideContainerRef,
}) => {
const { loading: loadingNamespace, routeNamespace } = useRouteNamespace();

Expand Down Expand Up @@ -185,6 +190,7 @@ export const TypeSlideOverSlide: FunctionComponent<TypeSlideOverSlideProps> = ({

return (
<Slide
container={slideContainerRef?.current ?? undefined}
in={open && !animateOut}
direction="left"
onClick={(event) => event.stopPropagation()}
Expand Down
68 changes: 39 additions & 29 deletions apps/hash-frontend/src/pages/shared/type-graph-visualizer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type {
PropertyTypeWithMetadata,
} from "@local/hash-graph-types/ontology";
import { useTheme } from "@mui/material";
import type { RefObject } from "react";
import { useCallback, useMemo } from "react";

import { useEntityTypesContextRequired } from "../../shared/entity-types-context/hooks/use-entity-types-context-required";
Expand All @@ -18,11 +19,23 @@ import type {

const anythingNodeId = "anything";

const defaultConfig = {
graphKey: "type-graph",
nodeHighlighting: {
direction: "All",
depth: 1,
},
nodeSizing: { mode: "static" },
} as const;

export const TypeGraphVisualizer = ({
onTypeClick,
types,
}: {
onTypeClick: (typeId: VersionedUrl) => void;
onTypeClick: (
typeId: VersionedUrl,
screenContainerRef?: RefObject<HTMLDivElement>,
) => void;
types: (
| DataTypeWithMetadata
| EntityTypeWithMetadata
Expand All @@ -38,6 +51,7 @@ export const TypeGraphVisualizer = ({
const nodesToAdd: GraphVizNode[] = [];

const addedNodeIds = new Set<string>();
const addedEdgeIds = new Set<string>();

const anythingNode: GraphVizNode = {
color: palette.gray[30],
Expand Down Expand Up @@ -109,7 +123,7 @@ export const TypeGraphVisualizer = ({
* The id is therefore based on the link type and the destination types.
*/
const linkNodeId = `${linkTypeId}~${
destinationTypeIds?.join("-") ?? "anything"
destinationTypeIds?.sort().join("-") ?? "anything"
}`;

if (!addedNodeIds.has(linkNodeId)) {
Expand Down Expand Up @@ -143,12 +157,16 @@ export const TypeGraphVisualizer = ({
continue;
}

edgesToAdd.push({
edgeId: `${linkNodeId}~${destinationTypeId}`,
size: 3,
source: linkNodeId,
target: destinationTypeId,
});
const edgeId = `${linkNodeId}~${destinationTypeId}`;
if (!addedEdgeIds.has(edgeId)) {
edgesToAdd.push({
edgeId: `${linkNodeId}~${destinationTypeId}`,
size: 3,
source: linkNodeId,
target: destinationTypeId,
});
addedEdgeIds.add(edgeId);
}
}
} else {
/**
Expand Down Expand Up @@ -184,12 +202,16 @@ export const TypeGraphVisualizer = ({
linkNodesByEntityTypeId[linkTypeId].instanceIds.push(linkNodeId);
}

edgesToAdd.push({
edgeId: `${entityTypeId}~${linkNodeId}`,
size: 3,
source: entityTypeId,
target: linkNodeId,
});
const edgeId = `${entityTypeId}~${linkNodeId}`;
if (!addedEdgeIds.has(edgeId)) {
edgesToAdd.push({
edgeId,
size: 3,
source: entityTypeId,
target: linkNodeId,
});
addedEdgeIds.add(edgeId);
}
}
}

Expand Down Expand Up @@ -220,33 +242,21 @@ export const TypeGraphVisualizer = ({
const onNodeClick = useCallback<
NonNullable<GraphVisualizerProps["onNodeSecondClick"]>
>(
({ nodeId, isFullScreen }) => {
({ nodeId, screenContainerRef }) => {
if (nodeId === anythingNodeId) {
return;
}

if (isFullScreen) {
return;
}

const typeVersionedUrl = nodeId.split("~")[0] as VersionedUrl;

onTypeClick(typeVersionedUrl);
onTypeClick(typeVersionedUrl, screenContainerRef);
},
[onTypeClick],
);

return (
<GraphVisualizer
defaultConfig={{
filters: {},
graphKey: "type-graph",
nodeHighlighting: {
direction: "All",
depth: 1,
},
nodeSizing: { mode: "static" },
}}
defaultConfig={defaultConfig}
onNodeSecondClick={onNodeClick}
edges={edges}
nodes={nodes}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { isExternalOntologyElementMetadata } from "@local/hash-subgraph";
import { Box, useTheme } from "@mui/material";
import { format } from "date-fns";
import { useRouter } from "next/router";
import type { FunctionComponent } from "react";
import type { FunctionComponent, RefObject } from "react";
import { useCallback, useMemo, useRef, useState } from "react";

import {
Expand Down Expand Up @@ -125,8 +125,10 @@ export const TypesTable: FunctionComponent<{
limitToWebs: false,
});

const [selectedEntityTypeId, setSelectedEntityTypeId] =
useState<VersionedUrl | null>(null);
const [selectedEntityType, setSelectedEntityType] = useState<{
entityTypeId: VersionedUrl;
slideContainerRef?: RefObject<HTMLDivElement>;
} | null>(null);

const { isSpecialEntityTypeLookup } = useEntityTypesContextRequired();

Expand Down Expand Up @@ -355,7 +357,7 @@ export const TypesTable: FunctionComponent<{
value: row.title,
onClick: () => {
if (row.kind === "entity-type") {
setSelectedEntityTypeId(row.typeId);
setSelectedEntityType({ entityTypeId: row.typeId });
} else {
void router.push(generateLinkParameters(row.typeId).href);
}
Expand Down Expand Up @@ -456,12 +458,22 @@ export const TypesTable: FunctionComponent<{

const currentlyDisplayedRowsRef = useRef<TypesTableRow[] | null>(null);

const onTypeClick = useCallback(
(typeId: VersionedUrl, slideContainerRef?: RefObject<HTMLDivElement>) =>
setSelectedEntityType({
entityTypeId: typeId,
slideContainerRef,
}),
[],
);

return (
<>
{selectedEntityTypeId && (
{selectedEntityType && (
<TypeSlideOverStack
rootTypeId={selectedEntityTypeId}
onClose={() => setSelectedEntityTypeId(null)}
rootTypeId={selectedEntityType.entityTypeId}
onClose={() => setSelectedEntityType(null)}
slideContainerRef={selectedEntityType.slideContainerRef}
/>
)}
<Box>
Expand Down Expand Up @@ -530,7 +542,7 @@ export const TypesTable: FunctionComponent<{
) : (
<Box height={maxTableHeight}>
<TypeGraphVisualizer
onTypeClick={setSelectedEntityTypeId}
onTypeClick={onTypeClick}
types={filteredTypes}
/>
</Box>
Expand Down

0 comments on commit 33c5aea

Please sign in to comment.