[PUI] Refactor "notYetImplemented" ()

* Remove default "not yet implemented" action

- Will force us to manually add "not yet implemented"
- Intended to highlight where we still need to work

* Refactor more components

* Fix for onClick
This commit is contained in:
Oliver 2024-08-19 21:01:05 +10:00 committed by GitHub
parent 4b140aba8d
commit a7d9600c3d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
48 changed files with 223 additions and 255 deletions

@ -2,7 +2,6 @@ import { ActionIcon, FloatingPosition, Group, Tooltip } from '@mantine/core';
import { ReactNode } from 'react';
import { identifierString } from '../../functions/conversion';
import { notYetImplemented } from '../../functions/notifications';
export type ActionButtonProps = {
icon?: ReactNode;
@ -13,7 +12,7 @@ export type ActionButtonProps = {
size?: number | string;
radius?: number | string;
disabled?: boolean;
onClick?: any;
onClick: (event?: any) => void;
hidden?: boolean;
tooltipAlignment?: FloatingPosition;
};
@ -42,7 +41,9 @@ export function ActionButton(props: ActionButtonProps) {
aria-label={`action-button-${identifierString(
props.tooltip ?? props.text ?? ''
)}`}
onClick={props.onClick ?? notYetImplemented}
onClick={() => {
props.onClick();
}}
variant={props.variant ?? 'transparent'}
>
<Group gap="xs" wrap="nowrap">

@ -1,7 +1,6 @@
import { Button, Tooltip } from '@mantine/core';
import { InvenTreeIcon, InvenTreeIconType } from '../../functions/icons';
import { notYetImplemented } from '../../functions/notifications';
/**
* A "primary action" button for display on a page detail, (for example)
@ -19,7 +18,7 @@ export default function PrimaryActionButton({
icon?: InvenTreeIconType;
color?: string;
hidden?: boolean;
onClick?: () => void;
onClick: () => void;
}) {
if (hidden) {
return null;
@ -32,7 +31,7 @@ export default function PrimaryActionButton({
color={color}
radius="sm"
p="xs"
onClick={onClick ?? notYetImplemented}
onClick={onClick}
>
{title}
</Button>

@ -22,7 +22,11 @@ import { apiUrl } from '../../states/ApiState';
import { TableColumn } from '../../tables/Column';
import { TableFilter } from '../../tables/Filter';
import { InvenTreeTable } from '../../tables/InvenTreeTable';
import { RowDeleteAction, RowEditAction } from '../../tables/RowActions';
import {
RowAction,
RowDeleteAction,
RowEditAction
} from '../../tables/RowActions';
import { ActionButton } from '../buttons/ActionButton';
import { YesNoButton } from '../buttons/YesNoButton';
import { ApiFormFieldSet } from '../forms/fields/ApiFormField';
@ -316,7 +320,7 @@ export default function ImporterDataSelector({
}, [session]);
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
return [
{
title: t`Accept`,

@ -20,16 +20,15 @@ import { ReactNode, useMemo } from 'react';
import { ModelType } from '../../enums/ModelType';
import { identifierString } from '../../functions/conversion';
import { InvenTreeIcon } from '../../functions/icons';
import { notYetImplemented } from '../../functions/notifications';
import { InvenTreeQRCode } from './QRCode';
export type ActionDropdownItem = {
icon: ReactNode;
name: string;
icon?: ReactNode;
name?: string;
tooltip?: string;
disabled?: boolean;
hidden?: boolean;
onClick?: () => void;
onClick: (event?: any) => void;
indicator?: Omit<IndicatorProps, 'children'>;
};
@ -97,13 +96,7 @@ export function ActionDropdown({
<Menu.Item
aria-label={id}
leftSection={action.icon}
onClick={() => {
if (action.onClick != undefined) {
action.onClick();
} else {
notYetImplemented();
}
}}
onClick={action.onClick}
disabled={action.disabled}
>
{action.name}
@ -159,131 +152,79 @@ export function ViewBarcodeAction({
}
// Common action button for linking a custom barcode
export function LinkBarcodeAction({
hidden = false,
onClick
}: {
hidden?: boolean;
onClick?: () => void;
}): ActionDropdownItem {
export function LinkBarcodeAction(
props: ActionDropdownItem
): ActionDropdownItem {
return {
...props,
icon: <IconLink />,
name: t`Link Barcode`,
tooltip: t`Link custom barcode`,
onClick: onClick,
hidden: hidden
tooltip: t`Link custom barcode`
};
}
// Common action button for un-linking a custom barcode
export function UnlinkBarcodeAction({
hidden = false,
onClick
}: {
hidden?: boolean;
onClick?: () => void;
}): ActionDropdownItem {
export function UnlinkBarcodeAction(
props: ActionDropdownItem
): ActionDropdownItem {
return {
...props,
icon: <IconUnlink />,
name: t`Unlink Barcode`,
tooltip: t`Unlink custom barcode`,
onClick: onClick,
hidden: hidden
tooltip: t`Unlink custom barcode`
};
}
// Common action button for editing an item
export function EditItemAction({
hidden = false,
tooltip,
onClick
}: {
hidden?: boolean;
tooltip?: string;
onClick?: () => void;
}): ActionDropdownItem {
export function EditItemAction(props: ActionDropdownItem): ActionDropdownItem {
return {
...props,
icon: <IconEdit color="blue" />,
name: t`Edit`,
tooltip: tooltip ?? `Edit item`,
onClick: onClick,
hidden: hidden
tooltip: props.tooltip ?? t`Edit item`
};
}
// Common action button for deleting an item
export function DeleteItemAction({
hidden = false,
disabled = false,
tooltip,
onClick
}: {
hidden?: boolean;
disabled?: boolean;
tooltip?: string;
onClick?: () => void;
}): ActionDropdownItem {
export function DeleteItemAction(
props: ActionDropdownItem
): ActionDropdownItem {
return {
...props,
icon: <IconTrash color="red" />,
name: t`Delete`,
tooltip: tooltip ?? t`Delete item`,
onClick: onClick,
hidden: hidden,
disabled: disabled
tooltip: props.tooltip ?? t`Delete item`
};
}
export function HoldItemAction({
hidden = false,
tooltip,
onClick
}: {
hidden?: boolean;
tooltip?: string;
onClick?: () => void;
}): ActionDropdownItem {
export function HoldItemAction(props: ActionDropdownItem): ActionDropdownItem {
return {
...props,
icon: <InvenTreeIcon icon="hold" iconProps={{ color: 'orange' }} />,
name: t`Hold`,
tooltip: tooltip ?? t`Hold`,
onClick: onClick,
hidden: hidden
tooltip: props.tooltip ?? t`Hold`
};
}
export function CancelItemAction({
hidden = false,
tooltip,
onClick
}: {
hidden?: boolean;
tooltip?: string;
onClick?: () => void;
}): ActionDropdownItem {
export function CancelItemAction(
props: ActionDropdownItem
): ActionDropdownItem {
return {
...props,
icon: <InvenTreeIcon icon="cancel" iconProps={{ color: 'red' }} />,
name: t`Cancel`,
tooltip: tooltip ?? t`Cancel`,
onClick: onClick,
hidden: hidden
tooltip: props.tooltip ?? t`Cancel`
};
}
// Common action button for duplicating an item
export function DuplicateItemAction({
hidden = false,
tooltip,
onClick
}: {
hidden?: boolean;
tooltip?: string;
onClick?: () => void;
}): ActionDropdownItem {
export function DuplicateItemAction(
props: ActionDropdownItem
): ActionDropdownItem {
return {
...props,
icon: <IconCopy color="green" />,
name: t`Duplicate`,
tooltip: tooltip ?? t`Duplicate item`,
onClick: onClick,
hidden: hidden
tooltip: props.tooltip ?? t`Duplicate item`
};
}

@ -43,6 +43,7 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles';
import { useBuildOrderFields } from '../../forms/BuildForms';
import { notYetImplemented } from '../../functions/notifications';
import {
useCreateApiFormModal,
useEditApiFormModal
@ -477,10 +478,12 @@ export default function BuildDetail() {
pk: build.pk
}),
LinkBarcodeAction({
hidden: build?.barcode_hash
hidden: build?.barcode_hash,
onClick: notYetImplemented
}),
UnlinkBarcodeAction({
hidden: !build?.barcode_hash
hidden: !build?.barcode_hash,
onClick: notYetImplemented
})
]}
/>,

@ -37,7 +37,10 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles';
import { companyFields } from '../../forms/CompanyForms';
import { useEditApiFormModal } from '../../hooks/UseForm';
import {
useDeleteApiFormModal,
useEditApiFormModal
} from '../../hooks/UseForm';
import { useInstance } from '../../hooks/UseInstance';
import { useUserState } from '../../states/UserState';
import { AddressTable } from '../../tables/company/AddressTable';
@ -289,6 +292,13 @@ export default function CompanyDetail(props: Readonly<CompanyDetailProps>) {
onFormSuccess: refreshInstance
});
const deleteCompany = useDeleteApiFormModal({
url: ApiEndpoints.company_list,
pk: company?.pk,
title: t`Delete Company`,
onFormSuccess: refreshInstance
});
const companyActions = useMemo(() => {
return [
<AdminButton model={ModelType.company} pk={company.pk} />,
@ -301,7 +311,8 @@ export default function CompanyDetail(props: Readonly<CompanyDetailProps>) {
onClick: () => editCompany.open()
}),
DeleteItemAction({
hidden: !user.hasDeleteRole(UserRoles.purchase_order)
hidden: !user.hasDeleteRole(UserRoles.purchase_order),
onClick: () => deleteCompany.open()
})
]}
/>
@ -321,6 +332,7 @@ export default function CompanyDetail(props: Readonly<CompanyDetailProps>) {
return (
<>
{editCompany.modal}
{deleteCompany.modal}
<InstanceDetail status={requestStatus} loading={instanceQuery.isFetching}>
<Stack gap="xs">
<PageDetail

@ -34,6 +34,7 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles';
import { useSupplierPartFields } from '../../forms/CompanyForms';
import { notYetImplemented } from '../../functions/notifications';
import { getDetailUrl } from '../../functions/urls';
import {
useCreateApiFormModal,
@ -278,12 +279,14 @@ export default function SupplierPartDetail() {
LinkBarcodeAction({
hidden:
supplierPart.barcode_hash ||
!user.hasChangeRole(UserRoles.purchase_order)
!user.hasChangeRole(UserRoles.purchase_order),
onClick: notYetImplemented
}),
UnlinkBarcodeAction({
hidden:
!supplierPart.barcode_hash ||
!user.hasChangeRole(UserRoles.purchase_order)
!user.hasChangeRole(UserRoles.purchase_order),
onClick: notYetImplemented
})
]}
/>,

@ -74,6 +74,7 @@ import {
useTransferStockItem
} from '../../forms/StockForms';
import { InvenTreeIcon } from '../../functions/icons';
import { notYetImplemented } from '../../functions/notifications';
import { getDetailUrl } from '../../functions/urls';
import {
useCreateApiFormModal,
@ -978,10 +979,12 @@ export default function PartDetail() {
pk: part.pk
}),
LinkBarcodeAction({
hidden: part?.barcode_hash || !user.hasChangeRole(UserRoles.part)
hidden: part?.barcode_hash || !user.hasChangeRole(UserRoles.part),
onClick: notYetImplemented
}),
UnlinkBarcodeAction({
hidden: !part?.barcode_hash || !user.hasChangeRole(UserRoles.part)
hidden: !part?.barcode_hash || !user.hasChangeRole(UserRoles.part),
onClick: notYetImplemented
})
]}
key="action_dropdown"

@ -19,7 +19,11 @@ import { apiUrl } from '../../../states/ApiState';
import { useUserState } from '../../../states/UserState';
import { TableColumn } from '../../../tables/Column';
import { InvenTreeTable } from '../../../tables/InvenTreeTable';
import { RowDeleteAction, RowEditAction } from '../../../tables/RowActions';
import {
RowAction,
RowDeleteAction,
RowEditAction
} from '../../../tables/RowActions';
import { NoPricingData } from './PricingPanel';
export default function PriceBreakPanel({
@ -113,7 +117,7 @@ export default function PriceBreakPanel({
}, [user]);
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
return [
RowEditAction({
hidden: !user.hasChangeRole(UserRoles.part),

@ -39,6 +39,7 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles';
import { usePurchaseOrderFields } from '../../forms/PurchaseOrderForms';
import { notYetImplemented } from '../../functions/notifications';
import {
useCreateApiFormModal,
useEditApiFormModal
@ -408,10 +409,12 @@ export default function PurchaseOrderDetail() {
pk: order.pk
}),
LinkBarcodeAction({
hidden: order?.barcode_hash
hidden: order?.barcode_hash,
onClick: notYetImplemented
}),
UnlinkBarcodeAction({
hidden: !order?.barcode_hash
hidden: !order?.barcode_hash,
onClick: notYetImplemented
})
]}
/>,

@ -38,6 +38,7 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles';
import { useReturnOrderFields } from '../../forms/SalesOrderForms';
import { notYetImplemented } from '../../functions/notifications';
import {
useCreateApiFormModal,
useEditApiFormModal
@ -409,10 +410,12 @@ export default function ReturnOrderDetail() {
pk: order.pk
}),
LinkBarcodeAction({
hidden: order?.barcode_hash
hidden: order?.barcode_hash,
onClick: notYetImplemented
}),
UnlinkBarcodeAction({
hidden: !order?.barcode_hash
hidden: !order?.barcode_hash,
onClick: notYetImplemented
})
]}
/>,

@ -41,6 +41,7 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles';
import { useSalesOrderFields } from '../../forms/SalesOrderForms';
import { notYetImplemented } from '../../functions/notifications';
import {
useCreateApiFormModal,
useEditApiFormModal
@ -449,10 +450,12 @@ export default function SalesOrderDetail() {
pk: order.pk
}),
LinkBarcodeAction({
hidden: order?.barcode_hash
hidden: order?.barcode_hash,
onClick: notYetImplemented
}),
UnlinkBarcodeAction({
hidden: !order?.barcode_hash
hidden: !order?.barcode_hash,
onClick: notYetImplemented
})
]}
/>,
@ -467,23 +470,23 @@ export default function SalesOrderDetail() {
actions={[
EditItemAction({
hidden: !canEdit,
onClick: () => editSalesOrder.open(),
onClick: editSalesOrder.open,
tooltip: t`Edit order`
}),
DuplicateItemAction({
hidden: !user.hasAddRole(UserRoles.sales_order),
onClick: () => duplicateSalesOrder.open(),
onClick: duplicateSalesOrder.open,
tooltip: t`Duplicate order`
}),
HoldItemAction({
tooltip: t`Hold order`,
hidden: !canHold,
onClick: () => holdOrder.open()
onClick: holdOrder.open
}),
CancelItemAction({
tooltip: t`Cancel order`,
hidden: !canCancel,
onClick: () => cancelOrder.open()
onClick: cancelOrder.open
})
]}
/>

@ -38,6 +38,7 @@ import {
useTransferStockItem
} from '../../forms/StockForms';
import { InvenTreeIcon } from '../../functions/icons';
import { notYetImplemented } from '../../functions/notifications';
import { getDetailUrl } from '../../functions/urls';
import {
useDeleteApiFormModal,
@ -280,6 +281,7 @@ export default function Stock() {
<AdminButton model={ModelType.stocklocation} pk={location.pk} />,
<ActionButton
icon={<InvenTreeIcon icon="stocktake" />}
onClick={notYetImplemented}
variant="outline"
size="lg"
/>,
@ -290,17 +292,23 @@ export default function Stock() {
model: ModelType.stocklocation,
pk: location.pk
}),
LinkBarcodeAction({}),
UnlinkBarcodeAction({}),
LinkBarcodeAction({
onClick: notYetImplemented
}),
UnlinkBarcodeAction({
onClick: notYetImplemented
}),
{
name: 'Scan in stock items',
icon: <InvenTreeIcon icon="stock" />,
tooltip: 'Scan items'
tooltip: 'Scan items',
onClick: notYetImplemented
},
{
name: 'Scan in container',
icon: <InvenTreeIcon icon="unallocated_stock" />,
tooltip: 'Scan container'
tooltip: 'Scan container',
onClick: notYetImplemented
}
]}
/>

@ -50,6 +50,7 @@ import {
useTransferStockItem
} from '../../forms/StockForms';
import { InvenTreeIcon } from '../../functions/icons';
import { notYetImplemented } from '../../functions/notifications';
import { getDetailUrl } from '../../functions/urls';
import {
useCreateApiFormModal,
@ -483,11 +484,13 @@ export default function StockDetail() {
}),
LinkBarcodeAction({
hidden:
stockitem?.barcode_hash || !user.hasChangeRole(UserRoles.stock)
stockitem?.barcode_hash || !user.hasChangeRole(UserRoles.stock),
onClick: notYetImplemented
}),
UnlinkBarcodeAction({
hidden:
!stockitem?.barcode_hash || !user.hasChangeRole(UserRoles.stock)
!stockitem?.barcode_hash || !user.hasChangeRole(UserRoles.stock),
onClick: notYetImplemented
})
]}
/>,

@ -53,7 +53,6 @@ import { TableFilter } from './Filter';
import { FilterSelectDrawer } from './FilterSelectDrawer';
import { RowAction, RowActions } from './RowActions';
import { TableSearchInput } from './Search';
import { UploadAction } from './UploadAction';
const defaultPageSize: number = 25;
@ -66,7 +65,6 @@ const defaultPageSize: number = 25;
* @param noRecordsText : string - Text to display when no records are found
* @param enableBulkDelete : boolean - Enable bulk deletion of records
* @param enableDownload : boolean - Enable download actions
* @param enableUpload : boolean - Enable upload actions
* @param enableFilters : boolean - Enable filter actions
* @param enableSelection : boolean - Enable row selection
* @param enableSearch : boolean - Enable search actions
@ -92,7 +90,6 @@ export type InvenTreeTableProps<T = any> = {
noRecordsText?: string;
enableBulkDelete?: boolean;
enableDownload?: boolean;
enableUpload?: boolean;
enableFilters?: boolean;
enableSelection?: boolean;
enableSearch?: boolean;
@ -125,7 +122,6 @@ const defaultInvenTreeTableProps: InvenTreeTableProps = {
params: {},
noRecordsText: t`No records found`,
enableDownload: false,
enableUpload: false,
enableLabels: false,
enableReports: false,
enableFilters: true,
@ -607,7 +603,6 @@ export function InvenTreeTable<T = any>({
<Stack gap="sm">
<Group justify="apart" grow wrap="nowrap">
<Group justify="left" key="custom-actions" gap={5} wrap="nowrap">
{tableProps.enableUpload && <UploadAction key="upload-action" />}
<PrintingActions
items={tableState.selectedIds}
modelType={tableProps.modelType}

@ -4,76 +4,45 @@ import { IconCopy, IconDots, IconEdit, IconTrash } from '@tabler/icons-react';
import { ReactNode, useMemo, useState } from 'react';
import { cancelEvent } from '../functions/events';
import { notYetImplemented } from '../functions/notifications';
// Type definition for a table row action
export type RowAction = {
title: string;
title?: string;
tooltip?: string;
color?: string;
icon: ReactNode;
onClick?: () => void;
icon?: ReactNode;
onClick: () => void;
hidden?: boolean;
disabled?: boolean;
};
// Component for duplicating a row in a table
export function RowDuplicateAction({
onClick,
tooltip,
hidden
}: {
onClick?: () => void;
tooltip?: string;
hidden?: boolean;
}): RowAction {
export function RowDuplicateAction(props: RowAction): RowAction {
return {
...props,
title: t`Duplicate`,
color: 'green',
tooltip: tooltip,
onClick: onClick,
icon: <IconCopy />,
hidden: hidden
icon: <IconCopy />
};
}
// Component for editing a row in a table
export function RowEditAction({
onClick,
tooltip,
hidden
}: {
onClick?: () => void;
tooltip?: string;
hidden?: boolean;
}): RowAction {
export function RowEditAction(props: RowAction): RowAction {
return {
...props,
title: t`Edit`,
color: 'blue',
tooltip: tooltip,
onClick: onClick,
icon: <IconEdit />,
hidden: hidden
icon: <IconEdit />
};
}
// Component for deleting a row in a table
export function RowDeleteAction({
onClick,
tooltip,
hidden
}: {
onClick?: () => void;
tooltip?: string;
hidden?: boolean;
}): RowAction {
export function RowDeleteAction(props: RowAction): RowAction {
return {
...props,
title: t`Delete`,
color: 'red',
tooltip: tooltip,
onClick: onClick,
icon: <IconTrash />,
hidden: hidden
icon: <IconTrash />
};
}
@ -120,13 +89,7 @@ export function RowActions({
onClick={(event) => {
// Prevent clicking on the action from selecting the row itself
cancelEvent(event);
if (action.onClick) {
action.onClick();
} else {
notYetImplemented();
}
action.onClick();
setOpened(false);
}}
disabled={action.disabled || false}

@ -1,8 +0,0 @@
import { t } from '@lingui/macro';
import { IconUpload } from '@tabler/icons-react';
import { ActionButton } from '../components/buttons/ActionButton';
export function UploadAction({}) {
return <ActionButton icon={<IconUpload />} tooltip={t`Upload Data`} />;
}

@ -23,6 +23,7 @@ import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles';
import { bomItemFields } from '../../forms/BomForms';
import { dataImporterSessionFields } from '../../forms/ImporterForms';
import { notYetImplemented } from '../../functions/notifications';
import {
useApiFormModal,
useCreateApiFormModal,
@ -41,7 +42,7 @@ import {
} from '../ColumnRenderers';
import { TableFilter } from '../Filter';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowDeleteAction, RowEditAction } from '../RowActions';
import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions';
import { TableHoverCard } from '../TableHoverCard';
// Calculate the total stock quantity available for a given BomItem
@ -454,7 +455,7 @@ export function BomTable({
}, []);
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
// If this BOM item is defined for a *different* parent, then it cannot be edited
if (record.part && record.part != partId) {
return [
@ -488,7 +489,8 @@ export function BomTable({
title: t`Edit Substitutes`,
color: 'blue',
hidden: partLocked || !user.hasChangeRole(UserRoles.part),
icon: <IconSwitch3 />
icon: <IconSwitch3 />,
onClick: notYetImplemented
},
RowDeleteAction({
hidden: partLocked || !user.hasDeleteRole(UserRoles.part),

@ -20,7 +20,7 @@ import {
} from '../ColumnRenderers';
import { TableFilter } from '../Filter';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowDeleteAction, RowEditAction } from '../RowActions';
import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions';
/**
* Render a table of allocated stock for a build.
@ -155,7 +155,7 @@ export default function BuildAllocatedStockTable({
});
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
return [
RowEditAction({
hidden: !user.hasChangeRole(UserRoles.build),

@ -12,6 +12,7 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles';
import { useBuildOrderFields } from '../../forms/BuildForms';
import { notYetImplemented } from '../../functions/notifications';
import { useCreateApiFormModal } from '../../hooks/UseForm';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
@ -20,6 +21,7 @@ import { TableColumn } from '../Column';
import { BooleanColumn, PartColumn } from '../ColumnRenderers';
import { TableFilter } from '../Filter';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowAction } from '../RowActions';
import { TableHoverCard } from '../TableHoverCard';
export default function BuildLineTable({
@ -270,7 +272,7 @@ export default function BuildLineTable({
});
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
let part = record.part_detail ?? {};
// Consumable items have no appropriate actions
@ -295,13 +297,15 @@ export default function BuildLineTable({
icon: <IconArrowRight />,
title: t`Allocate Stock`,
hidden: !canAllocate,
color: 'green'
color: 'green',
onClick: notYetImplemented
},
{
icon: <IconShoppingCart />,
title: t`Order Stock`,
hidden: !canOrder,
color: 'blue'
color: 'blue',
onClick: notYetImplemented
},
{
icon: <IconTool />,

@ -19,6 +19,7 @@ import { TableColumn } from '../Column';
import { LocationColumn } from '../ColumnRenderers';
import { TableFilter } from '../Filter';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowAction } from '../RowActions';
import { TableHoverCard } from '../TableHoverCard';
/**
@ -226,7 +227,7 @@ export default function BuildOrderTestTable({
}, []);
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
return [];
},
[user]

@ -18,6 +18,7 @@ import {
useScrapBuildOutputsForm
} from '../../forms/BuildForms';
import { InvenTreeIcon } from '../../functions/icons';
import { notYetImplemented } from '../../functions/notifications';
import { useCreateApiFormModal } from '../../hooks/UseForm';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
@ -245,19 +246,21 @@ export default function BuildOutputTable({ build }: { build: any }) {
}, [user, table.selectedRecords, table.hasSelectedRecords]);
const rowActions = useCallback(
(record: any) => {
let actions: RowAction[] = [
(record: any): RowAction[] => {
return [
{
title: t`Allocate`,
tooltip: t`Allocate stock to build output`,
color: 'blue',
icon: <InvenTreeIcon icon="plus" />
icon: <InvenTreeIcon icon="plus" />,
onClick: notYetImplemented
},
{
title: t`Deallocate`,
tooltip: t`Deallocate stock from build output`,
color: 'red',
icon: <InvenTreeIcon icon="minus" />
icon: <InvenTreeIcon icon="minus" />,
onClick: notYetImplemented
},
{
title: t`Complete`,
@ -290,8 +293,6 @@ export default function BuildOutputTable({ build }: { build: any }) {
}
}
];
return actions;
},
[user, partId]
);

@ -16,7 +16,7 @@ import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowDeleteAction, RowEditAction } from '../RowActions';
import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions';
export function AddressTable({
companyId,
@ -146,7 +146,7 @@ export function AddressTable({
});
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
let can_edit =
user.hasChangeRole(UserRoles.purchase_order) ||
user.hasChangeRole(UserRoles.sales_order);

@ -19,7 +19,7 @@ import { useUserState } from '../../states/UserState';
import { BooleanColumn, DescriptionColumn } from '../ColumnRenderers';
import { TableFilter } from '../Filter';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowEditAction } from '../RowActions';
import { RowAction, RowEditAction } from '../RowActions';
/**
* A table which displays a list of company records,
@ -128,7 +128,7 @@ export function CompanyTable({
}, [user]);
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
return [
RowEditAction({
hidden:

@ -15,7 +15,7 @@ import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowDeleteAction, RowEditAction } from '../RowActions';
import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions';
export function ContactTable({
companyId,
@ -91,7 +91,7 @@ export function ContactTable({
});
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
let can_edit =
user.hasChangeRole(UserRoles.purchase_order) ||
user.hasChangeRole(UserRoles.sales_order);

@ -28,7 +28,7 @@ import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { TableFilter } from '../Filter';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowDeleteAction, RowEditAction } from '../RowActions';
import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions';
/**
* Define set of columns to display for the attachment table
@ -262,7 +262,7 @@ export function AttachmentTable({
// Construct row actions for the attachment table
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
return [
RowEditAction({
hidden: !user.hasChangePermission(model_type),

@ -18,6 +18,7 @@ import { TableColumn } from '../Column';
import { LinkColumn, NoteColumn } from '../ColumnRenderers';
import { InvenTreeTable } from '../InvenTreeTable';
import {
RowAction,
RowDeleteAction,
RowDuplicateAction,
RowEditAction
@ -107,7 +108,7 @@ export default function ExtraLineItemTable({
});
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
return [
RowEditAction({
hidden: !user.hasChangeRole(role),

@ -20,7 +20,7 @@ import { TableColumn } from '../Column';
import { DescriptionColumn } from '../ColumnRenderers';
import { TableFilter } from '../Filter';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowEditAction } from '../RowActions';
import { RowAction, RowEditAction } from '../RowActions';
/**
* PartCategoryTable - Displays a table of part categories
@ -117,7 +117,7 @@ export function PartCategoryTable({ parentId }: { parentId?: any }) {
}, [user]);
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
let can_edit = user.hasChangeRole(UserRoles.part_category);
return [

@ -17,7 +17,7 @@ import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { TableFilter } from '../Filter';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowDeleteAction, RowEditAction } from '../RowActions';
import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions';
export default function PartCategoryTemplateTable() {
const table = useTable('part-category-parameter-templates');
@ -104,7 +104,7 @@ export default function PartCategoryTemplateTable() {
}, []);
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
return [
RowEditAction({
hidden: !user.hasChangeRole(UserRoles.part),

@ -20,7 +20,7 @@ import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { DescriptionColumn, PartColumn } from '../ColumnRenderers';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowDeleteAction, RowEditAction } from '../RowActions';
import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions';
import { TableHoverCard } from '../TableHoverCard';
/**
@ -140,7 +140,7 @@ export function PartParameterTable({
// Callback for row actions
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
// Actions not allowed for "variant" rows
if (String(partId) != String(record.part)) {
return [];

@ -17,7 +17,7 @@ import { TableColumn } from '../Column';
import { BooleanColumn, DescriptionColumn } from '../ColumnRenderers';
import { TableFilter } from '../Filter';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowDeleteAction, RowEditAction } from '../RowActions';
import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions';
export default function PartParameterTemplateTable() {
const table = useTable('part-parameter-templates');
@ -114,7 +114,7 @@ export default function PartParameterTemplateTable() {
// Callback for row actions
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
return [
RowEditAction({
hidden: !user.hasChangeRole(UserRoles.part),

@ -22,7 +22,7 @@ import { TableColumn } from '../Column';
import { BooleanColumn, DescriptionColumn } from '../ColumnRenderers';
import { TableFilter } from '../Filter';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowDeleteAction, RowEditAction } from '../RowActions';
import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions';
import { TableHoverCard } from '../TableHoverCard';
export default function PartTestTemplateTable({
@ -192,7 +192,7 @@ export default function PartTestTemplateTable({
});
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
const can_edit = user.hasChangeRole(UserRoles.part);
const can_delete = user.hasDeleteRole(UserRoles.part);

@ -17,7 +17,7 @@ import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowDeleteAction } from '../RowActions';
import { RowAction, RowDeleteAction } from '../RowActions';
/**
* Construct a table listing related parts for a given part
@ -111,7 +111,7 @@ export function RelatedPartTable({ partId }: { partId: number }): ReactNode {
}, [user]);
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
return [
RowDeleteAction({
hidden: !user.hasDeleteRole(UserRoles.part),

@ -351,7 +351,7 @@ export default function PluginListTable() {
// Determine available actions for a given plugin
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
// TODO: Plugin actions should be updated based on on the users's permissions
let actions: RowAction[] = [];

@ -15,7 +15,7 @@ import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowDeleteAction, RowEditAction } from '../RowActions';
import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions';
export default function ManufacturerPartParameterTable({
params
@ -80,7 +80,7 @@ export default function ManufacturerPartParameterTable({
});
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
return [
RowEditAction({
hidden: !user.hasChangeRole(UserRoles.purchase_order),

@ -18,7 +18,7 @@ import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { DescriptionColumn, LinkColumn, PartColumn } from '../ColumnRenderers';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowDeleteAction, RowEditAction } from '../RowActions';
import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions';
/*
* Construct a table listing manufacturer parts
@ -108,7 +108,7 @@ export function ManufacturerPartTable({ params }: { params: any }): ReactNode {
}, [user]);
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
return [
RowEditAction({
hidden: !user.hasChangeRole(UserRoles.purchase_order),

@ -37,6 +37,7 @@ import {
} from '../ColumnRenderers';
import { InvenTreeTable } from '../InvenTreeTable';
import {
RowAction,
RowDeleteAction,
RowDuplicateAction,
RowEditAction
@ -290,7 +291,7 @@ export function PurchaseOrderLineItemTable({
}, [order, poStatus]);
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
let received = (record?.received ?? 0) >= (record?.quantity ?? 0);
return [

@ -26,7 +26,7 @@ import {
} from '../ColumnRenderers';
import { TableFilter } from '../Filter';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowDeleteAction, RowEditAction } from '../RowActions';
import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions';
import { TableHoverCard } from '../TableHoverCard';
/*
@ -221,7 +221,7 @@ export function SupplierPartTable({ params }: { params: any }): ReactNode {
// Row action callback
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
return [
RowEditAction({
hidden: !user.hasChangeRole(UserRoles.purchase_order),

@ -20,7 +20,7 @@ import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowDeleteAction, RowEditAction } from '../RowActions';
import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions';
export function calculateSupplierPartUnitPrice(record: any) {
let pack_quantity = record?.part_detail?.pack_quantity_native ?? 1;
@ -175,7 +175,7 @@ export default function SupplierPriceBreakTable({
}, [user]);
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
return [
RowEditAction({
hidden: !user.hasChangeRole(UserRoles.purchase_order),

@ -8,6 +8,7 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles';
import { useReturnOrderLineItemFields } from '../../forms/ReturnOrderForms';
import { notYetImplemented } from '../../functions/notifications';
import {
useCreateApiFormModal,
useDeleteApiFormModal,
@ -27,7 +28,7 @@ import {
} from '../ColumnRenderers';
import { StatusFilterOptions, TableFilter } from '../Filter';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowDeleteAction, RowEditAction } from '../RowActions';
import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions';
export default function ReturnOrderLineItemTable({
orderId,
@ -148,14 +149,15 @@ export default function ReturnOrderLineItemTable({
}, [user, orderId]);
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
const received: boolean = !!record?.received_date;
return [
{
hidden: received || !user.hasChangeRole(UserRoles.return_order),
title: t`Receive Item`,
icon: <IconSquareArrowRight />
icon: <IconSquareArrowRight />,
onClick: notYetImplemented
},
RowEditAction({
hidden: !user.hasChangeRole(UserRoles.return_order),

@ -15,6 +15,7 @@ import {
} from '../ColumnRenderers';
import { TableFilter } from '../Filter';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowAction } from '../RowActions';
export default function SalesOrderAllocationTable({
partId,
@ -102,7 +103,7 @@ export default function SalesOrderAllocationTable({
}, []);
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
return [];
},
[user]

@ -15,6 +15,7 @@ import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles';
import { useBuildOrderFields } from '../../forms/BuildForms';
import { useSalesOrderLineItemFields } from '../../forms/SalesOrderForms';
import { notYetImplemented } from '../../functions/notifications';
import {
useCreateApiFormModal,
useDeleteApiFormModal,
@ -27,6 +28,7 @@ import { TableColumn } from '../Column';
import { DateColumn, LinkColumn, PartColumn } from '../ColumnRenderers';
import { InvenTreeTable } from '../InvenTreeTable';
import {
RowAction,
RowDeleteAction,
RowDuplicateAction,
RowEditAction
@ -248,7 +250,7 @@ export default function SalesOrderLineItemTable({
}, [user, orderId]);
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
const allocated = (record?.allocated ?? 0) > (record?.quantity ?? 0);
return [
@ -259,7 +261,8 @@ export default function SalesOrderLineItemTable({
!user.hasChangeRole(UserRoles.sales_order),
title: t`Allocate stock`,
icon: <IconSquareArrowRight />,
color: 'green'
color: 'green',
onClick: notYetImplemented
},
{
hidden:
@ -285,7 +288,8 @@ export default function SalesOrderLineItemTable({
!record?.part_detail?.purchaseable,
title: t`Order stock`,
icon: <IconShoppingCart />,
color: 'blue'
color: 'blue',
onClick: notYetImplemented
},
RowEditAction({
hidden: !editable || !user.hasChangeRole(UserRoles.sales_order),

@ -6,6 +6,7 @@ import { AddItemButton } from '../../components/buttons/AddItemButton';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { UserRoles } from '../../enums/Roles';
import { useSalesOrderShipmentFields } from '../../forms/SalesOrderForms';
import { notYetImplemented } from '../../functions/notifications';
import {
useCreateApiFormModal,
useDeleteApiFormModal,
@ -18,7 +19,7 @@ import { TableColumn } from '../Column';
import { DateColumn, LinkColumn, NoteColumn } from '../ColumnRenderers';
import { TableFilter } from '../Filter';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowDeleteAction, RowEditAction } from '../RowActions';
import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions';
export default function SalesOrderShipmentTable({
orderId
@ -97,14 +98,15 @@ export default function SalesOrderShipmentTable({
}, []);
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
const shipped: boolean = !!record.shipment_date;
return [
{
hidden: shipped || !user.hasChangeRole(UserRoles.sales_order),
title: t`Complete Shipment`,
icon: <IconTruckDelivery />
icon: <IconTruckDelivery />,
onClick: notYetImplemented
},
RowEditAction({
hidden: !user.hasChangeRole(UserRoles.sales_order),

@ -15,6 +15,7 @@ import { AttachmentLink } from '../../components/items/AttachmentLink';
import { DetailDrawer } from '../../components/nav/DetailDrawer';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { notYetImplemented } from '../../functions/notifications';
import { useFilters } from '../../hooks/UseFilter';
import {
useCreateApiFormModal,
@ -187,8 +188,9 @@ export function TemplateTable({
}
}),
RowDuplicateAction({
hidden: true
hidden: true,
// TODO: Duplicate selected template
onClick: notYetImplemented
}),
RowDeleteAction({
hidden: !user.hasDeletePermission(templateProps.modelType),

@ -16,7 +16,7 @@ import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowDeleteAction, RowEditAction } from '../RowActions';
import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions';
export default function LocationTypesTable() {
const table = useTable('location-types');
@ -81,7 +81,7 @@ export default function LocationTypesTable() {
}, []);
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
return [
RowEditAction({
hidden: !user.hasChangeRole(UserRoles.stock_location),

@ -21,6 +21,7 @@ import {
useTransferStockItem
} from '../../forms/StockForms';
import { InvenTreeIcon } from '../../functions/icons';
import { notYetImplemented } from '../../functions/notifications';
import { useCreateApiFormModal } from '../../hooks/UseForm';
import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState';
@ -506,7 +507,8 @@ export function StockItemTable({
name: t`Order stock`,
icon: <InvenTreeIcon icon="buy" />,
tooltip: t`Order new stock`,
disabled: !can_add_order || !can_change_order
disabled: !can_add_order || !can_change_order,
onClick: notYetImplemented
},
{
name: t`Assign to customer`,

@ -32,7 +32,12 @@ import { TableColumn } from '../Column';
import { DateColumn, DescriptionColumn, NoteColumn } from '../ColumnRenderers';
import { TableFilter } from '../Filter';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowActions, RowDeleteAction, RowEditAction } from '../RowActions';
import {
RowAction,
RowActions,
RowDeleteAction,
RowEditAction
} from '../RowActions';
export default function StockItemTestResultTable({
partId,
@ -301,7 +306,7 @@ export default function StockItemTestResultTable({
);
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
if (record.stock_item != undefined && record.stock_item != itemId) {
// Test results for other stock items cannot be edited
return [];

@ -20,7 +20,7 @@ import { TableColumn } from '../Column';
import { BooleanColumn, DescriptionColumn } from '../ColumnRenderers';
import { TableFilter } from '../Filter';
import { InvenTreeTable } from '../InvenTreeTable';
import { RowEditAction } from '../RowActions';
import { RowAction, RowEditAction } from '../RowActions';
/**
* Stock location table
@ -138,7 +138,7 @@ export function StockLocationTable({ parentId }: { parentId?: any }) {
}, [user]);
const rowActions = useCallback(
(record: any) => {
(record: any): RowAction[] => {
let can_edit = user.hasChangeRole(UserRoles.stock_location);
return [