Skip to content

Commit

Permalink
chore: Add "no-nested-ternary" ESLint rule to projects (#3514)
Browse files Browse the repository at this point in the history
  • Loading branch information
DafyddLlyr authored Aug 15, 2024
1 parent 9c903a7 commit af2d22e
Show file tree
Hide file tree
Showing 11 changed files with 181 additions and 147 deletions.
3 changes: 2 additions & 1 deletion api.planx.uk/.eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
"supertest.**.expect"
]
}
]
],
"no-nested-ternary": "error"
},
"globals": {
"require": "readonly",
Expand Down
3 changes: 2 additions & 1 deletion e2e/.eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"argsIgnorePattern": "^_"
}
],
"@typescript-eslint/no-non-null-assertion": "off"
"@typescript-eslint/no-non-null-assertion": "off",
"no-nested-ternary": "error"
},
"ignorePatterns": [ "dist/**", "pnpm-lock.yaml" ]
}
3 changes: 2 additions & 1 deletion editor.planx.uk/.eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@
"@typescript-eslint/no-var-requires": "warn",
"@typescript-eslint/no-empty-function": "warn",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/ban-ts-comment": "off"
"@typescript-eslint/ban-ts-comment": "off",
"no-nested-ternary": "error"
},
"settings": {
"jest": {
Expand Down
33 changes: 15 additions & 18 deletions editor.planx.uk/src/@planx/components/Checklist/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -316,24 +316,21 @@ export const ChecklistComponent: React.FC<ChecklistProps> = (props) => {
}),
},
},
options
? options
.filter((o) => o.data.text)
.map((o) => ({
...o,
id: o.id || undefined,
type: TYPES.Answer,
}))
: groupedOptions
? groupedOptions
.flatMap((gr) => gr.children)
.filter((o) => o.data.text)
.map((o) => ({
...o,
id: o.id || undefined,
type: TYPES.Answer,
}))
: [],
...[options && options
.filter((o) => o.data.text)
.map((o) => ({
...o,
id: o.id || undefined,
type: TYPES.Answer,
}))],
...[groupedOptions && groupedOptions
.flatMap((gr) => gr.children)
.filter((o) => o.data.text)
.map((o) => ({
...o,
id: o.id || undefined,
type: TYPES.Answer,
}))]
);
} else {
alert(JSON.stringify({ type, ...values, options }, null, 2));
Expand Down
18 changes: 7 additions & 11 deletions editor.planx.uk/src/@planx/components/Checklist/Public.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
type Checklist,
checklistValidationSchema,
getFlatOptions,
getLayout,
type Group,
} from "@planx/components/Checklist/model";
import ImageButton from "@planx/components/shared/Buttons/ImageButton";
Expand Down Expand Up @@ -71,14 +72,7 @@ const ChecklistComponent: React.FC<Props> = (props) => {
initialExpandedGroups,
);

const layout = options
? options.find((o) => o.data.img)
? ChecklistLayout.Images
: ChecklistLayout.Basic
: groupedOptions
? ChecklistLayout.Grouped
: ChecklistLayout.Basic;

const layout = getLayout({ options, groupedOptions});
const flatOptions = getFlatOptions({ options, groupedOptions });

