194 lines
5.9 KiB
TypeScript
194 lines
5.9 KiB
TypeScript
import React from "react";
|
|
import { IResourceComponentsProps, useTranslate, useInvalidate, useNavigation } from "@refinedev/core";
|
|
import { useTable, List } from "@refinedev/antd";
|
|
import { Table, Button, Dropdown } from "antd";
|
|
import dayjs from "dayjs";
|
|
import utc from "dayjs/plugin/utc";
|
|
import { IVendor } from "./model";
|
|
import { TableState, useInitialTableState, useStoreInitialState } from "../../utils/saveload";
|
|
import { EditOutlined, EyeOutlined, FilterOutlined, PlusSquareOutlined } from "@ant-design/icons";
|
|
import { DateColumn, RichColumn, SortedColumn, ActionsColumn, CustomFieldColumn } from "../../components/column";
|
|
import { useLiveify } from "../../components/liveify";
|
|
import { removeUndefined } from "../../utils/filtering";
|
|
import { EntityType, useGetFields } from "../../utils/queryFields";
|
|
import { useNavigate } from "react-router-dom";
|
|
|
|
dayjs.extend(utc);
|
|
|
|
const namespace = "vendorList-v2";
|
|
|
|
const allColumns: (keyof IVendor & string)[] = ["id", "name", "registered", "comment"];
|
|
|
|
export const VendorList: React.FC<IResourceComponentsProps> = () => {
|
|
const t = useTranslate();
|
|
const invalidate = useInvalidate();
|
|
const navigate = useNavigate();
|
|
const extraFields = useGetFields(EntityType.vendor);
|
|
|
|
const allColumnsWithExtraFields = [...allColumns, ...(extraFields.data?.map((field) => "extra." + field.key) ?? [])];
|
|
|
|
// Load initial state
|
|
const initialState = useInitialTableState(namespace);
|
|
|
|
// Fetch data from the API
|
|
const { tableProps, sorters, setSorters, filters, setFilters, current, pageSize, setCurrent } = useTable<IVendor>({
|
|
syncWithLocation: false,
|
|
pagination: {
|
|
mode: "server",
|
|
current: initialState.pagination.current,
|
|
pageSize: initialState.pagination.pageSize,
|
|
},
|
|
sorters: {
|
|
mode: "server",
|
|
initial: initialState.sorters,
|
|
},
|
|
filters: {
|
|
mode: "server",
|
|
initial: initialState.filters,
|
|
},
|
|
liveMode: "manual",
|
|
onLiveEvent(event) {
|
|
if (event.type === "created" || event.type === "deleted") {
|
|
// updated is handled by the liveify
|
|
invalidate({
|
|
resource: "vendor",
|
|
invalidates: ["list"],
|
|
});
|
|
}
|
|
},
|
|
});
|
|
|
|
// Create state for the columns to show
|
|
const [showColumns, setShowColumns] = React.useState<string[]>(initialState.showColumns ?? allColumns);
|
|
|
|
// Store state in local storage
|
|
const tableState: TableState = {
|
|
sorters,
|
|
filters,
|
|
pagination: { current, pageSize },
|
|
showColumns,
|
|
};
|
|
useStoreInitialState(namespace, tableState);
|
|
|
|
// Collapse the dataSource to a mutable list
|
|
const queryDataSource: IVendor[] = React.useMemo(
|
|
() => (tableProps.dataSource || []).map((record) => ({ ...record })),
|
|
[tableProps.dataSource]
|
|
);
|
|
const dataSource = useLiveify("vendor", queryDataSource, (record: IVendor) => record);
|
|
|
|
if (tableProps.pagination) {
|
|
tableProps.pagination.showSizeChanger = true;
|
|
}
|
|
|
|
const { editUrl, showUrl, cloneUrl } = useNavigation();
|
|
const actions = (record: IVendor) => [
|
|
{ name: t("buttons.show"), icon: <EyeOutlined />, link: showUrl("vendor", record.id) },
|
|
{ name: t("buttons.edit"), icon: <EditOutlined />, link: editUrl("vendor", record.id) },
|
|
{ name: t("buttons.clone"), icon: <PlusSquareOutlined />, link: cloneUrl("vendor", record.id) },
|
|
];
|
|
|
|
const commonProps = {
|
|
t,
|
|
navigate,
|
|
actions,
|
|
dataSource,
|
|
tableState,
|
|
sorter: true,
|
|
};
|
|
|
|
return (
|
|
<List
|
|
headerButtons={({ defaultButtons }) => (
|
|
<>
|
|
<Button
|
|
type="primary"
|
|
icon={<FilterOutlined />}
|
|
onClick={() => {
|
|
setFilters([], "replace");
|
|
setSorters([{ field: "id", order: "asc" }]);
|
|
setCurrent(1);
|
|
}}
|
|
>
|
|
{t("buttons.clearFilters")}
|
|
</Button>
|
|
<Dropdown
|
|
trigger={["click"]}
|
|
menu={{
|
|
items: allColumnsWithExtraFields.map((column_id) => {
|
|
if (column_id.indexOf("extra.") === 0) {
|
|
const extraField = extraFields.data?.find((field) => "extra." + field.key === column_id);
|
|
return {
|
|
key: column_id,
|
|
label: extraField?.name ?? column_id,
|
|
};
|
|
}
|
|
|
|
return {
|
|
key: column_id,
|
|
label: t(`vendor.fields.${column_id}`),
|
|
};
|
|
}),
|
|
selectedKeys: showColumns,
|
|
selectable: true,
|
|
multiple: true,
|
|
onDeselect: (keys) => {
|
|
setShowColumns(keys.selectedKeys);
|
|
},
|
|
onSelect: (keys) => {
|
|
setShowColumns(keys.selectedKeys);
|
|
},
|
|
}}
|
|
>
|
|
<Button type="primary" icon={<EditOutlined />}>
|
|
{t("buttons.hideColumns")}
|
|
</Button>
|
|
</Dropdown>
|
|
{defaultButtons}
|
|
</>
|
|
)}
|
|
>
|
|
<Table
|
|
{...tableProps}
|
|
sticky
|
|
tableLayout="auto"
|
|
scroll={{ x: "max-content" }}
|
|
dataSource={dataSource}
|
|
rowKey="id"
|
|
columns={removeUndefined([
|
|
SortedColumn({
|
|
...commonProps,
|
|
id: "id",
|
|
i18ncat: "vendor",
|
|
width: 70,
|
|
}),
|
|
SortedColumn({
|
|
...commonProps,
|
|
id: "name",
|
|
i18ncat: "vendor",
|
|
}),
|
|
DateColumn({
|
|
...commonProps,
|
|
id: "registered",
|
|
i18ncat: "vendor",
|
|
}),
|
|
...(extraFields.data?.map((field) => {
|
|
return CustomFieldColumn({
|
|
...commonProps,
|
|
field,
|
|
});
|
|
}) ?? []),
|
|
RichColumn({
|
|
...commonProps,
|
|
id: "comment",
|
|
i18ncat: "vendor",
|
|
}),
|
|
ActionsColumn<IVendor>(actions),
|
|
])}
|
|
/>
|
|
</List>
|
|
);
|
|
};
|
|
|
|
export default VendorList;
|