mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
[PUI] Add Link/Unlink Barcode action (#7939)
* Add Link/Unlink Barcode action Fixes #7920 * remove unneeded imports * remove duplication * simplify * add testing * refactor type * wait for reload to add coverage * Add warning if custom barcode is used
This commit is contained in:
parent
725181be5f
commit
b0c7a1aed5
@ -20,7 +20,7 @@ import { ReactNode, useMemo } from 'react';
|
||||
import { ModelType } from '../../enums/ModelType';
|
||||
import { identifierString } from '../../functions/conversion';
|
||||
import { InvenTreeIcon } from '../../functions/icons';
|
||||
import { InvenTreeQRCode } from './QRCode';
|
||||
import { InvenTreeQRCode, QRCodeLink, QRCodeUnlink } from './QRCode';
|
||||
|
||||
export type ActionDropdownItem = {
|
||||
icon?: ReactNode;
|
||||
@ -112,69 +112,91 @@ export function ActionDropdown({
|
||||
|
||||
// Dropdown menu for barcode actions
|
||||
export function BarcodeActionDropdown({
|
||||
actions
|
||||
}: {
|
||||
actions: ActionDropdownItem[];
|
||||
}) {
|
||||
model,
|
||||
pk,
|
||||
hash = null,
|
||||
actions = [],
|
||||
perm: permission = true
|
||||
}: Readonly<{
|
||||
model: ModelType;
|
||||
pk: number;
|
||||
hash?: boolean | null;
|
||||
actions?: ActionDropdownItem[];
|
||||
perm?: boolean;
|
||||
}>) {
|
||||
const hidden = hash === null;
|
||||
const prop = { model, pk, hash };
|
||||
return (
|
||||
<ActionDropdown
|
||||
tooltip={t`Barcode Actions`}
|
||||
icon={<IconQrcode />}
|
||||
actions={actions}
|
||||
actions={[
|
||||
GeneralBarcodeAction({
|
||||
mdl_prop: prop,
|
||||
title: t`View`,
|
||||
icon: <IconQrcode />,
|
||||
tooltip: t`View barcode`,
|
||||
ChildItem: InvenTreeQRCode
|
||||
}),
|
||||
GeneralBarcodeAction({
|
||||
hidden: hidden || hash || !permission,
|
||||
mdl_prop: prop,
|
||||
title: t`Link Barcode`,
|
||||
icon: <IconLink />,
|
||||
tooltip: t`Link a custom barcode to this item`,
|
||||
ChildItem: QRCodeLink
|
||||
}),
|
||||
GeneralBarcodeAction({
|
||||
hidden: hidden || !hash || !permission,
|
||||
mdl_prop: prop,
|
||||
title: t`Unlink Barcode`,
|
||||
icon: <IconUnlink />,
|
||||
tooltip: t`Unlink custom barcode`,
|
||||
ChildItem: QRCodeUnlink
|
||||
}),
|
||||
...actions
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// Common action button for viewing a barcode
|
||||
export function ViewBarcodeAction({
|
||||
hidden = false,
|
||||
model,
|
||||
pk
|
||||
}: {
|
||||
hidden?: boolean;
|
||||
export type QrCodeType = {
|
||||
model: ModelType;
|
||||
pk: number;
|
||||
hash?: boolean | null;
|
||||
};
|
||||
|
||||
function GeneralBarcodeAction({
|
||||
hidden = false,
|
||||
mdl_prop,
|
||||
title,
|
||||
icon,
|
||||
tooltip,
|
||||
ChildItem
|
||||
}: {
|
||||
hidden?: boolean;
|
||||
mdl_prop: QrCodeType;
|
||||
title: string;
|
||||
icon: ReactNode;
|
||||
tooltip: string;
|
||||
ChildItem: any;
|
||||
}): ActionDropdownItem {
|
||||
const onClick = () => {
|
||||
modals.open({
|
||||
title: t`View Barcode`,
|
||||
children: <InvenTreeQRCode model={model} pk={pk} />
|
||||
title: title,
|
||||
children: <ChildItem mdl_prop={mdl_prop} />
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
icon: <IconQrcode />,
|
||||
name: t`View`,
|
||||
tooltip: t`View barcode`,
|
||||
icon: icon,
|
||||
name: title,
|
||||
tooltip: tooltip,
|
||||
onClick: onClick,
|
||||
hidden: hidden
|
||||
};
|
||||
}
|
||||
|
||||
// Common action button for linking a custom barcode
|
||||
export function LinkBarcodeAction(
|
||||
props: ActionDropdownItem
|
||||
): ActionDropdownItem {
|
||||
return {
|
||||
...props,
|
||||
icon: <IconLink />,
|
||||
name: t`Link Barcode`,
|
||||
tooltip: t`Link custom barcode`
|
||||
};
|
||||
}
|
||||
|
||||
// Common action button for un-linking a custom barcode
|
||||
export function UnlinkBarcodeAction(
|
||||
props: ActionDropdownItem
|
||||
): ActionDropdownItem {
|
||||
return {
|
||||
...props,
|
||||
icon: <IconUnlink />,
|
||||
name: t`Unlink Barcode`,
|
||||
tooltip: t`Unlink custom barcode`
|
||||
};
|
||||
}
|
||||
|
||||
// Common action button for editing an item
|
||||
export function EditItemAction(props: ActionDropdownItem): ActionDropdownItem {
|
||||
return {
|
||||
|
@ -1,24 +1,28 @@
|
||||
import { Trans, t } from '@lingui/macro';
|
||||
import {
|
||||
Alert,
|
||||
Box,
|
||||
Button,
|
||||
Code,
|
||||
Group,
|
||||
Image,
|
||||
Select,
|
||||
Skeleton,
|
||||
Stack,
|
||||
Text
|
||||
Text,
|
||||
TextInput
|
||||
} from '@mantine/core';
|
||||
import { modals } from '@mantine/modals';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import QR from 'qrcode';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { api } from '../../App';
|
||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||
import { ModelType } from '../../enums/ModelType';
|
||||
import { apiUrl } from '../../states/ApiState';
|
||||
import { useGlobalSettingsState } from '../../states/SettingsState';
|
||||
import { CopyButton } from '../buttons/CopyButton';
|
||||
import { QrCodeType } from './ActionDropdown';
|
||||
|
||||
type QRCodeProps = {
|
||||
ecl?: 'L' | 'M' | 'Q' | 'H';
|
||||
@ -51,15 +55,13 @@ export const QRCode = ({ data, ecl = 'Q', margin = 1 }: QRCodeProps) => {
|
||||
};
|
||||
|
||||
type InvenTreeQRCodeProps = {
|
||||
model: ModelType;
|
||||
pk: number;
|
||||
mdl_prop: QrCodeType;
|
||||
showEclSelector?: boolean;
|
||||
} & Omit<QRCodeProps, 'data'>;
|
||||
|
||||
export const InvenTreeQRCode = ({
|
||||
mdl_prop,
|
||||
showEclSelector = true,
|
||||
model,
|
||||
pk,
|
||||
ecl: eclProp = 'Q',
|
||||
...props
|
||||
}: InvenTreeQRCodeProps) => {
|
||||
@ -71,11 +73,11 @@ export const InvenTreeQRCode = ({
|
||||
}, [eclProp]);
|
||||
|
||||
const { data } = useQuery({
|
||||
queryKey: ['qr-code', model, pk],
|
||||
queryKey: ['qr-code', mdl_prop.model, mdl_prop.pk],
|
||||
queryFn: async () => {
|
||||
const res = await api.post(apiUrl(ApiEndpoints.generate_barcode), {
|
||||
model,
|
||||
pk
|
||||
model: mdl_prop.model,
|
||||
pk: mdl_prop.pk
|
||||
});
|
||||
|
||||
return res.data?.barcode as string;
|
||||
@ -94,6 +96,15 @@ export const InvenTreeQRCode = ({
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
{mdl_prop.hash ? (
|
||||
<Alert variant="outline" color="red" title={t`Custom bascode`}>
|
||||
<Trans>
|
||||
A custom barcode is registered for this item. The shown code is not
|
||||
that custom barcode.
|
||||
</Trans>
|
||||
</Alert>
|
||||
) : null}
|
||||
|
||||
<QRCode data={data} ecl={ecl} {...props} />
|
||||
|
||||
{data && settings.getSetting('BARCODE_SHOW_TEXT', 'false') && (
|
||||
@ -128,3 +139,55 @@ export const InvenTreeQRCode = ({
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export const QRCodeLink = ({ mdl_prop }: { mdl_prop: QrCodeType }) => {
|
||||
const [barcode, setBarcode] = useState('');
|
||||
|
||||
function linkBarcode() {
|
||||
api
|
||||
.post(apiUrl(ApiEndpoints.barcode_link), {
|
||||
[mdl_prop.model]: mdl_prop.pk,
|
||||
barcode: barcode
|
||||
})
|
||||
.then((response) => {
|
||||
modals.closeAll();
|
||||
location.reload();
|
||||
});
|
||||
}
|
||||
return (
|
||||
<Box>
|
||||
<TextInput
|
||||
label={t`Barcode`}
|
||||
value={barcode}
|
||||
onChange={(event) => setBarcode(event.currentTarget.value)}
|
||||
placeholder={t`Scan barcode data here using barcode scanner`}
|
||||
/>
|
||||
<Button color="green" onClick={linkBarcode} mt="lg" fullWidth>
|
||||
<Trans>Link</Trans>
|
||||
</Button>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export const QRCodeUnlink = ({ mdl_prop }: { mdl_prop: QrCodeType }) => {
|
||||
function unlinkBarcode() {
|
||||
api
|
||||
.post(apiUrl(ApiEndpoints.barcode_unlink), {
|
||||
[mdl_prop.model]: mdl_prop.pk
|
||||
})
|
||||
.then((response) => {
|
||||
modals.closeAll();
|
||||
location.reload();
|
||||
});
|
||||
}
|
||||
return (
|
||||
<Box>
|
||||
<Text>
|
||||
<Trans>This will remove the link to the associated barcode</Trans>
|
||||
</Text>
|
||||
<Button color="red" onClick={unlinkBarcode}>
|
||||
<Trans>Unlink Barcode</Trans>
|
||||
</Button>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
@ -39,6 +39,8 @@ export enum ApiEndpoints {
|
||||
settings_global_list = 'settings/global/',
|
||||
settings_user_list = 'settings/user/',
|
||||
barcode = 'barcode/',
|
||||
barcode_link = 'barcode/link/',
|
||||
barcode_unlink = 'barcode/unlink/',
|
||||
generate_barcode = 'barcode/generate/',
|
||||
news = 'news/',
|
||||
global_status = 'generic/status/',
|
||||
|
@ -30,10 +30,7 @@ import {
|
||||
CancelItemAction,
|
||||
DuplicateItemAction,
|
||||
EditItemAction,
|
||||
HoldItemAction,
|
||||
LinkBarcodeAction,
|
||||
UnlinkBarcodeAction,
|
||||
ViewBarcodeAction
|
||||
HoldItemAction
|
||||
} from '../../components/items/ActionDropdown';
|
||||
import InstanceDetail from '../../components/nav/InstanceDetail';
|
||||
import { PageDetail } from '../../components/nav/PageDetail';
|
||||
@ -43,7 +40,6 @@ 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
|
||||
@ -472,20 +468,9 @@ export default function BuildDetail() {
|
||||
/>,
|
||||
<AdminButton model={ModelType.build} pk={build.pk} />,
|
||||
<BarcodeActionDropdown
|
||||
actions={[
|
||||
ViewBarcodeAction({
|
||||
model: ModelType.build,
|
||||
pk: build.pk
|
||||
}),
|
||||
LinkBarcodeAction({
|
||||
hidden: build?.barcode_hash,
|
||||
onClick: notYetImplemented
|
||||
}),
|
||||
UnlinkBarcodeAction({
|
||||
hidden: !build?.barcode_hash,
|
||||
onClick: notYetImplemented
|
||||
})
|
||||
]}
|
||||
model={ModelType.build}
|
||||
pk={build.pk}
|
||||
hash={build?.barcode_hash}
|
||||
/>,
|
||||
<PrintingActions
|
||||
modelType={ModelType.build}
|
||||
|
@ -22,10 +22,7 @@ import {
|
||||
BarcodeActionDropdown,
|
||||
DeleteItemAction,
|
||||
DuplicateItemAction,
|
||||
EditItemAction,
|
||||
LinkBarcodeAction,
|
||||
UnlinkBarcodeAction,
|
||||
ViewBarcodeAction
|
||||
EditItemAction
|
||||
} from '../../components/items/ActionDropdown';
|
||||
import InstanceDetail from '../../components/nav/InstanceDetail';
|
||||
import { PageDetail } from '../../components/nav/PageDetail';
|
||||
@ -34,7 +31,6 @@ 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,
|
||||
@ -271,24 +267,10 @@ export default function SupplierPartDetail() {
|
||||
return [
|
||||
<AdminButton model={ModelType.supplierpart} pk={supplierPart.pk} />,
|
||||
<BarcodeActionDropdown
|
||||
actions={[
|
||||
ViewBarcodeAction({
|
||||
model: ModelType.supplierpart,
|
||||
pk: supplierPart.pk
|
||||
}),
|
||||
LinkBarcodeAction({
|
||||
hidden:
|
||||
supplierPart.barcode_hash ||
|
||||
!user.hasChangeRole(UserRoles.purchase_order),
|
||||
onClick: notYetImplemented
|
||||
}),
|
||||
UnlinkBarcodeAction({
|
||||
hidden:
|
||||
!supplierPart.barcode_hash ||
|
||||
!user.hasChangeRole(UserRoles.purchase_order),
|
||||
onClick: notYetImplemented
|
||||
})
|
||||
]}
|
||||
model={ModelType.supplierpart}
|
||||
pk={supplierPart.pk}
|
||||
hash={supplierPart.barcode_hash}
|
||||
perm={user.hasChangeRole(UserRoles.purchase_order)}
|
||||
/>,
|
||||
<ActionDropdown
|
||||
tooltip={t`Supplier Part Actions`}
|
||||
|
@ -51,10 +51,7 @@ import {
|
||||
BarcodeActionDropdown,
|
||||
DeleteItemAction,
|
||||
DuplicateItemAction,
|
||||
EditItemAction,
|
||||
LinkBarcodeAction,
|
||||
UnlinkBarcodeAction,
|
||||
ViewBarcodeAction
|
||||
EditItemAction
|
||||
} from '../../components/items/ActionDropdown';
|
||||
import { PlaceholderPanel } from '../../components/items/Placeholder';
|
||||
import { StylishText } from '../../components/items/StylishText';
|
||||
@ -74,7 +71,6 @@ import {
|
||||
useTransferStockItem
|
||||
} from '../../forms/StockForms';
|
||||
import { InvenTreeIcon } from '../../functions/icons';
|
||||
import { notYetImplemented } from '../../functions/notifications';
|
||||
import { getDetailUrl } from '../../functions/urls';
|
||||
import {
|
||||
useCreateApiFormModal,
|
||||
@ -993,20 +989,10 @@ export default function PartDetail() {
|
||||
return [
|
||||
<AdminButton model={ModelType.part} pk={part.pk} />,
|
||||
<BarcodeActionDropdown
|
||||
actions={[
|
||||
ViewBarcodeAction({
|
||||
model: ModelType.part,
|
||||
pk: part.pk
|
||||
}),
|
||||
LinkBarcodeAction({
|
||||
hidden: part?.barcode_hash || !user.hasChangeRole(UserRoles.part),
|
||||
onClick: notYetImplemented
|
||||
}),
|
||||
UnlinkBarcodeAction({
|
||||
hidden: !part?.barcode_hash || !user.hasChangeRole(UserRoles.part),
|
||||
onClick: notYetImplemented
|
||||
})
|
||||
]}
|
||||
model={ModelType.part}
|
||||
pk={part.pk}
|
||||
hash={part?.barcode_hash}
|
||||
perm={user.hasChangeRole(UserRoles.part)}
|
||||
key="action_dropdown"
|
||||
/>,
|
||||
<PrintingActions
|
||||
|
@ -24,10 +24,7 @@ import {
|
||||
CancelItemAction,
|
||||
DuplicateItemAction,
|
||||
EditItemAction,
|
||||
HoldItemAction,
|
||||
LinkBarcodeAction,
|
||||
UnlinkBarcodeAction,
|
||||
ViewBarcodeAction
|
||||
HoldItemAction
|
||||
} from '../../components/items/ActionDropdown';
|
||||
import { StylishText } from '../../components/items/StylishText';
|
||||
import InstanceDetail from '../../components/nav/InstanceDetail';
|
||||
@ -39,7 +36,6 @@ 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
|
||||
@ -403,20 +399,9 @@ export default function PurchaseOrderDetail() {
|
||||
/>,
|
||||
<AdminButton model={ModelType.purchaseorder} pk={order.pk} />,
|
||||
<BarcodeActionDropdown
|
||||
actions={[
|
||||
ViewBarcodeAction({
|
||||
model: ModelType.purchaseorder,
|
||||
pk: order.pk
|
||||
}),
|
||||
LinkBarcodeAction({
|
||||
hidden: order?.barcode_hash,
|
||||
onClick: notYetImplemented
|
||||
}),
|
||||
UnlinkBarcodeAction({
|
||||
hidden: !order?.barcode_hash,
|
||||
onClick: notYetImplemented
|
||||
})
|
||||
]}
|
||||
model={ModelType.purchaseorder}
|
||||
pk={order.pk}
|
||||
hash={order?.barcode_hash}
|
||||
/>,
|
||||
<PrintingActions
|
||||
modelType={ModelType.purchaseorder}
|
||||
|
@ -23,10 +23,7 @@ import {
|
||||
CancelItemAction,
|
||||
DuplicateItemAction,
|
||||
EditItemAction,
|
||||
HoldItemAction,
|
||||
LinkBarcodeAction,
|
||||
UnlinkBarcodeAction,
|
||||
ViewBarcodeAction
|
||||
HoldItemAction
|
||||
} from '../../components/items/ActionDropdown';
|
||||
import { StylishText } from '../../components/items/StylishText';
|
||||
import InstanceDetail from '../../components/nav/InstanceDetail';
|
||||
@ -38,7 +35,6 @@ 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
|
||||
@ -404,20 +400,9 @@ export default function ReturnOrderDetail() {
|
||||
/>,
|
||||
<AdminButton model={ModelType.returnorder} pk={order.pk} />,
|
||||
<BarcodeActionDropdown
|
||||
actions={[
|
||||
ViewBarcodeAction({
|
||||
model: ModelType.returnorder,
|
||||
pk: order.pk
|
||||
}),
|
||||
LinkBarcodeAction({
|
||||
hidden: order?.barcode_hash,
|
||||
onClick: notYetImplemented
|
||||
}),
|
||||
UnlinkBarcodeAction({
|
||||
hidden: !order?.barcode_hash,
|
||||
onClick: notYetImplemented
|
||||
})
|
||||
]}
|
||||
model={ModelType.returnorder}
|
||||
pk={order.pk}
|
||||
hash={order?.barcode_hash}
|
||||
/>,
|
||||
<PrintingActions
|
||||
modelType={ModelType.returnorder}
|
||||
|
@ -26,10 +26,7 @@ import {
|
||||
CancelItemAction,
|
||||
DuplicateItemAction,
|
||||
EditItemAction,
|
||||
HoldItemAction,
|
||||
LinkBarcodeAction,
|
||||
UnlinkBarcodeAction,
|
||||
ViewBarcodeAction
|
||||
HoldItemAction
|
||||
} from '../../components/items/ActionDropdown';
|
||||
import { StylishText } from '../../components/items/StylishText';
|
||||
import InstanceDetail from '../../components/nav/InstanceDetail';
|
||||
@ -41,7 +38,6 @@ 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
|
||||
@ -444,20 +440,9 @@ export default function SalesOrderDetail() {
|
||||
/>,
|
||||
<AdminButton model={ModelType.salesorder} pk={order.pk} />,
|
||||
<BarcodeActionDropdown
|
||||
actions={[
|
||||
ViewBarcodeAction({
|
||||
model: ModelType.salesorder,
|
||||
pk: order.pk
|
||||
}),
|
||||
LinkBarcodeAction({
|
||||
hidden: order?.barcode_hash,
|
||||
onClick: notYetImplemented
|
||||
}),
|
||||
UnlinkBarcodeAction({
|
||||
hidden: !order?.barcode_hash,
|
||||
onClick: notYetImplemented
|
||||
})
|
||||
]}
|
||||
model={ModelType.salesorder}
|
||||
pk={order.pk}
|
||||
hash={order?.barcode_hash}
|
||||
/>,
|
||||
<PrintingActions
|
||||
modelType={ModelType.salesorder}
|
||||
|
@ -18,10 +18,7 @@ import {
|
||||
ActionDropdown,
|
||||
BarcodeActionDropdown,
|
||||
DeleteItemAction,
|
||||
EditItemAction,
|
||||
LinkBarcodeAction,
|
||||
UnlinkBarcodeAction,
|
||||
ViewBarcodeAction
|
||||
EditItemAction
|
||||
} from '../../components/items/ActionDropdown';
|
||||
import { ApiIcon } from '../../components/items/ApiIcon';
|
||||
import InstanceDetail from '../../components/nav/InstanceDetail';
|
||||
@ -287,17 +284,9 @@ export default function Stock() {
|
||||
/>,
|
||||
location.pk ? (
|
||||
<BarcodeActionDropdown
|
||||
model={ModelType.stocklocation}
|
||||
pk={location.pk}
|
||||
actions={[
|
||||
ViewBarcodeAction({
|
||||
model: ModelType.stocklocation,
|
||||
pk: location.pk
|
||||
}),
|
||||
LinkBarcodeAction({
|
||||
onClick: notYetImplemented
|
||||
}),
|
||||
UnlinkBarcodeAction({
|
||||
onClick: notYetImplemented
|
||||
}),
|
||||
{
|
||||
name: 'Scan in stock items',
|
||||
icon: <InvenTreeIcon icon="stock" />,
|
||||
|
@ -27,10 +27,7 @@ import {
|
||||
BarcodeActionDropdown,
|
||||
DeleteItemAction,
|
||||
DuplicateItemAction,
|
||||
EditItemAction,
|
||||
LinkBarcodeAction,
|
||||
UnlinkBarcodeAction,
|
||||
ViewBarcodeAction
|
||||
EditItemAction
|
||||
} from '../../components/items/ActionDropdown';
|
||||
import { StylishText } from '../../components/items/StylishText';
|
||||
import InstanceDetail from '../../components/nav/InstanceDetail';
|
||||
@ -50,7 +47,6 @@ import {
|
||||
useTransferStockItem
|
||||
} from '../../forms/StockForms';
|
||||
import { InvenTreeIcon } from '../../functions/icons';
|
||||
import { notYetImplemented } from '../../functions/notifications';
|
||||
import { getDetailUrl } from '../../functions/urls';
|
||||
import {
|
||||
useCreateApiFormModal,
|
||||
@ -477,22 +473,10 @@ export default function StockDetail() {
|
||||
() => [
|
||||
<AdminButton model={ModelType.stockitem} pk={stockitem.pk} />,
|
||||
<BarcodeActionDropdown
|
||||
actions={[
|
||||
ViewBarcodeAction({
|
||||
model: ModelType.stockitem,
|
||||
pk: stockitem.pk
|
||||
}),
|
||||
LinkBarcodeAction({
|
||||
hidden:
|
||||
stockitem?.barcode_hash || !user.hasChangeRole(UserRoles.stock),
|
||||
onClick: notYetImplemented
|
||||
}),
|
||||
UnlinkBarcodeAction({
|
||||
hidden:
|
||||
!stockitem?.barcode_hash || !user.hasChangeRole(UserRoles.stock),
|
||||
onClick: notYetImplemented
|
||||
})
|
||||
]}
|
||||
model={ModelType.stockitem}
|
||||
pk={stockitem.pk}
|
||||
hash={stockitem?.barcode_hash}
|
||||
perm={user.hasChangeRole(UserRoles.stock)}
|
||||
/>,
|
||||
<PrintingActions
|
||||
modelType={ModelType.stockitem}
|
||||
|
@ -59,9 +59,36 @@ test('PUI - Purchase Orders', async ({ page }) => {
|
||||
await page.getByRole('cell', { name: 'PO0013' }).click();
|
||||
|
||||
await page.getByRole('button', { name: 'Issue Order' }).waitFor();
|
||||
});
|
||||
|
||||
test('PUI - Purchase Orders - Barcodes', async ({ page }) => {
|
||||
await doQuickLogin(page);
|
||||
|
||||
await page.goto(`${baseUrl}/purchasing/purchase-order/13/detail`);
|
||||
await page.getByRole('button', { name: 'Issue Order' }).waitFor();
|
||||
|
||||
// Display QR code
|
||||
await page.getByLabel('action-menu-barcode-actions').click();
|
||||
await page.getByLabel('action-menu-barcode-actions-view').click();
|
||||
await page.getByRole('img', { name: 'QR Code' }).waitFor();
|
||||
await page.getByRole('banner').getByRole('button').click();
|
||||
|
||||
// Link to barcode
|
||||
await page.getByLabel('action-menu-barcode-actions').click();
|
||||
await page.getByLabel('action-menu-barcode-actions-link-barcode').click();
|
||||
await page.getByRole('heading', { name: 'Link Barcode' }).waitFor();
|
||||
await page
|
||||
.getByPlaceholder('Scan barcode data here using')
|
||||
.fill('1234567890');
|
||||
await page.getByRole('button', { name: 'Link' }).click();
|
||||
await page.getByRole('button', { name: 'Issue Order' }).waitFor();
|
||||
|
||||
// Unlink barcode
|
||||
await page.getByLabel('action-menu-barcode-actions').click();
|
||||
await page.getByLabel('action-menu-barcode-actions-unlink-barcode').click();
|
||||
await page.getByRole('heading', { name: 'Unlink Barcode' }).waitFor();
|
||||
await page.getByText('This will remove the link to').waitFor();
|
||||
await page.getByRole('button', { name: 'Unlink Barcode' }).click();
|
||||
await page.waitForTimeout(500);
|
||||
await page.getByRole('button', { name: 'Issue Order' }).waitFor();
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user