Skip to content

Commit

Permalink
chore: refactor filter panel with ts magic
Browse files Browse the repository at this point in the history
  • Loading branch information
drodil committed Oct 31, 2024
1 parent 0ef70d1 commit 54f7204
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 117 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ import { useAnalytics } from '@backstage/core-plugin-api';
import { filterTags } from '@drodil/backstage-plugin-qeta-common';
import { getFiltersWithDateRange } from '../../utils/utils';
import {
AnswerFilters,
FilterKey,
filterKeys,
FilterPanel,
Filters,
} from '../FilterPanel/FilterPanel';
import { AnswerList } from './AnswerList';
import { useQetaApi, useTranslation } from '../../hooks';
Expand All @@ -40,12 +40,11 @@ export const AnswersContainer = (props: AnswersContainerProps) => {
const [showFilterPanel, setShowFilterPanel] = React.useState(false);
const [searchParams, setSearchParams] = useSearchParams();
const [searchQuery, setSearchQuery] = React.useState('');
const [filters, setFilters] = React.useState<Filters>({
const [filters, setFilters] = React.useState<AnswerFilters>({
order: 'desc',
orderBy: 'created',
searchQuery: '',
dateRange: '',
noCorrectAnswer: 'false',
entity: entity ?? '',
tags: tags ?? [],
noVotes: 'false',
Expand All @@ -61,7 +60,10 @@ export const AnswersContainer = (props: AnswersContainerProps) => {
});
};

const onFilterChange = (key: FilterKey, value: string | string[]) => {
const onFilterChange = (
key: keyof AnswerFilters,
value: string | string[],
) => {
if (filters[key] === value) {
return;
}
Expand Down Expand Up @@ -229,21 +231,9 @@ export const AnswersContainer = (props: AnswersContainerProps) => {
</Grid>
{(showFilters ?? true) && (
<Collapse in={showFilterPanel}>
<FilterPanel
<FilterPanel<AnswerFilters>
onChange={onFilterChange}
filters={filters}
orderByFilters={{
showTrendsOrder: false,
showViewsOrder: false,
showAnswersOrder: false,
showUpdatedOrder: true,
showScoreOrder: true,
}}
quickFilters={{
showNoVotes: true,
showNoCorrectAnswer: false,
showNoAnswers: false,
}}
/>
</Collapse>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { CollectionsGridContent } from './CollectionsGridContent';
import { useQetaApi, useTranslation } from '../../hooks';
import useDebounce from 'react-use/lib/useDebounce';
import { QetaPagination } from '../QetaPagination/QetaPagination';
import { FilterKey, FilterPanel, Filters } from '../FilterPanel/FilterPanel';
import { CollectionFilters, FilterPanel } from '../FilterPanel/FilterPanel';
import FilterList from '@material-ui/icons/FilterList';
import { getFiltersWithDateRange } from '../../utils';

Expand All @@ -29,7 +29,7 @@ export const CollectionsGrid = (props: CollectionsGridProps) => {
const [searchQuery, setSearchQuery] = React.useState('');
const [collectionsPerPage, setCollectionsPerPage] = React.useState(25);
const [showFilterPanel, setShowFilterPanel] = React.useState(false);
const [filters, setFilters] = React.useState<Filters>({
const [filters, setFilters] = React.useState<CollectionFilters>({
order: 'desc',
searchQuery: '',
orderBy: 'created',
Expand Down Expand Up @@ -66,7 +66,10 @@ export const CollectionsGrid = (props: CollectionsGridProps) => {
}
}, [response, collectionsPerPage]);

const onFilterChange = (key: FilterKey, value: string | string[]) => {
const onFilterChange = (
key: keyof CollectionFilters,
value: string | string[],
) => {
if (filters[key] === value) {
return;
}
Expand Down Expand Up @@ -114,17 +117,9 @@ export const CollectionsGrid = (props: CollectionsGridProps) => {
</Grid>
{(showFilters ?? true) && (
<Collapse in={showFilterPanel}>
<FilterPanel
<FilterPanel<CollectionFilters>
onChange={onFilterChange}
filters={filters}
orderByFilters={{
showTitleOrder: true,
}}
quickFilters={{
showNoAnswers: false,
showNoCorrectAnswer: false,
showNoVotes: false,
}}
/>
</Collapse>
)}
Expand Down
116 changes: 64 additions & 52 deletions plugins/qeta-react/src/components/FilterPanel/FilterPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,63 +45,71 @@ export const filterKeys = [
export type FilterKey = (typeof filterKeys)[number];

export type Filters = {
order: string;
orderBy: string;
noAnswers?: string;
noCorrectAnswer?: string;
noVotes?: string;
searchQuery: string;
order?: 'asc' | 'desc';
orderBy?: string;
searchQuery?: string;
entity?: string;
tags?: string[];
dateRange?: string;
};

export type PostFilters = Filters & {
orderBy?:
| 'rank'
| 'created'
| 'title'
| 'views'
| 'score'
| 'trend'
| 'answersCount'
| 'updated';
noAnswers?: 'true' | 'false';
noCorrectAnswer?: 'true' | 'false';
noVotes?: 'true' | 'false';
collectionId?: number;
type?: PostType;
};

export interface FilterPanelProps {
onChange: (key: FilterKey, value: string | string[]) => void;
filters: Filters;
export type AnswerFilters = Filters & {
orderBy?: 'created' | 'score' | 'updated';
noVotes?: 'true' | 'false';
};

export type CollectionFilters = Filters & {
orderBy?: 'created' | 'title';
};

function isPostFilters(filters: Filters): filters is PostFilters {
return (filters as PostFilters).noAnswers !== undefined;
}

function isAnswerFilters(filters: Filters): filters is AnswerFilters {
return (
(filters as AnswerFilters).noVotes !== undefined &&
(filters as PostFilters).noAnswers === undefined
);
}

function isCollectionFilters(filters: Filters): filters is CollectionFilters {
return (filters as PostFilters).noAnswers === undefined;
}

export interface FilterPanelProps<T extends Filters> {
onChange: (key: keyof T, value: string | string[]) => void;
filters: T;
showEntityFilter?: boolean;
showTagFilter?: boolean;
answerFilters?: boolean;
type?: PostType;
orderByFilters?: {
showRankOrder?: boolean;
showViewsOrder?: boolean;
showTrendsOrder?: boolean;
showAnswersOrder?: boolean;
showUpdatedOrder?: boolean;
showScoreOrder?: boolean;
showTitleOrder?: boolean;
};
quickFilters?: {
showNoAnswers?: boolean;
showNoCorrectAnswer?: boolean;
showNoVotes?: boolean;
};
}

export const FilterPanel = (props: FilterPanelProps) => {
export const FilterPanel = <T extends Filters>(props: FilterPanelProps<T>) => {
const {
onChange,
filters,
showEntityFilter = true,
showTagFilter = true,
type,
orderByFilters = {
showRankOrder: false,
showViewsOrder: true,
showTrendsOrder: true,
showAnswersOrder: true,
showUpdatedOrder: true,
showScoreOrder: true,
showTitleOrder: true,
},
quickFilters = {
showNoAnswers: true,
showNoCorrectAnswer: true,
showNoVotes: true,
},
} = props;
const styles = useStyles();
const { value: refs } = useQetaApi(api => api.getEntities(), []);
Expand Down Expand Up @@ -197,9 +205,13 @@ export const FilterPanel = (props: FilterPanelProps) => {
if (event.target.type === 'checkbox') {
value = event.target.checked ? 'true' : 'false';
}
onChange(event.target.name as FilterKey, value);
onChange(event.target.name as keyof T, value);
};

const postFilters = isPostFilters(filters);
const answerFilters = isAnswerFilters(filters);
const collectionFilters = isCollectionFilters(filters);

return (
<Box className={`qetaFilterPanel ${styles.filterPanel}`}>
<Grid
Expand All @@ -208,15 +220,13 @@ export const FilterPanel = (props: FilterPanelProps) => {
alignItems="stretch"
justifyContent="space-evenly"
>
{(quickFilters.showNoVotes ||
quickFilters.showNoAnswers ||
quickFilters.showNoCorrectAnswer) && (
{(postFilters || answerFilters) && (
<Grid item>
<FormGroup>
<FormLabel id="qeta-filter-quick">
{t('filterPanel.quickFilters.label')}
</FormLabel>
{quickFilters.showNoAnswers && type !== 'article' && (
{postFilters && type !== 'article' && (
<FormControlLabel
control={
<Checkbox
Expand All @@ -229,7 +239,7 @@ export const FilterPanel = (props: FilterPanelProps) => {
label={t('filterPanel.noAnswers.label')}
/>
)}
{quickFilters.showNoCorrectAnswer && type !== 'article' && (
{postFilters && type !== 'article' && (
<FormControlLabel
control={
<Checkbox
Expand All @@ -242,7 +252,7 @@ export const FilterPanel = (props: FilterPanelProps) => {
label={t('filterPanel.noCorrectAnswers.label')}
/>
)}
{quickFilters.showNoVotes && (
{(postFilters || answerFilters) && (
<FormControlLabel
control={
<Checkbox
Expand Down Expand Up @@ -274,20 +284,22 @@ export const FilterPanel = (props: FilterPanelProps) => {
gap: '0 1rem',
}}
>
{orderByFilters.showRankOrder &&
{postFilters &&
filters.collectionId !== undefined &&
radioSelect('rank', t('filterPanel.orderBy.rank'))}
{radioSelect('created', t('filterPanel.orderBy.created'))}
{orderByFilters.showTitleOrder &&
{(postFilters || collectionFilters) &&
radioSelect('title', t('filterPanel.orderBy.title'))}
{orderByFilters.showViewsOrder &&
{postFilters &&
radioSelect('views', t('filterPanel.orderBy.views'))}
{orderByFilters.showScoreOrder &&
{(postFilters || answerFilters) &&
radioSelect('score', t('filterPanel.orderBy.score'))}
{orderByFilters.showTrendsOrder &&
{postFilters &&
radioSelect('trend', t('filterPanel.orderBy.trend'))}
{orderByFilters.showAnswersOrder &&
{postFilters &&
type !== 'article' &&
radioSelect('answersCount', t('filterPanel.orderBy.answers'))}
{orderByFilters.showUpdatedOrder &&
{(postFilters || answerFilters) &&
radioSelect('updated', t('filterPanel.orderBy.updated'))}
</RadioGroup>
</FormControl>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
Typography,
} from '@material-ui/core';
import React from 'react';
import { FilterPanel } from '../FilterPanel/FilterPanel';
import { FilterPanel, PostFilters } from '../FilterPanel/FilterPanel';
import { PostList } from './PostList';
import FilterList from '@material-ui/icons/FilterList';
import { AskQuestionButton } from '../Buttons/AskQuestionButton';
Expand Down Expand Up @@ -144,7 +144,7 @@ export const PostsContainer = (props: PaginatedPostsProps) => {
</Grid>
{(showFilters ?? true) && (
<Collapse in={showFilterPanel}>
<FilterPanel
<FilterPanel<PostFilters>
onChange={onFilterChange}
filters={filters}
type={type}
Expand Down
13 changes: 2 additions & 11 deletions plugins/qeta-react/src/components/PostsGrid/PostsGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
Typography,
} from '@material-ui/core';
import FilterList from '@material-ui/icons/FilterList';
import { FilterPanel } from '../FilterPanel/FilterPanel';
import { FilterPanel, PostFilters } from '../FilterPanel/FilterPanel';
import { PostsGridContent } from './PostsGridContent';
import { capitalize } from 'lodash';
import {
Expand Down Expand Up @@ -148,19 +148,10 @@ export const PostsGrid = (props: PostGridProps) => {
</Grid>
{(showFilters ?? true) && (
<Collapse in={showFilterPanel}>
<FilterPanel
<FilterPanel<PostFilters>
onChange={onFilterChange}
filters={filters}
type={type}
orderByFilters={{
showRankOrder: props.collectionId !== undefined,
showTrendsOrder: true,
showAnswersOrder: type === 'question',
showViewsOrder: true,
showTitleOrder: true,
showScoreOrder: true,
showUpdatedOrder: true,
}}
/>
</Collapse>
)}
Expand Down
Loading

0 comments on commit 54f7204

Please sign in to comment.