Skip to content

Commit

Permalink
Entity type editor – Show correct properties in property selector, ad…
Browse files Browse the repository at this point in the history
…d edit bar, and minor changes (#1184)
  • Loading branch information
nathggns authored Oct 12, 2022
1 parent 22bd892 commit 2646115
Show file tree
Hide file tree
Showing 16 changed files with 733 additions and 417 deletions.
18 changes: 18 additions & 0 deletions packages/hash/frontend/src/lib/use-init-type-system.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import init from "@blockprotocol/type-system-web";
import { useEffect, useState } from "react";

export const useInitTypeSystem = () => {
const [loadingTypeSystem, setLoadingTypeSystem] = useState(true);

useEffect(() => {
if (loadingTypeSystem) {
void (async () => {
await init().then(() => {
setLoadingTypeSystem(false);
});
})();
}
}, [loadingTypeSystem, setLoadingTypeSystem]);

return loadingTypeSystem;
};
Original file line number Diff line number Diff line change
@@ -1,151 +1,199 @@
import { EntityType } from "@blockprotocol/type-system-web";
import { EntityType, PropertyType } from "@blockprotocol/type-system-web";
import { faAsterisk } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@hashintel/hash-design-system/fontawesome-icon";
import { Box, Container, Stack, Typography } from "@mui/material";
import { Box, Collapse, Container, Stack, Typography } from "@mui/material";
import { useRouter } from "next/router";
import { useEffect, useRef, useState } from "react";
import { useEffect, useLayoutEffect, useRef, useState } from "react";
import { useBlockProtocolGetEntityType } from "../../../../components/hooks/blockProtocolFunctions/ontology/useBlockProtocolGetEntityType";
import { FRONTEND_URL } from "../../../../lib/config";
import { useInitTypeSystem } from "../../../../lib/use-init-type-system";
import { getPlainLayout, NextPageWithLayout } from "../../../../shared/layout";
import { TopContextBar } from "../../../shared/top-context-bar";
import { EmptyPropertyListCard } from "./empty-property-list-card";
import { EditBar } from "./edit-bar";
import { HashOntologyIcon } from "./hash-ontology-icon";
import { OntologyChip } from "./ontology-chip";
import { PlaceholderIcon } from "./placeholder-icon";
import { InsertPropertyCard } from "./property-list-card";
import { useStateCallback } from "./util";
import { PropertyListCard } from "./property-list-card";
import {
PropertyTypesContext,
useRemotePropertyTypes,
} from "./use-property-types";

const useEntityType = (entityTypeSlug: string) => {
const useEntityType = (entityTypeId: string, onCompleted?: () => void) => {
const { getEntityType } = useBlockProtocolGetEntityType();
const [entityType, setEntityType] = useState<EntityType | null>(null);

const onCompletedRef = useRef(onCompleted);

useLayoutEffect(() => {
onCompletedRef.current = onCompleted;
});

useEffect(() => {
void getEntityType({
// @todo get latest version somehow?
data: { entityTypeId: `${FRONTEND_URL}${entityTypeSlug}/v/1` },
data: { entityTypeId },
}).then((value) => {
if (value.data) {
setEntityType(value.data.entityType);
onCompletedRef.current?.();
}
});
}, [getEntityType, entityTypeSlug]);
}, [getEntityType, entityTypeId]);

return entityType;
};

