Skip to content

Commit

Permalink
generate form: refactor fields
Browse files Browse the repository at this point in the history
* add overridable components to admin forms
  • Loading branch information
kpsherva committed Aug 23, 2024
1 parent dbd9edf commit 5ac7f06
Show file tree
Hide file tree
Showing 11 changed files with 431 additions and 253 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import { Actions } from "../actions/Actions";
import _isEmpty from "lodash/isEmpty";
import { sortFields } from "../components/utils";
import { Loader, ErrorPage } from "../components";
import Overridable from "react-overridable";

export default class AdminDetailsView extends Component {
class AdminDetailsView extends Component {
constructor(props) {
super(props);
this.state = {
Expand Down Expand Up @@ -73,51 +74,60 @@ export default class AdminDetailsView extends Component {
displayDelete,
displayEdit,
uiSchema,
name,
} = this.props;
const { loading, data, error } = this.state;
const sortedColumns = sortFields(uiSchema);
return (
<Loader isLoading={loading}>
<ErrorPage
error={!_isEmpty(error)}
errorCode={error?.response.status}
errorMessage={error?.response.data}
>
<Grid stackable>
<Grid.Row columns="2">
<Grid.Column verticalAlign="middle">
<Header as="h1">{title}</Header>
</Grid.Column>
<Grid.Column verticalAlign="middle" floated="right" textAlign="right">
<Button.Group size="tiny" className="relaxed">
<Actions
title={title}
resourceName={resourceName}
apiEndpoint={apiEndpoint}
editUrl={AdminUIRoutes.editView(listUIEndpoint, data, idKeyPath)}
actions={actions}
displayEdit={displayEdit}
displayDelete={displayDelete}
resource={data}
idKeyPath={idKeyPath}
successCallback={this.handleDelete}
listUIEndpoint={listUIEndpoint}
/>
</Button.Group>
</Grid.Column>
</Grid.Row>
</Grid>
<Divider />
<Container fluid>
<DetailsTable
data={data}
schema={resourceSchema}
uiSchema={sortedColumns}
/>
{this.childrenWithData(data, columns)}
</Container>
</ErrorPage>
</Loader>
<Overridable
id={`InvenioAdministration.AdminDetailsView.${name}.layout`}
data={data}
error={error}
loading={loading}
{...this.props}
>
<Loader isLoading={loading}>
<ErrorPage
error={!_isEmpty(error)}
errorCode={error?.response.status}
errorMessage={error?.response.data}
>
<Grid stackable>
<Grid.Row columns="2">
<Grid.Column verticalAlign="middle">
<Header as="h1">{title}</Header>
</Grid.Column>
<Grid.Column verticalAlign="middle" floated="right" textAlign="right">
<Button.Group size="tiny" className="relaxed">
<Actions
title={title}
resourceName={resourceName}
apiEndpoint={apiEndpoint}
editUrl={AdminUIRoutes.editView(listUIEndpoint, data, idKeyPath)}
actions={actions}
displayEdit={displayEdit}
displayDelete={displayDelete}
resource={data}
idKeyPath={idKeyPath}
successCallback={this.handleDelete}
listUIEndpoint={listUIEndpoint}
/>
</Button.Group>
</Grid.Column>
</Grid.Row>
</Grid>
<Divider />
<Container fluid>
<DetailsTable
data={data}
schema={resourceSchema}
uiSchema={sortedColumns}
/>
{this.childrenWithData(data, columns)}
</Container>
</ErrorPage>
</Loader>
</Overridable>
);
}
}
Expand All @@ -137,9 +147,15 @@ AdminDetailsView.propTypes = {
resourceSchema: PropTypes.object.isRequired,
requestHeaders: PropTypes.object.isRequired,
uiSchema: PropTypes.object.isRequired,
name: PropTypes.string.isRequired,
};

AdminDetailsView.defaultProps = {
actions: undefined,
children: undefined,
};

export default Overridable.component(
"InvenioAdministration.AdminDetailsView",
AdminDetailsView
);
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import React from "react";
import ReactDOM from "react-dom";
import _get from "lodash/get";
import AdminDetailsView from "./AdminDetailsView";
import { OverridableContext, overrideStore } from "react-overridable";

const overriddenComponents = overrideStore.getAll();

const domContainer = document.getElementById("invenio-details-config");

Expand All @@ -24,23 +27,28 @@ const listUIEndpoint = domContainer.dataset.listEndpoint;
const resourceSchema = JSON.parse(domContainer.dataset?.resourceSchema);
const requestHeaders = JSON.parse(domContainer.dataset?.requestHeaders);
const uiSchema = JSON.parse(domContainer.dataset?.uiConfig);
const name = JSON.parse(domContainer.dataset?.name);

domContainer &&
ReactDOM.render(
<AdminDetailsView
title={title}
actions={actions}
apiEndpoint={apiEndpoint}
columns={fields}
pid={pidValue}
displayEdit={displayEdit}
displayDelete={displayDelete}
idKeyPath={idKeyPath}
resourceName={resourceName}
listUIEndpoint={listUIEndpoint}
resourceSchema={resourceSchema}
requestHeaders={requestHeaders}
uiSchema={uiSchema}
/>,
<OverridableContext.Provider value={overriddenComponents}>
<AdminDetailsView
title={title}
actions={actions}
apiEndpoint={apiEndpoint}
columns={fields}
pid={pidValue}
displayEdit={displayEdit}
displayDelete={displayDelete}
idKeyPath={idKeyPath}
resourceName={resourceName}
listUIEndpoint={listUIEndpoint}
resourceSchema={resourceSchema}
requestHeaders={requestHeaders}
uiSchema={uiSchema}
name={name}
/>
,
</OverridableContext.Provider>,
domContainer
);
Original file line number Diff line number Diff line change
@@ -1,9 +1,37 @@
import { mapFormFields } from "./fields";
import { generateFieldProps } from "./props_generator";
import React from "react";
import { Array } from "react-invenio-forms";
import { Form, Button, Icon } from "semantic-ui-react";
import { i18next } from "@translations/invenio_administration/i18next";
import PropTypes from "prop-types";

export const generateArrayFieldProps = (
fieldName,
fieldSchema,
parentField,
isCreate,
formFieldConfig,
formikProps,
formFieldsConfig
) => {
const fieldProps = generateFieldProps(
fieldName,
fieldSchema,
parentField,
isCreate,
formFieldConfig,
formikProps
);
const arrayFieldProps = {
fieldSchema: fieldSchema,
isCreate: isCreate,
mapFormFields: mapFormFields,
formFields: formFieldsConfig,
};
return { ...fieldProps, ...arrayFieldProps };
};

const createEmptyArrayRowObject = (properties) => {
const emptyRow = {};
for (let [key, schema] of Object.entries(properties)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import { BooleanField } from "react-invenio-forms";

export class AdminBoolField extends Component {
render() {
const { fieldSchema, ...fieldProps } = this.props;
const description = fieldProps.description;

return (
<>
<BooleanField
key={fieldProps.fieldPath}
required={fieldSchema.required}
value={fieldSchema.metadata.checked === "true"}
{...fieldProps}
/>
{description && <label className="helptext">{description}</label>}
</>
);
}
}

AdminBoolField.propTypes = {
fieldProps: PropTypes.object.isRequired,
fieldSchema: PropTypes.object.isRequired,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { generateFieldProps } from "./props_generator";
import { LazyForm } from "../LazyForm";
import React, { Component } from "react";
import PropTypes from "prop-types";
import { Form, Segment, Header } from "semantic-ui-react";

export const generateDynamicFieldProps = (
fieldName,
fieldSchema,
parentField,
isCreate,
formFieldConfig,
formikProps,
formFieldsConfig,
formData
) => {
const fieldProps = generateFieldProps(
fieldName,
fieldSchema,
parentField,
isCreate,
formFieldConfig,
formikProps
);
const dynamicFieldProps = {
formData: formData,
formikProps: formikProps,
};
return { ...fieldProps, ...dynamicFieldProps };
};

export class DynamicSubFormField extends Component {
render() {
const { formikProps, fieldSchema, formData, ...fieldProps } = this.props;

return (
<React.Fragment key={fieldProps.fieldPath}>
<Header attached="top" as="h5">
{fieldProps.label}
</Header>
<Segment attached="bottom">
<Form.Group grouped>
<LazyForm
{...fieldProps}
formikProps={formikProps}
fieldSchema={fieldSchema}
key={fieldProps.fieldPath}
formData={formData}
/>
</Form.Group>
</Segment>
</React.Fragment>
);
}
}

DynamicSubFormField.propTypes = {
fieldProps: PropTypes.object.isRequired,
fieldSchema: PropTypes.object.isRequired,
formikProps: PropTypes.object.isRequired,
formData: PropTypes.object.isRequired,
};
Loading

0 comments on commit 5ac7f06

Please sign in to comment.