Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement Client side server side filters and sort #1457

Merged
merged 10 commits into from
Aug 2, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,7 @@
width: 45%;
min-width: 192px;
}

.filter-row {
margin-bottom: 16px;
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
/* eslint-disable @typescript-eslint/naming-convention */
import React, { ReactNode, useMemo } from 'react';
import { useSimpleTabularView, NoData, Column } from '@opensrp/react-utils';
import {
useSimpleTabularView,
NoData,
Column,
GetControlledSortProps,
SortParamState,
} from '@opensrp/react-utils';
import { RouteComponentProps } from 'react-router';
import { locationResourceType } from '../../constants';
import { BrokenPage, TableLayout, BodyLayout, SearchForm } from '@opensrp/react-utils';
import { Helmet } from 'react-helmet';
import { useMls } from '../../mls';
import { TFunction } from '@opensrp/i18n';
import { Row, Col } from 'antd';
import { useHistory } from 'react-router-dom';
import { BundleEntry } from '@smile-cdr/fhirts/dist/FHIR-R4/classes/bundleEntry';
import { getEntryFromBundle, getTableData } from './utils';
import './base.css';
import type { URLParams } from '@opensrp/server-service';
import { Dictionary } from '@onaio/utils';
import { LocationGridFilterRowRender } from './dataGridFilterRow';
import { SorterResult } from 'antd/es/table/interface';

interface RouteParams {
locationId: string | undefined;
Expand All @@ -20,7 +30,7 @@ interface RouteParams {
export interface Props {
fhirBaseURL: string;
extraParamFilters?: URLParams;
columns: Column<Dictionary>[];
getColumns: (t: TFunction, getColumnSortProps: GetControlledSortProps) => Column<Dictionary>[];
pageTitle: string;
addLocationBtnRender: () => ReactNode;
}
Expand All @@ -41,7 +51,7 @@ export type BaseAllLocationListFlatProps = Props & RouteComponentProps<RoutePara
* @returns {Function} returns paginated locations list display
*/
export const BaseAllLocationListFlat: React.FC<BaseAllLocationListFlatProps> = (props) => {
const { fhirBaseURL, extraParamFilters, addLocationBtnRender, columns, pageTitle } = props;
const { fhirBaseURL, extraParamFilters, addLocationBtnRender, getColumns, pageTitle } = props;
const { t } = useMls();
const history = useHistory();
const getSearchParams = getSearchParamsFactory(extraParamFilters ?? {});
Expand All @@ -50,6 +60,8 @@ export const BaseAllLocationListFlat: React.FC<BaseAllLocationListFlatProps> = (
queryValues: { data, isFetching, isLoading, error },
tablePaginationProps,
searchFormProps,
sortOptions: { updateSortParams, getControlledSortProps },
filterOptions: { updateFilterParams, currentFilters },
} = useSimpleTabularView<BundleEntry>(
fhirBaseURL,
locationResourceType,
Expand Down Expand Up @@ -80,10 +92,29 @@ export const BaseAllLocationListFlat: React.FC<BaseAllLocationListFlatProps> = (

const tableProps = {
datasource: tableData,
columns,
columns: getColumns(t, getControlledSortProps),
loading: isFetching || isLoading,
pagination: tablePaginationProps,
locale: getTableLocale(),
onChange: function (
_: unknown,
__: unknown,
sorter: SorterResult<Dictionary> | SorterResult<Dictionary>[]
) {
const sorterArray = Array.isArray(sorter) ? sorter : [sorter];
const sortMap = sorterArray.reduce((acc, sort) => {
const dataIndex = sort.column?.dataIndex as string | undefined;
if (!sort.order) {
acc[dataIndex as string] = undefined;
return acc;
}
if (dataIndex) {
acc[dataIndex as string] = { paramAccessor: dataIndex, order: sort.order };
}
return acc;
}, {} as SortParamState);
updateSortParams(sortMap);
},
};
const headerProps = {
pageHeaderProps: {
Expand All @@ -103,6 +134,11 @@ export const BaseAllLocationListFlat: React.FC<BaseAllLocationListFlatProps> = (
<SearchForm {...searchFormProps} />
{addLocationBtnRender()}
</div>
<LocationGridFilterRowRender
fhirBaseUrl={fhirBaseURL}
updateFilterParams={updateFilterParams}
currentFilters={currentFilters}
/>
<TableLayout {...tableProps} />
</Col>
</Row>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import { MoreOutlined, PlusOutlined } from '@ant-design/icons';
import { BaseAllLocationListFlat, BaseAllLocationListFlatProps } from './base';
import { Dictionary } from '@onaio/utils';
import { EditLink } from '../EditLink';
import { TFunction } from '@opensrp/i18n';
import { GetControlledSortProps } from '@opensrp/react-utils';

export type AllLocationListFlatProps = Omit<
BaseAllLocationListFlatProps,
Expand Down Expand Up @@ -44,26 +46,24 @@ export const AllLocationListFlat: React.FC<AllLocationListFlatProps> = (props) =
];
};

const columns = [
const getColumns = (t: TFunction, getControlledSortProps: GetControlledSortProps) => [
{
title: t('Name'),
dataIndex: 'name' as const,
editable: true,
sorter: true,
...getControlledSortProps('name'),
},
{
title: t('Parent'),
dataIndex: 'parent' as const,
editable: true,
},
{
title: t('Physical Type'),
dataIndex: 'type' as const,
editable: true,
},
{
title: t('Status'),
dataIndex: 'status' as const,
editable: true,
},
{
title: t('Actions'),
Expand Down Expand Up @@ -107,7 +107,7 @@ export const AllLocationListFlat: React.FC<AllLocationListFlatProps> = (props) =
...props,
pageTitle: t('Locations'),
addLocationBtnRender,
columns,
getColumns,
};

return <BaseAllLocationListFlat {...baseProps} />;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { ILocation } from '@smile-cdr/fhirts/dist/FHIR-R4/interfaces/ILocation';
import { Space, Select } from 'antd';
import React from 'react';
import { FilterParamState, PaginatedAsyncSelect } from '@opensrp/react-utils';
import { locationResourceType } from '@opensrp/fhir-helpers';
import { useMls } from '.././../mls';
import { Trans } from '@opensrp/i18n';

export interface LocationGridFilterRowRenderProps {
fhirBaseUrl: string;
updateFilterParams: (filter: FilterParamState) => void;
currentFilters: FilterParamState;
}

const partOfFilterDataIdx = 'partof';
const statusFilterDataIdx = 'status';

export const LocationGridFilterRowRender = (props: LocationGridFilterRowRenderProps) => {
const { t } = useMls();
const { fhirBaseUrl, updateFilterParams, currentFilters } = props;
return (
<div className="filter-row" data-testid="filter-row">
<Space>
<Trans t={t} i18nKey="parentLocationFilter">
<Space>
Parent Location:
<PaginatedAsyncSelect<ILocation>
allowClear={true}
showSearch={true}
resourceType={locationResourceType}
baseUrl={fhirBaseUrl}
transformOption={(resource) => {
return {
value: resource.id as string,
label: resource.name as string,
ref: resource,
};
}}
onChange={(value) => {
if (!value) {
updateFilterParams({ [partOfFilterDataIdx]: undefined });
} else {
updateFilterParams({
[partOfFilterDataIdx]: {
paramAccessor: 'partof',
rawValue: value,
paramValue: value,
},
});
}
}}
/>
</Space>
</Trans>
<Trans t={t} i18nKey="locationStatusFilter">
<Space>
Status:
<Select
id="location-status-filter"
value={currentFilters['status']?.rawValue ?? '*'}
style={{ width: 120 }}
onChange={(value: string) => {
if (value === '*') {
updateFilterParams({ [statusFilterDataIdx]: undefined });
return;
}
updateFilterParams({
[statusFilterDataIdx]: {
paramAccessor: 'status',
rawValue: value,
paramValue: value,
},
});
}}
options={[
{ value: 'active', label: t('Active') },
{ value: 'inactive', label: t('Inactive') },
{ value: '*', label: t('Show all') },
]}
/>
</Space>
</Trans>
</Space>
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { BaseAllLocationListFlat, BaseAllLocationListFlatProps } from './base';
import { Dictionary } from '@onaio/utils';
import { eusmPhysicalLocationsFilterParams } from './utils';
import { URL_LOCATION_VIEW_DETAILS, URL_SERVICE_POINT_ADD_EDIT } from '../../constants';
import { TFunction } from '@opensrp/i18n';
import { GetControlledSortProps } from '@opensrp/react-utils';

export type EusmLocationListFlatProps = Omit<
BaseAllLocationListFlatProps,
Expand Down Expand Up @@ -38,26 +40,24 @@ export const EusmLocationListFlat: React.FC<EusmLocationListFlatProps> = (props)
];
};

const columns = [
const getColumns = (t: TFunction, getControlledSortProps: GetControlledSortProps) => [
{
title: t('Name'),
dataIndex: 'name' as const,
editable: true,
sorter: true,
...getControlledSortProps('name'),
},
{
title: t('Type'),
dataIndex: 'type' as const,
editable: true,
},
{
title: t('Status'),
dataIndex: 'status' as const,
editable: true,
},
{
title: t('Parent'),
dataIndex: 'parent' as const,
editable: true,
},
{
title: t('Actions'),
Expand Down Expand Up @@ -103,7 +103,7 @@ export const EusmLocationListFlat: React.FC<EusmLocationListFlatProps> = (props)
...props,
pageTitle: t('Service points'),
addLocationBtnRender,
columns,
getColumns,
extraParamFilters: eusmPhysicalLocationsFilterParams,
};

Expand Down
Loading
Loading