const changeCheckbox = (id: string) => (_checked: any) => {
Expand Down Expand Up @@ -117,7 +111,7 @@ const ChecklistComponent: React.FC<Props> = (props) => {
component="fieldset"
>
<legend style={visuallyHidden}>{text}</legend>
{options ? (
{options && (
options.map((option) =>
layout === ChecklistLayout.Basic ? (
<FormWrapper key={option.id}>
Expand Down Expand Up @@ -149,7 +143,9 @@ const ChecklistComponent: React.FC<Props> = (props) => {
</Grid>
),
)
) : groupedOptions ? (
)}

{groupedOptions && (
<FormWrapper>
<Grid item xs={12}>
<ExpandableList>
Expand Down Expand Up @@ -195,7 +191,7 @@ const ChecklistComponent: React.FC<Props> = (props) => {
</ExpandableList>
</Grid>
</FormWrapper>
) : null}
)}
</Grid>
</ErrorWrapper>
</FullWidthWrapper>
Expand Down
18 changes: 17 additions & 1 deletion editor.planx.uk/src/@planx/components/Checklist/model.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { array } from "yup";

import { MoreInformation, Option } from "../shared";
import { ChecklistLayout } from "./Public";

export interface Group<T> {
title: string;
Expand All @@ -23,7 +24,7 @@ interface ChecklistExpandableProps {
}

export const toggleExpandableChecklist = (
checklist: ChecklistExpandableProps,
checklist: ChecklistExpandableProps
): ChecklistExpandableProps => {
if (checklist.options !== undefined && checklist.options.length > 0) {
return {
Expand Down Expand Up @@ -75,6 +76,21 @@ export const getFlatOptions = ({
return [];
};

export const getLayout = ({
options,
groupedOptions,
}: {
options: Checklist["options"];
groupedOptions: Checklist["groupedOptions"];
}): ChecklistLayout => {
const hasImages = options?.some((o) => o.data.img);
if (hasImages) return ChecklistLayout.Images;

if (groupedOptions) return ChecklistLayout.Grouped;

return ChecklistLayout.Basic;
};

export const checklistValidationSchema = ({
allRequired,
options,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import digitalLandResponseMock from "./mocks/digitalLandResponseMock";
import PlanningConstraints from "./Public";

jest.spyOn(SWR, "default").mockImplementation((url: any) => {
return {
data: url()?.startsWith(`${process.env.REACT_APP_API_URL}/gis/`)
? digitalLandResponseMock
: url()?.startsWith(`${process.env.REACT_APP_API_URL}/roads/`)
? classifiedRoadsResponseMock
: null,
} as any;
const isGISRequest = url()?.startsWith(`${process.env.REACT_APP_API_URL}/gis/`);
const isRoadsRequest = url()?.startsWith(`${process.env.REACT_APP_API_URL}/roads/`);

if (isGISRequest) return { data: digitalLandResponseMock } as any;
if (isRoadsRequest) return { data: classifiedRoadsResponseMock } as any;

return { data: null };
});

it("renders correctly", async () => {
Expand Down
188 changes: 95 additions & 93 deletions editor.planx.uk/src/@planx/components/PlanningConstraints/Public.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,98 +146,100 @@ function Component(props: Props) {
...roads?.metadata,
};

if (showGraphError) return <ConstraintsGraphError {...props} />;

const isLoading = isValidating && isValidatingRoads && !constraints;

if (isLoading) return (
<Card handleSubmit={props.handleSubmit} isValid>
<CardHeader
title={props.title}
description={props.description || ""}
/>
<DelayedLoadingIndicator text="Fetching data..." />
</Card>
)

return (
<>
{showGraphError ? (
<ConstraintsGraphError {...props} />
) : !isValidating && !isValidatingRoads && constraints ? (
<PlanningConstraintsContent
title={props.title}
description={props.description || ""}
fn={props.fn}
disclaimer={props.disclaimer}
constraints={constraints}
metadata={metadata}
handleSubmit={() => {
// `_constraints` & `_overrides` are responsible for auditing
const _constraints: Array<
EnhancedGISResponse | GISResponse["constraints"]
> = [];
if (hasPlanningData) {
if (data && !dataError)
_constraints.push({
...data,
planxRequest: teamGisEndpoint,
} as EnhancedGISResponse);
if (roads && !roadsError)
_constraints.push({
...roads,
planxRequest: classifiedRoadsEndpoint,
} as EnhancedGISResponse);
} else {
if (data) _constraints.push(data as GISResponse["constraints"]);
}

const hasInaccurateConstraints = inaccurateConstraints && Object.keys(inaccurateConstraints).length > 0;
const _overrides = hasInaccurateConstraints ? { ...priorOverrides, [props.fn]: inaccurateConstraints } : undefined;

// `planningConstraints.action` is for analytics
const userAction = hasInaccurateConstraints
? "Reported at least one inaccurate planning constraint"
: "Accepted all planning constraints";

// `[props.fn]` & `_nots[props.fn]` are responsible for future service automations
const _nots: IntersectingConstraints = {};
const intersectingConstraints: IntersectingConstraints = {};
Object.entries(constraints).forEach(([key, data]) => {
if (data.value) {
intersectingConstraints[props.fn] ||= [];
intersectingConstraints[props.fn].push(key);
} else {
_nots[props.fn] ||= [];
_nots[props.fn].push(key);
}
});

// If the user reported inaccurate constraints, ensure they are correctly reflected in `[props.fn]` & `_nots[props.fn]`
const {
nots: notsAfterOverrides,
intersectingConstraints: intersectingConstraintsAfterOverrides,
} = handleOverrides(
props.fn,
constraints,
inaccurateConstraints,
intersectingConstraints,
_nots,
);

const passportData = {
_constraints,
_overrides,
"planningConstraints.action": userAction,
_nots: notsAfterOverrides,
...(intersectingConstraintsAfterOverrides[props.fn]?.length === 0 ? undefined : intersectingConstraintsAfterOverrides),
};

props.handleSubmit?.({
data: passportData,
});
}}
refreshConstraints={() => mutate()}
inaccurateConstraints={inaccurateConstraints}
setInaccurateConstraints={setInaccurateConstraints}
/>
) : (
<Card handleSubmit={props.handleSubmit} isValid>
<CardHeader
title={props.title}
description={props.description || ""}
/>
<DelayedLoadingIndicator text="Fetching data..." />
</Card>
)}
</>
);
<PlanningConstraintsContent
title={props.title}
description={props.description || ""}
fn={props.fn}
disclaimer={props.disclaimer}
constraints={constraints}
metadata={metadata}
handleSubmit={() => {
// `_constraints` & `_overrides` are responsible for auditing
const _constraints: Array<
EnhancedGISResponse | GISResponse["constraints"]
> = [];
if (hasPlanningData) {
if (data && !dataError)
_constraints.push({
...data,
planxRequest: teamGisEndpoint,
} as EnhancedGISResponse);
if (roads && !roadsError)
_constraints.push({
...roads,
planxRequest: classifiedRoadsEndpoint,
} as EnhancedGISResponse);
} else {
if (data) _constraints.push(data as GISResponse["constraints"]);
}

const hasInaccurateConstraints = inaccurateConstraints && Object.keys(inaccurateConstraints).length > 0;
const _overrides = hasInaccurateConstraints ? { ...priorOverrides, [props.fn]: inaccurateConstraints } : undefined;

// `planningConstraints.action` is for analytics
const userAction = hasInaccurateConstraints
? "Reported at least one inaccurate planning constraint"
: "Accepted all planning constraints";

// `[props.fn]` & `_nots[props.fn]` are responsible for future service automations
const _nots: IntersectingConstraints = {};
const intersectingConstraints: IntersectingConstraints = {};
Object.entries(constraints).forEach(([key, data]) => {
if (data.value) {
intersectingConstraints[props.fn] ||= [];
intersectingConstraints[props.fn].push(key);
} else {
_nots[props.fn] ||= [];
_nots[props.fn].push(key);
}
});

// If the user reported inaccurate constraints, ensure they are correctly reflected in `[props.fn]` & `_nots[props.fn]`
const {
nots: notsAfterOverrides,
intersectingConstraints: intersectingConstraintsAfterOverrides,
} = handleOverrides(
props.fn,
constraints,
inaccurateConstraints,
intersectingConstraints,
_nots,
);

const passportData = {
_constraints,
_overrides,
"planningConstraints.action": userAction,
_nots: notsAfterOverrides,
...(intersectingConstraintsAfterOverrides[props.fn]?.length === 0 ? undefined : intersectingConstraintsAfterOverrides),
};


props.handleSubmit?.({
data: passportData,
});
}}
refreshConstraints={() => mutate()}
inaccurateConstraints={inaccurateConstraints}
setInaccurateConstraints={setInaccurateConstraints}
/>
)

}

export type PlanningConstraintsContentProps = {
Expand Down Expand Up @@ -377,8 +379,8 @@ const ConstraintsFetchError = (props: ConstraintsFetchErrorProps) => (
No information available
</Typography>
{props.error &&
typeof props.error === "string" &&
props.error.endsWith("local authority") ? (
typeof props.error === "string" &&
props.error.endsWith("local authority") ? (
<Typography variant="body2">{capitalize(props.error)}</Typography>
) : (
<>
Expand Down
Loading

0 comments on commit af2d22e

Please sign in to comment.