import React from "react"; import { IResourceComponentsProps, BaseRecord, useTranslate, useInvalidate } from "@refinedev/core"; import { useTable, List, EditButton, ShowButton, CloneButton } from "@refinedev/antd"; import { Table, Space, Button, Dropdown } from "antd"; import dayjs from "dayjs"; import utc from "dayjs/plugin/utc"; import { IFilament } from "./model"; import { EditOutlined, FilterOutlined, ShareAltOutlined } from "@ant-design/icons"; import { TableState, shareSavedState, useInitialTableState, useStoreInitialState } from "../../utils/saveload"; import { DateColumn, FilteredQueryColumn, NumberColumn, RichColumn, SortedColumn, SpoolIconColumn, } from "../../components/column"; import { useSpoolmanArticleNumbers, useSpoolmanFilamentNames, useSpoolmanMaterials, useSpoolmanVendors, } from "../../components/otherModels"; import { useLiveify } from "../../components/liveify"; dayjs.extend(utc); interface IFilamentCollapsed extends Omit { "vendor.name": string | null; } function collapseFilament(element: IFilament): IFilamentCollapsed { let vendor_name: string | null; if (element.vendor) { vendor_name = element.vendor.name; } else { vendor_name = null; } return { ...element, "vendor.name": vendor_name }; } function translateColumnI18nKey(columnName: string): string { columnName = columnName.replace(".", "_"); return `filament.fields.${columnName}`; } const namespace = "filamentList-v2"; export const FilamentList: React.FC = () => { const t = useTranslate(); const invalidate = useInvalidate(); // Load initial state const initialState = useInitialTableState(namespace); // Fetch data from the API // To provide the live updates, we use a custom solution (useLiveify) instead of the built-in refine "liveMode" feature. // This is because the built-in feature does not call the liveProvider subscriber with a list of IDs, but instead // calls it with a list of filters, sorters, etc. This means the server-side has to support this, which is quite hard. const { tableProps, sorters, setSorters, filters, setFilters, current, pageSize, setCurrent } = useTable({ 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: "filament", invalidates: ["list"], }); } }, }); // Create state for the columns to show const allColumns: (keyof IFilamentCollapsed & string)[] = [ "id", "vendor.name", "name", "material", "price", "density", "diameter", "weight", "spool_weight", "article_number", "settings_extruder_temp", "settings_bed_temp", "registered", "comment", ]; const defaultColumns = allColumns.filter( (column_id) => ["registered", "density", "diameter", "spool_weight"].indexOf(column_id) === -1 ); const [showColumns, setShowColumns] = React.useState(initialState.showColumns ?? defaultColumns); // Store state in local storage const tableState: TableState = { sorters, filters, pagination: { current, pageSize }, showColumns, }; useStoreInitialState(namespace, tableState); // Collapse the dataSource to a mutable list and add a filament_name field const queryDataSource: IFilamentCollapsed[] = React.useMemo( () => (tableProps.dataSource ?? []).map(collapseFilament), [tableProps.dataSource] ); const dataSource = useLiveify("filament", queryDataSource, collapseFilament); if (tableProps.pagination) { tableProps.pagination.showSizeChanger = true; } return ( ( <> ({ key: column_id, label: t(translateColumnI18nKey(column_id)), })), selectedKeys: showColumns, selectable: true, multiple: true, onDeselect: (keys) => { setShowColumns(keys.selectedKeys); }, onSelect: (keys) => { setShowColumns(keys.selectedKeys); }, }} > {defaultButtons} )} > {SortedColumn({ id: "id", i18ncat: "filament", dataSource, tableState, })} {FilteredQueryColumn({ id: "vendor.name", i18nkey: "filament.fields.vendor_name", dataSource, tableState, filterValueQuery: useSpoolmanVendors(), })} {SpoolIconColumn({ id: "name", i18ncat: "filament", color: (record: IFilamentCollapsed) => record.color_hex, dataSource, tableState, filterValueQuery: useSpoolmanFilamentNames(), })} {FilteredQueryColumn({ id: "material", i18ncat: "filament", dataSource, tableState, filterValueQuery: useSpoolmanMaterials(), })} {SortedColumn({ id: "price", i18ncat: "filament", dataSource, tableState, })} {NumberColumn({ id: "density", i18ncat: "filament", unit: "g/cm³", decimals: 2, dataSource, tableState, })} {NumberColumn({ id: "diameter", i18ncat: "filament", unit: "mm", decimals: 2, dataSource, tableState, })} {NumberColumn({ id: "weight", i18ncat: "filament", unit: "g", decimals: 1, dataSource, tableState, })} {NumberColumn({ id: "spool_weight", i18ncat: "filament", unit: "g", decimals: 1, dataSource, tableState, })} {FilteredQueryColumn({ id: "article_number", i18ncat: "filament", dataSource, tableState, filterValueQuery: useSpoolmanArticleNumbers(), })} {NumberColumn({ id: "settings_extruder_temp", i18ncat: "filament", unit: "°C", decimals: 0, dataSource, tableState, })} {NumberColumn({ id: "settings_bed_temp", i18ncat: "filament", unit: "°C", decimals: 0, dataSource, tableState, })} {DateColumn({ id: "registered", i18ncat: "filament", dataSource, tableState, })} {RichColumn({ id: "comment", i18ncat: "filament", dataSource, tableState, })} ( )} />
); }; export default FilamentList;