mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-11-04 07:05:41 +00:00 
			
		
		
		
	Refactor table columns (#5519)
- Improve show/hide - Refactor "actions" colum
This commit is contained in:
		@@ -15,6 +15,7 @@ import { DownloadAction } from './DownloadAction';
 | 
				
			|||||||
import { TableFilter } from './Filter';
 | 
					import { TableFilter } from './Filter';
 | 
				
			||||||
import { FilterGroup } from './FilterGroup';
 | 
					import { FilterGroup } from './FilterGroup';
 | 
				
			||||||
import { FilterSelectModal } from './FilterSelectModal';
 | 
					import { FilterSelectModal } from './FilterSelectModal';
 | 
				
			||||||
 | 
					import { RowAction, RowActions } from './RowActions';
 | 
				
			||||||
import { TableSearchInput } from './Search';
 | 
					import { TableSearchInput } from './Search';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -96,7 +97,8 @@ export function InvenTreeTable({
 | 
				
			|||||||
  printingActions = [],
 | 
					  printingActions = [],
 | 
				
			||||||
  barcodeActions = [],
 | 
					  barcodeActions = [],
 | 
				
			||||||
  customActionGroups = [],
 | 
					  customActionGroups = [],
 | 
				
			||||||
  customFilters = []
 | 
					  customFilters = [],
 | 
				
			||||||
 | 
					  rowActions
 | 
				
			||||||
}: {
 | 
					}: {
 | 
				
			||||||
  url: string;
 | 
					  url: string;
 | 
				
			||||||
  params: any;
 | 
					  params: any;
 | 
				
			||||||
@@ -115,12 +117,15 @@ export function InvenTreeTable({
 | 
				
			|||||||
  barcodeActions?: any[];
 | 
					  barcodeActions?: any[];
 | 
				
			||||||
  customActionGroups?: any[];
 | 
					  customActionGroups?: any[];
 | 
				
			||||||
  customFilters?: TableFilter[];
 | 
					  customFilters?: TableFilter[];
 | 
				
			||||||
 | 
					  rowActions?: (record: any) => RowAction[];
 | 
				
			||||||
}) {
 | 
					}) {
 | 
				
			||||||
  // Data columns
 | 
					  // Data columns
 | 
				
			||||||
  const [dataColumns, setDataColumns] = useState<any[]>(columns);
 | 
					  const [dataColumns, setDataColumns] = useState<any[]>(columns);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Check if any columns are switchable (can be hidden)
 | 
					  // Check if any columns are switchable (can be hidden)
 | 
				
			||||||
  const hasSwitchableColumns = columns.some((col: any) => col.switchable);
 | 
					  const hasSwitchableColumns = columns.some(
 | 
				
			||||||
 | 
					    (col: TableColumn) => col.switchable
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Manage state for switchable columns (initially load from local storage)
 | 
					  // Manage state for switchable columns (initially load from local storage)
 | 
				
			||||||
  let [hiddenColumns, setHiddenColumns] = useState(() =>
 | 
					  let [hiddenColumns, setHiddenColumns] = useState(() =>
 | 
				
			||||||
@@ -129,15 +134,34 @@ export function InvenTreeTable({
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // Update column visibility when hiddenColumns change
 | 
					  // Update column visibility when hiddenColumns change
 | 
				
			||||||
  useEffect(() => {
 | 
					  useEffect(() => {
 | 
				
			||||||
    setDataColumns(
 | 
					    let cols = dataColumns.map((col) => {
 | 
				
			||||||
      dataColumns.map((col) => {
 | 
					      let hidden: boolean = col.hidden;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (col.switchable) {
 | 
				
			||||||
 | 
					        hidden = hiddenColumns.includes(col.accessor);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return {
 | 
					      return {
 | 
				
			||||||
        ...col,
 | 
					        ...col,
 | 
				
			||||||
          hidden: hiddenColumns.includes(col.accessor)
 | 
					        hidden: hidden
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
      })
 | 
					    });
 | 
				
			||||||
    );
 | 
					
 | 
				
			||||||
  }, [hiddenColumns]);
 | 
					    // If row actions are available, add a column for them
 | 
				
			||||||
 | 
					    if (rowActions) {
 | 
				
			||||||
 | 
					      cols.push({
 | 
				
			||||||
 | 
					        accessor: 'actions',
 | 
				
			||||||
 | 
					        title: '',
 | 
				
			||||||
 | 
					        hidden: false,
 | 
				
			||||||
 | 
					        switchable: false,
 | 
				
			||||||
 | 
					        render: function (record: any) {
 | 
				
			||||||
 | 
					          return <RowActions actions={rowActions(record)} />;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setDataColumns(cols);
 | 
				
			||||||
 | 
					  }, [columns, hiddenColumns, rowActions]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Callback when column visibility is toggled
 | 
					  // Callback when column visibility is toggled
 | 
				
			||||||
  function toggleColumn(columnName: string) {
 | 
					  function toggleColumn(columnName: string) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,6 +24,7 @@ export function RowActions({
 | 
				
			|||||||
  actions: RowAction[];
 | 
					  actions: RowAction[];
 | 
				
			||||||
}): ReactNode {
 | 
					}): ReactNode {
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
 | 
					    actions.length > 0 && (
 | 
				
			||||||
      <Menu>
 | 
					      <Menu>
 | 
				
			||||||
        <Menu.Target>
 | 
					        <Menu.Target>
 | 
				
			||||||
          <ActionIcon variant="subtle" color="gray">
 | 
					          <ActionIcon variant="subtle" color="gray">
 | 
				
			||||||
@@ -44,5 +45,6 @@ export function RowActions({
 | 
				
			|||||||
          ))}
 | 
					          ))}
 | 
				
			||||||
        </Menu.Dropdown>
 | 
					        </Menu.Dropdown>
 | 
				
			||||||
      </Menu>
 | 
					      </Menu>
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,7 +10,7 @@ import { ThumbnailHoverCard } from '../../items/Thumbnail';
 | 
				
			|||||||
import { TableColumn } from '../Column';
 | 
					import { TableColumn } from '../Column';
 | 
				
			||||||
import { TableFilter } from '../Filter';
 | 
					import { TableFilter } from '../Filter';
 | 
				
			||||||
import { InvenTreeTable } from '../InvenTreeTable';
 | 
					import { InvenTreeTable } from '../InvenTreeTable';
 | 
				
			||||||
import { RowActions } from '../RowActions';
 | 
					import { RowAction } from '../RowActions';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Construct a list of columns for the part table
 | 
					 * Construct a list of columns for the part table
 | 
				
			||||||
@@ -82,38 +82,6 @@ function partTableColumns(): TableColumn[] {
 | 
				
			|||||||
      accessor: 'link',
 | 
					      accessor: 'link',
 | 
				
			||||||
      title: t`Link`,
 | 
					      title: t`Link`,
 | 
				
			||||||
      switchable: true
 | 
					      switchable: true
 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      accessor: 'actions',
 | 
					 | 
				
			||||||
      title: '',
 | 
					 | 
				
			||||||
      switchable: false,
 | 
					 | 
				
			||||||
      render: function (record: any) {
 | 
					 | 
				
			||||||
        return (
 | 
					 | 
				
			||||||
          <RowActions
 | 
					 | 
				
			||||||
            title={`Part Actions`}
 | 
					 | 
				
			||||||
            actions={[
 | 
					 | 
				
			||||||
              {
 | 
					 | 
				
			||||||
                title: t`Edit`,
 | 
					 | 
				
			||||||
                icon: <IconEdit color="blue" />,
 | 
					 | 
				
			||||||
                onClick: () =>
 | 
					 | 
				
			||||||
                  editPart({
 | 
					 | 
				
			||||||
                    part_id: record.pk,
 | 
					 | 
				
			||||||
                    callback: () => {
 | 
					 | 
				
			||||||
                      // TODO: Reload the table, somehow?
 | 
					 | 
				
			||||||
                      // TODO: Insert / update a single row in the table?
 | 
					 | 
				
			||||||
                      // TODO: We need to have a hook back into the table
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                  })
 | 
					 | 
				
			||||||
              },
 | 
					 | 
				
			||||||
              {
 | 
					 | 
				
			||||||
                title: t`Delete`,
 | 
					 | 
				
			||||||
                onClick: notYetImplemented,
 | 
					 | 
				
			||||||
                icon: <IconTrash color="red" />
 | 
					 | 
				
			||||||
              }
 | 
					 | 
				
			||||||
            ]}
 | 
					 | 
				
			||||||
          />
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  ];
 | 
					  ];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -229,6 +197,32 @@ export function PartListTable({ params = {} }: { params?: any }) {
 | 
				
			|||||||
  // Add required query parameters
 | 
					  // Add required query parameters
 | 
				
			||||||
  tableParams.category_detail = true;
 | 
					  tableParams.category_detail = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function partTableRowActions(record: any): RowAction[] {
 | 
				
			||||||
 | 
					    let actions: RowAction[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    actions.push({
 | 
				
			||||||
 | 
					      title: t`Edit`,
 | 
				
			||||||
 | 
					      onClick: () => {
 | 
				
			||||||
 | 
					        editPart({
 | 
				
			||||||
 | 
					          part_id: record.pk,
 | 
				
			||||||
 | 
					          callback: () => {
 | 
				
			||||||
 | 
					            // TODO: Reload the table, somehow?
 | 
				
			||||||
 | 
					            notYetImplemented();
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (record.IPN) {
 | 
				
			||||||
 | 
					      actions.push({
 | 
				
			||||||
 | 
					        title: t`View IPN`,
 | 
				
			||||||
 | 
					        onClick: () => {}
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return actions;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <InvenTreeTable
 | 
					    <InvenTreeTable
 | 
				
			||||||
      url="part/"
 | 
					      url="part/"
 | 
				
			||||||
@@ -241,6 +235,7 @@ export function PartListTable({ params = {} }: { params?: any }) {
 | 
				
			|||||||
      params={tableParams}
 | 
					      params={tableParams}
 | 
				
			||||||
      columns={tableColumns}
 | 
					      columns={tableColumns}
 | 
				
			||||||
      customFilters={tableFilters}
 | 
					      customFilters={tableFilters}
 | 
				
			||||||
 | 
					      rowActions={partTableRowActions}
 | 
				
			||||||
    />
 | 
					    />
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@ import { ActionButton } from '../../items/ActionButton';
 | 
				
			|||||||
import { ThumbnailHoverCard } from '../../items/Thumbnail';
 | 
					import { ThumbnailHoverCard } from '../../items/Thumbnail';
 | 
				
			||||||
import { TableColumn } from '../Column';
 | 
					import { TableColumn } from '../Column';
 | 
				
			||||||
import { TableFilter } from '../Filter';
 | 
					import { TableFilter } from '../Filter';
 | 
				
			||||||
import { RowActions } from '../RowActions';
 | 
					import { RowAction } from '../RowActions';
 | 
				
			||||||
import { InvenTreeTable } from './../InvenTreeTable';
 | 
					import { InvenTreeTable } from './../InvenTreeTable';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@@ -66,7 +66,7 @@ function stockItemTableColumns(): TableColumn[] {
 | 
				
			|||||||
        // TODO: Custom renderer for location
 | 
					        // TODO: Custom renderer for location
 | 
				
			||||||
        return record.location;
 | 
					        return record.location;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    }
 | 
				
			||||||
    // TODO: stocktake column
 | 
					    // TODO: stocktake column
 | 
				
			||||||
    // TODO: expiry date
 | 
					    // TODO: expiry date
 | 
				
			||||||
    // TODO: last updated
 | 
					    // TODO: last updated
 | 
				
			||||||
@@ -76,31 +76,6 @@ function stockItemTableColumns(): TableColumn[] {
 | 
				
			|||||||
    // TODO: stock value
 | 
					    // TODO: stock value
 | 
				
			||||||
    // TODO: packaging
 | 
					    // TODO: packaging
 | 
				
			||||||
    // TODO: notes
 | 
					    // TODO: notes
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      accessor: 'actions',
 | 
					 | 
				
			||||||
      title: '',
 | 
					 | 
				
			||||||
      sortable: false,
 | 
					 | 
				
			||||||
      switchable: false,
 | 
					 | 
				
			||||||
      render: function (record: any) {
 | 
					 | 
				
			||||||
        return (
 | 
					 | 
				
			||||||
          <RowActions
 | 
					 | 
				
			||||||
            title={t`Stock Actions`}
 | 
					 | 
				
			||||||
            actions={[
 | 
					 | 
				
			||||||
              {
 | 
					 | 
				
			||||||
                title: t`Edit`,
 | 
					 | 
				
			||||||
                icon: <IconEdit color="blue" />,
 | 
					 | 
				
			||||||
                onClick: notYetImplemented
 | 
					 | 
				
			||||||
              },
 | 
					 | 
				
			||||||
              {
 | 
					 | 
				
			||||||
                title: t`Delete`,
 | 
					 | 
				
			||||||
                icon: <IconTrash color="red" />,
 | 
					 | 
				
			||||||
                onClick: notYetImplemented
 | 
					 | 
				
			||||||
              }
 | 
					 | 
				
			||||||
            ]}
 | 
					 | 
				
			||||||
          />
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  ];
 | 
					  ];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -142,6 +117,19 @@ export function StockItemTable({ params = {} }: { params?: any }) {
 | 
				
			|||||||
  let tableColumns = useMemo(() => stockItemTableColumns(), []);
 | 
					  let tableColumns = useMemo(() => stockItemTableColumns(), []);
 | 
				
			||||||
  let tableFilters = useMemo(() => stockItemTableFilters(), []);
 | 
					  let tableFilters = useMemo(() => stockItemTableFilters(), []);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function stockItemRowActions(record: any): RowAction[] {
 | 
				
			||||||
 | 
					    let actions: RowAction[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    actions.push({
 | 
				
			||||||
 | 
					      title: t`Edit`,
 | 
				
			||||||
 | 
					      onClick: () => {
 | 
				
			||||||
 | 
					        notYetImplemented();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return actions;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <InvenTreeTable
 | 
					    <InvenTreeTable
 | 
				
			||||||
      url="stock/"
 | 
					      url="stock/"
 | 
				
			||||||
@@ -151,6 +139,7 @@ export function StockItemTable({ params = {} }: { params?: any }) {
 | 
				
			|||||||
      params={tableParams}
 | 
					      params={tableParams}
 | 
				
			||||||
      columns={tableColumns}
 | 
					      columns={tableColumns}
 | 
				
			||||||
      customFilters={tableFilters}
 | 
					      customFilters={tableFilters}
 | 
				
			||||||
 | 
					      rowActions={stockItemRowActions}
 | 
				
			||||||
    />
 | 
					    />
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user