Skip to content

Commit

Permalink
custom_fields: add filtering and search on compose fields
Browse files Browse the repository at this point in the history
  • Loading branch information
kpsherva committed Jan 30, 2024
1 parent de9aac9 commit e27a4d1
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 72 deletions.
10 changes: 7 additions & 3 deletions src/lib/forms/widgets/custom_fields/ComposeFields.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export class ComposeFields extends Component {
const { composeSections } = this.props;

this.state = { sections: composeSections, tempFields: [] };
this.fieldsCfg = this.getFieldsConfig(composeSections);
this.sectionsList = composeSections.map((section) => section.section);
}

getFieldsConfig = (sectionCfg) => {
Expand Down Expand Up @@ -57,7 +59,9 @@ export class ComposeFields extends Component {
const sectionToUpdate = this.getSectionOfField(field);
for (const section of sections) {
if (section.section === sectionToUpdate) {
section["fields"] = [...section.fields, field];
section["fields"] = [...section.fields, field].sort((a, b) =>
a.key.localeCompare(b.key)
);
}
}
this.setState({ sections: [...sections], tempFields: [...prevTempFields, field] });
Expand All @@ -67,7 +71,6 @@ export class ComposeFields extends Component {
const { templateLoaders, record } = this.props;
const { sections } = this.state;

const fields = this.getFieldsConfig(sections);
return (
<AccordionField key="compose fields" label="Domain specific fields" active>
{sections.map(({ fields, paths, ...sectionConfig }) => (
Expand All @@ -83,9 +86,10 @@ export class ComposeFields extends Component {
))}
<Extensions
fieldPath="custom_fields"
{...fields}
{...this.fieldsCfg}
templateLoaders={templateLoaders}
addFieldCallback={this.addFieldCallback}
sections={this.sectionsList}
record={record}
/>
</AccordionField>
Expand Down
84 changes: 15 additions & 69 deletions src/lib/forms/widgets/custom_fields/Extensions.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,10 @@
// under the terms of the MIT License; see LICENSE file for more details.

import React, { Component } from "react";
import { ListAndFilterCustomFields } from "./ListAndFilterCustomFields";
import { importWidget } from "../loader";

import {
Button,
Icon,
Modal,
Item,
Divider,
Label,
Grid,
Segment,
} from "semantic-ui-react";
import { Button, Icon, Modal, Divider } from "semantic-ui-react";

import PropTypes from "prop-types";

Expand All @@ -31,7 +23,6 @@ export class Extensions extends Component {
fields: [],
};
}

handleModalOpen = () => {
this.setState({ modalOpen: true });
};
Expand Down Expand Up @@ -69,8 +60,8 @@ export class Extensions extends Component {
if (withClose) {
this.handleModalClosed();
}
this.setState({ selectedField: undefined, selectedFieldTarget: undefined });
addFieldCallback(field);
console.log(`${fieldPath}.${selectedField.field}`);
};

render() {
Expand All @@ -81,10 +72,10 @@ export class Extensions extends Component {
record,
templateLoaders,
addFieldCallback,
sections,
...fieldsList
} = this.props;
const { modalOpen, fields } = this.state;
console.warn(fieldsList, "---------------%%%%%%%%%%%%%%%%%%");

return (
<>
Expand All @@ -95,60 +86,13 @@ export class Extensions extends Component {
</Button>
<Modal open={modalOpen}>
<Modal.Header>Add domain specific fields</Modal.Header>
<Segment as={Modal.Content} attached="bottom ml-0">
test
</Segment>
<Modal.Content scrolling>
<Item.Group divided relaxed>
{Object.entries(fieldsList).map(([key, value]) => {
const names = key.split(":");
const isDisabled = fields
.map((field) => field.key)
.includes(`${fieldPath}.${key}`);

return (
<Item
key={key}
className={
isDisabled ? "pr-10 pl-10 disabled" : "clickable pr-10 pl-10"
}
fieldName={key}
field={fieldsList[key]}
onClick={(e) =>
!isDisabled ? this.handleSelectField(e, key, value) : {}
}
>
<Item.Content>
<Item.Header className={isDisabled ? "text-muted mb-5" : "mb-5"}>
{value.label}
</Item.Header>
<Item.Description>
<Grid>
<Grid.Column width={12}>{value.note}</Grid.Column>
</Grid>
</Item.Description>
<Item.Extra>
<Label>
<Icon name={value.section.icon} />
{value.section.section}: {names[0]}
</Label>
{value.multiple_values === true && (
<Label basic>
<Icon name="list ol" /> Multiple value field
</Label>
)}
{value.type === "text" && (
<Label basic>
<Icon name="text cursor" /> Text field
</Label>
)}
</Item.Extra>
</Item.Content>
</Item>
);
})}
</Item.Group>
</Modal.Content>
<ListAndFilterCustomFields
fieldPath={fieldPath}
handleSelectField={this.handleSelectField}
alreadyAddedFields={fields}
fieldsList={fieldsList}
sections={sections}
/>
<Modal.Actions>
<Button
onClick={this.handleModalClosed}
Expand All @@ -157,11 +101,11 @@ export class Extensions extends Component {
labelPosition="left"
content="Cancel"
/>
<Button icon labelPosition="left">
<Button icon labelPosition="left" onClick={this.handleAddField}>
<Icon name="plus" />
Add field and continue
</Button>
<Button onClick={() => this.handleAddField(true)}>
<Button icon labelPosition="left" onClick={() => this.handleAddField(true)}>
<Icon name="plus" />
Add field and close
</Button>
Expand All @@ -179,9 +123,11 @@ Extensions.propTypes = {
label: PropTypes.string,
templateLoaders: PropTypes.array.isRequired,
addFieldCallback: PropTypes.func.isRequired,
sections: PropTypes.array,
};

Extensions.defaultProps = {
icon: undefined,
label: undefined,
sections: undefined,
};
157 changes: 157 additions & 0 deletions src/lib/forms/widgets/custom_fields/ListAndFilterCustomFields.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import {
Dropdown,
Grid,
Icon,
Input,
Item,
Label,
List,
Modal,
Segment,
} from "semantic-ui-react";

export class ListAndFilterCustomFields extends Component {
constructor(props) {
super(props);
const { fieldsList } = props;
this.state = { filteredFieldsList: fieldsList };
}

resetFilter = () => {
const { fieldsList } = this.props;
this.setState({ filteredFieldsList: fieldsList });
};
handleSearch = (e, { value }) => {
const { fieldsList } = this.props;
if (value) {
const filteredResults = Object.fromEntries(
Object.entries(fieldsList).filter(([key, val]) => {
return val.label.toLowerCase().includes(value.toLowerCase());
})
);

this.setState({ filteredFieldsList: filteredResults });
} else {
this.resetFilter();
}
};

handleDomainFilter = (e, { value }) => {
const { fieldsList } = this.props;
if (value) {
const filteredResults = Object.fromEntries(
Object.entries(fieldsList).filter(([key, val]) => val.section.section === value)
);

this.setState({ filteredFieldsList: filteredResults });
} else {
this.resetFilter();
}
};

render() {
const { filteredFieldsList } = this.state;
const { alreadyAddedFields, fieldPath, handleSelectField, sections } = this.props;
const dropdownOptions = sections.map((section) => ({
key: section,
text: section,
value: section,
}));

return (
<>
<Segment as={Modal.Content} attached="bottom ml-0">
<Grid>
<Grid.Column width={10}>
<Input
fluid
icon="search"
placeholder="Search..."
onChange={this.handleSearch}
/>
</Grid.Column>
<Grid.Column width={6}>
<span className="flex align-items-center">
in:{" "}
<Dropdown
className="ml-5"
fluid
inline
clearable
selection
placeholder="All domains"
options={dropdownOptions}
onChange={this.handleDomainFilter}
/>
</span>
</Grid.Column>
</Grid>
</Segment>
<Modal.Content scrolling>
<Item.Group divided relaxed>
{Object.entries(filteredFieldsList).map(([key, value]) => {
const names = key.split(":");

const isDisabled = alreadyAddedFields
.map((field) => field.key)
.includes(`${fieldPath}.${key}`);

return (
<Item
key={key}
className={
isDisabled ? "pr-10 pl-10 disabled" : "clickable pr-10 pl-10"
}
fieldName={key}
field={filteredFieldsList[key]}
onClick={(e) => (!isDisabled ? handleSelectField(e, key, value) : {})}
>
<Item.Content>
<Item.Header className={isDisabled ? "text-muted mb-5" : "mb-5"}>
{value.label}
</Item.Header>
<Item.Description>
<Grid>
<Grid.Column width={12}>{value.note}</Grid.Column>
</Grid>
</Item.Description>
<Item.Extra>
<Label>
<Icon name={value.section.icon} />
{value.section.section}: {names[0]}
</Label>
{value.multiple_values === true && (
<Label basic>
<Icon name="list ol" /> Multiple value field
</Label>
)}
{value.type === "text" && (
<Label basic>
<Icon name="text cursor" /> Text field
</Label>
)}
</Item.Extra>
</Item.Content>
</Item>
);
})}{" "}
</Item.Group>
</Modal.Content>
</>
);
}
}

ListAndFilterCustomFields.propTypes = {
alreadyAddedFields: PropTypes.array.isRequired,
fieldsList: PropTypes.array.isRequired,
fieldPath: PropTypes.string.isRequired,
handleSelectField: PropTypes.func.isRequired,
sections: PropTypes.array,
};

ListAndFilterCustomFields.defaultProps = {
sections: undefined,
};

0 comments on commit e27a4d1

Please sign in to comment.