Skip to content

Commit

Permalink
[New #168] Added template filter for records table
Browse files Browse the repository at this point in the history
  • Loading branch information
LaChope authored and blcham committed Jun 5, 2024
1 parent a92e673 commit cb59fea
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 1 deletion.
41 changes: 40 additions & 1 deletion src/components/record/RecordTable.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { ROLE } from "../../constants/DefaultConstants";
import DateIntervalFilter from "./filter/DateIntervalFilter";
import PhaseFilter from "./filter/PhaseFilter";
import InstitutionFilter from "./filter/InstitutionFilter";
import TemplateFilter from "./filter/TemplateFilter.jsx";
import SortIndicator from "../misc/SortIndicator";
import { useI18n } from "../../hooks/useI18n";
import FilterIndicator from "../misc/FilterIndicator";
Expand Down Expand Up @@ -93,7 +94,7 @@ class RecordTable extends React.Component {
<th className="col-2 content-center">{this.i18n("records.local-name")}</th>
<IfGranted expected={ROLE.ADMIN} actual={this.props.currentUser.role}>
<FilterableInstitutionHeader filters={filters} onFilterChange={onChange} />
<th className="col-2 content-center">{this.i18n("records.form-template")}</th>
<FilterableTemplateHeader filters={filters} onFilterChange={onChange} />
</IfGranted>
<FilterableLastModifiedHeader filters={filters} sort={sort} onFilterAndSortChange={onChange} />
<FilterablePhaseHeader filters={filters} onFilterChange={onChange} />
Expand Down Expand Up @@ -169,6 +170,7 @@ FilterableInstitutionHeader.propTypes = {
minDate: PropTypes.instanceOf(Date),
maxDate: PropTypes.instanceOf(Date),
phase: PropTypes.string,
template: PropTypes.string,
}),
onFilterChange: PropTypes.func,
};
Expand Down Expand Up @@ -212,6 +214,7 @@ FilterableLastModifiedHeader.propTypes = {
minDate: PropTypes.instanceOf(Date),
maxDate: PropTypes.instanceOf(Date),
phase: PropTypes.string,
template: PropTypes.string,
}),
sort: PropTypes.shape({
date: PropTypes.string,
Expand Down Expand Up @@ -248,6 +251,42 @@ FilterablePhaseHeader.propTypes = {
minDate: PropTypes.instanceOf(Date),
maxDate: PropTypes.instanceOf(Date),
phase: PropTypes.string,
template: PropTypes.string,
}),
onFilterChange: PropTypes.func,
};

// TODO: Change `filters.phase` to filters.`template` when backend is ready
const FilterableTemplateHeader = ({ filters, onFilterChange }) => {
const { i18n } = useI18n();
return (
<OverlayTrigger
trigger="click"
placement="bottom"
rootClose={true}
overlay={
<Popover id="records-filters-template" className="record-filters-popup">
<Popover.Content>
<TemplateFilter value={filters.phase} onChange={onFilterChange} />
</Popover.Content>
</Popover>
}
>
<th id="records-template" className="col-2 content-center cursor-pointer" title={i18n("table.column.filterable")}>
{i18n("records.form-template")}
<FilterIndicator filterValue={filters.phase} />
</th>
</OverlayTrigger>
);
};

FilterableTemplateHeader.propTypes = {
filters: PropTypes.shape({
institution: PropTypes.string,
minDate: PropTypes.instanceOf(Date),
maxDate: PropTypes.instanceOf(Date),
phase: PropTypes.string,
template: PropTypes.string,
}),
onFilterChange: PropTypes.func,
};
Expand Down
86 changes: 86 additions & 0 deletions src/components/record/filter/TemplateFilter.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import React from "react";
import { Button, Col, Form, Row } from "react-bootstrap";
import { IntelligentTreeSelect } from "intelligent-tree-select";
import { useI18n } from "../../../hooks/useI18n";
import { sanitizeArray } from "../../../utils/Utils";
import PropTypes from "prop-types";
import { useDispatch, useSelector } from "react-redux";
import { loadFormTemplates } from "../../../actions/FormTemplatesActions.js";

const TemplateFilter = ({ value, onChange }) => {
const { i18n } = useI18n();
const dispatch = useDispatch();
const templates = useSelector((state) => state.formTemplates.formTemplatesLoaded.formTemplates);
React.useEffect(() => {
if (!templates) {
dispatch(loadFormTemplates());
}
}, [dispatch, templates]);
const values = sanitizeArray(value);
const selected = templates.filter(
(o) => values.indexOf(o["http://www.w3.org/2000/01/rdf-schema#label"]["@value"]) !== -1, //this is probably not correct
);

const getFilterOptions = () => {
let templatesWithLabelAndValue = [];
for (const t of templates) {
templatesWithLabelAndValue.push({
value: t["http://www.w3.org/2000/01/rdf-schema#label"][0]["@value"],
label: t["http://www.w3.org/2000/01/rdf-schema#label"][0]["@value"],
...t,
});
}
return templatesWithLabelAndValue;
};

return (
<Form className="mt-1">
<Form.Group as={Row}>
<Form.Label column={true} xs={4}>
{i18n("records.form-template")}
</Form.Label>
<Col xs={8}>
<IntelligentTreeSelect
options={getFilterOptions()}
multi={true}
renderAsTree={false}
onChange={
(o) => onChange({ phase: o.map((o) => o["http://www.w3.org/2000/01/rdf-schema#label"][0]["@value"]) }, {}) // this is probably not correct
}
value={selected}
placeholder={i18n("select.placeholder")}
isClearable={false}
/>
</Col>
</Form.Group>
<hr />
<Row>
<Col>
<div className="float-right">
<Button
size="sm"
disabled={values.length === 0}
onClick={() =>
onChange(
{
phase: undefined,
},
{},
)
}
>
{i18n("filters.reset")}
</Button>
</div>
</Col>
</Row>
</Form>
);
};

TemplateFilter.propTypes = {
value: PropTypes.string,
onChange: PropTypes.func.isRequired,
};

export default TemplateFilter;

0 comments on commit cb59fea

Please sign in to comment.