2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-08-01 17:41:33 +00:00
Files
InvenTree/src/frontend/src/tables/stock/StockLocationTable.tsx
Oliver 0e0abf2d75 [plugin] Library updates (#10070)
* Expose lingui modules to plugins

* Add i18n object to plugin context

* Expose form types

* Update package.json requirements

* Externalize react and mantine when building @inventreedb/ui components

* Externalize lingui packages too

* Extern <AddItemButton />
2025-07-25 01:23:34 +10:00

211 lines
5.8 KiB
TypeScript

import { t } from '@lingui/core/macro';
import { Group } from '@mantine/core';
import { useCallback, useMemo, useState } from 'react';
import { AddItemButton } from '@lib/components/AddItemButton';
import { type RowAction, RowEditAction } from '@lib/components/RowActions';
import { ApiEndpoints } from '@lib/enums/ApiEndpoints';
import { ModelType } from '@lib/enums/ModelType';
import { UserRoles } from '@lib/enums/Roles';
import { apiUrl } from '@lib/functions/Api';
import type { TableFilter } from '@lib/types/Filters';
import type { TableColumn } from '@lib/types/Tables';
import { ActionDropdown } from '../../components/items/ActionDropdown';
import { ApiIcon } from '../../components/items/ApiIcon';
import { stockLocationFields } from '../../forms/StockForms';
import { InvenTreeIcon } from '../../functions/icons';
import {
useBulkEditApiFormModal,
useCreateApiFormModal,
useEditApiFormModal
} from '../../hooks/UseForm';
import { useTable } from '../../hooks/UseTable';
import { useUserState } from '../../states/UserState';
import { BooleanColumn, DescriptionColumn } from '../ColumnRenderers';
import { InvenTreeTable } from '../InvenTreeTable';
/**
* Stock location table
*/
export function StockLocationTable({ parentId }: Readonly<{ parentId?: any }>) {
const table = useTable('stocklocation');
const user = useUserState();
const tableFilters: TableFilter[] = useMemo(() => {
return [
{
name: 'cascade',
label: t`Include Sublocations`,
description: t`Include sublocations in results`
},
{
name: 'structural',
label: t`Structural`,
description: t`Show structural locations`
},
{
name: 'external',
label: t`External`,
description: t`Show external locations`
},
{
name: 'has_location_type',
label: t`Has location type`
},
{
name: 'location_type',
label: t`Location Type`,
description: t`Filter by location type`,
apiUrl: apiUrl(ApiEndpoints.stock_location_type_list),
model: ModelType.stocklocationtype,
modelRenderer: (instance: any) => instance.name
}
];
}, []);
const tableColumns: TableColumn[] = useMemo(() => {
return [
{
accessor: 'name',
switchable: false,
render: (record: any) => (
<Group gap='xs'>
{record.icon && <ApiIcon name={record.icon} />}
{record.name}
</Group>
)
},
DescriptionColumn({}),
{
accessor: 'pathstring',
sortable: true
},
{
accessor: 'items',
sortable: true
},
BooleanColumn({
accessor: 'structural',
defaultVisible: false
}),
BooleanColumn({
accessor: 'external',
defaultVisible: false
}),
{
accessor: 'location_type',
sortable: false,
render: (record: any) => record.location_type_detail?.name
}
];
}, []);
const newLocation = useCreateApiFormModal({
url: ApiEndpoints.stock_location_list,
title: t`Add Stock Location`,
fields: stockLocationFields(),
focus: 'name',
initialData: {
parent: parentId
},
follow: true,
modelType: ModelType.stocklocation,
table: table
});
const [selectedLocation, setSelectedLocation] = useState<number>(-1);
const editLocation = useEditApiFormModal({
url: ApiEndpoints.stock_location_list,
pk: selectedLocation,
title: t`Edit Stock Location`,
fields: stockLocationFields(),
onFormSuccess: (record: any) => table.updateRecord(record)
});
const setParent = useBulkEditApiFormModal({
url: ApiEndpoints.stock_location_list,
items: table.selectedIds,
title: t`Set Parent Location`,
fields: {
parent: {}
},
onFormSuccess: table.refreshTable
});
const tableActions = useMemo(() => {
const can_add = user.hasAddRole(UserRoles.stock_location);
const can_edit = user.hasChangeRole(UserRoles.stock_location);
return [
<ActionDropdown
tooltip={t`Location Actions`}
icon={<InvenTreeIcon icon='location' />}
disabled={!table.hasSelectedRecords}
actions={[
{
name: t`Set Parent`,
icon: <InvenTreeIcon icon='location' />,
tooltip: t`Set parent location for the selected items`,
hidden: !can_edit,
disabled: !table.hasSelectedRecords,
onClick: () => {
setParent.open();
}
}
]}
/>,
<AddItemButton
key='add-stock-location'
tooltip={t`Add Stock Location`}
onClick={() => newLocation.open()}
hidden={!can_add}
/>
];
}, [user, table.hasSelectedRecords]);
const rowActions = useCallback(
(record: any): RowAction[] => {
const can_edit = user.hasChangeRole(UserRoles.stock_location);
return [
RowEditAction({
hidden: !can_edit,
onClick: () => {
setSelectedLocation(record.pk);
editLocation.open();
}
})
];
},
[user]
);
return (
<>
{newLocation.modal}
{editLocation.modal}
{setParent.modal}
<InvenTreeTable
url={apiUrl(ApiEndpoints.stock_location_list)}
tableState={table}
columns={tableColumns}
props={{
enableSelection: true,
enableDownload: true,
enableLabels: true,
enableReports: true,
params: {
parent: parentId,
top_level: parentId === undefined ? true : undefined
},
tableFilters: tableFilters,
tableActions: tableActions,
rowActions: rowActions,
modelType: ModelType.stocklocation
}}
/>
</>
);
}