mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-31 05:05:42 +00:00 
			
		
		
		
	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 <code@mjmair.com> * 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 <code@mjmair.com>
This commit is contained in:
		| @@ -1075,16 +1075,34 @@ class BuildLineSerializer(InvenTreeModelSerializer): | |||||||
|  |  | ||||||
|     quantity = serializers.FloatField() |     quantity = serializers.FloatField() | ||||||
|  |  | ||||||
|  |     bom_item = serializers.PrimaryKeyRelatedField(label=_('Bom Item'), read_only=True) | ||||||
|  |  | ||||||
|     # Foreign key fields |     # Foreign key fields | ||||||
|     bom_item_detail = BomItemSerializer(source='bom_item', many=False, read_only=True, pricing=False) |     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) |     part_detail = PartSerializer(source='bom_item.sub_part', many=False, read_only=True, pricing=False) | ||||||
|     allocations = BuildItemSerializer(many=True, read_only=True) |     allocations = BuildItemSerializer(many=True, read_only=True) | ||||||
|  |  | ||||||
|     # Annotated (calculated) fields |     # Annotated (calculated) fields | ||||||
|     allocated = serializers.FloatField(read_only=True) |     allocated = serializers.FloatField( | ||||||
|     on_order = serializers.FloatField(read_only=True) |         label=_('Allocated Stock'), | ||||||
|     in_production = serializers.FloatField(read_only=True) |         read_only=True | ||||||
|     available_stock = serializers.FloatField(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_substitute_stock = serializers.FloatField(read_only=True) | ||||||
|     available_variant_stock = serializers.FloatField(read_only=True) |     available_variant_stock = serializers.FloatField(read_only=True) | ||||||
|     total_available_stock = serializers.FloatField(read_only=True) |     total_available_stock = serializers.FloatField(read_only=True) | ||||||
|   | |||||||
| @@ -1408,8 +1408,9 @@ class BomItemSerializer(InvenTree.serializers.InvenTreeModelSerializer): | |||||||
|  |  | ||||||
|     sub_part_detail = PartBriefSerializer(source='sub_part', many=False, read_only=True) |     sub_part_detail = PartBriefSerializer(source='sub_part', many=False, read_only=True) | ||||||
|  |  | ||||||
|     on_order = serializers.FloatField(read_only=True) |     on_order = serializers.FloatField(label=_('On Order'), read_only=True) | ||||||
|     building = serializers.FloatField(read_only=True) |  | ||||||
|  |     building = serializers.FloatField(label=_('In Production'), read_only=True) | ||||||
|  |  | ||||||
|     # Cached pricing fields |     # Cached pricing fields | ||||||
|     pricing_min = InvenTree.serializers.InvenTreeMoneySerializer( |     pricing_min = InvenTree.serializers.InvenTreeMoneySerializer( | ||||||
| @@ -1420,7 +1421,8 @@ class BomItemSerializer(InvenTree.serializers.InvenTreeModelSerializer): | |||||||
|     ) |     ) | ||||||
|  |  | ||||||
|     # Annotated fields for available stock |     # 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_substitute_stock = serializers.FloatField(read_only=True) | ||||||
|     available_variant_stock = serializers.FloatField(read_only=True) |     available_variant_stock = serializers.FloatField(read_only=True) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -18,8 +18,8 @@ import { api } from '../../App'; | |||||||
| import { UserRoles } from '../../enums/Roles'; | import { UserRoles } from '../../enums/Roles'; | ||||||
| import { InvenTreeIcon } from '../../functions/icons'; | import { InvenTreeIcon } from '../../functions/icons'; | ||||||
| import { useUserState } from '../../states/UserState'; | import { useUserState } from '../../states/UserState'; | ||||||
|  | import { PartThumbTable } from '../../tables/part/PartThumbTable'; | ||||||
| import { ActionButton } from '../buttons/ActionButton'; | import { ActionButton } from '../buttons/ActionButton'; | ||||||
| import { PartThumbTable } from '../tables/part/PartThumbTable'; |  | ||||||
| import { ApiImage } from './ApiImage'; | import { ApiImage } from './ApiImage'; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|   | |||||||
| @@ -92,6 +92,9 @@ export function LanguageContext({ children }: { children: JSX.Element }) { | |||||||
|  |  | ||||||
|         // Reload server state (refresh status codes) |         // Reload server state (refresh status codes) | ||||||
|         useServerApiState.getState().fetchServerApiState(); |         useServerApiState.getState().fetchServerApiState(); | ||||||
|  |  | ||||||
|  |         // Clear out cached table column names | ||||||
|  |         useLocalState.getState().clearTableColumnNames(); | ||||||
|       }) |       }) | ||||||
|       .catch((err) => { |       .catch((err) => { | ||||||
|         console.error('Failed loading translations', err); |         console.error('Failed loading translations', err); | ||||||
|   | |||||||
| @@ -263,7 +263,6 @@ export function openModalApiForm(props: OpenApiFormProps) { | |||||||
|       }); |       }); | ||||||
|     }) |     }) | ||||||
|     .catch((error) => { |     .catch((error) => { | ||||||
|       console.log('Error:', error); |  | ||||||
|       if (error.response) { |       if (error.response) { | ||||||
|         invalidResponse(error.response.status); |         invalidResponse(error.response.status); | ||||||
|       } else { |       } else { | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| import { randomId, useLocalStorage } from '@mantine/hooks'; | import { randomId, useLocalStorage } from '@mantine/hooks'; | ||||||
| import { useCallback, useState } from 'react'; | 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: |  * Type definition for representing the state of a table: | ||||||
|   | |||||||
| @@ -30,22 +30,19 @@ const PluginManagementPanel = Loadable( | |||||||
| ); | ); | ||||||
|  |  | ||||||
| const ErrorReportTable = Loadable( | const ErrorReportTable = Loadable( | ||||||
|   lazy(() => import('../../../../components/tables/settings/ErrorTable')) |   lazy(() => import('../../../../tables/settings/ErrorTable')) | ||||||
| ); | ); | ||||||
|  |  | ||||||
| const ProjectCodeTable = Loadable( | const ProjectCodeTable = Loadable( | ||||||
|   lazy(() => import('../../../../components/tables/settings/ProjectCodeTable')) |   lazy(() => import('../../../../tables/settings/ProjectCodeTable')) | ||||||
| ); | ); | ||||||
|  |  | ||||||
| const CustomUnitsTable = Loadable( | const CustomUnitsTable = Loadable( | ||||||
|   lazy(() => import('../../../../components/tables/settings/CustomUnitsTable')) |   lazy(() => import('../../../../tables/settings/CustomUnitsTable')) | ||||||
| ); | ); | ||||||
|  |  | ||||||
| const PartParameterTemplateTable = Loadable( | const PartParameterTemplateTable = Loadable( | ||||||
|   lazy( |   lazy(() => import('../../../../tables/part/PartParameterTemplateTable')) | ||||||
|     () => |  | ||||||
|       import('../../../../components/tables/part/PartParameterTemplateTable') |  | ||||||
|   ) |  | ||||||
| ); | ); | ||||||
|  |  | ||||||
| export default function AdminCenter() { | export default function AdminCenter() { | ||||||
|   | |||||||
| @@ -3,9 +3,9 @@ import { Alert, Stack, Title } from '@mantine/core'; | |||||||
| import { IconInfoCircle } from '@tabler/icons-react'; | import { IconInfoCircle } from '@tabler/icons-react'; | ||||||
|  |  | ||||||
| import { GlobalSettingList } from '../../../../components/settings/SettingList'; | 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 { useServerApiState } from '../../../../states/ApiState'; | ||||||
|  | import { PluginErrorTable } from '../../../../tables/plugin/PluginErrorTable'; | ||||||
|  | import { PluginListTable } from '../../../../tables/plugin/PluginListTable'; | ||||||
|  |  | ||||||
| export default function PluginManagementPanel() { | export default function PluginManagementPanel() { | ||||||
|   const pluginsEnabled = useServerApiState( |   const pluginsEnabled = useServerApiState( | ||||||
|   | |||||||
| @@ -6,17 +6,15 @@ import { StylishText } from '../../../../components/items/StylishText'; | |||||||
| import { Loadable } from '../../../../functions/loading'; | import { Loadable } from '../../../../functions/loading'; | ||||||
|  |  | ||||||
| const PendingTasksTable = Loadable( | const PendingTasksTable = Loadable( | ||||||
|   lazy(() => import('../../../../components/tables/settings/PendingTasksTable')) |   lazy(() => import('../../../../tables/settings/PendingTasksTable')) | ||||||
| ); | ); | ||||||
|  |  | ||||||
| const ScheduledTasksTable = Loadable( | const ScheduledTasksTable = Loadable( | ||||||
|   lazy( |   lazy(() => import('../../../../tables/settings/ScheduledTasksTable')) | ||||||
|     () => import('../../../../components/tables/settings/ScheduledTasksTable') |  | ||||||
|   ) |  | ||||||
| ); | ); | ||||||
|  |  | ||||||
| const FailedTasksTable = Loadable( | const FailedTasksTable = Loadable( | ||||||
|   lazy(() => import('../../../../components/tables/settings/FailedTasksTable')) |   lazy(() => import('../../../../tables/settings/FailedTasksTable')) | ||||||
| ); | ); | ||||||
|  |  | ||||||
| export default function TaskManagementPanel() { | export default function TaskManagementPanel() { | ||||||
|   | |||||||
| @@ -3,8 +3,8 @@ import { Anchor, Divider, Group, Stack, Text, Title } from '@mantine/core'; | |||||||
| import { Link } from 'react-router-dom'; | import { Link } from 'react-router-dom'; | ||||||
|  |  | ||||||
| import { GlobalSettingList } from '../../../../components/settings/SettingList'; | import { GlobalSettingList } from '../../../../components/settings/SettingList'; | ||||||
| import { GroupTable } from '../../../../components/tables/settings/GroupTable'; | import { GroupTable } from '../../../../tables/settings/GroupTable'; | ||||||
| import { UserTable } from '../../../../components/tables/settings/UserTable'; | import { UserTable } from '../../../../tables/settings/UserTable'; | ||||||
|  |  | ||||||
| export default function UserManagementPanel() { | export default function UserManagementPanel() { | ||||||
|   return ( |   return ( | ||||||
|   | |||||||
| @@ -23,8 +23,8 @@ import { StylishText } from '../../../components/items/StylishText'; | |||||||
| import { PanelGroup, PanelType } from '../../../components/nav/PanelGroup'; | import { PanelGroup, PanelType } from '../../../components/nav/PanelGroup'; | ||||||
| import { SettingsHeader } from '../../../components/nav/SettingsHeader'; | import { SettingsHeader } from '../../../components/nav/SettingsHeader'; | ||||||
| import { GlobalSettingList } from '../../../components/settings/SettingList'; | import { GlobalSettingList } from '../../../components/settings/SettingList'; | ||||||
| import { CurrencyTable } from '../../../components/tables/settings/CurrencyTable'; |  | ||||||
| import { useServerApiState } from '../../../states/ApiState'; | import { useServerApiState } from '../../../states/ApiState'; | ||||||
|  | import { CurrencyTable } from '../../../tables/settings/CurrencyTable'; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * System settings page |  * System settings page | ||||||
|   | |||||||
| @@ -12,10 +12,10 @@ import { useMemo } from 'react'; | |||||||
| import { api } from '../App'; | import { api } from '../App'; | ||||||
| import { PageDetail } from '../components/nav/PageDetail'; | import { PageDetail } from '../components/nav/PageDetail'; | ||||||
| import { PanelGroup } from '../components/nav/PanelGroup'; | import { PanelGroup } from '../components/nav/PanelGroup'; | ||||||
| import { NotificationTable } from '../components/tables/notifications/NotificationsTable'; |  | ||||||
| import { ApiEndpoints } from '../enums/ApiEndpoints'; | import { ApiEndpoints } from '../enums/ApiEndpoints'; | ||||||
| import { useTable } from '../hooks/UseTable'; | import { useTable } from '../hooks/UseTable'; | ||||||
| import { apiUrl } from '../states/ApiState'; | import { apiUrl } from '../states/ApiState'; | ||||||
|  | import { NotificationTable } from '../tables/notifications/NotificationsTable'; | ||||||
|  |  | ||||||
| export default function NotificationsPage() { | export default function NotificationsPage() { | ||||||
|   const unreadTable = useTable('unreadnotifications'); |   const unreadTable = useTable('unreadnotifications'); | ||||||
|   | |||||||
| @@ -28,10 +28,6 @@ import { | |||||||
| import { PageDetail } from '../../components/nav/PageDetail'; | import { PageDetail } from '../../components/nav/PageDetail'; | ||||||
| import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; | import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; | ||||||
| import { StatusRenderer } from '../../components/render/StatusRenderer'; | 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 { NotesEditor } from '../../components/widgets/MarkdownEditor'; | ||||||
| import { ApiEndpoints } from '../../enums/ApiEndpoints'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { ModelType } from '../../enums/ModelType'; | import { ModelType } from '../../enums/ModelType'; | ||||||
| @@ -41,6 +37,10 @@ import { useEditApiFormModal } from '../../hooks/UseForm'; | |||||||
| import { useInstance } from '../../hooks/UseInstance'; | import { useInstance } from '../../hooks/UseInstance'; | ||||||
| import { apiUrl } from '../../states/ApiState'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { useUserState } from '../../states/UserState'; | 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 |  * Detail page for a single Build Order | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ import { t } from '@lingui/macro'; | |||||||
| import { Stack } from '@mantine/core'; | import { Stack } from '@mantine/core'; | ||||||
|  |  | ||||||
| import { PageDetail } from '../../components/nav/PageDetail'; | import { PageDetail } from '../../components/nav/PageDetail'; | ||||||
| import { BuildOrderTable } from '../../components/tables/build/BuildOrderTable'; | import { BuildOrderTable } from '../../tables/build/BuildOrderTable'; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Build Order index page |  * Build Order index page | ||||||
|   | |||||||
| @@ -27,15 +27,6 @@ import { Breadcrumb } from '../../components/nav/BreadcrumbList'; | |||||||
| import { PageDetail } from '../../components/nav/PageDetail'; | import { PageDetail } from '../../components/nav/PageDetail'; | ||||||
| import { PanelGroup } from '../../components/nav/PanelGroup'; | import { PanelGroup } from '../../components/nav/PanelGroup'; | ||||||
| import { PanelType } 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 { NotesEditor } from '../../components/widgets/MarkdownEditor'; | ||||||
| import { ApiEndpoints } from '../../enums/ApiEndpoints'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { UserRoles } from '../../enums/Roles'; | import { UserRoles } from '../../enums/Roles'; | ||||||
| @@ -44,6 +35,15 @@ import { useEditApiFormModal } from '../../hooks/UseForm'; | |||||||
| import { useInstance } from '../../hooks/UseInstance'; | import { useInstance } from '../../hooks/UseInstance'; | ||||||
| import { apiUrl } from '../../states/ApiState'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { useUserState } from '../../states/UserState'; | 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 = { | export type CompanyDetailProps = { | ||||||
|   title: string; |   title: string; | ||||||
|   | |||||||
| @@ -11,11 +11,11 @@ import { useParams } from 'react-router-dom'; | |||||||
|  |  | ||||||
| import { PageDetail } from '../../components/nav/PageDetail'; | import { PageDetail } from '../../components/nav/PageDetail'; | ||||||
| import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; | 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 { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { useInstance } from '../../hooks/UseInstance'; | 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() { | export default function ManufacturerPartDetail() { | ||||||
|   const { id } = useParams(); |   const { id } = useParams(); | ||||||
|   | |||||||
| @@ -11,9 +11,9 @@ import { useParams } from 'react-router-dom'; | |||||||
|  |  | ||||||
| import { PageDetail } from '../../components/nav/PageDetail'; | import { PageDetail } from '../../components/nav/PageDetail'; | ||||||
| import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; | import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; | ||||||
| import { PurchaseOrderTable } from '../../components/tables/purchasing/PurchaseOrderTable'; |  | ||||||
| import { ApiEndpoints } from '../../enums/ApiEndpoints'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { useInstance } from '../../hooks/UseInstance'; | import { useInstance } from '../../hooks/UseInstance'; | ||||||
|  | import { PurchaseOrderTable } from '../../tables/purchasing/PurchaseOrderTable'; | ||||||
|  |  | ||||||
| export default function SupplierPartDetail() { | export default function SupplierPartDetail() { | ||||||
|   const { id } = useParams(); |   const { id } = useParams(); | ||||||
|   | |||||||
| @@ -12,10 +12,10 @@ import { PlaceholderPanel } from '../../components/items/Placeholder'; | |||||||
| import { PageDetail } from '../../components/nav/PageDetail'; | import { PageDetail } from '../../components/nav/PageDetail'; | ||||||
| import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; | import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; | ||||||
| import { PartCategoryTree } from '../../components/nav/PartCategoryTree'; | 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 { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { useInstance } from '../../hooks/UseInstance'; | import { useInstance } from '../../hooks/UseInstance'; | ||||||
|  | import { PartCategoryTable } from '../../tables/part/PartCategoryTable'; | ||||||
|  | import { PartListTable } from '../../tables/part/PartTable'; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Detail view for a single PartCategory instance. |  * Detail view for a single PartCategory instance. | ||||||
|   | |||||||
| @@ -41,24 +41,6 @@ import { | |||||||
| import { PageDetail } from '../../components/nav/PageDetail'; | import { PageDetail } from '../../components/nav/PageDetail'; | ||||||
| import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; | import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; | ||||||
| import { PartCategoryTree } from '../../components/nav/PartCategoryTree'; | 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 { NotesEditor } from '../../components/widgets/MarkdownEditor'; | ||||||
| import { formatPriceRange } from '../../defaults/formatters'; | import { formatPriceRange } from '../../defaults/formatters'; | ||||||
| import { ApiEndpoints } from '../../enums/ApiEndpoints'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| @@ -68,6 +50,24 @@ import { useEditApiFormModal } from '../../hooks/UseForm'; | |||||||
| import { useInstance } from '../../hooks/UseInstance'; | import { useInstance } from '../../hooks/UseInstance'; | ||||||
| import { apiUrl } from '../../states/ApiState'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { useUserState } from '../../states/UserState'; | 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 |  * 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; | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|       ]); |       ]); | ||||||
|   | |||||||
| @@ -22,14 +22,14 @@ import { | |||||||
| } from '../../components/items/ActionDropdown'; | } from '../../components/items/ActionDropdown'; | ||||||
| import { PageDetail } from '../../components/nav/PageDetail'; | import { PageDetail } from '../../components/nav/PageDetail'; | ||||||
| import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; | 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 { NotesEditor } from '../../components/widgets/MarkdownEditor'; | ||||||
| import { ApiEndpoints } from '../../enums/ApiEndpoints'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { useInstance } from '../../hooks/UseInstance'; | import { useInstance } from '../../hooks/UseInstance'; | ||||||
| import { apiUrl } from '../../states/ApiState'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { useUserState } from '../../states/UserState'; | 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 |  * Detail page for a single PurchaseOrder | ||||||
|   | |||||||
| @@ -9,8 +9,8 @@ import { useMemo } from 'react'; | |||||||
|  |  | ||||||
| import { PageDetail } from '../../components/nav/PageDetail'; | import { PageDetail } from '../../components/nav/PageDetail'; | ||||||
| import { PanelGroup } from '../../components/nav/PanelGroup'; | import { PanelGroup } from '../../components/nav/PanelGroup'; | ||||||
| import { CompanyTable } from '../../components/tables/company/CompanyTable'; | import { CompanyTable } from '../../tables/company/CompanyTable'; | ||||||
| import { PurchaseOrderTable } from '../../components/tables/purchasing/PurchaseOrderTable'; | import { PurchaseOrderTable } from '../../tables/purchasing/PurchaseOrderTable'; | ||||||
|  |  | ||||||
| export default function PurchasingIndex() { | export default function PurchasingIndex() { | ||||||
|   const panels = useMemo(() => { |   const panels = useMemo(() => { | ||||||
|   | |||||||
| @@ -6,11 +6,11 @@ import { useParams } from 'react-router-dom'; | |||||||
|  |  | ||||||
| import { PageDetail } from '../../components/nav/PageDetail'; | import { PageDetail } from '../../components/nav/PageDetail'; | ||||||
| import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; | import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; | ||||||
| import { AttachmentTable } from '../../components/tables/general/AttachmentTable'; |  | ||||||
| import { NotesEditor } from '../../components/widgets/MarkdownEditor'; | import { NotesEditor } from '../../components/widgets/MarkdownEditor'; | ||||||
| import { ApiEndpoints } from '../../enums/ApiEndpoints'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { useInstance } from '../../hooks/UseInstance'; | import { useInstance } from '../../hooks/UseInstance'; | ||||||
| import { apiUrl } from '../../states/ApiState'; | import { apiUrl } from '../../states/ApiState'; | ||||||
|  | import { AttachmentTable } from '../../tables/general/AttachmentTable'; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Detail page for a single ReturnOrder |  * Detail page for a single ReturnOrder | ||||||
|   | |||||||
| @@ -9,9 +9,9 @@ import { useMemo } from 'react'; | |||||||
|  |  | ||||||
| import { PageDetail } from '../../components/nav/PageDetail'; | import { PageDetail } from '../../components/nav/PageDetail'; | ||||||
| import { PanelGroup } from '../../components/nav/PanelGroup'; | import { PanelGroup } from '../../components/nav/PanelGroup'; | ||||||
| import { CompanyTable } from '../../components/tables/company/CompanyTable'; | import { CompanyTable } from '../../tables/company/CompanyTable'; | ||||||
| import { ReturnOrderTable } from '../../components/tables/sales/ReturnOrderTable'; | import { ReturnOrderTable } from '../../tables/sales/ReturnOrderTable'; | ||||||
| import { SalesOrderTable } from '../../components/tables/sales/SalesOrderTable'; | import { SalesOrderTable } from '../../tables/sales/SalesOrderTable'; | ||||||
|  |  | ||||||
| export default function PurchasingIndex() { | export default function PurchasingIndex() { | ||||||
|   const panels = useMemo(() => { |   const panels = useMemo(() => { | ||||||
|   | |||||||
| @@ -14,12 +14,12 @@ import { useParams } from 'react-router-dom'; | |||||||
|  |  | ||||||
| import { PageDetail } from '../../components/nav/PageDetail'; | import { PageDetail } from '../../components/nav/PageDetail'; | ||||||
| import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; | 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 { NotesEditor } from '../../components/widgets/MarkdownEditor'; | ||||||
| import { ApiEndpoints } from '../../enums/ApiEndpoints'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { useInstance } from '../../hooks/UseInstance'; | import { useInstance } from '../../hooks/UseInstance'; | ||||||
| import { apiUrl } from '../../states/ApiState'; | import { apiUrl } from '../../states/ApiState'; | ||||||
|  | import { BuildOrderTable } from '../../tables/build/BuildOrderTable'; | ||||||
|  | import { AttachmentTable } from '../../tables/general/AttachmentTable'; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Detail page for a single SalesOrder |  * Detail page for a single SalesOrder | ||||||
|   | |||||||
| @@ -7,10 +7,10 @@ import { useParams } from 'react-router-dom'; | |||||||
| import { PageDetail } from '../../components/nav/PageDetail'; | import { PageDetail } from '../../components/nav/PageDetail'; | ||||||
| import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; | import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; | ||||||
| import { StockLocationTree } from '../../components/nav/StockLocationTree'; | 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 { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { useInstance } from '../../hooks/UseInstance'; | import { useInstance } from '../../hooks/UseInstance'; | ||||||
|  | import { StockItemTable } from '../../tables/stock/StockItemTable'; | ||||||
|  | import { StockLocationTable } from '../../tables/stock/StockLocationTable'; | ||||||
|  |  | ||||||
| export default function Stock() { | export default function Stock() { | ||||||
|   const { id: _id } = useParams(); |   const { id: _id } = useParams(); | ||||||
|   | |||||||
| @@ -33,14 +33,14 @@ import { PlaceholderPanel } from '../../components/items/Placeholder'; | |||||||
| import { PageDetail } from '../../components/nav/PageDetail'; | import { PageDetail } from '../../components/nav/PageDetail'; | ||||||
| import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; | import { PanelGroup, PanelType } from '../../components/nav/PanelGroup'; | ||||||
| import { StockLocationTree } from '../../components/nav/StockLocationTree'; | 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 { NotesEditor } from '../../components/widgets/MarkdownEditor'; | ||||||
| import { ApiEndpoints } from '../../enums/ApiEndpoints'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { useEditStockItem } from '../../forms/StockForms'; | import { useEditStockItem } from '../../forms/StockForms'; | ||||||
| import { useInstance } from '../../hooks/UseInstance'; | import { useInstance } from '../../hooks/UseInstance'; | ||||||
| import { apiUrl } from '../../states/ApiState'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { useUserState } from '../../states/UserState'; | import { useUserState } from '../../states/UserState'; | ||||||
|  | import { AttachmentTable } from '../../tables/general/AttachmentTable'; | ||||||
|  | import { StockItemTable } from '../../tables/stock/StockItemTable'; | ||||||
|  |  | ||||||
| export default function StockDetail() { | export default function StockDetail() { | ||||||
|   const { id } = useParams(); |   const { id } = useParams(); | ||||||
|   | |||||||
| @@ -24,6 +24,12 @@ interface LocalStateProps { | |||||||
|   loader: LoaderType; |   loader: LoaderType; | ||||||
|   lastUsedPanels: Record<string, string>; |   lastUsedPanels: Record<string, string>; | ||||||
|   setLastUsedPanel: (panelKey: string) => (value: string) => void; |   setLastUsedPanel: (panelKey: string) => (value: string) => void; | ||||||
|  |   tableColumnNames: Record<string, Record<string, string>>; | ||||||
|  |   getTableColumnNames: (tableKey: string) => Record<string, string>; | ||||||
|  |   setTableColumnNames: ( | ||||||
|  |     tableKey: string | ||||||
|  |   ) => (names: Record<string, string>) => void; | ||||||
|  |   clearTableColumnNames: () => void; | ||||||
| } | } | ||||||
|  |  | ||||||
| export const useLocalState = create<LocalStateProps>()( | export const useLocalState = create<LocalStateProps>()( | ||||||
| @@ -55,6 +61,22 @@ export const useLocalState = create<LocalStateProps>()( | |||||||
|             lastUsedPanels: { ...get().lastUsedPanels, [panelKey]: value } |             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: {} }); | ||||||
|       } |       } | ||||||
|     }), |     }), | ||||||
|     { |     { | ||||||
|   | |||||||
| @@ -3,8 +3,8 @@ | |||||||
|  */ |  */ | ||||||
| export type TableColumn<T = any> = { | export type TableColumn<T = any> = { | ||||||
|   accessor: string; // The key in the record to access
 |   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)
 |   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
 |   sortable?: boolean; // Whether the column is sortable
 | ||||||
|   switchable?: boolean; // Whether the column is switchable
 |   switchable?: boolean; // Whether the column is switchable
 | ||||||
|   hidden?: boolean; // Whether the column is hidden
 |   hidden?: boolean; // Whether the column is hidden
 | ||||||
| @@ -3,13 +3,13 @@ | |||||||
|  */ |  */ | ||||||
| import { t } from '@lingui/macro'; | import { t } from '@lingui/macro'; | ||||||
| 
 | 
 | ||||||
| import { formatCurrency, renderDate } from '../../defaults/formatters'; | import { Thumbnail } from '../components/images/Thumbnail'; | ||||||
| import { ModelType } from '../../enums/ModelType'; | import { ProgressBar } from '../components/items/ProgressBar'; | ||||||
| import { Thumbnail } from '../images/Thumbnail'; | import { YesNoButton } from '../components/items/YesNoButton'; | ||||||
| import { ProgressBar } from '../items/ProgressBar'; | import { TableStatusRenderer } from '../components/render/StatusRenderer'; | ||||||
| import { YesNoButton } from '../items/YesNoButton'; | import { RenderOwner } from '../components/render/User'; | ||||||
| import { TableStatusRenderer } from '../render/StatusRenderer'; | import { formatCurrency, renderDate } from '../defaults/formatters'; | ||||||
| import { RenderOwner } from '../render/User'; | import { ModelType } from '../enums/ModelType'; | ||||||
| import { TableColumn } from './Column'; | import { TableColumn } from './Column'; | ||||||
| import { ProjectCodeHoverCard } from './TableHoverCard'; | import { ProjectCodeHoverCard } from './TableHoverCard'; | ||||||
| 
 | 
 | ||||||
| @@ -25,7 +25,7 @@ export function BooleanColumn({ | |||||||
|   switchable |   switchable | ||||||
| }: { | }: { | ||||||
|   accessor: string; |   accessor: string; | ||||||
|   title: string; |   title?: string; | ||||||
|   sortable?: boolean; |   sortable?: boolean; | ||||||
|   switchable?: boolean; |   switchable?: boolean; | ||||||
| }): TableColumn { | }): TableColumn { | ||||||
| @@ -58,16 +58,29 @@ export function DescriptionColumn({ | |||||||
| export function LinkColumn(): TableColumn { | export function LinkColumn(): TableColumn { | ||||||
|   return { |   return { | ||||||
|     accessor: 'link', |     accessor: 'link', | ||||||
|     title: t`Link`, |  | ||||||
|     sortable: false |     sortable: false | ||||||
|     // TODO: Custom URL hyperlink renderer?
 |     // 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 { | export function LineItemsProgressColumn(): TableColumn { | ||||||
|   return { |   return { | ||||||
|     accessor: 'line_items', |     accessor: 'line_items', | ||||||
|     title: t`Line Items`, |  | ||||||
|     sortable: true, |     sortable: true, | ||||||
|     render: (record: any) => ( |     render: (record: any) => ( | ||||||
|       <ProgressBar |       <ProgressBar | ||||||
| @@ -82,7 +95,6 @@ export function LineItemsProgressColumn(): TableColumn { | |||||||
| export function ProjectCodeColumn(): TableColumn { | export function ProjectCodeColumn(): TableColumn { | ||||||
|   return { |   return { | ||||||
|     accessor: 'project_code', |     accessor: 'project_code', | ||||||
|     title: t`Project Code`, |  | ||||||
|     sortable: true, |     sortable: true, | ||||||
|     render: (record: any) => ( |     render: (record: any) => ( | ||||||
|       <ProjectCodeHoverCard projectCode={record.project_code_detail} /> |       <ProjectCodeHoverCard projectCode={record.project_code_detail} /> | ||||||
| @@ -94,7 +106,6 @@ export function StatusColumn(model: ModelType) { | |||||||
|   return { |   return { | ||||||
|     accessor: 'status', |     accessor: 'status', | ||||||
|     sortable: true, |     sortable: true, | ||||||
|     title: t`Status`, |  | ||||||
|     render: TableStatusRenderer(model) |     render: TableStatusRenderer(model) | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
| @@ -102,7 +113,6 @@ export function StatusColumn(model: ModelType) { | |||||||
| export function ResponsibleColumn(): TableColumn { | export function ResponsibleColumn(): TableColumn { | ||||||
|   return { |   return { | ||||||
|     accessor: 'responsible', |     accessor: 'responsible', | ||||||
|     title: t`Responsible`, |  | ||||||
|     sortable: true, |     sortable: true, | ||||||
|     render: (record: any) => |     render: (record: any) => | ||||||
|       record.responsible && RenderOwner({ instance: record.responsible_detail }) |       record.responsible && RenderOwner({ instance: record.responsible_detail }) | ||||||
| @@ -112,8 +122,8 @@ export function ResponsibleColumn(): TableColumn { | |||||||
| export function TargetDateColumn(): TableColumn { | export function TargetDateColumn(): TableColumn { | ||||||
|   return { |   return { | ||||||
|     accessor: 'target_date', |     accessor: 'target_date', | ||||||
|     title: t`Target Date`, |  | ||||||
|     sortable: true, |     sortable: true, | ||||||
|  |     title: t`Target Date`, | ||||||
|     // TODO: custom renderer which alerts user if target date is overdue
 |     // TODO: custom renderer which alerts user if target date is overdue
 | ||||||
|     render: (record: any) => renderDate(record.target_date) |     render: (record: any) => renderDate(record.target_date) | ||||||
|   }; |   }; | ||||||
| @@ -122,7 +132,6 @@ export function TargetDateColumn(): TableColumn { | |||||||
| export function CreationDateColumn(): TableColumn { | export function CreationDateColumn(): TableColumn { | ||||||
|   return { |   return { | ||||||
|     accessor: 'creation_date', |     accessor: 'creation_date', | ||||||
|     title: t`Creation Date`, |  | ||||||
|     sortable: true, |     sortable: true, | ||||||
|     render: (record: any) => renderDate(record.creation_date) |     render: (record: any) => renderDate(record.creation_date) | ||||||
|   }; |   }; | ||||||
| @@ -131,7 +140,6 @@ export function CreationDateColumn(): TableColumn { | |||||||
| export function ShipmentDateColumn(): TableColumn { | export function ShipmentDateColumn(): TableColumn { | ||||||
|   return { |   return { | ||||||
|     accessor: 'shipment_date', |     accessor: 'shipment_date', | ||||||
|     title: t`Shipment Date`, |  | ||||||
|     sortable: true, |     sortable: true, | ||||||
|     render: (record: any) => renderDate(record.shipment_date) |     render: (record: any) => renderDate(record.shipment_date) | ||||||
|   }; |   }; | ||||||
| @@ -29,7 +29,7 @@ export function TableColumnSelect({ | |||||||
|               <Checkbox |               <Checkbox | ||||||
|                 checked={!col.hidden} |                 checked={!col.hidden} | ||||||
|                 label={col.title || col.accessor} |                 label={col.title || col.accessor} | ||||||
|                 onChange={(event) => onToggleColumn(col.accessor)} |                 onChange={() => onToggleColumn(col.accessor)} | ||||||
|                 radius="sm" |                 radius="sm" | ||||||
|               /> |               /> | ||||||
|             </Menu.Item> |             </Menu.Item> | ||||||
| @@ -13,12 +13,12 @@ import { | |||||||
| import { useSuspenseQuery } from '@tanstack/react-query'; | import { useSuspenseQuery } from '@tanstack/react-query'; | ||||||
| import { Suspense } from 'react'; | import { Suspense } from 'react'; | ||||||
| 
 | 
 | ||||||
| import { api } from '../../App'; | import { api } from '../App'; | ||||||
| import { ApiEndpoints } from '../../enums/ApiEndpoints'; | import { ProgressBar } from '../components/items/ProgressBar'; | ||||||
| import { InvenTreeIcon } from '../../functions/icons'; | import { ApiEndpoints } from '../enums/ApiEndpoints'; | ||||||
| import { apiUrl } from '../../states/ApiState'; | import { InvenTreeIcon } from '../functions/icons'; | ||||||
| import { useGlobalSettingsState } from '../../states/SettingsState'; | import { apiUrl } from '../states/ApiState'; | ||||||
| import { ProgressBar } from '../items/ProgressBar'; | import { useGlobalSettingsState } from '../states/SettingsState'; | ||||||
| 
 | 
 | ||||||
| export type PartIconsType = { | export type PartIconsType = { | ||||||
|   assembly: boolean; |   assembly: boolean; | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| import { t } from '@lingui/macro'; | import { t } from '@lingui/macro'; | ||||||
| 
 | 
 | ||||||
| import { ModelType } from '../../enums/ModelType'; | import { ModelType } from '../enums/ModelType'; | ||||||
| import { useServerApiState } from '../../states/ApiState'; | import { useServerApiState } from '../states/ApiState'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Interface for the table filter choice |  * Interface for the table filter choice | ||||||
| @@ -20,7 +20,7 @@ export type TableFilterChoice = { | |||||||
|  */ |  */ | ||||||
| export type TableFilter = { | export type TableFilter = { | ||||||
|   name: string; |   name: string; | ||||||
|   label: string; |   label?: string; | ||||||
|   description?: string; |   description?: string; | ||||||
|   type?: string; |   type?: string; | ||||||
|   choices?: TableFilterChoice[]; |   choices?: TableFilterChoice[]; | ||||||
| @@ -14,8 +14,8 @@ import { | |||||||
| } from '@mantine/core'; | } from '@mantine/core'; | ||||||
| import { forwardRef, useCallback, useEffect, useMemo, useState } from 'react'; | import { forwardRef, useCallback, useEffect, useMemo, useState } from 'react'; | ||||||
| 
 | 
 | ||||||
| import { TableState } from '../../hooks/UseTable'; | import { StylishText } from '../components/items/StylishText'; | ||||||
| import { StylishText } from '../items/StylishText'; | import { TableState } from '../hooks/UseTable'; | ||||||
| import { | import { | ||||||
|   TableFilter, |   TableFilter, | ||||||
|   TableFilterChoice, |   TableFilterChoice, | ||||||
| @@ -2,7 +2,9 @@ import { t } from '@lingui/macro'; | |||||||
| import { | import { | ||||||
|   ActionIcon, |   ActionIcon, | ||||||
|   Alert, |   Alert, | ||||||
|  |   Box, | ||||||
|   Indicator, |   Indicator, | ||||||
|  |   LoadingOverlay, | ||||||
|   Space, |   Space, | ||||||
|   Stack, |   Stack, | ||||||
|   Tooltip |   Tooltip | ||||||
| @@ -16,10 +18,13 @@ import { useQuery } from '@tanstack/react-query'; | |||||||
| import { DataTable, DataTableSortStatus } from 'mantine-datatable'; | import { DataTable, DataTableSortStatus } from 'mantine-datatable'; | ||||||
| import { Fragment, useCallback, useEffect, useMemo, useState } from 'react'; | import { Fragment, useCallback, useEffect, useMemo, useState } from 'react'; | ||||||
| 
 | 
 | ||||||
| import { api } from '../../App'; | import { api } from '../App'; | ||||||
| import { TableState } from '../../hooks/UseTable'; | import { ActionButton } from '../components/buttons/ActionButton'; | ||||||
| import { ActionButton } from '../buttons/ActionButton'; | import { ButtonMenu } from '../components/buttons/ButtonMenu'; | ||||||
| import { ButtonMenu } from '../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 { TableColumn } from './Column'; | ||||||
| import { TableColumnSelect } from './ColumnSelect'; | import { TableColumnSelect } from './ColumnSelect'; | ||||||
| import { DownloadAction } from './DownloadAction'; | import { DownloadAction } from './DownloadAction'; | ||||||
| @@ -93,8 +98,7 @@ const defaultInvenTreeTableProps: InvenTreeTableProps = { | |||||||
|   barcodeActions: [], |   barcodeActions: [], | ||||||
|   tableFilters: [], |   tableFilters: [], | ||||||
|   tableActions: [], |   tableActions: [], | ||||||
|   idAccessor: 'pk', |   idAccessor: 'pk' | ||||||
|   onRowClick: (record: any, index: number, event: any) => {} |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @@ -111,6 +115,73 @@ export function InvenTreeTable<T = any>({ | |||||||
|   columns: TableColumn<T>[]; |   columns: TableColumn<T>[]; | ||||||
|   props: InvenTreeTableProps<T>; |   props: InvenTreeTableProps<T>; | ||||||
| }) { | }) { | ||||||
|  |   const { getTableColumnNames, setTableColumnNames } = useLocalState(); | ||||||
|  |   const [fieldNames, setFieldNames] = useState<Record<string, string>>({}); | ||||||
|  | 
 | ||||||
|  |   // 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<string, string> = {}; | ||||||
|  |             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)
 |   // Build table properties based on provided props (and default props)
 | ||||||
|   const tableProps: InvenTreeTableProps<T> = useMemo(() => { |   const tableProps: InvenTreeTableProps<T> = useMemo(() => { | ||||||
|     return { |     return { | ||||||
| @@ -139,7 +210,8 @@ export function InvenTreeTable<T = any>({ | |||||||
| 
 | 
 | ||||||
|       return { |       return { | ||||||
|         ...col, |         ...col, | ||||||
|         hidden: hidden |         hidden: hidden, | ||||||
|  |         title: col.title ?? fieldNames[col.accessor] ?? `? ${col.accessor} ?` | ||||||
|       }; |       }; | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
| @@ -165,6 +237,7 @@ export function InvenTreeTable<T = any>({ | |||||||
|     return cols; |     return cols; | ||||||
|   }, [ |   }, [ | ||||||
|     columns, |     columns, | ||||||
|  |     fieldNames, | ||||||
|     tableProps.rowActions, |     tableProps.rowActions, | ||||||
|     tableProps.enableSelection, |     tableProps.enableSelection, | ||||||
|     tableState.hiddenColumns, |     tableState.hiddenColumns, | ||||||
| @@ -289,7 +362,7 @@ export function InvenTreeTable<T = any>({ | |||||||
|     let queryParams = getTableFilters(true); |     let queryParams = getTableFilters(true); | ||||||
| 
 | 
 | ||||||
|     return api |     return api | ||||||
|       .get(`${url}`, { |       .get(url, { | ||||||
|         params: queryParams, |         params: queryParams, | ||||||
|         timeout: 30 * 1000 |         timeout: 30 * 1000 | ||||||
|       }) |       }) | ||||||
| @@ -424,15 +497,14 @@ export function InvenTreeTable<T = any>({ | |||||||
| 
 | 
 | ||||||
|   return ( |   return ( | ||||||
|     <> |     <> | ||||||
|       {tableProps.enableFilters && |       {tableProps.enableFilters && (filters.length ?? 0) > 0 && ( | ||||||
|         (tableProps.tableFilters?.length ?? 0) > 0 && ( |         <FilterSelectDrawer | ||||||
|           <FilterSelectDrawer |           availableFilters={filters} | ||||||
|             availableFilters={tableProps.tableFilters ?? []} |           tableState={tableState} | ||||||
|             tableState={tableState} |           opened={filtersVisible} | ||||||
|             opened={filtersVisible} |           onClose={() => setFiltersVisible(false)} | ||||||
|             onClose={() => setFiltersVisible(false)} |         /> | ||||||
|           /> |       )} | ||||||
|         )} |  | ||||||
|       <Stack spacing="sm"> |       <Stack spacing="sm"> | ||||||
|         <Group position="apart"> |         <Group position="apart"> | ||||||
|           <Group position="left" key="custom-actions" spacing={5}> |           <Group position="left" key="custom-actions" spacing={5}> | ||||||
| @@ -489,22 +561,21 @@ export function InvenTreeTable<T = any>({ | |||||||
|                 onToggleColumn={toggleColumn} |                 onToggleColumn={toggleColumn} | ||||||
|               /> |               /> | ||||||
|             )} |             )} | ||||||
|             {tableProps.enableFilters && |             {tableProps.enableFilters && filters.length > 0 && ( | ||||||
|               (tableProps.tableFilters?.length ?? 0 > 0) && ( |               <Indicator | ||||||
|                 <Indicator |                 size="xs" | ||||||
|                   size="xs" |                 label={tableState.activeFilters.length} | ||||||
|                   label={tableState.activeFilters.length} |                 disabled={tableState.activeFilters.length == 0} | ||||||
|                   disabled={tableState.activeFilters.length == 0} |               > | ||||||
|                 > |                 <ActionIcon> | ||||||
|                   <ActionIcon> |                   <Tooltip label={t`Table filters`}> | ||||||
|                     <Tooltip label={t`Table filters`}> |                     <IconFilter | ||||||
|                       <IconFilter |                       onClick={() => setFiltersVisible(!filtersVisible)} | ||||||
|                         onClick={() => setFiltersVisible(!filtersVisible)} |                     /> | ||||||
|                       /> |                   </Tooltip> | ||||||
|                     </Tooltip> |                 </ActionIcon> | ||||||
|                   </ActionIcon> |               </Indicator> | ||||||
|                 </Indicator> |             )} | ||||||
|               )} |  | ||||||
|             {tableProps.enableDownload && ( |             {tableProps.enableDownload && ( | ||||||
|               <DownloadAction |               <DownloadAction | ||||||
|                 key="download-action" |                 key="download-action" | ||||||
| @@ -513,40 +584,48 @@ export function InvenTreeTable<T = any>({ | |||||||
|             )} |             )} | ||||||
|           </Group> |           </Group> | ||||||
|         </Group> |         </Group> | ||||||
|         <DataTable |         <Box pos="relative"> | ||||||
|           withBorder |           <LoadingOverlay | ||||||
|           striped |             visible={tableOptionQuery.isLoading || tableOptionQuery.isFetching} | ||||||
|           highlightOnHover |           /> | ||||||
|           loaderVariant="dots" | 
 | ||||||
|           pinLastColumn={tableProps.rowActions != undefined} |           <DataTable | ||||||
|           idAccessor={tableProps.idAccessor} |             withBorder | ||||||
|           minHeight={300} |             striped | ||||||
|           totalRecords={recordCount} |             highlightOnHover | ||||||
|           recordsPerPage={tableProps.pageSize ?? defaultPageSize} |             loaderVariant="dots" | ||||||
|           page={page} |             pinLastColumn={tableProps.rowActions != undefined} | ||||||
|           onPageChange={setPage} |             idAccessor={tableProps.idAccessor} | ||||||
|           sortStatus={sortStatus} |             minHeight={300} | ||||||
|           onSortStatusChange={handleSortStatusChange} |             totalRecords={recordCount} | ||||||
|           selectedRecords={ |             recordsPerPage={tableProps.pageSize ?? defaultPageSize} | ||||||
|             tableProps.enableSelection ? tableState.selectedRecords : undefined |             page={page} | ||||||
|           } |             onPageChange={setPage} | ||||||
|           onSelectedRecordsChange={ |             sortStatus={sortStatus} | ||||||
|             tableProps.enableSelection ? onSelectedRecordsChange : undefined |             onSortStatusChange={handleSortStatusChange} | ||||||
|           } |             selectedRecords={ | ||||||
|           fetching={isFetching} |               tableProps.enableSelection | ||||||
|           noRecordsText={missingRecordsText} |                 ? tableState.selectedRecords | ||||||
|           records={data} |                 : undefined | ||||||
|           columns={dataColumns} |  | ||||||
|           onRowClick={tableProps.onRowClick} |  | ||||||
|           defaultColumnProps={{ |  | ||||||
|             noWrap: true, |  | ||||||
|             textAlignment: 'left', |  | ||||||
|             cellsStyle: { |  | ||||||
|               // TODO: Need a better way of handling "wide" cells,
 |  | ||||||
|               overflow: 'hidden' |  | ||||||
|             } |             } | ||||||
|           }} |             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' | ||||||
|  |               } | ||||||
|  |             }} | ||||||
|  |           /> | ||||||
|  |         </Box> | ||||||
|       </Stack> |       </Stack> | ||||||
|     </> |     </> | ||||||
|   ); |   ); | ||||||
| @@ -1,7 +1,10 @@ | |||||||
| import { Paper } from '@mantine/core'; | import { Paper } from '@mantine/core'; | ||||||
| 
 | 
 | ||||||
| import { UserRoles } from '../../enums/Roles'; | import { | ||||||
| import { DetailImageButtonProps, DetailsImage } from '../images/DetailsImage'; |   DetailImageButtonProps, | ||||||
|  |   DetailsImage | ||||||
|  | } from '../components/images/DetailsImage'; | ||||||
|  | import { UserRoles } from '../enums/Roles'; | ||||||
| import { DetailsField, DetailsTable } from './Details'; | import { DetailsField, DetailsTable } from './Details'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @@ -4,7 +4,7 @@ import { Menu } from '@mantine/core'; | |||||||
| import { IconCopy, IconDots, IconEdit, IconTrash } from '@tabler/icons-react'; | import { IconCopy, IconDots, IconEdit, IconTrash } from '@tabler/icons-react'; | ||||||
| import { ReactNode, useMemo, useState } from 'react'; | import { ReactNode, useMemo, useState } from 'react'; | ||||||
| 
 | 
 | ||||||
| import { notYetImplemented } from '../../functions/notifications'; | import { notYetImplemented } from '../functions/notifications'; | ||||||
| 
 | 
 | ||||||
| // Type definition for a table row action
 | // Type definition for a table row action
 | ||||||
| export type RowAction = { | export type RowAction = { | ||||||
| @@ -1,3 +1,4 @@ | |||||||
|  | import { t } from '@lingui/macro'; | ||||||
| import { CloseButton, TextInput } from '@mantine/core'; | import { CloseButton, TextInput } from '@mantine/core'; | ||||||
| import { useDebouncedValue } from '@mantine/hooks'; | import { useDebouncedValue } from '@mantine/hooks'; | ||||||
| import { IconSearch } from '@tabler/icons-react'; | import { IconSearch } from '@tabler/icons-react'; | ||||||
| @@ -19,11 +20,11 @@ export function TableSearchInput({ | |||||||
|     <TextInput |     <TextInput | ||||||
|       value={value} |       value={value} | ||||||
|       icon={<IconSearch />} |       icon={<IconSearch />} | ||||||
|       placeholder="Search" |       placeholder={t`Search`} | ||||||
|       onChange={(event) => setValue(event.target.value)} |       onChange={(event) => setValue(event.target.value)} | ||||||
|       rightSection={ |       rightSection={ | ||||||
|         value.length > 0 ? ( |         value.length > 0 ? ( | ||||||
|           <CloseButton size="xs" onClick={(event) => setValue('')} /> |           <CloseButton size="xs" onClick={() => setValue('')} /> | ||||||
|         ) : null |         ) : null | ||||||
|       } |       } | ||||||
|     /> |     /> | ||||||
| @@ -8,20 +8,25 @@ import { | |||||||
| import { ReactNode, useCallback, useMemo } from 'react'; | import { ReactNode, useCallback, useMemo } from 'react'; | ||||||
| import { useNavigate } from 'react-router-dom'; | import { useNavigate } from 'react-router-dom'; | ||||||
| 
 | 
 | ||||||
| import { formatPriceRange } from '../../../defaults/formatters'; | import { Thumbnail } from '../../components/images/Thumbnail'; | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { YesNoButton } from '../../components/items/YesNoButton'; | ||||||
| import { ModelType } from '../../../enums/ModelType'; | import { formatPriceRange } from '../../defaults/formatters'; | ||||||
| import { UserRoles } from '../../../enums/Roles'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { bomItemFields } from '../../../forms/BomForms'; | import { ModelType } from '../../enums/ModelType'; | ||||||
| import { openDeleteApiForm, openEditApiForm } from '../../../functions/forms'; | import { UserRoles } from '../../enums/Roles'; | ||||||
| import { getDetailUrl } from '../../../functions/urls'; | import { bomItemFields } from '../../forms/BomForms'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { openDeleteApiForm, openEditApiForm } from '../../functions/forms'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { getDetailUrl } from '../../functions/urls'; | ||||||
| import { useUserState } from '../../../states/UserState'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { Thumbnail } from '../../images/Thumbnail'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { YesNoButton } from '../../items/YesNoButton'; | import { useUserState } from '../../states/UserState'; | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { BooleanColumn } from '../ColumnRenderers'; | import { | ||||||
|  |   BooleanColumn, | ||||||
|  |   DescriptionColumn, | ||||||
|  |   NoteColumn, | ||||||
|  |   ReferenceColumn | ||||||
|  | } from '../ColumnRenderers'; | ||||||
| import { TableFilter } from '../Filter'; | import { TableFilter } from '../Filter'; | ||||||
| import { InvenTreeTable } from '../InvenTreeTable'; | import { InvenTreeTable } from '../InvenTreeTable'; | ||||||
| import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions'; | import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions'; | ||||||
| @@ -58,10 +63,8 @@ export function BomTable({ | |||||||
| 
 | 
 | ||||||
|   const tableColumns: TableColumn[] = useMemo(() => { |   const tableColumns: TableColumn[] = useMemo(() => { | ||||||
|     return [ |     return [ | ||||||
|       // TODO: Improve column rendering
 |  | ||||||
|       { |       { | ||||||
|         accessor: 'part', |         accessor: 'part', | ||||||
|         title: t`Part`, |  | ||||||
|         switchable: false, |         switchable: false, | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         render: (record) => { |         render: (record) => { | ||||||
| @@ -91,18 +94,12 @@ export function BomTable({ | |||||||
|           ); |           ); | ||||||
|         } |         } | ||||||
|       }, |       }, | ||||||
|       { |       DescriptionColumn({ | ||||||
|         accessor: 'description', |         accessor: 'sub_part_detail.description' | ||||||
|         title: t`Description`, |       }), | ||||||
|         render: (row) => row?.sub_part_detail?.description |       ReferenceColumn(), | ||||||
|       }, |  | ||||||
|       { |  | ||||||
|         accessor: 'reference', |  | ||||||
|         title: t`Reference` |  | ||||||
|       }, |  | ||||||
|       { |       { | ||||||
|         accessor: 'quantity', |         accessor: 'quantity', | ||||||
|         title: t`Quantity`, |  | ||||||
|         switchable: false, |         switchable: false, | ||||||
|         sortable: true |         sortable: true | ||||||
|         // TODO: Custom quantity renderer
 |         // TODO: Custom quantity renderer
 | ||||||
| @@ -110,7 +107,6 @@ export function BomTable({ | |||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'substitutes', |         accessor: 'substitutes', | ||||||
|         title: t`Substitutes`, |  | ||||||
|         // TODO: Show hovercard with list of substitutes
 |         // TODO: Show hovercard with list of substitutes
 | ||||||
|         render: (row) => { |         render: (row) => { | ||||||
|           let substitutes = row.substitutes ?? []; |           let substitutes = row.substitutes ?? []; | ||||||
| @@ -123,20 +119,16 @@ export function BomTable({ | |||||||
|         } |         } | ||||||
|       }, |       }, | ||||||
|       BooleanColumn({ |       BooleanColumn({ | ||||||
|         accessor: 'optional', |         accessor: 'optional' | ||||||
|         title: t`Optional` |  | ||||||
|       }), |       }), | ||||||
|       BooleanColumn({ |       BooleanColumn({ | ||||||
|         accessor: 'consumable', |         accessor: 'consumable' | ||||||
|         title: t`Consumable` |  | ||||||
|       }), |       }), | ||||||
|       BooleanColumn({ |       BooleanColumn({ | ||||||
|         accessor: 'allow_variants', |         accessor: 'allow_variants' | ||||||
|         title: t`Allow Variants` |  | ||||||
|       }), |       }), | ||||||
|       BooleanColumn({ |       BooleanColumn({ | ||||||
|         accessor: 'inherited', |         accessor: 'inherited' | ||||||
|         title: t`Gets Inherited` |  | ||||||
|         // TODO: Custom renderer for this column
 |         // TODO: Custom renderer for this column
 | ||||||
|         // TODO: See bom.js for existing implementation
 |         // TODO: See bom.js for existing implementation
 | ||||||
|       }), |       }), | ||||||
| @@ -150,7 +142,6 @@ export function BomTable({ | |||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'available_stock', |         accessor: 'available_stock', | ||||||
|         title: t`Available`, |  | ||||||
| 
 | 
 | ||||||
|         render: (record) => { |         render: (record) => { | ||||||
|           let extra: ReactNode[] = []; |           let extra: ReactNode[] = []; | ||||||
| @@ -225,11 +216,7 @@ export function BomTable({ | |||||||
|           ); |           ); | ||||||
|         } |         } | ||||||
|       }, |       }, | ||||||
|       { |       NoteColumn() | ||||||
|         accessor: 'note', |  | ||||||
|         title: t`Notes`, |  | ||||||
|         switchable: true |  | ||||||
|       } |  | ||||||
|     ]; |     ]; | ||||||
|   }, [partId, params]); |   }, [partId, params]); | ||||||
| 
 | 
 | ||||||
| @@ -247,32 +234,26 @@ export function BomTable({ | |||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         name: 'available_stock', |         name: 'available_stock', | ||||||
|         label: t`Has Available Stock`, |  | ||||||
|         description: t`Show items with available stock` |         description: t`Show items with available stock` | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         name: 'on_order', |         name: 'on_order', | ||||||
|         label: t`On Order`, |  | ||||||
|         description: t`Show items on order` |         description: t`Show items on order` | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         name: 'validated', |         name: 'validated', | ||||||
|         label: t`Validated`, |  | ||||||
|         description: t`Show validated items` |         description: t`Show validated items` | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         name: 'inherited', |         name: 'inherited', | ||||||
|         label: t`Gets Inherited`, |  | ||||||
|         description: t`Show inherited items` |         description: t`Show inherited items` | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         name: 'optional', |         name: 'optional', | ||||||
|         label: t`Optional`, |  | ||||||
|         description: t`Show optional items` |         description: t`Show optional items` | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         name: 'consumable', |         name: 'consumable', | ||||||
|         label: t`Consumable`, |  | ||||||
|         description: t`Show consumable items` |         description: t`Show consumable items` | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
| @@ -2,13 +2,14 @@ import { t } from '@lingui/macro'; | |||||||
| import { useMemo } from 'react'; | import { useMemo } from 'react'; | ||||||
| import { useNavigate } from 'react-router-dom'; | import { useNavigate } from 'react-router-dom'; | ||||||
| 
 | 
 | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { PartHoverCard } from '../../components/images/Thumbnail'; | ||||||
| import { ModelType } from '../../../enums/ModelType'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { getDetailUrl } from '../../../functions/urls'; | import { ModelType } from '../../enums/ModelType'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { getDetailUrl } from '../../functions/urls'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { PartHoverCard } from '../../images/Thumbnail'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
|  | import { ReferenceColumn } from '../ColumnRenderers'; | ||||||
| import { TableFilter } from '../Filter'; | import { TableFilter } from '../Filter'; | ||||||
| import { InvenTreeTable } from '../InvenTreeTable'; | import { InvenTreeTable } from '../InvenTreeTable'; | ||||||
| 
 | 
 | ||||||
| @@ -30,30 +31,23 @@ export function UsedInTable({ | |||||||
|     return [ |     return [ | ||||||
|       { |       { | ||||||
|         accessor: 'part', |         accessor: 'part', | ||||||
|         title: t`Assembled Part`, |  | ||||||
|         switchable: false, |         switchable: false, | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         render: (record: any) => <PartHoverCard part={record.part_detail} /> |         render: (record: any) => <PartHoverCard part={record.part_detail} /> | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'sub_part', |         accessor: 'sub_part', | ||||||
|         title: t`Required Part`, |  | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         render: (record: any) => <PartHoverCard part={record.sub_part_detail} /> |         render: (record: any) => <PartHoverCard part={record.sub_part_detail} /> | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'quantity', |         accessor: 'quantity', | ||||||
|         title: t`Quantity`, |  | ||||||
|         render: (record: any) => { |         render: (record: any) => { | ||||||
|           // TODO: render units if appropriate
 |           // TODO: render units if appropriate
 | ||||||
|           return record.quantity; |           return record.quantity; | ||||||
|         } |         } | ||||||
|       }, |       }, | ||||||
|       { |       ReferenceColumn() | ||||||
|         accessor: 'reference', |  | ||||||
|         title: t`Reference`, |  | ||||||
|         sortable: true |  | ||||||
|       } |  | ||||||
|     ]; |     ]; | ||||||
|   }, [partId]); |   }, [partId]); | ||||||
| 
 | 
 | ||||||
| @@ -61,12 +55,10 @@ export function UsedInTable({ | |||||||
|     return [ |     return [ | ||||||
|       { |       { | ||||||
|         name: 'inherited', |         name: 'inherited', | ||||||
|         label: t`Gets Inherited`, |  | ||||||
|         description: t`Show inherited items` |         description: t`Show inherited items` | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         name: 'optional', |         name: 'optional', | ||||||
|         label: t`Optional`, |  | ||||||
|         description: t`Show optional items` |         description: t`Show optional items` | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
| @@ -8,14 +8,14 @@ import { | |||||||
| import { useCallback, useMemo } from 'react'; | import { useCallback, useMemo } from 'react'; | ||||||
| import { useNavigate } from 'react-router-dom'; | import { useNavigate } from 'react-router-dom'; | ||||||
| 
 | 
 | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { PartHoverCard } from '../../components/images/Thumbnail'; | ||||||
| import { ModelType } from '../../../enums/ModelType'; | import { ProgressBar } from '../../components/items/ProgressBar'; | ||||||
| import { getDetailUrl } from '../../../functions/urls'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { ModelType } from '../../enums/ModelType'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { getDetailUrl } from '../../functions/urls'; | ||||||
| import { useUserState } from '../../../states/UserState'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { PartHoverCard } from '../../images/Thumbnail'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { ProgressBar } from '../../items/ProgressBar'; | import { useUserState } from '../../states/UserState'; | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { BooleanColumn } from '../ColumnRenderers'; | import { BooleanColumn } from '../ColumnRenderers'; | ||||||
| import { TableFilter } from '../Filter'; | import { TableFilter } from '../Filter'; | ||||||
| @@ -31,7 +31,6 @@ export default function BuildLineTable({ params = {} }: { params?: any }) { | |||||||
|     return [ |     return [ | ||||||
|       { |       { | ||||||
|         name: 'allocated', |         name: 'allocated', | ||||||
|         label: t`Allocated`, |  | ||||||
|         description: t`Show allocated lines` |         description: t`Show allocated lines` | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
| @@ -114,28 +113,24 @@ export default function BuildLineTable({ params = {} }: { params?: any }) { | |||||||
|     return [ |     return [ | ||||||
|       { |       { | ||||||
|         accessor: 'bom_item', |         accessor: 'bom_item', | ||||||
|         title: t`Part`, |  | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         switchable: false, |         switchable: false, | ||||||
|         render: (record: any) => <PartHoverCard part={record.part_detail} /> |         render: (record: any) => <PartHoverCard part={record.part_detail} /> | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'reference', |         accessor: 'bom_item_detail.reference' | ||||||
|         title: t`Reference`, |  | ||||||
|         render: (record: any) => record.bom_item_detail.reference |  | ||||||
|       }, |       }, | ||||||
|       BooleanColumn({ |       BooleanColumn({ | ||||||
|         accessor: 'bom_item_detail.consumable', |         accessor: 'bom_item_detail.consumable' | ||||||
|         title: t`Consumable` |  | ||||||
|       }), |       }), | ||||||
|       BooleanColumn({ |       BooleanColumn({ | ||||||
|         accessor: 'bom_item_detail.optional', |         accessor: 'bom_item_detail.optional' | ||||||
|         title: t`Optional` |  | ||||||
|       }), |       }), | ||||||
|       { |       { | ||||||
|         accessor: 'unit_quantity', |         accessor: 'bom_item_detail.quantity', | ||||||
|         title: t`Unit Quantity`, |  | ||||||
|         sortable: true, |         sortable: true, | ||||||
|  |         title: t`Unit Quantity`, | ||||||
|  |         ordering: 'unit_quantity', | ||||||
|         render: (record: any) => { |         render: (record: any) => { | ||||||
|           return ( |           return ( | ||||||
|             <Group position="apart"> |             <Group position="apart"> | ||||||
| @@ -149,7 +144,6 @@ export default function BuildLineTable({ params = {} }: { params?: any }) { | |||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'quantity', |         accessor: 'quantity', | ||||||
|         title: t`Required Quantity`, |  | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         render: (record: any) => { |         render: (record: any) => { | ||||||
|           return ( |           return ( | ||||||
| @@ -164,14 +158,12 @@ export default function BuildLineTable({ params = {} }: { params?: any }) { | |||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'available_stock', |         accessor: 'available_stock', | ||||||
|         title: t`Available`, |  | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         switchable: false, |         switchable: false, | ||||||
|         render: renderAvailableColumn |         render: renderAvailableColumn | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'allocated', |         accessor: 'allocated', | ||||||
|         title: t`Allocated`, |  | ||||||
|         switchable: false, |         switchable: false, | ||||||
|         render: (record: any) => { |         render: (record: any) => { | ||||||
|           return record?.bom_item_detail?.consumable ? ( |           return record?.bom_item_detail?.consumable ? ( | ||||||
| @@ -2,24 +2,25 @@ import { t } from '@lingui/macro'; | |||||||
| import { useMemo } from 'react'; | import { useMemo } from 'react'; | ||||||
| import { useNavigate } from 'react-router-dom'; | import { useNavigate } from 'react-router-dom'; | ||||||
| 
 | 
 | ||||||
| import { renderDate } from '../../../defaults/formatters'; | import { AddItemButton } from '../../components/buttons/AddItemButton'; | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { PartHoverCard } from '../../components/images/Thumbnail'; | ||||||
| import { ModelType } from '../../../enums/ModelType'; | import { ProgressBar } from '../../components/items/ProgressBar'; | ||||||
| import { UserRoles } from '../../../enums/Roles'; | import { RenderUser } from '../../components/render/User'; | ||||||
| import { buildOrderFields } from '../../../forms/BuildForms'; | import { renderDate } from '../../defaults/formatters'; | ||||||
| import { getDetailUrl } from '../../../functions/urls'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { useCreateApiFormModal } from '../../../hooks/UseForm'; | import { ModelType } from '../../enums/ModelType'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { UserRoles } from '../../enums/Roles'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { buildOrderFields } from '../../forms/BuildForms'; | ||||||
| import { useUserState } from '../../../states/UserState'; | import { getDetailUrl } from '../../functions/urls'; | ||||||
| import { AddItemButton } from '../../buttons/AddItemButton'; | import { useCreateApiFormModal } from '../../hooks/UseForm'; | ||||||
| import { PartHoverCard } from '../../images/Thumbnail'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { ProgressBar } from '../../items/ProgressBar'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { RenderUser } from '../../render/User'; | import { useUserState } from '../../states/UserState'; | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { | import { | ||||||
|   CreationDateColumn, |   CreationDateColumn, | ||||||
|   ProjectCodeColumn, |   ProjectCodeColumn, | ||||||
|  |   ReferenceColumn, | ||||||
|   ResponsibleColumn, |   ResponsibleColumn, | ||||||
|   StatusColumn, |   StatusColumn, | ||||||
|   TargetDateColumn |   TargetDateColumn | ||||||
| @@ -32,29 +33,21 @@ import { InvenTreeTable } from '../InvenTreeTable'; | |||||||
|  */ |  */ | ||||||
| function buildOrderTableColumns(): TableColumn[] { | function buildOrderTableColumns(): TableColumn[] { | ||||||
|   return [ |   return [ | ||||||
|     { |     ReferenceColumn(), | ||||||
|       accessor: 'reference', |  | ||||||
|       sortable: true, |  | ||||||
|       switchable: false, |  | ||||||
|       title: t`Reference` |  | ||||||
|     }, |  | ||||||
|     { |     { | ||||||
|       accessor: 'part', |       accessor: 'part', | ||||||
|       sortable: true, |       sortable: true, | ||||||
|       switchable: false, |       switchable: false, | ||||||
|       title: t`Part`, |  | ||||||
|       render: (record: any) => <PartHoverCard part={record.part_detail} /> |       render: (record: any) => <PartHoverCard part={record.part_detail} /> | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       accessor: 'title', |       accessor: 'title', | ||||||
|       sortable: false, |       sortable: false | ||||||
|       title: t`Description` |  | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       accessor: 'completed', |       accessor: 'completed', | ||||||
|       sortable: true, |       sortable: true, | ||||||
|       switchable: false, |       switchable: false, | ||||||
|       title: t`Progress`, |  | ||||||
|       render: (record: any) => ( |       render: (record: any) => ( | ||||||
|         <ProgressBar |         <ProgressBar | ||||||
|           progressLabel={true} |           progressLabel={true} | ||||||
| @@ -67,7 +60,6 @@ function buildOrderTableColumns(): TableColumn[] { | |||||||
|     ProjectCodeColumn(), |     ProjectCodeColumn(), | ||||||
|     { |     { | ||||||
|       accessor: 'priority', |       accessor: 'priority', | ||||||
|       title: t`Priority`, |  | ||||||
|       sortable: true |       sortable: true | ||||||
|     }, |     }, | ||||||
|     CreationDateColumn(), |     CreationDateColumn(), | ||||||
| @@ -75,13 +67,11 @@ function buildOrderTableColumns(): TableColumn[] { | |||||||
|     { |     { | ||||||
|       accessor: 'completion_date', |       accessor: 'completion_date', | ||||||
|       sortable: true, |       sortable: true, | ||||||
|       title: t`Completed`, |  | ||||||
|       render: (record: any) => renderDate(record.completion_date) |       render: (record: any) => renderDate(record.completion_date) | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       accessor: 'issued_by', |       accessor: 'issued_by', | ||||||
|       sortable: true, |       sortable: true, | ||||||
|       title: t`Issued By`, |  | ||||||
|       render: (record: any) => ( |       render: (record: any) => ( | ||||||
|         <RenderUser instance={record?.issued_by_detail} /> |         <RenderUser instance={record?.issued_by_detail} /> | ||||||
|       ) |       ) | ||||||
| @@ -114,14 +104,12 @@ export function BuildOrderTable({ | |||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         name: 'status', |         name: 'status', | ||||||
|         label: t`Status`, |  | ||||||
|         description: t`Filter by order status`, |         description: t`Filter by order status`, | ||||||
|         choiceFunction: StatusFilterOptions(ModelType.build) |         choiceFunction: StatusFilterOptions(ModelType.build) | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         name: 'overdue', |         name: 'overdue', | ||||||
|         type: 'boolean', |         type: 'boolean', | ||||||
|         label: t`Overdue`, |  | ||||||
|         description: t`Show overdue status` |         description: t`Show overdue status` | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
| @@ -1,19 +1,19 @@ | |||||||
| import { t } from '@lingui/macro'; | import { t } from '@lingui/macro'; | ||||||
| import { useCallback, useMemo, useState } from 'react'; | import { useCallback, useMemo, useState } from 'react'; | ||||||
| 
 | 
 | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { AddItemButton } from '../../components/buttons/AddItemButton'; | ||||||
| import { UserRoles } from '../../../enums/Roles'; | import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField'; | ||||||
|  | import { YesNoButton } from '../../components/items/YesNoButton'; | ||||||
|  | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
|  | import { UserRoles } from '../../enums/Roles'; | ||||||
| import { | import { | ||||||
|   useCreateApiFormModal, |   useCreateApiFormModal, | ||||||
|   useDeleteApiFormModal, |   useDeleteApiFormModal, | ||||||
|   useEditApiFormModal |   useEditApiFormModal | ||||||
| } from '../../../hooks/UseForm'; | } from '../../hooks/UseForm'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { useUserState } from '../../../states/UserState'; | import { useUserState } from '../../states/UserState'; | ||||||
| import { AddItemButton } from '../../buttons/AddItemButton'; |  | ||||||
| import { ApiFormFieldSet } from '../../forms/fields/ApiFormField'; |  | ||||||
| import { YesNoButton } from '../../items/YesNoButton'; |  | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { InvenTreeTable } from '../InvenTreeTable'; | import { InvenTreeTable } from '../InvenTreeTable'; | ||||||
| import { RowDeleteAction, RowEditAction } from '../RowActions'; | import { RowDeleteAction, RowEditAction } from '../RowActions'; | ||||||
| @@ -33,13 +33,11 @@ export function AddressTable({ | |||||||
|     return [ |     return [ | ||||||
|       { |       { | ||||||
|         accessor: 'title', |         accessor: 'title', | ||||||
|         title: t`Title`, |  | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         switchable: false |         switchable: false | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'primary', |         accessor: 'primary', | ||||||
|         title: t`Primary`, |  | ||||||
|         switchable: false, |         switchable: false, | ||||||
|         sortable: false, |         sortable: false, | ||||||
|         render: (record: any) => YesNoButton({ value: record.primary }) |         render: (record: any) => YesNoButton({ value: record.primary }) | ||||||
| @@ -65,43 +63,36 @@ export function AddressTable({ | |||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'postal_code', |         accessor: 'postal_code', | ||||||
|         title: t`Postal Code`, |  | ||||||
|         sortable: false, |         sortable: false, | ||||||
|         switchable: true |         switchable: true | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'postal_city', |         accessor: 'postal_city', | ||||||
|         title: t`City`, |  | ||||||
|         sortable: false, |         sortable: false, | ||||||
|         switchable: true |         switchable: true | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'province', |         accessor: 'province', | ||||||
|         title: t`State / Province`, |  | ||||||
|         sortable: false, |         sortable: false, | ||||||
|         switchable: true |         switchable: true | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'country', |         accessor: 'country', | ||||||
|         title: t`Country`, |  | ||||||
|         sortable: false, |         sortable: false, | ||||||
|         switchable: true |         switchable: true | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'shipping_notes', |         accessor: 'shipping_notes', | ||||||
|         title: t`Courier Notes`, |  | ||||||
|         sortable: false, |         sortable: false, | ||||||
|         switchable: true |         switchable: true | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'internal_shipping_notes', |         accessor: 'internal_shipping_notes', | ||||||
|         title: t`Internal Notes`, |  | ||||||
|         sortable: false, |         sortable: false, | ||||||
|         switchable: true |         switchable: true | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'link', |         accessor: 'link', | ||||||
|         title: t`Link`, |  | ||||||
|         sortable: false, |         sortable: false, | ||||||
|         switchable: true |         switchable: true | ||||||
|       } |       } | ||||||
| @@ -3,15 +3,15 @@ import { Group, Text } from '@mantine/core'; | |||||||
| import { useMemo } from 'react'; | import { useMemo } from 'react'; | ||||||
| import { useNavigate } from 'react-router-dom'; | import { useNavigate } from 'react-router-dom'; | ||||||
| 
 | 
 | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { AddItemButton } from '../../components/buttons/AddItemButton'; | ||||||
| import { UserRoles } from '../../../enums/Roles'; | import { Thumbnail } from '../../components/images/Thumbnail'; | ||||||
| import { companyFields } from '../../../forms/CompanyForms'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { useCreateApiFormModal } from '../../../hooks/UseForm'; | import { UserRoles } from '../../enums/Roles'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { companyFields } from '../../forms/CompanyForms'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { useCreateApiFormModal } from '../../hooks/UseForm'; | ||||||
| import { useUserState } from '../../../states/UserState'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { AddItemButton } from '../../buttons/AddItemButton'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { Thumbnail } from '../../images/Thumbnail'; | import { useUserState } from '../../states/UserState'; | ||||||
| import { DescriptionColumn } from '../ColumnRenderers'; | import { DescriptionColumn } from '../ColumnRenderers'; | ||||||
| import { InvenTreeTable } from '../InvenTreeTable'; | import { InvenTreeTable } from '../InvenTreeTable'; | ||||||
| 
 | 
 | ||||||
| @@ -35,7 +35,6 @@ export function CompanyTable({ | |||||||
|     return [ |     return [ | ||||||
|       { |       { | ||||||
|         accessor: 'name', |         accessor: 'name', | ||||||
|         title: t`Company Name`, |  | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         render: (record: any) => { |         render: (record: any) => { | ||||||
|           return ( |           return ( | ||||||
| @@ -53,7 +52,6 @@ export function CompanyTable({ | |||||||
|       DescriptionColumn({}), |       DescriptionColumn({}), | ||||||
|       { |       { | ||||||
|         accessor: 'website', |         accessor: 'website', | ||||||
|         title: t`Website`, |  | ||||||
|         sortable: false |         sortable: false | ||||||
|       } |       } | ||||||
|     ]; |     ]; | ||||||
| @@ -65,7 +63,6 @@ export function CompanyTable({ | |||||||
|     fields: companyFields(), |     fields: companyFields(), | ||||||
|     initialData: params, |     initialData: params, | ||||||
|     onFormSuccess: (response) => { |     onFormSuccess: (response) => { | ||||||
|       console.log('onFormSuccess:', response); |  | ||||||
|       if (response.pk) { |       if (response.pk) { | ||||||
|         let base = path ?? 'company'; |         let base = path ?? 'company'; | ||||||
|         navigate(`/${base}/${response.pk}`); |         navigate(`/${base}/${response.pk}`); | ||||||
| @@ -1,18 +1,18 @@ | |||||||
| import { t } from '@lingui/macro'; | import { t } from '@lingui/macro'; | ||||||
| import { useCallback, useMemo, useState } from 'react'; | import { useCallback, useMemo, useState } from 'react'; | ||||||
| 
 | 
 | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { AddItemButton } from '../../components/buttons/AddItemButton'; | ||||||
| import { UserRoles } from '../../../enums/Roles'; | import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField'; | ||||||
|  | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
|  | import { UserRoles } from '../../enums/Roles'; | ||||||
| import { | import { | ||||||
|   useCreateApiFormModal, |   useCreateApiFormModal, | ||||||
|   useDeleteApiFormModal, |   useDeleteApiFormModal, | ||||||
|   useEditApiFormModal |   useEditApiFormModal | ||||||
| } from '../../../hooks/UseForm'; | } from '../../hooks/UseForm'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { useUserState } from '../../../states/UserState'; | import { useUserState } from '../../states/UserState'; | ||||||
| import { AddItemButton } from '../../buttons/AddItemButton'; |  | ||||||
| import { ApiFormFieldSet } from '../../forms/fields/ApiFormField'; |  | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { InvenTreeTable } from '../InvenTreeTable'; | import { InvenTreeTable } from '../InvenTreeTable'; | ||||||
| import { RowDeleteAction, RowEditAction } from '../RowActions'; | import { RowDeleteAction, RowEditAction } from '../RowActions'; | ||||||
| @@ -32,25 +32,21 @@ export function ContactTable({ | |||||||
|     return [ |     return [ | ||||||
|       { |       { | ||||||
|         accessor: 'name', |         accessor: 'name', | ||||||
|         title: t`Name`, |  | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         switchable: false |         switchable: false | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'phone', |         accessor: 'phone', | ||||||
|         title: t`Phone`, |  | ||||||
|         switchable: true, |         switchable: true, | ||||||
|         sortable: false |         sortable: false | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'email', |         accessor: 'email', | ||||||
|         title: t`Email`, |  | ||||||
|         switchable: true, |         switchable: true, | ||||||
|         sortable: false |         sortable: false | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'role', |         accessor: 'role', | ||||||
|         title: t`Role`, |  | ||||||
|         switchable: true, |         switchable: true, | ||||||
|         sortable: false |         sortable: false | ||||||
|       } |       } | ||||||
| @@ -6,16 +6,16 @@ import { notifications } from '@mantine/notifications'; | |||||||
| import { IconExternalLink, IconFileUpload } from '@tabler/icons-react'; | import { IconExternalLink, IconFileUpload } from '@tabler/icons-react'; | ||||||
| import { ReactNode, useEffect, useMemo, useState } from 'react'; | import { ReactNode, useEffect, useMemo, useState } from 'react'; | ||||||
| 
 | 
 | ||||||
| import { api } from '../../../App'; | import { api } from '../../App'; | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { AttachmentLink } from '../../components/items/AttachmentLink'; | ||||||
|  | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { | import { | ||||||
|   addAttachment, |   addAttachment, | ||||||
|   deleteAttachment, |   deleteAttachment, | ||||||
|   editAttachment |   editAttachment | ||||||
| } from '../../../forms/AttachmentForms'; | } from '../../forms/AttachmentForms'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { AttachmentLink } from '../../items/AttachmentLink'; |  | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { InvenTreeTable } from '../InvenTreeTable'; | import { InvenTreeTable } from '../InvenTreeTable'; | ||||||
| import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions'; | import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions'; | ||||||
| @@ -27,7 +27,6 @@ function attachmentTableColumns(): TableColumn[] { | |||||||
|   return [ |   return [ | ||||||
|     { |     { | ||||||
|       accessor: 'attachment', |       accessor: 'attachment', | ||||||
|       title: t`Attachment`, |  | ||||||
|       sortable: false, |       sortable: false, | ||||||
|       switchable: false, |       switchable: false, | ||||||
|       noWrap: true, |       noWrap: true, | ||||||
| @@ -44,7 +43,6 @@ function attachmentTableColumns(): TableColumn[] { | |||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       accessor: 'comment', |       accessor: 'comment', | ||||||
|       title: t`Comment`, |  | ||||||
|       sortable: false, |       sortable: false, | ||||||
| 
 | 
 | ||||||
|       render: function (record: any) { |       render: function (record: any) { | ||||||
| @@ -52,9 +50,8 @@ function attachmentTableColumns(): TableColumn[] { | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       accessor: 'uploaded', |       accessor: 'upload_date', | ||||||
|       title: t`Uploaded`, |       sortable: true, | ||||||
|       sortable: false, |  | ||||||
| 
 | 
 | ||||||
|       render: function (record: any) { |       render: function (record: any) { | ||||||
|         return ( |         return ( | ||||||
| @@ -1,9 +1,9 @@ | |||||||
| import { t } from '@lingui/macro'; | import { t } from '@lingui/macro'; | ||||||
| import { useMemo } from 'react'; | import { useMemo } from 'react'; | ||||||
| 
 | 
 | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { TableState } from '../../../hooks/UseTable'; | import { TableState } from '../../hooks/UseTable'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { InvenTreeTable } from '../InvenTreeTable'; | import { InvenTreeTable } from '../InvenTreeTable'; | ||||||
| import { RowAction } from '../RowActions'; | import { RowAction } from '../RowActions'; | ||||||
| @@ -2,20 +2,20 @@ import { t } from '@lingui/macro'; | |||||||
| import { useCallback, useMemo, useState } from 'react'; | import { useCallback, useMemo, useState } from 'react'; | ||||||
| import { useNavigate } from 'react-router-dom'; | import { useNavigate } from 'react-router-dom'; | ||||||
| 
 | 
 | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { AddItemButton } from '../../components/buttons/AddItemButton'; | ||||||
| import { ModelType } from '../../../enums/ModelType'; | import { YesNoButton } from '../../components/items/YesNoButton'; | ||||||
| import { UserRoles } from '../../../enums/Roles'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { partCategoryFields } from '../../../forms/PartForms'; | import { ModelType } from '../../enums/ModelType'; | ||||||
| import { getDetailUrl } from '../../../functions/urls'; | import { UserRoles } from '../../enums/Roles'; | ||||||
|  | import { partCategoryFields } from '../../forms/PartForms'; | ||||||
|  | import { getDetailUrl } from '../../functions/urls'; | ||||||
| import { | import { | ||||||
|   useCreateApiFormModal, |   useCreateApiFormModal, | ||||||
|   useEditApiFormModal |   useEditApiFormModal | ||||||
| } from '../../../hooks/UseForm'; | } from '../../hooks/UseForm'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { useUserState } from '../../../states/UserState'; | import { useUserState } from '../../states/UserState'; | ||||||
| import { AddItemButton } from '../../buttons/AddItemButton'; |  | ||||||
| import { YesNoButton } from '../../items/YesNoButton'; |  | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { DescriptionColumn } from '../ColumnRenderers'; | import { DescriptionColumn } from '../ColumnRenderers'; | ||||||
| import { TableFilter } from '../Filter'; | import { TableFilter } from '../Filter'; | ||||||
| @@ -35,19 +35,16 @@ export function PartCategoryTable({ parentId }: { parentId?: any }) { | |||||||
|     return [ |     return [ | ||||||
|       { |       { | ||||||
|         accessor: 'name', |         accessor: 'name', | ||||||
|         title: t`Name`, |  | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         switchable: false |         switchable: false | ||||||
|       }, |       }, | ||||||
|       DescriptionColumn({}), |       DescriptionColumn({}), | ||||||
|       { |       { | ||||||
|         accessor: 'pathstring', |         accessor: 'pathstring', | ||||||
|         title: t`Path`, |  | ||||||
|         sortable: false |         sortable: false | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'structural', |         accessor: 'structural', | ||||||
|         title: t`Structural`, |  | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         render: (record: any) => { |         render: (record: any) => { | ||||||
|           return <YesNoButton value={record.structural} />; |           return <YesNoButton value={record.structural} />; | ||||||
| @@ -55,7 +52,6 @@ export function PartCategoryTable({ parentId }: { parentId?: any }) { | |||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'part_count', |         accessor: 'part_count', | ||||||
|         title: t`Parts`, |  | ||||||
|         sortable: true |         sortable: true | ||||||
|       } |       } | ||||||
|     ]; |     ]; | ||||||
| @@ -2,21 +2,21 @@ import { t } from '@lingui/macro'; | |||||||
| import { Text } from '@mantine/core'; | import { Text } from '@mantine/core'; | ||||||
| import { useCallback, useMemo, useState } from 'react'; | import { useCallback, useMemo, useState } from 'react'; | ||||||
| 
 | 
 | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { AddItemButton } from '../../components/buttons/AddItemButton'; | ||||||
| import { UserRoles } from '../../../enums/Roles'; | import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField'; | ||||||
|  | import { YesNoButton } from '../../components/items/YesNoButton'; | ||||||
|  | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
|  | import { UserRoles } from '../../enums/Roles'; | ||||||
| import { | import { | ||||||
|   useCreateApiFormModal, |   useCreateApiFormModal, | ||||||
|   useDeleteApiFormModal, |   useDeleteApiFormModal, | ||||||
|   useEditApiFormModal |   useEditApiFormModal | ||||||
| } from '../../../hooks/UseForm'; | } from '../../hooks/UseForm'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { useUserState } from '../../../states/UserState'; | import { useUserState } from '../../states/UserState'; | ||||||
| import { AddItemButton } from '../../buttons/AddItemButton'; |  | ||||||
| import { ApiFormFieldSet } from '../../forms/fields/ApiFormField'; |  | ||||||
| import { YesNoButton } from '../../items/YesNoButton'; |  | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { PartColumn } from '../ColumnRenderers'; | import { DescriptionColumn, PartColumn } from '../ColumnRenderers'; | ||||||
| import { InvenTreeTable } from '../InvenTreeTable'; | import { InvenTreeTable } from '../InvenTreeTable'; | ||||||
| import { RowDeleteAction, RowEditAction } from '../RowActions'; | import { RowDeleteAction, RowEditAction } from '../RowActions'; | ||||||
| 
 | 
 | ||||||
| @@ -32,20 +32,16 @@ export function PartParameterTable({ partId }: { partId: any }) { | |||||||
|     return [ |     return [ | ||||||
|       { |       { | ||||||
|         accessor: 'part', |         accessor: 'part', | ||||||
|         title: t`Part`, |  | ||||||
| 
 |  | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         render: (record: any) => PartColumn(record?.part_detail) |         render: (record: any) => PartColumn(record?.part_detail) | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'part_detail.IPN', |         accessor: 'part_detail.IPN', | ||||||
|         title: t`IPN`, |  | ||||||
|         sortable: false, |         sortable: false, | ||||||
|         switchable: true |         switchable: true | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'name', |         accessor: 'template_detail.name', | ||||||
|         title: t`Parameter`, |  | ||||||
|         switchable: false, |         switchable: false, | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         render: (record) => { |         render: (record) => { | ||||||
| @@ -54,16 +50,11 @@ export function PartParameterTable({ partId }: { partId: any }) { | |||||||
|           return <Text italic={variant}>{record.template_detail?.name}</Text>; |           return <Text italic={variant}>{record.template_detail?.name}</Text>; | ||||||
|         } |         } | ||||||
|       }, |       }, | ||||||
|       { |       DescriptionColumn({ | ||||||
|         accessor: 'description', |         accessor: 'template_detail.description' | ||||||
|         title: t`Description`, |       }), | ||||||
|         sortable: false, |  | ||||||
| 
 |  | ||||||
|         render: (record) => record.template_detail?.description |  | ||||||
|       }, |  | ||||||
|       { |       { | ||||||
|         accessor: 'data', |         accessor: 'data', | ||||||
|         title: t`Value`, |  | ||||||
|         switchable: false, |         switchable: false, | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         render: (record) => { |         render: (record) => { | ||||||
| @@ -83,11 +74,8 @@ export function PartParameterTable({ partId }: { partId: any }) { | |||||||
|         } |         } | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'units', |         accessor: 'template_detail.units', | ||||||
|         title: t`Units`, |         sortable: false | ||||||
| 
 |  | ||||||
|         sortable: true, |  | ||||||
|         render: (record) => record.template_detail?.units |  | ||||||
|       } |       } | ||||||
|     ]; |     ]; | ||||||
|   }, [partId]); |   }, [partId]); | ||||||
| @@ -1,18 +1,18 @@ | |||||||
| import { t } from '@lingui/macro'; | import { t } from '@lingui/macro'; | ||||||
| import { useCallback, useMemo, useState } from 'react'; | import { useCallback, useMemo, useState } from 'react'; | ||||||
| 
 | 
 | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { AddItemButton } from '../../components/buttons/AddItemButton'; | ||||||
| import { UserRoles } from '../../../enums/Roles'; | import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField'; | ||||||
|  | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
|  | import { UserRoles } from '../../enums/Roles'; | ||||||
| import { | import { | ||||||
|   useCreateApiFormModal, |   useCreateApiFormModal, | ||||||
|   useDeleteApiFormModal, |   useDeleteApiFormModal, | ||||||
|   useEditApiFormModal |   useEditApiFormModal | ||||||
| } from '../../../hooks/UseForm'; | } from '../../hooks/UseForm'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { useUserState } from '../../../states/UserState'; | import { useUserState } from '../../states/UserState'; | ||||||
| import { AddItemButton } from '../../buttons/AddItemButton'; |  | ||||||
| import { ApiFormFieldSet } from '../../forms/fields/ApiFormField'; |  | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { DescriptionColumn } from '../ColumnRenderers'; | import { DescriptionColumn } from '../ColumnRenderers'; | ||||||
| import { TableFilter } from '../Filter'; | import { TableFilter } from '../Filter'; | ||||||
| @@ -48,23 +48,19 @@ export default function PartParameterTemplateTable() { | |||||||
|     return [ |     return [ | ||||||
|       { |       { | ||||||
|         accessor: 'name', |         accessor: 'name', | ||||||
|         title: t`Name`, |  | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         switchable: false |         switchable: false | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'units', |         accessor: 'units', | ||||||
|         title: t`Units`, |  | ||||||
|         sortable: true |         sortable: true | ||||||
|       }, |       }, | ||||||
|       DescriptionColumn({}), |       DescriptionColumn({}), | ||||||
|       { |       { | ||||||
|         accessor: 'checkbox', |         accessor: 'checkbox' | ||||||
|         title: t`Checkbox` |  | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'choices', |         accessor: 'choices' | ||||||
|         title: t`Choices` |  | ||||||
|       } |       } | ||||||
|     ]; |     ]; | ||||||
|   }, []); |   }, []); | ||||||
| @@ -3,14 +3,14 @@ import { Group, Text } from '@mantine/core'; | |||||||
| import { ReactNode, useMemo } from 'react'; | import { ReactNode, useMemo } from 'react'; | ||||||
| import { useNavigate } from 'react-router-dom'; | import { useNavigate } from 'react-router-dom'; | ||||||
| 
 | 
 | ||||||
| import { formatPriceRange } from '../../../defaults/formatters'; | import { Thumbnail } from '../../components/images/Thumbnail'; | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { formatPriceRange } from '../../defaults/formatters'; | ||||||
| import { ModelType } from '../../../enums/ModelType'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { shortenString } from '../../../functions/tables'; | import { ModelType } from '../../enums/ModelType'; | ||||||
| import { getDetailUrl } from '../../../functions/urls'; | import { shortenString } from '../../functions/tables'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { getDetailUrl } from '../../functions/urls'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { Thumbnail } from '../../images/Thumbnail'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { DescriptionColumn, LinkColumn } from '../ColumnRenderers'; | import { DescriptionColumn, LinkColumn } from '../ColumnRenderers'; | ||||||
| import { TableFilter } from '../Filter'; | import { TableFilter } from '../Filter'; | ||||||
| @@ -26,7 +26,6 @@ function partTableColumns(): TableColumn[] { | |||||||
|       accessor: 'name', |       accessor: 'name', | ||||||
|       sortable: true, |       sortable: true, | ||||||
|       noWrap: true, |       noWrap: true, | ||||||
|       title: t`Part`, |  | ||||||
|       render: function (record: any) { |       render: function (record: any) { | ||||||
|         return ( |         return ( | ||||||
|           <Thumbnail |           <Thumbnail | ||||||
| @@ -39,18 +38,15 @@ function partTableColumns(): TableColumn[] { | |||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       accessor: 'IPN', |       accessor: 'IPN', | ||||||
|       title: t`IPN`, |  | ||||||
|       sortable: true |       sortable: true | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       accessor: 'units', |       accessor: 'units', | ||||||
|       sortable: true, |       sortable: true | ||||||
|       title: t`Units` |  | ||||||
|     }, |     }, | ||||||
|     DescriptionColumn({}), |     DescriptionColumn({}), | ||||||
|     { |     { | ||||||
|       accessor: 'category', |       accessor: 'category', | ||||||
|       title: t`Category`, |  | ||||||
|       sortable: true, |       sortable: true, | ||||||
| 
 | 
 | ||||||
|       render: function (record: any) { |       render: function (record: any) { | ||||||
| @@ -62,7 +58,6 @@ function partTableColumns(): TableColumn[] { | |||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       accessor: 'total_in_stock', |       accessor: 'total_in_stock', | ||||||
|       title: t`Stock`, |  | ||||||
|       sortable: true, |       sortable: true, | ||||||
| 
 | 
 | ||||||
|       render: (record) => { |       render: (record) => { | ||||||
| @@ -1,18 +1,18 @@ | |||||||
| import { t } from '@lingui/macro'; | import { t } from '@lingui/macro'; | ||||||
| import { useCallback, useMemo, useState } from 'react'; | import { useCallback, useMemo, useState } from 'react'; | ||||||
| 
 | 
 | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { AddItemButton } from '../../components/buttons/AddItemButton'; | ||||||
| import { UserRoles } from '../../../enums/Roles'; | import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField'; | ||||||
|  | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
|  | import { UserRoles } from '../../enums/Roles'; | ||||||
| import { | import { | ||||||
|   useCreateApiFormModal, |   useCreateApiFormModal, | ||||||
|   useDeleteApiFormModal, |   useDeleteApiFormModal, | ||||||
|   useEditApiFormModal |   useEditApiFormModal | ||||||
| } from '../../../hooks/UseForm'; | } from '../../hooks/UseForm'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { useUserState } from '../../../states/UserState'; | import { useUserState } from '../../states/UserState'; | ||||||
| import { AddItemButton } from '../../buttons/AddItemButton'; |  | ||||||
| import { ApiFormFieldSet } from '../../forms/fields/ApiFormField'; |  | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { BooleanColumn, DescriptionColumn } from '../ColumnRenderers'; | import { BooleanColumn, DescriptionColumn } from '../ColumnRenderers'; | ||||||
| import { TableFilter } from '../Filter'; | import { TableFilter } from '../Filter'; | ||||||
| @@ -27,7 +27,6 @@ export default function PartTestTemplateTable({ partId }: { partId: number }) { | |||||||
|     return [ |     return [ | ||||||
|       { |       { | ||||||
|         accessor: 'test_name', |         accessor: 'test_name', | ||||||
|         title: t`Test Name`, |  | ||||||
|         switchable: false, |         switchable: false, | ||||||
|         sortable: true |         sortable: true | ||||||
|       }, |       }, | ||||||
| @@ -35,16 +34,13 @@ export default function PartTestTemplateTable({ partId }: { partId: number }) { | |||||||
|         switchable: false |         switchable: false | ||||||
|       }), |       }), | ||||||
|       BooleanColumn({ |       BooleanColumn({ | ||||||
|         accessor: 'required', |         accessor: 'required' | ||||||
|         title: t`Required` |  | ||||||
|       }), |       }), | ||||||
|       BooleanColumn({ |       BooleanColumn({ | ||||||
|         accessor: 'requires_value', |         accessor: 'requires_value' | ||||||
|         title: t`Requires Value` |  | ||||||
|       }), |       }), | ||||||
|       BooleanColumn({ |       BooleanColumn({ | ||||||
|         accessor: 'requires_attachment', |         accessor: 'requires_attachment' | ||||||
|         title: t`Requires Attachment` |  | ||||||
|       }) |       }) | ||||||
|     ]; |     ]; | ||||||
|   }, []); |   }, []); | ||||||
| @@ -53,17 +49,14 @@ export default function PartTestTemplateTable({ partId }: { partId: number }) { | |||||||
|     return [ |     return [ | ||||||
|       { |       { | ||||||
|         name: 'required', |         name: 'required', | ||||||
|         label: t`Required`, |  | ||||||
|         description: t`Show required tests` |         description: t`Show required tests` | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         name: 'requires_value', |         name: 'requires_value', | ||||||
|         label: t`Requires Value`, |  | ||||||
|         description: t`Show tests that require a value` |         description: t`Show tests that require a value` | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         name: 'requires_attachment', |         name: 'requires_attachment', | ||||||
|         label: t`Requires Attachment`, |  | ||||||
|         description: t`Show tests that require an attachment` |         description: t`Show tests that require an attachment` | ||||||
|       } |       } | ||||||
|     ]; |     ]; | ||||||
| @@ -4,10 +4,10 @@ import { useHover } from '@mantine/hooks'; | |||||||
| import { useQuery } from '@tanstack/react-query'; | import { useQuery } from '@tanstack/react-query'; | ||||||
| import React, { Suspense, useEffect, useState } from 'react'; | import React, { Suspense, useEffect, useState } from 'react'; | ||||||
| 
 | 
 | ||||||
| import { api } from '../../../App'; | import { api } from '../../App'; | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { Thumbnail } from '../../components/images/Thumbnail'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { Thumbnail } from '../../images/Thumbnail'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Input props to table |  * Input props to table | ||||||
| @@ -3,18 +3,18 @@ import { Group, Text } from '@mantine/core'; | |||||||
| import { ReactNode, useCallback, useMemo, useState } from 'react'; | import { ReactNode, useCallback, useMemo, useState } from 'react'; | ||||||
| import { useNavigate } from 'react-router-dom'; | import { useNavigate } from 'react-router-dom'; | ||||||
| 
 | 
 | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { AddItemButton } from '../../components/buttons/AddItemButton'; | ||||||
| import { UserRoles } from '../../../enums/Roles'; | import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField'; | ||||||
|  | import { Thumbnail } from '../../components/images/Thumbnail'; | ||||||
|  | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
|  | import { UserRoles } from '../../enums/Roles'; | ||||||
| import { | import { | ||||||
|   useCreateApiFormModal, |   useCreateApiFormModal, | ||||||
|   useDeleteApiFormModal |   useDeleteApiFormModal | ||||||
| } from '../../../hooks/UseForm'; | } from '../../hooks/UseForm'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { useUserState } from '../../../states/UserState'; | import { useUserState } from '../../states/UserState'; | ||||||
| import { AddItemButton } from '../../buttons/AddItemButton'; |  | ||||||
| import { ApiFormFieldSet } from '../../forms/fields/ApiFormField'; |  | ||||||
| import { Thumbnail } from '../../images/Thumbnail'; |  | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { InvenTreeTable } from '../InvenTreeTable'; | import { InvenTreeTable } from '../InvenTreeTable'; | ||||||
| import { RowDeleteAction } from '../RowActions'; | import { RowDeleteAction } from '../RowActions'; | ||||||
| @@ -2,9 +2,9 @@ import { t } from '@lingui/macro'; | |||||||
| import { Code } from '@mantine/core'; | import { Code } from '@mantine/core'; | ||||||
| import { useMemo } from 'react'; | import { useMemo } from 'react'; | ||||||
| 
 | 
 | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { InvenTreeTable, InvenTreeTableProps } from '../InvenTreeTable'; | import { InvenTreeTable, InvenTreeTableProps } from '../InvenTreeTable'; | ||||||
| 
 | 
 | ||||||
| @@ -23,20 +23,23 @@ import { IconDots } from '@tabler/icons-react'; | |||||||
| import { useCallback, useMemo } from 'react'; | import { useCallback, useMemo } from 'react'; | ||||||
| import { useNavigate } from 'react-router-dom'; | import { useNavigate } from 'react-router-dom'; | ||||||
| 
 | 
 | ||||||
| import { api } from '../../../App'; | import { api } from '../../App'; | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { ActionButton } from '../../components/buttons/ActionButton'; | ||||||
| import { openEditApiForm } from '../../../functions/forms'; | import { | ||||||
| import { useCreateApiFormModal } from '../../../hooks/UseForm'; |   ActionDropdown, | ||||||
| import { useInstance } from '../../../hooks/UseInstance'; |   EditItemAction | ||||||
| import { useTable } from '../../../hooks/UseTable'; | } from '../../components/items/ActionDropdown'; | ||||||
| import { apiUrl, useServerApiState } from '../../../states/ApiState'; | import { InfoItem } from '../../components/items/InfoItem'; | ||||||
| import { useUserState } from '../../../states/UserState'; | import { StylishText } from '../../components/items/StylishText'; | ||||||
| import { ActionButton } from '../../buttons/ActionButton'; | import { DetailDrawer } from '../../components/nav/DetailDrawer'; | ||||||
| import { ActionDropdown, EditItemAction } from '../../items/ActionDropdown'; | import { PluginSettingList } from '../../components/settings/SettingList'; | ||||||
| import { InfoItem } from '../../items/InfoItem'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { StylishText } from '../../items/StylishText'; | import { openEditApiForm } from '../../functions/forms'; | ||||||
| import { DetailDrawer } from '../../nav/DetailDrawer'; | import { useCreateApiFormModal } from '../../hooks/UseForm'; | ||||||
| import { PluginSettingList } from '../../settings/SettingList'; | 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 { TableColumn } from '../Column'; | ||||||
| import { InvenTreeTable, InvenTreeTableProps } from '../InvenTreeTable'; | import { InvenTreeTable, InvenTreeTableProps } from '../InvenTreeTable'; | ||||||
| import { RowAction } from '../RowActions'; | import { RowAction } from '../RowActions'; | ||||||
| @@ -1,13 +1,13 @@ | |||||||
| import { t } from '@lingui/macro'; | import { t } from '@lingui/macro'; | ||||||
| import { useCallback, useMemo } from 'react'; | import { useCallback, useMemo } from 'react'; | ||||||
| 
 | 
 | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { UserRoles } from '../../../enums/Roles'; | import { UserRoles } from '../../enums/Roles'; | ||||||
| import { useManufacturerPartParameterFields } from '../../../forms/CompanyForms'; | import { useManufacturerPartParameterFields } from '../../forms/CompanyForms'; | ||||||
| import { openDeleteApiForm, openEditApiForm } from '../../../functions/forms'; | import { openDeleteApiForm, openEditApiForm } from '../../functions/forms'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { useUserState } from '../../../states/UserState'; | import { useUserState } from '../../states/UserState'; | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { InvenTreeTable } from '../InvenTreeTable'; | import { InvenTreeTable } from '../InvenTreeTable'; | ||||||
| import { RowDeleteAction, RowEditAction } from '../RowActions'; | import { RowDeleteAction, RowEditAction } from '../RowActions'; | ||||||
| @@ -2,18 +2,18 @@ import { t } from '@lingui/macro'; | |||||||
| import { ReactNode, useCallback, useMemo } from 'react'; | import { ReactNode, useCallback, useMemo } from 'react'; | ||||||
| import { useNavigate } from 'react-router-dom'; | import { useNavigate } from 'react-router-dom'; | ||||||
| 
 | 
 | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { AddItemButton } from '../../components/buttons/AddItemButton'; | ||||||
| import { ModelType } from '../../../enums/ModelType'; | import { Thumbnail } from '../../components/images/Thumbnail'; | ||||||
| import { UserRoles } from '../../../enums/Roles'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { useManufacturerPartFields } from '../../../forms/CompanyForms'; | import { ModelType } from '../../enums/ModelType'; | ||||||
| import { openDeleteApiForm, openEditApiForm } from '../../../functions/forms'; | import { UserRoles } from '../../enums/Roles'; | ||||||
| import { notYetImplemented } from '../../../functions/notifications'; | import { useManufacturerPartFields } from '../../forms/CompanyForms'; | ||||||
| import { getDetailUrl } from '../../../functions/urls'; | import { openDeleteApiForm, openEditApiForm } from '../../functions/forms'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { notYetImplemented } from '../../functions/notifications'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { getDetailUrl } from '../../functions/urls'; | ||||||
| import { useUserState } from '../../../states/UserState'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { AddItemButton } from '../../buttons/AddItemButton'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { Thumbnail } from '../../images/Thumbnail'; | import { useUserState } from '../../states/UserState'; | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { DescriptionColumn, LinkColumn, PartColumn } from '../ColumnRenderers'; | import { DescriptionColumn, LinkColumn, PartColumn } from '../ColumnRenderers'; | ||||||
| import { InvenTreeTable } from '../InvenTreeTable'; | import { InvenTreeTable } from '../InvenTreeTable'; | ||||||
| @@ -33,14 +33,12 @@ export function ManufacturerPartTable({ params }: { params: any }): ReactNode { | |||||||
|     return [ |     return [ | ||||||
|       { |       { | ||||||
|         accessor: 'part', |         accessor: 'part', | ||||||
|         title: t`Part`, |  | ||||||
|         switchable: 'part' in params, |         switchable: 'part' in params, | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         render: (record: any) => PartColumn(record?.part_detail) |         render: (record: any) => PartColumn(record?.part_detail) | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'manufacturer', |         accessor: 'manufacturer', | ||||||
|         title: t`Manufacturer`, |  | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         render: (record: any) => { |         render: (record: any) => { | ||||||
|           let manufacturer = record?.manufacturer_detail ?? {}; |           let manufacturer = record?.manufacturer_detail ?? {}; | ||||||
| @@ -4,27 +4,28 @@ import { IconSquareArrowRight } from '@tabler/icons-react'; | |||||||
| import { useCallback, useMemo, useState } from 'react'; | import { useCallback, useMemo, useState } from 'react'; | ||||||
| import { useNavigate } from 'react-router-dom'; | import { useNavigate } from 'react-router-dom'; | ||||||
| 
 | 
 | ||||||
| import { ProgressBar } from '../../../components/items/ProgressBar'; | import { ActionButton } from '../../components/buttons/ActionButton'; | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { AddItemButton } from '../../components/buttons/AddItemButton'; | ||||||
| import { ModelType } from '../../../enums/ModelType'; | import { Thumbnail } from '../../components/images/Thumbnail'; | ||||||
| import { UserRoles } from '../../../enums/Roles'; | import { ProgressBar } from '../../components/items/ProgressBar'; | ||||||
| import { purchaseOrderLineItemFields } from '../../../forms/PurchaseOrderForms'; | import { RenderStockLocation } from '../../components/render/Stock'; | ||||||
| import { getDetailUrl } from '../../../functions/urls'; | 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 { | import { | ||||||
|   useCreateApiFormModal, |   useCreateApiFormModal, | ||||||
|   useDeleteApiFormModal, |   useDeleteApiFormModal, | ||||||
|   useEditApiFormModal |   useEditApiFormModal | ||||||
| } from '../../../hooks/UseForm'; | } from '../../hooks/UseForm'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { useUserState } from '../../../states/UserState'; | import { useUserState } from '../../states/UserState'; | ||||||
| import { ActionButton } from '../../buttons/ActionButton'; |  | ||||||
| import { AddItemButton } from '../../buttons/AddItemButton'; |  | ||||||
| import { Thumbnail } from '../../images/Thumbnail'; |  | ||||||
| import { RenderStockLocation } from '../../render/Stock'; |  | ||||||
| import { | import { | ||||||
|   CurrencyColumn, |   CurrencyColumn, | ||||||
|   LinkColumn, |   LinkColumn, | ||||||
|  |   ReferenceColumn, | ||||||
|   TargetDateColumn, |   TargetDateColumn, | ||||||
|   TotalPriceColumn |   TotalPriceColumn | ||||||
| } from '../ColumnRenderers'; | } from '../ColumnRenderers'; | ||||||
| @@ -74,11 +75,7 @@ export function PurchaseOrderLineItemTable({ | |||||||
|         sortable: false, |         sortable: false, | ||||||
|         render: (record: any) => record?.part_detail?.description |         render: (record: any) => record?.part_detail?.description | ||||||
|       }, |       }, | ||||||
|       { |       ReferenceColumn(), | ||||||
|         accessor: 'reference', |  | ||||||
|         title: t`Reference`, |  | ||||||
|         sortable: true |  | ||||||
|       }, |  | ||||||
|       { |       { | ||||||
|         accessor: 'quantity', |         accessor: 'quantity', | ||||||
|         title: t`Quantity`, |         title: t`Quantity`, | ||||||
| @@ -2,22 +2,23 @@ import { t } from '@lingui/macro'; | |||||||
| import { useMemo } from 'react'; | import { useMemo } from 'react'; | ||||||
| import { useNavigate } from 'react-router-dom'; | import { useNavigate } from 'react-router-dom'; | ||||||
| 
 | 
 | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { AddItemButton } from '../../components/buttons/AddItemButton'; | ||||||
| import { ModelType } from '../../../enums/ModelType'; | import { Thumbnail } from '../../components/images/Thumbnail'; | ||||||
| import { UserRoles } from '../../../enums/Roles'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { purchaseOrderFields } from '../../../forms/PurchaseOrderForms'; | import { ModelType } from '../../enums/ModelType'; | ||||||
| import { getDetailUrl } from '../../../functions/urls'; | import { UserRoles } from '../../enums/Roles'; | ||||||
| import { useCreateApiFormModal } from '../../../hooks/UseForm'; | import { purchaseOrderFields } from '../../forms/PurchaseOrderForms'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { getDetailUrl } from '../../functions/urls'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { useCreateApiFormModal } from '../../hooks/UseForm'; | ||||||
| import { useUserState } from '../../../states/UserState'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { AddItemButton } from '../../buttons/AddItemButton'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { Thumbnail } from '../../images/Thumbnail'; | import { useUserState } from '../../states/UserState'; | ||||||
| import { | import { | ||||||
|   CreationDateColumn, |   CreationDateColumn, | ||||||
|   DescriptionColumn, |   DescriptionColumn, | ||||||
|   LineItemsProgressColumn, |   LineItemsProgressColumn, | ||||||
|   ProjectCodeColumn, |   ProjectCodeColumn, | ||||||
|  |   ReferenceColumn, | ||||||
|   ResponsibleColumn, |   ResponsibleColumn, | ||||||
|   StatusColumn, |   StatusColumn, | ||||||
|   TargetDateColumn, |   TargetDateColumn, | ||||||
| @@ -65,13 +66,7 @@ export function PurchaseOrderTable({ | |||||||
| 
 | 
 | ||||||
|   const tableColumns = useMemo(() => { |   const tableColumns = useMemo(() => { | ||||||
|     return [ |     return [ | ||||||
|       { |       ReferenceColumn(), | ||||||
|         accessor: 'reference', |  | ||||||
|         title: t`Reference`, |  | ||||||
|         sortable: true, |  | ||||||
|         switchable: false |  | ||||||
|         // TODO: Display extra information if order is overdue
 |  | ||||||
|       }, |  | ||||||
|       DescriptionColumn({}), |       DescriptionColumn({}), | ||||||
|       { |       { | ||||||
|         accessor: 'supplier__name', |         accessor: 'supplier__name', | ||||||
| @@ -90,8 +85,7 @@ export function PurchaseOrderTable({ | |||||||
|         } |         } | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'supplier_reference', |         accessor: 'supplier_reference' | ||||||
|         title: t`Supplier Reference` |  | ||||||
|       }, |       }, | ||||||
|       LineItemsProgressColumn(), |       LineItemsProgressColumn(), | ||||||
|       StatusColumn(ModelType.purchaseorder), |       StatusColumn(ModelType.purchaseorder), | ||||||
| @@ -3,20 +3,25 @@ import { Text } from '@mantine/core'; | |||||||
| import { ReactNode, useCallback, useMemo } from 'react'; | import { ReactNode, useCallback, useMemo } from 'react'; | ||||||
| import { useNavigate } from 'react-router-dom'; | import { useNavigate } from 'react-router-dom'; | ||||||
| 
 | 
 | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { AddItemButton } from '../../components/buttons/AddItemButton'; | ||||||
| import { ModelType } from '../../../enums/ModelType'; | import { Thumbnail } from '../../components/images/Thumbnail'; | ||||||
| import { UserRoles } from '../../../enums/Roles'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { useSupplierPartFields } from '../../../forms/CompanyForms'; | import { ModelType } from '../../enums/ModelType'; | ||||||
| import { openDeleteApiForm, openEditApiForm } from '../../../functions/forms'; | import { UserRoles } from '../../enums/Roles'; | ||||||
| import { getDetailUrl } from '../../../functions/urls'; | import { useSupplierPartFields } from '../../forms/CompanyForms'; | ||||||
| import { useCreateApiFormModal } from '../../../hooks/UseForm'; | import { openDeleteApiForm, openEditApiForm } from '../../functions/forms'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { getDetailUrl } from '../../functions/urls'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { useCreateApiFormModal } from '../../hooks/UseForm'; | ||||||
| import { useUserState } from '../../../states/UserState'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { AddItemButton } from '../../buttons/AddItemButton'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { Thumbnail } from '../../images/Thumbnail'; | import { useUserState } from '../../states/UserState'; | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { DescriptionColumn, LinkColumn, PartColumn } from '../ColumnRenderers'; | import { | ||||||
|  |   DescriptionColumn, | ||||||
|  |   LinkColumn, | ||||||
|  |   NoteColumn, | ||||||
|  |   PartColumn | ||||||
|  | } from '../ColumnRenderers'; | ||||||
| import { InvenTreeTable } from '../InvenTreeTable'; | import { InvenTreeTable } from '../InvenTreeTable'; | ||||||
| import { RowDeleteAction, RowEditAction } from '../RowActions'; | import { RowDeleteAction, RowEditAction } from '../RowActions'; | ||||||
| import { TableHoverCard } from '../TableHoverCard'; | import { TableHoverCard } from '../TableHoverCard'; | ||||||
| @@ -36,14 +41,12 @@ export function SupplierPartTable({ params }: { params: any }): ReactNode { | |||||||
|     return [ |     return [ | ||||||
|       { |       { | ||||||
|         accessor: 'part', |         accessor: 'part', | ||||||
|         title: t`Part`, |  | ||||||
|         switchable: 'part' in params, |         switchable: 'part' in params, | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         render: (record: any) => PartColumn(record?.part_detail) |         render: (record: any) => PartColumn(record?.part_detail) | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'supplier', |         accessor: 'supplier', | ||||||
|         title: t`Supplier`, |  | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         render: (record: any) => { |         render: (record: any) => { | ||||||
|           let supplier = record?.supplier_detail ?? {}; |           let supplier = record?.supplier_detail ?? {}; | ||||||
| @@ -68,7 +71,6 @@ export function SupplierPartTable({ params }: { params: any }): ReactNode { | |||||||
|         accessor: 'manufacturer', |         accessor: 'manufacturer', | ||||||
| 
 | 
 | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         title: t`Manufacturer`, |  | ||||||
|         render: (record: any) => { |         render: (record: any) => { | ||||||
|           let manufacturer = record?.manufacturer_detail ?? {}; |           let manufacturer = record?.manufacturer_detail ?? {}; | ||||||
| 
 | 
 | ||||||
| @@ -91,17 +93,14 @@ export function SupplierPartTable({ params }: { params: any }): ReactNode { | |||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'in_stock', |         accessor: 'in_stock', | ||||||
|         title: t`In Stock`, |  | ||||||
|         sortable: true |         sortable: true | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'packaging', |         accessor: 'packaging', | ||||||
|         title: t`Packaging`, |  | ||||||
|         sortable: true |         sortable: true | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'pack_quantity', |         accessor: 'pack_quantity', | ||||||
|         title: t`Pack Quantity`, |  | ||||||
|         sortable: true, |         sortable: true, | ||||||
| 
 | 
 | ||||||
|         render: (record: any) => { |         render: (record: any) => { | ||||||
| @@ -127,14 +126,9 @@ export function SupplierPartTable({ params }: { params: any }): ReactNode { | |||||||
|         } |         } | ||||||
|       }, |       }, | ||||||
|       LinkColumn(), |       LinkColumn(), | ||||||
|       { |       NoteColumn(), | ||||||
|         accessor: 'note', |  | ||||||
|         title: t`Notes`, |  | ||||||
|         sortable: false |  | ||||||
|       }, |  | ||||||
|       { |       { | ||||||
|         accessor: 'available', |         accessor: 'available', | ||||||
|         title: t`Availability`, |  | ||||||
|         sortable: true, |         sortable: true, | ||||||
| 
 | 
 | ||||||
|         render: (record: any) => { |         render: (record: any) => { | ||||||
| @@ -2,24 +2,26 @@ import { t } from '@lingui/macro'; | |||||||
| import { useCallback, useMemo } from 'react'; | import { useCallback, useMemo } from 'react'; | ||||||
| import { useNavigate } from 'react-router-dom'; | import { useNavigate } from 'react-router-dom'; | ||||||
| 
 | 
 | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { AddItemButton } from '../../components/buttons/AddItemButton'; | ||||||
| import { ModelType } from '../../../enums/ModelType'; | import { Thumbnail } from '../../components/images/Thumbnail'; | ||||||
| import { UserRoles } from '../../../enums/Roles'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { notYetImplemented } from '../../../functions/notifications'; | import { ModelType } from '../../enums/ModelType'; | ||||||
| import { getDetailUrl } from '../../../functions/urls'; | import { UserRoles } from '../../enums/Roles'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { notYetImplemented } from '../../functions/notifications'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { getDetailUrl } from '../../functions/urls'; | ||||||
| import { useUserState } from '../../../states/UserState'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { AddItemButton } from '../../buttons/AddItemButton'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { Thumbnail } from '../../images/Thumbnail'; | import { useUserState } from '../../states/UserState'; | ||||||
| import { | import { | ||||||
|   CreationDateColumn, |   CreationDateColumn, | ||||||
|   DescriptionColumn, |   DescriptionColumn, | ||||||
|   LineItemsProgressColumn, |   LineItemsProgressColumn, | ||||||
|   ProjectCodeColumn, |   ProjectCodeColumn, | ||||||
|  |   ReferenceColumn, | ||||||
|   ResponsibleColumn, |   ResponsibleColumn, | ||||||
|   StatusColumn, |   StatusColumn, | ||||||
|   TargetDateColumn |   TargetDateColumn, | ||||||
|  |   TotalPriceColumn | ||||||
| } from '../ColumnRenderers'; | } from '../ColumnRenderers'; | ||||||
| import { | import { | ||||||
|   AssignedToMeFilter, |   AssignedToMeFilter, | ||||||
| @@ -56,12 +58,7 @@ export function ReturnOrderTable({ params }: { params?: any }) { | |||||||
| 
 | 
 | ||||||
|   const tableColumns = useMemo(() => { |   const tableColumns = useMemo(() => { | ||||||
|     return [ |     return [ | ||||||
|       { |       ReferenceColumn(), | ||||||
|         accessor: 'reference', |  | ||||||
|         title: t`Return Order`, |  | ||||||
|         sortable: true |  | ||||||
|         // TODO: Display extra information if order is overdue
 |  | ||||||
|       }, |  | ||||||
|       { |       { | ||||||
|         accessor: 'customer__name', |         accessor: 'customer__name', | ||||||
|         title: t`Customer`, |         title: t`Customer`, | ||||||
| @@ -79,8 +76,7 @@ export function ReturnOrderTable({ params }: { params?: any }) { | |||||||
|         } |         } | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'customer_reference', |         accessor: 'customer_reference' | ||||||
|         title: t`Customer Reference` |  | ||||||
|       }, |       }, | ||||||
|       DescriptionColumn({}), |       DescriptionColumn({}), | ||||||
|       LineItemsProgressColumn(), |       LineItemsProgressColumn(), | ||||||
| @@ -89,10 +85,7 @@ export function ReturnOrderTable({ params }: { params?: any }) { | |||||||
|       CreationDateColumn(), |       CreationDateColumn(), | ||||||
|       TargetDateColumn(), |       TargetDateColumn(), | ||||||
|       ResponsibleColumn(), |       ResponsibleColumn(), | ||||||
|       { |       TotalPriceColumn() | ||||||
|         accessor: 'total_cost', |  | ||||||
|         title: t`Total Cost` |  | ||||||
|       } |  | ||||||
|     ]; |     ]; | ||||||
|   }, []); |   }, []); | ||||||
| 
 | 
 | ||||||
| @@ -2,22 +2,23 @@ import { t } from '@lingui/macro'; | |||||||
| import { useMemo } from 'react'; | import { useMemo } from 'react'; | ||||||
| import { useNavigate } from 'react-router-dom'; | import { useNavigate } from 'react-router-dom'; | ||||||
| 
 | 
 | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { AddItemButton } from '../../components/buttons/AddItemButton'; | ||||||
| import { ModelType } from '../../../enums/ModelType'; | import { Thumbnail } from '../../components/images/Thumbnail'; | ||||||
| import { UserRoles } from '../../../enums/Roles'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { salesOrderFields } from '../../../forms/SalesOrderForms'; | import { ModelType } from '../../enums/ModelType'; | ||||||
| import { getDetailUrl } from '../../../functions/urls'; | import { UserRoles } from '../../enums/Roles'; | ||||||
| import { useCreateApiFormModal } from '../../../hooks/UseForm'; | import { salesOrderFields } from '../../forms/SalesOrderForms'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { getDetailUrl } from '../../functions/urls'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { useCreateApiFormModal } from '../../hooks/UseForm'; | ||||||
| import { useUserState } from '../../../states/UserState'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { AddItemButton } from '../../buttons/AddItemButton'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { Thumbnail } from '../../images/Thumbnail'; | import { useUserState } from '../../states/UserState'; | ||||||
| import { | import { | ||||||
|   CreationDateColumn, |   CreationDateColumn, | ||||||
|   DescriptionColumn, |   DescriptionColumn, | ||||||
|   LineItemsProgressColumn, |   LineItemsProgressColumn, | ||||||
|   ProjectCodeColumn, |   ProjectCodeColumn, | ||||||
|  |   ReferenceColumn, | ||||||
|   ShipmentDateColumn, |   ShipmentDateColumn, | ||||||
|   StatusColumn, |   StatusColumn, | ||||||
|   TargetDateColumn, |   TargetDateColumn, | ||||||
| @@ -88,13 +89,7 @@ export function SalesOrderTable({ | |||||||
| 
 | 
 | ||||||
|   const tableColumns = useMemo(() => { |   const tableColumns = useMemo(() => { | ||||||
|     return [ |     return [ | ||||||
|       { |       ReferenceColumn(), | ||||||
|         accessor: 'reference', |  | ||||||
|         title: t`Sales Order`, |  | ||||||
|         sortable: true, |  | ||||||
|         switchable: false |  | ||||||
|         // TODO: Display extra information if order is overdue
 |  | ||||||
|       }, |  | ||||||
|       { |       { | ||||||
|         accessor: 'customer__name', |         accessor: 'customer__name', | ||||||
|         title: t`Customer`, |         title: t`Customer`, | ||||||
| @@ -3,11 +3,11 @@ import { showNotification } from '@mantine/notifications'; | |||||||
| import { IconReload } from '@tabler/icons-react'; | import { IconReload } from '@tabler/icons-react'; | ||||||
| import { useCallback, useMemo } from 'react'; | import { useCallback, useMemo } from 'react'; | ||||||
| 
 | 
 | ||||||
| import { api } from '../../../App'; | import { api } from '../../App'; | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { ActionButton } from '../../components/buttons/ActionButton'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { ActionButton } from '../../buttons/ActionButton'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { InvenTreeTable } from '../InvenTreeTable'; | import { InvenTreeTable } from '../InvenTreeTable'; | ||||||
| 
 | 
 | ||||||
| /* | /* | ||||||
| @@ -1,18 +1,18 @@ | |||||||
| import { t } from '@lingui/macro'; | import { t } from '@lingui/macro'; | ||||||
| import { useCallback, useMemo, useState } from 'react'; | import { useCallback, useMemo, useState } from 'react'; | ||||||
| 
 | 
 | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { AddItemButton } from '../../components/buttons/AddItemButton'; | ||||||
| import { UserRoles } from '../../../enums/Roles'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { customUnitsFields } from '../../../forms/CommonForms'; | import { UserRoles } from '../../enums/Roles'; | ||||||
|  | import { customUnitsFields } from '../../forms/CommonForms'; | ||||||
| import { | import { | ||||||
|   useCreateApiFormModal, |   useCreateApiFormModal, | ||||||
|   useDeleteApiFormModal, |   useDeleteApiFormModal, | ||||||
|   useEditApiFormModal |   useEditApiFormModal | ||||||
| } from '../../../hooks/UseForm'; | } from '../../hooks/UseForm'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { useUserState } from '../../../states/UserState'; | import { useUserState } from '../../states/UserState'; | ||||||
| import { AddItemButton } from '../../buttons/AddItemButton'; |  | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { InvenTreeTable } from '../InvenTreeTable'; | import { InvenTreeTable } from '../InvenTreeTable'; | ||||||
| import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions'; | import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions'; | ||||||
| @@ -29,19 +29,16 @@ export default function CustomUnitsTable() { | |||||||
|     return [ |     return [ | ||||||
|       { |       { | ||||||
|         accessor: 'name', |         accessor: 'name', | ||||||
|         title: t`Name`, |  | ||||||
|         switchable: false, |         switchable: false, | ||||||
|         sortable: true |         sortable: true | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'definition', |         accessor: 'definition', | ||||||
|         title: t`Definition`, |  | ||||||
|         switchable: false, |         switchable: false, | ||||||
|         sortable: false |         sortable: false | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'symbol', |         accessor: 'symbol', | ||||||
|         title: t`Symbol`, |  | ||||||
|         switchable: false, |         switchable: false, | ||||||
|         sortable: true |         sortable: true | ||||||
|       } |       } | ||||||
| @@ -3,11 +3,11 @@ import { Drawer, Text } from '@mantine/core'; | |||||||
| import { useDisclosure } from '@mantine/hooks'; | import { useDisclosure } from '@mantine/hooks'; | ||||||
| import { useCallback, useMemo, useState } from 'react'; | import { useCallback, useMemo, useState } from 'react'; | ||||||
| 
 | 
 | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { StylishText } from '../../components/items/StylishText'; | ||||||
| import { openDeleteApiForm } from '../../../functions/forms'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { openDeleteApiForm } from '../../functions/forms'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { StylishText } from '../../items/StylishText'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { InvenTreeTable } from '../InvenTreeTable'; | import { InvenTreeTable } from '../InvenTreeTable'; | ||||||
| import { RowAction, RowDeleteAction } from '../RowActions'; | import { RowAction, RowDeleteAction } from '../RowActions'; | ||||||
| @@ -3,10 +3,10 @@ import { Drawer, Text } from '@mantine/core'; | |||||||
| import { useDisclosure } from '@mantine/hooks'; | import { useDisclosure } from '@mantine/hooks'; | ||||||
| import { useMemo, useState } from 'react'; | import { useMemo, useState } from 'react'; | ||||||
| 
 | 
 | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { StylishText } from '../../components/items/StylishText'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { StylishText } from '../../items/StylishText'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { InvenTreeTable } from '../InvenTreeTable'; | import { InvenTreeTable } from '../InvenTreeTable'; | ||||||
| 
 | 
 | ||||||
| @@ -3,18 +3,18 @@ import { Group, LoadingOverlay, Stack, Text, Title } from '@mantine/core'; | |||||||
| import { useCallback, useMemo, useState } from 'react'; | import { useCallback, useMemo, useState } from 'react'; | ||||||
| import { useNavigate } from 'react-router-dom'; | 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 { | import { | ||||||
|   useCreateApiFormModal, |   useCreateApiFormModal, | ||||||
|   useDeleteApiFormModal |   useDeleteApiFormModal | ||||||
| } from '../../../hooks/UseForm'; | } from '../../hooks/UseForm'; | ||||||
| import { useInstance } from '../../../hooks/UseInstance'; | import { useInstance } from '../../hooks/UseInstance'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | 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'; |  | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { InvenTreeTable } from '../InvenTreeTable'; | import { InvenTreeTable } from '../InvenTreeTable'; | ||||||
| import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions'; | import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions'; | ||||||
| @@ -1,9 +1,9 @@ | |||||||
| import { t } from '@lingui/macro'; | import { t } from '@lingui/macro'; | ||||||
| import { useMemo } from 'react'; | import { useMemo } from 'react'; | ||||||
| 
 | 
 | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { InvenTreeTable } from '../InvenTreeTable'; | import { InvenTreeTable } from '../InvenTreeTable'; | ||||||
| 
 | 
 | ||||||
| @@ -1,18 +1,18 @@ | |||||||
| import { t } from '@lingui/macro'; | import { t } from '@lingui/macro'; | ||||||
| import { useCallback, useMemo, useState } from 'react'; | import { useCallback, useMemo, useState } from 'react'; | ||||||
| 
 | 
 | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { AddItemButton } from '../../components/buttons/AddItemButton'; | ||||||
| import { UserRoles } from '../../../enums/Roles'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { projectCodeFields } from '../../../forms/CommonForms'; | import { UserRoles } from '../../enums/Roles'; | ||||||
|  | import { projectCodeFields } from '../../forms/CommonForms'; | ||||||
| import { | import { | ||||||
|   useCreateApiFormModal, |   useCreateApiFormModal, | ||||||
|   useDeleteApiFormModal, |   useDeleteApiFormModal, | ||||||
|   useEditApiFormModal |   useEditApiFormModal | ||||||
| } from '../../../hooks/UseForm'; | } from '../../hooks/UseForm'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { useUserState } from '../../../states/UserState'; | import { useUserState } from '../../states/UserState'; | ||||||
| import { AddItemButton } from '../../buttons/AddItemButton'; |  | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { DescriptionColumn, ResponsibleColumn } from '../ColumnRenderers'; | import { DescriptionColumn, ResponsibleColumn } from '../ColumnRenderers'; | ||||||
| import { InvenTreeTable } from '../InvenTreeTable'; | import { InvenTreeTable } from '../InvenTreeTable'; | ||||||
| @@ -30,8 +30,7 @@ export default function ProjectCodeTable() { | |||||||
|     return [ |     return [ | ||||||
|       { |       { | ||||||
|         accessor: 'code', |         accessor: 'code', | ||||||
|         sortable: true, |         sortable: true | ||||||
|         title: t`Project Code` |  | ||||||
|       }, |       }, | ||||||
|       DescriptionColumn({}), |       DescriptionColumn({}), | ||||||
|       ResponsibleColumn() |       ResponsibleColumn() | ||||||
| @@ -3,9 +3,9 @@ import { Group, Text } from '@mantine/core'; | |||||||
| import { IconCircleCheck, IconCircleX } from '@tabler/icons-react'; | import { IconCircleCheck, IconCircleX } from '@tabler/icons-react'; | ||||||
| import { useMemo } from 'react'; | import { useMemo } from 'react'; | ||||||
| 
 | 
 | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { InvenTreeTable } from '../InvenTreeTable'; | import { InvenTreeTable } from '../InvenTreeTable'; | ||||||
| 
 | 
 | ||||||
| @@ -5,15 +5,15 @@ import { useCallback, useMemo } from 'react'; | |||||||
| import { useNavigate } from 'react-router-dom'; | import { useNavigate } from 'react-router-dom'; | ||||||
| import { Link } from 'react-router-dom'; | import { Link } from 'react-router-dom'; | ||||||
| 
 | 
 | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { AddItemButton } from '../../components/buttons/AddItemButton'; | ||||||
| import { openCreateApiForm, openDeleteApiForm } from '../../../functions/forms'; | import { EditApiForm } from '../../components/forms/ApiForm'; | ||||||
| import { useInstance } from '../../../hooks/UseInstance'; | import { DetailDrawer } from '../../components/nav/DetailDrawer'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { openCreateApiForm, openDeleteApiForm } from '../../functions/forms'; | ||||||
| import { useUserState } from '../../../states/UserState'; | import { useInstance } from '../../hooks/UseInstance'; | ||||||
| import { AddItemButton } from '../../buttons/AddItemButton'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { EditApiForm } from '../../forms/ApiForm'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { DetailDrawer } from '../../nav/DetailDrawer'; | import { useUserState } from '../../states/UserState'; | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { BooleanColumn } from '../ColumnRenderers'; | import { BooleanColumn } from '../ColumnRenderers'; | ||||||
| import { InvenTreeTable } from '../InvenTreeTable'; | import { InvenTreeTable } from '../InvenTreeTable'; | ||||||
| @@ -153,45 +153,37 @@ export function UserTable() { | |||||||
|     return [ |     return [ | ||||||
|       { |       { | ||||||
|         accessor: 'email', |         accessor: 'email', | ||||||
|         sortable: true, |         sortable: true | ||||||
|         title: t`Email` |  | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'username', |         accessor: 'username', | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         switchable: false, |         switchable: false | ||||||
|         title: t`Username` |  | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'first_name', |         accessor: 'first_name', | ||||||
|         sortable: true, |         sortable: true | ||||||
|         title: t`First Name` |  | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'last_name', |         accessor: 'last_name', | ||||||
|         sortable: true, |         sortable: true | ||||||
|         title: t`Last Name` |  | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'groups', |         accessor: 'groups', | ||||||
|         sortable: true, |         sortable: true, | ||||||
|         switchable: true, |         switchable: true, | ||||||
|         title: t`Groups`, |  | ||||||
|         render: (record: any) => { |         render: (record: any) => { | ||||||
|           return record.groups.length; |           return record.groups.length; | ||||||
|         } |         } | ||||||
|       }, |       }, | ||||||
|       BooleanColumn({ |       BooleanColumn({ | ||||||
|         accessor: 'is_staff', |         accessor: 'is_staff' | ||||||
|         title: t`Staff` |  | ||||||
|       }), |       }), | ||||||
|       BooleanColumn({ |       BooleanColumn({ | ||||||
|         accessor: 'is_superuser', |         accessor: 'is_superuser' | ||||||
|         title: t`Superuser` |  | ||||||
|       }), |       }), | ||||||
|       BooleanColumn({ |       BooleanColumn({ | ||||||
|         accessor: 'is_active', |         accessor: 'is_active' | ||||||
|         title: t`Active` |  | ||||||
|       }) |       }) | ||||||
|     ]; |     ]; | ||||||
|   }, []); |   }, []); | ||||||
| @@ -3,17 +3,21 @@ import { Group, Text } from '@mantine/core'; | |||||||
| import { ReactNode, useMemo } from 'react'; | import { ReactNode, useMemo } from 'react'; | ||||||
| import { useNavigate } from 'react-router-dom'; | import { useNavigate } from 'react-router-dom'; | ||||||
| 
 | 
 | ||||||
| import { formatCurrency, renderDate } from '../../../defaults/formatters'; | import { formatCurrency, renderDate } from '../../defaults/formatters'; | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { ModelType } from '../../../enums/ModelType'; | import { ModelType } from '../../enums/ModelType'; | ||||||
| import { getDetailUrl } from '../../../functions/urls'; | import { getDetailUrl } from '../../functions/urls'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { PartColumn, StatusColumn } from '../ColumnRenderers'; | import { | ||||||
|  |   DescriptionColumn, | ||||||
|  |   PartColumn, | ||||||
|  |   StatusColumn | ||||||
|  | } from '../ColumnRenderers'; | ||||||
| import { StatusFilterOptions, TableFilter } from '../Filter'; | import { StatusFilterOptions, TableFilter } from '../Filter'; | ||||||
|  | import { InvenTreeTable } from '../InvenTreeTable'; | ||||||
| import { TableHoverCard } from '../TableHoverCard'; | import { TableHoverCard } from '../TableHoverCard'; | ||||||
| import { InvenTreeTable } from './../InvenTreeTable'; |  | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Construct a list of columns for the stock item table |  * Construct a list of columns for the stock item table | ||||||
| @@ -23,14 +27,11 @@ function stockItemTableColumns(): TableColumn[] { | |||||||
|     { |     { | ||||||
|       accessor: 'part', |       accessor: 'part', | ||||||
|       sortable: true, |       sortable: true, | ||||||
|       title: t`Part`, |  | ||||||
|       render: (record: any) => PartColumn(record?.part_detail) |       render: (record: any) => PartColumn(record?.part_detail) | ||||||
|     }, |     }, | ||||||
|     { |     DescriptionColumn({ | ||||||
|       accessor: 'part_detail.description', |       accessor: 'part_detail.description' | ||||||
|       sortable: false, |     }), | ||||||
|       title: t`Description` |  | ||||||
|     }, |  | ||||||
|     { |     { | ||||||
|       accessor: 'quantity', |       accessor: 'quantity', | ||||||
|       sortable: true, |       sortable: true, | ||||||
| @@ -176,15 +177,11 @@ function stockItemTableColumns(): TableColumn[] { | |||||||
|     StatusColumn(ModelType.stockitem), |     StatusColumn(ModelType.stockitem), | ||||||
|     { |     { | ||||||
|       accessor: 'batch', |       accessor: 'batch', | ||||||
|       sortable: true, |       sortable: true | ||||||
| 
 |  | ||||||
|       title: t`Batch` |  | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       accessor: 'location', |       accessor: 'location', | ||||||
|       sortable: true, |       sortable: true, | ||||||
| 
 |  | ||||||
|       title: t`Location`, |  | ||||||
|       render: function (record: any) { |       render: function (record: any) { | ||||||
|         // TODO: Custom renderer for location
 |         // TODO: Custom renderer for location
 | ||||||
|         // TODO: Note, if not "In stock" we don't want to display the actual location here
 |         // 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', |       accessor: 'expiry_date', | ||||||
|       sortable: true, |       sortable: true, | ||||||
|       title: t`Expiry Date`, |  | ||||||
|       switchable: true, |       switchable: true, | ||||||
|       render: (record: any) => renderDate(record.expiry_date) |       render: (record: any) => renderDate(record.expiry_date) | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       accessor: 'updated', |       accessor: 'updated', | ||||||
|       sortable: true, |       sortable: true, | ||||||
|       title: t`Last Updated`, |  | ||||||
|       switchable: true, |       switchable: true, | ||||||
|       render: (record: any) => renderDate(record.updated) |       render: (record: any) => renderDate(record.updated) | ||||||
|     }, |     }, | ||||||
| @@ -211,7 +206,6 @@ function stockItemTableColumns(): TableColumn[] { | |||||||
|     { |     { | ||||||
|       accessor: 'purchase_price', |       accessor: 'purchase_price', | ||||||
|       sortable: true, |       sortable: true, | ||||||
|       title: t`Purchase Price`, |  | ||||||
|       switchable: true, |       switchable: true, | ||||||
|       render: (record: any) => |       render: (record: any) => | ||||||
|         formatCurrency(record.purchase_price, { |         formatCurrency(record.purchase_price, { | ||||||
| @@ -2,22 +2,21 @@ import { t } from '@lingui/macro'; | |||||||
| import { useCallback, useMemo, useState } from 'react'; | import { useCallback, useMemo, useState } from 'react'; | ||||||
| import { useNavigate } from 'react-router-dom'; | import { useNavigate } from 'react-router-dom'; | ||||||
| 
 | 
 | ||||||
| import { ApiEndpoints } from '../../../enums/ApiEndpoints'; | import { AddItemButton } from '../../components/buttons/AddItemButton'; | ||||||
| import { ModelType } from '../../../enums/ModelType'; | import { ApiEndpoints } from '../../enums/ApiEndpoints'; | ||||||
| import { UserRoles } from '../../../enums/Roles'; | import { ModelType } from '../../enums/ModelType'; | ||||||
| import { stockLocationFields } from '../../../forms/StockForms'; | import { UserRoles } from '../../enums/Roles'; | ||||||
| import { getDetailUrl } from '../../../functions/urls'; | import { stockLocationFields } from '../../forms/StockForms'; | ||||||
|  | import { getDetailUrl } from '../../functions/urls'; | ||||||
| import { | import { | ||||||
|   useCreateApiFormModal, |   useCreateApiFormModal, | ||||||
|   useEditApiFormModal |   useEditApiFormModal | ||||||
| } from '../../../hooks/UseForm'; | } from '../../hooks/UseForm'; | ||||||
| import { useTable } from '../../../hooks/UseTable'; | import { useTable } from '../../hooks/UseTable'; | ||||||
| import { apiUrl } from '../../../states/ApiState'; | import { apiUrl } from '../../states/ApiState'; | ||||||
| import { useUserState } from '../../../states/UserState'; | import { useUserState } from '../../states/UserState'; | ||||||
| import { AddItemButton } from '../../buttons/AddItemButton'; |  | ||||||
| import { YesNoButton } from '../../items/YesNoButton'; |  | ||||||
| import { TableColumn } from '../Column'; | import { TableColumn } from '../Column'; | ||||||
| import { DescriptionColumn } from '../ColumnRenderers'; | import { BooleanColumn, DescriptionColumn } from '../ColumnRenderers'; | ||||||
| import { TableFilter } from '../Filter'; | import { TableFilter } from '../Filter'; | ||||||
| import { InvenTreeTable } from '../InvenTreeTable'; | import { InvenTreeTable } from '../InvenTreeTable'; | ||||||
| import { RowEditAction } from '../RowActions'; | import { RowEditAction } from '../RowActions'; | ||||||
| @@ -40,12 +39,10 @@ export function StockLocationTable({ parentId }: { parentId?: any }) { | |||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         name: 'structural', |         name: 'structural', | ||||||
|         label: t`Structural`, |  | ||||||
|         description: t`Show structural locations` |         description: t`Show structural locations` | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         name: 'external', |         name: 'external', | ||||||
|         label: t`External`, |  | ||||||
|         description: t`Show external locations` |         description: t`Show external locations` | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
| @@ -60,39 +57,25 @@ export function StockLocationTable({ parentId }: { parentId?: any }) { | |||||||
|     return [ |     return [ | ||||||
|       { |       { | ||||||
|         accessor: 'name', |         accessor: 'name', | ||||||
|         title: t`Name`, |  | ||||||
|         switchable: false |         switchable: false | ||||||
|       }, |       }, | ||||||
|       DescriptionColumn({}), |       DescriptionColumn({}), | ||||||
|       { |       { | ||||||
|         accessor: 'pathstring', |         accessor: 'pathstring', | ||||||
|         title: t`Path`, |  | ||||||
|         sortable: true |         sortable: true | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         accessor: 'items', |         accessor: 'items', | ||||||
|         title: t`Stock Items`, |  | ||||||
| 
 |  | ||||||
|         sortable: true |         sortable: true | ||||||
|       }, |       }, | ||||||
|       { |       BooleanColumn({ | ||||||
|         accessor: 'structural', |         accessor: 'structural' | ||||||
|         title: t`Structural`, |       }), | ||||||
| 
 |       BooleanColumn({ | ||||||
|         sortable: true, |         accessor: 'external' | ||||||
|         render: (record: any) => <YesNoButton value={record.structural} /> |       }), | ||||||
|       }, |  | ||||||
|       { |  | ||||||
|         accessor: 'external', |  | ||||||
|         title: t`External`, |  | ||||||
| 
 |  | ||||||
|         sortable: true, |  | ||||||
|         render: (record: any) => <YesNoButton value={record.external} /> |  | ||||||
|       }, |  | ||||||
|       { |       { | ||||||
|         accessor: 'location_type', |         accessor: 'location_type', | ||||||
|         title: t`Location Type`, |  | ||||||
| 
 |  | ||||||
|         sortable: false, |         sortable: false, | ||||||
|         render: (record: any) => record.location_type_detail?.name |         render: (record: any) => record.location_type_detail?.name | ||||||
|       } |       } | ||||||
| @@ -35,7 +35,6 @@ export default function DesktopAppView() { | |||||||
|   const [token] = sessionState.token ? [sessionState.token] : [null]; |   const [token] = sessionState.token ? [sessionState.token] : [null]; | ||||||
|   useEffect(() => { |   useEffect(() => { | ||||||
|     if (Object.keys(hostList).length === 0) { |     if (Object.keys(hostList).length === 0) { | ||||||
|       console.log('Loading default host list', defaultHostList); |  | ||||||
|       useLocalState.setState({ hostList: defaultHostList }); |       useLocalState.setState({ hostList: defaultHostList }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user