-
Notifications
You must be signed in to change notification settings - Fork 123
Open
Labels
staleUsed to mark when there was no activity for a set period of timeUsed to mark when there was no activity for a set period of time
Description
import React from 'react';
import { Grid, Box, FormControl } from '@contentful/f36-components';
import { EditorAppSDK, FieldAppSDK } from '@contentful/app-sdk';
import { useSDK } from '@contentful/react-apps-toolkit';
import { Field, FieldWrapper } from '@contentful/default-field-editors';
import { JsonEditor } from '@contentful/field-editor-json';
// Patches the sdk to include the help text
const getHelpText = (fieldId: string, sdk: EditorAppSDK) => {
return sdk?.editor?.editorInterface?.controls?.find((field) => field.fieldId === fieldId)?.settings?.helpText || '';
}
// Converts a field into <FieldAPI> data type, which is the expected data type for many API methods
const getFieldAPI = (fieldId: string, sdk: EditorAppSDK) => {
return sdk.entry.fields[fieldId].getForLocale(sdk.locales.default);
}
// Creates a <FieldExtensionSDK> type that can be passed to components from the default-field-editors package
const getFieldExtensionSdk = (fieldId: string, sdk: EditorAppSDK): FieldAppSDK => {
return {
...sdk,
ids: {
extension: '',
app: '',
environmentAlias: '',
field: '',
...sdk.ids,
},
field: getFieldAPI(fieldId, sdk),
window: {
updateHeight: (height?: number) => null,
startAutoResizer: () => null,
stopAutoResizer: () => null,
},
// TODO: missing some invocation property, not sure what this does...
// @ts-ignore
parameters: {
installation: {},
instance: {
helpText: getHelpText(fieldId, sdk)
},
}
};
}
// we need to patch the sdk to include the widget id
const getWidgetId = (fieldId: string, sdk: EditorAppSDK) => {
return sdk?.editor?.editorInterface?.controls?.find((field) => field.fieldId === fieldId)?.widgetId || '';
}
// we need to patch the sdk to include the field name
const getFieldName = (fieldId: string, sdk: EditorAppSDK) => {
return sdk?.contentType?.fields?.find((field) => field.id === fieldId)?.name || '';
}
// helper function to make generating a field configuration easier
const getFieldProps = ({ fieldId, sdk }: { fieldId: string, sdk: EditorAppSDK }) => {
return {
sdk: getFieldExtensionSdk(fieldId, sdk),
widgetId: getWidgetId(fieldId, sdk),
name: getFieldName(fieldId, sdk),
};
}
const TYPES = {
NONE: undefined,
DEFAULT: 'Default',
CARDS_ROW: 'Cards Row',
LOGO_WALL: 'Logo Wall',
};
const Entry = () => {
const sdk = useSDK<EditorAppSDK>();
const triggerElement = getFieldProps({ fieldId: 'type', sdk });
const [currentType, setCurrentType] = React.useState(triggerElement.sdk.field.getValue());
React.useEffect(() => {
triggerElement.sdk.field.onValueChanged((value) => {
setCurrentType(value);
});
});
const [isFocused, setIsFocused] = React.useState({ styles: false });
const fields = [
{
shouldRenderWhenType: [TYPES.NONE, TYPES.DEFAULT, TYPES.CARDS_ROW, TYPES.LOGO_WALL],
props: getFieldProps({ fieldId: 'internalTitle', sdk }),
},
{
shouldRenderWhenType: [TYPES.NONE, TYPES.DEFAULT, TYPES.CARDS_ROW, TYPES.LOGO_WALL],
props: getFieldProps({ fieldId: 'type', sdk }),
},
{
shouldRenderWhenType: [TYPES.DEFAULT],
props: getFieldProps({ fieldId: 'defaultLayout', sdk }),
},
{
shouldRenderWhenType: [TYPES.DEFAULT],
props: getFieldProps({ fieldId: 'defaultBody', sdk }),
},
{
shouldRenderWhenType: [TYPES.DEFAULT],
props: getFieldProps({ fieldId: 'defaultMedia', sdk }),
},
{
shouldRenderWhenType: [TYPES.CARDS_ROW],
props: getFieldProps({ fieldId: 'cardsRowheader', sdk }),
},
{
shouldRenderWhenType: [TYPES.CARDS_ROW],
props: getFieldProps({ fieldId: 'components', sdk }),
},
{
shouldRenderWhenType: [TYPES.LOGO_WALL],
props: getFieldProps({ fieldId: 'logos', sdk }),
},
{
shouldRenderWhenType: [TYPES.DEFAULT, TYPES.CARDS_ROW, TYPES.LOGO_WALL],
props: getFieldProps({ fieldId: 'backgroundColor', sdk }),
},
{
shouldRenderWhenType: [TYPES.DEFAULT, TYPES.CARDS_ROW, TYPES.LOGO_WALL],
props: getFieldProps({ fieldId: 'styles', sdk }),
},
];
return (
<Grid
style={{ maxWidth: '816px', marginLeft: 'auto', marginRight: 'auto' }}
marginTop="spacingXl"
columns="1fr"
rowGap="spacingM"
columnGap="spacingM"
>
<Grid.Item>
{fields.map((field) => {
if (field.shouldRenderWhenType.includes(currentType)) {
switch (field.props.widgetId) {
case 'objectEditor':
// NOTE: we're using the json editor because the default json field seems to be throwing an error
return (
<Box
paddingLeft="spacingL"
paddingRight="spacingL"
onFocus={() => {
setIsFocused({ ...isFocused, styles: true });
}}
onBlur={() => {
setIsFocused({ ...isFocused, styles: false });
}}
>
<Box
style={{
borderLeft: isFocused.styles ? '3px solid #0059C8' : '3px solid #CFD9E0'
}}
paddingLeft='spacingM'
>
<FormControl>
<FormControl.Label
style={{
color: '#67728A',
fontFamily: 'var(--font-stack-primary)',
fontWeight: 'var(--font-weight-normal)'
}}>
{field.props.name}
</FormControl.Label>
<JsonEditor field={field.props.sdk.field} isInitiallyDisabled={false} />
<FormControl.HelpText>{field.props.sdk.parameters.instance.helpText}</FormControl.HelpText>
</FormControl>
</Box>
</Box>
);
default:
return (
<FieldWrapper sdk={field.props.sdk} name={field.props.name} key={field.props.sdk.field.id}>
<Field sdk={field.props.sdk} widgetId={field.props.widgetId} />
</FieldWrapper>
);
}
} else {
return null;
}
})}
</Grid.Item>
</Grid>
);
};
export default Entry; "dependencies": {
"@contentful/app-sdk": "^4.22.1",
"@contentful/default-field-editors": "^1.4.10",
"@contentful/f36-components": "4.48.0",
"@contentful/f36-tokens": "4.0.2",
"@contentful/field-editor-json": "^3.3.1",
"@contentful/react-apps-toolkit": "1.2.16",
"contentful-management": "10.39.2",
"emotion": "10.0.27",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-scripts": "5.0.1"
},Metadata
Metadata
Assignees
Labels
staleUsed to mark when there was no activity for a set period of timeUsed to mark when there was no activity for a set period of time
