Skip to content

Commit

Permalink
fix structure relationship fields
Browse files Browse the repository at this point in the history
  • Loading branch information
dcousens committed Dec 10, 2024
1 parent d570971 commit ea185d3
Show file tree
Hide file tree
Showing 11 changed files with 178 additions and 164 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ function ItemForm ({
position="form"
fieldPositions={fieldPositions}
onChange={useCallback(value => {
setValue(state => ({ item: state.item, value: value(state.value) }))
setValue(state => ({ item: state.item, value: state.value }))
}, [setValue])}
value={state.value}
/>
Expand All @@ -195,7 +195,7 @@ function ItemForm ({
fieldPositions={fieldPositions}
onChange={useCallback(
value => {
setValue(state => ({ item: state.item, value: value(state.value) }))
setValue(state => ({ item: state.item, value: state.value }))
},
[setValue]
)}
Expand Down
117 changes: 53 additions & 64 deletions packages/core/src/admin-ui/utils/useAdminMeta.tsx
Original file line number Diff line number Diff line change
@@ -1,110 +1,103 @@
import { useEffect, useMemo, useState } from "react";
import hashString from "@emotion/hash";
import { type AdminMeta, type FieldViews } from "../../types";
import { useLazyQuery } from "../apollo";
import {
useEffect,
useMemo,
useState
} from "react"
import hashString from "@emotion/hash"
import type { AdminMeta, FieldViews } from "../../types"
import { useLazyQuery } from "../apollo"
import {
type StaticAdminMetaQuery,
staticAdminMetaQuery,
} from "../admin-meta-graphql";
} from "../admin-meta-graphql"

const expectedExports = new Set(["Field", "controller"]);
const adminMetaLocalStorageKey = "keystone.adminMeta";
const expectedExports = new Set(["Field", "controller"])
const adminMetaLocalStorageKey = "keystone.adminMeta"

let _mustRenderServerResult = true;
let _mustRenderServerResult = true

function useMustRenderServerResult() {
const [, forceUpdate] = useState(0);
const [, forceUpdate] = useState(0)
useEffect(() => {
_mustRenderServerResult = false;
forceUpdate(1);
}, []);
_mustRenderServerResult = false
forceUpdate(1)
}, [])

if (typeof window === "undefined") return true;
if (typeof window === "undefined") return true

return _mustRenderServerResult;
return _mustRenderServerResult
}

export function useAdminMeta(adminMetaHash: string, fieldViews: FieldViews) {
const adminMetaFromLocalStorage = useMemo(() => {
if (typeof window === "undefined") return;
if (typeof window === "undefined") return

const item = localStorage.getItem(adminMetaLocalStorageKey);
if (item === null) return;
const item = localStorage.getItem(adminMetaLocalStorageKey)
if (item === null) return

try {
const parsed = JSON.parse(item);
if (parsed.hash === adminMetaHash) {
return parsed.meta as StaticAdminMetaQuery["keystone"]["adminMeta"];
}
const parsed = JSON.parse(item)
if (parsed.hash === adminMetaHash) return parsed.meta as StaticAdminMetaQuery["keystone"]["adminMeta"]
} catch (err) {
return;
return
}
}, [adminMetaHash]);
}, [adminMetaHash])

// it seems like Apollo doesn't skip the first fetch when using skip: true so we're using useLazyQuery instead
const [fetchStaticAdminMeta, { data, error, called }] = useLazyQuery(
staticAdminMetaQuery,
{
fetchPolicy: "no-cache", // TODO: something is bugged
}
);
)

const shouldFetchAdminMeta =
adminMetaFromLocalStorage === undefined && !called;
adminMetaFromLocalStorage === undefined && !called

useEffect(() => {
if (shouldFetchAdminMeta) {
fetchStaticAdminMeta();
}
}, [shouldFetchAdminMeta, fetchStaticAdminMeta]);
if (shouldFetchAdminMeta) fetchStaticAdminMeta()
}, [shouldFetchAdminMeta, fetchStaticAdminMeta])

const runtimeAdminMeta = useMemo(() => {
if ((!data || error) && !adminMetaFromLocalStorage) return undefined;
if ((!data || error) && !adminMetaFromLocalStorage) return undefined

const adminMeta: StaticAdminMetaQuery["keystone"]["adminMeta"] =
adminMetaFromLocalStorage
? adminMetaFromLocalStorage
: data.keystone.adminMeta;
: data.keystone.adminMeta

const runtimeAdminMeta: AdminMeta = {
lists: {},
};
}

for (const list of adminMeta.lists) {
runtimeAdminMeta.lists[list.key] = {
...list,
groups: [],
fields: {},
};
}

for (const field of list.fields) {
for (const exportName of expectedExports) {
if ((fieldViews[field.viewsIndex] as any)[exportName] === undefined) {
throw new Error(
`The view for the field at ${list.key}.${field.path} is missing the ${exportName} export`
);
)
}
}

const views = { ...fieldViews[field.viewsIndex] };
const customViews: Record<string, any> = {};
const views = { ...fieldViews[field.viewsIndex] }
const customViews: Record<string, any> = {}
if (field.customViewsIndex !== null) {
const customViewsSource: FieldViews[number] & Record<string, any> =
fieldViews[field.customViewsIndex];
const allowedExportsOnCustomViews = new Set(
views.allowedExportsOnCustomViews
);
Object.keys(customViewsSource).forEach((exportName) => {
const customViewsSource: FieldViews[number] & Record<string, any> = fieldViews[field.customViewsIndex]
const allowedExportsOnCustomViews = new Set(views.allowedExportsOnCustomViews)
for (const exportName in customViewsSource) {
if (allowedExportsOnCustomViews.has(exportName)) {
customViews[exportName] = customViewsSource[exportName];
customViews[exportName] = customViewsSource[exportName]
} else if (expectedExports.has(exportName)) {
(views as any)[exportName] = customViewsSource[exportName];
} else {
throw new Error(
`Unexpected export named ${exportName} from the custom view from field at ${list.key}.${field.path}`
);
(views as any)[exportName] = customViewsSource[exportName]
}
});
}
}

runtimeAdminMeta.lists[list.key].fields[field.path] = {
Expand All @@ -121,7 +114,7 @@ export function useAdminMeta(adminMetaHash: string, fieldViews: FieldViews) {
path: field.path,
customViews,
}),
};
}
}

