From ec2a66e7a51ac2a5cc88ceb01568da35694e947e Mon Sep 17 00:00:00 2001 From: Oliver Date: Fri, 2 Feb 2024 10:11:37 +1100 Subject: [PATCH] Request column names from server when loading table (#6375) * Request column names from server when loading table - As these are translated by the server, we can make use of them on the client side! - Reduces duplication of translated titles * Move tables up one level * Cache translated table column names * Clear table column cache whenever we change locale context * Fix cache behavioue * Enforce titleCase for table column names * Refactor BuildOrder table * Refactor Company table * Refactor order tables * More refactoring - Refactoring more columns * Update more tables * Refactor BomTable * Remove toTitleCase - We will rely on the server-side translations! * Remove debug messages * Update src/frontend/src/tables/InvenTreeTable.tsx Co-authored-by: Matthias Mair * Cleanup * Update docstring * Cleanup * Support nested fields with dot notation - Powerful code reuse is powerful * Complete refactor for BuildLine table - Add some missing field descriptors on the backend * Cleanup hooks a bit * Update BomTable * Allow table filters to make use of the same info * Add ReferenceColumn helper * Use queryParams when fetching table OPTIONS - Required to ensure the same columns are fetched * More refactoring * Fix ProjectCodeTable * Code cleanup * Fix unused var --------- Co-authored-by: Matthias Mair --- InvenTree/build/serializers.py | 26 ++- InvenTree/part/serializers.py | 8 +- .../src/components/images/DetailsImage.tsx | 2 +- src/frontend/src/contexts/LanguageContext.tsx | 3 + src/frontend/src/functions/forms.tsx | 1 - src/frontend/src/hooks/UseTable.tsx | 2 +- .../Index/Settings/AdminCenter/Index.tsx | 11 +- .../AdminCenter/PluginManagementPanel.tsx | 4 +- .../AdminCenter/TaskManagementPanel.tsx | 8 +- .../AdminCenter/UserManagementPanel.tsx | 4 +- .../pages/Index/Settings/SystemSettings.tsx | 2 +- src/frontend/src/pages/Notifications.tsx | 2 +- src/frontend/src/pages/build/BuildDetail.tsx | 8 +- src/frontend/src/pages/build/BuildIndex.tsx | 2 +- .../src/pages/company/CompanyDetail.tsx | 18 +- .../pages/company/ManufacturerPartDetail.tsx | 6 +- .../src/pages/company/SupplierPartDetail.tsx | 2 +- .../src/pages/part/CategoryDetail.tsx | 4 +- src/frontend/src/pages/part/PartDetail.tsx | 40 ++-- .../pages/purchasing/PurchaseOrderDetail.tsx | 6 +- .../src/pages/purchasing/PurchasingIndex.tsx | 4 +- .../src/pages/sales/ReturnOrderDetail.tsx | 2 +- src/frontend/src/pages/sales/SalesIndex.tsx | 6 +- .../src/pages/sales/SalesOrderDetail.tsx | 4 +- .../src/pages/stock/LocationDetail.tsx | 4 +- src/frontend/src/pages/stock/StockDetail.tsx | 4 +- src/frontend/src/states/LocalState.tsx | 22 ++ .../src/{components => }/tables/Column.tsx | 2 +- .../tables/ColumnRenderers.tsx | 40 ++-- .../{components => }/tables/ColumnSelect.tsx | 2 +- .../src/{components => }/tables/Details.tsx | 12 +- .../tables/DownloadAction.tsx | 0 .../src/{components => }/tables/Filter.tsx | 6 +- .../tables/FilterSelectDrawer.tsx | 4 +- .../tables/InvenTreeTable.tsx | 211 ++++++++++++------ .../{components => }/tables/ItemDetails.tsx | 7 +- .../{components => }/tables/RowActions.tsx | 2 +- .../src/{components => }/tables/Search.tsx | 5 +- .../tables/TableHoverCard.tsx | 0 .../{components => }/tables/bom/BomTable.tsx | 73 +++--- .../tables/bom/UsedInTable.tsx | 24 +- .../tables/build/BuildLineTable.tsx | 36 ++- .../tables/build/BuildOrderTable.tsx | 46 ++-- .../tables/company/AddressTable.tsx | 27 +-- .../tables/company/CompanyTable.tsx | 21 +- .../tables/company/ContactTable.tsx | 20 +- .../tables/general/AttachmentTable.tsx | 19 +- .../notifications/NotificationsTable.tsx | 6 +- .../tables/part/PartCategoryTable.tsx | 26 +-- .../tables/part/PartParameterTable.tsx | 44 ++-- .../part/PartParameterTemplateTable.tsx | 24 +- .../tables/part/PartTable.tsx | 23 +- .../tables/part/PartTestTemplateTable.tsx | 29 +-- .../tables/part/PartThumbTable.tsx | 8 +- .../tables/part/PartVariantTable.tsx | 0 .../tables/part/RelatedPartTable.tsx | 18 +- .../tables/plugin/PluginErrorTable.tsx | 6 +- .../tables/plugin/PluginListTable.tsx | 31 +-- .../ManufacturerPartParameterTable.tsx | 14 +- .../purchasing/ManufacturerPartTable.tsx | 26 +-- .../purchasing/PurchaseOrderLineItemTable.tsx | 35 ++- .../tables/purchasing/PurchaseOrderTable.tsx | 34 ++- .../tables/purchasing/SupplierPartTable.tsx | 44 ++-- .../tables/sales/ReturnOrderTable.tsx | 39 ++-- .../tables/sales/SalesOrderTable.tsx | 31 ++- .../tables/settings/CurrencyTable.tsx | 10 +- .../tables/settings/CustomUnitsTable.tsx | 19 +- .../tables/settings/ErrorTable.tsx | 10 +- .../tables/settings/FailedTasksTable.tsx | 8 +- .../tables/settings/GroupTable.tsx | 18 +- .../tables/settings/PendingTasksTable.tsx | 6 +- .../tables/settings/ProjectCodeTable.tsx | 19 +- .../tables/settings/ScheduledTasksTable.tsx | 6 +- .../tables/settings/UserTable.tsx | 40 ++-- .../tables/stock/StockItemTable.tsx | 38 ++-- .../tables/stock/StockLocationTable.tsx | 51 ++--- src/frontend/src/views/DesktopAppView.tsx | 1 - 77 files changed, 698 insertions(+), 728 deletions(-) rename src/frontend/src/{components => }/tables/Column.tsx (85%) rename src/frontend/src/{components => }/tables/ColumnRenderers.tsx (83%) rename src/frontend/src/{components => }/tables/ColumnSelect.tsx (93%) rename src/frontend/src/{components => }/tables/Details.tsx (97%) rename src/frontend/src/{components => }/tables/DownloadAction.tsx (100%) rename src/frontend/src/{components => }/tables/Filter.tsx (94%) rename src/frontend/src/{components => }/tables/FilterSelectDrawer.tsx (98%) rename src/frontend/src/{components => }/tables/InvenTreeTable.tsx (74%) rename src/frontend/src/{components => }/tables/ItemDetails.tsx (94%) rename src/frontend/src/{components => }/tables/RowActions.tsx (98%) rename src/frontend/src/{components => }/tables/Search.tsx (84%) rename src/frontend/src/{components => }/tables/TableHoverCard.tsx (100%) rename src/frontend/src/{components => }/tables/bom/BomTable.tsx (83%) rename src/frontend/src/{components => }/tables/bom/UsedInTable.tsx (77%) rename src/frontend/src/{components => }/tables/build/BuildLineTable.tsx (86%) rename src/frontend/src/{components => }/tables/build/BuildOrderTable.tsx (78%) rename src/frontend/src/{components => }/tables/company/AddressTable.tsx (86%) rename src/frontend/src/{components => }/tables/company/CompanyTable.tsx (79%) rename src/frontend/src/{components => }/tables/company/ContactTable.tsx (86%) rename src/frontend/src/{components => }/tables/general/AttachmentTable.tsx (93%) rename src/frontend/src/{components => }/tables/notifications/NotificationsTable.tsx (86%) rename src/frontend/src/{components => }/tables/part/PartCategoryTable.tsx (83%) rename src/frontend/src/{components => }/tables/part/PartParameterTable.tsx (81%) rename src/frontend/src/{components => }/tables/part/PartParameterTemplateTable.tsx (85%) rename src/frontend/src/{components => }/tables/part/PartTable.tsx (92%) rename src/frontend/src/{components => }/tables/part/PartTestTemplateTable.tsx (82%) rename src/frontend/src/{components => }/tables/part/PartThumbTable.tsx (96%) rename src/frontend/src/{components => }/tables/part/PartVariantTable.tsx (100%) rename src/frontend/src/{components => }/tables/part/RelatedPartTable.tsx (87%) rename src/frontend/src/{components => }/tables/plugin/PluginErrorTable.tsx (89%) rename src/frontend/src/{components => }/tables/plugin/PluginListTable.tsx (93%) rename src/frontend/src/{components => }/tables/purchasing/ManufacturerPartParameterTable.tsx (84%) rename src/frontend/src/{components => }/tables/purchasing/ManufacturerPartTable.tsx (82%) rename src/frontend/src/{components => }/tables/purchasing/PurchaseOrderLineItemTable.tsx (88%) rename src/frontend/src/{components => }/tables/purchasing/PurchaseOrderTable.tsx (78%) rename src/frontend/src/{components => }/tables/purchasing/SupplierPartTable.tsx (84%) rename src/frontend/src/{components => }/tables/sales/ReturnOrderTable.tsx (73%) rename src/frontend/src/{components => }/tables/sales/SalesOrderTable.tsx (79%) rename src/frontend/src/{components => }/tables/settings/CurrencyTable.tsx (87%) rename src/frontend/src/{components => }/tables/settings/CustomUnitsTable.tsx (84%) rename src/frontend/src/{components => }/tables/settings/ErrorTable.tsx (88%) rename src/frontend/src/{components => }/tables/settings/FailedTasksTable.tsx (88%) rename src/frontend/src/{components => }/tables/settings/GroupTable.tsx (88%) rename src/frontend/src/{components => }/tables/settings/PendingTasksTable.tsx (86%) rename src/frontend/src/{components => }/tables/settings/ProjectCodeTable.tsx (84%) rename src/frontend/src/{components => }/tables/settings/ScheduledTasksTable.tsx (89%) rename src/frontend/src/{components => }/tables/settings/UserTable.tsx (86%) rename src/frontend/src/{components => }/tables/stock/StockItemTable.tsx (92%) rename src/frontend/src/{components => }/tables/stock/StockLocationTable.tsx (75%) diff --git a/InvenTree/build/serializers.py b/InvenTree/build/serializers.py index 19686f58cd..cf330760b4 100644 --- a/InvenTree/build/serializers.py +++ b/InvenTree/build/serializers.py @@ -1075,16 +1075,34 @@ class BuildLineSerializer(InvenTreeModelSerializer): quantity = serializers.FloatField() + bom_item = serializers.PrimaryKeyRelatedField(label=_('Bom Item'), read_only=True) + # Foreign key fields bom_item_detail = BomItemSerializer(source='bom_item', many=False, read_only=True, pricing=False) part_detail = PartSerializer(source='bom_item.sub_part', many=False, read_only=True, pricing=False) allocations = BuildItemSerializer(many=True, read_only=True) # Annotated (calculated) fields - allocated = serializers.FloatField(read_only=True) - on_order = serializers.FloatField(read_only=True) - in_production = serializers.FloatField(read_only=True) - available_stock = serializers.FloatField(read_only=True) + allocated = serializers.FloatField( + label=_('Allocated Stock'), + read_only=True + ) + + on_order = serializers.FloatField( + label=_('On Order'), + read_only=True + ) + + in_production = serializers.FloatField( + label=_('In Production'), + read_only=True + ) + + available_stock = serializers.FloatField( + label=_('Available Stock'), + read_only=True + ) + available_substitute_stock = serializers.FloatField(read_only=True) available_variant_stock = serializers.FloatField(read_only=True) total_available_stock = serializers.FloatField(read_only=True) diff --git a/InvenTree/part/serializers.py b/InvenTree/part/serializers.py index c26d60c2df..bbd0f9f6bf 100644 --- a/InvenTree/part/serializers.py +++ b/InvenTree/part/serializers.py @@ -1408,8 +1408,9 @@ class BomItemSerializer(InvenTree.serializers.InvenTreeModelSerializer): sub_part_detail = PartBriefSerializer(source='sub_part', many=False, read_only=True) - on_order = serializers.FloatField(read_only=True) - building = serializers.FloatField(read_only=True) + on_order = serializers.FloatField(label=_('On Order'), read_only=True) + + building = serializers.FloatField(label=_('In Production'), read_only=True) # Cached pricing fields pricing_min = InvenTree.serializers.InvenTreeMoneySerializer( @@ -1420,7 +1421,8 @@ class BomItemSerializer(InvenTree.serializers.InvenTreeModelSerializer): ) # Annotated fields for available stock - available_stock = serializers.FloatField(read_only=True) + available_stock = serializers.FloatField(label=_('Available Stock'), read_only=True) + available_substitute_stock = serializers.FloatField(read_only=True) available_variant_stock = serializers.FloatField(read_only=True) diff --git a/src/frontend/src/components/images/DetailsImage.tsx b/src/frontend/src/components/images/DetailsImage.tsx index b446d0abbf..44f896e031 100644 --- a/src/frontend/src/components/images/DetailsImage.tsx +++ b/src/frontend/src/components/images/DetailsImage.tsx @@ -18,8 +18,8 @@ import { api } from '../../App'; import { UserRoles } from '../../enums/Roles'; import { InvenTreeIcon } from '../../functions/icons'; import { useUserState } from '../../states/UserState'; +import { PartThumbTable } from '../../tables/part/PartThumbTable'; import { ActionButton } from '../buttons/ActionButton'; -import { PartThumbTable } from '../tables/part/PartThumbTable'; import { ApiImage } from './ApiImage'; /** diff --git a/src/frontend/src/contexts/LanguageContext.tsx b/src/frontend/src/contexts/LanguageContext.tsx index 19cbd2a088..4780d1006a 100644 --- a/src/frontend/src/contexts/LanguageContext.tsx +++ b/src/frontend/src/contexts/LanguageContext.tsx @@ -92,6 +92,9 @@ export function LanguageContext({ children }: { children: JSX.Element }) { // Reload server state (refresh status codes) useServerApiState.getState().fetchServerApiState(); + + // Clear out cached table column names + useLocalState.getState().clearTableColumnNames(); }) .catch((err) => { console.error('Failed loading translations', err); diff --git a/src/frontend/src/functions/forms.tsx b/src/frontend/src/functions/forms.tsx index 0807f449dd..4406facfe9 100644 --- a/src/frontend/src/functions/forms.tsx +++ b/src/frontend/src/functions/forms.tsx @@ -263,7 +263,6 @@ export function openModalApiForm(props: OpenApiFormProps) { }); }) .catch((error) => { - console.log('Error:', error); if (error.response) { invalidResponse(error.response.status); } else { diff --git a/src/frontend/src/hooks/UseTable.tsx b/src/frontend/src/hooks/UseTable.tsx index 15efe7ca3a..7a0e66a0ce 100644 --- a/src/frontend/src/hooks/UseTable.tsx +++ b/src/frontend/src/hooks/UseTable.tsx @@ -1,7 +1,7 @@ import { randomId, useLocalStorage } from '@mantine/hooks'; import { useCallback, useState } from 'react'; -import { TableFilter } from '../components/tables/Filter'; +import { TableFilter } from '../tables/Filter'; /* * Type definition for representing the state of a table: diff --git a/src/frontend/src/pages/Index/Settings/AdminCenter/Index.tsx b/src/frontend/src/pages/Index/Settings/AdminCenter/Index.tsx index 3aa646ee22..77a6716ffe 100644 --- a/src/frontend/src/pages/Index/Settings/AdminCenter/Index.tsx +++ b/src/frontend/src/pages/Index/Settings/AdminCenter/Index.tsx @@ -30,22 +30,19 @@ const PluginManagementPanel = Loadable( ); const ErrorReportTable = Loadable( - lazy(() => import('../../../../components/tables/settings/ErrorTable')) + lazy(() => import('../../../../tables/settings/ErrorTable')) ); const ProjectCodeTable = Loadable( - lazy(() => import('../../../../components/tables/settings/ProjectCodeTable')) + lazy(() => import('../../../../tables/settings/ProjectCodeTable')) ); const CustomUnitsTable = Loadable( - lazy(() => import('../../../../components/tables/settings/CustomUnitsTable')) + lazy(() => import('../../../../tables/settings/CustomUnitsTable')) ); const PartParameterTemplateTable = Loadable( - lazy( - () => - import('../../../../components/tables/part/PartParameterTemplateTable') - ) + lazy(() => import('../../../../tables/part/PartParameterTemplateTable')) ); export default function AdminCenter() { diff --git a/src/frontend/src/pages/Index/Settings/AdminCenter/PluginManagementPanel.tsx b/src/frontend/src/pages/Index/Settings/AdminCenter/PluginManagementPanel.tsx index c6ccc87ce2..8052d1310d 100644 --- a/src/frontend/src/pages/Index/Settings/AdminCenter/PluginManagementPanel.tsx +++ b/src/frontend/src/pages/Index/Settings/AdminCenter/PluginManagementPanel.tsx @@ -3,9 +3,9 @@ import { Alert, Stack, Title } from '@mantine/core'; import { IconInfoCircle } from '@tabler/icons-react'; import { GlobalSettingList } from '../../../../components/settings/SettingList'; -import { PluginErrorTable } from '../../../../components/tables/plugin/PluginErrorTable'; -import { PluginListTable } from '../../../../components/tables/plugin/PluginListTable'; import { useServerApiState } from '../../../../states/ApiState'; +import { PluginErrorTable } from '../../../../tables/plugin/PluginErrorTable'; +import { PluginListTable } from '../../../../tables/plugin/PluginListTable'; export default function PluginManagementPanel() { const pluginsEnabled = useServerApiState( diff --git a/src/frontend/src/pages/Index/Settings/AdminCenter/TaskManagementPanel.tsx b/src/frontend/src/pages/Index/Settings/AdminCenter/TaskManagementPanel.tsx index d0166e4d23..d8f5213fe0 100644 --- a/src/frontend/src/pages/Index/Settings/AdminCenter/TaskManagementPanel.tsx +++ b/src/frontend/src/pages/Index/Settings/AdminCenter/TaskManagementPanel.tsx @@ -6,17 +6,15 @@ import { StylishText } from '../../../../components/items/StylishText'; import { Loadable } from '../../../../functions/loading'; const PendingTasksTable = Loadable( - lazy(() => import('../../../../components/tables/settings/PendingTasksTable')) + lazy(() => import('../../../../tables/settings/PendingTasksTable')) ); const ScheduledTasksTable = Loadable( - lazy( - () => import('../../../../components/tables/settings/ScheduledTasksTable') - ) + lazy(() => import('../../../../tables/settings/ScheduledTasksTable')) ); const FailedTasksTable = Loadable( - lazy(() => import('../../../../components/tables/settings/FailedTasksTable')) + lazy(() => import('../../../../tables/settings/FailedTasksTable')) ); export default function TaskManagementPanel() { diff --git a/src/frontend/src/pages/Index/Settings/AdminCenter/UserManagementPanel.tsx b/src/frontend/src/pages/Index/Settings/AdminCenter/UserManagementPanel.tsx index c6d1406a4e..8b0b1c400e 100644 --- a/src/frontend/src/pages/Index/Settings/AdminCenter/UserManagementPanel.tsx +++ b/src/frontend/src/pages/Index/Settings/AdminCenter/UserManagementPanel.tsx @@ -3,8 +3,8 @@ import { Anchor, Divider, Group, Stack, Text, Title } from '@mantine/core'; import { Link } from 'react-router-dom'; import { GlobalSettingList } from '../../../../components/settings/SettingList'; -import { GroupTable } from '../../../../components/tables/settings/GroupTable'; -import { UserTable } from '../../../../components/tables/settings/UserTable'; +import { GroupTable } from '../../../../tables/settings/GroupTable'; +import { UserTable } from '../../../../tables/settings/UserTable'; export default function UserManagementPanel() { return ( diff --git a/src/frontend/src/pages/Index/Settings/SystemSettings.tsx b/src/frontend/src/pages/Index/Settings/SystemSettings.tsx index 8a2f163fb3..0f3cdfdc09 100644 --- a/src/frontend/src/pages/Index/Settings/SystemSettings.tsx +++ b/src/frontend/src/pages/Index/Settings/SystemSettings.tsx @@ -23,8 +23,8 @@ import { StylishText } from '../../../components/items/StylishText'; import { PanelGroup, PanelType } from '../../../components/nav/PanelGroup'; import { SettingsHeader } from '../../../components/nav/SettingsHeader'; import { GlobalSettingList } from '../../../components/settings/SettingList'; -import { CurrencyTable } from '../../../components/tables/settings/CurrencyTable'; import { useServerApiState } from '../../../states/ApiState'; +import { CurrencyTable } from '../../../tables/settings/CurrencyTable'; /** * System settings page diff --git a/src/frontend/src/pages/Notifications.tsx b/src/frontend/src/pages/Notifications.tsx index 756dbf2826..b70fc59c22 100644 --- a/src/frontend/src/pages/Notifications.tsx +++ b/src/frontend/src/pages/Notifications.tsx @@ -12,10 +12,10 @@ import { useMemo } from 'react'; import { api } from '../App'; import { PageDetail } from '../components/nav/PageDetail'; import { PanelGroup } from '../components/nav/PanelGroup'; -import { NotificationTable } from '../components/tables/notifications/NotificationsTable'; import { ApiEndpoints } from '../enums/ApiEndpoints'; import { useTable } from '../hooks/UseTable'; import { apiUrl } from '../states/ApiState'; +import { NotificationTable } from '../tables/notifications/NotificationsTable'; export default function NotificationsPage() { const unreadTable = useTable('unreadnotifications'); diff --git a/src/frontend/src/pages/build/BuildDetail.tsx b/src/frontend/src/pages/build/BuildDetail.tsx index 62415eeb1b..5f32b55fc5 100644 --- a/src/frontend/src/pages/build/BuildDetail.tsx +++ b/src/frontend/src/pages/build/BuildDetail.tsx @@ -28,10 +28,6 @@ import { import { PageDetail } from '../../components/nav/PageDetail'; import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; import { StatusRenderer } from '../../components/render/StatusRenderer'; -import BuildLineTable from '../../components/tables/build/BuildLineTable'; -import { BuildOrderTable } from '../../components/tables/build/BuildOrderTable'; -import { AttachmentTable } from '../../components/tables/general/AttachmentTable'; -import { StockItemTable } from '../../components/tables/stock/StockItemTable'; import { NotesEditor } from '../../components/widgets/MarkdownEditor'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ModelType } from '../../enums/ModelType'; @@ -41,6 +37,10 @@ import { useEditApiFormModal } from '../../hooks/UseForm'; import { useInstance } from '../../hooks/UseInstance'; import { apiUrl } from '../../states/ApiState'; import { useUserState } from '../../states/UserState'; +import BuildLineTable from '../../tables/build/BuildLineTable'; +import { BuildOrderTable } from '../../tables/build/BuildOrderTable'; +import { AttachmentTable } from '../../tables/general/AttachmentTable'; +import { StockItemTable } from '../../tables/stock/StockItemTable'; /** * Detail page for a single Build Order diff --git a/src/frontend/src/pages/build/BuildIndex.tsx b/src/frontend/src/pages/build/BuildIndex.tsx index 320ce6d233..557de69c87 100644 --- a/src/frontend/src/pages/build/BuildIndex.tsx +++ b/src/frontend/src/pages/build/BuildIndex.tsx @@ -2,7 +2,7 @@ import { t } from '@lingui/macro'; import { Stack } from '@mantine/core'; import { PageDetail } from '../../components/nav/PageDetail'; -import { BuildOrderTable } from '../../components/tables/build/BuildOrderTable'; +import { BuildOrderTable } from '../../tables/build/BuildOrderTable'; /** * Build Order index page diff --git a/src/frontend/src/pages/company/CompanyDetail.tsx b/src/frontend/src/pages/company/CompanyDetail.tsx index 4c6bd13832..6728cb1caf 100644 --- a/src/frontend/src/pages/company/CompanyDetail.tsx +++ b/src/frontend/src/pages/company/CompanyDetail.tsx @@ -27,15 +27,6 @@ import { Breadcrumb } from '../../components/nav/BreadcrumbList'; import { PageDetail } from '../../components/nav/PageDetail'; import { PanelGroup } from '../../components/nav/PanelGroup'; import { PanelType } from '../../components/nav/PanelGroup'; -import { AddressTable } from '../../components/tables/company/AddressTable'; -import { ContactTable } from '../../components/tables/company/ContactTable'; -import { AttachmentTable } from '../../components/tables/general/AttachmentTable'; -import { ManufacturerPartTable } from '../../components/tables/purchasing/ManufacturerPartTable'; -import { PurchaseOrderTable } from '../../components/tables/purchasing/PurchaseOrderTable'; -import { SupplierPartTable } from '../../components/tables/purchasing/SupplierPartTable'; -import { ReturnOrderTable } from '../../components/tables/sales/ReturnOrderTable'; -import { SalesOrderTable } from '../../components/tables/sales/SalesOrderTable'; -import { StockItemTable } from '../../components/tables/stock/StockItemTable'; import { NotesEditor } from '../../components/widgets/MarkdownEditor'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { UserRoles } from '../../enums/Roles'; @@ -44,6 +35,15 @@ import { useEditApiFormModal } from '../../hooks/UseForm'; import { useInstance } from '../../hooks/UseInstance'; import { apiUrl } from '../../states/ApiState'; import { useUserState } from '../../states/UserState'; +import { AddressTable } from '../../tables/company/AddressTable'; +import { ContactTable } from '../../tables/company/ContactTable'; +import { AttachmentTable } from '../../tables/general/AttachmentTable'; +import { ManufacturerPartTable } from '../../tables/purchasing/ManufacturerPartTable'; +import { PurchaseOrderTable } from '../../tables/purchasing/PurchaseOrderTable'; +import { SupplierPartTable } from '../../tables/purchasing/SupplierPartTable'; +import { ReturnOrderTable } from '../../tables/sales/ReturnOrderTable'; +import { SalesOrderTable } from '../../tables/sales/SalesOrderTable'; +import { StockItemTable } from '../../tables/stock/StockItemTable'; export type CompanyDetailProps = { title: string; diff --git a/src/frontend/src/pages/company/ManufacturerPartDetail.tsx b/src/frontend/src/pages/company/ManufacturerPartDetail.tsx index 03e48a7def..17f64d600c 100644 --- a/src/frontend/src/pages/company/ManufacturerPartDetail.tsx +++ b/src/frontend/src/pages/company/ManufacturerPartDetail.tsx @@ -11,11 +11,11 @@ import { useParams } from 'react-router-dom'; import { PageDetail } from '../../components/nav/PageDetail'; import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; -import { AttachmentTable } from '../../components/tables/general/AttachmentTable'; -import ManufacturerPartParameterTable from '../../components/tables/purchasing/ManufacturerPartParameterTable'; -import { SupplierPartTable } from '../../components/tables/purchasing/SupplierPartTable'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { useInstance } from '../../hooks/UseInstance'; +import { AttachmentTable } from '../../tables/general/AttachmentTable'; +import ManufacturerPartParameterTable from '../../tables/purchasing/ManufacturerPartParameterTable'; +import { SupplierPartTable } from '../../tables/purchasing/SupplierPartTable'; export default function ManufacturerPartDetail() { const { id } = useParams(); diff --git a/src/frontend/src/pages/company/SupplierPartDetail.tsx b/src/frontend/src/pages/company/SupplierPartDetail.tsx index d52d8217c2..54b0c652c6 100644 --- a/src/frontend/src/pages/company/SupplierPartDetail.tsx +++ b/src/frontend/src/pages/company/SupplierPartDetail.tsx @@ -11,9 +11,9 @@ import { useParams } from 'react-router-dom'; import { PageDetail } from '../../components/nav/PageDetail'; import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; -import { PurchaseOrderTable } from '../../components/tables/purchasing/PurchaseOrderTable'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { useInstance } from '../../hooks/UseInstance'; +import { PurchaseOrderTable } from '../../tables/purchasing/PurchaseOrderTable'; export default function SupplierPartDetail() { const { id } = useParams(); diff --git a/src/frontend/src/pages/part/CategoryDetail.tsx b/src/frontend/src/pages/part/CategoryDetail.tsx index a2b4602d48..32664a5ff9 100644 --- a/src/frontend/src/pages/part/CategoryDetail.tsx +++ b/src/frontend/src/pages/part/CategoryDetail.tsx @@ -12,10 +12,10 @@ import { PlaceholderPanel } from '../../components/items/Placeholder'; import { PageDetail } from '../../components/nav/PageDetail'; import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; import { PartCategoryTree } from '../../components/nav/PartCategoryTree'; -import { PartCategoryTable } from '../../components/tables/part/PartCategoryTable'; -import { PartListTable } from '../../components/tables/part/PartTable'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { useInstance } from '../../hooks/UseInstance'; +import { PartCategoryTable } from '../../tables/part/PartCategoryTable'; +import { PartListTable } from '../../tables/part/PartTable'; /** * Detail view for a single PartCategory instance. diff --git a/src/frontend/src/pages/part/PartDetail.tsx b/src/frontend/src/pages/part/PartDetail.tsx index 0681ef8547..eab798de80 100644 --- a/src/frontend/src/pages/part/PartDetail.tsx +++ b/src/frontend/src/pages/part/PartDetail.tsx @@ -41,24 +41,6 @@ import { import { PageDetail } from '../../components/nav/PageDetail'; import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; import { PartCategoryTree } from '../../components/nav/PartCategoryTree'; -import { DetailsField } from '../../components/tables/Details'; -import { - DetailsImageType, - ItemDetailFields, - ItemDetails -} from '../../components/tables/ItemDetails'; -import { BomTable } from '../../components/tables/bom/BomTable'; -import { UsedInTable } from '../../components/tables/bom/UsedInTable'; -import { BuildOrderTable } from '../../components/tables/build/BuildOrderTable'; -import { AttachmentTable } from '../../components/tables/general/AttachmentTable'; -import { PartParameterTable } from '../../components/tables/part/PartParameterTable'; -import PartTestTemplateTable from '../../components/tables/part/PartTestTemplateTable'; -import { PartVariantTable } from '../../components/tables/part/PartVariantTable'; -import { RelatedPartTable } from '../../components/tables/part/RelatedPartTable'; -import { ManufacturerPartTable } from '../../components/tables/purchasing/ManufacturerPartTable'; -import { SupplierPartTable } from '../../components/tables/purchasing/SupplierPartTable'; -import { SalesOrderTable } from '../../components/tables/sales/SalesOrderTable'; -import { StockItemTable } from '../../components/tables/stock/StockItemTable'; import { NotesEditor } from '../../components/widgets/MarkdownEditor'; import { formatPriceRange } from '../../defaults/formatters'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; @@ -68,6 +50,24 @@ import { useEditApiFormModal } from '../../hooks/UseForm'; import { useInstance } from '../../hooks/UseInstance'; import { apiUrl } from '../../states/ApiState'; import { useUserState } from '../../states/UserState'; +import { DetailsField } from '../../tables/Details'; +import { + DetailsImageType, + ItemDetailFields, + ItemDetails +} from '../../tables/ItemDetails'; +import { BomTable } from '../../tables/bom/BomTable'; +import { UsedInTable } from '../../tables/bom/UsedInTable'; +import { BuildOrderTable } from '../../tables/build/BuildOrderTable'; +import { AttachmentTable } from '../../tables/general/AttachmentTable'; +import { PartParameterTable } from '../../tables/part/PartParameterTable'; +import PartTestTemplateTable from '../../tables/part/PartTestTemplateTable'; +import { PartVariantTable } from '../../tables/part/PartVariantTable'; +import { RelatedPartTable } from '../../tables/part/RelatedPartTable'; +import { ManufacturerPartTable } from '../../tables/purchasing/ManufacturerPartTable'; +import { SupplierPartTable } from '../../tables/purchasing/SupplierPartTable'; +import { SalesOrderTable } from '../../tables/sales/SalesOrderTable'; +import { StockItemTable } from '../../tables/stock/StockItemTable'; /** * Detail view for a single Part instance @@ -353,7 +353,7 @@ export default function PartDetail() { }); } }); - return data.quantity; + return data?.quantity; } }, { @@ -381,7 +381,7 @@ export default function PartDetail() { }); } }); - return data.user; + return data?.user; } } ]); diff --git a/src/frontend/src/pages/purchasing/PurchaseOrderDetail.tsx b/src/frontend/src/pages/purchasing/PurchaseOrderDetail.tsx index 5b0c222a3c..0464f7d4b5 100644 --- a/src/frontend/src/pages/purchasing/PurchaseOrderDetail.tsx +++ b/src/frontend/src/pages/purchasing/PurchaseOrderDetail.tsx @@ -22,14 +22,14 @@ import { } from '../../components/items/ActionDropdown'; import { PageDetail } from '../../components/nav/PageDetail'; import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; -import { AttachmentTable } from '../../components/tables/general/AttachmentTable'; -import { PurchaseOrderLineItemTable } from '../../components/tables/purchasing/PurchaseOrderLineItemTable'; -import { StockItemTable } from '../../components/tables/stock/StockItemTable'; import { NotesEditor } from '../../components/widgets/MarkdownEditor'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { useInstance } from '../../hooks/UseInstance'; import { apiUrl } from '../../states/ApiState'; import { useUserState } from '../../states/UserState'; +import { AttachmentTable } from '../../tables/general/AttachmentTable'; +import { PurchaseOrderLineItemTable } from '../../tables/purchasing/PurchaseOrderLineItemTable'; +import { StockItemTable } from '../../tables/stock/StockItemTable'; /** * Detail page for a single PurchaseOrder diff --git a/src/frontend/src/pages/purchasing/PurchasingIndex.tsx b/src/frontend/src/pages/purchasing/PurchasingIndex.tsx index ec04a9d907..2a47575ca5 100644 --- a/src/frontend/src/pages/purchasing/PurchasingIndex.tsx +++ b/src/frontend/src/pages/purchasing/PurchasingIndex.tsx @@ -9,8 +9,8 @@ import { useMemo } from 'react'; import { PageDetail } from '../../components/nav/PageDetail'; import { PanelGroup } from '../../components/nav/PanelGroup'; -import { CompanyTable } from '../../components/tables/company/CompanyTable'; -import { PurchaseOrderTable } from '../../components/tables/purchasing/PurchaseOrderTable'; +import { CompanyTable } from '../../tables/company/CompanyTable'; +import { PurchaseOrderTable } from '../../tables/purchasing/PurchaseOrderTable'; export default function PurchasingIndex() { const panels = useMemo(() => { diff --git a/src/frontend/src/pages/sales/ReturnOrderDetail.tsx b/src/frontend/src/pages/sales/ReturnOrderDetail.tsx index e73135961c..d08be33201 100644 --- a/src/frontend/src/pages/sales/ReturnOrderDetail.tsx +++ b/src/frontend/src/pages/sales/ReturnOrderDetail.tsx @@ -6,11 +6,11 @@ import { useParams } from 'react-router-dom'; import { PageDetail } from '../../components/nav/PageDetail'; import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; -import { AttachmentTable } from '../../components/tables/general/AttachmentTable'; import { NotesEditor } from '../../components/widgets/MarkdownEditor'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { useInstance } from '../../hooks/UseInstance'; import { apiUrl } from '../../states/ApiState'; +import { AttachmentTable } from '../../tables/general/AttachmentTable'; /** * Detail page for a single ReturnOrder diff --git a/src/frontend/src/pages/sales/SalesIndex.tsx b/src/frontend/src/pages/sales/SalesIndex.tsx index 441ba0c5bd..db13d4b298 100644 --- a/src/frontend/src/pages/sales/SalesIndex.tsx +++ b/src/frontend/src/pages/sales/SalesIndex.tsx @@ -9,9 +9,9 @@ import { useMemo } from 'react'; import { PageDetail } from '../../components/nav/PageDetail'; import { PanelGroup } from '../../components/nav/PanelGroup'; -import { CompanyTable } from '../../components/tables/company/CompanyTable'; -import { ReturnOrderTable } from '../../components/tables/sales/ReturnOrderTable'; -import { SalesOrderTable } from '../../components/tables/sales/SalesOrderTable'; +import { CompanyTable } from '../../tables/company/CompanyTable'; +import { ReturnOrderTable } from '../../tables/sales/ReturnOrderTable'; +import { SalesOrderTable } from '../../tables/sales/SalesOrderTable'; export default function PurchasingIndex() { const panels = useMemo(() => { diff --git a/src/frontend/src/pages/sales/SalesOrderDetail.tsx b/src/frontend/src/pages/sales/SalesOrderDetail.tsx index bcb619822b..04908963ca 100644 --- a/src/frontend/src/pages/sales/SalesOrderDetail.tsx +++ b/src/frontend/src/pages/sales/SalesOrderDetail.tsx @@ -14,12 +14,12 @@ import { useParams } from 'react-router-dom'; import { PageDetail } from '../../components/nav/PageDetail'; import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; -import { BuildOrderTable } from '../../components/tables/build/BuildOrderTable'; -import { AttachmentTable } from '../../components/tables/general/AttachmentTable'; import { NotesEditor } from '../../components/widgets/MarkdownEditor'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { useInstance } from '../../hooks/UseInstance'; import { apiUrl } from '../../states/ApiState'; +import { BuildOrderTable } from '../../tables/build/BuildOrderTable'; +import { AttachmentTable } from '../../tables/general/AttachmentTable'; /** * Detail page for a single SalesOrder diff --git a/src/frontend/src/pages/stock/LocationDetail.tsx b/src/frontend/src/pages/stock/LocationDetail.tsx index 473aca55b5..a1da38dd23 100644 --- a/src/frontend/src/pages/stock/LocationDetail.tsx +++ b/src/frontend/src/pages/stock/LocationDetail.tsx @@ -7,10 +7,10 @@ import { useParams } from 'react-router-dom'; import { PageDetail } from '../../components/nav/PageDetail'; import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; import { StockLocationTree } from '../../components/nav/StockLocationTree'; -import { StockItemTable } from '../../components/tables/stock/StockItemTable'; -import { StockLocationTable } from '../../components/tables/stock/StockLocationTable'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { useInstance } from '../../hooks/UseInstance'; +import { StockItemTable } from '../../tables/stock/StockItemTable'; +import { StockLocationTable } from '../../tables/stock/StockLocationTable'; export default function Stock() { const { id: _id } = useParams(); diff --git a/src/frontend/src/pages/stock/StockDetail.tsx b/src/frontend/src/pages/stock/StockDetail.tsx index c114e93c6a..e8af423437 100644 --- a/src/frontend/src/pages/stock/StockDetail.tsx +++ b/src/frontend/src/pages/stock/StockDetail.tsx @@ -33,14 +33,14 @@ import { PlaceholderPanel } from '../../components/items/Placeholder'; import { PageDetail } from '../../components/nav/PageDetail'; import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; import { StockLocationTree } from '../../components/nav/StockLocationTree'; -import { AttachmentTable } from '../../components/tables/general/AttachmentTable'; -import { StockItemTable } from '../../components/tables/stock/StockItemTable'; import { NotesEditor } from '../../components/widgets/MarkdownEditor'; import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { useEditStockItem } from '../../forms/StockForms'; import { useInstance } from '../../hooks/UseInstance'; import { apiUrl } from '../../states/ApiState'; import { useUserState } from '../../states/UserState'; +import { AttachmentTable } from '../../tables/general/AttachmentTable'; +import { StockItemTable } from '../../tables/stock/StockItemTable'; export default function StockDetail() { const { id } = useParams(); diff --git a/src/frontend/src/states/LocalState.tsx b/src/frontend/src/states/LocalState.tsx index 1eda3fcceb..bc82d5a18a 100644 --- a/src/frontend/src/states/LocalState.tsx +++ b/src/frontend/src/states/LocalState.tsx @@ -24,6 +24,12 @@ interface LocalStateProps { loader: LoaderType; lastUsedPanels: Record; setLastUsedPanel: (panelKey: string) => (value: string) => void; + tableColumnNames: Record>; + getTableColumnNames: (tableKey: string) => Record; + setTableColumnNames: ( + tableKey: string + ) => (names: Record) => void; + clearTableColumnNames: () => void; } export const useLocalState = create()( @@ -55,6 +61,22 @@ export const useLocalState = create()( lastUsedPanels: { ...get().lastUsedPanels, [panelKey]: value } }); } + }, + tableColumnNames: {}, + getTableColumnNames: (tableKey) => { + return get().tableColumnNames[tableKey] || {}; + }, + setTableColumnNames: (tableKey) => (names) => { + // Update the table column names for the given table + set({ + tableColumnNames: { + ...get().tableColumnNames, + [tableKey]: names + } + }); + }, + clearTableColumnNames: () => { + set({ tableColumnNames: {} }); } }), { diff --git a/src/frontend/src/components/tables/Column.tsx b/src/frontend/src/tables/Column.tsx similarity index 85% rename from src/frontend/src/components/tables/Column.tsx rename to src/frontend/src/tables/Column.tsx index 4917689b99..f47a8f32d8 100644 --- a/src/frontend/src/components/tables/Column.tsx +++ b/src/frontend/src/tables/Column.tsx @@ -3,8 +3,8 @@ */ export type TableColumn = { accessor: string; // The key in the record to access + title?: string; // The title of the column - Note: this may be supplied by the API, and is not required, but it can be overridden if required ordering?: string; // The key in the record to sort by (defaults to accessor) - title: string; // The title of the column sortable?: boolean; // Whether the column is sortable switchable?: boolean; // Whether the column is switchable hidden?: boolean; // Whether the column is hidden diff --git a/src/frontend/src/components/tables/ColumnRenderers.tsx b/src/frontend/src/tables/ColumnRenderers.tsx similarity index 83% rename from src/frontend/src/components/tables/ColumnRenderers.tsx rename to src/frontend/src/tables/ColumnRenderers.tsx index 560614f07e..a70f809894 100644 --- a/src/frontend/src/components/tables/ColumnRenderers.tsx +++ b/src/frontend/src/tables/ColumnRenderers.tsx @@ -3,13 +3,13 @@ */ import { t } from '@lingui/macro'; -import { formatCurrency, renderDate } from '../../defaults/formatters'; -import { ModelType } from '../../enums/ModelType'; -import { Thumbnail } from '../images/Thumbnail'; -import { ProgressBar } from '../items/ProgressBar'; -import { YesNoButton } from '../items/YesNoButton'; -import { TableStatusRenderer } from '../render/StatusRenderer'; -import { RenderOwner } from '../render/User'; +import { Thumbnail } from '../components/images/Thumbnail'; +import { ProgressBar } from '../components/items/ProgressBar'; +import { YesNoButton } from '../components/items/YesNoButton'; +import { TableStatusRenderer } from '../components/render/StatusRenderer'; +import { RenderOwner } from '../components/render/User'; +import { formatCurrency, renderDate } from '../defaults/formatters'; +import { ModelType } from '../enums/ModelType'; import { TableColumn } from './Column'; import { ProjectCodeHoverCard } from './TableHoverCard'; @@ -25,7 +25,7 @@ export function BooleanColumn({ switchable }: { accessor: string; - title: string; + title?: string; sortable?: boolean; switchable?: boolean; }): TableColumn { @@ -58,16 +58,29 @@ export function DescriptionColumn({ export function LinkColumn(): TableColumn { return { accessor: 'link', - title: t`Link`, sortable: false // TODO: Custom URL hyperlink renderer? }; } +export function ReferenceColumn(): TableColumn { + return { + accessor: 'reference', + sortable: true, + switchable: false + }; +} + +export function NoteColumn(): TableColumn { + return { + accessor: 'note', + sortable: false + }; +} + export function LineItemsProgressColumn(): TableColumn { return { accessor: 'line_items', - title: t`Line Items`, sortable: true, render: (record: any) => ( ( @@ -94,7 +106,6 @@ export function StatusColumn(model: ModelType) { return { accessor: 'status', sortable: true, - title: t`Status`, render: TableStatusRenderer(model) }; } @@ -102,7 +113,6 @@ export function StatusColumn(model: ModelType) { export function ResponsibleColumn(): TableColumn { return { accessor: 'responsible', - title: t`Responsible`, sortable: true, render: (record: any) => record.responsible && RenderOwner({ instance: record.responsible_detail }) @@ -112,8 +122,8 @@ export function ResponsibleColumn(): TableColumn { export function TargetDateColumn(): TableColumn { return { accessor: 'target_date', - title: t`Target Date`, sortable: true, + title: t`Target Date`, // TODO: custom renderer which alerts user if target date is overdue render: (record: any) => renderDate(record.target_date) }; @@ -122,7 +132,6 @@ export function TargetDateColumn(): TableColumn { export function CreationDateColumn(): TableColumn { return { accessor: 'creation_date', - title: t`Creation Date`, sortable: true, render: (record: any) => renderDate(record.creation_date) }; @@ -131,7 +140,6 @@ export function CreationDateColumn(): TableColumn { export function ShipmentDateColumn(): TableColumn { return { accessor: 'shipment_date', - title: t`Shipment Date`, sortable: true, render: (record: any) => renderDate(record.shipment_date) }; diff --git a/src/frontend/src/components/tables/ColumnSelect.tsx b/src/frontend/src/tables/ColumnSelect.tsx similarity index 93% rename from src/frontend/src/components/tables/ColumnSelect.tsx rename to src/frontend/src/tables/ColumnSelect.tsx index 05b768ec4b..4cf66fe58f 100644 --- a/src/frontend/src/components/tables/ColumnSelect.tsx +++ b/src/frontend/src/tables/ColumnSelect.tsx @@ -29,7 +29,7 @@ export function TableColumnSelect({ onToggleColumn(col.accessor)} + onChange={() => onToggleColumn(col.accessor)} radius="sm" /> diff --git a/src/frontend/src/components/tables/Details.tsx b/src/frontend/src/tables/Details.tsx similarity index 97% rename from src/frontend/src/components/tables/Details.tsx rename to src/frontend/src/tables/Details.tsx index 374550e0a8..e62b8f23c8 100644 --- a/src/frontend/src/components/tables/Details.tsx +++ b/src/frontend/src/tables/Details.tsx @@ -13,12 +13,12 @@ import { import { useSuspenseQuery } from '@tanstack/react-query'; import { Suspense } from 'react'; -import { api } from '../../App'; -import { ApiEndpoints } from '../../enums/ApiEndpoints'; -import { InvenTreeIcon } from '../../functions/icons'; -import { apiUrl } from '../../states/ApiState'; -import { useGlobalSettingsState } from '../../states/SettingsState'; -import { ProgressBar } from '../items/ProgressBar'; +import { api } from '../App'; +import { ProgressBar } from '../components/items/ProgressBar'; +import { ApiEndpoints } from '../enums/ApiEndpoints'; +import { InvenTreeIcon } from '../functions/icons'; +import { apiUrl } from '../states/ApiState'; +import { useGlobalSettingsState } from '../states/SettingsState'; export type PartIconsType = { assembly: boolean; diff --git a/src/frontend/src/components/tables/DownloadAction.tsx b/src/frontend/src/tables/DownloadAction.tsx similarity index 100% rename from src/frontend/src/components/tables/DownloadAction.tsx rename to src/frontend/src/tables/DownloadAction.tsx diff --git a/src/frontend/src/components/tables/Filter.tsx b/src/frontend/src/tables/Filter.tsx similarity index 94% rename from src/frontend/src/components/tables/Filter.tsx rename to src/frontend/src/tables/Filter.tsx index 23e06bf41a..1208ae36ca 100644 --- a/src/frontend/src/components/tables/Filter.tsx +++ b/src/frontend/src/tables/Filter.tsx @@ -1,7 +1,7 @@ import { t } from '@lingui/macro'; -import { ModelType } from '../../enums/ModelType'; -import { useServerApiState } from '../../states/ApiState'; +import { ModelType } from '../enums/ModelType'; +import { useServerApiState } from '../states/ApiState'; /** * Interface for the table filter choice @@ -20,7 +20,7 @@ export type TableFilterChoice = { */ export type TableFilter = { name: string; - label: string; + label?: string; description?: string; type?: string; choices?: TableFilterChoice[]; diff --git a/src/frontend/src/components/tables/FilterSelectDrawer.tsx b/src/frontend/src/tables/FilterSelectDrawer.tsx similarity index 98% rename from src/frontend/src/components/tables/FilterSelectDrawer.tsx rename to src/frontend/src/tables/FilterSelectDrawer.tsx index b49ca8c155..c95c814094 100644 --- a/src/frontend/src/components/tables/FilterSelectDrawer.tsx +++ b/src/frontend/src/tables/FilterSelectDrawer.tsx @@ -14,8 +14,8 @@ import { } from '@mantine/core'; import { forwardRef, useCallback, useEffect, useMemo, useState } from 'react'; -import { TableState } from '../../hooks/UseTable'; -import { StylishText } from '../items/StylishText'; +import { StylishText } from '../components/items/StylishText'; +import { TableState } from '../hooks/UseTable'; import { TableFilter, TableFilterChoice, diff --git a/src/frontend/src/components/tables/InvenTreeTable.tsx b/src/frontend/src/tables/InvenTreeTable.tsx similarity index 74% rename from src/frontend/src/components/tables/InvenTreeTable.tsx rename to src/frontend/src/tables/InvenTreeTable.tsx index 3409b0e319..242548a59f 100644 --- a/src/frontend/src/components/tables/InvenTreeTable.tsx +++ b/src/frontend/src/tables/InvenTreeTable.tsx @@ -2,7 +2,9 @@ import { t } from '@lingui/macro'; import { ActionIcon, Alert, + Box, Indicator, + LoadingOverlay, Space, Stack, Tooltip @@ -16,10 +18,13 @@ import { useQuery } from '@tanstack/react-query'; import { DataTable, DataTableSortStatus } from 'mantine-datatable'; import { Fragment, useCallback, useEffect, useMemo, useState } from 'react'; -import { api } from '../../App'; -import { TableState } from '../../hooks/UseTable'; -import { ActionButton } from '../buttons/ActionButton'; -import { ButtonMenu } from '../buttons/ButtonMenu'; +import { api } from '../App'; +import { ActionButton } from '../components/buttons/ActionButton'; +import { ButtonMenu } from '../components/buttons/ButtonMenu'; +import { ApiFormFieldSet } from '../components/forms/fields/ApiFormField'; +import { extractAvailableFields, mapFields } from '../functions/forms'; +import { TableState } from '../hooks/UseTable'; +import { useLocalState } from '../states/LocalState'; import { TableColumn } from './Column'; import { TableColumnSelect } from './ColumnSelect'; import { DownloadAction } from './DownloadAction'; @@ -93,8 +98,7 @@ const defaultInvenTreeTableProps: InvenTreeTableProps = { barcodeActions: [], tableFilters: [], tableActions: [], - idAccessor: 'pk', - onRowClick: (record: any, index: number, event: any) => {} + idAccessor: 'pk' }; /** @@ -111,6 +115,73 @@ export function InvenTreeTable({ columns: TableColumn[]; props: InvenTreeTableProps; }) { + const { getTableColumnNames, setTableColumnNames } = useLocalState(); + const [fieldNames, setFieldNames] = useState>({}); + + // Construct table filters - note that we can introspect filter labels from column names + const filters: TableFilter[] = useMemo(() => { + return ( + props.tableFilters?.map((filter) => { + return { + ...filter, + label: filter.label ?? fieldNames[filter.name] ?? `? ${filter.name} ?` + }; + }) ?? [] + ); + }, [props.tableFilters, fieldNames]); + + // Request OPTIONS data from the API, before we load the table + const tableOptionQuery = useQuery({ + enabled: false, + queryKey: ['options', url, tableState.tableKey], + queryFn: async () => { + return api + .options(url, { + params: tableProps.params + }) + .then((response) => { + if (response.status == 200) { + // Extract field information from the API + + let names: Record = {}; + let fields: ApiFormFieldSet = + extractAvailableFields(response, 'POST') || {}; + + // Extract flattened map of fields + mapFields(fields, (path, field) => { + if (field.label) { + names[path] = field.label; + } + }); + + const cacheKey = tableState.tableKey.split('-')[0]; + + setFieldNames(names); + setTableColumnNames(cacheKey)(names); + } + + return null; + }); + } + }); + + // Rebuild set of translated column names + useEffect(() => { + const cacheKey = tableState.tableKey.split('-')[0]; + + // First check the local cache + const cachedNames = getTableColumnNames(cacheKey); + + if (Object.keys(cachedNames).length > 0) { + // Cached names are available - use them! + setFieldNames(cachedNames); + return; + } + + // Otherwise, fetch the data from the API + tableOptionQuery.refetch(); + }, [url, tableState.tableKey, props.params]); + // Build table properties based on provided props (and default props) const tableProps: InvenTreeTableProps = useMemo(() => { return { @@ -139,7 +210,8 @@ export function InvenTreeTable({ return { ...col, - hidden: hidden + hidden: hidden, + title: col.title ?? fieldNames[col.accessor] ?? `? ${col.accessor} ?` }; }); @@ -165,6 +237,7 @@ export function InvenTreeTable({ return cols; }, [ columns, + fieldNames, tableProps.rowActions, tableProps.enableSelection, tableState.hiddenColumns, @@ -289,7 +362,7 @@ export function InvenTreeTable({ let queryParams = getTableFilters(true); return api - .get(`${url}`, { + .get(url, { params: queryParams, timeout: 30 * 1000 }) @@ -424,15 +497,14 @@ export function InvenTreeTable({ return ( <> - {tableProps.enableFilters && - (tableProps.tableFilters?.length ?? 0) > 0 && ( - setFiltersVisible(false)} - /> - )} + {tableProps.enableFilters && (filters.length ?? 0) > 0 && ( + setFiltersVisible(false)} + /> + )} @@ -489,22 +561,21 @@ export function InvenTreeTable({ onToggleColumn={toggleColumn} /> )} - {tableProps.enableFilters && - (tableProps.tableFilters?.length ?? 0 > 0) && ( - - - - setFiltersVisible(!filtersVisible)} - /> - - - - )} + {tableProps.enableFilters && filters.length > 0 && ( + + + + setFiltersVisible(!filtersVisible)} + /> + + + + )} {tableProps.enableDownload && ( ({ )} - + + + + onSelectedRecordsChange={ + tableProps.enableSelection ? onSelectedRecordsChange : undefined + } + fetching={isFetching} + noRecordsText={missingRecordsText} + records={data} + columns={dataColumns} + onRowClick={tableProps.onRowClick} + defaultColumnProps={{ + noWrap: true, + textAlignment: 'left', + cellsStyle: { + // TODO @SchrodingersGat : Need a better way of handling "wide" cells, + overflow: 'hidden' + } + }} + /> + ); diff --git a/src/frontend/src/components/tables/ItemDetails.tsx b/src/frontend/src/tables/ItemDetails.tsx similarity index 94% rename from src/frontend/src/components/tables/ItemDetails.tsx rename to src/frontend/src/tables/ItemDetails.tsx index eb2f24454b..76e08296df 100644 --- a/src/frontend/src/components/tables/ItemDetails.tsx +++ b/src/frontend/src/tables/ItemDetails.tsx @@ -1,7 +1,10 @@ import { Paper } from '@mantine/core'; -import { UserRoles } from '../../enums/Roles'; -import { DetailImageButtonProps, DetailsImage } from '../images/DetailsImage'; +import { + DetailImageButtonProps, + DetailsImage +} from '../components/images/DetailsImage'; +import { UserRoles } from '../enums/Roles'; import { DetailsField, DetailsTable } from './Details'; /** diff --git a/src/frontend/src/components/tables/RowActions.tsx b/src/frontend/src/tables/RowActions.tsx similarity index 98% rename from src/frontend/src/components/tables/RowActions.tsx rename to src/frontend/src/tables/RowActions.tsx index a9f46e3afc..784cb16210 100644 --- a/src/frontend/src/components/tables/RowActions.tsx +++ b/src/frontend/src/tables/RowActions.tsx @@ -4,7 +4,7 @@ import { Menu } from '@mantine/core'; import { IconCopy, IconDots, IconEdit, IconTrash } from '@tabler/icons-react'; import { ReactNode, useMemo, useState } from 'react'; -import { notYetImplemented } from '../../functions/notifications'; +import { notYetImplemented } from '../functions/notifications'; // Type definition for a table row action export type RowAction = { diff --git a/src/frontend/src/components/tables/Search.tsx b/src/frontend/src/tables/Search.tsx similarity index 84% rename from src/frontend/src/components/tables/Search.tsx rename to src/frontend/src/tables/Search.tsx index 300b9e43fa..d3f3b9cd9c 100644 --- a/src/frontend/src/components/tables/Search.tsx +++ b/src/frontend/src/tables/Search.tsx @@ -1,3 +1,4 @@ +import { t } from '@lingui/macro'; import { CloseButton, TextInput } from '@mantine/core'; import { useDebouncedValue } from '@mantine/hooks'; import { IconSearch } from '@tabler/icons-react'; @@ -19,11 +20,11 @@ export function TableSearchInput({ } - placeholder="Search" + placeholder={t`Search`} onChange={(event) => setValue(event.target.value)} rightSection={ value.length > 0 ? ( - setValue('')} /> + setValue('')} /> ) : null } /> diff --git a/src/frontend/src/components/tables/TableHoverCard.tsx b/src/frontend/src/tables/TableHoverCard.tsx similarity index 100% rename from src/frontend/src/components/tables/TableHoverCard.tsx rename to src/frontend/src/tables/TableHoverCard.tsx diff --git a/src/frontend/src/components/tables/bom/BomTable.tsx b/src/frontend/src/tables/bom/BomTable.tsx similarity index 83% rename from src/frontend/src/components/tables/bom/BomTable.tsx rename to src/frontend/src/tables/bom/BomTable.tsx index e471a46da1..3bbcb00744 100644 --- a/src/frontend/src/components/tables/bom/BomTable.tsx +++ b/src/frontend/src/tables/bom/BomTable.tsx @@ -8,20 +8,25 @@ import { import { ReactNode, useCallback, useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; -import { formatPriceRange } from '../../../defaults/formatters'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { ModelType } from '../../../enums/ModelType'; -import { UserRoles } from '../../../enums/Roles'; -import { bomItemFields } from '../../../forms/BomForms'; -import { openDeleteApiForm, openEditApiForm } from '../../../functions/forms'; -import { getDetailUrl } from '../../../functions/urls'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { useUserState } from '../../../states/UserState'; -import { Thumbnail } from '../../images/Thumbnail'; -import { YesNoButton } from '../../items/YesNoButton'; +import { Thumbnail } from '../../components/images/Thumbnail'; +import { YesNoButton } from '../../components/items/YesNoButton'; +import { formatPriceRange } from '../../defaults/formatters'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { ModelType } from '../../enums/ModelType'; +import { UserRoles } from '../../enums/Roles'; +import { bomItemFields } from '../../forms/BomForms'; +import { openDeleteApiForm, openEditApiForm } from '../../functions/forms'; +import { getDetailUrl } from '../../functions/urls'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; +import { useUserState } from '../../states/UserState'; import { TableColumn } from '../Column'; -import { BooleanColumn } from '../ColumnRenderers'; +import { + BooleanColumn, + DescriptionColumn, + NoteColumn, + ReferenceColumn +} from '../ColumnRenderers'; import { TableFilter } from '../Filter'; import { InvenTreeTable } from '../InvenTreeTable'; import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions'; @@ -58,10 +63,8 @@ export function BomTable({ const tableColumns: TableColumn[] = useMemo(() => { return [ - // TODO: Improve column rendering { accessor: 'part', - title: t`Part`, switchable: false, sortable: true, render: (record) => { @@ -91,18 +94,12 @@ export function BomTable({ ); } }, - { - accessor: 'description', - title: t`Description`, - render: (row) => row?.sub_part_detail?.description - }, - { - accessor: 'reference', - title: t`Reference` - }, + DescriptionColumn({ + accessor: 'sub_part_detail.description' + }), + ReferenceColumn(), { accessor: 'quantity', - title: t`Quantity`, switchable: false, sortable: true // TODO: Custom quantity renderer @@ -110,7 +107,6 @@ export function BomTable({ }, { accessor: 'substitutes', - title: t`Substitutes`, // TODO: Show hovercard with list of substitutes render: (row) => { let substitutes = row.substitutes ?? []; @@ -123,20 +119,16 @@ export function BomTable({ } }, BooleanColumn({ - accessor: 'optional', - title: t`Optional` + accessor: 'optional' }), BooleanColumn({ - accessor: 'consumable', - title: t`Consumable` + accessor: 'consumable' }), BooleanColumn({ - accessor: 'allow_variants', - title: t`Allow Variants` + accessor: 'allow_variants' }), BooleanColumn({ - accessor: 'inherited', - title: t`Gets Inherited` + accessor: 'inherited' // TODO: Custom renderer for this column // TODO: See bom.js for existing implementation }), @@ -150,7 +142,6 @@ export function BomTable({ }, { accessor: 'available_stock', - title: t`Available`, render: (record) => { let extra: ReactNode[] = []; @@ -225,11 +216,7 @@ export function BomTable({ ); } }, - { - accessor: 'note', - title: t`Notes`, - switchable: true - } + NoteColumn() ]; }, [partId, params]); @@ -247,32 +234,26 @@ export function BomTable({ }, { name: 'available_stock', - label: t`Has Available Stock`, description: t`Show items with available stock` }, { name: 'on_order', - label: t`On Order`, description: t`Show items on order` }, { name: 'validated', - label: t`Validated`, description: t`Show validated items` }, { name: 'inherited', - label: t`Gets Inherited`, description: t`Show inherited items` }, { name: 'optional', - label: t`Optional`, description: t`Show optional items` }, { name: 'consumable', - label: t`Consumable`, description: t`Show consumable items` }, { diff --git a/src/frontend/src/components/tables/bom/UsedInTable.tsx b/src/frontend/src/tables/bom/UsedInTable.tsx similarity index 77% rename from src/frontend/src/components/tables/bom/UsedInTable.tsx rename to src/frontend/src/tables/bom/UsedInTable.tsx index 82b7ebeaef..aa7700ee1c 100644 --- a/src/frontend/src/components/tables/bom/UsedInTable.tsx +++ b/src/frontend/src/tables/bom/UsedInTable.tsx @@ -2,13 +2,14 @@ import { t } from '@lingui/macro'; import { useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { ModelType } from '../../../enums/ModelType'; -import { getDetailUrl } from '../../../functions/urls'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { PartHoverCard } from '../../images/Thumbnail'; +import { PartHoverCard } from '../../components/images/Thumbnail'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { ModelType } from '../../enums/ModelType'; +import { getDetailUrl } from '../../functions/urls'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; import { TableColumn } from '../Column'; +import { ReferenceColumn } from '../ColumnRenderers'; import { TableFilter } from '../Filter'; import { InvenTreeTable } from '../InvenTreeTable'; @@ -30,30 +31,23 @@ export function UsedInTable({ return [ { accessor: 'part', - title: t`Assembled Part`, switchable: false, sortable: true, render: (record: any) => }, { accessor: 'sub_part', - title: t`Required Part`, sortable: true, render: (record: any) => }, { accessor: 'quantity', - title: t`Quantity`, render: (record: any) => { // TODO: render units if appropriate return record.quantity; } }, - { - accessor: 'reference', - title: t`Reference`, - sortable: true - } + ReferenceColumn() ]; }, [partId]); @@ -61,12 +55,10 @@ export function UsedInTable({ return [ { name: 'inherited', - label: t`Gets Inherited`, description: t`Show inherited items` }, { name: 'optional', - label: t`Optional`, description: t`Show optional items` }, { diff --git a/src/frontend/src/components/tables/build/BuildLineTable.tsx b/src/frontend/src/tables/build/BuildLineTable.tsx similarity index 86% rename from src/frontend/src/components/tables/build/BuildLineTable.tsx rename to src/frontend/src/tables/build/BuildLineTable.tsx index 9074ae775f..5bd53c8801 100644 --- a/src/frontend/src/components/tables/build/BuildLineTable.tsx +++ b/src/frontend/src/tables/build/BuildLineTable.tsx @@ -8,14 +8,14 @@ import { import { useCallback, useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { ModelType } from '../../../enums/ModelType'; -import { getDetailUrl } from '../../../functions/urls'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { useUserState } from '../../../states/UserState'; -import { PartHoverCard } from '../../images/Thumbnail'; -import { ProgressBar } from '../../items/ProgressBar'; +import { PartHoverCard } from '../../components/images/Thumbnail'; +import { ProgressBar } from '../../components/items/ProgressBar'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { ModelType } from '../../enums/ModelType'; +import { getDetailUrl } from '../../functions/urls'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; +import { useUserState } from '../../states/UserState'; import { TableColumn } from '../Column'; import { BooleanColumn } from '../ColumnRenderers'; import { TableFilter } from '../Filter'; @@ -31,7 +31,6 @@ export default function BuildLineTable({ params = {} }: { params?: any }) { return [ { name: 'allocated', - label: t`Allocated`, description: t`Show allocated lines` }, { @@ -114,28 +113,24 @@ export default function BuildLineTable({ params = {} }: { params?: any }) { return [ { accessor: 'bom_item', - title: t`Part`, sortable: true, switchable: false, render: (record: any) => }, { - accessor: 'reference', - title: t`Reference`, - render: (record: any) => record.bom_item_detail.reference + accessor: 'bom_item_detail.reference' }, BooleanColumn({ - accessor: 'bom_item_detail.consumable', - title: t`Consumable` + accessor: 'bom_item_detail.consumable' }), BooleanColumn({ - accessor: 'bom_item_detail.optional', - title: t`Optional` + accessor: 'bom_item_detail.optional' }), { - accessor: 'unit_quantity', - title: t`Unit Quantity`, + accessor: 'bom_item_detail.quantity', sortable: true, + title: t`Unit Quantity`, + ordering: 'unit_quantity', render: (record: any) => { return ( @@ -149,7 +144,6 @@ export default function BuildLineTable({ params = {} }: { params?: any }) { }, { accessor: 'quantity', - title: t`Required Quantity`, sortable: true, render: (record: any) => { return ( @@ -164,14 +158,12 @@ export default function BuildLineTable({ params = {} }: { params?: any }) { }, { accessor: 'available_stock', - title: t`Available`, sortable: true, switchable: false, render: renderAvailableColumn }, { accessor: 'allocated', - title: t`Allocated`, switchable: false, render: (record: any) => { return record?.bom_item_detail?.consumable ? ( diff --git a/src/frontend/src/components/tables/build/BuildOrderTable.tsx b/src/frontend/src/tables/build/BuildOrderTable.tsx similarity index 78% rename from src/frontend/src/components/tables/build/BuildOrderTable.tsx rename to src/frontend/src/tables/build/BuildOrderTable.tsx index b824c9beb9..5e5afd8b33 100644 --- a/src/frontend/src/components/tables/build/BuildOrderTable.tsx +++ b/src/frontend/src/tables/build/BuildOrderTable.tsx @@ -2,24 +2,25 @@ import { t } from '@lingui/macro'; import { useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; -import { renderDate } from '../../../defaults/formatters'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { ModelType } from '../../../enums/ModelType'; -import { UserRoles } from '../../../enums/Roles'; -import { buildOrderFields } from '../../../forms/BuildForms'; -import { getDetailUrl } from '../../../functions/urls'; -import { useCreateApiFormModal } from '../../../hooks/UseForm'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { useUserState } from '../../../states/UserState'; -import { AddItemButton } from '../../buttons/AddItemButton'; -import { PartHoverCard } from '../../images/Thumbnail'; -import { ProgressBar } from '../../items/ProgressBar'; -import { RenderUser } from '../../render/User'; +import { AddItemButton } from '../../components/buttons/AddItemButton'; +import { PartHoverCard } from '../../components/images/Thumbnail'; +import { ProgressBar } from '../../components/items/ProgressBar'; +import { RenderUser } from '../../components/render/User'; +import { renderDate } from '../../defaults/formatters'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { ModelType } from '../../enums/ModelType'; +import { UserRoles } from '../../enums/Roles'; +import { buildOrderFields } from '../../forms/BuildForms'; +import { getDetailUrl } from '../../functions/urls'; +import { useCreateApiFormModal } from '../../hooks/UseForm'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; +import { useUserState } from '../../states/UserState'; import { TableColumn } from '../Column'; import { CreationDateColumn, ProjectCodeColumn, + ReferenceColumn, ResponsibleColumn, StatusColumn, TargetDateColumn @@ -32,29 +33,21 @@ import { InvenTreeTable } from '../InvenTreeTable'; */ function buildOrderTableColumns(): TableColumn[] { return [ - { - accessor: 'reference', - sortable: true, - switchable: false, - title: t`Reference` - }, + ReferenceColumn(), { accessor: 'part', sortable: true, switchable: false, - title: t`Part`, render: (record: any) => }, { accessor: 'title', - sortable: false, - title: t`Description` + sortable: false }, { accessor: 'completed', sortable: true, switchable: false, - title: t`Progress`, render: (record: any) => ( renderDate(record.completion_date) }, { accessor: 'issued_by', sortable: true, - title: t`Issued By`, render: (record: any) => ( ) @@ -114,14 +104,12 @@ export function BuildOrderTable({ }, { name: 'status', - label: t`Status`, description: t`Filter by order status`, choiceFunction: StatusFilterOptions(ModelType.build) }, { name: 'overdue', type: 'boolean', - label: t`Overdue`, description: t`Show overdue status` }, { diff --git a/src/frontend/src/components/tables/company/AddressTable.tsx b/src/frontend/src/tables/company/AddressTable.tsx similarity index 86% rename from src/frontend/src/components/tables/company/AddressTable.tsx rename to src/frontend/src/tables/company/AddressTable.tsx index f093fb6bd8..af4732a0a1 100644 --- a/src/frontend/src/components/tables/company/AddressTable.tsx +++ b/src/frontend/src/tables/company/AddressTable.tsx @@ -1,19 +1,19 @@ import { t } from '@lingui/macro'; import { useCallback, useMemo, useState } from 'react'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { UserRoles } from '../../../enums/Roles'; +import { AddItemButton } from '../../components/buttons/AddItemButton'; +import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField'; +import { YesNoButton } from '../../components/items/YesNoButton'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { UserRoles } from '../../enums/Roles'; import { useCreateApiFormModal, useDeleteApiFormModal, useEditApiFormModal -} from '../../../hooks/UseForm'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { useUserState } from '../../../states/UserState'; -import { AddItemButton } from '../../buttons/AddItemButton'; -import { ApiFormFieldSet } from '../../forms/fields/ApiFormField'; -import { YesNoButton } from '../../items/YesNoButton'; +} from '../../hooks/UseForm'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; +import { useUserState } from '../../states/UserState'; import { TableColumn } from '../Column'; import { InvenTreeTable } from '../InvenTreeTable'; import { RowDeleteAction, RowEditAction } from '../RowActions'; @@ -33,13 +33,11 @@ export function AddressTable({ return [ { accessor: 'title', - title: t`Title`, sortable: true, switchable: false }, { accessor: 'primary', - title: t`Primary`, switchable: false, sortable: false, render: (record: any) => YesNoButton({ value: record.primary }) @@ -65,43 +63,36 @@ export function AddressTable({ }, { accessor: 'postal_code', - title: t`Postal Code`, sortable: false, switchable: true }, { accessor: 'postal_city', - title: t`City`, sortable: false, switchable: true }, { accessor: 'province', - title: t`State / Province`, sortable: false, switchable: true }, { accessor: 'country', - title: t`Country`, sortable: false, switchable: true }, { accessor: 'shipping_notes', - title: t`Courier Notes`, sortable: false, switchable: true }, { accessor: 'internal_shipping_notes', - title: t`Internal Notes`, sortable: false, switchable: true }, { accessor: 'link', - title: t`Link`, sortable: false, switchable: true } diff --git a/src/frontend/src/components/tables/company/CompanyTable.tsx b/src/frontend/src/tables/company/CompanyTable.tsx similarity index 79% rename from src/frontend/src/components/tables/company/CompanyTable.tsx rename to src/frontend/src/tables/company/CompanyTable.tsx index f064c3e23a..96062212e7 100644 --- a/src/frontend/src/components/tables/company/CompanyTable.tsx +++ b/src/frontend/src/tables/company/CompanyTable.tsx @@ -3,15 +3,15 @@ import { Group, Text } from '@mantine/core'; import { useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { UserRoles } from '../../../enums/Roles'; -import { companyFields } from '../../../forms/CompanyForms'; -import { useCreateApiFormModal } from '../../../hooks/UseForm'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { useUserState } from '../../../states/UserState'; -import { AddItemButton } from '../../buttons/AddItemButton'; -import { Thumbnail } from '../../images/Thumbnail'; +import { AddItemButton } from '../../components/buttons/AddItemButton'; +import { Thumbnail } from '../../components/images/Thumbnail'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { UserRoles } from '../../enums/Roles'; +import { companyFields } from '../../forms/CompanyForms'; +import { useCreateApiFormModal } from '../../hooks/UseForm'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; +import { useUserState } from '../../states/UserState'; import { DescriptionColumn } from '../ColumnRenderers'; import { InvenTreeTable } from '../InvenTreeTable'; @@ -35,7 +35,6 @@ export function CompanyTable({ return [ { accessor: 'name', - title: t`Company Name`, sortable: true, render: (record: any) => { return ( @@ -53,7 +52,6 @@ export function CompanyTable({ DescriptionColumn({}), { accessor: 'website', - title: t`Website`, sortable: false } ]; @@ -65,7 +63,6 @@ export function CompanyTable({ fields: companyFields(), initialData: params, onFormSuccess: (response) => { - console.log('onFormSuccess:', response); if (response.pk) { let base = path ?? 'company'; navigate(`/${base}/${response.pk}`); diff --git a/src/frontend/src/components/tables/company/ContactTable.tsx b/src/frontend/src/tables/company/ContactTable.tsx similarity index 86% rename from src/frontend/src/components/tables/company/ContactTable.tsx rename to src/frontend/src/tables/company/ContactTable.tsx index e2e32d9089..08f2176bbd 100644 --- a/src/frontend/src/components/tables/company/ContactTable.tsx +++ b/src/frontend/src/tables/company/ContactTable.tsx @@ -1,18 +1,18 @@ import { t } from '@lingui/macro'; import { useCallback, useMemo, useState } from 'react'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { UserRoles } from '../../../enums/Roles'; +import { AddItemButton } from '../../components/buttons/AddItemButton'; +import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { UserRoles } from '../../enums/Roles'; import { useCreateApiFormModal, useDeleteApiFormModal, useEditApiFormModal -} from '../../../hooks/UseForm'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { useUserState } from '../../../states/UserState'; -import { AddItemButton } from '../../buttons/AddItemButton'; -import { ApiFormFieldSet } from '../../forms/fields/ApiFormField'; +} from '../../hooks/UseForm'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; +import { useUserState } from '../../states/UserState'; import { TableColumn } from '../Column'; import { InvenTreeTable } from '../InvenTreeTable'; import { RowDeleteAction, RowEditAction } from '../RowActions'; @@ -32,25 +32,21 @@ export function ContactTable({ return [ { accessor: 'name', - title: t`Name`, sortable: true, switchable: false }, { accessor: 'phone', - title: t`Phone`, switchable: true, sortable: false }, { accessor: 'email', - title: t`Email`, switchable: true, sortable: false }, { accessor: 'role', - title: t`Role`, switchable: true, sortable: false } diff --git a/src/frontend/src/components/tables/general/AttachmentTable.tsx b/src/frontend/src/tables/general/AttachmentTable.tsx similarity index 93% rename from src/frontend/src/components/tables/general/AttachmentTable.tsx rename to src/frontend/src/tables/general/AttachmentTable.tsx index b7153f4ea9..44297f5524 100644 --- a/src/frontend/src/components/tables/general/AttachmentTable.tsx +++ b/src/frontend/src/tables/general/AttachmentTable.tsx @@ -6,16 +6,16 @@ import { notifications } from '@mantine/notifications'; import { IconExternalLink, IconFileUpload } from '@tabler/icons-react'; import { ReactNode, useEffect, useMemo, useState } from 'react'; -import { api } from '../../../App'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; +import { api } from '../../App'; +import { AttachmentLink } from '../../components/items/AttachmentLink'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { addAttachment, deleteAttachment, editAttachment -} from '../../../forms/AttachmentForms'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { AttachmentLink } from '../../items/AttachmentLink'; +} from '../../forms/AttachmentForms'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; import { TableColumn } from '../Column'; import { InvenTreeTable } from '../InvenTreeTable'; import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions'; @@ -27,7 +27,6 @@ function attachmentTableColumns(): TableColumn[] { return [ { accessor: 'attachment', - title: t`Attachment`, sortable: false, switchable: false, noWrap: true, @@ -44,7 +43,6 @@ function attachmentTableColumns(): TableColumn[] { }, { accessor: 'comment', - title: t`Comment`, sortable: false, render: function (record: any) { @@ -52,9 +50,8 @@ function attachmentTableColumns(): TableColumn[] { } }, { - accessor: 'uploaded', - title: t`Uploaded`, - sortable: false, + accessor: 'upload_date', + sortable: true, render: function (record: any) { return ( diff --git a/src/frontend/src/components/tables/notifications/NotificationsTable.tsx b/src/frontend/src/tables/notifications/NotificationsTable.tsx similarity index 86% rename from src/frontend/src/components/tables/notifications/NotificationsTable.tsx rename to src/frontend/src/tables/notifications/NotificationsTable.tsx index 74519c7563..c2224ffaa4 100644 --- a/src/frontend/src/components/tables/notifications/NotificationsTable.tsx +++ b/src/frontend/src/tables/notifications/NotificationsTable.tsx @@ -1,9 +1,9 @@ import { t } from '@lingui/macro'; import { useMemo } from 'react'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { TableState } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { TableState } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; import { TableColumn } from '../Column'; import { InvenTreeTable } from '../InvenTreeTable'; import { RowAction } from '../RowActions'; diff --git a/src/frontend/src/components/tables/part/PartCategoryTable.tsx b/src/frontend/src/tables/part/PartCategoryTable.tsx similarity index 83% rename from src/frontend/src/components/tables/part/PartCategoryTable.tsx rename to src/frontend/src/tables/part/PartCategoryTable.tsx index 0bd92ede90..914195ba14 100644 --- a/src/frontend/src/components/tables/part/PartCategoryTable.tsx +++ b/src/frontend/src/tables/part/PartCategoryTable.tsx @@ -2,20 +2,20 @@ import { t } from '@lingui/macro'; import { useCallback, useMemo, useState } from 'react'; import { useNavigate } from 'react-router-dom'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { ModelType } from '../../../enums/ModelType'; -import { UserRoles } from '../../../enums/Roles'; -import { partCategoryFields } from '../../../forms/PartForms'; -import { getDetailUrl } from '../../../functions/urls'; +import { AddItemButton } from '../../components/buttons/AddItemButton'; +import { YesNoButton } from '../../components/items/YesNoButton'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { ModelType } from '../../enums/ModelType'; +import { UserRoles } from '../../enums/Roles'; +import { partCategoryFields } from '../../forms/PartForms'; +import { getDetailUrl } from '../../functions/urls'; import { useCreateApiFormModal, useEditApiFormModal -} from '../../../hooks/UseForm'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { useUserState } from '../../../states/UserState'; -import { AddItemButton } from '../../buttons/AddItemButton'; -import { YesNoButton } from '../../items/YesNoButton'; +} from '../../hooks/UseForm'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; +import { useUserState } from '../../states/UserState'; import { TableColumn } from '../Column'; import { DescriptionColumn } from '../ColumnRenderers'; import { TableFilter } from '../Filter'; @@ -35,19 +35,16 @@ export function PartCategoryTable({ parentId }: { parentId?: any }) { return [ { accessor: 'name', - title: t`Name`, sortable: true, switchable: false }, DescriptionColumn({}), { accessor: 'pathstring', - title: t`Path`, sortable: false }, { accessor: 'structural', - title: t`Structural`, sortable: true, render: (record: any) => { return ; @@ -55,7 +52,6 @@ export function PartCategoryTable({ parentId }: { parentId?: any }) { }, { accessor: 'part_count', - title: t`Parts`, sortable: true } ]; diff --git a/src/frontend/src/components/tables/part/PartParameterTable.tsx b/src/frontend/src/tables/part/PartParameterTable.tsx similarity index 81% rename from src/frontend/src/components/tables/part/PartParameterTable.tsx rename to src/frontend/src/tables/part/PartParameterTable.tsx index 7e8467d1c2..8002a736e9 100644 --- a/src/frontend/src/components/tables/part/PartParameterTable.tsx +++ b/src/frontend/src/tables/part/PartParameterTable.tsx @@ -2,21 +2,21 @@ import { t } from '@lingui/macro'; import { Text } from '@mantine/core'; import { useCallback, useMemo, useState } from 'react'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { UserRoles } from '../../../enums/Roles'; +import { AddItemButton } from '../../components/buttons/AddItemButton'; +import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField'; +import { YesNoButton } from '../../components/items/YesNoButton'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { UserRoles } from '../../enums/Roles'; import { useCreateApiFormModal, useDeleteApiFormModal, useEditApiFormModal -} from '../../../hooks/UseForm'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { useUserState } from '../../../states/UserState'; -import { AddItemButton } from '../../buttons/AddItemButton'; -import { ApiFormFieldSet } from '../../forms/fields/ApiFormField'; -import { YesNoButton } from '../../items/YesNoButton'; +} from '../../hooks/UseForm'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; +import { useUserState } from '../../states/UserState'; import { TableColumn } from '../Column'; -import { PartColumn } from '../ColumnRenderers'; +import { DescriptionColumn, PartColumn } from '../ColumnRenderers'; import { InvenTreeTable } from '../InvenTreeTable'; import { RowDeleteAction, RowEditAction } from '../RowActions'; @@ -32,20 +32,16 @@ export function PartParameterTable({ partId }: { partId: any }) { return [ { accessor: 'part', - title: t`Part`, - sortable: true, render: (record: any) => PartColumn(record?.part_detail) }, { accessor: 'part_detail.IPN', - title: t`IPN`, sortable: false, switchable: true }, { - accessor: 'name', - title: t`Parameter`, + accessor: 'template_detail.name', switchable: false, sortable: true, render: (record) => { @@ -54,16 +50,11 @@ export function PartParameterTable({ partId }: { partId: any }) { return {record.template_detail?.name}; } }, - { - accessor: 'description', - title: t`Description`, - sortable: false, - - render: (record) => record.template_detail?.description - }, + DescriptionColumn({ + accessor: 'template_detail.description' + }), { accessor: 'data', - title: t`Value`, switchable: false, sortable: true, render: (record) => { @@ -83,11 +74,8 @@ export function PartParameterTable({ partId }: { partId: any }) { } }, { - accessor: 'units', - title: t`Units`, - - sortable: true, - render: (record) => record.template_detail?.units + accessor: 'template_detail.units', + sortable: false } ]; }, [partId]); diff --git a/src/frontend/src/components/tables/part/PartParameterTemplateTable.tsx b/src/frontend/src/tables/part/PartParameterTemplateTable.tsx similarity index 85% rename from src/frontend/src/components/tables/part/PartParameterTemplateTable.tsx rename to src/frontend/src/tables/part/PartParameterTemplateTable.tsx index 650fed7c2e..ac5d0de818 100644 --- a/src/frontend/src/components/tables/part/PartParameterTemplateTable.tsx +++ b/src/frontend/src/tables/part/PartParameterTemplateTable.tsx @@ -1,18 +1,18 @@ import { t } from '@lingui/macro'; import { useCallback, useMemo, useState } from 'react'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { UserRoles } from '../../../enums/Roles'; +import { AddItemButton } from '../../components/buttons/AddItemButton'; +import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { UserRoles } from '../../enums/Roles'; import { useCreateApiFormModal, useDeleteApiFormModal, useEditApiFormModal -} from '../../../hooks/UseForm'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { useUserState } from '../../../states/UserState'; -import { AddItemButton } from '../../buttons/AddItemButton'; -import { ApiFormFieldSet } from '../../forms/fields/ApiFormField'; +} from '../../hooks/UseForm'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; +import { useUserState } from '../../states/UserState'; import { TableColumn } from '../Column'; import { DescriptionColumn } from '../ColumnRenderers'; import { TableFilter } from '../Filter'; @@ -48,23 +48,19 @@ export default function PartParameterTemplateTable() { return [ { accessor: 'name', - title: t`Name`, sortable: true, switchable: false }, { accessor: 'units', - title: t`Units`, sortable: true }, DescriptionColumn({}), { - accessor: 'checkbox', - title: t`Checkbox` + accessor: 'checkbox' }, { - accessor: 'choices', - title: t`Choices` + accessor: 'choices' } ]; }, []); diff --git a/src/frontend/src/components/tables/part/PartTable.tsx b/src/frontend/src/tables/part/PartTable.tsx similarity index 92% rename from src/frontend/src/components/tables/part/PartTable.tsx rename to src/frontend/src/tables/part/PartTable.tsx index 739c4b3634..4f8f11bf44 100644 --- a/src/frontend/src/components/tables/part/PartTable.tsx +++ b/src/frontend/src/tables/part/PartTable.tsx @@ -3,14 +3,14 @@ import { Group, Text } from '@mantine/core'; import { ReactNode, useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; -import { formatPriceRange } from '../../../defaults/formatters'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { ModelType } from '../../../enums/ModelType'; -import { shortenString } from '../../../functions/tables'; -import { getDetailUrl } from '../../../functions/urls'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { Thumbnail } from '../../images/Thumbnail'; +import { Thumbnail } from '../../components/images/Thumbnail'; +import { formatPriceRange } from '../../defaults/formatters'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { ModelType } from '../../enums/ModelType'; +import { shortenString } from '../../functions/tables'; +import { getDetailUrl } from '../../functions/urls'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; import { TableColumn } from '../Column'; import { DescriptionColumn, LinkColumn } from '../ColumnRenderers'; import { TableFilter } from '../Filter'; @@ -26,7 +26,6 @@ function partTableColumns(): TableColumn[] { accessor: 'name', sortable: true, noWrap: true, - title: t`Part`, render: function (record: any) { return ( { diff --git a/src/frontend/src/components/tables/part/PartTestTemplateTable.tsx b/src/frontend/src/tables/part/PartTestTemplateTable.tsx similarity index 82% rename from src/frontend/src/components/tables/part/PartTestTemplateTable.tsx rename to src/frontend/src/tables/part/PartTestTemplateTable.tsx index f26919303c..46ec95ed1a 100644 --- a/src/frontend/src/components/tables/part/PartTestTemplateTable.tsx +++ b/src/frontend/src/tables/part/PartTestTemplateTable.tsx @@ -1,18 +1,18 @@ import { t } from '@lingui/macro'; import { useCallback, useMemo, useState } from 'react'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { UserRoles } from '../../../enums/Roles'; +import { AddItemButton } from '../../components/buttons/AddItemButton'; +import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { UserRoles } from '../../enums/Roles'; import { useCreateApiFormModal, useDeleteApiFormModal, useEditApiFormModal -} from '../../../hooks/UseForm'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { useUserState } from '../../../states/UserState'; -import { AddItemButton } from '../../buttons/AddItemButton'; -import { ApiFormFieldSet } from '../../forms/fields/ApiFormField'; +} from '../../hooks/UseForm'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; +import { useUserState } from '../../states/UserState'; import { TableColumn } from '../Column'; import { BooleanColumn, DescriptionColumn } from '../ColumnRenderers'; import { TableFilter } from '../Filter'; @@ -27,7 +27,6 @@ export default function PartTestTemplateTable({ partId }: { partId: number }) { return [ { accessor: 'test_name', - title: t`Test Name`, switchable: false, sortable: true }, @@ -35,16 +34,13 @@ export default function PartTestTemplateTable({ partId }: { partId: number }) { switchable: false }), BooleanColumn({ - accessor: 'required', - title: t`Required` + accessor: 'required' }), BooleanColumn({ - accessor: 'requires_value', - title: t`Requires Value` + accessor: 'requires_value' }), BooleanColumn({ - accessor: 'requires_attachment', - title: t`Requires Attachment` + accessor: 'requires_attachment' }) ]; }, []); @@ -53,17 +49,14 @@ export default function PartTestTemplateTable({ partId }: { partId: number }) { return [ { name: 'required', - label: t`Required`, description: t`Show required tests` }, { name: 'requires_value', - label: t`Requires Value`, description: t`Show tests that require a value` }, { name: 'requires_attachment', - label: t`Requires Attachment`, description: t`Show tests that require an attachment` } ]; diff --git a/src/frontend/src/components/tables/part/PartThumbTable.tsx b/src/frontend/src/tables/part/PartThumbTable.tsx similarity index 96% rename from src/frontend/src/components/tables/part/PartThumbTable.tsx rename to src/frontend/src/tables/part/PartThumbTable.tsx index 57d1fb16f9..0d18becfc9 100644 --- a/src/frontend/src/components/tables/part/PartThumbTable.tsx +++ b/src/frontend/src/tables/part/PartThumbTable.tsx @@ -4,10 +4,10 @@ import { useHover } from '@mantine/hooks'; import { useQuery } from '@tanstack/react-query'; import React, { Suspense, useEffect, useState } from 'react'; -import { api } from '../../../App'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { apiUrl } from '../../../states/ApiState'; -import { Thumbnail } from '../../images/Thumbnail'; +import { api } from '../../App'; +import { Thumbnail } from '../../components/images/Thumbnail'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { apiUrl } from '../../states/ApiState'; /** * Input props to table diff --git a/src/frontend/src/components/tables/part/PartVariantTable.tsx b/src/frontend/src/tables/part/PartVariantTable.tsx similarity index 100% rename from src/frontend/src/components/tables/part/PartVariantTable.tsx rename to src/frontend/src/tables/part/PartVariantTable.tsx diff --git a/src/frontend/src/components/tables/part/RelatedPartTable.tsx b/src/frontend/src/tables/part/RelatedPartTable.tsx similarity index 87% rename from src/frontend/src/components/tables/part/RelatedPartTable.tsx rename to src/frontend/src/tables/part/RelatedPartTable.tsx index c16f2cd364..2051df1f22 100644 --- a/src/frontend/src/components/tables/part/RelatedPartTable.tsx +++ b/src/frontend/src/tables/part/RelatedPartTable.tsx @@ -3,18 +3,18 @@ import { Group, Text } from '@mantine/core'; import { ReactNode, useCallback, useMemo, useState } from 'react'; import { useNavigate } from 'react-router-dom'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { UserRoles } from '../../../enums/Roles'; +import { AddItemButton } from '../../components/buttons/AddItemButton'; +import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField'; +import { Thumbnail } from '../../components/images/Thumbnail'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { UserRoles } from '../../enums/Roles'; import { useCreateApiFormModal, useDeleteApiFormModal -} from '../../../hooks/UseForm'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { useUserState } from '../../../states/UserState'; -import { AddItemButton } from '../../buttons/AddItemButton'; -import { ApiFormFieldSet } from '../../forms/fields/ApiFormField'; -import { Thumbnail } from '../../images/Thumbnail'; +} from '../../hooks/UseForm'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; +import { useUserState } from '../../states/UserState'; import { TableColumn } from '../Column'; import { InvenTreeTable } from '../InvenTreeTable'; import { RowDeleteAction } from '../RowActions'; diff --git a/src/frontend/src/components/tables/plugin/PluginErrorTable.tsx b/src/frontend/src/tables/plugin/PluginErrorTable.tsx similarity index 89% rename from src/frontend/src/components/tables/plugin/PluginErrorTable.tsx rename to src/frontend/src/tables/plugin/PluginErrorTable.tsx index 2e2d13729a..96450dfd22 100644 --- a/src/frontend/src/components/tables/plugin/PluginErrorTable.tsx +++ b/src/frontend/src/tables/plugin/PluginErrorTable.tsx @@ -2,9 +2,9 @@ import { t } from '@lingui/macro'; import { Code } from '@mantine/core'; import { useMemo } from 'react'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; import { TableColumn } from '../Column'; import { InvenTreeTable, InvenTreeTableProps } from '../InvenTreeTable'; diff --git a/src/frontend/src/components/tables/plugin/PluginListTable.tsx b/src/frontend/src/tables/plugin/PluginListTable.tsx similarity index 93% rename from src/frontend/src/components/tables/plugin/PluginListTable.tsx rename to src/frontend/src/tables/plugin/PluginListTable.tsx index 63c75e120f..d2ef921613 100644 --- a/src/frontend/src/components/tables/plugin/PluginListTable.tsx +++ b/src/frontend/src/tables/plugin/PluginListTable.tsx @@ -23,20 +23,23 @@ import { IconDots } from '@tabler/icons-react'; import { useCallback, useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; -import { api } from '../../../App'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { openEditApiForm } from '../../../functions/forms'; -import { useCreateApiFormModal } from '../../../hooks/UseForm'; -import { useInstance } from '../../../hooks/UseInstance'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl, useServerApiState } from '../../../states/ApiState'; -import { useUserState } from '../../../states/UserState'; -import { ActionButton } from '../../buttons/ActionButton'; -import { ActionDropdown, EditItemAction } from '../../items/ActionDropdown'; -import { InfoItem } from '../../items/InfoItem'; -import { StylishText } from '../../items/StylishText'; -import { DetailDrawer } from '../../nav/DetailDrawer'; -import { PluginSettingList } from '../../settings/SettingList'; +import { api } from '../../App'; +import { ActionButton } from '../../components/buttons/ActionButton'; +import { + ActionDropdown, + EditItemAction +} from '../../components/items/ActionDropdown'; +import { InfoItem } from '../../components/items/InfoItem'; +import { StylishText } from '../../components/items/StylishText'; +import { DetailDrawer } from '../../components/nav/DetailDrawer'; +import { PluginSettingList } from '../../components/settings/SettingList'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { openEditApiForm } from '../../functions/forms'; +import { useCreateApiFormModal } from '../../hooks/UseForm'; +import { useInstance } from '../../hooks/UseInstance'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl, useServerApiState } from '../../states/ApiState'; +import { useUserState } from '../../states/UserState'; import { TableColumn } from '../Column'; import { InvenTreeTable, InvenTreeTableProps } from '../InvenTreeTable'; import { RowAction } from '../RowActions'; diff --git a/src/frontend/src/components/tables/purchasing/ManufacturerPartParameterTable.tsx b/src/frontend/src/tables/purchasing/ManufacturerPartParameterTable.tsx similarity index 84% rename from src/frontend/src/components/tables/purchasing/ManufacturerPartParameterTable.tsx rename to src/frontend/src/tables/purchasing/ManufacturerPartParameterTable.tsx index 5e5c6f046f..299b0ad830 100644 --- a/src/frontend/src/components/tables/purchasing/ManufacturerPartParameterTable.tsx +++ b/src/frontend/src/tables/purchasing/ManufacturerPartParameterTable.tsx @@ -1,13 +1,13 @@ import { t } from '@lingui/macro'; import { useCallback, useMemo } from 'react'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { UserRoles } from '../../../enums/Roles'; -import { useManufacturerPartParameterFields } from '../../../forms/CompanyForms'; -import { openDeleteApiForm, openEditApiForm } from '../../../functions/forms'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { useUserState } from '../../../states/UserState'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { UserRoles } from '../../enums/Roles'; +import { useManufacturerPartParameterFields } from '../../forms/CompanyForms'; +import { openDeleteApiForm, openEditApiForm } from '../../functions/forms'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; +import { useUserState } from '../../states/UserState'; import { TableColumn } from '../Column'; import { InvenTreeTable } from '../InvenTreeTable'; import { RowDeleteAction, RowEditAction } from '../RowActions'; diff --git a/src/frontend/src/components/tables/purchasing/ManufacturerPartTable.tsx b/src/frontend/src/tables/purchasing/ManufacturerPartTable.tsx similarity index 82% rename from src/frontend/src/components/tables/purchasing/ManufacturerPartTable.tsx rename to src/frontend/src/tables/purchasing/ManufacturerPartTable.tsx index b8782937a6..93ff5be477 100644 --- a/src/frontend/src/components/tables/purchasing/ManufacturerPartTable.tsx +++ b/src/frontend/src/tables/purchasing/ManufacturerPartTable.tsx @@ -2,18 +2,18 @@ import { t } from '@lingui/macro'; import { ReactNode, useCallback, useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { ModelType } from '../../../enums/ModelType'; -import { UserRoles } from '../../../enums/Roles'; -import { useManufacturerPartFields } from '../../../forms/CompanyForms'; -import { openDeleteApiForm, openEditApiForm } from '../../../functions/forms'; -import { notYetImplemented } from '../../../functions/notifications'; -import { getDetailUrl } from '../../../functions/urls'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { useUserState } from '../../../states/UserState'; -import { AddItemButton } from '../../buttons/AddItemButton'; -import { Thumbnail } from '../../images/Thumbnail'; +import { AddItemButton } from '../../components/buttons/AddItemButton'; +import { Thumbnail } from '../../components/images/Thumbnail'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { ModelType } from '../../enums/ModelType'; +import { UserRoles } from '../../enums/Roles'; +import { useManufacturerPartFields } from '../../forms/CompanyForms'; +import { openDeleteApiForm, openEditApiForm } from '../../functions/forms'; +import { notYetImplemented } from '../../functions/notifications'; +import { getDetailUrl } from '../../functions/urls'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; +import { useUserState } from '../../states/UserState'; import { TableColumn } from '../Column'; import { DescriptionColumn, LinkColumn, PartColumn } from '../ColumnRenderers'; import { InvenTreeTable } from '../InvenTreeTable'; @@ -33,14 +33,12 @@ export function ManufacturerPartTable({ params }: { params: any }): ReactNode { return [ { accessor: 'part', - title: t`Part`, switchable: 'part' in params, sortable: true, render: (record: any) => PartColumn(record?.part_detail) }, { accessor: 'manufacturer', - title: t`Manufacturer`, sortable: true, render: (record: any) => { let manufacturer = record?.manufacturer_detail ?? {}; diff --git a/src/frontend/src/components/tables/purchasing/PurchaseOrderLineItemTable.tsx b/src/frontend/src/tables/purchasing/PurchaseOrderLineItemTable.tsx similarity index 88% rename from src/frontend/src/components/tables/purchasing/PurchaseOrderLineItemTable.tsx rename to src/frontend/src/tables/purchasing/PurchaseOrderLineItemTable.tsx index 28be8e3217..99b958eb6a 100644 --- a/src/frontend/src/components/tables/purchasing/PurchaseOrderLineItemTable.tsx +++ b/src/frontend/src/tables/purchasing/PurchaseOrderLineItemTable.tsx @@ -4,27 +4,28 @@ import { IconSquareArrowRight } from '@tabler/icons-react'; import { useCallback, useMemo, useState } from 'react'; import { useNavigate } from 'react-router-dom'; -import { ProgressBar } from '../../../components/items/ProgressBar'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { ModelType } from '../../../enums/ModelType'; -import { UserRoles } from '../../../enums/Roles'; -import { purchaseOrderLineItemFields } from '../../../forms/PurchaseOrderForms'; -import { getDetailUrl } from '../../../functions/urls'; +import { ActionButton } from '../../components/buttons/ActionButton'; +import { AddItemButton } from '../../components/buttons/AddItemButton'; +import { Thumbnail } from '../../components/images/Thumbnail'; +import { ProgressBar } from '../../components/items/ProgressBar'; +import { RenderStockLocation } from '../../components/render/Stock'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { ModelType } from '../../enums/ModelType'; +import { UserRoles } from '../../enums/Roles'; +import { purchaseOrderLineItemFields } from '../../forms/PurchaseOrderForms'; +import { getDetailUrl } from '../../functions/urls'; import { useCreateApiFormModal, useDeleteApiFormModal, useEditApiFormModal -} from '../../../hooks/UseForm'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { useUserState } from '../../../states/UserState'; -import { ActionButton } from '../../buttons/ActionButton'; -import { AddItemButton } from '../../buttons/AddItemButton'; -import { Thumbnail } from '../../images/Thumbnail'; -import { RenderStockLocation } from '../../render/Stock'; +} from '../../hooks/UseForm'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; +import { useUserState } from '../../states/UserState'; import { CurrencyColumn, LinkColumn, + ReferenceColumn, TargetDateColumn, TotalPriceColumn } from '../ColumnRenderers'; @@ -74,11 +75,7 @@ export function PurchaseOrderLineItemTable({ sortable: false, render: (record: any) => record?.part_detail?.description }, - { - accessor: 'reference', - title: t`Reference`, - sortable: true - }, + ReferenceColumn(), { accessor: 'quantity', title: t`Quantity`, diff --git a/src/frontend/src/components/tables/purchasing/PurchaseOrderTable.tsx b/src/frontend/src/tables/purchasing/PurchaseOrderTable.tsx similarity index 78% rename from src/frontend/src/components/tables/purchasing/PurchaseOrderTable.tsx rename to src/frontend/src/tables/purchasing/PurchaseOrderTable.tsx index eca41fd789..418ac20e1a 100644 --- a/src/frontend/src/components/tables/purchasing/PurchaseOrderTable.tsx +++ b/src/frontend/src/tables/purchasing/PurchaseOrderTable.tsx @@ -2,22 +2,23 @@ import { t } from '@lingui/macro'; import { useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { ModelType } from '../../../enums/ModelType'; -import { UserRoles } from '../../../enums/Roles'; -import { purchaseOrderFields } from '../../../forms/PurchaseOrderForms'; -import { getDetailUrl } from '../../../functions/urls'; -import { useCreateApiFormModal } from '../../../hooks/UseForm'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { useUserState } from '../../../states/UserState'; -import { AddItemButton } from '../../buttons/AddItemButton'; -import { Thumbnail } from '../../images/Thumbnail'; +import { AddItemButton } from '../../components/buttons/AddItemButton'; +import { Thumbnail } from '../../components/images/Thumbnail'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { ModelType } from '../../enums/ModelType'; +import { UserRoles } from '../../enums/Roles'; +import { purchaseOrderFields } from '../../forms/PurchaseOrderForms'; +import { getDetailUrl } from '../../functions/urls'; +import { useCreateApiFormModal } from '../../hooks/UseForm'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; +import { useUserState } from '../../states/UserState'; import { CreationDateColumn, DescriptionColumn, LineItemsProgressColumn, ProjectCodeColumn, + ReferenceColumn, ResponsibleColumn, StatusColumn, TargetDateColumn, @@ -65,13 +66,7 @@ export function PurchaseOrderTable({ const tableColumns = useMemo(() => { return [ - { - accessor: 'reference', - title: t`Reference`, - sortable: true, - switchable: false - // TODO: Display extra information if order is overdue - }, + ReferenceColumn(), DescriptionColumn({}), { accessor: 'supplier__name', @@ -90,8 +85,7 @@ export function PurchaseOrderTable({ } }, { - accessor: 'supplier_reference', - title: t`Supplier Reference` + accessor: 'supplier_reference' }, LineItemsProgressColumn(), StatusColumn(ModelType.purchaseorder), diff --git a/src/frontend/src/components/tables/purchasing/SupplierPartTable.tsx b/src/frontend/src/tables/purchasing/SupplierPartTable.tsx similarity index 84% rename from src/frontend/src/components/tables/purchasing/SupplierPartTable.tsx rename to src/frontend/src/tables/purchasing/SupplierPartTable.tsx index 587ee1baa1..d980077c2a 100644 --- a/src/frontend/src/components/tables/purchasing/SupplierPartTable.tsx +++ b/src/frontend/src/tables/purchasing/SupplierPartTable.tsx @@ -3,20 +3,25 @@ import { Text } from '@mantine/core'; import { ReactNode, useCallback, useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { ModelType } from '../../../enums/ModelType'; -import { UserRoles } from '../../../enums/Roles'; -import { useSupplierPartFields } from '../../../forms/CompanyForms'; -import { openDeleteApiForm, openEditApiForm } from '../../../functions/forms'; -import { getDetailUrl } from '../../../functions/urls'; -import { useCreateApiFormModal } from '../../../hooks/UseForm'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { useUserState } from '../../../states/UserState'; -import { AddItemButton } from '../../buttons/AddItemButton'; -import { Thumbnail } from '../../images/Thumbnail'; +import { AddItemButton } from '../../components/buttons/AddItemButton'; +import { Thumbnail } from '../../components/images/Thumbnail'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { ModelType } from '../../enums/ModelType'; +import { UserRoles } from '../../enums/Roles'; +import { useSupplierPartFields } from '../../forms/CompanyForms'; +import { openDeleteApiForm, openEditApiForm } from '../../functions/forms'; +import { getDetailUrl } from '../../functions/urls'; +import { useCreateApiFormModal } from '../../hooks/UseForm'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; +import { useUserState } from '../../states/UserState'; import { TableColumn } from '../Column'; -import { DescriptionColumn, LinkColumn, PartColumn } from '../ColumnRenderers'; +import { + DescriptionColumn, + LinkColumn, + NoteColumn, + PartColumn +} from '../ColumnRenderers'; import { InvenTreeTable } from '../InvenTreeTable'; import { RowDeleteAction, RowEditAction } from '../RowActions'; import { TableHoverCard } from '../TableHoverCard'; @@ -36,14 +41,12 @@ export function SupplierPartTable({ params }: { params: any }): ReactNode { return [ { accessor: 'part', - title: t`Part`, switchable: 'part' in params, sortable: true, render: (record: any) => PartColumn(record?.part_detail) }, { accessor: 'supplier', - title: t`Supplier`, sortable: true, render: (record: any) => { let supplier = record?.supplier_detail ?? {}; @@ -68,7 +71,6 @@ export function SupplierPartTable({ params }: { params: any }): ReactNode { accessor: 'manufacturer', sortable: true, - title: t`Manufacturer`, render: (record: any) => { let manufacturer = record?.manufacturer_detail ?? {}; @@ -91,17 +93,14 @@ export function SupplierPartTable({ params }: { params: any }): ReactNode { }, { accessor: 'in_stock', - title: t`In Stock`, sortable: true }, { accessor: 'packaging', - title: t`Packaging`, sortable: true }, { accessor: 'pack_quantity', - title: t`Pack Quantity`, sortable: true, render: (record: any) => { @@ -127,14 +126,9 @@ export function SupplierPartTable({ params }: { params: any }): ReactNode { } }, LinkColumn(), - { - accessor: 'note', - title: t`Notes`, - sortable: false - }, + NoteColumn(), { accessor: 'available', - title: t`Availability`, sortable: true, render: (record: any) => { diff --git a/src/frontend/src/components/tables/sales/ReturnOrderTable.tsx b/src/frontend/src/tables/sales/ReturnOrderTable.tsx similarity index 73% rename from src/frontend/src/components/tables/sales/ReturnOrderTable.tsx rename to src/frontend/src/tables/sales/ReturnOrderTable.tsx index 6609df0cc0..a917e4117f 100644 --- a/src/frontend/src/components/tables/sales/ReturnOrderTable.tsx +++ b/src/frontend/src/tables/sales/ReturnOrderTable.tsx @@ -2,24 +2,26 @@ import { t } from '@lingui/macro'; import { useCallback, useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { ModelType } from '../../../enums/ModelType'; -import { UserRoles } from '../../../enums/Roles'; -import { notYetImplemented } from '../../../functions/notifications'; -import { getDetailUrl } from '../../../functions/urls'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { useUserState } from '../../../states/UserState'; -import { AddItemButton } from '../../buttons/AddItemButton'; -import { Thumbnail } from '../../images/Thumbnail'; +import { AddItemButton } from '../../components/buttons/AddItemButton'; +import { Thumbnail } from '../../components/images/Thumbnail'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { ModelType } from '../../enums/ModelType'; +import { UserRoles } from '../../enums/Roles'; +import { notYetImplemented } from '../../functions/notifications'; +import { getDetailUrl } from '../../functions/urls'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; +import { useUserState } from '../../states/UserState'; import { CreationDateColumn, DescriptionColumn, LineItemsProgressColumn, ProjectCodeColumn, + ReferenceColumn, ResponsibleColumn, StatusColumn, - TargetDateColumn + TargetDateColumn, + TotalPriceColumn } from '../ColumnRenderers'; import { AssignedToMeFilter, @@ -56,12 +58,7 @@ export function ReturnOrderTable({ params }: { params?: any }) { const tableColumns = useMemo(() => { return [ - { - accessor: 'reference', - title: t`Return Order`, - sortable: true - // TODO: Display extra information if order is overdue - }, + ReferenceColumn(), { accessor: 'customer__name', title: t`Customer`, @@ -79,8 +76,7 @@ export function ReturnOrderTable({ params }: { params?: any }) { } }, { - accessor: 'customer_reference', - title: t`Customer Reference` + accessor: 'customer_reference' }, DescriptionColumn({}), LineItemsProgressColumn(), @@ -89,10 +85,7 @@ export function ReturnOrderTable({ params }: { params?: any }) { CreationDateColumn(), TargetDateColumn(), ResponsibleColumn(), - { - accessor: 'total_cost', - title: t`Total Cost` - } + TotalPriceColumn() ]; }, []); diff --git a/src/frontend/src/components/tables/sales/SalesOrderTable.tsx b/src/frontend/src/tables/sales/SalesOrderTable.tsx similarity index 79% rename from src/frontend/src/components/tables/sales/SalesOrderTable.tsx rename to src/frontend/src/tables/sales/SalesOrderTable.tsx index 1344a018b0..c007305072 100644 --- a/src/frontend/src/components/tables/sales/SalesOrderTable.tsx +++ b/src/frontend/src/tables/sales/SalesOrderTable.tsx @@ -2,22 +2,23 @@ import { t } from '@lingui/macro'; import { useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { ModelType } from '../../../enums/ModelType'; -import { UserRoles } from '../../../enums/Roles'; -import { salesOrderFields } from '../../../forms/SalesOrderForms'; -import { getDetailUrl } from '../../../functions/urls'; -import { useCreateApiFormModal } from '../../../hooks/UseForm'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { useUserState } from '../../../states/UserState'; -import { AddItemButton } from '../../buttons/AddItemButton'; -import { Thumbnail } from '../../images/Thumbnail'; +import { AddItemButton } from '../../components/buttons/AddItemButton'; +import { Thumbnail } from '../../components/images/Thumbnail'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { ModelType } from '../../enums/ModelType'; +import { UserRoles } from '../../enums/Roles'; +import { salesOrderFields } from '../../forms/SalesOrderForms'; +import { getDetailUrl } from '../../functions/urls'; +import { useCreateApiFormModal } from '../../hooks/UseForm'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; +import { useUserState } from '../../states/UserState'; import { CreationDateColumn, DescriptionColumn, LineItemsProgressColumn, ProjectCodeColumn, + ReferenceColumn, ShipmentDateColumn, StatusColumn, TargetDateColumn, @@ -88,13 +89,7 @@ export function SalesOrderTable({ const tableColumns = useMemo(() => { return [ - { - accessor: 'reference', - title: t`Sales Order`, - sortable: true, - switchable: false - // TODO: Display extra information if order is overdue - }, + ReferenceColumn(), { accessor: 'customer__name', title: t`Customer`, diff --git a/src/frontend/src/components/tables/settings/CurrencyTable.tsx b/src/frontend/src/tables/settings/CurrencyTable.tsx similarity index 87% rename from src/frontend/src/components/tables/settings/CurrencyTable.tsx rename to src/frontend/src/tables/settings/CurrencyTable.tsx index f9fb425136..6773f85473 100644 --- a/src/frontend/src/components/tables/settings/CurrencyTable.tsx +++ b/src/frontend/src/tables/settings/CurrencyTable.tsx @@ -3,11 +3,11 @@ import { showNotification } from '@mantine/notifications'; import { IconReload } from '@tabler/icons-react'; import { useCallback, useMemo } from 'react'; -import { api } from '../../../App'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { ActionButton } from '../../buttons/ActionButton'; +import { api } from '../../App'; +import { ActionButton } from '../../components/buttons/ActionButton'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; import { InvenTreeTable } from '../InvenTreeTable'; /* diff --git a/src/frontend/src/components/tables/settings/CustomUnitsTable.tsx b/src/frontend/src/tables/settings/CustomUnitsTable.tsx similarity index 84% rename from src/frontend/src/components/tables/settings/CustomUnitsTable.tsx rename to src/frontend/src/tables/settings/CustomUnitsTable.tsx index 371dcb49a7..4e7bbc30fe 100644 --- a/src/frontend/src/components/tables/settings/CustomUnitsTable.tsx +++ b/src/frontend/src/tables/settings/CustomUnitsTable.tsx @@ -1,18 +1,18 @@ import { t } from '@lingui/macro'; import { useCallback, useMemo, useState } from 'react'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { UserRoles } from '../../../enums/Roles'; -import { customUnitsFields } from '../../../forms/CommonForms'; +import { AddItemButton } from '../../components/buttons/AddItemButton'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { UserRoles } from '../../enums/Roles'; +import { customUnitsFields } from '../../forms/CommonForms'; import { useCreateApiFormModal, useDeleteApiFormModal, useEditApiFormModal -} from '../../../hooks/UseForm'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { useUserState } from '../../../states/UserState'; -import { AddItemButton } from '../../buttons/AddItemButton'; +} from '../../hooks/UseForm'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; +import { useUserState } from '../../states/UserState'; import { TableColumn } from '../Column'; import { InvenTreeTable } from '../InvenTreeTable'; import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions'; @@ -29,19 +29,16 @@ export default function CustomUnitsTable() { return [ { accessor: 'name', - title: t`Name`, switchable: false, sortable: true }, { accessor: 'definition', - title: t`Definition`, switchable: false, sortable: false }, { accessor: 'symbol', - title: t`Symbol`, switchable: false, sortable: true } diff --git a/src/frontend/src/components/tables/settings/ErrorTable.tsx b/src/frontend/src/tables/settings/ErrorTable.tsx similarity index 88% rename from src/frontend/src/components/tables/settings/ErrorTable.tsx rename to src/frontend/src/tables/settings/ErrorTable.tsx index b61c2f1fe8..0141807ec8 100644 --- a/src/frontend/src/components/tables/settings/ErrorTable.tsx +++ b/src/frontend/src/tables/settings/ErrorTable.tsx @@ -3,11 +3,11 @@ import { Drawer, Text } from '@mantine/core'; import { useDisclosure } from '@mantine/hooks'; import { useCallback, useMemo, useState } from 'react'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { openDeleteApiForm } from '../../../functions/forms'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { StylishText } from '../../items/StylishText'; +import { StylishText } from '../../components/items/StylishText'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { openDeleteApiForm } from '../../functions/forms'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; import { TableColumn } from '../Column'; import { InvenTreeTable } from '../InvenTreeTable'; import { RowAction, RowDeleteAction } from '../RowActions'; diff --git a/src/frontend/src/components/tables/settings/FailedTasksTable.tsx b/src/frontend/src/tables/settings/FailedTasksTable.tsx similarity index 88% rename from src/frontend/src/components/tables/settings/FailedTasksTable.tsx rename to src/frontend/src/tables/settings/FailedTasksTable.tsx index 666126a0d2..ec7a636f36 100644 --- a/src/frontend/src/components/tables/settings/FailedTasksTable.tsx +++ b/src/frontend/src/tables/settings/FailedTasksTable.tsx @@ -3,10 +3,10 @@ import { Drawer, Text } from '@mantine/core'; import { useDisclosure } from '@mantine/hooks'; import { useMemo, useState } from 'react'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { StylishText } from '../../items/StylishText'; +import { StylishText } from '../../components/items/StylishText'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; import { TableColumn } from '../Column'; import { InvenTreeTable } from '../InvenTreeTable'; diff --git a/src/frontend/src/components/tables/settings/GroupTable.tsx b/src/frontend/src/tables/settings/GroupTable.tsx similarity index 88% rename from src/frontend/src/components/tables/settings/GroupTable.tsx rename to src/frontend/src/tables/settings/GroupTable.tsx index 58c1d66f29..78538b7381 100644 --- a/src/frontend/src/components/tables/settings/GroupTable.tsx +++ b/src/frontend/src/tables/settings/GroupTable.tsx @@ -3,18 +3,18 @@ import { Group, LoadingOverlay, Stack, Text, Title } from '@mantine/core'; import { useCallback, useMemo, useState } from 'react'; import { useNavigate } from 'react-router-dom'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; +import { AddItemButton } from '../../components/buttons/AddItemButton'; +import { EditApiForm } from '../../components/forms/ApiForm'; +import { PlaceholderPill } from '../../components/items/Placeholder'; +import { DetailDrawer } from '../../components/nav/DetailDrawer'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { useCreateApiFormModal, useDeleteApiFormModal -} from '../../../hooks/UseForm'; -import { useInstance } from '../../../hooks/UseInstance'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { AddItemButton } from '../../buttons/AddItemButton'; -import { EditApiForm } from '../../forms/ApiForm'; -import { PlaceholderPill } from '../../items/Placeholder'; -import { DetailDrawer } from '../../nav/DetailDrawer'; +} from '../../hooks/UseForm'; +import { useInstance } from '../../hooks/UseInstance'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; import { TableColumn } from '../Column'; import { InvenTreeTable } from '../InvenTreeTable'; import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions'; diff --git a/src/frontend/src/components/tables/settings/PendingTasksTable.tsx b/src/frontend/src/tables/settings/PendingTasksTable.tsx similarity index 86% rename from src/frontend/src/components/tables/settings/PendingTasksTable.tsx rename to src/frontend/src/tables/settings/PendingTasksTable.tsx index bad6c8a58c..7177427c7c 100644 --- a/src/frontend/src/components/tables/settings/PendingTasksTable.tsx +++ b/src/frontend/src/tables/settings/PendingTasksTable.tsx @@ -1,9 +1,9 @@ import { t } from '@lingui/macro'; import { useMemo } from 'react'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; import { TableColumn } from '../Column'; import { InvenTreeTable } from '../InvenTreeTable'; diff --git a/src/frontend/src/components/tables/settings/ProjectCodeTable.tsx b/src/frontend/src/tables/settings/ProjectCodeTable.tsx similarity index 84% rename from src/frontend/src/components/tables/settings/ProjectCodeTable.tsx rename to src/frontend/src/tables/settings/ProjectCodeTable.tsx index 51c8ce0c89..9161975032 100644 --- a/src/frontend/src/components/tables/settings/ProjectCodeTable.tsx +++ b/src/frontend/src/tables/settings/ProjectCodeTable.tsx @@ -1,18 +1,18 @@ import { t } from '@lingui/macro'; import { useCallback, useMemo, useState } from 'react'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { UserRoles } from '../../../enums/Roles'; -import { projectCodeFields } from '../../../forms/CommonForms'; +import { AddItemButton } from '../../components/buttons/AddItemButton'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { UserRoles } from '../../enums/Roles'; +import { projectCodeFields } from '../../forms/CommonForms'; import { useCreateApiFormModal, useDeleteApiFormModal, useEditApiFormModal -} from '../../../hooks/UseForm'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { useUserState } from '../../../states/UserState'; -import { AddItemButton } from '../../buttons/AddItemButton'; +} from '../../hooks/UseForm'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; +import { useUserState } from '../../states/UserState'; import { TableColumn } from '../Column'; import { DescriptionColumn, ResponsibleColumn } from '../ColumnRenderers'; import { InvenTreeTable } from '../InvenTreeTable'; @@ -30,8 +30,7 @@ export default function ProjectCodeTable() { return [ { accessor: 'code', - sortable: true, - title: t`Project Code` + sortable: true }, DescriptionColumn({}), ResponsibleColumn() diff --git a/src/frontend/src/components/tables/settings/ScheduledTasksTable.tsx b/src/frontend/src/tables/settings/ScheduledTasksTable.tsx similarity index 89% rename from src/frontend/src/components/tables/settings/ScheduledTasksTable.tsx rename to src/frontend/src/tables/settings/ScheduledTasksTable.tsx index ff5bc93b07..a6701c5123 100644 --- a/src/frontend/src/components/tables/settings/ScheduledTasksTable.tsx +++ b/src/frontend/src/tables/settings/ScheduledTasksTable.tsx @@ -3,9 +3,9 @@ import { Group, Text } from '@mantine/core'; import { IconCircleCheck, IconCircleX } from '@tabler/icons-react'; import { useMemo } from 'react'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; import { TableColumn } from '../Column'; import { InvenTreeTable } from '../InvenTreeTable'; diff --git a/src/frontend/src/components/tables/settings/UserTable.tsx b/src/frontend/src/tables/settings/UserTable.tsx similarity index 86% rename from src/frontend/src/components/tables/settings/UserTable.tsx rename to src/frontend/src/tables/settings/UserTable.tsx index 2972f77b18..8c00be1ce9 100644 --- a/src/frontend/src/components/tables/settings/UserTable.tsx +++ b/src/frontend/src/tables/settings/UserTable.tsx @@ -5,15 +5,15 @@ import { useCallback, useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; import { Link } from 'react-router-dom'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { openCreateApiForm, openDeleteApiForm } from '../../../functions/forms'; -import { useInstance } from '../../../hooks/UseInstance'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { useUserState } from '../../../states/UserState'; -import { AddItemButton } from '../../buttons/AddItemButton'; -import { EditApiForm } from '../../forms/ApiForm'; -import { DetailDrawer } from '../../nav/DetailDrawer'; +import { AddItemButton } from '../../components/buttons/AddItemButton'; +import { EditApiForm } from '../../components/forms/ApiForm'; +import { DetailDrawer } from '../../components/nav/DetailDrawer'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { openCreateApiForm, openDeleteApiForm } from '../../functions/forms'; +import { useInstance } from '../../hooks/UseInstance'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; +import { useUserState } from '../../states/UserState'; import { TableColumn } from '../Column'; import { BooleanColumn } from '../ColumnRenderers'; import { InvenTreeTable } from '../InvenTreeTable'; @@ -153,45 +153,37 @@ export function UserTable() { return [ { accessor: 'email', - sortable: true, - title: t`Email` + sortable: true }, { accessor: 'username', sortable: true, - switchable: false, - title: t`Username` + switchable: false }, { accessor: 'first_name', - sortable: true, - title: t`First Name` + sortable: true }, { accessor: 'last_name', - sortable: true, - title: t`Last Name` + sortable: true }, { accessor: 'groups', sortable: true, switchable: true, - title: t`Groups`, render: (record: any) => { return record.groups.length; } }, BooleanColumn({ - accessor: 'is_staff', - title: t`Staff` + accessor: 'is_staff' }), BooleanColumn({ - accessor: 'is_superuser', - title: t`Superuser` + accessor: 'is_superuser' }), BooleanColumn({ - accessor: 'is_active', - title: t`Active` + accessor: 'is_active' }) ]; }, []); diff --git a/src/frontend/src/components/tables/stock/StockItemTable.tsx b/src/frontend/src/tables/stock/StockItemTable.tsx similarity index 92% rename from src/frontend/src/components/tables/stock/StockItemTable.tsx rename to src/frontend/src/tables/stock/StockItemTable.tsx index 337ab4b396..567031268d 100644 --- a/src/frontend/src/components/tables/stock/StockItemTable.tsx +++ b/src/frontend/src/tables/stock/StockItemTable.tsx @@ -3,17 +3,21 @@ import { Group, Text } from '@mantine/core'; import { ReactNode, useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; -import { formatCurrency, renderDate } from '../../../defaults/formatters'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { ModelType } from '../../../enums/ModelType'; -import { getDetailUrl } from '../../../functions/urls'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; +import { formatCurrency, renderDate } from '../../defaults/formatters'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { ModelType } from '../../enums/ModelType'; +import { getDetailUrl } from '../../functions/urls'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; import { TableColumn } from '../Column'; -import { PartColumn, StatusColumn } from '../ColumnRenderers'; +import { + DescriptionColumn, + PartColumn, + StatusColumn +} from '../ColumnRenderers'; import { StatusFilterOptions, TableFilter } from '../Filter'; +import { InvenTreeTable } from '../InvenTreeTable'; import { TableHoverCard } from '../TableHoverCard'; -import { InvenTreeTable } from './../InvenTreeTable'; /** * Construct a list of columns for the stock item table @@ -23,14 +27,11 @@ function stockItemTableColumns(): TableColumn[] { { accessor: 'part', sortable: true, - title: t`Part`, render: (record: any) => PartColumn(record?.part_detail) }, - { - accessor: 'part_detail.description', - sortable: false, - title: t`Description` - }, + DescriptionColumn({ + accessor: 'part_detail.description' + }), { accessor: 'quantity', sortable: true, @@ -176,15 +177,11 @@ function stockItemTableColumns(): TableColumn[] { StatusColumn(ModelType.stockitem), { accessor: 'batch', - sortable: true, - - title: t`Batch` + sortable: true }, { accessor: 'location', sortable: true, - - title: t`Location`, render: function (record: any) { // TODO: Custom renderer for location // TODO: Note, if not "In stock" we don't want to display the actual location here @@ -195,14 +192,12 @@ function stockItemTableColumns(): TableColumn[] { { accessor: 'expiry_date', sortable: true, - title: t`Expiry Date`, switchable: true, render: (record: any) => renderDate(record.expiry_date) }, { accessor: 'updated', sortable: true, - title: t`Last Updated`, switchable: true, render: (record: any) => renderDate(record.updated) }, @@ -211,7 +206,6 @@ function stockItemTableColumns(): TableColumn[] { { accessor: 'purchase_price', sortable: true, - title: t`Purchase Price`, switchable: true, render: (record: any) => formatCurrency(record.purchase_price, { diff --git a/src/frontend/src/components/tables/stock/StockLocationTable.tsx b/src/frontend/src/tables/stock/StockLocationTable.tsx similarity index 75% rename from src/frontend/src/components/tables/stock/StockLocationTable.tsx rename to src/frontend/src/tables/stock/StockLocationTable.tsx index b5254f2dc4..3437e6843e 100644 --- a/src/frontend/src/components/tables/stock/StockLocationTable.tsx +++ b/src/frontend/src/tables/stock/StockLocationTable.tsx @@ -2,22 +2,21 @@ import { t } from '@lingui/macro'; import { useCallback, useMemo, useState } from 'react'; import { useNavigate } from 'react-router-dom'; -import { ApiEndpoints } from '../../../enums/ApiEndpoints'; -import { ModelType } from '../../../enums/ModelType'; -import { UserRoles } from '../../../enums/Roles'; -import { stockLocationFields } from '../../../forms/StockForms'; -import { getDetailUrl } from '../../../functions/urls'; +import { AddItemButton } from '../../components/buttons/AddItemButton'; +import { ApiEndpoints } from '../../enums/ApiEndpoints'; +import { ModelType } from '../../enums/ModelType'; +import { UserRoles } from '../../enums/Roles'; +import { stockLocationFields } from '../../forms/StockForms'; +import { getDetailUrl } from '../../functions/urls'; import { useCreateApiFormModal, useEditApiFormModal -} from '../../../hooks/UseForm'; -import { useTable } from '../../../hooks/UseTable'; -import { apiUrl } from '../../../states/ApiState'; -import { useUserState } from '../../../states/UserState'; -import { AddItemButton } from '../../buttons/AddItemButton'; -import { YesNoButton } from '../../items/YesNoButton'; +} from '../../hooks/UseForm'; +import { useTable } from '../../hooks/UseTable'; +import { apiUrl } from '../../states/ApiState'; +import { useUserState } from '../../states/UserState'; import { TableColumn } from '../Column'; -import { DescriptionColumn } from '../ColumnRenderers'; +import { BooleanColumn, DescriptionColumn } from '../ColumnRenderers'; import { TableFilter } from '../Filter'; import { InvenTreeTable } from '../InvenTreeTable'; import { RowEditAction } from '../RowActions'; @@ -40,12 +39,10 @@ export function StockLocationTable({ parentId }: { parentId?: any }) { }, { name: 'structural', - label: t`Structural`, description: t`Show structural locations` }, { name: 'external', - label: t`External`, description: t`Show external locations` }, { @@ -60,39 +57,25 @@ export function StockLocationTable({ parentId }: { parentId?: any }) { return [ { accessor: 'name', - title: t`Name`, switchable: false }, DescriptionColumn({}), { accessor: 'pathstring', - title: t`Path`, sortable: true }, { accessor: 'items', - title: t`Stock Items`, - sortable: true }, - { - accessor: 'structural', - title: t`Structural`, - - sortable: true, - render: (record: any) => - }, - { - accessor: 'external', - title: t`External`, - - sortable: true, - render: (record: any) => - }, + BooleanColumn({ + accessor: 'structural' + }), + BooleanColumn({ + accessor: 'external' + }), { accessor: 'location_type', - title: t`Location Type`, - sortable: false, render: (record: any) => record.location_type_detail?.name } diff --git a/src/frontend/src/views/DesktopAppView.tsx b/src/frontend/src/views/DesktopAppView.tsx index c0598c04c7..410b85b94f 100644 --- a/src/frontend/src/views/DesktopAppView.tsx +++ b/src/frontend/src/views/DesktopAppView.tsx @@ -35,7 +35,6 @@ export default function DesktopAppView() { const [token] = sessionState.token ? [sessionState.token] : [null]; useEffect(() => { if (Object.keys(hostList).length === 0) { - console.log('Loading default host list', defaultHostList); useLocalState.setState({ hostList: defaultHostList }); }