From 86c49795ac1d198836242772ec01bd755ee699c8 Mon Sep 17 00:00:00 2001 From: Chris Villa Date: Wed, 25 Oct 2023 15:27:35 +0100 Subject: [PATCH] feat: add mapProp API to external field adaptors --- README.md | 1 + apps/demo/config/blocks/Hero/index.tsx | 28 +++++++++---------- .../core/components/ExternalInput/index.tsx | 6 ++-- packages/core/types/Config.tsx | 13 +++++---- 4 files changed, 27 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index bcd6f7fbc0..f8cd3de6d7 100644 --- a/README.md +++ b/README.md @@ -500,6 +500,7 @@ External fields can be used to load content from an external content repository, - **adaptor** (`Adaptor`): Content adaptor responsible for fetching data to show in the table - **name** (`string`): The human-readable name of the adaptor - **fetchList** (`(adaptorParams: object) => object`): Fetch a list of content and return an array + - **mapProp** (`(selectedItem: object) => object`): Map the selected item into another shape - **adaptorParams** (`object`): Paramaters passed to the adaptor ### Custom Fields diff --git a/apps/demo/config/blocks/Hero/index.tsx b/apps/demo/config/blocks/Hero/index.tsx index 2d05e95a2c..8ffabe2f91 100644 --- a/apps/demo/config/blocks/Hero/index.tsx +++ b/apps/demo/config/blocks/Hero/index.tsx @@ -10,7 +10,7 @@ import { quotes } from "./quotes"; const getClassName = getClassNameFactory("Hero", styles); export type HeroProps = { - quote?: { index: number }; + quote?: { index: number; label: string }; title: string; description: string; align?: string; @@ -20,23 +20,23 @@ export type HeroProps = { buttons: { label: string; href: string; variant?: "primary" | "secondary" }[]; }; -// TODO add resolveValue prop so the fetch can return different data to the adaptor -const quotesAdaptor = { - name: "Quotes API", - fetchList: async (): Promise[]> => - quotes.map((quote, idx) => ({ - index: idx, - title: quote.author, - description: quote.content, - })), -}; - export const Hero: ComponentConfig = { fields: { quote: { type: "external", - adaptor: quotesAdaptor, - getItemSummary: (item: Partial) => item.description, + adaptor: { + name: "Quotes API", + fetchList: async () => + quotes.map((quote, idx) => ({ + index: idx, + title: quote.author, + description: quote.content, + })), + mapProp: (result) => { + return { index: result.index, label: result.description }; + }, + }, + getItemSummary: (item) => item.label, }, title: { type: "text" }, description: { type: "textarea" }, diff --git a/packages/core/components/ExternalInput/index.tsx b/packages/core/components/ExternalInput/index.tsx index 54a8b59813..58ba63744a 100644 --- a/packages/core/components/ExternalInput/index.tsx +++ b/packages/core/components/ExternalInput/index.tsx @@ -15,6 +15,8 @@ export const ExternalInput = ({ onChange: (value: any) => void; value: any; }) => { + const { mapProp = (val) => val } = field.adaptor || {}; + const [data, setData] = useState[]>([]); const [isOpen, setOpen] = useState(false); const [selectedData, setSelectedData] = useState(value); @@ -112,11 +114,11 @@ export const ExternalInput = ({ key={i} style={{ whiteSpace: "nowrap" }} onClick={(e) => { - onChange(item); + onChange(mapProp(item)); setOpen(false); - setSelectedData(item); + setSelectedData(mapProp(item)); }} > {keys.map((key) => ( diff --git a/packages/core/types/Config.tsx b/packages/core/types/Config.tsx index 69f70e7976..fec4591034 100644 --- a/packages/core/types/Config.tsx +++ b/packages/core/types/Config.tsx @@ -2,11 +2,14 @@ import { ReactElement } from "react"; import { ReactNode } from "react"; import { ItemSelector } from "../lib/get-item"; -export type Adaptor = { +export type Adaptor< + AdaptorParams = {}, + TableShape extends Record = {}, + PropShape = TableShape +> = { name: string; - fetchList: ( - adaptorParams?: AdaptorParams - ) => Promise[] | null>; + fetchList: (adaptorParams?: AdaptorParams) => Promise; + mapProp?: (value: TableShape) => PropShape; }; type WithPuckProps = Props & { @@ -47,7 +50,7 @@ export type ExternalField< Props extends { [key: string]: any } = { [key: string]: any } > = BaseField & { type: "external"; - adaptor: Adaptor; + adaptor: Adaptor; adaptorParams?: object; getItemSummary: (item: Props, index?: number) => string; };