Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/components/react-admin/CustomToolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const CustomToolbar = ({
<CancelButton redirect={redirect || basePath} className={classes.cancel} />
<DeleteWithConfirmButton
redirect={redirect || 'list'}
mutationMode="optimistic"
mutationMode="pessimistic"
/>
</Toolbar>
);
Expand Down
15 changes: 15 additions & 0 deletions src/components/react-admin/ServerSideSimpleForm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import { SimpleForm } from 'react-admin';
import useSaveWithErrorHandling from '../../hooks/useSaveWithErrorHandling';

function ServerSideSimpleForm ({ children, record, resource, ...props }) {
const save = useSaveWithErrorHandling(record.id !== undefined, resource);

return (
<SimpleForm {...props} record={record} resource={resource} save={save}>
{children}
</SimpleForm>
);
}

export default ServerSideSimpleForm;
15 changes: 15 additions & 0 deletions src/components/react-admin/ServerSideTabbedForm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import { TabbedForm } from 'react-admin';
import useSaveWithErrorHandling from '../../hooks/useSaveWithErrorHandling';

function ServerSideTabbedForm ({ children, record, resource, ...props }) {
const save = useSaveWithErrorHandling(record.id !== undefined, resource);

return (
<TabbedForm {...props} record={record} resource={resource} save={save}>
{children}
</TabbedForm>
);
}

export default ServerSideTabbedForm;
41 changes: 41 additions & 0 deletions src/hooks/useSaveWithErrorHandling.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { useMutation, useNotify, useRedirect } from 'ra-core';
import { useCallback } from 'react';

/**
* Convert the django error response to an object react-admin understands
*
* See https://marmelab.com/react-admin/doc/3.19/CreateEdit.html#server-side-validation
*/
function useSaveWithErrorHandling (edit, resource) {
const [mutate] = useMutation();
const notify = useNotify();
const redirect = useRedirect();

const save = useCallback(
async values => {
try {
await mutate({
type: edit ? 'update' : 'create',
resource,
payload: { id: values.id, data: values },
}, { returnPromise: true });
redirect(`/${resource}`);
} catch (error) {
const errorData = error.body ?? error.data;
if (error.status === 400 && errorData) {
const errorObject = { ...errorData };
Object.entries(errorObject).forEach(([key, value]) => {
errorObject[key] = value.reduce((acc, current) => `${acc} ${current}`);
});
notify('ra.message.invalid_form', { type: 'error' });
return errorObject;
}
}
return null;
},
[mutate, edit, resource, notify, redirect],
);
return save;
}

export default useSaveWithErrorHandling;
6 changes: 3 additions & 3 deletions src/modules/RA/BaseLayer/components/BaseLayerForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
required,
NumberInput,
SelectInput,
SimpleForm,
TextInput,
SimpleFormIterator,
translate,
Expand All @@ -21,6 +20,7 @@ import ZoomInput from '../../../../components/react-admin/ZoomInput';
import FieldGroup from '../../../../components/react-admin/FieldGroup';

import compose from '../../../../utils/compose';
import ServerSideSimpleForm from '../../../../components/react-admin/ServerSideSimpleForm';

const styles = {
inline: {
Expand Down Expand Up @@ -93,7 +93,7 @@ const BaseLayerForm = ({ basePath, classes, translate: t, ...props }) => {
}, [t, validateURL]);

return (
<SimpleForm sanitizeEmptyValues={false} {...props}>
<ServerSideSimpleForm sanitizeEmptyValues={false} {...props}>
<TextInput source="name" label="baseLayer.form.name" validate={required()} />

<BaseLayerType
Expand Down Expand Up @@ -165,7 +165,7 @@ const BaseLayerForm = ({ basePath, classes, translate: t, ...props }) => {
</FieldGroup>
)}

</SimpleForm>
</ServerSideSimpleForm>
);
};
export default compose(
Expand Down
2 changes: 1 addition & 1 deletion src/modules/RA/BaseLayer/views/Edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import DefaultActions from '../../../../components/react-admin/DefaultActions';

export const BaseLayerEdit = props => (
<Edit
mutationMode="optimistic"
mutationMode="pessimistic"
{...props}
actions={<DefaultActions />}
>
Expand Down
6 changes: 3 additions & 3 deletions src/modules/RA/Campaign/components/CampaignFields.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
FormTab,
ReferenceInput,
SelectInput,
TabbedForm,
TextInput,
} from 'react-admin';

Expand All @@ -23,6 +22,7 @@ import CampaignState from './CampaignState';

import UserNameField from '../../User/components/UserNameField';
import StatsBar from './StatsBar';
import ServerSideTabbedForm from '../../../../components/react-admin/ServerSideTabbedForm';

const useStyles = makeStyles({
inline: {
Expand All @@ -47,7 +47,7 @@ const CampaignFields = ({ edit, location, ...props }) => {
const isEditable = edit && state !== 'draft';

return (
<TabbedForm
<ServerSideTabbedForm
{...props}
toolbar={<CustomToolbar />}
initialValues={{ viewpoints: [], state: 'draft' }}
Expand Down Expand Up @@ -95,7 +95,7 @@ const CampaignFields = ({ edit, location, ...props }) => {

<ViewpointGrid />
</FormTab>
</TabbedForm>
</ServerSideTabbedForm>
);
};

Expand Down
4 changes: 2 additions & 2 deletions src/modules/RA/Campaign/views/Edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ export const CampaignEdit = ({ staticContext, ...props }) => {
return (
<Edit
{...props}
mutationMode="optimistic"
mutationMode="pessimistic"
actions={<CampaignActions redirect={redirect} />}
>
<EditCampaignFields edit redirect={redirect} />
<EditCampaignFields redirect={redirect} />
</Edit>
);
};
Expand Down
7 changes: 4 additions & 3 deletions src/modules/RA/DataLayer/components/DataLayerForm.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';

import { ArrayInput, FormTab, SimpleFormIterator, TabbedForm, TabbedFormTabs } from 'react-admin';
import { ArrayInput, FormTab, SimpleFormIterator, TabbedFormTabs } from 'react-admin';

import CustomFormTab from '../../../../components/react-admin/CustomFormTab';

Expand All @@ -15,6 +15,7 @@ import ReportingTab from './tabs/ReportingTab';
import StyleTab from './tabs/StyleTab';
import TableTab from './tabs/TableTab';
import WidgetsTab from './tabs/WidgetsTab/WidgetsTab';
import ServerSideTabbedForm from '../../../../components/react-admin/ServerSideTabbedForm';

const initialErrorState = {
definition: false,
Expand Down Expand Up @@ -154,7 +155,7 @@ const DataLayerForm = React.memo(props => {
}, []);

return (
<TabbedForm
<ServerSideTabbedForm
tabs={<TabbedFormTabs variant="scrollable" scrollButtons="auto" />}
sanitizeEmptyValues={false}
{...props}
Expand Down Expand Up @@ -258,7 +259,7 @@ const DataLayerForm = React.memo(props => {
>
<ReportingTab />
</CustomFormTab>
</TabbedForm>
</ServerSideTabbedForm>
);
});

Expand Down
2 changes: 1 addition & 1 deletion src/modules/RA/DataLayer/views/Edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const EditDataLayerForm = PreventPartialData('description', DataLayerForm);

export const DataLayerEdit = props => (
<Edit
mutationMode="optimistic"
mutationMode="pessimistic"
{...props}
actions={<DefaultActions />}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import React from 'react';
import {
TextInput,
Labeled,
SimpleForm,
translate,
} from 'react-admin';

import DataSourceMainFields from './DataSourceMainFields';
import ServerSideSimpleForm from '../../../../components/react-admin/ServerSideSimpleForm';

const DataSourceReadOnlyForm = ({ translate: t, ...props }) => (
<SimpleForm {...props} toolbar={null}>
<ServerSideSimpleForm {...props} toolbar={null}>
<Labeled label="datasource.form.read-only" fullWidth />

<DataSourceMainFields disabled />
Expand All @@ -22,7 +22,7 @@ const DataSourceReadOnlyForm = ({ translate: t, ...props }) => (
helperText={t('datasource.form.uid-field-help')}
fullWidth
/>
</SimpleForm>
</ServerSideSimpleForm>
);

export default translate(DataSourceReadOnlyForm);
6 changes: 3 additions & 3 deletions src/modules/RA/DataSource/components/DataSourceTabbedForm.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React from 'react';
import {
TabbedForm,
TextInput,
BooleanInput,
SelectInput,
Expand All @@ -18,14 +17,15 @@ import { fieldTypeChoices } from '..';
import MainTab from './MainTab';
import ReportTab from './ReportTab';
import GeneralInfoTab from './GeneralInfoTab';
import ServerSideTabbedForm from '../../../../components/react-admin/ServerSideTabbedForm';


const DataSourceTabbedForm = ({ translate: t, ...props }) => {
const { report } = useRecordContext();
// report is null when a source has been created and no refresh has been done
const errors = report?.errors ?? [];
return (
<TabbedForm {...props}>
<ServerSideTabbedForm {...props}>
<FormTab label="datasource.form.definition">
<MainTab />
</FormTab>
Expand Down Expand Up @@ -59,7 +59,7 @@ const DataSourceTabbedForm = ({ translate: t, ...props }) => {
<FormTab label="datasource.form.infos.title">
<GeneralInfoTab translate={t} />
</FormTab>
</TabbedForm>
</ServerSideTabbedForm>
);
};

Expand Down
2 changes: 1 addition & 1 deletion src/modules/RA/DataSource/views/Edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const DataSourceEdit = props => {

return (
<Edit
mutationMode="optimistic"
mutationMode="pessimistic"
actions={<DataSourceEditActions {...props} />}
{...props}
>
Expand Down
2 changes: 1 addition & 1 deletion src/modules/RA/Picture/components/CustomToolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ const CustomToolbar = ({ basePath, redirect, ...props }) => {
<CancelButton redirect={redirect === 'list' ? basePath : redirect} className={classes.cancel} />
<DeleteWithConfirmButtonJS
redirect={redirect || 'list'}
mutationMode="optimistic"
mutationMode="pessimistic"
translateOptions={{
id: record.identifier,
}}
Expand Down
6 changes: 3 additions & 3 deletions src/modules/RA/Picture/components/PictureFields.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
NumberInput,
ReferenceInput,
SelectInput,
TabbedForm,
TextInput,
required,
ReferenceField,
Expand All @@ -29,6 +28,7 @@ import PictureState from './PictureState';
import { ISODateFormat } from '../../../../utils/date';

import PictureInput from './PictureInput';
import ServerSideTabbedForm from '../../../../components/react-admin/ServerSideTabbedForm';

const useStyles = makeStyles({
inline: {
Expand Down Expand Up @@ -56,7 +56,7 @@ const PictureFields = ({ edit, mapConfig, location, ...props }) => {
const { record: { state } } = props;

return (
<TabbedForm {...props} toolbar={<CustomToolbar />} initialValues={{ state: 'draft' }}>
<ServerSideTabbedForm {...props} toolbar={<CustomToolbar />} initialValues={{ state: 'draft' }}>
<FormTab label="resources.picture.tabs.metadata">

<PictureInput />
Expand Down Expand Up @@ -167,7 +167,7 @@ const PictureFields = ({ edit, mapConfig, location, ...props }) => {
style={{ width: '50%' }}
/>
</FormTab>
</TabbedForm>
</ServerSideTabbedForm>
);
};

Expand Down
4 changes: 2 additions & 2 deletions src/modules/RA/Picture/views/Edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ export const PictureEdit = ({ staticContext, ...props }) => {
return (
<Edit
{...props}
mutationMode="optimistic"
mutationMode="pessimistic"
actions={<DefaultActions redirect={redirect} />}
>
<PictureFields edit redirect={redirect} />
<PictureFields redirect={redirect} />
</Edit>
);
};
Expand Down
10 changes: 5 additions & 5 deletions src/modules/RA/Scene/components/SceneForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
ImageField,
NumberInput,
SelectInput,
SimpleForm,
TextInput,
FormDataConsumer,
required,
Expand All @@ -27,6 +26,7 @@ import SceneFormNameField from './SceneFormNameField';
import { RES_BASELAYER } from '../../ra-modules';

import MapExtentInput from './MapExtentInput';
import ServerSideSimpleForm from '../../../../components/react-admin/ServerSideSimpleForm';

const styles = {
inline: {
Expand All @@ -51,14 +51,14 @@ const ReportField = ({ record, source, className, label, ...rest }) => {
);
};

const SceneForm = ({ edit = false, translate: t, classes, ...props }) => {
const SceneForm = ({ translate: t, classes, ...props }) => {
const { record } = props;

const edit = record.id !== undefined;
/* sanitizeEmptyValues is false for this form to prevent
* this issue with the layer tree https://github.com/marmelab/react-admin/issues/5427
*/
return (
<SimpleForm {...props} sanitizeEmptyValues={false}>
<ServerSideSimpleForm {...props} sanitizeEmptyValues={false}>
{edit && <TextInput disabled source="id" />}

{isObjectEmpty(record) && (
Expand Down Expand Up @@ -111,7 +111,7 @@ const SceneForm = ({ edit = false, translate: t, classes, ...props }) => {
(<ReportField label={t('view.form.import-report')} source="config.report" {...rest} />)}
</FormDataConsumer>

</SimpleForm>
</ServerSideSimpleForm>
);
};

Expand Down
4 changes: 2 additions & 2 deletions src/modules/RA/Scene/views/Edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ const EditSceneForm = PreventPartialData('config', SceneForm);

export const SceneEdit = props => (
<Edit
mutationMode="optimistic"
mutationMode="pessimistic"
{...props}
actions={<DefaultActions />}

>
<EditSceneForm edit />
<EditSceneForm />
</Edit>
);

Expand Down
Loading