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:
Oliver 2024-02-02 10:11:37 +11:00 committed by GitHub
parent 577185cd98
commit ec2a66e7a5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
77 changed files with 698 additions and 728 deletions

View File

@ -1075,16 +1075,34 @@ class BuildLineSerializer(InvenTreeModelSerializer):
quantity = serializers.FloatField()
bom_item = serializers.PrimaryKeyRelatedField(label=_('Bom Item'), read_only=True)
# Foreign key fields
bom_item_detail = BomItemSerializer(source='bom_item', many=False, read_only=True, pricing=False)
part_detail = PartSerializer(source='bom_item.sub_part', many=False, read_only=True, pricing=False)
allocations = BuildItemSerializer(many=True, read_only=True)
# Annotated (calculated) fields
allocated = serializers.FloatField(read_only=True)
on_order = serializers.FloatField(read_only=True)
in_production = serializers.FloatField(read_only=True)
available_stock = serializers.FloatField(read_only=True)
allocated = serializers.FloatField(
label=_('Allocated Stock'),
read_only=True
)
on_order = serializers.FloatField(
label=_('On Order'),
read_only=True
)
in_production = serializers.FloatField(
label=_('In Production'),
read_only=True
)
available_stock = serializers.FloatField(
label=_('Available Stock'),
read_only=True
)
available_substitute_stock = serializers.FloatField(read_only=True)
available_variant_stock = serializers.FloatField(read_only=True)
total_available_stock = serializers.FloatField(read_only=True)

View File

@ -1408,8 +1408,9 @@ class BomItemSerializer(InvenTree.serializers.InvenTreeModelSerializer):
sub_part_detail = PartBriefSerializer(source='sub_part', many=False, read_only=True)
on_order = serializers.FloatField(read_only=True)
building = serializers.FloatField(read_only=True)
on_order = serializers.FloatField(label=_('On Order'), read_only=True)
building = serializers.FloatField(label=_('In Production'), read_only=True)
# Cached pricing fields
pricing_min = InvenTree.serializers.InvenTreeMoneySerializer(
@ -1420,7 +1421,8 @@ class BomItemSerializer(InvenTree.serializers.InvenTreeModelSerializer):
)
# Annotated fields for available stock
available_stock = serializers.FloatField(read_only=True)
available_stock = serializers.FloatField(label=_('Available Stock'), read_only=True)
available_substitute_stock = serializers.FloatField(read_only=True)
available_variant_stock = serializers.FloatField(read_only=True)

View File

