Skip to content

Commit

Permalink
Add Initial Support For Creation in Choices Inputs
Browse files Browse the repository at this point in the history
  • Loading branch information
djhi committed Apr 27, 2021
1 parent dd0e793 commit f6b1341
Show file tree
Hide file tree
Showing 12 changed files with 731 additions and 411 deletions.
324 changes: 194 additions & 130 deletions examples/simple/src/posts/PostEdit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,58 @@ import {
number,
required,
FormDataConsumer,
useCreateSuggestion,
EditActionsProps,
} from 'react-admin'; // eslint-disable-line import/no-unresolved
import { Box, BoxProps } from '@material-ui/core';
import {
Box,
BoxProps,
Button,
Dialog,
DialogActions,
DialogContent,
TextField as MuiTextField,
} from '@material-ui/core';

import PostTitle from './PostTitle';
import TagReferenceInput from './TagReferenceInput';

const EditActions = ({ basePath, data, hasShow }: any) => (
const CreateCategory = ({
onAddChoice,
}: {
onAddChoice: (record: any) => void;
}) => {
const { filter, onCancel, onCreate } = useCreateSuggestion();
const [value, setValue] = React.useState(filter || '');
const handleSubmit = (event: React.FormEvent) => {
event.preventDefault();
const choice = { name: value, id: value };
onAddChoice(choice);
onCreate(value, choice);
setValue('');
return false;
};
return (
<Dialog open onClose={onCancel}>
<form onSubmit={handleSubmit}>
<DialogContent>
<MuiTextField
label="New Category"
value={value}
onChange={event => setValue(event.target.value)}
autoFocus
/>
</DialogContent>
<DialogActions>
<Button type="submit">Save</Button>
<Button onClick={onCancel}>Cancel</Button>
</DialogActions>
</form>
</Dialog>
);
};

const EditActions = ({ basePath, data, hasShow }: EditActionsProps) => (
<TopToolbar>
<CloneButton
className="button-clone"
Expand All @@ -51,140 +96,159 @@ const SanitizedBox = ({
...props
}: BoxProps & { fullWidth?: boolean; basePath?: string }) => <Box {...props} />;

const PostEdit = ({ permissions, ...props }) => (
<Edit title={<PostTitle />} actions={<EditActions />} {...props}>
<TabbedForm initialValues={{ average_note: 0 }} warnWhenUnsavedChanges>
<FormTab label="post.form.summary">
<SanitizedBox
display="flex"
flexDirection="column"
width="100%"
justifyContent="space-between"
fullWidth
>
<TextInput disabled source="id" />
const categories = [
{ name: 'Tech', id: 'tech' },
{ name: 'Lifestyle', id: 'lifestyle' },
];

const PostEdit = ({ permissions, ...props }) => {
return (
<Edit title={<PostTitle />} actions={<EditActions />} {...props}>
<TabbedForm
initialValues={{ average_note: 0 }}
warnWhenUnsavedChanges
>
<FormTab label="post.form.summary">
<SanitizedBox
display="flex"
flexDirection="column"
width="100%"
justifyContent="space-between"
fullWidth
>
<TextInput disabled source="id" />
<TextInput
source="title"
validate={required()}
resettable
/>
</SanitizedBox>
<TextInput
source="title"
multiline={true}
fullWidth={true}
source="teaser"
validate={required()}
resettable
/>
</SanitizedBox>
<TextInput
multiline={true}
fullWidth={true}
source="teaser"
validate={required()}
resettable
/>
<CheckboxGroupInput
source="notifications"
choices={[
{ id: 12, name: 'Ray Hakt' },
{ id: 31, name: 'Ann Gullar' },
{ id: 42, name: 'Sean Phonee' },
]}
/>
<ImageInput multiple source="pictures" accept="image/*">
<ImageField source="src" title="title" />
</ImageInput>
{permissions === 'admin' && (
<ArrayInput source="authors">
<CheckboxGroupInput
source="notifications"
choices={[
{ id: 12, name: 'Ray Hakt' },
{ id: 31, name: 'Ann Gullar' },
{ id: 42, name: 'Sean Phonee' },
]}
/>
<ImageInput multiple source="pictures" accept="image/*">
<ImageField source="src" title="title" />
</ImageInput>
{permissions === 'admin' && (
<ArrayInput source="authors">
<SimpleFormIterator>
<ReferenceInput
label="User"
source="user_id"
reference="users"
>
<AutocompleteInput />
</ReferenceInput>
<FormDataConsumer>
{({
formData,
scopedFormData,
getSource,
...rest
}) =>
scopedFormData &&
scopedFormData.user_id ? (
<SelectInput
label="Role"
source={getSource('role')}
choices={[
{
id: 'headwriter',
name: 'Head Writer',
},
{
id: 'proofreader',
name: 'Proof reader',
},
{
id: 'cowriter',
name: 'Co-Writer',
},
]}
{...rest}
/>
) : null
}
</FormDataConsumer>
</SimpleFormIterator>
</ArrayInput>
)}
</FormTab>
<FormTab label="post.form.body">
<RichTextInput
source="body"
label=""
validate={required()}
addLabel={false}
/>
</FormTab>
<FormTab label="post.form.miscellaneous">
<TagReferenceInput
reference="tags"
source="tags"
label="Tags"
/>
<ArrayInput source="backlinks">
<SimpleFormIterator>
<ReferenceInput
label="User"
source="user_id"
reference="users"
>
<AutocompleteInput />
</ReferenceInput>
<FormDataConsumer>
{({
formData,
scopedFormData,
getSource,
...rest
}) =>
scopedFormData && scopedFormData.user_id ? (
<SelectInput
label="Role"
source={getSource('role')}
choices={[
{
id: 'headwriter',
name: 'Head Writer',
},
{
id: 'proofreader',
name: 'Proof reader',
},
{
id: 'cowriter',
name: 'Co-Writer',
},
]}
{...rest}
/>
) : null
}
</FormDataConsumer>
<DateInput source="date" />
<TextInput source="url" validate={required()} />
</SimpleFormIterator>
</ArrayInput>
)}
</FormTab>
<FormTab label="post.form.body">
<RichTextInput
source="body"
label=""
validate={required()}
addLabel={false}
/>
</FormTab>
<FormTab label="post.form.miscellaneous">
<TagReferenceInput
reference="tags"
source="tags"
label="Tags"
/>
<ArrayInput source="backlinks">
<SimpleFormIterator>
<DateInput source="date" />
<TextInput source="url" validate={required()} />
</SimpleFormIterator>
</ArrayInput>
<DateInput source="published_at" />
<SelectInput
allowEmpty
resettable
source="category"
choices={[
{ name: 'Tech', id: 'tech' },
{ name: 'Lifestyle', id: 'lifestyle' },
]}
/>
<NumberInput
source="average_note"
validate={[required(), number(), minValue(0)]}
/>
<BooleanInput source="commentable" defaultValue />
<TextInput disabled source="views" />
</FormTab>
<FormTab label="post.form.comments">
<ReferenceManyField
reference="comments"
target="post_id"
addLabel={false}
fullWidth
>
<Datagrid>
<DateField source="created_at" />
<TextField source="author.name" />
<TextField source="body" />
<EditButton />
</Datagrid>
</ReferenceManyField>
</FormTab>
</TabbedForm>
</Edit>
);
<DateInput
source="published_at"
options={{ locale: 'pt' }}
/>
<SelectInput
create={
<CreateCategory
// Ajouté sur le composant parce que je ne suis pas
// dans un ReferenceInput donc faut que je mette
// à jour ma liste de choix à donner à l'AutocompleteInput
onAddChoice={choice => categories.push(choice)}
/>
}
allowEmpty
resettable
source="category"
choices={categories}
/>
<NumberInput
source="average_note"
validate={[required(), number(), minValue(0)]}
/>
<BooleanInput source="commentable" defaultValue />
<TextInput disabled source="views" />
</FormTab>
<FormTab label="post.form.comments">
<ReferenceManyField
reference="comments"
target="post_id"
addLabel={false}
fullWidth
>
<Datagrid>
<DateField source="created_at" />
<TextField source="author.name" />
<TextField source="body" />
<EditButton />
</Datagrid>
</ReferenceManyField>
</FormTab>
</TabbedForm>
</Edit>
);
};

export default PostEdit;
4 changes: 2 additions & 2 deletions examples/simple/src/posts/PostTitle.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';
import { useTranslate, Record } from 'react-admin';
import { TitleProps, useTranslate } from 'react-admin';

export default ({ record }: { record?: Record }) => {
export default ({ record }: TitleProps) => {
const translate = useTranslate();
return (
<span>
Expand Down
13 changes: 10 additions & 3 deletions packages/ra-core/src/form/useChoices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import { InputProps } from '.';
export type OptionTextElement = ReactElement<{
record: Record;
}>;
export type OptionText = (choice: object) => string | OptionTextElement;
export type OptionTextFunc = (choice: object) => string | OptionTextElement;
export type OptionText = OptionTextElement | OptionTextFunc | string;

export interface ChoicesInputProps<T = any>
extends Omit<InputProps<T>, 'source'> {
Expand All @@ -22,13 +23,13 @@ export interface ChoicesInputProps<T = any>
export interface ChoicesProps {
choices: object[];
optionValue?: string;
optionText?: OptionTextElement | OptionText | string;
optionText?: OptionText;
translateChoice?: boolean;
}

export interface UseChoicesOptions {
optionValue?: string;
optionText?: OptionTextElement | OptionText | string;
optionText?: OptionText;
disableValue?: string;
translateChoice?: boolean;
}
Expand Down Expand Up @@ -64,6 +65,12 @@ const useChoices = ({
? optionText(choice)
: get(choice, optionText);

if (isValidElement<{ record: any }>(choiceName)) {
return cloneElement<{ record: any }>(choiceName, {
record: choice,
});
}

return translateChoice
? translate(choiceName, { _: choiceName })
: choiceName;
Expand Down
Loading

0 comments on commit f6b1341

Please sign in to comment.