mirror of
https://github.com/collinbarrett/FilterLists.git
synced 2026-03-11 09:04:27 +00:00
show count of lists matching each filter option
closes #556, closes #551
This commit is contained in:
parent
90c835fd4d
commit
6caeae5d91
1 changed files with 134 additions and 122 deletions
|
|
@ -1,5 +1,6 @@
|
|||
import { Table, Tag } from 'antd';
|
||||
import React from 'react';
|
||||
import { PaginationConfig, SorterResult, TableCurrentDataSource } from 'antd/lib/table';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { RouteComponentProps } from 'react-router';
|
||||
|
||||
import { useSearchColumnFilter, useTablePageSizer } from '../../hooks';
|
||||
|
|
@ -18,128 +19,139 @@ import { arraySorter } from './arraySorter';
|
|||
import styles from './ListsTable.module.css';
|
||||
|
||||
interface Props {
|
||||
lists: List[];
|
||||
languages: Language[];
|
||||
licenses: License[];
|
||||
software: Software[];
|
||||
tags: TagInterface[];
|
||||
lists: List[];
|
||||
languages: Language[];
|
||||
licenses: License[];
|
||||
software: Software[];
|
||||
tags: TagInterface[];
|
||||
};
|
||||
|
||||
export const ListsTable = (props: RouteComponentProps & Props) => {
|
||||
const { lists, languages, licenses, software, tags, ...routeComponentProps } = props;
|
||||
const tablePageSize = useTablePageSizer();
|
||||
const searchNameColumn = useSearchColumnFilter<List>(nameof<List>("name"));
|
||||
const searchDescriptionColumn = useSearchColumnFilter<List>(nameof<List>("description"));
|
||||
return (
|
||||
<Table<List>
|
||||
dataSource={lists}
|
||||
rowKey={record => record.id.toString()}
|
||||
loading={lists.length ? false : true}
|
||||
size="small"
|
||||
pagination={{
|
||||
size: "small",
|
||||
simple: true,
|
||||
style: { float: "left" },
|
||||
pageSize: tablePageSize.pageSize
|
||||
}}
|
||||
scroll={{ x: tablePageSize.isNarrowWindow ? undefined : 1200 }}>
|
||||
<Table.Column<List>
|
||||
title="Info"
|
||||
dataIndex={nameof<List>("id")}
|
||||
className={styles.nogrow}
|
||||
fixed="left"
|
||||
render={(_id: number, list: List) =>
|
||||
<ListInfoButton listName={list.name} {...routeComponentProps} />} />
|
||||
<Table.Column<List>
|
||||
title="Name"
|
||||
dataIndex={nameof<List>("name")}
|
||||
sorter={(a, b) => a.name.localeCompare(b.name)}
|
||||
defaultSortOrder={"ascend"}
|
||||
width={tablePageSize.isNarrowWindow ? undefined : 200}
|
||||
className={styles.nogrow}
|
||||
fixed="left"
|
||||
filterDropdown={searchNameColumn.filterDropdown}
|
||||
filterIcon={searchNameColumn.filterIcon}
|
||||
onFilter={searchNameColumn.onFilter}
|
||||
render={(name: string) =>
|
||||
<div>{name}</div>} />
|
||||
{tablePageSize.isNarrowWindow
|
||||
? null
|
||||
: <Table.Column<List>
|
||||
title="Description"
|
||||
dataIndex={nameof<List>("description")}
|
||||
className={styles.nogrow}
|
||||
filterDropdown={searchDescriptionColumn.filterDropdown}
|
||||
filterIcon={searchDescriptionColumn.filterIcon}
|
||||
onFilter={searchDescriptionColumn.onFilter}
|
||||
render={(description: string, list: List) =>
|
||||
<Description
|
||||
description={description}
|
||||
descriptionSourceUrl={list.descriptionSourceUrl} />} />}
|
||||
{tablePageSize.isNarrowWindow
|
||||
? null
|
||||
: <Table.Column<List>
|
||||
title="Software"
|
||||
dataIndex={nameof<List>("syntaxId")}
|
||||
sorter={(a, b) => {
|
||||
const getSoftwareIds = (l: List) => software.filter((s: Software) => s.syntaxIds.includes(l.syntaxId)).map(s => s.id);
|
||||
return arraySorter(getSoftwareIds(a), getSoftwareIds(b), software);
|
||||
}}
|
||||
width={143}
|
||||
className={styles.nogrow}
|
||||
filters={software.map(s => ({
|
||||
text: <>
|
||||
<SoftwareIcon id={s.id} />
|
||||
{s.name}
|
||||
</>,
|
||||
value: s.name
|
||||
}))}
|
||||
onFilter={(value, record) => software.filter((s: Software) => s.name === value).flatMap(s => s.syntaxIds).includes(record.syntaxId)}
|
||||
render={(syntaxId: number) =>
|
||||
syntaxId
|
||||
? <SoftwareCloud software={software.filter((s: Software) => s.syntaxIds.includes(syntaxId))} />
|
||||
: null} />}
|
||||
{tablePageSize.isNarrowWindow
|
||||
? null
|
||||
: <Table.Column<List>
|
||||
title="Languages"
|
||||
dataIndex={nameof<List>("languageIds")}
|
||||
sorter={(a, b) => arraySorter(a.languageIds, b.languageIds, languages)}
|
||||
width={125}
|
||||
className={styles.nogrow}
|
||||
filters={languages.map(l => ({
|
||||
text: <>
|
||||
<Tag title={l.name}>{l.iso6391}</Tag>
|
||||
{l.name}
|
||||
</>,
|
||||
value: l.id.toString()
|
||||
}))}
|
||||
onFilter={(value, record) => record.languageIds
|
||||
? record.languageIds.includes(+value)
|
||||
: false}
|
||||
render={(languageIds: number[]) =>
|
||||
languageIds
|
||||
? <LanguageCloud languages={languages.filter((l: Language) => languageIds.includes(l.id))} />
|
||||
: null} />}
|
||||
{tablePageSize.isNarrowWindow
|
||||
? null
|
||||
: <Table.Column<List>
|
||||
title="Tags"
|
||||
dataIndex={nameof<List>("tagIds")}
|
||||
sorter={(a, b) => arraySorter(a.tagIds, b.tagIds, tags)}
|
||||
width={275}
|
||||
className={styles.nogrow}
|
||||
filters={tags.map(t => ({
|
||||
text: <Tag title={t.description}>{t.name}</Tag>,
|
||||
value: t.id.toString()
|
||||
}))}
|
||||
onFilter={(value, record) => record.tagIds
|
||||
? record.tagIds.includes(+value)
|
||||
: false}
|
||||
render={(tagIds: number[]) =>
|
||||
tagIds
|
||||
? <TagCloud tags={tags.filter((t: TagInterface) => tagIds.includes(t.id))} />
|
||||
: null} />}
|
||||
</Table>
|
||||
);
|
||||
const { lists, languages, licenses, software, tags, ...routeComponentProps } = props;
|
||||
const tablePageSize = useTablePageSizer();
|
||||
const searchNameColumn = useSearchColumnFilter<List>(nameof<List>("name"));
|
||||
const searchDescriptionColumn = useSearchColumnFilter<List>(nameof<List>("description"));
|
||||
const [visibleLists, setVisibleLists] = useState<List[]>(lists);
|
||||
useEffect(() => {
|
||||
setVisibleLists(lists);
|
||||
}, [lists]);
|
||||
return (
|
||||
<Table<List>
|
||||
dataSource={lists}
|
||||
rowKey={record => record.id.toString()}
|
||||
loading={lists.length ? false : true}
|
||||
size="small"
|
||||
pagination={{
|
||||
size: "small",
|
||||
simple: true,
|
||||
style: { float: "left" },
|
||||
pageSize: tablePageSize.pageSize
|
||||
}}
|
||||
scroll={{ x: tablePageSize.isNarrowWindow ? undefined : 1200 }}
|
||||
onChange={(_pagination: PaginationConfig, _filters: Record<keyof List, string[]>, _sorter: SorterResult<List>, extra: TableCurrentDataSource<List>) =>
|
||||
setVisibleLists(extra.currentDataSource)}>
|
||||
<Table.Column<List>
|
||||
title="Info"
|
||||
dataIndex={nameof<List>("id")}
|
||||
className={styles.nogrow}
|
||||
fixed="left"
|
||||
render={(_id: number, list: List) =>
|
||||
<ListInfoButton listName={list.name} {...routeComponentProps} />} />
|
||||
<Table.Column<List>
|
||||
title="Name"
|
||||
dataIndex={nameof<List>("name")}
|
||||
sorter={(a, b) => a.name.localeCompare(b.name)}
|
||||
defaultSortOrder={"ascend"}
|
||||
width={tablePageSize.isNarrowWindow ? undefined : 200}
|
||||
className={styles.nogrow}
|
||||
fixed="left"
|
||||
filterDropdown={searchNameColumn.filterDropdown}
|
||||
filterIcon={searchNameColumn.filterIcon}
|
||||
onFilter={searchNameColumn.onFilter}
|
||||
render={(name: string) =>
|
||||
<div>{name}</div>} />
|
||||
{tablePageSize.isNarrowWindow
|
||||
? null
|
||||
: <Table.Column<List>
|
||||
title="Description"
|
||||
dataIndex={nameof<List>("description")}
|
||||
className={styles.nogrow}
|
||||
filterDropdown={searchDescriptionColumn.filterDropdown}
|
||||
filterIcon={searchDescriptionColumn.filterIcon}
|
||||
onFilter={searchDescriptionColumn.onFilter}
|
||||
render={(description: string, list: List) =>
|
||||
<Description
|
||||
description={description}
|
||||
descriptionSourceUrl={list.descriptionSourceUrl} />} />}
|
||||
{tablePageSize.isNarrowWindow
|
||||
? null
|
||||
: <Table.Column<List>
|
||||
title="Software"
|
||||
dataIndex={nameof<List>("syntaxId")}
|
||||
sorter={(a, b) => {
|
||||
const getSoftwareIds = (l: List) => software.filter((s: Software) => s.syntaxIds.includes(l.syntaxId)).map(s => s.id);
|
||||
return arraySorter(getSoftwareIds(a), getSoftwareIds(b), software);
|
||||
}}
|
||||
width={143}
|
||||
className={styles.nogrow}
|
||||
filters={software.map(s => ({
|
||||
text: <>
|
||||
<SoftwareIcon id={s.id} />
|
||||
{s.name}
|
||||
({visibleLists.filter(l => s.syntaxIds && s.syntaxIds.includes(l.syntaxId)).length})
|
||||
</>,
|
||||
value: s.name
|
||||
}))}
|
||||
onFilter={(value, record) => software.filter((s: Software) => s.name === value).flatMap(s => s.syntaxIds).includes(record.syntaxId)}
|
||||
render={(syntaxId: number) =>
|
||||
syntaxId
|
||||
? <SoftwareCloud software={software.filter((s: Software) => s.syntaxIds.includes(syntaxId))} />
|
||||
: null} />}
|
||||
{tablePageSize.isNarrowWindow
|
||||
? null
|
||||
: <Table.Column<List>
|
||||
title="Languages"
|
||||
dataIndex={nameof<List>("languageIds")}
|
||||
sorter={(a, b) => arraySorter(a.languageIds, b.languageIds, languages)}
|
||||
width={125}
|
||||
className={styles.nogrow}
|
||||
filters={languages.map(l => ({
|
||||
text: <>
|
||||
<Tag title={l.name}>{l.iso6391}</Tag>
|
||||
{l.name}
|
||||
({visibleLists.filter(li => li.languageIds && li.languageIds.includes(l.id)).length})
|
||||
</>,
|
||||
value: l.id.toString()
|
||||
}))}
|
||||
onFilter={(value, record) => record.languageIds
|
||||
? record.languageIds.includes(+value)
|
||||
: false}
|
||||
render={(languageIds: number[]) =>
|
||||
languageIds
|
||||
? <LanguageCloud languages={languages.filter((l: Language) => languageIds.includes(l.id))} />
|
||||
: null} />}
|
||||
{tablePageSize.isNarrowWindow
|
||||
? null
|
||||
: <Table.Column<List>
|
||||
title="Tags"
|
||||
dataIndex={nameof<List>("tagIds")}
|
||||
sorter={(a, b) => arraySorter(a.tagIds, b.tagIds, tags)}
|
||||
width={275}
|
||||
className={styles.nogrow}
|
||||
filters={tags.map(t => ({
|
||||
text: <>
|
||||
<Tag title={t.description}>{t.name}</Tag>
|
||||
({visibleLists.filter(l => l.tagIds && l.tagIds.includes(t.id)).length})
|
||||
</>,
|
||||
value: t.id.toString()
|
||||
}))}
|
||||
onFilter={(value, record) => record.tagIds
|
||||
? record.tagIds.includes(+value)
|
||||
: false}
|
||||
render={(tagIds: number[]) =>
|
||||
tagIds
|
||||
? <TagCloud tags={tags.filter((t: TagInterface) => tagIds.includes(t.id))} />
|
||||
: null} />}
|
||||
</Table>
|
||||
);
|
||||
};
|
||||
Loading…
Reference in a new issue