@ -18,8 +18,8 @@ import { api } from '../../App';
import { UserRoles } from '../../enums/Roles';
import { InvenTreeIcon } from '../../functions/icons';
import { useUserState } from '../../states/UserState';
import { PartThumbTable } from '../../tables/part/PartThumbTable';
import { ActionButton } from '../buttons/ActionButton';
import { PartThumbTable } from '../tables/part/PartThumbTable';
import { ApiImage } from './ApiImage';
/**

View File

@ -92,6 +92,9 @@ export function LanguageContext({ children }: { children: JSX.Element }) {
// Reload server state (refresh status codes)
useServerApiState.getState().fetchServerApiState();
// Clear out cached table column names
useLocalState.getState().clearTableColumnNames();
})
.catch((err) => {
console.error('Failed loading translations', err);

View File

@ -263,7 +263,6 @@ export function openModalApiForm(props: OpenApiFormProps) {
});
})
.catch((error) => {
console.log('Error:', error);
if (error.response) {
invalidResponse(error.response.status);
} else {

View File

@ -1,7 +1,7 @@
import { randomId, useLocalStorage } from '@mantine/hooks';
import { useCallback, useState } from 'react';
import { TableFilter } from '../components/tables/Filter';
import { TableFilter } from '../tables/Filter';
/*
* Type definition for representing the state of a table:

View File

@ -30,22 +30,19 @@ const PluginManagementPanel = Loadable(
);
const ErrorReportTable = Loadable(
lazy(() => import('../../../../components/tables/settings/ErrorTable'))
lazy(() => import('../../../../tables/settings/ErrorTable'))
);
const ProjectCodeTable = Loadable(
lazy(() => import('../../../../components/tables/settings/ProjectCodeTable'))
lazy(() => import('../../../../tables/settings/ProjectCodeTable'))
);
const CustomUnitsTable = Loadable(
lazy(() => import('../../../../components/tables/settings/CustomUnitsTable'))
lazy(() => import('../../../../tables/settings/CustomUnitsTable'))
);
const PartParameterTemplateTable = Loadable(
lazy(
() =>
import('../../../../components/tables/part/PartParameterTemplateTable')
)
lazy(() => import('../../../../tables/part/PartParameterTemplateTable'))
);
export default function AdminCenter() {

View File

@ -3,9 +3,9 @@ import { Alert, Stack, Title } from '@mantine/core';
import { IconInfoCircle } from '@tabler/icons-react';
import { GlobalSettingList } from '../../../../components/settings/SettingList';
import { PluginErrorTable } from '../../../../components/tables/plugin/PluginErrorTable';
import { PluginListTable } from '../../../../components/tables/plugin/PluginListTable';
import { useServerApiState } from '../../../../states/ApiState';
import { PluginErrorTable } from '../../../../tables/plugin/PluginErrorTable';
import { PluginListTable } from '../../../../tables/plugin/PluginListTable';
export default function PluginManagementPanel() {
const pluginsEnabled = useServerApiState(

View File

@ -6,17 +6,15 @@ import { StylishText } from '../../../../components/items/StylishText';
import { Loadable } from '../../../../functions/loading';
const PendingTasksTable = Loadable(
lazy(() => import('../../../../components/tables/settings/PendingTasksTable'))
lazy(() => import('../../../../tables/settings/PendingTasksTable'))
);
const ScheduledTasksTable = Loadable(
lazy(
() => import('../../../../components/tables/settings/ScheduledTasksTable')
)
lazy(() => import('../../../../tables/settings/ScheduledTasksTable'))
);
const FailedTasksTable = Loadable(
lazy(() => import('../../../../components/tables/settings/FailedTasksTable'))
lazy(() => import('../../../../tables/settings/FailedTasksTable'))
);
export default function TaskManagementPanel() {

View File

@ -3,8 +3,8 @@ import { Anchor, Divider, Group, Stack, Text, Title } from '@mantine/core';
import { Link } from 'react-router-dom';
import { GlobalSettingList } from '../../../../components/settings/SettingList';
import { GroupTable } from '../../../../components/tables/settings/GroupTable';
import { UserTable } from '../../../../components/tables/settings/UserTable';
import { GroupTable } from '../../../../tables/settings/GroupTable';
import { UserTable } from '../../../../tables/settings/UserTable';
export default function UserManagementPanel() {
return (

View File

@ -23,8 +23,8 @@ import { StylishText } from '../../../components/items/StylishText';
import { PanelGroup, PanelType } from '../../../components/nav/PanelGroup';
import { SettingsHeader } from '../../../components/nav/SettingsHeader';
import { GlobalSettingList } from '../../../components/settings/SettingList';
import { CurrencyTable } from '../../../components/tables/settings/CurrencyTable';
import { useServerApiState } from '../../../states/ApiState';
import { CurrencyTable } from '../../../tables/settings/CurrencyTable';
/**
* System settings page

View File

@ -12,10 +12,10 @@ import { useMemo } from 'react';
import { api } from '../App';
import { PageDetail } from '../components/nav/PageDetail';
import { PanelGroup } from '../components/nav/PanelGroup';
import { NotificationTable } from '../components/tables/notifications/NotificationsTable';
import { ApiEndpoints } from '../enums/ApiEndpoints';
import { useTable } from '../hooks/UseTable';
import { apiUrl } from '../states/ApiState';
import { NotificationTable } from '../tables/notifications/NotificationsTable';
export default function NotificationsPage() {
const unreadTable = useTable('unreadnotifications');

View File

@ -28,10 +28,6 @@ import {
import { PageDetail } from '../../components/nav/PageDetail';
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
import { StatusRenderer } from '../../components/render/StatusRenderer';
import BuildLineTable from '../../components/tables/build/BuildLineTable';
import { BuildOrderTable } from '../../components/tables/build/BuildOrderTable';
import { AttachmentTable } from '../../components/tables/general/AttachmentTable';
import { StockItemTable } from '../../components/tables/stock/StockItemTable';
import { NotesEditor } from '../../components/widgets/MarkdownEditor';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
@ -41,6 +37,10 @@ import { useEditApiFormModal } from '../../hooks/UseForm';
import { useInstance } from '../../hooks/UseInstance';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import BuildLineTable from '../../tables/build/BuildLineTable';
import { BuildOrderTable } from '../../tables/build/BuildOrderTable';
import { AttachmentTable } from '../../tables/general/AttachmentTable';
import { StockItemTable } from '../../tables/stock/StockItemTable';
/**
* Detail page for a single Build Order

View File

@ -2,7 +2,7 @@ import { t } from '@lingui/macro';
import { Stack } from '@mantine/core';
import { PageDetail } from '../../components/nav/PageDetail';
import { BuildOrderTable } from '../../components/tables/build/BuildOrderTable';
import { BuildOrderTable } from '../../tables/build/BuildOrderTable';
/**
* Build Order index page

View File

@ -27,15 +27,6 @@ import { Breadcrumb } from '../../components/nav/BreadcrumbList';
import { PageDetail } from '../../components/nav/PageDetail';
import { PanelGroup } from '../../components/nav/PanelGroup';
import { PanelType } from '../../components/nav/PanelGroup';
import { AddressTable } from '../../components/tables/company/AddressTable';
import { ContactTable } from '../../components/tables/company/ContactTable';
import { AttachmentTable } from '../../components/tables/general/AttachmentTable';
import { ManufacturerPartTable } from '../../components/tables/purchasing/ManufacturerPartTable';
import { PurchaseOrderTable } from '../../components/tables/purchasing/PurchaseOrderTable';
import { SupplierPartTable } from '../../components/tables/purchasing/SupplierPartTable';
import { ReturnOrderTable } from '../../components/tables/sales/ReturnOrderTable';
import { SalesOrderTable } from '../../components/tables/sales/SalesOrderTable';
import { StockItemTable } from '../../components/tables/stock/StockItemTable';
import { NotesEditor } from '../../components/widgets/MarkdownEditor';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { UserRoles } from '../../enums/Roles';
@ -44,6 +35,15 @@ import { useEditApiFormModal } from '../../hooks/UseForm';
import { useInstance } from '../../hooks/UseInstance';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { AddressTable } from '../../tables/company/AddressTable';
import { ContactTable } from '../../tables/company/ContactTable';
import { AttachmentTable } from '../../tables/general/AttachmentTable';
import { ManufacturerPartTable } from '../../tables/purchasing/ManufacturerPartTable';
import { PurchaseOrderTable } from '../../tables/purchasing/PurchaseOrderTable';
import { SupplierPartTable } from '../../tables/purchasing/SupplierPartTable';
import { ReturnOrderTable } from '../../tables/sales/ReturnOrderTable';
import { SalesOrderTable } from '../../tables/sales/SalesOrderTable';
import { StockItemTable } from '../../tables/stock/StockItemTable';
export type CompanyDetailProps = {
title: string;

View File

@ -11,11 +11,11 @@ import { useParams } from 'react-router-dom';
import { PageDetail } from '../../components/nav/PageDetail';
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
import { AttachmentTable } from '../../components/tables/general/AttachmentTable';
import ManufacturerPartParameterTable from '../../components/tables/purchasing/ManufacturerPartParameterTable';
import { SupplierPartTable } from '../../components/tables/purchasing/SupplierPartTable';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { useInstance } from '../../hooks/UseInstance';
import { AttachmentTable } from '../../tables/general/AttachmentTable';
import ManufacturerPartParameterTable from '../../tables/purchasing/ManufacturerPartParameterTable';
import { SupplierPartTable } from '../../tables/purchasing/SupplierPartTable';
export default function ManufacturerPartDetail() {
const { id } = useParams();

View File

@ -11,9 +11,9 @@ import { useParams } from 'react-router-dom';
import { PageDetail } from '../../components/nav/PageDetail';
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
import { PurchaseOrderTable } from '../../components/tables/purchasing/PurchaseOrderTable';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { useInstance } from '../../hooks/UseInstance';
import { PurchaseOrderTable } from '../../tables/purchasing/PurchaseOrderTable';
export default function SupplierPartDetail() {
const { id } = useParams();

View File

@ -12,10 +12,10 @@ import { PlaceholderPanel } from '../../components/items/Placeholder';
import { PageDetail } from '../../components/nav/PageDetail';
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
import { PartCategoryTree } from '../../components/nav/PartCategoryTree';
import { PartCategoryTable } from '../../components/tables/part/PartCategoryTable';
import { PartListTable } from '../../components/tables/part/PartTable';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { useInstance } from '../../hooks/UseInstance';
import { PartCategoryTable } from '../../tables/part/PartCategoryTable';
import { PartListTable } from '../../tables/part/PartTable';
/**
* Detail view for a single PartCategory instance.

View File

@ -41,24 +41,6 @@ import {
import { PageDetail } from '../../components/nav/PageDetail';
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
import { PartCategoryTree } from '../../components/nav/PartCategoryTree';
import { DetailsField } from '../../components/tables/Details';
import {
DetailsImageType,
ItemDetailFields,
ItemDetails
} from '../../components/tables/ItemDetails';
import { BomTable } from '../../components/tables/bom/BomTable';
import { UsedInTable } from '../../components/tables/bom/UsedInTable';
import { BuildOrderTable } from '../../components/tables/build/BuildOrderTable';
import { AttachmentTable } from '../../components/tables/general/AttachmentTable';
import { PartParameterTable } from '../../components/tables/part/PartParameterTable';
import PartTestTemplateTable from '../../components/tables/part/PartTestTemplateTable';
import { PartVariantTable } from '../../components/tables/part/PartVariantTable';
import { RelatedPartTable } from '../../components/tables/part/RelatedPartTable';
import { ManufacturerPartTable } from '../../components/tables/purchasing/ManufacturerPartTable';
import { SupplierPartTable } from '../../components/tables/purchasing/SupplierPartTable';
import { SalesOrderTable } from '../../components/tables/sales/SalesOrderTable';
import { StockItemTable } from '../../components/tables/stock/StockItemTable';
import { NotesEditor } from '../../components/widgets/MarkdownEditor';
import { formatPriceRange } from '../../defaults/formatters';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
@ -68,6 +50,24 @@ import { useEditApiFormModal } from '../../hooks/UseForm';
import { useInstance } from '../../hooks/UseInstance';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { DetailsField } from '../../tables/Details';
import {
DetailsImageType,
ItemDetailFields,
ItemDetails
} from '../../tables/ItemDetails';
import { BomTable } from '../../tables/bom/BomTable';
import { UsedInTable } from '../../tables/bom/UsedInTable';
import { BuildOrderTable } from '../../tables/build/BuildOrderTable';
import { AttachmentTable } from '../../tables/general/AttachmentTable';
import { PartParameterTable } from '../../tables/part/PartParameterTable';
import PartTestTemplateTable from '../../tables/part/PartTestTemplateTable';
import { PartVariantTable } from '../../tables/part/PartVariantTable';
import { RelatedPartTable } from '../../tables/part/RelatedPartTable';
import { ManufacturerPartTable } from '../../tables/purchasing/ManufacturerPartTable';
import { SupplierPartTable } from '../../tables/purchasing/SupplierPartTable';
import { SalesOrderTable } from '../../tables/sales/SalesOrderTable';
import { StockItemTable } from '../../tables/stock/StockItemTable';
/**
* Detail view for a single Part instance
@ -353,7 +353,7 @@ export default function PartDetail() {
});
}
});
return data.quantity;
return data?.quantity;
}
},
{
@ -381,7 +381,7 @@ export default function PartDetail() {
});
}
});
return data.user;
return data?.user;
}
}
]);

View File

@ -22,14 +22,14 @@ import {
} from '../../components/items/ActionDropdown';
import { PageDetail } from '../../components/nav/PageDetail';
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
import { AttachmentTable } from '../../components/tables/general/AttachmentTable';
import { PurchaseOrderLineItemTable } from '../../components/tables/purchasing/PurchaseOrderLineItemTable';
import { StockItemTable } from '../../components/tables/stock/StockItemTable';
import { NotesEditor } from '../../components/widgets/MarkdownEditor';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { useInstance } from '../../hooks/UseInstance';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { AttachmentTable } from '../../tables/general/AttachmentTable';
import { PurchaseOrderLineItemTable } from '../../tables/purchasing/PurchaseOrderLineItemTable';
import { StockItemTable } from '../../tables/stock/StockItemTable';
/**
* Detail page for a single PurchaseOrder

View File

@ -9,8 +9,8 @@ import { useMemo } from 'react';
import { PageDetail } from '../../components/nav/PageDetail';
import { PanelGroup } from '../../components/nav/PanelGroup';
import { CompanyTable } from '../../components/tables/company/CompanyTable';
import { PurchaseOrderTable } from '../../components/tables/purchasing/PurchaseOrderTable';
import { CompanyTable } from '../../tables/company/CompanyTable';
import { PurchaseOrderTable } from '../../tables/purchasing/PurchaseOrderTable';
export default function PurchasingIndex() {
const panels = useMemo(() => {

View File

@ -6,11 +6,11 @@ import { useParams } from 'react-router-dom';
import { PageDetail } from '../../components/nav/PageDetail';
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
import { AttachmentTable } from '../../components/tables/general/AttachmentTable';
import { NotesEditor } from '../../components/widgets/MarkdownEditor';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { useInstance } from '../../hooks/UseInstance';
import { apiUrl } from '../../states/ApiState';
import { AttachmentTable } from '../../tables/general/AttachmentTable';
/**
* Detail page for a single ReturnOrder

View File

@ -9,9 +9,9 @@ import { useMemo } from 'react';
import { PageDetail } from '../../components/nav/PageDetail';
import { PanelGroup } from '../../components/nav/PanelGroup';
import { CompanyTable } from '../../components/tables/company/CompanyTable';
import { ReturnOrderTable } from '../../components/tables/sales/ReturnOrderTable';
import { SalesOrderTable } from '../../components/tables/sales/SalesOrderTable';
import { CompanyTable } from '../../tables/company/CompanyTable';
import { ReturnOrderTable } from '../../tables/sales/ReturnOrderTable';
import { SalesOrderTable } from '../../tables/sales/SalesOrderTable';
export default function PurchasingIndex() {
const panels = useMemo(() => {

View File

@ -14,12 +14,12 @@ import { useParams } from 'react-router-dom';
import { PageDetail } from '../../components/nav/PageDetail';
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
import { BuildOrderTable } from '../../components/tables/build/BuildOrderTable';
import { AttachmentTable } from '../../components/tables/general/AttachmentTable';
import { NotesEditor } from '../../components/widgets/MarkdownEditor';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { useInstance } from '../../hooks/UseInstance';
import { apiUrl } from '../../states/ApiState';
import { BuildOrderTable } from '../../tables/build/BuildOrderTable';
import { AttachmentTable } from '../../tables/general/AttachmentTable';
/**
* Detail page for a single SalesOrder

View File

@ -7,10 +7,10 @@ import { useParams } from 'react-router-dom';
import { PageDetail } from '../../components/nav/PageDetail';
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
import { StockLocationTree } from '../../components/nav/StockLocationTree';
import { StockItemTable } from '../../components/tables/stock/StockItemTable';
import { StockLocationTable } from '../../components/tables/stock/StockLocationTable';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { useInstance } from '../../hooks/UseInstance';
import { StockItemTable } from '../../tables/stock/StockItemTable';
import { StockLocationTable } from '../../tables/stock/StockLocationTable';
export default function Stock() {
const { id: _id } = useParams();

View File

@ -33,14 +33,14 @@ import { PlaceholderPanel } from '../../components/items/Placeholder';
import { PageDetail } from '../../components/nav/PageDetail';
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
import { StockLocationTree } from '../../components/nav/StockLocationTree';
import { AttachmentTable } from '../../components/tables/general/AttachmentTable';
import { StockItemTable } from '../../components/tables/stock/StockItemTable';
import { NotesEditor } from '../../components/widgets/MarkdownEditor';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { useEditStockItem } from '../../forms/StockForms';
import { useInstance } from '../../hooks/UseInstance';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { AttachmentTable } from '../../tables/general/AttachmentTable';
import { StockItemTable } from '../../tables/stock/StockItemTable';
export default function StockDetail() {
const { id } = useParams();

View File

@ -24,6 +24,12 @@ interface LocalStateProps {
loader: LoaderType;
lastUsedPanels: Record<string, string>;
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>()(
@ -55,6 +61,22 @@ export const useLocalState = create<LocalStateProps>()(
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: {} });
}
}),
{

View File

@ -3,8 +3,8 @@
*/
export type TableColumn<T = any> = {
accessor: string; // The key in the record to access
title?: string; // The title of the column - Note: this may be supplied by the API, and is not required, but it can be overridden if required
ordering?: string; // The key in the record to sort by (defaults to accessor)
title: string; // The title of the column
sortable?: boolean; // Whether the column is sortable
switchable?: boolean; // Whether the column is switchable
hidden?: boolean; // Whether the column is hidden

View File

@ -3,13 +3,13 @@
*/
import { t } from '@lingui/macro';
import { formatCurrency, renderDate } from '../../defaults/formatters';
import { ModelType } from '../../enums/ModelType';
import { Thumbnail } from '../images/Thumbnail';
import { ProgressBar } from '../items/ProgressBar';
import { YesNoButton } from '../items/YesNoButton';
import { TableStatusRenderer } from '../render/StatusRenderer';
import { RenderOwner } from '../render/User';
import { Thumbnail } from '../components/images/Thumbnail';
import { ProgressBar } from '../components/items/ProgressBar';
import { YesNoButton } from '../components/items/YesNoButton';
import { TableStatusRenderer } from '../components/render/StatusRenderer';
import { RenderOwner } from '../components/render/User';
import { formatCurrency, renderDate } from '../defaults/formatters';
import { ModelType } from '../enums/ModelType';
import { TableColumn } from './Column';
import { ProjectCodeHoverCard } from './TableHoverCard';
@ -25,7 +25,7 @@ export function BooleanColumn({
switchable
}: {
accessor: string;
title: string;
title?: string;
sortable?: boolean;
switchable?: boolean;
}): TableColumn {
@ -58,16 +58,29 @@ export function DescriptionColumn({
export function LinkColumn(): TableColumn {
return {
accessor: 'link',
title: t`Link`,
sortable: false
// TODO: Custom URL hyperlink renderer?
};
}
export function ReferenceColumn(): TableColumn {
return {
accessor: 'reference',
sortable: true,
switchable: false
};
}
export function NoteColumn(): TableColumn {
return {
accessor: 'note',
sortable: false
};
}
export function LineItemsProgressColumn(): TableColumn {
return {
accessor: 'line_items',
title: t`Line Items`,
sortable: true,
render: (record: any) => (
<ProgressBar
@ -82,7 +95,6 @@ export function LineItemsProgressColumn(): TableColumn {
export function ProjectCodeColumn(): TableColumn {
return {
accessor: 'project_code',
title: t`Project Code`,
sortable: true,
render: (record: any) => (
<ProjectCodeHoverCard projectCode={record.project_code_detail} />
@ -94,7 +106,6 @@ export function StatusColumn(model: ModelType) {
return {
accessor: 'status',
sortable: true,
title: t`Status`,
render: TableStatusRenderer(model)
};
}
@ -102,7 +113,6 @@ export function StatusColumn(model: ModelType) {
export function ResponsibleColumn(): TableColumn {
return {
accessor: 'responsible',
title: t`Responsible`,
sortable: true,
render: (record: any) =>
record.responsible && RenderOwner({ instance: record.responsible_detail })
@ -112,8 +122,8 @@ export function ResponsibleColumn(): TableColumn {
export function TargetDateColumn(): TableColumn {
return {
accessor: 'target_date',
title: t`Target Date`,
sortable: true,
title: t`Target Date`,
// TODO: custom renderer which alerts user if target date is overdue
render: (record: any) => renderDate(record.target_date)
};
@ -122,7 +132,6 @@ export function TargetDateColumn(): TableColumn {
export function CreationDateColumn(): TableColumn {
return {
accessor: 'creation_date',
title: t`Creation Date`,
sortable: true,
render: (record: any) => renderDate(record.creation_date)
};
@ -131,7 +140,6 @@ export function CreationDateColumn(): TableColumn {
export function ShipmentDateColumn(): TableColumn {
return {
accessor: 'shipment_date',
title: t`Shipment Date`,
sortable: true,
render: (record: any) => renderDate(record.shipment_date)
};

View File

@ -29,7 +29,7 @@ export function TableColumnSelect({
<Checkbox
checked={!col.hidden}
label={col.title || col.accessor}
onChange={(event) => onToggleColumn(col.accessor)}
onChange={() => onToggleColumn(col.accessor)}
radius="sm"
/>
</Menu.Item>

View File

@ -13,12 +13,12 @@ import {
import { useSuspenseQuery } from '@tanstack/react-query';
import { Suspense } from 'react';
import { api } from '../../App';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { InvenTreeIcon } from '../../functions/icons';
import { apiUrl } from '../../states/ApiState';
import { useGlobalSettingsState } from '../../states/SettingsState';
import { ProgressBar } from '../items/ProgressBar';
import { api } from '../App';
import { ProgressBar } from '../components/items/ProgressBar';
import { ApiEndpoints } from '../enums/ApiEndpoints';
import { InvenTreeIcon } from '../functions/icons';
import { apiUrl } from '../states/ApiState';
import { useGlobalSettingsState } from '../states/SettingsState';
export type PartIconsType = {
assembly: boolean;

View File

@ -1,7 +1,7 @@
import { t } from '@lingui/macro';
import { ModelType } from '../../enums/ModelType';
import { useServerApiState } from '../../states/ApiState';
import { ModelType } from '../enums/ModelType';
import { useServerApiState } from '../states/ApiState';
/**
* Interface for the table filter choice
@ -20,7 +20,7 @@ export type TableFilterChoice = {
*/
export type TableFilter = {
name: string;
label: string;
label?: string;
description?: string;
type?: string;
choices?: TableFilterChoice[];

View File

@ -14,8 +14,8 @@ import {
} from '@mantine/core';
import { forwardRef, useCallback, useEffect, useMemo, useState } from 'react';
import { TableState } from '../../hooks/UseTable';
import { StylishText } from '../items/StylishText';
import { StylishText } from '../components/items/StylishText';
import { TableState } from '../hooks/UseTable';
import {
TableFilter,
TableFilterChoice,

View File

@ -2,7 +2,9 @@ import { t } from '@lingui/macro';
import {
ActionIcon,
Alert,
Box,
Indicator,
LoadingOverlay,
Space,
Stack,
Tooltip
@ -16,10 +18,13 @@ import { useQuery } from '@tanstack/react-query';
import { DataTable, DataTableSortStatus } from 'mantine-datatable';
import { Fragment, useCallback, useEffect, useMemo, useState } from 'react';
import { api } from '../../App';
import { TableState } from '../../hooks/UseTable';
import { ActionButton } from '../buttons/ActionButton';
import { ButtonMenu } from '../buttons/ButtonMenu';
import { api } from '../App';
import { ActionButton } from '../components/buttons/ActionButton';
import { ButtonMenu } from '../components/buttons/ButtonMenu';
import { ApiFormFieldSet } from '../components/forms/fields/ApiFormField';
import { extractAvailableFields, mapFields } from '../functions/forms';
import { TableState } from '../hooks/UseTable';
import { useLocalState } from '../states/LocalState';
import { TableColumn } from './Column';
import { TableColumnSelect } from './ColumnSelect';
import { DownloadAction } from './DownloadAction';
@ -93,8 +98,7 @@ const defaultInvenTreeTableProps: InvenTreeTableProps = {
barcodeActions: [],
tableFilters: [],
tableActions: [],
idAccessor: 'pk',
onRowClick: (record: any, index: number, event: any) => {}
idAccessor: 'pk'
};
/**
@ -111,6 +115,73 @@ export function InvenTreeTable<T = any>({
columns: TableColumn<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)
const tableProps: InvenTreeTableProps<T> = useMemo(() => {
return {
@ -139,7 +210,8 @@ export function InvenTreeTable<T = any>({
return {
...col,
hidden: hidden
hidden: hidden,
title: col.title ?? fieldNames[col.accessor] ?? `? ${col.accessor} ?`
};
});
@ -165,6 +237,7 @@ export function InvenTreeTable<T = any>({
return cols;
}, [
columns,
fieldNames,
tableProps.rowActions,
tableProps.enableSelection,
tableState.hiddenColumns,
@ -289,7 +362,7 @@ export function InvenTreeTable<T = any>({
let queryParams = getTableFilters(true);
return api
.get(`${url}`, {
.get(url, {
params: queryParams,
timeout: 30 * 1000
})
@ -424,15 +497,14 @@ export function InvenTreeTable<T = any>({
return (
<>
{tableProps.enableFilters &&
(tableProps.tableFilters?.length ?? 0) > 0 && (
<FilterSelectDrawer
availableFilters={tableProps.tableFilters ?? []}
tableState={tableState}
opened={filtersVisible}
onClose={() => setFiltersVisible(false)}
/>
)}
{tableProps.enableFilters && (filters.length ?? 0) > 0 && (
<FilterSelectDrawer
availableFilters={filters}
tableState={tableState}
opened={filtersVisible}
onClose={() => setFiltersVisible(false)}
/>
)}
<Stack spacing="sm">
<Group position="apart">
<Group position="left" key="custom-actions" spacing={5}>
@ -489,22 +561,21 @@ export function InvenTreeTable<T = any>({
onToggleColumn={toggleColumn}
/>
)}
{tableProps.enableFilters &&
(tableProps.tableFilters?.length ?? 0 > 0) && (
<Indicator
size="xs"
label={tableState.activeFilters.length}
disabled={tableState.activeFilters.length == 0}
>
<ActionIcon>
<Tooltip label={t`Table filters`}>
<IconFilter
onClick={() => setFiltersVisible(!filtersVisible)}
/>
</Tooltip>
</ActionIcon>
</Indicator>
)}
{tableProps.enableFilters && filters.length > 0 && (
<Indicator
size="xs"
label={tableState.activeFilters.length}
disabled={tableState.activeFilters.length == 0}
>
<ActionIcon>
<Tooltip label={t`Table filters`}>
<IconFilter
onClick={() => setFiltersVisible(!filtersVisible)}
/>
</Tooltip>
</ActionIcon>
</Indicator>
)}
{tableProps.enableDownload && (
<DownloadAction
key="download-action"
@ -513,40 +584,48 @@ export function InvenTreeTable<T = any>({
)}
</Group>
</Group>
<DataTable
withBorder
striped
highlightOnHover
loaderVariant="dots"
pinLastColumn={tableProps.rowActions != undefined}
idAccessor={tableProps.idAccessor}
minHeight={300}
totalRecords={recordCount}
recordsPerPage={tableProps.pageSize ?? defaultPageSize}
page={page}
onPageChange={setPage}
sortStatus={sortStatus}
onSortStatusChange={handleSortStatusChange}
selectedRecords={
tableProps.enableSelection ? tableState.selectedRecords : undefined
}
onSelectedRecordsChange={
tableProps.enableSelection ? onSelectedRecordsChange : undefined
}
fetching={isFetching}
noRecordsText={missingRecordsText}
records={data}
columns={dataColumns}
onRowClick={tableProps.onRowClick}
defaultColumnProps={{
noWrap: true,
textAlignment: 'left',
cellsStyle: {
// TODO: Need a better way of handling "wide" cells,
overflow: 'hidden'
<Box pos="relative">
<LoadingOverlay
visible={tableOptionQuery.isLoading || tableOptionQuery.isFetching}
/>
<DataTable
withBorder
striped
highlightOnHover
loaderVariant="dots"
pinLastColumn={tableProps.rowActions != undefined}
idAccessor={tableProps.idAccessor}
minHeight={300}
totalRecords={recordCount}
recordsPerPage={tableProps.pageSize ?? defaultPageSize}
page={page}
onPageChange={setPage}
sortStatus={sortStatus}
onSortStatusChange={handleSortStatusChange}
selectedRecords={
tableProps.enableSelection
? tableState.selectedRecords
: undefined
}
}}
/>
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>
</>
);

View File

@ -1,7 +1,10 @@
import { Paper } from '@mantine/core';
import { UserRoles } from '../../enums/Roles';
import { DetailImageButtonProps, DetailsImage } from '../images/DetailsImage';
import {
DetailImageButtonProps,
DetailsImage
} from '../components/images/DetailsImage';
import { UserRoles } from '../enums/Roles';
import { DetailsField, DetailsTable } from './Details';
/**

View File

@ -4,7 +4,7 @@ import { Menu } from '@mantine/core';
import { IconCopy, IconDots, IconEdit, IconTrash } from '@tabler/icons-react';
import { ReactNode, useMemo, useState } from 'react';
import { notYetImplemented } from '../../functions/notifications';
import { notYetImplemented } from '../functions/notifications';
// Type definition for a table row action
export type RowAction = {

View File

@ -1,3 +1,4 @@
import { t } from '@lingui/macro';
import { CloseButton, TextInput } from '@mantine/core';
import { useDebouncedValue } from '@mantine/hooks';
import { IconSearch } from '@tabler/icons-react';
@ -19,11 +20,11 @@ export function TableSearchInput({
<TextInput
value={value}
icon={<IconSearch />}
placeholder="Search"
placeholder={t`Search`}
onChange={(event) => setValue(event.target.value)}
rightSection={
value.length > 0 ? (
<CloseButton size="xs" onClick={(event) => setValue('')} />
<CloseButton size="xs" onClick={() => setValue('')} />
) : null
}
/>

View File

@ -8,20 +8,25 @@ import {
import { ReactNode, useCallback, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { formatPriceRange } from '../../../defaults/formatters';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { ModelType } from '../../../enums/ModelType';
import { UserRoles } from '../../../enums/Roles';
import { bomItemFields } from '../../../forms/BomForms';
import { openDeleteApiForm, openEditApiForm } from '../../../functions/forms';
import { getDetailUrl } from '../../../functions/urls';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
import { Thumbnail } from '../../images/Thumbnail';
import { YesNoButton } from '../../items/YesNoButton';
import { Thumbnail } from '../../components/images/Thumbnail';
import { YesNoButton } from '../../components/items/YesNoButton';
import { formatPriceRange } from '../../defaults/formatters';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles';
import { bomItemFields } from '../../forms/BomForms';
import { openDeleteApiForm, openEditApiForm } from '../../functions/forms';
import { getDetailUrl } from '../../functions/urls';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { BooleanColumn } from '../ColumnRenderers';
import {
BooleanColumn,
DescriptionColumn,
NoteColumn,
ReferenceColumn
} from '../ColumnRenderers';
import { TableFilter } from '../Filter';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions';
@ -58,10 +63,8 @@ export function BomTable({
const tableColumns: TableColumn[] = useMemo(() => {
return [
// TODO: Improve column rendering
{
accessor: 'part',
title: t`Part`,
switchable: false,
sortable: true,
render: (record) => {
@ -91,18 +94,12 @@ export function BomTable({
);
}
},
{
accessor: 'description',
title: t`Description`,
render: (row) => row?.sub_part_detail?.description
},
{
accessor: 'reference',
title: t`Reference`
},
DescriptionColumn({
accessor: 'sub_part_detail.description'
}),
ReferenceColumn(),
{
accessor: 'quantity',
title: t`Quantity`,
switchable: false,
sortable: true
// TODO: Custom quantity renderer
@ -110,7 +107,6 @@ export function BomTable({
},
{
accessor: 'substitutes',
title: t`Substitutes`,
// TODO: Show hovercard with list of substitutes
render: (row) => {
let substitutes = row.substitutes ?? [];
@ -123,20 +119,16 @@ export function BomTable({
}
},
BooleanColumn({
accessor: 'optional',
title: t`Optional`
accessor: 'optional'
}),
BooleanColumn({
accessor: 'consumable',
title: t`Consumable`
accessor: 'consumable'
}),
BooleanColumn({
accessor: 'allow_variants',
title: t`Allow Variants`
accessor: 'allow_variants'
}),
BooleanColumn({
accessor: 'inherited',
title: t`Gets Inherited`
accessor: 'inherited'
// TODO: Custom renderer for this column
// TODO: See bom.js for existing implementation
}),
@ -150,7 +142,6 @@ export function BomTable({
},
{
accessor: 'available_stock',
title: t`Available`,
render: (record) => {
let extra: ReactNode[] = [];
@ -225,11 +216,7 @@ export function BomTable({
);
}
},
{
accessor: 'note',
title: t`Notes`,
switchable: true
}
NoteColumn()
];
}, [partId, params]);
@ -247,32 +234,26 @@ export function BomTable({
},
{
name: 'available_stock',
label: t`Has Available Stock`,
description: t`Show items with available stock`
},
{
name: 'on_order',
label: t`On Order`,
description: t`Show items on order`
},
{
name: 'validated',
label: t`Validated`,
description: t`Show validated items`
},
{
name: 'inherited',
label: t`Gets Inherited`,
description: t`Show inherited items`
},
{
name: 'optional',
label: t`Optional`,
description: t`Show optional items`
},
{
name: 'consumable',
label: t`Consumable`,
description: t`Show consumable items`
},
{

View File

@ -2,13 +2,14 @@ import { t } from '@lingui/macro';
import { useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { ModelType } from '../../../enums/ModelType';
import { getDetailUrl } from '../../../functions/urls';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { PartHoverCard } from '../../images/Thumbnail';
import { PartHoverCard } from '../../components/images/Thumbnail';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { getDetailUrl } from '../../functions/urls';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { TableColumn } from '../Column';
import { ReferenceColumn } from '../ColumnRenderers';
import { TableFilter } from '../Filter';
import { InvenTreeTable } from '../InvenTreeTable';
@ -30,30 +31,23 @@ export function UsedInTable({
return [
{
accessor: 'part',
title: t`Assembled Part`,
switchable: false,
sortable: true,
render: (record: any) => <PartHoverCard part={record.part_detail} />
},
{
accessor: 'sub_part',
title: t`Required Part`,
sortable: true,
render: (record: any) => <PartHoverCard part={record.sub_part_detail} />
},
{
accessor: 'quantity',
title: t`Quantity`,
render: (record: any) => {
// TODO: render units if appropriate
return record.quantity;
}
},
{
accessor: 'reference',
title: t`Reference`,
sortable: true
}
ReferenceColumn()
];
}, [partId]);
@ -61,12 +55,10 @@ export function UsedInTable({
return [
{
name: 'inherited',
label: t`Gets Inherited`,
description: t`Show inherited items`
},
{
name: 'optional',
label: t`Optional`,
description: t`Show optional items`
},
{

View File

@ -8,14 +8,14 @@ import {
import { useCallback, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { ModelType } from '../../../enums/ModelType';
import { getDetailUrl } from '../../../functions/urls';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
import { PartHoverCard } from '../../images/Thumbnail';
import { ProgressBar } from '../../items/ProgressBar';
import { PartHoverCard } from '../../components/images/Thumbnail';
import { ProgressBar } from '../../components/items/ProgressBar';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { getDetailUrl } from '../../functions/urls';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { BooleanColumn } from '../ColumnRenderers';
import { TableFilter } from '../Filter';
@ -31,7 +31,6 @@ export default function BuildLineTable({ params = {} }: { params?: any }) {
return [
{
name: 'allocated',
label: t`Allocated`,
description: t`Show allocated lines`
},
{
@ -114,28 +113,24 @@ export default function BuildLineTable({ params = {} }: { params?: any }) {
return [
{
accessor: 'bom_item',
title: t`Part`,
sortable: true,
switchable: false,
render: (record: any) => <PartHoverCard part={record.part_detail} />
},
{
accessor: 'reference',
title: t`Reference`,
render: (record: any) => record.bom_item_detail.reference
accessor: 'bom_item_detail.reference'
},
BooleanColumn({
accessor: 'bom_item_detail.consumable',
title: t`Consumable`
accessor: 'bom_item_detail.consumable'
}),
BooleanColumn({
accessor: 'bom_item_detail.optional',
title: t`Optional`
accessor: 'bom_item_detail.optional'
}),
{
accessor: 'unit_quantity',
title: t`Unit Quantity`,
accessor: 'bom_item_detail.quantity',
sortable: true,
title: t`Unit Quantity`,
ordering: 'unit_quantity',
render: (record: any) => {
return (
<Group position="apart">
@ -149,7 +144,6 @@ export default function BuildLineTable({ params = {} }: { params?: any }) {
},
{
accessor: 'quantity',
title: t`Required Quantity`,
sortable: true,
render: (record: any) => {
return (
@ -164,14 +158,12 @@ export default function BuildLineTable({ params = {} }: { params?: any }) {
},
{
accessor: 'available_stock',
title: t`Available`,
sortable: true,
switchable: false,
render: renderAvailableColumn
},
{
accessor: 'allocated',
title: t`Allocated`,
switchable: false,
render: (record: any) => {
return record?.bom_item_detail?.consumable ? (

View File

@ -2,24 +2,25 @@ import { t } from '@lingui/macro';
import { useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { renderDate } from '../../../defaults/formatters';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { ModelType } from '../../../enums/ModelType';
import { UserRoles } from '../../../enums/Roles';
import { buildOrderFields } from '../../../forms/BuildForms';
import { getDetailUrl } from '../../../functions/urls';
import { useCreateApiFormModal } from '../../../hooks/UseForm';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
import { AddItemButton } from '../../buttons/AddItemButton';
import { PartHoverCard } from '../../images/Thumbnail';
import { ProgressBar } from '../../items/ProgressBar';
import { RenderUser } from '../../render/User';
import { AddItemButton } from '../../components/buttons/AddItemButton';
import { PartHoverCard } from '../../components/images/Thumbnail';
import { ProgressBar } from '../../components/items/ProgressBar';
import { RenderUser } from '../../components/render/User';
import { renderDate } from '../../defaults/formatters';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles';
import { buildOrderFields } from '../../forms/BuildForms';
import { getDetailUrl } from '../../functions/urls';
import { useCreateApiFormModal } from '../../hooks/UseForm';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import {
CreationDateColumn,
ProjectCodeColumn,
ReferenceColumn,
ResponsibleColumn,
StatusColumn,
TargetDateColumn
@ -32,29 +33,21 @@ import { InvenTreeTable } from '../InvenTreeTable';
*/
function buildOrderTableColumns(): TableColumn[] {
return [
{
accessor: 'reference',
sortable: true,
switchable: false,
title: t`Reference`
},
ReferenceColumn(),
{
accessor: 'part',
sortable: true,
switchable: false,
title: t`Part`,
render: (record: any) => <PartHoverCard part={record.part_detail} />
},
{
accessor: 'title',
sortable: false,
title: t`Description`
sortable: false
},
{
accessor: 'completed',
sortable: true,
switchable: false,
title: t`Progress`,
render: (record: any) => (
<ProgressBar
progressLabel={true}
@ -67,7 +60,6 @@ function buildOrderTableColumns(): TableColumn[] {
ProjectCodeColumn(),
{
accessor: 'priority',
title: t`Priority`,
sortable: true
},
CreationDateColumn(),
@ -75,13 +67,11 @@ function buildOrderTableColumns(): TableColumn[] {
{
accessor: 'completion_date',
sortable: true,
title: t`Completed`,
render: (record: any) => renderDate(record.completion_date)
},
{
accessor: 'issued_by',
sortable: true,
title: t`Issued By`,
render: (record: any) => (
<RenderUser instance={record?.issued_by_detail} />
)
@ -114,14 +104,12 @@ export function BuildOrderTable({
},
{
name: 'status',
label: t`Status`,
description: t`Filter by order status`,
choiceFunction: StatusFilterOptions(ModelType.build)
},
{
name: 'overdue',
type: 'boolean',
label: t`Overdue`,
description: t`Show overdue status`
},
{

View File

@ -1,19 +1,19 @@
import { t } from '@lingui/macro';
import { useCallback, useMemo, useState } from 'react';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { UserRoles } from '../../../enums/Roles';
import { AddItemButton } from '../../components/buttons/AddItemButton';
import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField';
import { YesNoButton } from '../../components/items/YesNoButton';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { UserRoles } from '../../enums/Roles';
import {
useCreateApiFormModal,
useDeleteApiFormModal,
useEditApiFormModal
} from '../../../hooks/UseForm';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
import { AddItemButton } from '../../buttons/AddItemButton';
import { ApiFormFieldSet } from '../../forms/fields/ApiFormField';
import { YesNoButton } from '../../items/YesNoButton';
} from '../../hooks/UseForm';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowDeleteAction, RowEditAction } from '../RowActions';
@ -33,13 +33,11 @@ export function AddressTable({
return [
{
accessor: 'title',
title: t`Title`,
sortable: true,
switchable: false
},
{
accessor: 'primary',
title: t`Primary`,
switchable: false,
sortable: false,
render: (record: any) => YesNoButton({ value: record.primary })
@ -65,43 +63,36 @@ export function AddressTable({
},
{
accessor: 'postal_code',
title: t`Postal Code`,
sortable: false,
switchable: true
},
{
accessor: 'postal_city',
title: t`City`,
sortable: false,
switchable: true
},
{
accessor: 'province',
title: t`State / Province`,
sortable: false,
switchable: true
},
{
accessor: 'country',
title: t`Country`,
sortable: false,
switchable: true
},
{
accessor: 'shipping_notes',
title: t`Courier Notes`,
sortable: false,
switchable: true
},
{
accessor: 'internal_shipping_notes',
title: t`Internal Notes`,
sortable: false,
switchable: true
},
{
accessor: 'link',
title: t`Link`,
sortable: false,
switchable: true
}

View File

@ -3,15 +3,15 @@ import { Group, Text } from '@mantine/core';
import { useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { UserRoles } from '../../../enums/Roles';
import { companyFields } from '../../../forms/CompanyForms';
import { useCreateApiFormModal } from '../../../hooks/UseForm';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
import { AddItemButton } from '../../buttons/AddItemButton';
import { Thumbnail } from '../../images/Thumbnail';
import { AddItemButton } from '../../components/buttons/AddItemButton';
import { Thumbnail } from '../../components/images/Thumbnail';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { UserRoles } from '../../enums/Roles';
import { companyFields } from '../../forms/CompanyForms';
import { useCreateApiFormModal } from '../../hooks/UseForm';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { DescriptionColumn } from '../ColumnRenderers';
import { InvenTreeTable } from '../InvenTreeTable';
@ -35,7 +35,6 @@ export function CompanyTable({
return [
{
accessor: 'name',
title: t`Company Name`,
sortable: true,
render: (record: any) => {
return (
@ -53,7 +52,6 @@ export function CompanyTable({
DescriptionColumn({}),
{
accessor: 'website',
title: t`Website`,
sortable: false
}
];
@ -65,7 +63,6 @@ export function CompanyTable({
fields: companyFields(),
initialData: params,
onFormSuccess: (response) => {
console.log('onFormSuccess:', response);
if (response.pk) {
let base = path ?? 'company';
navigate(`/${base}/${response.pk}`);

View File

@ -1,18 +1,18 @@
import { t } from '@lingui/macro';
import { useCallback, useMemo, useState } from 'react';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { UserRoles } from '../../../enums/Roles';
import { AddItemButton } from '../../components/buttons/AddItemButton';
import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { UserRoles } from '../../enums/Roles';
import {
useCreateApiFormModal,
useDeleteApiFormModal,
useEditApiFormModal
} from '../../../hooks/UseForm';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
import { AddItemButton } from '../../buttons/AddItemButton';
import { ApiFormFieldSet } from '../../forms/fields/ApiFormField';
} from '../../hooks/UseForm';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowDeleteAction, RowEditAction } from '../RowActions';
@ -32,25 +32,21 @@ export function ContactTable({
return [
{
accessor: 'name',
title: t`Name`,
sortable: true,
switchable: false
},
{
accessor: 'phone',
title: t`Phone`,
switchable: true,
sortable: false
},
{
accessor: 'email',
title: t`Email`,
switchable: true,
sortable: false
},
{
accessor: 'role',
title: t`Role`,
switchable: true,
sortable: false
}

View File

@ -6,16 +6,16 @@ import { notifications } from '@mantine/notifications';
import { IconExternalLink, IconFileUpload } from '@tabler/icons-react';
import { ReactNode, useEffect, useMemo, useState } from 'react';
import { api } from '../../../App';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { api } from '../../App';
import { AttachmentLink } from '../../components/items/AttachmentLink';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import {
addAttachment,
deleteAttachment,
editAttachment
} from '../../../forms/AttachmentForms';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { AttachmentLink } from '../../items/AttachmentLink';
} from '../../forms/AttachmentForms';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { TableColumn } from '../Column';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions';
@ -27,7 +27,6 @@ function attachmentTableColumns(): TableColumn[] {
return [
{
accessor: 'attachment',
title: t`Attachment`,
sortable: false,
switchable: false,
noWrap: true,
@ -44,7 +43,6 @@ function attachmentTableColumns(): TableColumn[] {
},
{
accessor: 'comment',
title: t`Comment`,
sortable: false,
render: function (record: any) {
@ -52,9 +50,8 @@ function attachmentTableColumns(): TableColumn[] {
}
},
{
accessor: 'uploaded',
title: t`Uploaded`,
sortable: false,
accessor: 'upload_date',
sortable: true,
render: function (record: any) {
return (

View File

@ -1,9 +1,9 @@
import { t } from '@lingui/macro';
import { useMemo } from 'react';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { TableState } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { TableState } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { TableColumn } from '../Column';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowAction } from '../RowActions';

View File

@ -2,20 +2,20 @@ import { t } from '@lingui/macro';
import { useCallback, useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { ModelType } from '../../../enums/ModelType';
import { UserRoles } from '../../../enums/Roles';
import { partCategoryFields } from '../../../forms/PartForms';
import { getDetailUrl } from '../../../functions/urls';
import { AddItemButton } from '../../components/buttons/AddItemButton';
import { YesNoButton } from '../../components/items/YesNoButton';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles';
import { partCategoryFields } from '../../forms/PartForms';
import { getDetailUrl } from '../../functions/urls';
import {
useCreateApiFormModal,
useEditApiFormModal
} from '../../../hooks/UseForm';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
import { AddItemButton } from '../../buttons/AddItemButton';
import { YesNoButton } from '../../items/YesNoButton';
} from '../../hooks/UseForm';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { DescriptionColumn } from '../ColumnRenderers';
import { TableFilter } from '../Filter';
@ -35,19 +35,16 @@ export function PartCategoryTable({ parentId }: { parentId?: any }) {
return [
{
accessor: 'name',
title: t`Name`,
sortable: true,
switchable: false
},
DescriptionColumn({}),
{
accessor: 'pathstring',
title: t`Path`,
sortable: false
},
{
accessor: 'structural',
title: t`Structural`,
sortable: true,
render: (record: any) => {
return <YesNoButton value={record.structural} />;
@ -55,7 +52,6 @@ export function PartCategoryTable({ parentId }: { parentId?: any }) {
},
{
accessor: 'part_count',
title: t`Parts`,
sortable: true
}
];

View File

@ -2,21 +2,21 @@ import { t } from '@lingui/macro';
import { Text } from '@mantine/core';
import { useCallback, useMemo, useState } from 'react';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { UserRoles } from '../../../enums/Roles';
import { AddItemButton } from '../../components/buttons/AddItemButton';
import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField';
import { YesNoButton } from '../../components/items/YesNoButton';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { UserRoles } from '../../enums/Roles';
import {
useCreateApiFormModal,
useDeleteApiFormModal,
useEditApiFormModal
} from '../../../hooks/UseForm';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
import { AddItemButton } from '../../buttons/AddItemButton';
import { ApiFormFieldSet } from '../../forms/fields/ApiFormField';
import { YesNoButton } from '../../items/YesNoButton';
} from '../../hooks/UseForm';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { PartColumn } from '../ColumnRenderers';
import { DescriptionColumn, PartColumn } from '../ColumnRenderers';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowDeleteAction, RowEditAction } from '../RowActions';
@ -32,20 +32,16 @@ export function PartParameterTable({ partId }: { partId: any }) {
return [
{
accessor: 'part',
title: t`Part`,
sortable: true,
render: (record: any) => PartColumn(record?.part_detail)
},
{
accessor: 'part_detail.IPN',
title: t`IPN`,
sortable: false,
switchable: true
},
{
accessor: 'name',
title: t`Parameter`,
accessor: 'template_detail.name',
switchable: false,
sortable: true,
render: (record) => {
@ -54,16 +50,11 @@ export function PartParameterTable({ partId }: { partId: any }) {
return <Text italic={variant}>{record.template_detail?.name}</Text>;
}
},
{
accessor: 'description',
title: t`Description`,
sortable: false,
render: (record) => record.template_detail?.description
},
DescriptionColumn({
accessor: 'template_detail.description'
}),
{
accessor: 'data',
title: t`Value`,
switchable: false,
sortable: true,
render: (record) => {
@ -83,11 +74,8 @@ export function PartParameterTable({ partId }: { partId: any }) {
}
},
{
accessor: 'units',
title: t`Units`,
sortable: true,
render: (record) => record.template_detail?.units
accessor: 'template_detail.units',
sortable: false
}
];
}, [partId]);

View File

@ -1,18 +1,18 @@
import { t } from '@lingui/macro';
import { useCallback, useMemo, useState } from 'react';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { UserRoles } from '../../../enums/Roles';
import { AddItemButton } from '../../components/buttons/AddItemButton';
import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { UserRoles } from '../../enums/Roles';
import {
useCreateApiFormModal,
useDeleteApiFormModal,
useEditApiFormModal
} from '../../../hooks/UseForm';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
import { AddItemButton } from '../../buttons/AddItemButton';
import { ApiFormFieldSet } from '../../forms/fields/ApiFormField';
} from '../../hooks/UseForm';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { DescriptionColumn } from '../ColumnRenderers';
import { TableFilter } from '../Filter';
@ -48,23 +48,19 @@ export default function PartParameterTemplateTable() {
return [
{
accessor: 'name',
title: t`Name`,
sortable: true,
switchable: false
},
{
accessor: 'units',
title: t`Units`,
sortable: true
},
DescriptionColumn({}),
{
accessor: 'checkbox',
title: t`Checkbox`
accessor: 'checkbox'
},
{
accessor: 'choices',
title: t`Choices`
accessor: 'choices'
}
];
}, []);

View File

@ -3,14 +3,14 @@ import { Group, Text } from '@mantine/core';
import { ReactNode, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { formatPriceRange } from '../../../defaults/formatters';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { ModelType } from '../../../enums/ModelType';
import { shortenString } from '../../../functions/tables';
import { getDetailUrl } from '../../../functions/urls';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { Thumbnail } from '../../images/Thumbnail';
import { Thumbnail } from '../../components/images/Thumbnail';
import { formatPriceRange } from '../../defaults/formatters';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { shortenString } from '../../functions/tables';
import { getDetailUrl } from '../../functions/urls';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { TableColumn } from '../Column';
import { DescriptionColumn, LinkColumn } from '../ColumnRenderers';
import { TableFilter } from '../Filter';
@ -26,7 +26,6 @@ function partTableColumns(): TableColumn[] {
accessor: 'name',
sortable: true,
noWrap: true,
title: t`Part`,
render: function (record: any) {
return (
<Thumbnail
@ -39,18 +38,15 @@ function partTableColumns(): TableColumn[] {
},
{
accessor: 'IPN',
title: t`IPN`,
sortable: true
},
{
accessor: 'units',
sortable: true,
title: t`Units`
sortable: true
},
DescriptionColumn({}),
{
accessor: 'category',
title: t`Category`,
sortable: true,
render: function (record: any) {
@ -62,7 +58,6 @@ function partTableColumns(): TableColumn[] {
},
{
accessor: 'total_in_stock',
title: t`Stock`,
sortable: true,
render: (record) => {

View File

@ -1,18 +1,18 @@
import { t } from '@lingui/macro';
import { useCallback, useMemo, useState } from 'react';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { UserRoles } from '../../../enums/Roles';
import { AddItemButton } from '../../components/buttons/AddItemButton';
import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { UserRoles } from '../../enums/Roles';
import {
useCreateApiFormModal,
useDeleteApiFormModal,
useEditApiFormModal
} from '../../../hooks/UseForm';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
import { AddItemButton } from '../../buttons/AddItemButton';
import { ApiFormFieldSet } from '../../forms/fields/ApiFormField';
} from '../../hooks/UseForm';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { BooleanColumn, DescriptionColumn } from '../ColumnRenderers';
import { TableFilter } from '../Filter';
@ -27,7 +27,6 @@ export default function PartTestTemplateTable({ partId }: { partId: number }) {
return [
{
accessor: 'test_name',
title: t`Test Name`,
switchable: false,
sortable: true
},
@ -35,16 +34,13 @@ export default function PartTestTemplateTable({ partId }: { partId: number }) {
switchable: false
}),
BooleanColumn({
accessor: 'required',
title: t`Required`
accessor: 'required'
}),
BooleanColumn({
accessor: 'requires_value',
title: t`Requires Value`
accessor: 'requires_value'
}),
BooleanColumn({
accessor: 'requires_attachment',
title: t`Requires Attachment`
accessor: 'requires_attachment'
})
];
}, []);
@ -53,17 +49,14 @@ export default function PartTestTemplateTable({ partId }: { partId: number }) {
return [
{
name: 'required',
label: t`Required`,
description: t`Show required tests`
},
{
name: 'requires_value',
label: t`Requires Value`,
description: t`Show tests that require a value`
},
{
name: 'requires_attachment',
label: t`Requires Attachment`,
description: t`Show tests that require an attachment`
}
];

View File

@ -4,10 +4,10 @@ import { useHover } from '@mantine/hooks';
import { useQuery } from '@tanstack/react-query';
import React, { Suspense, useEffect, useState } from 'react';
import { api } from '../../../App';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { apiUrl } from '../../../states/ApiState';
import { Thumbnail } from '../../images/Thumbnail';
import { api } from '../../App';
import { Thumbnail } from '../../components/images/Thumbnail';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { apiUrl } from '../../states/ApiState';
/**
* Input props to table

View File

@ -3,18 +3,18 @@ import { Group, Text } from '@mantine/core';
import { ReactNode, useCallback, useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { UserRoles } from '../../../enums/Roles';
import { AddItemButton } from '../../components/buttons/AddItemButton';
import { ApiFormFieldSet } from '../../components/forms/fields/ApiFormField';
import { Thumbnail } from '../../components/images/Thumbnail';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { UserRoles } from '../../enums/Roles';
import {
useCreateApiFormModal,
useDeleteApiFormModal
} from '../../../hooks/UseForm';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
import { AddItemButton } from '../../buttons/AddItemButton';
import { ApiFormFieldSet } from '../../forms/fields/ApiFormField';
import { Thumbnail } from '../../images/Thumbnail';
} from '../../hooks/UseForm';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowDeleteAction } from '../RowActions';

View File

@ -2,9 +2,9 @@ import { t } from '@lingui/macro';
import { Code } from '@mantine/core';
import { useMemo } from 'react';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { TableColumn } from '../Column';
import { InvenTreeTable, InvenTreeTableProps } from '../InvenTreeTable';

View File

@ -23,20 +23,23 @@ import { IconDots } from '@tabler/icons-react';
import { useCallback, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { api } from '../../../App';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { openEditApiForm } from '../../../functions/forms';
import { useCreateApiFormModal } from '../../../hooks/UseForm';
import { useInstance } from '../../../hooks/UseInstance';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl, useServerApiState } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
import { ActionButton } from '../../buttons/ActionButton';
import { ActionDropdown, EditItemAction } from '../../items/ActionDropdown';
import { InfoItem } from '../../items/InfoItem';
import { StylishText } from '../../items/StylishText';
import { DetailDrawer } from '../../nav/DetailDrawer';
import { PluginSettingList } from '../../settings/SettingList';
import { api } from '../../App';
import { ActionButton } from '../../components/buttons/ActionButton';
import {
ActionDropdown,
EditItemAction
} from '../../components/items/ActionDropdown';
import { InfoItem } from '../../components/items/InfoItem';
import { StylishText } from '../../components/items/StylishText';
import { DetailDrawer } from '../../components/nav/DetailDrawer';
import { PluginSettingList } from '../../components/settings/SettingList';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { openEditApiForm } from '../../functions/forms';
import { useCreateApiFormModal } from '../../hooks/UseForm';
import { useInstance } from '../../hooks/UseInstance';
import { useTable } from '../../hooks/UseTable';
import { apiUrl, useServerApiState } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { InvenTreeTable, InvenTreeTableProps } from '../InvenTreeTable';
import { RowAction } from '../RowActions';

View File

@ -1,13 +1,13 @@
import { t } from '@lingui/macro';
import { useCallback, useMemo } from 'react';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { UserRoles } from '../../../enums/Roles';
import { useManufacturerPartParameterFields } from '../../../forms/CompanyForms';
import { openDeleteApiForm, openEditApiForm } from '../../../functions/forms';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { UserRoles } from '../../enums/Roles';
import { useManufacturerPartParameterFields } from '../../forms/CompanyForms';
import { openDeleteApiForm, openEditApiForm } from '../../functions/forms';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowDeleteAction, RowEditAction } from '../RowActions';

View File

@ -2,18 +2,18 @@ import { t } from '@lingui/macro';
import { ReactNode, useCallback, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { ModelType } from '../../../enums/ModelType';
import { UserRoles } from '../../../enums/Roles';
import { useManufacturerPartFields } from '../../../forms/CompanyForms';
import { openDeleteApiForm, openEditApiForm } from '../../../functions/forms';
import { notYetImplemented } from '../../../functions/notifications';
import { getDetailUrl } from '../../../functions/urls';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
import { AddItemButton } from '../../buttons/AddItemButton';
import { Thumbnail } from '../../images/Thumbnail';
import { AddItemButton } from '../../components/buttons/AddItemButton';
import { Thumbnail } from '../../components/images/Thumbnail';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles';
import { useManufacturerPartFields } from '../../forms/CompanyForms';
import { openDeleteApiForm, openEditApiForm } from '../../functions/forms';
import { notYetImplemented } from '../../functions/notifications';
import { getDetailUrl } from '../../functions/urls';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { DescriptionColumn, LinkColumn, PartColumn } from '../ColumnRenderers';
import { InvenTreeTable } from '../InvenTreeTable';
@ -33,14 +33,12 @@ export function ManufacturerPartTable({ params }: { params: any }): ReactNode {
return [
{
accessor: 'part',
title: t`Part`,
switchable: 'part' in params,
sortable: true,
render: (record: any) => PartColumn(record?.part_detail)
},
{
accessor: 'manufacturer',
title: t`Manufacturer`,
sortable: true,
render: (record: any) => {
let manufacturer = record?.manufacturer_detail ?? {};

View File

@ -4,27 +4,28 @@ import { IconSquareArrowRight } from '@tabler/icons-react';
import { useCallback, useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { ProgressBar } from '../../../components/items/ProgressBar';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { ModelType } from '../../../enums/ModelType';
import { UserRoles } from '../../../enums/Roles';
import { purchaseOrderLineItemFields } from '../../../forms/PurchaseOrderForms';
import { getDetailUrl } from '../../../functions/urls';
import { ActionButton } from '../../components/buttons/ActionButton';
import { AddItemButton } from '../../components/buttons/AddItemButton';
import { Thumbnail } from '../../components/images/Thumbnail';
import { ProgressBar } from '../../components/items/ProgressBar';
import { RenderStockLocation } from '../../components/render/Stock';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles';
import { purchaseOrderLineItemFields } from '../../forms/PurchaseOrderForms';
import { getDetailUrl } from '../../functions/urls';
import {
useCreateApiFormModal,
useDeleteApiFormModal,
useEditApiFormModal
} from '../../../hooks/UseForm';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
import { ActionButton } from '../../buttons/ActionButton';
import { AddItemButton } from '../../buttons/AddItemButton';
import { Thumbnail } from '../../images/Thumbnail';
import { RenderStockLocation } from '../../render/Stock';
} from '../../hooks/UseForm';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import {
CurrencyColumn,
LinkColumn,
ReferenceColumn,
TargetDateColumn,
TotalPriceColumn
} from '../ColumnRenderers';
@ -74,11 +75,7 @@ export function PurchaseOrderLineItemTable({
sortable: false,
render: (record: any) => record?.part_detail?.description
},
{
accessor: 'reference',
title: t`Reference`,
sortable: true
},
ReferenceColumn(),
{
accessor: 'quantity',
title: t`Quantity`,

View File

@ -2,22 +2,23 @@ import { t } from '@lingui/macro';
import { useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { ModelType } from '../../../enums/ModelType';
import { UserRoles } from '../../../enums/Roles';
import { purchaseOrderFields } from '../../../forms/PurchaseOrderForms';
import { getDetailUrl } from '../../../functions/urls';
import { useCreateApiFormModal } from '../../../hooks/UseForm';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
import { AddItemButton } from '../../buttons/AddItemButton';
import { Thumbnail } from '../../images/Thumbnail';
import { AddItemButton } from '../../components/buttons/AddItemButton';
import { Thumbnail } from '../../components/images/Thumbnail';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles';
import { purchaseOrderFields } from '../../forms/PurchaseOrderForms';
import { getDetailUrl } from '../../functions/urls';
import { useCreateApiFormModal } from '../../hooks/UseForm';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import {
CreationDateColumn,
DescriptionColumn,
LineItemsProgressColumn,
ProjectCodeColumn,
ReferenceColumn,
ResponsibleColumn,
StatusColumn,
TargetDateColumn,
@ -65,13 +66,7 @@ export function PurchaseOrderTable({
const tableColumns = useMemo(() => {
return [
{
accessor: 'reference',
title: t`Reference`,
sortable: true,
switchable: false
// TODO: Display extra information if order is overdue
},
ReferenceColumn(),
DescriptionColumn({}),
{
accessor: 'supplier__name',
@ -90,8 +85,7 @@ export function PurchaseOrderTable({
}
},
{
accessor: 'supplier_reference',
title: t`Supplier Reference`
accessor: 'supplier_reference'
},
LineItemsProgressColumn(),
StatusColumn(ModelType.purchaseorder),

View File

@ -3,20 +3,25 @@ import { Text } from '@mantine/core';
import { ReactNode, useCallback, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { ModelType } from '../../../enums/ModelType';
import { UserRoles } from '../../../enums/Roles';
import { useSupplierPartFields } from '../../../forms/CompanyForms';
import { openDeleteApiForm, openEditApiForm } from '../../../functions/forms';
import { getDetailUrl } from '../../../functions/urls';
import { useCreateApiFormModal } from '../../../hooks/UseForm';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
import { AddItemButton } from '../../buttons/AddItemButton';
import { Thumbnail } from '../../images/Thumbnail';
import { AddItemButton } from '../../components/buttons/AddItemButton';
import { Thumbnail } from '../../components/images/Thumbnail';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles';
import { useSupplierPartFields } from '../../forms/CompanyForms';
import { openDeleteApiForm, openEditApiForm } from '../../functions/forms';
import { getDetailUrl } from '../../functions/urls';
import { useCreateApiFormModal } from '../../hooks/UseForm';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { DescriptionColumn, LinkColumn, PartColumn } from '../ColumnRenderers';
import {
DescriptionColumn,
LinkColumn,
NoteColumn,
PartColumn
} from '../ColumnRenderers';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowDeleteAction, RowEditAction } from '../RowActions';
import { TableHoverCard } from '../TableHoverCard';
@ -36,14 +41,12 @@ export function SupplierPartTable({ params }: { params: any }): ReactNode {
return [
{
accessor: 'part',
title: t`Part`,
switchable: 'part' in params,
sortable: true,
render: (record: any) => PartColumn(record?.part_detail)
},
{
accessor: 'supplier',
title: t`Supplier`,
sortable: true,
render: (record: any) => {
let supplier = record?.supplier_detail ?? {};
@ -68,7 +71,6 @@ export function SupplierPartTable({ params }: { params: any }): ReactNode {
accessor: 'manufacturer',
sortable: true,
title: t`Manufacturer`,
render: (record: any) => {
let manufacturer = record?.manufacturer_detail ?? {};
@ -91,17 +93,14 @@ export function SupplierPartTable({ params }: { params: any }): ReactNode {
},
{
accessor: 'in_stock',
title: t`In Stock`,
sortable: true
},
{
accessor: 'packaging',
title: t`Packaging`,
sortable: true
},
{
accessor: 'pack_quantity',
title: t`Pack Quantity`,
sortable: true,
render: (record: any) => {
@ -127,14 +126,9 @@ export function SupplierPartTable({ params }: { params: any }): ReactNode {
}
},
LinkColumn(),
{
accessor: 'note',
title: t`Notes`,
sortable: false
},
NoteColumn(),
{
accessor: 'available',
title: t`Availability`,
sortable: true,
render: (record: any) => {

View File

@ -2,24 +2,26 @@ import { t } from '@lingui/macro';
import { useCallback, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { ModelType } from '../../../enums/ModelType';
import { UserRoles } from '../../../enums/Roles';
import { notYetImplemented } from '../../../functions/notifications';
import { getDetailUrl } from '../../../functions/urls';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
import { AddItemButton } from '../../buttons/AddItemButton';
import { Thumbnail } from '../../images/Thumbnail';
import { AddItemButton } from '../../components/buttons/AddItemButton';
import { Thumbnail } from '../../components/images/Thumbnail';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles';
import { notYetImplemented } from '../../functions/notifications';
import { getDetailUrl } from '../../functions/urls';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import {
CreationDateColumn,
DescriptionColumn,
LineItemsProgressColumn,
ProjectCodeColumn,
ReferenceColumn,
ResponsibleColumn,
StatusColumn,
TargetDateColumn
TargetDateColumn,
TotalPriceColumn
} from '../ColumnRenderers';
import {
AssignedToMeFilter,
@ -56,12 +58,7 @@ export function ReturnOrderTable({ params }: { params?: any }) {
const tableColumns = useMemo(() => {
return [
{
accessor: 'reference',
title: t`Return Order`,
sortable: true
// TODO: Display extra information if order is overdue
},
ReferenceColumn(),
{
accessor: 'customer__name',
title: t`Customer`,
@ -79,8 +76,7 @@ export function ReturnOrderTable({ params }: { params?: any }) {
}
},
{
accessor: 'customer_reference',
title: t`Customer Reference`
accessor: 'customer_reference'
},
DescriptionColumn({}),
LineItemsProgressColumn(),
@ -89,10 +85,7 @@ export function ReturnOrderTable({ params }: { params?: any }) {
CreationDateColumn(),
TargetDateColumn(),
ResponsibleColumn(),
{
accessor: 'total_cost',
title: t`Total Cost`
}
TotalPriceColumn()
];
}, []);

View File

@ -2,22 +2,23 @@ import { t } from '@lingui/macro';
import { useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { ModelType } from '../../../enums/ModelType';
import { UserRoles } from '../../../enums/Roles';
import { salesOrderFields } from '../../../forms/SalesOrderForms';
import { getDetailUrl } from '../../../functions/urls';
import { useCreateApiFormModal } from '../../../hooks/UseForm';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
import { AddItemButton } from '../../buttons/AddItemButton';
import { Thumbnail } from '../../images/Thumbnail';
import { AddItemButton } from '../../components/buttons/AddItemButton';
import { Thumbnail } from '../../components/images/Thumbnail';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles';
import { salesOrderFields } from '../../forms/SalesOrderForms';
import { getDetailUrl } from '../../functions/urls';
import { useCreateApiFormModal } from '../../hooks/UseForm';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import {
CreationDateColumn,
DescriptionColumn,
LineItemsProgressColumn,
ProjectCodeColumn,
ReferenceColumn,
ShipmentDateColumn,
StatusColumn,
TargetDateColumn,
@ -88,13 +89,7 @@ export function SalesOrderTable({
const tableColumns = useMemo(() => {
return [
{
accessor: 'reference',
title: t`Sales Order`,
sortable: true,
switchable: false
// TODO: Display extra information if order is overdue
},
ReferenceColumn(),
{
accessor: 'customer__name',
title: t`Customer`,

View File

@ -3,11 +3,11 @@ import { showNotification } from '@mantine/notifications';
import { IconReload } from '@tabler/icons-react';
import { useCallback, useMemo } from 'react';
import { api } from '../../../App';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { ActionButton } from '../../buttons/ActionButton';
import { api } from '../../App';
import { ActionButton } from '../../components/buttons/ActionButton';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { InvenTreeTable } from '../InvenTreeTable';
/*

View File

@ -1,18 +1,18 @@
import { t } from '@lingui/macro';
import { useCallback, useMemo, useState } from 'react';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { UserRoles } from '../../../enums/Roles';
import { customUnitsFields } from '../../../forms/CommonForms';
import { AddItemButton } from '../../components/buttons/AddItemButton';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { UserRoles } from '../../enums/Roles';
import { customUnitsFields } from '../../forms/CommonForms';
import {
useCreateApiFormModal,
useDeleteApiFormModal,
useEditApiFormModal
} from '../../../hooks/UseForm';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
import { AddItemButton } from '../../buttons/AddItemButton';
} from '../../hooks/UseForm';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions';
@ -29,19 +29,16 @@ export default function CustomUnitsTable() {
return [
{
accessor: 'name',
title: t`Name`,
switchable: false,
sortable: true
},
{
accessor: 'definition',
title: t`Definition`,
switchable: false,
sortable: false
},
{
accessor: 'symbol',
title: t`Symbol`,
switchable: false,
sortable: true
}

View File

@ -3,11 +3,11 @@ import { Drawer, Text } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
import { useCallback, useMemo, useState } from 'react';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { openDeleteApiForm } from '../../../functions/forms';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { StylishText } from '../../items/StylishText';
import { StylishText } from '../../components/items/StylishText';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { openDeleteApiForm } from '../../functions/forms';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { TableColumn } from '../Column';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowAction, RowDeleteAction } from '../RowActions';

View File

@ -3,10 +3,10 @@ import { Drawer, Text } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
import { useMemo, useState } from 'react';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { StylishText } from '../../items/StylishText';
import { StylishText } from '../../components/items/StylishText';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { TableColumn } from '../Column';
import { InvenTreeTable } from '../InvenTreeTable';

View File

@ -3,18 +3,18 @@ import { Group, LoadingOverlay, Stack, Text, Title } from '@mantine/core';
import { useCallback, useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { AddItemButton } from '../../components/buttons/AddItemButton';
import { EditApiForm } from '../../components/forms/ApiForm';
import { PlaceholderPill } from '../../components/items/Placeholder';
import { DetailDrawer } from '../../components/nav/DetailDrawer';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import {
useCreateApiFormModal,
useDeleteApiFormModal
} from '../../../hooks/UseForm';
import { useInstance } from '../../../hooks/UseInstance';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { AddItemButton } from '../../buttons/AddItemButton';
import { EditApiForm } from '../../forms/ApiForm';
import { PlaceholderPill } from '../../items/Placeholder';
import { DetailDrawer } from '../../nav/DetailDrawer';
} from '../../hooks/UseForm';
import { useInstance } from '../../hooks/UseInstance';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { TableColumn } from '../Column';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions';

View File

@ -1,9 +1,9 @@
import { t } from '@lingui/macro';
import { useMemo } from 'react';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { TableColumn } from '../Column';
import { InvenTreeTable } from '../InvenTreeTable';

View File

@ -1,18 +1,18 @@
import { t } from '@lingui/macro';
import { useCallback, useMemo, useState } from 'react';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { UserRoles } from '../../../enums/Roles';
import { projectCodeFields } from '../../../forms/CommonForms';
import { AddItemButton } from '../../components/buttons/AddItemButton';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { UserRoles } from '../../enums/Roles';
import { projectCodeFields } from '../../forms/CommonForms';
import {
useCreateApiFormModal,
useDeleteApiFormModal,
useEditApiFormModal
} from '../../../hooks/UseForm';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
import { AddItemButton } from '../../buttons/AddItemButton';
} from '../../hooks/UseForm';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { DescriptionColumn, ResponsibleColumn } from '../ColumnRenderers';
import { InvenTreeTable } from '../InvenTreeTable';
@ -30,8 +30,7 @@ export default function ProjectCodeTable() {
return [
{
accessor: 'code',
sortable: true,
title: t`Project Code`
sortable: true
},
DescriptionColumn({}),
ResponsibleColumn()

View File

@ -3,9 +3,9 @@ import { Group, Text } from '@mantine/core';
import { IconCircleCheck, IconCircleX } from '@tabler/icons-react';
import { useMemo } from 'react';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { TableColumn } from '../Column';
import { InvenTreeTable } from '../InvenTreeTable';

View File

@ -5,15 +5,15 @@ import { useCallback, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { Link } from 'react-router-dom';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { openCreateApiForm, openDeleteApiForm } from '../../../functions/forms';
import { useInstance } from '../../../hooks/UseInstance';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
import { AddItemButton } from '../../buttons/AddItemButton';
import { EditApiForm } from '../../forms/ApiForm';
import { DetailDrawer } from '../../nav/DetailDrawer';
import { AddItemButton } from '../../components/buttons/AddItemButton';
import { EditApiForm } from '../../components/forms/ApiForm';
import { DetailDrawer } from '../../components/nav/DetailDrawer';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { openCreateApiForm, openDeleteApiForm } from '../../functions/forms';
import { useInstance } from '../../hooks/UseInstance';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { BooleanColumn } from '../ColumnRenderers';
import { InvenTreeTable } from '../InvenTreeTable';
@ -153,45 +153,37 @@ export function UserTable() {
return [
{
accessor: 'email',
sortable: true,
title: t`Email`
sortable: true
},
{
accessor: 'username',
sortable: true,
switchable: false,
title: t`Username`
switchable: false
},
{
accessor: 'first_name',
sortable: true,
title: t`First Name`
sortable: true
},
{
accessor: 'last_name',
sortable: true,
title: t`Last Name`
sortable: true
},
{
accessor: 'groups',
sortable: true,
switchable: true,
title: t`Groups`,
render: (record: any) => {
return record.groups.length;
}
},
BooleanColumn({
accessor: 'is_staff',
title: t`Staff`
accessor: 'is_staff'
}),
BooleanColumn({
accessor: 'is_superuser',
title: t`Superuser`
accessor: 'is_superuser'
}),
BooleanColumn({
accessor: 'is_active',
title: t`Active`
accessor: 'is_active'
})
];
}, []);

View File

@ -3,17 +3,21 @@ import { Group, Text } from '@mantine/core';
import { ReactNode, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { formatCurrency, renderDate } from '../../../defaults/formatters';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { ModelType } from '../../../enums/ModelType';
import { getDetailUrl } from '../../../functions/urls';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { formatCurrency, renderDate } from '../../defaults/formatters';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { getDetailUrl } from '../../functions/urls';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { TableColumn } from '../Column';
import { PartColumn, StatusColumn } from '../ColumnRenderers';
import {
DescriptionColumn,
PartColumn,
StatusColumn
} from '../ColumnRenderers';
import { StatusFilterOptions, TableFilter } from '../Filter';
import { InvenTreeTable } from '../InvenTreeTable';
import { TableHoverCard } from '../TableHoverCard';
import { InvenTreeTable } from './../InvenTreeTable';
/**
* Construct a list of columns for the stock item table
@ -23,14 +27,11 @@ function stockItemTableColumns(): TableColumn[] {
{
accessor: 'part',
sortable: true,
title: t`Part`,
render: (record: any) => PartColumn(record?.part_detail)
},
{
accessor: 'part_detail.description',
sortable: false,
title: t`Description`
},
DescriptionColumn({
accessor: 'part_detail.description'
}),
{
accessor: 'quantity',
sortable: true,
@ -176,15 +177,11 @@ function stockItemTableColumns(): TableColumn[] {
StatusColumn(ModelType.stockitem),
{
accessor: 'batch',
sortable: true,
title: t`Batch`
sortable: true
},
{
accessor: 'location',
sortable: true,
title: t`Location`,
render: function (record: any) {
// TODO: Custom renderer for location
// TODO: Note, if not "In stock" we don't want to display the actual location here
@ -195,14 +192,12 @@ function stockItemTableColumns(): TableColumn[] {
{
accessor: 'expiry_date',
sortable: true,
title: t`Expiry Date`,
switchable: true,
render: (record: any) => renderDate(record.expiry_date)
},
{
accessor: 'updated',
sortable: true,
title: t`Last Updated`,
switchable: true,
render: (record: any) => renderDate(record.updated)
},
@ -211,7 +206,6 @@ function stockItemTableColumns(): TableColumn[] {
{
accessor: 'purchase_price',
sortable: true,
title: t`Purchase Price`,
switchable: true,
render: (record: any) =>
formatCurrency(record.purchase_price, {

View File

@ -2,22 +2,21 @@ import { t } from '@lingui/macro';
import { useCallback, useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
import { ModelType } from '../../../enums/ModelType';
import { UserRoles } from '../../../enums/Roles';
import { stockLocationFields } from '../../../forms/StockForms';
import { getDetailUrl } from '../../../functions/urls';
import { AddItemButton } from '../../components/buttons/AddItemButton';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles';
import { stockLocationFields } from '../../forms/StockForms';
import { getDetailUrl } from '../../functions/urls';
import {
useCreateApiFormModal,
useEditApiFormModal
} from '../../../hooks/UseForm';
import { useTable } from '../../../hooks/UseTable';
import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
import { AddItemButton } from '../../buttons/AddItemButton';
import { YesNoButton } from '../../items/YesNoButton';
} from '../../hooks/UseForm';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { DescriptionColumn } from '../ColumnRenderers';
import { BooleanColumn, DescriptionColumn } from '../ColumnRenderers';
import { TableFilter } from '../Filter';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowEditAction } from '../RowActions';
@ -40,12 +39,10 @@ export function StockLocationTable({ parentId }: { parentId?: any }) {
},
{
name: 'structural',
label: t`Structural`,
description: t`Show structural locations`
},
{
name: 'external',
label: t`External`,
description: t`Show external locations`
},
{
@ -60,39 +57,25 @@ export function StockLocationTable({ parentId }: { parentId?: any }) {
return [
{
accessor: 'name',
title: t`Name`,
switchable: false
},
DescriptionColumn({}),
{
accessor: 'pathstring',
title: t`Path`,
sortable: true
},
{
accessor: 'items',
title: t`Stock Items`,
sortable: true
},
{
accessor: 'structural',
title: t`Structural`,
sortable: true,
render: (record: any) => <YesNoButton value={record.structural} />
},
{
accessor: 'external',
title: t`External`,
sortable: true,
render: (record: any) => <YesNoButton value={record.external} />
},
BooleanColumn({
accessor: 'structural'
}),
BooleanColumn({
accessor: 'external'
}),
{
accessor: 'location_type',
title: t`Location Type`,
sortable: false,
render: (record: any) => record.location_type_detail?.name
}

View File

@ -35,7 +35,6 @@ export default function DesktopAppView() {
const [token] = sessionState.token ? [sessionState.token] : [null];
useEffect(() => {
if (Object.keys(hostList).length === 0) {
console.log('Loading default host list', defaultHostList);
useLocalState.setState({ hostList: defaultHostList });
}