Skip to content

Commit

Permalink
Refactors, Fixes and minor updates
Browse files Browse the repository at this point in the history
  • Loading branch information
Onitoxan committed Apr 26, 2024
1 parent 1e39564 commit f9a9905
Show file tree
Hide file tree
Showing 14 changed files with 131 additions and 60 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Form, Formik, FormikState } from 'formik';
import tw from 'twin.macro';

import { C, FormObjectValue } from '@unocha/hpc-ui';
import { C } from '@unocha/hpc-ui';
import { util as codecs, FormObjectValue } from '@unocha/hpc-data';
import { Environment } from '../../../environments/interface';
import { decodeFilters, encodeFilters } from '../../utils/parse-filters';
import { LanguageKey, t } from '../../../i18n';
Expand Down Expand Up @@ -52,7 +53,7 @@ export const FilterOrganizationsTable = (props: Props) => {
);

const FORM_VALIDATION = io.partial({
organization: io.string,
date: codecs.VALID_DAYJS_DATE,
});

const handleSubmit = (values: OrganizationFilterValues) => {
Expand Down Expand Up @@ -125,6 +126,7 @@ export const FilterOrganizationsTable = (props: Props) => {
)}
name="organizationType"
fnPromise={() => fnCategories('organizationType', environment)}
isAutocompleteAPI={false}
/>
<C.AsyncAutocompleteSelect
label={t.t(
Expand Down Expand Up @@ -153,7 +155,7 @@ export const FilterOrganizationsTable = (props: Props) => {
(s) => s.components.organizationsFilter.filters.date
)}
/>
<C.SingleSelect
<C.AutocompleteSelect
name="status"
label={t.t(
lang,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import { Form, Formik, FormikState } from 'formik';
import tw from 'twin.macro';

import { C, FormObjectValue } from '@unocha/hpc-ui';
import { C } from '@unocha/hpc-ui';
import { FormObjectValue } from '@unocha/hpc-data';
import { decodeFilters, encodeFilters } from '../../utils/parse-filters';
import { t } from '../../../i18n';
import { Query } from '../tables/table-utils';
import { useContext } from 'react';
import { AppContext } from '../../context';
import validateForm from '../../utils/form-validation';
import * as io from 'io-ts';
import { util as codecs } from '@unocha/hpc-data';
import {
fnLocations,
fnOrganizations,
Expand All @@ -21,8 +19,8 @@ interface Props {
handleAbortController: () => void;
}
export interface PendingFlowsFilterValues {
status?: string;
dataProvider?: string;
status?: FormObjectValue | null;
dataProvider?: FormObjectValue | null;
reporterRefCode?: string;
sourceOrganizations?: Array<FormObjectValue>;
sourceCountries?: Array<FormObjectValue>;
Expand All @@ -33,8 +31,8 @@ export interface PendingFlowsFilterValues {
}

export const PENDING_FLOWS_FILTER_INITIAL_VALUES: PendingFlowsFilterValues = {
status: '',
dataProvider: '',
status: null,
dataProvider: null,
reporterRefCode: '',
sourceOrganizations: [],
sourceCountries: [],
Expand All @@ -55,10 +53,6 @@ export const FilterPendingFlowsTable = (props: Props) => {
const { lang, env } = useContext(AppContext);
const environment = env();

const FORM_VALIDATION = io.partial({
reporterRefCode: codecs.POSITIVE_INTEGER_FROM_STRING,
});

const handleSubmit = (values: PendingFlowsFilterValues) => {
const encodedFilters = encodeFilters(
values,
Expand Down Expand Up @@ -100,7 +94,6 @@ export const FilterPendingFlowsTable = (props: Props) => {
query.filters,
PENDING_FLOWS_FILTER_INITIAL_VALUES
)}
validate={(values) => validateForm(values, FORM_VALIDATION)}
onSubmit={handleSubmit}
>
{({ resetForm }) => (
Expand All @@ -125,21 +118,21 @@ export const FilterPendingFlowsTable = (props: Props) => {
(s) => s.components.pendingFlowsFilter.filters.details
)}
>
<C.SingleSelect
<C.AutocompleteSelect
label={t.t(
lang,
(s) => s.components.pendingFlowsFilter.filters.status
)}
name="status"
options={[
{ displayLabel: 'New', value: 'New' },
{ displayLabel: 'Update', value: 'Update' },
{ displayLabel: 'New', value: 'new' },
{ displayLabel: 'Update', value: 'updated' },
]}
/>
<C.AsyncSingleSelect
<C.AsyncAutocompleteSelect
label={t.t(
lang,
(s) => s.components.pendingFlowsFilter.filters.flowType
(s) => s.components.pendingFlowsFilter.filters.dataProvider
)}
name="dataProvider"
fnPromise={async () => {
Expand All @@ -151,6 +144,7 @@ export const FilterPendingFlowsTable = (props: Props) => {
};
});
}}
isAutocompleteAPI={false}
/>
<C.NumberField
label={t.t(
Expand Down
14 changes: 4 additions & 10 deletions apps/hpc-ftsadmin/src/app/pages/organizations/organization.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import {
C,
CLASSES,
FormObjectValue,
combineClasses,
useDataLoader,
} from '@unocha/hpc-ui';
import { C, CLASSES, combineClasses, useDataLoader } from '@unocha/hpc-ui';
import { t } from '../../../i18n';
import PageMeta from '../../components/page-meta';
import { AppContext, getEnv } from '../../context';
Expand All @@ -13,7 +7,7 @@ import { useParams } from 'react-router-dom';
import OrganizationForm, {
AddEditOrganizationValues,
} from '../../components/organization-form';
import { organizations } from '@unocha/hpc-data';
import { organizations, FormObjectValue } from '@unocha/hpc-data';

interface Props {
className?: string;
Expand Down Expand Up @@ -159,7 +153,7 @@ export default (props: Props) => {
<InfoText>
{t.t(
lang,
(s) => s.components.organizationUpdateCreate.update
(s) => s.components.organizationUpdateCreate.text.edit
)}
</InfoText>
<OrganizationForm
Expand All @@ -181,7 +175,7 @@ export default (props: Props) => {
<InfoText>
{t.t(
lang,
(s) => s.components.organizationUpdateCreate.create
(s) => s.components.organizationUpdateCreate.text.create
)}
</InfoText>
<OrganizationForm />
Expand Down
3 changes: 1 addition & 2 deletions apps/hpc-ftsadmin/src/app/utils/fn-promises.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { categories } from '@unocha/hpc-data';
import { categories, FormObjectValue } from '@unocha/hpc-data';
import { Environment } from '../../environments/interface';
import { FormObjectValue } from '@unocha/hpc-ui';

/** Functions to pass to <AsyncAutocompleteSelect /> fnPromise prop */

Expand Down
3 changes: 1 addition & 2 deletions apps/hpc-ftsadmin/src/app/utils/map-functions.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { organizations } from '@unocha/hpc-data';
import { organizations, FormObjectValue } from '@unocha/hpc-data';
import { LanguageKey } from '../../i18n';
import dayjs from 'dayjs';
import { FormObjectValue } from '@unocha/hpc-ui';

export const valueToInteger = (value: string | number) => {
return typeof value === 'number' ? value : parseInt(value);
Expand Down
61 changes: 50 additions & 11 deletions apps/hpc-ftsadmin/src/app/utils/parse-filters.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { categories, flows, organizations } from '@unocha/hpc-data';
import {
categories,
flows,
organizations,
FormObjectValue,
} from '@unocha/hpc-data';
import { PendingFlowsFilterValues } from '../components/filters/filter-pending-flows-table';
import { Strings } from '../../i18n/iface';
import { OrganizationFilterValues } from '../components/filters/filter-organization-table';
import { Dayjs } from 'dayjs';
import { FlowsFilterValues } from '../components/filters/filter-flows-table';
import { valueToInteger } from './map-functions';
import { FormObjectValue } from '@unocha/hpc-ui';

/**
* The whole idea of this filtering system is to parse every Filter Form to a common type, in this case Filter<T>
Expand Down Expand Up @@ -43,7 +47,7 @@ export type FlowStatusType =
| 'commitment'
| 'carryover'
| 'paid'
| 'pledged'
| 'pledge'
| 'parked'
| 'pass_through'
| 'standard';
Expand All @@ -52,7 +56,7 @@ export type FlowStatusType =
* Type guard functions
*/

const filterValueIsString = (value: FilterValues): value is string => {
const filterValueIsString = (value: FilterValues | number): value is string => {
return typeof value === 'string';
};

Expand Down Expand Up @@ -92,13 +96,13 @@ const filterValueIsDayJS = (value: FilterValues): value is Dayjs => {
};

const filterValueIsFlowStatusType = (
value: FilterValues
value: FilterValues | number
): value is FlowStatusType => {
const values = [
'commitment',
'carryover',
'paid',
'pledged',
'pledge',
'parked',
'pass_through',
'standard',
Expand Down Expand Up @@ -252,7 +256,10 @@ const parseActiveStatus = (activeStatus: string): boolean | undefined => {
};

export const parseFlowFilters = (
filters: Filter<keyof Strings['components']['flowsFilter']['filters']>,
filters: Filter<
| keyof Strings['components']['flowsFilter']['filters']
| keyof Strings['components']['pendingFlowsFilter']['filters']
>,
pending?: boolean
): flows.SearchFlowsParams => {
const res: flows.SearchFlowsParams = {
Expand Down Expand Up @@ -346,11 +353,13 @@ export const parseFlowFilters = (
case 'flowType':
case 'flowStatus': {
const filterValue = filters[key]?.value;
console.log(filterValue);
if (!filterValue) {
break;
}
if (filterValueIsFlowStatusType(filterValue)) {
res[filterValue] = true;
if (filterValueIsFormObjectValue(filterValue)) {
const statusType = filterValue.value;
if (filterValueIsFlowStatusType(statusType)) res[statusType] = true;
}
break;
}
Expand Down Expand Up @@ -407,6 +416,33 @@ export const parseFlowFilters = (
}
break;
}
case 'dataProvider': {
const dataProvider = filters.dataProvider?.value;
if (!dataProvider) {
break;
}
if (
filterValueIsFormObjectValue(dataProvider) &&
filterValueIsString(dataProvider.value)
) {
res.nestedFlowFilters.systemID = dataProvider.value;
}
break;
}
case 'status': {
const status = filters.status?.value;
if (!status) {
break;
}
if (
filterValueIsFormObjectValue(status) &&
filterValueIsString(status.value) &&
(status.value === 'new' || status.value === 'updated')
) {
res.status = status.value;
}
break;
}
}
}
}
Expand Down Expand Up @@ -478,8 +514,11 @@ export const parseOrganizationFilters = (
if (!value) {
break;
}
if (filterValueIsString(value)) {
res.search[key] = value;
if (
filterValueIsFormObjectValue(value) &&
filterValueIsString(value.value)
) {
res.search[key] = value.value;
}
break;
}
Expand Down
2 changes: 2 additions & 0 deletions libs/hpc-data/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import * as projects from './lib/projects';
import * as reportingWindows from './lib/reporting-windows';
import * as usageYears from './lib/usageYears';
import * as util from './lib/util';
import { FormObjectValue } from './lib/util';

export interface Model {
access: access.Model;
Expand Down Expand Up @@ -48,4 +49,5 @@ export {
usageYears,
util,
systems,
FormObjectValue,
};
44 changes: 42 additions & 2 deletions libs/hpc-data/src/lib/util.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import * as t from 'io-ts';
import { Dayjs, isDayjs } from 'dayjs';

export type FormObjectValue = { displayLabel: string; value: string | number };

export const resultWithPermissions = <D, P extends { [id: string]: boolean }>(
data: t.Type<D>,
Expand Down Expand Up @@ -203,8 +206,8 @@ export const ARRAY_BUFFER = new t.Type<ArrayBuffer, ArrayBuffer>(
* Takes date string and verifies that
* it is a valid date in YYYY-MM-DD format
*/
const isDateValid = (date: string) => {
if (!ISO_DATE.test(date)) {
const isDateValid = (date: string | undefined) => {
if (!date || !ISO_DATE.test(date)) {
return false;
}

Expand Down Expand Up @@ -269,3 +272,40 @@ export const DATE_FROM_STRING = new t.Type(
},
t.identity
);

const isFormObjectValue = (v: unknown): v is FormObjectValue =>
typeof v === 'object' &&
!Array.isArray(v) &&
v !== null &&
Object.keys(v).includes('displayLabel') &&
Object.keys(v).includes('value');

/**
* Accepts a FormObjectValue.
*/
export const FORM_OBJECT_VALUE = new t.Type<FormObjectValue, FormObjectValue>(
'FORM_OBJECT_VALUE',
isFormObjectValue,
(v, c) => {
if (isFormObjectValue(v)) {
return t.success(v);
}
return t.failure(v, c);
},
t.identity
);

export const VALID_DAYJS_DATE = new t.Type<Dayjs, Dayjs>(
'VALID_DAYJS_DATE',
(u): u is Dayjs => u instanceof Dayjs,
(v, c) => {
if (isDayjs(v)) {
if (isDateValid(v.toISOString().split('T').at(0))) {
return t.success(v);
}
return t.failure(v, c);
}
return t.failure(v, c);
},
t.identity
);
Loading

0 comments on commit f9a9905

Please sign in to comment.