Files
InvenTree/src/frontend/src/components/items/ActionDropdown.tsx
Oliver 767b76314e Revision Improvements (#7585)
* Bump djangorestframework from 3.14.0 to 3.15.2 in /src/backend

Bumps [djangorestframework](https://github.com/encode/django-rest-framework) from 3.14.0 to 3.15.2.
- [Release notes](https://github.com/encode/django-rest-framework/releases)
- [Commits](https://github.com/encode/django-rest-framework/compare/3.14.0...3.15.2)

---
updated-dependencies:
- dependency-name: djangorestframework
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix req

* fix deps again

* patch serializer

* bump api version

* Fix "min_value" for DRF decimal fields

* Add default serializer values for 'IPN' and 'revision'

* Add specific serializer for email field

* Fix API version

* Add 'revision_of' field to Part model

* Add validation checks for new revision_of field

* Update migration

* Add unit test for 'revision' rules

* Add API filters for revision control

* Add table filters for PUI

* Add "revision_of" field to PUI form

* Update part forms for PUI

* Render part revision selection dropdown in PUI

* Prevent refetch on focus

* Ensure select renders above other items

* Disable searching

* Cleanup <PartDetail/>

* UI tweak

* Add setting to control revisions for assemblies

* Hide revision selection drop-down if revisions are not enabled

* Query updates

* Validate entire BOM table from PUI

* Sort revisions

* Fix requirements files

* Fix api_version.py

* Reintroduce previous check for IPN / revision uniqueness

* Set default value for refetchOnWindowFocus (false)

* Revert serializer change

* Further CI fixes

* Further unit test updates

* Fix defaults for query client

* Add docs

* Add link to "revision_of" in CUI

* Add playwright test for revisions

* Ignore notification errors for playwright

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Matthias Mair <code@mjmair.com>
2024-07-12 14:37:32 +10:00

256 lines
5.6 KiB
TypeScript

import { t } from '@lingui/macro';
import {
ActionIcon,
Indicator,
IndicatorProps,
Menu,
Tooltip
} from '@mantine/core';
import {
IconCopy,
IconEdit,
IconLink,
IconQrcode,
IconTrash,
IconUnlink
} from '@tabler/icons-react';
import { ReactNode, useMemo } from 'react';
import { identifierString } from '../../functions/conversion';
import { InvenTreeIcon } from '../../functions/icons';
import { notYetImplemented } from '../../functions/notifications';
export type ActionDropdownItem = {
icon: ReactNode;
name: string;
tooltip?: string;
disabled?: boolean;
hidden?: boolean;
onClick?: () => void;
indicator?: Omit<IndicatorProps, 'children'>;
};
/**
* A simple Menu component which renders a set of actions.
*
* If no "active" actions are provided, the menu will not be rendered
*/
export function ActionDropdown({
icon,
tooltip,
actions,
disabled = false,
hidden = false
}: {
icon: ReactNode;
tooltip: string;
actions: ActionDropdownItem[];
disabled?: boolean;
hidden?: boolean;
}) {
const hasActions = useMemo(() => {
return actions.some((action) => !action.hidden);
}, [actions]);
const indicatorProps = useMemo(() => {
return actions.find((action) => action.indicator);
}, [actions]);
const menuName: string = useMemo(() => {
return identifierString(`action-menu-${tooltip}`);
}, [tooltip]);
return !hidden && hasActions ? (
<Menu position="bottom-end" key={menuName}>
<Indicator disabled={!indicatorProps} {...indicatorProps?.indicator}>
<Menu.Target>
<Tooltip label={tooltip} hidden={!tooltip}>
<ActionIcon
size="lg"
radius="sm"
variant="transparent"
disabled={disabled}
aria-label={menuName}
>
{icon}
</ActionIcon>
</Tooltip>
</Menu.Target>
</Indicator>
<Menu.Dropdown>
{actions.map((action) => {
const id: string = identifierString(`${menuName}-${action.name}`);
return action.hidden ? null : (
<Indicator
disabled={!action.indicator}
{...action.indicator}
key={action.name}
>
<Tooltip label={action.tooltip} hidden={!action.tooltip}>
<Menu.Item
aria-label={id}
leftSection={action.icon}
onClick={() => {
if (action.onClick != undefined) {
action.onClick();
} else {
notYetImplemented();
}
}}
disabled={action.disabled}
>
{action.name}
</Menu.Item>
</Tooltip>
</Indicator>
);
})}
</Menu.Dropdown>
</Menu>
) : null;
}
// Dropdown menu for barcode actions
export function BarcodeActionDropdown({
actions
}: {
actions: ActionDropdownItem[];
}) {
return (
<ActionDropdown
tooltip={t`Barcode Actions`}
icon={<IconQrcode />}
actions={actions}
/>
);
}
// Common action button for viewing a barcode
export function ViewBarcodeAction({
hidden = false,
onClick
}: {
hidden?: boolean;
onClick?: () => void;
}): ActionDropdownItem {
return {
icon: <IconQrcode />,
name: t`View`,
tooltip: t`View barcode`,
onClick: onClick,
hidden: hidden
};
}
// Common action button for linking a custom barcode
export function LinkBarcodeAction({
hidden = false,
onClick
}: {
hidden?: boolean;
onClick?: () => void;
}): ActionDropdownItem {
return {
icon: <IconLink />,
name: t`Link Barcode`,
tooltip: t`Link custom barcode`,
onClick: onClick,
hidden: hidden
};
}
// Common action button for un-linking a custom barcode
export function UnlinkBarcodeAction({
hidden = false,
onClick
}: {
hidden?: boolean;
onClick?: () => void;
}): ActionDropdownItem {
return {
icon: <IconUnlink />,
name: t`Unlink Barcode`,
tooltip: t`Unlink custom barcode`,
onClick: onClick,
hidden: hidden
};
}
// Common action button for editing an item
export function EditItemAction({
hidden = false,
tooltip,
onClick
}: {
hidden?: boolean;
tooltip?: string;
onClick?: () => void;
}): ActionDropdownItem {
return {
icon: <IconEdit color="blue" />,
name: t`Edit`,
tooltip: tooltip ?? `Edit item`,
onClick: onClick,
hidden: hidden
};
}
// 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 {
return {
icon: <IconTrash color="red" />,
name: t`Delete`,
tooltip: tooltip ?? t`Delete item`,
onClick: onClick,
hidden: hidden,
disabled: disabled
};
}
export function CancelItemAction({
hidden = false,
tooltip,
onClick
}: {
hidden?: boolean;
tooltip?: string;
onClick?: () => void;
}): ActionDropdownItem {
return {
icon: <InvenTreeIcon icon="cancel" iconProps={{ color: 'red' }} />,
name: t`Cancel`,
tooltip: tooltip ?? t`Cancel`,
onClick: onClick,
hidden: hidden
};
}
// Common action button for duplicating an item
export function DuplicateItemAction({
hidden = false,
tooltip,
onClick
}: {
hidden?: boolean;
tooltip?: string;
onClick?: () => void;
}): ActionDropdownItem {
return {
icon: <IconCopy color="green" />,
name: t`Duplicate`,
tooltip: tooltip ?? t`Duplicate item`,
onClick: onClick,
hidden: hidden
};
}