// @todo loading state
// @todo handle displaying entity type not yet created
const Page: NextPageWithLayout = () => {
const [mode, setMode] = useStateCallback<"empty" | "inserting">("empty");
const insertFieldRef = useRef<HTMLInputElement>(null);

const router = useRouter();
const entityType = useEntityType(router.asPath);
const [insertedPropertyTypes, setInsertedPropertyTypes] = useState<
PropertyType[]
>([]);
const [removedPropertyTypes, setRemovedPropertyTypes] = useState<
PropertyType[]
>([]);

// @todo find this out somehow
const currentVersion = 1;
const entityTypeId = `${FRONTEND_URL}/${router.query["account-slug"]}/types/entity-type/${router.query["entity-type-id"]}/v/${currentVersion}`;

if (!entityType) {
const entityType = useEntityType(entityTypeId, () => {
setInsertedPropertyTypes([]);
setRemovedPropertyTypes([]);
});

const propertyTypes = useRemotePropertyTypes();
const loadingTypeSystem = useInitTypeSystem();

if (!entityType || loadingTypeSystem) {
return null;
}

return (
<Box
component={Stack}
sx={(theme) => ({
minHeight: "100vh",
background: theme.palette.gray[10],
})}
>
<Box bgcolor="white" borderBottom={1} borderColor="gray.20">
<TopContextBar
defaultCrumbIcon={null}
crumbs={[
{
title: "Types",
href: "#",
id: "types",
},
{
title: "Entity types",
href: "#",
id: "entity-types",
},
{
title: entityType.title,
href: "#",
id: entityType.$id,
icon: <FontAwesomeIcon icon={faAsterisk} />,
},
]}
scrollToTop={() => {}}
/>
<Box pt={3.75}>
<Container>
<OntologyChip
icon={<PlaceholderIcon />}
domain="hash.ai"
path={
<>
<Typography
component="span"
fontWeight="bold"
color={(theme) => theme.palette.blue[70]}
>
{router.query["account-slug"]}
</Typography>
<Typography
component="span"
color={(theme) => theme.palette.blue[70]}
>
/types/entity-types/
</Typography>
<Typography
component="span"
fontWeight="bold"
color={(theme) => theme.palette.blue[70]}
>
{router.query["entity-type-id"]}
</Typography>
</>
}
<PropertyTypesContext.Provider value={propertyTypes}>
<Box
component={Stack}
sx={(theme) => ({
minHeight: "100vh",
background: theme.palette.gray[10],
})}
>
<Box bgcolor="white" borderBottom={1} borderColor="gray.20">
<TopContextBar
defaultCrumbIcon={null}
crumbs={[
{
title: "Types",
href: "#",
id: "types",
},
{
title: "Entity types",
href: "#",
id: "entity-types",
},
{
title: entityType.title,
href: "#",
id: entityType.$id,
icon: <FontAwesomeIcon icon={faAsterisk} />,
},
]}
scrollToTop={() => {}}
/>
<Collapse
in={insertedPropertyTypes.length + removedPropertyTypes.length > 0}
>
<EditBar
currentVersion={currentVersion}
onDiscardChanges={() => {
setInsertedPropertyTypes([]);
setRemovedPropertyTypes([]);
}}
/>
<Typography variant="h1" fontWeight="bold" mt={3} mb={4.5}>
<FontAwesomeIcon
icon={faAsterisk}
sx={(theme) => ({
fontSize: 40,
mr: 3,
color: theme.palette.gray[70],
verticalAlign: "middle",
})}
</Collapse>
<Box pt={3.75}>
<Container>
<OntologyChip
icon={<HashOntologyIcon />}
domain="hash.ai"
path={
<>
<Typography
component="span"
fontWeight="bold"
color={(theme) => theme.palette.blue[70]}
>
{router.query["account-slug"]}
</Typography>
<Typography
component="span"
color={(theme) => theme.palette.blue[70]}
>
/types/entity-types/
</Typography>
<Typography
component="span"
fontWeight="bold"
color={(theme) => theme.palette.blue[70]}
>
{router.query["entity-type-id"]}
</Typography>
</>
}
/>
{entityType.title}
</Typography>
</Container>
<Typography variant="h1" fontWeight="bold" mt={3} mb={4.5}>
<FontAwesomeIcon
icon={faAsterisk}
sx={(theme) => ({
fontSize: 40,
mr: 3,
color: theme.palette.gray[70],
verticalAlign: "middle",
})}
/>
{entityType.title}
</Typography>
</Container>
</Box>
</Box>
</Box>
<Box py={5}>
<Container>
<Typography variant="h5" mb={1.25}>
Properties of{" "}
<Box component="span" sx={{ fontWeight: "bold" }}>
{entityType.title}
</Box>
</Typography>
{mode === "empty" ? (
<EmptyPropertyListCard
onClick={() => {
setMode("inserting", () => {
insertFieldRef.current?.focus();
});
<Box py={5}>
<Container>
<Typography variant="h5" mb={1.25}>
Properties of{" "}
<Box component="span" sx={{ fontWeight: "bold" }}>
{entityType.title}
</Box>
</Typography>
<PropertyListCard
propertyTypes={insertedPropertyTypes}
onRemovePropertyType={(propertyType) => {
if (insertedPropertyTypes.includes(propertyType)) {
const nextInsertedPropertyTypes =
insertedPropertyTypes.filter(
(type) => type !== propertyType,
);
setInsertedPropertyTypes(nextInsertedPropertyTypes);
} else if (!removedPropertyTypes.includes(propertyType)) {
setRemovedPropertyTypes([
...removedPropertyTypes,
propertyType,
]);
}
}}
/>
) : (
<InsertPropertyCard
insertFieldRef={insertFieldRef}
onCancel={() => {
setMode("empty");
onAddPropertyType={(propertyType) => {
if (!insertedPropertyTypes.includes(propertyType)) {
setInsertedPropertyTypes([
...insertedPropertyTypes,
propertyType,
]);
}
}}
/>
)}
</Container>
</Container>
</Box>
</Box>
</Box>
</PropertyTypesContext.Provider>
);
};

Expand Down
Loading

0 comments on commit 2646115

Please sign in to comment.