Skip to content

Commit

Permalink
H-3686, H-3700, H-3775: Introduce new data type selector (#5864)
Browse files Browse the repository at this point in the history
  • Loading branch information
CiaranMn authored Dec 12, 2024
1 parent 171998e commit 6c9fae7
Show file tree
Hide file tree
Showing 33 changed files with 1,322 additions and 428 deletions.
5 changes: 3 additions & 2 deletions apps/hash-api/src/graphql/resolvers/ontology/entity-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,9 @@ export const getClosedMultiEntityTypeResolver: ResolverFn<
graphQLContext.authentication,
{
entityTypeIds,
// All references to other types are resolved, and those types provided under 'definitions' in the response
includeResolved: "resolved",
// All references to other types are resolved, and those types provided under 'definitions' in the response,
// including the children of any data types which are resolved (to allow picking more specific types)
includeResolved: "resolvedWithDataTypeChildren",
includeDrafts: includeDrafts ?? false,
temporalAxes: includeArchived
? fullTransactionTimeAxis
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,8 @@ import { InteractableManager } from "./interactable-manager";

const ScrollLockWrapper = ({ children }: PropsWithChildren) => {
/**
* We're locking scroll on `main` element,
* because our table components are rendered inside `LayoutWithSidebar`.
* Which has the overflow-y happening on `main` instead of `body` or `html`
* So we need to lock `main` elements scroll when grid editors are visible
* */

* The editBarContext provides the node that will have vertical scroll when the page is longer than the viewport
*/
const editBarContext = useEditBarContext();

useScrollLock(true, editBarContext?.scrollingNode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ const Page: NextPageWithLayout = () => {
hasLeftEntity: { outgoing: 1, incoming: 1 },
hasRightEntity: { outgoing: 1, incoming: 1 },
},
includeEntityTypes: "resolved",
includeEntityTypes: "resolvedWithDataTypeChildren",
includeDrafts: !!draftId,
temporalAxes: currentTimeInstantTemporalAxes,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ const EditEntitySlideOver = memo(
hasRightEntity: { incoming: 1, outgoing: 1 },
},
includeDrafts: !!draftId,
includeEntityTypes: "resolved",
includeEntityTypes: "resolvedWithDataTypeChildren",
},
includePermissions: false,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,7 @@ export const createRenderChangeTypeCell = (
);

const newContent = produce(valueCellOfThisRow, (draft) => {
draft.data.propertyRow.value = undefined;
draft.data.propertyRow.valueMetadata = undefined;
draft.data.showTypePicker = true;
});

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,13 @@ export const renderValueCell: CustomRenderer<ValueCell> = {

const { readonly } = cell.data;

const { value, valueMetadata, permittedDataTypes, isArray, isSingleUrl } =
cell.data.propertyRow;
const {
value,
valueMetadata,
permittedDataTypesIncludingChildren,
isArray,
isSingleUrl,
} = cell.data.propertyRow;

ctx.fillStyle = theme.textHeader;
ctx.font = theme.baseFontStyle;
Expand Down Expand Up @@ -102,8 +107,8 @@ export const renderValueCell: CustomRenderer<ValueCell> = {

const dataTypeId = arrayItemMetadata.metadata.dataTypeId;

const dataType = permittedDataTypes.find(
(type) => type.$id === dataTypeId,
const dataType = permittedDataTypesIncludingChildren.find(
(type) => type.schema.$id === dataTypeId,
);

if (!dataType) {
Expand All @@ -112,7 +117,7 @@ export const renderValueCell: CustomRenderer<ValueCell> = {
);
}

const schema = getMergedDataTypeSchema(dataType);
const schema = getMergedDataTypeSchema(dataType.schema);

if ("anyOf" in schema) {
throw new Error(
Expand All @@ -138,8 +143,8 @@ export const renderValueCell: CustomRenderer<ValueCell> = {

const dataTypeId = valueMetadata.metadata.dataTypeId;

const dataType = permittedDataTypes.find(
(type) => type.$id === dataTypeId,
const dataType = permittedDataTypesIncludingChildren.find(
(type) => type.schema.$id === dataTypeId,
);

if (!dataType) {
Expand All @@ -148,7 +153,7 @@ export const renderValueCell: CustomRenderer<ValueCell> = {
);
}

const schema = getMergedDataTypeSchema(dataType);
const schema = getMergedDataTypeSchema(dataType.schema);

if ("anyOf" in schema) {
throw new Error(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export const ArrayEditor: ValueCellEditorComponent = ({
valueMetadata,
generateNewMetadataObject,
permittedDataTypes,
permittedDataTypesIncludingChildren,
propertyKeyChain,
maxItems,
minItems,
Expand Down Expand Up @@ -94,9 +95,9 @@ export const ArrayEditor: ValueCellEditorComponent = ({

const dataTypeId = arrayItemMetadata.metadata.dataTypeId;

const dataType = permittedDataTypes.find(
(type) => type.$id === dataTypeId,
);
const dataType = permittedDataTypesIncludingChildren.find(
(type) => type.schema.$id === dataTypeId,
)?.schema;

if (!dataType) {
throw new Error(
Expand All @@ -113,7 +114,7 @@ export const ArrayEditor: ValueCellEditorComponent = ({
});

return itemsArray;
}, [propertyValue, valueMetadata, permittedDataTypes]);
}, [propertyValue, valueMetadata, permittedDataTypesIncludingChildren]);

const [selectedRow, setSelectedRow] = useState("");
const [editingRow, setEditingRow] = useState(() => {
Expand All @@ -122,10 +123,13 @@ export const ArrayEditor: ValueCellEditorComponent = ({
return "";
}

if (permittedDataTypes.length === 1) {
if (
permittedDataTypes.length === 1 &&
!permittedDataTypes[0]!.schema.abstract
) {
const expectedType = permittedDataTypes[0]!;

const schema = getMergedDataTypeSchema(expectedType);
const schema = getMergedDataTypeSchema(expectedType.schema);

if ("anyOf" in schema) {
throw new Error(
Expand All @@ -134,7 +138,7 @@ export const ArrayEditor: ValueCellEditorComponent = ({
}

if (
getEditorSpecs(expectedType, schema).arrayEditException ===
getEditorSpecs(expectedType.schema, schema).arrayEditException ===
"no-edit-mode"
) {
return "";
Expand Down Expand Up @@ -254,24 +258,26 @@ export const ArrayEditor: ValueCellEditorComponent = ({
const handleAddAnotherClick = () => {
setSelectedRow("");

const onlyOneExpectedType = permittedDataTypes.length === 1;
const onlyOneExpectedType =
permittedDataTypes.length === 1 &&
!permittedDataTypes[0]!.schema.abstract;
const expectedType = permittedDataTypes[0]!;

const schema = getMergedDataTypeSchema(expectedType);
const schema = getMergedDataTypeSchema(expectedType.schema);

if ("anyOf" in schema) {
throw new Error(
"Data types with different expected sets of constraints (anyOf) are not yet supported",
);
}

const editorSpec = getEditorSpecs(expectedType, schema);
const editorSpec = getEditorSpecs(expectedType.schema, schema);

const noEditMode = editorSpec.arrayEditException === "no-edit-mode";

// add the value on click instead of showing draftRow
if (onlyOneExpectedType && noEditMode) {
return addItem(editorSpec.defaultValue, expectedType.$id);
return addItem(editorSpec.defaultValue, expectedType.schema.$id);
}

setEditingRow(DRAFT_ROW_KEY);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import type { ClosedDataType, VersionedUrl } from "@blockprotocol/type-system";
import type { ClosedDataTypeDefinition } from "@local/hash-graph-types/ontology";
import { getMergedDataTypeSchema } from "@local/hash-isomorphic-utils/data-types";
import { useState } from "react";

import { DRAFT_ROW_KEY } from "../array-editor";
import { getEditorSpecs } from "../editor-specs";
import { EditorTypePicker } from "../editor-type-picker";
import { isBlankStringOrNullish } from "../utils";
import { SortableRow } from "./sortable-row";

interface DraftRowProps {
expectedTypes: ClosedDataType[];
expectedTypes: ClosedDataTypeDefinition[];
existingItemCount: number;
onDraftSaved: (value: unknown, dataTypeId: VersionedUrl) => void;
onDraftDiscarded: () => void;
Expand All @@ -28,14 +31,26 @@ export const DraftRow = ({
throw new Error("there is no expectedType found on property type");
}

return expectedTypes[0];
return expectedTypes[0].schema;
});

if (!dataType) {
return (
<EditorTypePicker
expectedTypes={expectedTypes}
onTypeChange={(type) => {
const schema = getMergedDataTypeSchema(type);

if ("anyOf" in schema) {
throw new Error("Expected a single data type, but got multiple");
}

const editorSpec = getEditorSpecs(type, schema);

if (editorSpec.arrayEditException === "no-edit-mode") {
onDraftSaved(editorSpec.defaultValue, type.$id);
}

setDataType(type);
}}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { JsonValue } from "@blockprotocol/core";
import type { ClosedDataType } from "@blockprotocol/type-system";
import { useSortable } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import {
Expand All @@ -8,6 +7,7 @@ import {
faPencil,
faTrash,
} from "@fortawesome/free-solid-svg-icons";
import type { ClosedDataTypeDefinition } from "@local/hash-graph-types/ontology";
import {
formatDataValue,
getMergedDataTypeSchema,
Expand All @@ -31,7 +31,7 @@ interface SortableRowProps {
onSelect?: (id: string) => void;
onEditClicked?: (id: string) => void;
editing: boolean;
expectedTypes: ClosedDataType[];
expectedTypes: ClosedDataTypeDefinition[];
onSaveChanges: (index: number, value: unknown) => void;
onDiscardChanges: () => void;
}
Expand Down Expand Up @@ -60,20 +60,23 @@ export const SortableRow = ({
animateLayoutChanges: undefined,
});

const schema = getMergedDataTypeSchema(dataType);

const editorSpec =
"anyOf" in schema ? undefined : getEditorSpecs(dataType, schema);

const [hovered, setHovered] = useState(false);
const [draftValue, setDraftValue] = useState(value);
const [draftValue, setDraftValue] = useState(
value === undefined ? editorSpec?.defaultValue : value,
);
const [prevEditing, setPrevEditing] = useState(editing);

const schema = getMergedDataTypeSchema(dataType);

if ("anyOf" in schema) {
if ("anyOf" in schema || !editorSpec) {
throw new Error(
"Data types with different expected sets of constraints (anyOf) are not yet supported",
);
}

const editorSpec = getEditorSpecs(dataType, schema);

const { arrayEditException } = editorSpec;

const shouldShowActions =
Expand Down
Loading

0 comments on commit 6c9fae7

Please sign in to comment.