Skip to content

Commit

Permalink
Add "All" or "All/None" option to dropdown filters. (#52)
Browse files Browse the repository at this point in the history
* Add all/none filter option to "Column types" / "Show columns" filters

* Refactor and display other content types when no selected option

* Fix all content types selection

* Apply changes

* Fix content type base filter

* Refactor items filtering

* Fix filterItems dependencies

* Make first content type bases filters item always "All"

* Fix filterItems deps for text searching
  • Loading branch information
Fifok authored Aug 22, 2023
1 parent c9f2cdf commit 91645e8
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ function ColumnsFilter<TableDataType>({
return translations.filters.mixed;
}, [columns, translations]);

const isAllSelected = columns.every((c) => c.visible);

return (
<Dropdown
arrowIcon="down"
Expand All @@ -35,6 +37,23 @@ function ColumnsFilter<TableDataType>({
shouldHideChildrenOnClick={false}
>
<Dropdown.Contents>
<Dropdown.ListItem key="All">
<Dropdown.BlockLink
isItemSelected={isAllSelected}
isMultiSelect={true}
onClick={
onChange
? () => {
columns.forEach((c) => {
onChange(c.id, !isAllSelected);
});
}
: undefined
}
>
<Dropdown.BlockLinkText text={translations.filters.all} />
</Dropdown.BlockLink>
</Dropdown.ListItem>
{columns.map(({ id, name, visible }) => (
<Dropdown.ListItem key={name}>
<Dropdown.BlockLink
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useTranslations } from "../../Contexts/TranslationsProvider";

interface ContentTypeBasesFilterProps {
contentTypeBases: ContentTypeBase[];
onChange?: (contentTypeBase: ContentTypeBase) => void;
onChange?: (contentTypeBase: ContentTypeBase, selectAll?: boolean) => void;
}

function ContentTypeBasesFilter({
Expand All @@ -28,6 +28,8 @@ function ContentTypeBasesFilter({
return translations.filters.none;
}, [contentTypeBases, translations]);

const isAllSelected = contentTypeBases.every((c) => c.visible);

return (
<Dropdown
arrowIcon="down"
Expand All @@ -39,6 +41,23 @@ function ContentTypeBasesFilter({
shouldHideChildrenOnClick={false}
>
<Dropdown.Contents>
<Dropdown.ListItem key="All/None">
<Dropdown.BlockLink
isItemSelected={isAllSelected}
isMultiSelect={true}
onClick={
onChange
? () => {
contentTypeBases.forEach((c) => {
onChange(c, !isAllSelected);
});
}
: undefined
}
>
<Dropdown.BlockLinkText text={translations.filters.all} />
</Dropdown.BlockLink>
</Dropdown.ListItem>
{contentTypeBases.map((contentTypeBase) => (
<Dropdown.ListItem key={contentTypeBase.name}>
<Dropdown.BlockLink
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ interface FilteredTableDataHookOptions<TableDataType> {
disableFrontendFiltering?: boolean;
disableFrontendPagination?: boolean;
disableFrontendSorting?: boolean;
defaultVisiableColumn: keyof TableDataType;
}

export function useFilteredTableData<TableDataType>({
Expand All @@ -43,6 +44,7 @@ export function useFilteredTableData<TableDataType>({
disableFrontendFiltering = false,
disableFrontendPagination = false,
disableFrontendSorting = false,
defaultVisiableColumn,
}: FilteredTableDataHookOptions<TableDataType>): {
rows: TableDataType[];
searchValue: string;
Expand Down Expand Up @@ -269,6 +271,14 @@ export function useFilteredTableData<TableDataType>({
(id: string, visible: boolean) => {
if (tableColumns.filter((column) => column.visible).length > 1 || visible)
changeColumnVisibility(id, visible);
else {
const displayNameColumn = tableColumns.find(
(c) => c.id === defaultVisiableColumn
);

changeColumnVisibility(id, visible);
changeColumnVisibility(displayNameColumn.id as string, true);
}
},
[tableColumns, changeColumnVisibility]
);
Expand Down Expand Up @@ -322,75 +332,89 @@ export function useFilteredTableData<TableDataType>({
);

const onContentTypeBaseChange = useCallback(
({ name, visible }: ContentTypeBase) => {
if (
contentTypeBases.filter((contentTypeBase) => contentTypeBase.visible)
.length > 1 ||
!visible
) {
const newContentTypeBases = contentTypeBases.slice(0);
({ name, visible }: ContentTypeBase, valueForAll?: boolean) => {
const newContentTypeBases = contentTypeBases.slice(0);

if (valueForAll) {
newContentTypeBases.forEach((v) => (v.visible = valueForAll));
} else {
const contentTypeBaseIndex = newContentTypeBases.findIndex(
(contentTypeBase) => contentTypeBase.name === name
);

newContentTypeBases[contentTypeBaseIndex].visible = !visible;
setPageToStart();
triggerUpdate.current = false;
setContentTypeBases(newContentTypeBases);
setChangesTracker({
...changesTracker,
contentTypeBases: true,
currentPage: true,
});
}

setPageToStart();
setContentTypeBases(newContentTypeBases);
},
[contentTypeBases, handlePageChange]
);

const filteredItems = useMemo(() => {
return rows
.filter((row) => {
if (disableFrontendFiltering) return true;
const filterItems = useCallback((rows: TableDataType[]) => {
if (disableFrontendFiltering) return rows;

if (
contentTypeBases &&
contentTypeBaseColumnId &&
row[contentTypeBaseColumnId as keyof TableDataType]
) {
const type = row[
contentTypeBaseColumnId as keyof TableDataType
] as unknown;
const contentTypeBase = contentTypeBases
.filter((contentTypeBase) => contentTypeBase.visible)
.find((contentTypeBase) => contentTypeBase.name === type);

if (!contentTypeBase) return false;
}
if (filterFn) {
return rows.filter((row) => {
return filterFn(row, searchQuery);
});
}

const parsedSearchValue = searchQuery.toLocaleLowerCase().trim();
if (!parsedSearchValue) return true;
return rows.filter((row) => {
if (contentTypeBases && contentTypeBaseColumnId) {
const allSelected = contentTypeBases.every(
(contentTypeBase) => contentTypeBase.visible
);

if (filterFn) return filterFn(row, searchQuery);
if (allSelected) {
return true;
}
const type = row[
contentTypeBaseColumnId as keyof TableDataType
] as unknown;

for (const column in row) {
const tableColumn = tableColumns.find(({ id }) => id === column);
const allDeselected = contentTypeBases.every(
(contentTypeBase) => !contentTypeBase.visible
);

if (tableColumn && tableColumn.filter && tableColumn.visible) {
const value = row[column];
if (allDeselected) {
if (type && contentTypeBases.some((t) => t.name === type))
return false;
return true;
}

if (
value &&
value
.toString()
.toLocaleLowerCase()
.includes(parsedSearchValue.toLocaleLowerCase())
)
return true;
}
const contentTypeBase = contentTypeBases
.filter((contentTypeBase) => contentTypeBase.visible)
.find((contentTypeBase) => contentTypeBase.name === type);

if (!contentTypeBase) return false;
}
return true;
})
.filter((row) => {
for (const column in row) {
const parsedSearchValue = searchQuery.toLocaleLowerCase().trim();
const tableColumn = tableColumns.find(({ id }) => id === column);

if (tableColumn && tableColumn.filter && tableColumn.visible) {
const value = row[column];

if (
value &&
value
.toString()
.toLocaleLowerCase()
.includes(parsedSearchValue.toLocaleLowerCase())
)
return true;
}
}

return false;
})
}, [disableFrontendFiltering, contentTypeBases, filterFn, searchQuery, tableColumns])

return false;
})
const filteredItems = useMemo(() => {
return filterItems(rows)
.sort((prevValue, nextValue) => {
if (disableFrontendSorting) return 0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ const ContentTypeUsageView = () => {
disableFrontendFiltering: true,
disableFrontendPagination: true,
disableFrontendSorting: true,
defaultVisiableColumn: "name"
});

const [totalPages, setTotalPages] = useState<number>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ const ContentTypesView = () => {
rows: contentTypes,
initialTableColumns,
initialContentTypeBases,
defaultVisiableColumn: "displayName"
});

const handlePageChange = useCallback(
Expand Down

0 comments on commit 91645e8

Please sign in to comment.