for (const group of list.groups) {
Expand All @@ -131,7 +124,7 @@ export function useAdminMeta(adminMetaHash: string, fieldViews: FieldViews) {
fields: group.fields.map(
(field) => runtimeAdminMeta.lists[list.key].fields[field.path]
),
});
})
}
}

Expand All @@ -142,28 +135,24 @@ export function useAdminMeta(adminMetaHash: string, fieldViews: FieldViews) {
hash: hashString(JSON.stringify(adminMeta)),
meta: adminMeta,
})
);
)
}

return runtimeAdminMeta;
}, [data, error, adminMetaFromLocalStorage, fieldViews]);
return runtimeAdminMeta
}, [data, error, adminMetaFromLocalStorage, fieldViews])

const mustRenderServerResult = useMustRenderServerResult();
const mustRenderServerResult = useMustRenderServerResult()

if (mustRenderServerResult) {
return { state: "loading" as const };
}
if (runtimeAdminMeta) {
return { state: "loaded" as const, value: runtimeAdminMeta };
}
if (mustRenderServerResult) return { state: "loading" as const }
if (runtimeAdminMeta) return { state: "loaded" as const, value: runtimeAdminMeta }
if (error) {
return {
state: "error" as const,
error,
refetch: async () => {
await fetchStaticAdminMeta();
await fetchStaticAdminMeta()
},
};
}
}
return { state: "loading" as const };
return { state: "loading" as const }
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ export function ComboboxMany ({
}) {
const { data, loadingState, error, onLoadMore, search, setSearch } =
useApolloQuery({
extraSelection,
labelField,
list,
searchFields,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ export function ComboboxSingle ({
list,
placeholder,
state,
extraSelection = '',
}: {
autoFocus?: boolean
description?: string
Expand All @@ -36,11 +35,9 @@ export function ComboboxSingle ({
value: RelationshipValue | null
onChange(value: RelationshipValue | null): void
}
extraSelection?: string
}) {
const { data, loading, error, onLoadMore, search, setSearch } =
useApolloQuery({
extraSelection,
labelField,
list,
searchFields,
Expand Down
21 changes: 11 additions & 10 deletions packages/core/src/fields/types/relationship/views/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,16 @@ export function Field (props: FieldProps<typeof controller>) {
} = props
const foreignList = useList(field.refListKey)
const [dialogIsOpen, setDialogOpen] = useState(false)
const description = field.description || undefined
const isReadOnly = onChange === undefined

if (value.kind === 'count') {
return (
<TextField
autoFocus={autoFocus}
isReadOnly
label={field.label}
description={description}
isReadOnly
value={value.count.toString()}
width="alias.singleLineWidth"
/>
Expand All @@ -48,11 +51,10 @@ export function Field (props: FieldProps<typeof controller>) {
<ContextualActions onAdd={() => setDialogOpen(true)} {...props}>
{value.kind === 'many' ? (
<ComboboxMany
key={field.path}
autoFocus={autoFocus}
label={field.label}
description={field.description || undefined}
isReadOnly={onChange === undefined}
description={description}
isReadOnly={isReadOnly}
labelField={field.refLabelField}
searchFields={field.refSearchFields}
list={foreignList}
Expand All @@ -66,11 +68,10 @@ export function Field (props: FieldProps<typeof controller>) {
/>
) : (
<ComboboxSingle
key={field.path}
autoFocus={autoFocus}
label={field.label}
description={field.description || undefined}
isReadOnly={onChange === undefined}
description={description}
isReadOnly={isReadOnly}
labelField={field.refLabelField}
searchFields={field.refSearchFields}
list={foreignList}
Expand Down Expand Up @@ -114,7 +115,7 @@ export function Field (props: FieldProps<typeof controller>) {
)}
</VStack>

{onChange !== undefined && (
{!isReadOnly && (
<DialogContainer onDismiss={() => setDialogOpen(false)}>
{dialogIsOpen && (
<BuildItemDialog
Expand Down Expand Up @@ -243,7 +244,7 @@ export function controller (
initialValue: null
},
validate() { return true },
deserialize: data => {
deserialize: (data) => {
if (config.fieldMeta.displayMode === 'count') {
return {
id: data.id,
Expand Down Expand Up @@ -277,7 +278,7 @@ export function controller (
initialValue: value,
}
},
serialize: state => {
serialize: (state) => {
if (state.kind === 'many') {
const newAllIds = new Set(state.value.map(x => x.id))
const initialIds = new Set(state.initialValue.map(x => x.id))
Expand Down
Loading

0 comments on commit ea185d3

Please sign in to comment.