mirror of
https://github.com/inventree/InvenTree.git
synced 2025-07-01 19:20:55 +00:00
Table default cols (#9868)
* Work in progress - Seems to reset the columns on page refresh - Probably related to the useLocalStorage hook * Do not overwrite until the tablestate is loaded * Prevent table fetch until data has been loaded from localStorage * Improved persistance * Adjust default column visibility * Adjust playwright test
This commit is contained in:
@ -52,7 +52,7 @@ export type TableState = {
|
|||||||
hasSelectedRecords: boolean;
|
hasSelectedRecords: boolean;
|
||||||
setSelectedRecords: (records: any[]) => void;
|
setSelectedRecords: (records: any[]) => void;
|
||||||
clearSelectedRecords: () => void;
|
clearSelectedRecords: () => void;
|
||||||
hiddenColumns: string[];
|
hiddenColumns: string[] | null;
|
||||||
setHiddenColumns: (columns: string[]) => void;
|
setHiddenColumns: (columns: string[]) => void;
|
||||||
searchTerm: string;
|
searchTerm: string;
|
||||||
setSearchTerm: (term: string) => void;
|
setSearchTerm: (term: string) => void;
|
||||||
@ -62,6 +62,7 @@ export type TableState = {
|
|||||||
setPage: (page: number) => void;
|
setPage: (page: number) => void;
|
||||||
pageSize: number;
|
pageSize: number;
|
||||||
setPageSize: (pageSize: number) => void;
|
setPageSize: (pageSize: number) => void;
|
||||||
|
storedDataLoaded: boolean;
|
||||||
records: any[];
|
records: any[];
|
||||||
setRecords: (records: any[]) => void;
|
setRecords: (records: any[]) => void;
|
||||||
updateRecord: (record: any) => void;
|
updateRecord: (record: any) => void;
|
||||||
|
@ -65,19 +65,36 @@ export function useTable(tableName: string, idAccessor = 'pk'): TableState {
|
|||||||
// Total record count
|
// Total record count
|
||||||
const [recordCount, setRecordCount] = useState<number>(0);
|
const [recordCount, setRecordCount] = useState<number>(0);
|
||||||
|
|
||||||
|
const [pageSizeLoaded, setPageSizeLoaded] = useState<boolean>(false);
|
||||||
|
|
||||||
// Pagination data
|
// Pagination data
|
||||||
const [page, setPage] = useState<number>(1);
|
const [page, setPage] = useState<number>(1);
|
||||||
const [pageSize, setPageSize] = useLocalStorage<number>({
|
const [pageSize, setPageSize] = useLocalStorage<number>({
|
||||||
key: 'inventree-table-page-size',
|
key: 'inventree-table-page-size',
|
||||||
defaultValue: 25
|
defaultValue: 25,
|
||||||
|
deserialize: (value: string | undefined) => {
|
||||||
|
setPageSizeLoaded(true);
|
||||||
|
return value === undefined ? 25 : JSON.parse(value);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [hiddenColumnsLoaded, setHiddenColumnsLoaded] =
|
||||||
|
useState<boolean>(false);
|
||||||
|
|
||||||
// A list of hidden columns, saved to local storage
|
// A list of hidden columns, saved to local storage
|
||||||
const [hiddenColumns, setHiddenColumns] = useLocalStorage<string[]>({
|
const [hiddenColumns, setHiddenColumns] = useLocalStorage<string[] | null>({
|
||||||
key: `inventree-hidden-table-columns-${tableName}`,
|
key: `inventree-hidden-table-columns-${tableName}`,
|
||||||
defaultValue: []
|
defaultValue: null,
|
||||||
|
deserialize: (value) => {
|
||||||
|
setHiddenColumnsLoaded(true);
|
||||||
|
return value === undefined ? null : JSON.parse(value);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const storedDataLoaded = useMemo(() => {
|
||||||
|
return pageSizeLoaded && hiddenColumnsLoaded;
|
||||||
|
}, [pageSizeLoaded, hiddenColumnsLoaded]);
|
||||||
|
|
||||||
// Search term
|
// Search term
|
||||||
const [searchTerm, setSearchTerm] = useState<string>('');
|
const [searchTerm, setSearchTerm] = useState<string>('');
|
||||||
|
|
||||||
@ -137,6 +154,7 @@ export function useTable(tableName: string, idAccessor = 'pk'): TableState {
|
|||||||
setPage,
|
setPage,
|
||||||
pageSize,
|
pageSize,
|
||||||
setPageSize,
|
setPageSize,
|
||||||
|
storedDataLoaded,
|
||||||
records,
|
records,
|
||||||
setRecords,
|
setRecords,
|
||||||
updateRecord,
|
updateRecord,
|
||||||
|
@ -9,7 +9,8 @@ import type { ApiFormFieldType } from '@lib/types/Forms';
|
|||||||
* @param ordering - The key in the record to sort by (defaults to accessor)
|
* @param ordering - The key in the record to sort by (defaults to accessor)
|
||||||
* @param sortable - Whether the column is sortable
|
* @param sortable - Whether the column is sortable
|
||||||
* @param switchable - Whether the column is switchable
|
* @param switchable - Whether the column is switchable
|
||||||
* @param hidden - Whether the column is hidden
|
* @param defaultVisible - Whether the column is visible by default (defaults to true)
|
||||||
|
* @param hidden - Whether the column is hidden (forced hidden, cannot be toggled by the user))
|
||||||
* @param editable - Whether the value of this column can be edited
|
* @param editable - Whether the value of this column can be edited
|
||||||
* @param definition - Optional field definition for the column
|
* @param definition - Optional field definition for the column
|
||||||
* @param render - A custom render function
|
* @param render - A custom render function
|
||||||
@ -31,6 +32,7 @@ export type TableColumnProps<T = any> = {
|
|||||||
sortable?: boolean;
|
sortable?: boolean;
|
||||||
switchable?: boolean;
|
switchable?: boolean;
|
||||||
hidden?: boolean;
|
hidden?: boolean;
|
||||||
|
defaultVisible?: boolean;
|
||||||
editable?: boolean;
|
editable?: boolean;
|
||||||
definition?: ApiFormFieldType;
|
definition?: ApiFormFieldType;
|
||||||
render?: (record: T, index?: number) => any;
|
render?: (record: T, index?: number) => any;
|
||||||
|
@ -105,6 +105,7 @@ export function LinkColumn(props: TableColumnProps): TableColumn {
|
|||||||
return {
|
return {
|
||||||
accessor: 'link',
|
accessor: 'link',
|
||||||
sortable: false,
|
sortable: false,
|
||||||
|
defaultVisible: false,
|
||||||
render: (record: any) => {
|
render: (record: any) => {
|
||||||
const url = resolveItem(record, props.accessor ?? 'link');
|
const url = resolveItem(record, props.accessor ?? 'link');
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { t } from '@lingui/core/macro';
|
import { t } from '@lingui/core/macro';
|
||||||
import { Box, type MantineStyleProp, Stack } from '@mantine/core';
|
import { Box, type MantineStyleProp, Skeleton, Stack } from '@mantine/core';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import {
|
import {
|
||||||
type ContextMenuItemOptions,
|
type ContextMenuItemOptions,
|
||||||
@ -186,7 +186,7 @@ export function InvenTreeTable<T extends Record<string, any>>({
|
|||||||
|
|
||||||
// Request OPTIONS data from the API, before we load the table
|
// Request OPTIONS data from the API, before we load the table
|
||||||
const tableOptionQuery = useQuery({
|
const tableOptionQuery = useQuery({
|
||||||
enabled: !!url && !tableData,
|
enabled: !!url && !tableData && tableState.storedDataLoaded,
|
||||||
queryKey: [
|
queryKey: [
|
||||||
'options',
|
'options',
|
||||||
url,
|
url,
|
||||||
@ -273,6 +273,30 @@ export function InvenTreeTable<T extends Record<string, any>>({
|
|||||||
return tableProps.enableSelection || tableProps.enableBulkDelete || false;
|
return tableProps.enableSelection || tableProps.enableBulkDelete || false;
|
||||||
}, [tableProps]);
|
}, [tableProps]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// On first table render, "hide" any default hidden columns
|
||||||
|
if (tableProps.enableColumnSwitching == false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A "null" value indicates that the initial "hidden" columns have not been set
|
||||||
|
if (tableState.storedDataLoaded && tableState.hiddenColumns == null) {
|
||||||
|
const columnNames: string[] = columns
|
||||||
|
.filter((col) => {
|
||||||
|
// Find any switchable columns which are hidden by default
|
||||||
|
return col.switchable != false && col.defaultVisible == false;
|
||||||
|
})
|
||||||
|
.map((col) => col.accessor);
|
||||||
|
|
||||||
|
tableState.setHiddenColumns(columnNames);
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
columns,
|
||||||
|
tableProps.enableColumnSwitching,
|
||||||
|
tableState.hiddenColumns,
|
||||||
|
tableState.storedDataLoaded
|
||||||
|
]);
|
||||||
|
|
||||||
// Check if any columns are switchable (can be hidden)
|
// Check if any columns are switchable (can be hidden)
|
||||||
const hasSwitchableColumns: boolean = useMemo(() => {
|
const hasSwitchableColumns: boolean = useMemo(() => {
|
||||||
if (props.enableColumnSwitching == false) {
|
if (props.enableColumnSwitching == false) {
|
||||||
@ -300,22 +324,28 @@ export function InvenTreeTable<T extends Record<string, any>>({
|
|||||||
|
|
||||||
// Update column visibility when hiddenColumns change
|
// Update column visibility when hiddenColumns change
|
||||||
const dataColumns: any = useMemo(() => {
|
const dataColumns: any = useMemo(() => {
|
||||||
const cols: TableColumn[] = columns
|
let cols: TableColumn[] = columns.filter((col) => col?.hidden != true);
|
||||||
.filter((col) => col?.hidden != true)
|
|
||||||
.map((col) => {
|
|
||||||
let hidden: boolean = col.hidden ?? false;
|
|
||||||
|
|
||||||
if (col.switchable ?? true) {
|
if (!tableState.storedDataLoaded) {
|
||||||
hidden = tableState.hiddenColumns.includes(col.accessor);
|
cols = cols.filter((col) => col?.defaultVisible != false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
cols = cols.map((col) => {
|
||||||
...col,
|
// If the column is *not* switchable, it is always visible
|
||||||
hidden: hidden,
|
// Otherwise, check if it is "default hidden"
|
||||||
resizable: col.resizable ?? true,
|
|
||||||
title: col.title ?? fieldNames[col.accessor] ?? `${col.accessor}`
|
const hidden: boolean =
|
||||||
};
|
col.switchable == false
|
||||||
});
|
? false
|
||||||
|
: (tableState.hiddenColumns?.includes(col.accessor) ?? false);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...col,
|
||||||
|
hidden: hidden,
|
||||||
|
resizable: col.resizable ?? true,
|
||||||
|
title: col.title ?? fieldNames[col.accessor] ?? `${col.accessor}`
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
// If row actions are available, add a column for them
|
// If row actions are available, add a column for them
|
||||||
if (tableProps.rowActions) {
|
if (tableProps.rowActions) {
|
||||||
@ -342,7 +372,8 @@ export function InvenTreeTable<T extends Record<string, any>>({
|
|||||||
fieldNames,
|
fieldNames,
|
||||||
tableProps.rowActions,
|
tableProps.rowActions,
|
||||||
tableState.hiddenColumns,
|
tableState.hiddenColumns,
|
||||||
tableState.selectedRecords
|
tableState.selectedRecords,
|
||||||
|
tableState.storedDataLoaded
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Callback when column visibility is toggled
|
// Callback when column visibility is toggled
|
||||||
@ -583,7 +614,7 @@ export function InvenTreeTable<T extends Record<string, any>>({
|
|||||||
tableState.filterSet.activeFilters,
|
tableState.filterSet.activeFilters,
|
||||||
tableState.searchTerm
|
tableState.searchTerm
|
||||||
],
|
],
|
||||||
enabled: !!url && !tableData,
|
enabled: !!url && !tableData && tableState.storedDataLoaded,
|
||||||
queryFn: fetchTableData,
|
queryFn: fetchTableData,
|
||||||
refetchOnMount: true
|
refetchOnMount: true
|
||||||
});
|
});
|
||||||
@ -784,6 +815,10 @@ export function InvenTreeTable<T extends Record<string, any>>({
|
|||||||
);
|
);
|
||||||
}, [tableProps.onCellClick, tableProps.onRowClick, tableProps.modelType]);
|
}, [tableProps.onCellClick, tableProps.onRowClick, tableProps.modelType]);
|
||||||
|
|
||||||
|
if (!tableState.storedDataLoaded) {
|
||||||
|
return <Skeleton w='100%' h='100%' animate />;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack gap='xs'>
|
<Stack gap='xs'>
|
||||||
|
@ -145,6 +145,7 @@ export function BomTable({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessor: 'substitutes',
|
accessor: 'substitutes',
|
||||||
|
defaultVisible: false,
|
||||||
render: (row) => {
|
render: (row) => {
|
||||||
const substitutes = row.substitutes ?? [];
|
const substitutes = row.substitutes ?? [];
|
||||||
|
|
||||||
@ -162,21 +163,24 @@ export function BomTable({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
BooleanColumn({
|
BooleanColumn({
|
||||||
accessor: 'optional'
|
accessor: 'optional',
|
||||||
|
defaultVisible: false
|
||||||
}),
|
}),
|
||||||
BooleanColumn({
|
BooleanColumn({
|
||||||
accessor: 'consumable'
|
accessor: 'consumable',
|
||||||
|
defaultVisible: false
|
||||||
}),
|
}),
|
||||||
BooleanColumn({
|
BooleanColumn({
|
||||||
accessor: 'allow_variants'
|
accessor: 'allow_variants',
|
||||||
|
defaultVisible: false
|
||||||
}),
|
}),
|
||||||
BooleanColumn({
|
BooleanColumn({
|
||||||
accessor: 'inherited'
|
accessor: 'inherited',
|
||||||
// TODO: Custom renderer for this column
|
defaultVisible: false
|
||||||
// TODO: See bom.js for existing implementation
|
|
||||||
}),
|
}),
|
||||||
BooleanColumn({
|
BooleanColumn({
|
||||||
accessor: 'validated'
|
accessor: 'validated',
|
||||||
|
defaultVisible: false
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
accessor: 'price_range',
|
accessor: 'price_range',
|
||||||
@ -184,6 +188,7 @@ export function BomTable({
|
|||||||
ordering: 'pricing_max',
|
ordering: 'pricing_max',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
switchable: true,
|
switchable: true,
|
||||||
|
defaultVisible: false,
|
||||||
render: (record: any) =>
|
render: (record: any) =>
|
||||||
formatPriceRange(record.pricing_min, record.pricing_max)
|
formatPriceRange(record.pricing_min, record.pricing_max)
|
||||||
},
|
},
|
||||||
|
@ -45,7 +45,8 @@ export function UsedInTable({
|
|||||||
{
|
{
|
||||||
accessor: 'part_detail.revision',
|
accessor: 'part_detail.revision',
|
||||||
title: t`Revision`,
|
title: t`Revision`,
|
||||||
sortable: true
|
sortable: true,
|
||||||
|
defaultVisible: false
|
||||||
},
|
},
|
||||||
DescriptionColumn({
|
DescriptionColumn({
|
||||||
accessor: 'part_detail.description'
|
accessor: 'part_detail.description'
|
||||||
|
@ -340,33 +340,39 @@ export default function BuildLineTable({
|
|||||||
BooleanColumn({
|
BooleanColumn({
|
||||||
accessor: 'bom_item_detail.optional',
|
accessor: 'bom_item_detail.optional',
|
||||||
ordering: 'optional',
|
ordering: 'optional',
|
||||||
hidden: hasOutput
|
hidden: hasOutput,
|
||||||
|
defaultVisible: false
|
||||||
}),
|
}),
|
||||||
BooleanColumn({
|
BooleanColumn({
|
||||||
accessor: 'bom_item_detail.consumable',
|
accessor: 'bom_item_detail.consumable',
|
||||||
ordering: 'consumable',
|
ordering: 'consumable',
|
||||||
hidden: hasOutput
|
hidden: hasOutput,
|
||||||
|
defaultVisible: false
|
||||||
}),
|
}),
|
||||||
BooleanColumn({
|
BooleanColumn({
|
||||||
accessor: 'bom_item_detail.allow_variants',
|
accessor: 'bom_item_detail.allow_variants',
|
||||||
ordering: 'allow_variants',
|
ordering: 'allow_variants',
|
||||||
hidden: hasOutput
|
hidden: hasOutput,
|
||||||
|
defaultVisible: false
|
||||||
}),
|
}),
|
||||||
BooleanColumn({
|
BooleanColumn({
|
||||||
accessor: 'bom_item_detail.inherited',
|
accessor: 'bom_item_detail.inherited',
|
||||||
ordering: 'inherited',
|
ordering: 'inherited',
|
||||||
title: t`Gets Inherited`,
|
title: t`Gets Inherited`,
|
||||||
hidden: hasOutput
|
hidden: hasOutput,
|
||||||
|
defaultVisible: false
|
||||||
}),
|
}),
|
||||||
BooleanColumn({
|
BooleanColumn({
|
||||||
accessor: 'part_detail.trackable',
|
accessor: 'part_detail.trackable',
|
||||||
ordering: 'trackable',
|
ordering: 'trackable',
|
||||||
hidden: hasOutput
|
hidden: hasOutput,
|
||||||
|
defaultVisible: false
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
accessor: 'bom_item_detail.quantity',
|
accessor: 'bom_item_detail.quantity',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
title: t`Unit Quantity`,
|
title: t`Unit Quantity`,
|
||||||
|
defaultVisible: false,
|
||||||
ordering: 'unit_quantity',
|
ordering: 'unit_quantity',
|
||||||
render: (record: any) => {
|
render: (record: any) => {
|
||||||
return (
|
return (
|
||||||
@ -383,6 +389,7 @@ export default function BuildLineTable({
|
|||||||
accessor: 'quantity',
|
accessor: 'quantity',
|
||||||
title: t`Required Quantity`,
|
title: t`Required Quantity`,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
|
defaultVisible: false,
|
||||||
switchable: false,
|
switchable: false,
|
||||||
render: (record: any) => {
|
render: (record: any) => {
|
||||||
// If a build output is specified, use the provided quantity
|
// If a build output is specified, use the provided quantity
|
||||||
|
@ -82,7 +82,8 @@ export function BuildOrderTable({
|
|||||||
{
|
{
|
||||||
accessor: 'part_detail.revision',
|
accessor: 'part_detail.revision',
|
||||||
title: t`Revision`,
|
title: t`Revision`,
|
||||||
sortable: true
|
sortable: true,
|
||||||
|
defaultVisible: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessor: 'title',
|
accessor: 'title',
|
||||||
@ -101,16 +102,20 @@ export function BuildOrderTable({
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
StatusColumn({ model: ModelType.build }),
|
StatusColumn({ model: ModelType.build }),
|
||||||
ProjectCodeColumn({}),
|
ProjectCodeColumn({
|
||||||
|
defaultVisible: false
|
||||||
|
}),
|
||||||
{
|
{
|
||||||
accessor: 'level',
|
accessor: 'level',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
switchable: true,
|
switchable: true,
|
||||||
hidden: !parentBuildId
|
hidden: !parentBuildId,
|
||||||
|
defaultVisible: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessor: 'priority',
|
accessor: 'priority',
|
||||||
sortable: true
|
sortable: true,
|
||||||
|
defaultVisible: false
|
||||||
},
|
},
|
||||||
BooleanColumn({
|
BooleanColumn({
|
||||||
accessor: 'external',
|
accessor: 'external',
|
||||||
@ -119,8 +124,12 @@ export function BuildOrderTable({
|
|||||||
switchable: true,
|
switchable: true,
|
||||||
hidden: !globalSettings.isSet('BUILDORDER_EXTERNAL_BUILDS')
|
hidden: !globalSettings.isSet('BUILDORDER_EXTERNAL_BUILDS')
|
||||||
}),
|
}),
|
||||||
CreationDateColumn({}),
|
CreationDateColumn({
|
||||||
StartDateColumn({}),
|
defaultVisible: false
|
||||||
|
}),
|
||||||
|
StartDateColumn({
|
||||||
|
defaultVisible: false
|
||||||
|
}),
|
||||||
TargetDateColumn({}),
|
TargetDateColumn({}),
|
||||||
DateColumn({
|
DateColumn({
|
||||||
accessor: 'completion_date',
|
accessor: 'completion_date',
|
||||||
|
@ -368,15 +368,19 @@ export default function ParametricPartTable({
|
|||||||
const partColumns: TableColumn[] = [
|
const partColumns: TableColumn[] = [
|
||||||
{
|
{
|
||||||
accessor: 'name',
|
accessor: 'name',
|
||||||
|
title: t`Part`,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
switchable: false,
|
switchable: false,
|
||||||
noWrap: true,
|
noWrap: true,
|
||||||
render: (record: any) => PartColumn({ part: record })
|
render: (record: any) => PartColumn({ part: record })
|
||||||
},
|
},
|
||||||
DescriptionColumn({}),
|
DescriptionColumn({
|
||||||
|
defaultVisible: false
|
||||||
|
}),
|
||||||
{
|
{
|
||||||
accessor: 'IPN',
|
accessor: 'IPN',
|
||||||
sortable: true
|
sortable: true,
|
||||||
|
defaultVisible: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessor: 'total_in_stock',
|
accessor: 'total_in_stock',
|
||||||
|
@ -65,6 +65,7 @@ export function PartCategoryTable({ parentId }: Readonly<{ parentId?: any }>) {
|
|||||||
{
|
{
|
||||||
accessor: 'structural',
|
accessor: 'structural',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
|
defaultVisible: false,
|
||||||
render: (record: any) => {
|
render: (record: any) => {
|
||||||
return <YesNoButton value={record.structural} />;
|
return <YesNoButton value={record.structural} />;
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,8 @@ export function PartParameterTable({
|
|||||||
{
|
{
|
||||||
accessor: 'part_detail.IPN',
|
accessor: 'part_detail.IPN',
|
||||||
sortable: false,
|
sortable: false,
|
||||||
switchable: true
|
switchable: true,
|
||||||
|
defaultVisible: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessor: 'template_detail.name',
|
accessor: 'template_detail.name',
|
||||||
|
@ -61,7 +61,8 @@ function partTableColumns(): TableColumn[] {
|
|||||||
{
|
{
|
||||||
accessor: 'default_location',
|
accessor: 'default_location',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
render: (record: any) => record.default_location_detail?.pathstring
|
render: (record: any) => record.default_location_detail?.pathstring,
|
||||||
|
defaultVisible: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessor: 'total_in_stock',
|
accessor: 'total_in_stock',
|
||||||
@ -167,6 +168,7 @@ function partTableColumns(): TableColumn[] {
|
|||||||
title: t`Price Range`,
|
title: t`Price Range`,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
ordering: 'pricing_max',
|
ordering: 'pricing_max',
|
||||||
|
defaultVisible: false,
|
||||||
render: (record: any) =>
|
render: (record: any) =>
|
||||||
formatPriceRange(record.pricing_min, record.pricing_max)
|
formatPriceRange(record.pricing_min, record.pricing_max)
|
||||||
},
|
},
|
||||||
|
@ -152,6 +152,7 @@ export function PurchaseOrderLineItemTable({
|
|||||||
accessor: 'build_order',
|
accessor: 'build_order',
|
||||||
title: t`Build Order`,
|
title: t`Build Order`,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
|
defaultVisible: false,
|
||||||
render: (record: any) => {
|
render: (record: any) => {
|
||||||
if (record.build_order_detail) {
|
if (record.build_order_detail) {
|
||||||
return (
|
return (
|
||||||
@ -219,7 +220,8 @@ export function PurchaseOrderLineItemTable({
|
|||||||
{
|
{
|
||||||
accessor: 'supplier_part_detail.packaging',
|
accessor: 'supplier_part_detail.packaging',
|
||||||
sortable: false,
|
sortable: false,
|
||||||
title: t`Packaging`
|
title: t`Packaging`,
|
||||||
|
defaultVisible: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessor: 'supplier_part_detail.pack_quantity',
|
accessor: 'supplier_part_detail.pack_quantity',
|
||||||
@ -236,13 +238,15 @@ export function PurchaseOrderLineItemTable({
|
|||||||
LinkColumn({
|
LinkColumn({
|
||||||
accessor: 'supplier_part_detail.link',
|
accessor: 'supplier_part_detail.link',
|
||||||
title: t`Supplier Link`,
|
title: t`Supplier Link`,
|
||||||
sortable: false
|
sortable: false,
|
||||||
|
defaultVisible: false
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
accessor: 'mpn',
|
accessor: 'mpn',
|
||||||
ordering: 'MPN',
|
ordering: 'MPN',
|
||||||
title: t`Manufacturer Code`,
|
title: t`Manufacturer Code`,
|
||||||
sortable: true
|
sortable: true,
|
||||||
|
defaultVisible: false
|
||||||
},
|
},
|
||||||
CurrencyColumn({
|
CurrencyColumn({
|
||||||
accessor: 'purchase_price',
|
accessor: 'purchase_price',
|
||||||
|
@ -123,10 +123,18 @@ export function PurchaseOrderTable({
|
|||||||
},
|
},
|
||||||
LineItemsProgressColumn(),
|
LineItemsProgressColumn(),
|
||||||
StatusColumn({ model: ModelType.purchaseorder }),
|
StatusColumn({ model: ModelType.purchaseorder }),
|
||||||
ProjectCodeColumn({}),
|
ProjectCodeColumn({
|
||||||
CreationDateColumn({}),
|
defaultVisible: false
|
||||||
CreatedByColumn({}),
|
}),
|
||||||
StartDateColumn({}),
|
CreationDateColumn({
|
||||||
|
defaultVisible: false
|
||||||
|
}),
|
||||||
|
CreatedByColumn({
|
||||||
|
defaultVisible: false
|
||||||
|
}),
|
||||||
|
StartDateColumn({
|
||||||
|
defaultVisible: false
|
||||||
|
}),
|
||||||
TargetDateColumn({}),
|
TargetDateColumn({}),
|
||||||
CompletionDateColumn({
|
CompletionDateColumn({
|
||||||
accessor: 'complete_date'
|
accessor: 'complete_date'
|
||||||
|
@ -100,7 +100,8 @@ export function SupplierPartTable({
|
|||||||
accessor: 'active',
|
accessor: 'active',
|
||||||
title: t`Active`,
|
title: t`Active`,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
switchable: true
|
switchable: true,
|
||||||
|
defaultVisible: false
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
accessor: 'in_stock',
|
accessor: 'in_stock',
|
||||||
@ -108,7 +109,8 @@ export function SupplierPartTable({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessor: 'packaging',
|
accessor: 'packaging',
|
||||||
sortable: true
|
sortable: true,
|
||||||
|
defaultVisible: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessor: 'pack_quantity',
|
accessor: 'pack_quantity',
|
||||||
@ -141,7 +143,7 @@ export function SupplierPartTable({
|
|||||||
{
|
{
|
||||||
accessor: 'available',
|
accessor: 'available',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
|
defaultVisible: false,
|
||||||
render: (record: any) => {
|
render: (record: any) => {
|
||||||
const extra = [];
|
const extra = [];
|
||||||
|
|
||||||
|
@ -129,10 +129,18 @@ export function ReturnOrderTable({
|
|||||||
DescriptionColumn({}),
|
DescriptionColumn({}),
|
||||||
LineItemsProgressColumn(),
|
LineItemsProgressColumn(),
|
||||||
StatusColumn({ model: ModelType.returnorder }),
|
StatusColumn({ model: ModelType.returnorder }),
|
||||||
ProjectCodeColumn({}),
|
ProjectCodeColumn({
|
||||||
CreationDateColumn({}),
|
defaultVisible: false
|
||||||
CreatedByColumn({}),
|
}),
|
||||||
StartDateColumn({}),
|
CreationDateColumn({
|
||||||
|
defaultVisible: false
|
||||||
|
}),
|
||||||
|
CreatedByColumn({
|
||||||
|
defaultVisible: false
|
||||||
|
}),
|
||||||
|
StartDateColumn({
|
||||||
|
defaultVisible: false
|
||||||
|
}),
|
||||||
TargetDateColumn({}),
|
TargetDateColumn({}),
|
||||||
CompletionDateColumn({
|
CompletionDateColumn({
|
||||||
accessor: 'complete_date'
|
accessor: 'complete_date'
|
||||||
|
@ -166,10 +166,18 @@ export function SalesOrderTable({
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
StatusColumn({ model: ModelType.salesorder }),
|
StatusColumn({ model: ModelType.salesorder }),
|
||||||
ProjectCodeColumn({}),
|
ProjectCodeColumn({
|
||||||
CreationDateColumn({}),
|
defaultVisible: false
|
||||||
CreatedByColumn({}),
|
}),
|
||||||
StartDateColumn({}),
|
CreationDateColumn({
|
||||||
|
defaultVisible: false
|
||||||
|
}),
|
||||||
|
CreatedByColumn({
|
||||||
|
defaultVisible: false
|
||||||
|
}),
|
||||||
|
StartDateColumn({
|
||||||
|
defaultVisible: false
|
||||||
|
}),
|
||||||
TargetDateColumn({}),
|
TargetDateColumn({}),
|
||||||
ShipmentDateColumn({}),
|
ShipmentDateColumn({}),
|
||||||
ResponsibleColumn({}),
|
ResponsibleColumn({}),
|
||||||
|
@ -64,7 +64,8 @@ function stockItemTableColumns({
|
|||||||
{
|
{
|
||||||
accessor: 'part_detail.revision',
|
accessor: 'part_detail.revision',
|
||||||
title: t`Revision`,
|
title: t`Revision`,
|
||||||
sortable: true
|
sortable: true,
|
||||||
|
defaultVisible: false
|
||||||
},
|
},
|
||||||
DescriptionColumn({
|
DescriptionColumn({
|
||||||
accessor: 'part_detail.description'
|
accessor: 'part_detail.description'
|
||||||
@ -228,6 +229,7 @@ function stockItemTableColumns({
|
|||||||
{
|
{
|
||||||
accessor: 'purchase_order',
|
accessor: 'purchase_order',
|
||||||
title: t`Purchase Order`,
|
title: t`Purchase Order`,
|
||||||
|
defaultVisible: false,
|
||||||
render: (record: any) => {
|
render: (record: any) => {
|
||||||
return record.purchase_order_reference;
|
return record.purchase_order_reference;
|
||||||
}
|
}
|
||||||
@ -235,12 +237,14 @@ function stockItemTableColumns({
|
|||||||
{
|
{
|
||||||
accessor: 'SKU',
|
accessor: 'SKU',
|
||||||
title: t`Supplier Part`,
|
title: t`Supplier Part`,
|
||||||
sortable: true
|
sortable: true,
|
||||||
|
defaultVisible: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessor: 'MPN',
|
accessor: 'MPN',
|
||||||
title: t`Manufacturer Part`,
|
title: t`Manufacturer Part`,
|
||||||
sortable: true
|
sortable: true,
|
||||||
|
defaultVisible: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessor: 'purchase_price',
|
accessor: 'purchase_price',
|
||||||
@ -248,6 +252,7 @@ function stockItemTableColumns({
|
|||||||
sortable: true,
|
sortable: true,
|
||||||
switchable: true,
|
switchable: true,
|
||||||
hidden: !showPricing,
|
hidden: !showPricing,
|
||||||
|
defaultVisible: false,
|
||||||
render: (record: any) =>
|
render: (record: any) =>
|
||||||
formatCurrency(record.purchase_price, {
|
formatCurrency(record.purchase_price, {
|
||||||
currency: record.purchase_price_currency
|
currency: record.purchase_price_currency
|
||||||
@ -273,13 +278,15 @@ function stockItemTableColumns({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessor: 'packaging',
|
accessor: 'packaging',
|
||||||
sortable: true
|
sortable: true,
|
||||||
|
defaultVisible: false
|
||||||
},
|
},
|
||||||
|
|
||||||
DateColumn({
|
DateColumn({
|
||||||
title: t`Expiry Date`,
|
title: t`Expiry Date`,
|
||||||
accessor: 'expiry_date',
|
accessor: 'expiry_date',
|
||||||
hidden: !useGlobalSettingsState.getState().isSet('STOCK_ENABLE_EXPIRY')
|
hidden: !useGlobalSettingsState.getState().isSet('STOCK_ENABLE_EXPIRY'),
|
||||||
|
defaultVisible: false
|
||||||
}),
|
}),
|
||||||
DateColumn({
|
DateColumn({
|
||||||
title: t`Last Updated`,
|
title: t`Last Updated`,
|
||||||
|
@ -85,10 +85,12 @@ export function StockLocationTable({ parentId }: Readonly<{ parentId?: any }>) {
|
|||||||
sortable: true
|
sortable: true
|
||||||
},
|
},
|
||||||
BooleanColumn({
|
BooleanColumn({
|
||||||
accessor: 'structural'
|
accessor: 'structural',
|
||||||
|
defaultVisible: false
|
||||||
}),
|
}),
|
||||||
BooleanColumn({
|
BooleanColumn({
|
||||||
accessor: 'external'
|
accessor: 'external',
|
||||||
|
defaultVisible: false
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
accessor: 'location_type',
|
accessor: 'location_type',
|
||||||
|
@ -364,7 +364,6 @@ test('Purchase Orders - Receive Items', async ({ browser }) => {
|
|||||||
await clearTableFilters(page);
|
await clearTableFilters(page);
|
||||||
|
|
||||||
await page.getByRole('cell', { name: 'my-batch-code' }).first().waitFor();
|
await page.getByRole('cell', { name: 'my-batch-code' }).first().waitFor();
|
||||||
await page.getByRole('cell', { name: 'bucket' }).first().waitFor();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Purchase Orders - Duplicate', async ({ browser }) => {
|
test('Purchase Orders - Duplicate', async ({ browser }) => {
|
||||||
|
Reference in New Issue
Block a user