mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
[PUI] Small updates (#6320)
* Ensure .ts files are generated - "yarn run compile" before "yarn run dev" - ensures that .ts locale files are all generated * Implement "Add Part Category" button * Create new stock location * Rename customActionGroups to tableActions * Rename customFilters to tableFilters * Edit category from table * Edit stock location from table * Add some placeholder buttons * More placeholders
This commit is contained in:
parent
ab921ccb31
commit
d502d93380
@ -20,8 +20,10 @@ export type ActionButtonProps = {
|
|||||||
* Construct a simple action button with consistent styling
|
* Construct a simple action button with consistent styling
|
||||||
*/
|
*/
|
||||||
export function ActionButton(props: ActionButtonProps) {
|
export function ActionButton(props: ActionButtonProps) {
|
||||||
|
const hidden = props.hidden ?? false;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
!props.hidden && (
|
!hidden && (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
key={`tooltip-${props.key}`}
|
key={`tooltip-${props.key}`}
|
||||||
disabled={!props.tooltip && !props.text}
|
disabled={!props.tooltip && !props.text}
|
||||||
|
@ -234,7 +234,6 @@ export function SearchDrawer({
|
|||||||
|
|
||||||
// Re-fetch data whenever the search term is updated
|
// Re-fetch data whenever the search term is updated
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// TODO: Implement search functionality
|
|
||||||
searchQuery.refetch();
|
searchQuery.refetch();
|
||||||
}, [searchText]);
|
}, [searchText]);
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { t } from '@lingui/macro';
|
||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
import { RenderInlineModel } from './Instance';
|
import { RenderInlineModel } from './Instance';
|
||||||
@ -6,10 +7,13 @@ import { RenderInlineModel } from './Instance';
|
|||||||
* Inline rendering of a single Part instance
|
* Inline rendering of a single Part instance
|
||||||
*/
|
*/
|
||||||
export function RenderPart({ instance }: { instance: any }): ReactNode {
|
export function RenderPart({ instance }: { instance: any }): ReactNode {
|
||||||
|
const stock = t`Stock` + `: ${instance.in_stock}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RenderInlineModel
|
<RenderInlineModel
|
||||||
primary={instance.name}
|
primary={instance.name}
|
||||||
secondary={instance.description}
|
secondary={instance.description}
|
||||||
|
suffix={stock}
|
||||||
image={instance.thumnbnail || instance.image}
|
image={instance.thumnbnail || instance.image}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -46,8 +46,8 @@ const defaultPageSize: number = 25;
|
|||||||
* @param enableRefresh : boolean - Enable refresh actions
|
* @param enableRefresh : boolean - Enable refresh actions
|
||||||
* @param pageSize : number - Number of records per page
|
* @param pageSize : number - Number of records per page
|
||||||
* @param barcodeActions : any[] - List of barcode actions
|
* @param barcodeActions : any[] - List of barcode actions
|
||||||
* @param customFilters : TableFilter[] - List of custom filters
|
* @param tableFilters : TableFilter[] - List of custom filters
|
||||||
* @param customActionGroups : any[] - List of custom action groups
|
* @param tableActions : any[] - List of custom action groups
|
||||||
* @param printingActions : any[] - List of printing actions
|
* @param printingActions : any[] - List of printing actions
|
||||||
* @param dataFormatter : (data: any) => any - Callback function to reformat data returned by server (if not in default format)
|
* @param dataFormatter : (data: any) => any - Callback function to reformat data returned by server (if not in default format)
|
||||||
* @param rowActions : (record: any) => RowAction[] - Callback function to generate row actions
|
* @param rowActions : (record: any) => RowAction[] - Callback function to generate row actions
|
||||||
@ -66,8 +66,8 @@ export type InvenTreeTableProps<T = any> = {
|
|||||||
enableRefresh?: boolean;
|
enableRefresh?: boolean;
|
||||||
pageSize?: number;
|
pageSize?: number;
|
||||||
barcodeActions?: any[];
|
barcodeActions?: any[];
|
||||||
customFilters?: TableFilter[];
|
tableFilters?: TableFilter[];
|
||||||
customActionGroups?: React.ReactNode[];
|
tableActions?: React.ReactNode[];
|
||||||
printingActions?: any[];
|
printingActions?: any[];
|
||||||
idAccessor?: string;
|
idAccessor?: string;
|
||||||
dataFormatter?: (data: T) => any;
|
dataFormatter?: (data: T) => any;
|
||||||
@ -91,8 +91,8 @@ const defaultInvenTreeTableProps: InvenTreeTableProps = {
|
|||||||
defaultSortColumn: '',
|
defaultSortColumn: '',
|
||||||
printingActions: [],
|
printingActions: [],
|
||||||
barcodeActions: [],
|
barcodeActions: [],
|
||||||
customFilters: [],
|
tableFilters: [],
|
||||||
customActionGroups: [],
|
tableActions: [],
|
||||||
idAccessor: 'pk',
|
idAccessor: 'pk',
|
||||||
onRowClick: (record: any, index: number, event: any) => {}
|
onRowClick: (record: any, index: number, event: any) => {}
|
||||||
};
|
};
|
||||||
@ -425,9 +425,9 @@ export function InvenTreeTable<T = any>({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{tableProps.enableFilters &&
|
{tableProps.enableFilters &&
|
||||||
(tableProps.customFilters?.length ?? 0) > 0 && (
|
(tableProps.tableFilters?.length ?? 0) > 0 && (
|
||||||
<FilterSelectDrawer
|
<FilterSelectDrawer
|
||||||
availableFilters={tableProps.customFilters ?? []}
|
availableFilters={tableProps.tableFilters ?? []}
|
||||||
tableState={tableState}
|
tableState={tableState}
|
||||||
opened={filtersVisible}
|
opened={filtersVisible}
|
||||||
onClose={() => setFiltersVisible(false)}
|
onClose={() => setFiltersVisible(false)}
|
||||||
@ -436,7 +436,7 @@ export function InvenTreeTable<T = any>({
|
|||||||
<Stack spacing="sm">
|
<Stack spacing="sm">
|
||||||
<Group position="apart">
|
<Group position="apart">
|
||||||
<Group position="left" key="custom-actions" spacing={5}>
|
<Group position="left" key="custom-actions" spacing={5}>
|
||||||
{tableProps.customActionGroups?.map((group, idx) => (
|
{tableProps.tableActions?.map((group, idx) => (
|
||||||
<Fragment key={idx}>{group}</Fragment>
|
<Fragment key={idx}>{group}</Fragment>
|
||||||
))}
|
))}
|
||||||
{(tableProps.barcodeActions?.length ?? 0 > 0) && (
|
{(tableProps.barcodeActions?.length ?? 0 > 0) && (
|
||||||
@ -490,7 +490,7 @@ export function InvenTreeTable<T = any>({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{tableProps.enableFilters &&
|
{tableProps.enableFilters &&
|
||||||
(tableProps.customFilters?.length ?? 0 > 0) && (
|
(tableProps.tableFilters?.length ?? 0 > 0) && (
|
||||||
<Indicator
|
<Indicator
|
||||||
size="xs"
|
size="xs"
|
||||||
label={tableState.activeFilters.length}
|
label={tableState.activeFilters.length}
|
||||||
|
@ -363,7 +363,7 @@ export function BomTable({
|
|||||||
part_detail: true,
|
part_detail: true,
|
||||||
sub_part_detail: true
|
sub_part_detail: true
|
||||||
},
|
},
|
||||||
customFilters: tableFilters,
|
tableFilters: tableFilters,
|
||||||
onRowClick: (row) => navigate(`/part/${row.sub_part}`),
|
onRowClick: (row) => navigate(`/part/${row.sub_part}`),
|
||||||
rowActions: rowActions
|
rowActions: rowActions
|
||||||
}}
|
}}
|
||||||
|
@ -116,7 +116,7 @@ export function UsedInTable({
|
|||||||
part_detail: true,
|
part_detail: true,
|
||||||
sub_part_detail: true
|
sub_part_detail: true
|
||||||
},
|
},
|
||||||
customFilters: tableFilters,
|
tableFilters: tableFilters,
|
||||||
onRowClick: (row) => navigate(`/part/${row.part}`)
|
onRowClick: (row) => navigate(`/part/${row.part}`)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -155,7 +155,7 @@ export function BuildOrderTable({ params = {} }: { params?: any }) {
|
|||||||
...params,
|
...params,
|
||||||
part_detail: true
|
part_detail: true
|
||||||
},
|
},
|
||||||
customFilters: tableFilters,
|
tableFilters: tableFilters,
|
||||||
onRowClick: (row) => navigate(`/build/${row.pk}`)
|
onRowClick: (row) => navigate(`/build/${row.pk}`)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -185,7 +185,7 @@ export function AddressTable({
|
|||||||
columns={columns}
|
columns={columns}
|
||||||
props={{
|
props={{
|
||||||
rowActions: rowActions,
|
rowActions: rowActions,
|
||||||
customActionGroups: tableActions,
|
tableActions: tableActions,
|
||||||
params: {
|
params: {
|
||||||
...params,
|
...params,
|
||||||
company: companyId
|
company: companyId
|
||||||
|
@ -133,7 +133,7 @@ export function ContactTable({
|
|||||||
columns={columns}
|
columns={columns}
|
||||||
props={{
|
props={{
|
||||||
rowActions: rowActions,
|
rowActions: rowActions,
|
||||||
customActionGroups: tableActions,
|
tableActions: tableActions,
|
||||||
params: {
|
params: {
|
||||||
...params,
|
...params,
|
||||||
company: companyId
|
company: companyId
|
||||||
|
@ -178,7 +178,7 @@ export function AttachmentTable({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const customActionGroups: ReactNode[] = useMemo(() => {
|
const tableActions: ReactNode[] = useMemo(() => {
|
||||||
let actions = [];
|
let actions = [];
|
||||||
|
|
||||||
if (allowEdit) {
|
if (allowEdit) {
|
||||||
@ -235,7 +235,7 @@ export function AttachmentTable({
|
|||||||
props={{
|
props={{
|
||||||
noRecordsText: t`No attachments found`,
|
noRecordsText: t`No attachments found`,
|
||||||
enableSelection: true,
|
enableSelection: true,
|
||||||
customActionGroups: customActionGroups,
|
tableActions: tableActions,
|
||||||
rowActions: allowEdit && allowDelete ? rowActions : undefined,
|
rowActions: allowEdit && allowDelete ? rowActions : undefined,
|
||||||
params: {
|
params: {
|
||||||
[model]: pk
|
[model]: pk
|
||||||
|
@ -1,23 +1,30 @@
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
import { ApiPaths } from '../../../enums/ApiEndpoints';
|
import { ApiPaths } from '../../../enums/ApiEndpoints';
|
||||||
|
import { UserRoles } from '../../../enums/Roles';
|
||||||
|
import { partCategoryFields } from '../../../forms/PartForms';
|
||||||
|
import { openCreateApiForm, openEditApiForm } from '../../../functions/forms';
|
||||||
import { useTable } from '../../../hooks/UseTable';
|
import { useTable } from '../../../hooks/UseTable';
|
||||||
import { apiUrl } from '../../../states/ApiState';
|
import { apiUrl } from '../../../states/ApiState';
|
||||||
|
import { useUserState } from '../../../states/UserState';
|
||||||
|
import { AddItemButton } from '../../buttons/AddItemButton';
|
||||||
import { YesNoButton } from '../../items/YesNoButton';
|
import { YesNoButton } from '../../items/YesNoButton';
|
||||||
import { TableColumn } from '../Column';
|
import { TableColumn } from '../Column';
|
||||||
import { DescriptionColumn } from '../ColumnRenderers';
|
import { DescriptionColumn } from '../ColumnRenderers';
|
||||||
import { TableFilter } from '../Filter';
|
import { TableFilter } from '../Filter';
|
||||||
import { InvenTreeTable } from '../InvenTreeTable';
|
import { InvenTreeTable } from '../InvenTreeTable';
|
||||||
|
import { RowEditAction } from '../RowActions';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PartCategoryTable - Displays a table of part categories
|
* PartCategoryTable - Displays a table of part categories
|
||||||
*/
|
*/
|
||||||
export function PartCategoryTable({ params = {} }: { params?: any }) {
|
export function PartCategoryTable({ parentId }: { parentId?: any }) {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const table = useTable('partcategory');
|
const table = useTable('partcategory');
|
||||||
|
const user = useUserState();
|
||||||
|
|
||||||
const tableColumns: TableColumn[] = useMemo(() => {
|
const tableColumns: TableColumn[] = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
@ -64,6 +71,62 @@ export function PartCategoryTable({ params = {} }: { params?: any }) {
|
|||||||
];
|
];
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const addCategory = useCallback(() => {
|
||||||
|
let fields = partCategoryFields({});
|
||||||
|
|
||||||
|
if (parentId) {
|
||||||
|
fields['parent'].value = parentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
openCreateApiForm({
|
||||||
|
url: apiUrl(ApiPaths.category_list),
|
||||||
|
title: t`Add Part Category`,
|
||||||
|
fields: fields,
|
||||||
|
onFormSuccess(data: any) {
|
||||||
|
if (data.pk) {
|
||||||
|
navigate(`/part/category/${data.pk}`);
|
||||||
|
} else {
|
||||||
|
table.refreshTable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, [parentId]);
|
||||||
|
|
||||||
|
const tableActions = useMemo(() => {
|
||||||
|
let can_add = user.hasAddRole(UserRoles.part_category);
|
||||||
|
|
||||||
|
return [
|
||||||
|
<AddItemButton
|
||||||
|
tooltip={t`Add Part Category`}
|
||||||
|
onClick={addCategory}
|
||||||
|
disabled={!can_add}
|
||||||
|
/>
|
||||||
|
];
|
||||||
|
}, [user]);
|
||||||
|
|
||||||
|
const rowActions = useCallback(
|
||||||
|
(record: any) => {
|
||||||
|
let can_edit = user.hasChangeRole(UserRoles.part_category);
|
||||||
|
|
||||||
|
return [
|
||||||
|
RowEditAction({
|
||||||
|
hidden: !can_edit,
|
||||||
|
onClick: () => {
|
||||||
|
openEditApiForm({
|
||||||
|
url: ApiPaths.category_list,
|
||||||
|
pk: record.pk,
|
||||||
|
title: t`Edit Part Category`,
|
||||||
|
fields: partCategoryFields({}),
|
||||||
|
successMessage: t`Part category updated`,
|
||||||
|
onFormSuccess: table.refreshTable
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
];
|
||||||
|
},
|
||||||
|
[user]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InvenTreeTable
|
<InvenTreeTable
|
||||||
url={apiUrl(ApiPaths.category_list)}
|
url={apiUrl(ApiPaths.category_list)}
|
||||||
@ -71,11 +134,12 @@ export function PartCategoryTable({ params = {} }: { params?: any }) {
|
|||||||
columns={tableColumns}
|
columns={tableColumns}
|
||||||
props={{
|
props={{
|
||||||
enableDownload: true,
|
enableDownload: true,
|
||||||
enableSelection: true,
|
|
||||||
params: {
|
params: {
|
||||||
...params
|
parent: parentId ?? 'null'
|
||||||
},
|
},
|
||||||
customFilters: tableFilters,
|
tableFilters: tableFilters,
|
||||||
|
tableActions: tableActions,
|
||||||
|
rowActions: rowActions,
|
||||||
onRowClick: (record, index, event) => {
|
onRowClick: (record, index, event) => {
|
||||||
navigate(`/part/category/${record.pk}`);
|
navigate(`/part/category/${record.pk}`);
|
||||||
}
|
}
|
||||||
|
@ -180,8 +180,8 @@ export function PartParameterTable({ partId }: { partId: any }) {
|
|||||||
columns={tableColumns}
|
columns={tableColumns}
|
||||||
props={{
|
props={{
|
||||||
rowActions: rowActions,
|
rowActions: rowActions,
|
||||||
customActionGroups: tableActions,
|
tableActions: tableActions,
|
||||||
customFilters: [
|
tableFilters: [
|
||||||
{
|
{
|
||||||
name: 'include_variants',
|
name: 'include_variants',
|
||||||
label: t`Include Variants`,
|
label: t`Include Variants`,
|
||||||
|
@ -131,8 +131,8 @@ export default function PartParameterTemplateTable() {
|
|||||||
columns={tableColumns}
|
columns={tableColumns}
|
||||||
props={{
|
props={{
|
||||||
rowActions: rowActions,
|
rowActions: rowActions,
|
||||||
customFilters: tableFilters,
|
tableFilters: tableFilters,
|
||||||
customActionGroups: tableActions
|
tableActions: tableActions
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -275,7 +275,7 @@ export function PartListTable({ props }: { props: InvenTreeTableProps }) {
|
|||||||
props={{
|
props={{
|
||||||
...props,
|
...props,
|
||||||
enableDownload: true,
|
enableDownload: true,
|
||||||
customFilters: tableFilters,
|
tableFilters: tableFilters,
|
||||||
params: {
|
params: {
|
||||||
...props.params,
|
...props.params,
|
||||||
category_detail: true
|
category_detail: true
|
||||||
|
@ -140,8 +140,8 @@ export default function PartTestTemplateTable({ partId }: { partId: number }) {
|
|||||||
params: {
|
params: {
|
||||||
part: partId
|
part: partId
|
||||||
},
|
},
|
||||||
customFilters: tableFilters,
|
tableFilters: tableFilters,
|
||||||
customActionGroups: tableActions,
|
tableActions: tableActions,
|
||||||
rowActions: rowActions
|
rowActions: rowActions
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -37,7 +37,7 @@ export function PartVariantTable({ partId }: { partId: string }) {
|
|||||||
<PartListTable
|
<PartListTable
|
||||||
props={{
|
props={{
|
||||||
enableDownload: false,
|
enableDownload: false,
|
||||||
customFilters: tableFilters,
|
tableFilters: tableFilters,
|
||||||
params: {
|
params: {
|
||||||
ancestor: partId
|
ancestor: partId
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,7 @@ export function RelatedPartTable({ partId }: { partId: number }): ReactNode {
|
|||||||
category_detail: true
|
category_detail: true
|
||||||
},
|
},
|
||||||
rowActions: rowActions,
|
rowActions: rowActions,
|
||||||
customActionGroups: customActions
|
tableActions: customActions
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -493,8 +493,8 @@ export function PluginListTable({ props }: { props: InvenTreeTableProps }) {
|
|||||||
},
|
},
|
||||||
rowActions: rowActions,
|
rowActions: rowActions,
|
||||||
onRowClick: (plugin) => navigate(`${plugin.pk}/`),
|
onRowClick: (plugin) => navigate(`${plugin.pk}/`),
|
||||||
customActionGroups: tableActions,
|
tableActions: tableActions,
|
||||||
customFilters: [
|
tableFilters: [
|
||||||
{
|
{
|
||||||
name: 'active',
|
name: 'active',
|
||||||
label: t`Active`,
|
label: t`Active`,
|
||||||
|
@ -5,9 +5,11 @@ import { ApiPaths } from '../../../enums/ApiEndpoints';
|
|||||||
import { UserRoles } from '../../../enums/Roles';
|
import { UserRoles } from '../../../enums/Roles';
|
||||||
import { useManufacturerPartFields } from '../../../forms/CompanyForms';
|
import { useManufacturerPartFields } from '../../../forms/CompanyForms';
|
||||||
import { openDeleteApiForm, openEditApiForm } from '../../../functions/forms';
|
import { openDeleteApiForm, openEditApiForm } from '../../../functions/forms';
|
||||||
|
import { notYetImplemented } from '../../../functions/notifications';
|
||||||
import { useTable } from '../../../hooks/UseTable';
|
import { useTable } from '../../../hooks/UseTable';
|
||||||
import { apiUrl } from '../../../states/ApiState';
|
import { apiUrl } from '../../../states/ApiState';
|
||||||
import { useUserState } from '../../../states/UserState';
|
import { useUserState } from '../../../states/UserState';
|
||||||
|
import { AddItemButton } from '../../buttons/AddItemButton';
|
||||||
import { Thumbnail } from '../../images/Thumbnail';
|
import { Thumbnail } from '../../images/Thumbnail';
|
||||||
import { TableColumn } from '../Column';
|
import { TableColumn } from '../Column';
|
||||||
import { DescriptionColumn, LinkColumn, PartColumn } from '../ColumnRenderers';
|
import { DescriptionColumn, LinkColumn, PartColumn } from '../ColumnRenderers';
|
||||||
@ -57,9 +59,22 @@ export function ManufacturerPartTable({ params }: { params: any }): ReactNode {
|
|||||||
];
|
];
|
||||||
}, [params]);
|
}, [params]);
|
||||||
|
|
||||||
|
const addManufacturerPart = useCallback(() => {
|
||||||
|
notYetImplemented();
|
||||||
|
}, []);
|
||||||
|
|
||||||
const tableActions = useMemo(() => {
|
const tableActions = useMemo(() => {
|
||||||
// TODO: Custom actions
|
let can_add =
|
||||||
return [];
|
user.hasAddRole(UserRoles.purchase_order) &&
|
||||||
|
user.hasAddRole(UserRoles.part);
|
||||||
|
|
||||||
|
return [
|
||||||
|
<AddItemButton
|
||||||
|
tooltip={t`Add Manufacturer Part`}
|
||||||
|
onClick={addManufacturerPart}
|
||||||
|
hidden={!can_add}
|
||||||
|
/>
|
||||||
|
];
|
||||||
}, [user]);
|
}, [user]);
|
||||||
|
|
||||||
const editManufacturerPartFields = useManufacturerPartFields();
|
const editManufacturerPartFields = useManufacturerPartFields();
|
||||||
@ -112,7 +127,7 @@ export function ManufacturerPartTable({ params }: { params: any }): ReactNode {
|
|||||||
manufacturer_detail: true
|
manufacturer_detail: true
|
||||||
},
|
},
|
||||||
rowActions: rowActions,
|
rowActions: rowActions,
|
||||||
customActionGroups: tableActions
|
tableActions: tableActions
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -260,7 +260,7 @@ export function PurchaseOrderLineItemTable({
|
|||||||
part_detail: true
|
part_detail: true
|
||||||
},
|
},
|
||||||
rowActions: rowActions,
|
rowActions: rowActions,
|
||||||
customActionGroups: tableActions
|
tableActions: tableActions
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
import { ApiPaths } from '../../../enums/ApiEndpoints';
|
import { ApiPaths } from '../../../enums/ApiEndpoints';
|
||||||
import { ModelType } from '../../../enums/ModelType';
|
import { ModelType } from '../../../enums/ModelType';
|
||||||
|
import { UserRoles } from '../../../enums/Roles';
|
||||||
|
import { notYetImplemented } from '../../../functions/notifications';
|
||||||
import { useTable } from '../../../hooks/UseTable';
|
import { useTable } from '../../../hooks/UseTable';
|
||||||
import { apiUrl } from '../../../states/ApiState';
|
import { apiUrl } from '../../../states/ApiState';
|
||||||
|
import { useUserState } from '../../../states/UserState';
|
||||||
|
import { AddItemButton } from '../../buttons/AddItemButton';
|
||||||
import { Thumbnail } from '../../images/Thumbnail';
|
import { Thumbnail } from '../../images/Thumbnail';
|
||||||
import {
|
import {
|
||||||
CreationDateColumn,
|
CreationDateColumn,
|
||||||
@ -33,6 +37,7 @@ export function PurchaseOrderTable({ params }: { params?: any }) {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const table = useTable('purchase-order');
|
const table = useTable('purchase-order');
|
||||||
|
const user = useUserState();
|
||||||
|
|
||||||
const tableFilters: TableFilter[] = useMemo(() => {
|
const tableFilters: TableFilter[] = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
@ -94,6 +99,20 @@ export function PurchaseOrderTable({ params }: { params?: any }) {
|
|||||||
];
|
];
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const addPurchaseOrder = useCallback(() => {
|
||||||
|
notYetImplemented();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const tableActions = useMemo(() => {
|
||||||
|
return [
|
||||||
|
<AddItemButton
|
||||||
|
tooltip={t`Add Purchase Order`}
|
||||||
|
onClick={addPurchaseOrder}
|
||||||
|
hidden={!user.hasAddRole(UserRoles.purchase_order)}
|
||||||
|
/>
|
||||||
|
];
|
||||||
|
}, [user]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InvenTreeTable
|
<InvenTreeTable
|
||||||
url={apiUrl(ApiPaths.purchase_order_list)}
|
url={apiUrl(ApiPaths.purchase_order_list)}
|
||||||
@ -104,7 +123,8 @@ export function PurchaseOrderTable({ params }: { params?: any }) {
|
|||||||
...params,
|
...params,
|
||||||
supplier_detail: true
|
supplier_detail: true
|
||||||
},
|
},
|
||||||
customFilters: tableFilters,
|
tableFilters: tableFilters,
|
||||||
|
tableActions: tableActions,
|
||||||
onRowClick: (row: any) => {
|
onRowClick: (row: any) => {
|
||||||
if (row.pk) {
|
if (row.pk) {
|
||||||
navigate(`/purchasing/purchase-order/${row.pk}`);
|
navigate(`/purchasing/purchase-order/${row.pk}`);
|
||||||
|
@ -229,7 +229,7 @@ export function SupplierPartTable({ params }: { params: any }): ReactNode {
|
|||||||
manufacturer_detail: true
|
manufacturer_detail: true
|
||||||
},
|
},
|
||||||
rowActions: rowActions,
|
rowActions: rowActions,
|
||||||
customActionGroups: tableActions
|
tableActions: tableActions
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
import { ApiPaths } from '../../../enums/ApiEndpoints';
|
import { ApiPaths } from '../../../enums/ApiEndpoints';
|
||||||
import { ModelType } from '../../../enums/ModelType';
|
import { ModelType } from '../../../enums/ModelType';
|
||||||
|
import { UserRoles } from '../../../enums/Roles';
|
||||||
|
import { notYetImplemented } from '../../../functions/notifications';
|
||||||
import { useTable } from '../../../hooks/UseTable';
|
import { useTable } from '../../../hooks/UseTable';
|
||||||
import { apiUrl } from '../../../states/ApiState';
|
import { apiUrl } from '../../../states/ApiState';
|
||||||
|
import { useUserState } from '../../../states/UserState';
|
||||||
|
import { AddItemButton } from '../../buttons/AddItemButton';
|
||||||
import { Thumbnail } from '../../images/Thumbnail';
|
import { Thumbnail } from '../../images/Thumbnail';
|
||||||
import {
|
import {
|
||||||
CreationDateColumn,
|
CreationDateColumn,
|
||||||
@ -27,6 +31,7 @@ import { InvenTreeTable } from '../InvenTreeTable';
|
|||||||
|
|
||||||
export function ReturnOrderTable({ params }: { params?: any }) {
|
export function ReturnOrderTable({ params }: { params?: any }) {
|
||||||
const table = useTable('return-orders');
|
const table = useTable('return-orders');
|
||||||
|
const user = useUserState();
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
@ -90,6 +95,20 @@ export function ReturnOrderTable({ params }: { params?: any }) {
|
|||||||
];
|
];
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const addReturnOrder = useCallback(() => {
|
||||||
|
notYetImplemented();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const tableActions = useMemo(() => {
|
||||||
|
return [
|
||||||
|
<AddItemButton
|
||||||
|
tooltip={t`Add Return Order`}
|
||||||
|
onClick={addReturnOrder}
|
||||||
|
hidden={!user.hasAddRole(UserRoles.sales_order)}
|
||||||
|
/>
|
||||||
|
];
|
||||||
|
}, [user]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InvenTreeTable
|
<InvenTreeTable
|
||||||
url={apiUrl(ApiPaths.return_order_list)}
|
url={apiUrl(ApiPaths.return_order_list)}
|
||||||
@ -100,7 +119,8 @@ export function ReturnOrderTable({ params }: { params?: any }) {
|
|||||||
...params,
|
...params,
|
||||||
customer_detail: true
|
customer_detail: true
|
||||||
},
|
},
|
||||||
customFilters: tableFilters,
|
tableFilters: tableFilters,
|
||||||
|
tableActions: tableActions,
|
||||||
onRowClick: (row: any) => {
|
onRowClick: (row: any) => {
|
||||||
if (row.pk) {
|
if (row.pk) {
|
||||||
navigate(`/sales/return-order/${row.pk}/`);
|
navigate(`/sales/return-order/${row.pk}/`);
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
import { ApiPaths } from '../../../enums/ApiEndpoints';
|
import { ApiPaths } from '../../../enums/ApiEndpoints';
|
||||||
import { ModelType } from '../../../enums/ModelType';
|
import { ModelType } from '../../../enums/ModelType';
|
||||||
|
import { UserRoles } from '../../../enums/Roles';
|
||||||
|
import { notYetImplemented } from '../../../functions/notifications';
|
||||||
import { useTable } from '../../../hooks/UseTable';
|
import { useTable } from '../../../hooks/UseTable';
|
||||||
import { apiUrl } from '../../../states/ApiState';
|
import { apiUrl } from '../../../states/ApiState';
|
||||||
|
import { useUserState } from '../../../states/UserState';
|
||||||
|
import { AddItemButton } from '../../buttons/AddItemButton';
|
||||||
import { Thumbnail } from '../../images/Thumbnail';
|
import { Thumbnail } from '../../images/Thumbnail';
|
||||||
import {
|
import {
|
||||||
CreationDateColumn,
|
CreationDateColumn,
|
||||||
@ -28,6 +32,7 @@ import { InvenTreeTable } from '../InvenTreeTable';
|
|||||||
|
|
||||||
export function SalesOrderTable({ params }: { params?: any }) {
|
export function SalesOrderTable({ params }: { params?: any }) {
|
||||||
const table = useTable('sales-order');
|
const table = useTable('sales-order');
|
||||||
|
const user = useUserState();
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
@ -91,6 +96,20 @@ export function SalesOrderTable({ params }: { params?: any }) {
|
|||||||
];
|
];
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const addSalesOrder = useCallback(() => {
|
||||||
|
notYetImplemented();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const tableActions = useMemo(() => {
|
||||||
|
return [
|
||||||
|
<AddItemButton
|
||||||
|
tooltip={t`Add Sales Order`}
|
||||||
|
onClick={addSalesOrder}
|
||||||
|
hidden={!user.hasAddRole(UserRoles.sales_order)}
|
||||||
|
/>
|
||||||
|
];
|
||||||
|
}, [user]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InvenTreeTable
|
<InvenTreeTable
|
||||||
url={apiUrl(ApiPaths.sales_order_list)}
|
url={apiUrl(ApiPaths.sales_order_list)}
|
||||||
@ -101,7 +120,8 @@ export function SalesOrderTable({ params }: { params?: any }) {
|
|||||||
...params,
|
...params,
|
||||||
customer_detail: true
|
customer_detail: true
|
||||||
},
|
},
|
||||||
customFilters: tableFilters,
|
tableFilters: tableFilters,
|
||||||
|
tableActions: tableActions,
|
||||||
onRowClick: (row: any) => {
|
onRowClick: (row: any) => {
|
||||||
if (row.pk) {
|
if (row.pk) {
|
||||||
navigate(`/sales/sales-order/${row.pk}/`);
|
navigate(`/sales/sales-order/${row.pk}/`);
|
||||||
|
@ -66,7 +66,7 @@ export function CurrencyTable() {
|
|||||||
tableState={table}
|
tableState={table}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
props={{
|
props={{
|
||||||
customActionGroups: tableActions,
|
tableActions: tableActions,
|
||||||
dataFormatter: (data) => {
|
dataFormatter: (data) => {
|
||||||
let rates = data?.exchange_rates ?? {};
|
let rates = data?.exchange_rates ?? {};
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ export default function CustomUnitsTable() {
|
|||||||
columns={columns}
|
columns={columns}
|
||||||
props={{
|
props={{
|
||||||
rowActions: rowActions,
|
rowActions: rowActions,
|
||||||
customActionGroups: tableActions
|
tableActions: tableActions
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -166,7 +166,7 @@ export function GroupTable() {
|
|||||||
columns={columns}
|
columns={columns}
|
||||||
props={{
|
props={{
|
||||||
rowActions: rowActions,
|
rowActions: rowActions,
|
||||||
customActionGroups: tableActions,
|
tableActions: tableActions,
|
||||||
onRowClick: (record) => openDetailDrawer(record.pk)
|
onRowClick: (record) => openDetailDrawer(record.pk)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -106,7 +106,7 @@ export default function ProjectCodeTable() {
|
|||||||
columns={columns}
|
columns={columns}
|
||||||
props={{
|
props={{
|
||||||
rowActions: rowActions,
|
rowActions: rowActions,
|
||||||
customActionGroups: tableActions
|
tableActions: tableActions
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -261,7 +261,7 @@ export function UserTable() {
|
|||||||
columns={columns}
|
columns={columns}
|
||||||
props={{
|
props={{
|
||||||
rowActions: rowActions,
|
rowActions: rowActions,
|
||||||
customActionGroups: tableActions,
|
tableActions: tableActions,
|
||||||
onRowClick: (record) => openDetailDrawer(record.pk)
|
onRowClick: (record) => openDetailDrawer(record.pk)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -344,7 +344,7 @@ export function StockItemTable({ params = {} }: { params?: any }) {
|
|||||||
props={{
|
props={{
|
||||||
enableDownload: true,
|
enableDownload: true,
|
||||||
enableSelection: true,
|
enableSelection: true,
|
||||||
customFilters: tableFilters,
|
tableFilters: tableFilters,
|
||||||
onRowClick: (record) => navigate(`/stock/item/${record.pk}`),
|
onRowClick: (record) => navigate(`/stock/item/${record.pk}`),
|
||||||
params: {
|
params: {
|
||||||
...params,
|
...params,
|
||||||
|
@ -1,21 +1,28 @@
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
import { ApiPaths } from '../../../enums/ApiEndpoints';
|
import { ApiPaths } from '../../../enums/ApiEndpoints';
|
||||||
|
import { UserRoles } from '../../../enums/Roles';
|
||||||
|
import { stockLocationFields } from '../../../forms/StockForms';
|
||||||
|
import { openCreateApiForm, openEditApiForm } from '../../../functions/forms';
|
||||||
import { useTable } from '../../../hooks/UseTable';
|
import { useTable } from '../../../hooks/UseTable';
|
||||||
import { apiUrl } from '../../../states/ApiState';
|
import { apiUrl } from '../../../states/ApiState';
|
||||||
|
import { useUserState } from '../../../states/UserState';
|
||||||
|
import { AddItemButton } from '../../buttons/AddItemButton';
|
||||||
import { YesNoButton } from '../../items/YesNoButton';
|
import { YesNoButton } from '../../items/YesNoButton';
|
||||||
import { TableColumn } from '../Column';
|
import { TableColumn } from '../Column';
|
||||||
import { DescriptionColumn } from '../ColumnRenderers';
|
import { DescriptionColumn } from '../ColumnRenderers';
|
||||||
import { TableFilter } from '../Filter';
|
import { TableFilter } from '../Filter';
|
||||||
import { InvenTreeTable } from '../InvenTreeTable';
|
import { InvenTreeTable } from '../InvenTreeTable';
|
||||||
|
import { RowEditAction } from '../RowActions';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stock location table
|
* Stock location table
|
||||||
*/
|
*/
|
||||||
export function StockLocationTable({ params = {} }: { params?: any }) {
|
export function StockLocationTable({ parentId }: { parentId?: any }) {
|
||||||
const table = useTable('stocklocation');
|
const table = useTable('stocklocation');
|
||||||
|
const user = useUserState();
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
@ -85,7 +92,63 @@ export function StockLocationTable({ params = {} }: { params?: any }) {
|
|||||||
render: (record: any) => record.location_type_detail?.name
|
render: (record: any) => record.location_type_detail?.name
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}, [params]);
|
}, []);
|
||||||
|
|
||||||
|
const addLocation = useCallback(() => {
|
||||||
|
let fields = stockLocationFields({});
|
||||||
|
|
||||||
|
if (parentId) {
|
||||||
|
fields['parent'].value = parentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
openCreateApiForm({
|
||||||
|
url: apiUrl(ApiPaths.stock_location_list),
|
||||||
|
title: t`Add Stock Location`,
|
||||||
|
fields: fields,
|
||||||
|
onFormSuccess(data: any) {
|
||||||
|
if (data.pk) {
|
||||||
|
navigate(`/stock/location/${data.pk}`);
|
||||||
|
} else {
|
||||||
|
table.refreshTable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, [parentId]);
|
||||||
|
|
||||||
|
const tableActions = useMemo(() => {
|
||||||
|
let can_add = user.hasAddRole(UserRoles.stock_location);
|
||||||
|
|
||||||
|
return [
|
||||||
|
<AddItemButton
|
||||||
|
tooltip={t`Add Stock Location`}
|
||||||
|
onClick={addLocation}
|
||||||
|
disabled={!can_add}
|
||||||
|
/>
|
||||||
|
];
|
||||||
|
}, [user]);
|
||||||
|
|
||||||
|
const rowActions = useCallback(
|
||||||
|
(record: any) => {
|
||||||
|
let can_edit = user.hasChangeRole(UserRoles.stock_location);
|
||||||
|
|
||||||
|
return [
|
||||||
|
RowEditAction({
|
||||||
|
hidden: !can_edit,
|
||||||
|
onClick: () => {
|
||||||
|
openEditApiForm({
|
||||||
|
url: ApiPaths.stock_location_list,
|
||||||
|
pk: record.pk,
|
||||||
|
title: t`Edit Stock Location`,
|
||||||
|
fields: stockLocationFields({}),
|
||||||
|
successMessage: t`Stock location updated`,
|
||||||
|
onFormSuccess: table.refreshTable
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
];
|
||||||
|
},
|
||||||
|
[user]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InvenTreeTable
|
<InvenTreeTable
|
||||||
@ -94,8 +157,12 @@ export function StockLocationTable({ params = {} }: { params?: any }) {
|
|||||||
columns={tableColumns}
|
columns={tableColumns}
|
||||||
props={{
|
props={{
|
||||||
enableDownload: true,
|
enableDownload: true,
|
||||||
params: params,
|
params: {
|
||||||
customFilters: tableFilters,
|
parent: parentId ?? 'null'
|
||||||
|
},
|
||||||
|
tableFilters: tableFilters,
|
||||||
|
tableActions: tableActions,
|
||||||
|
rowActions: rowActions,
|
||||||
onRowClick: (record) => {
|
onRowClick: (record) => {
|
||||||
navigate(`/stock/location/${record.pk}`);
|
navigate(`/stock/location/${record.pk}`);
|
||||||
}
|
}
|
||||||
|
@ -133,3 +133,19 @@ export function useEditStockItem({
|
|||||||
onFormSuccess: callback
|
onFormSuccess: callback
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function stockLocationFields({}: {}): ApiFormFieldSet {
|
||||||
|
let fields: ApiFormFieldSet = {
|
||||||
|
parent: {
|
||||||
|
description: t`Parent stock location`,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
name: {},
|
||||||
|
description: {},
|
||||||
|
structural: {},
|
||||||
|
external: {},
|
||||||
|
location_type: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
@ -64,13 +64,7 @@ export default function CategoryDetail({}: {}) {
|
|||||||
name: 'subcategories',
|
name: 'subcategories',
|
||||||
label: t`Part Categories`,
|
label: t`Part Categories`,
|
||||||
icon: <IconSitemap />,
|
icon: <IconSitemap />,
|
||||||
content: (
|
content: <PartCategoryTable parentId={id} />
|
||||||
<PartCategoryTable
|
|
||||||
params={{
|
|
||||||
parent: id
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'parameters',
|
name: 'parameters',
|
||||||
|
@ -53,13 +53,7 @@ export default function Stock() {
|
|||||||
name: 'sublocations',
|
name: 'sublocations',
|
||||||
label: t`Stock Locations`,
|
label: t`Stock Locations`,
|
||||||
icon: <IconSitemap />,
|
icon: <IconSitemap />,
|
||||||
content: (
|
content: <StockLocationTable parentId={id} />
|
||||||
<StockLocationTable
|
|
||||||
params={{
|
|
||||||
parent: id
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}, [location, id]);
|
}, [location, id]);
|
||||||
|
Loading…
Reference in New Issue
Block a user