2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-05-04 06:18:48 +00:00

Enable "link" column for tables (#6765)

- Have to handle click events cleverly
This commit is contained in:
Oliver 2024-03-20 23:00:09 +11:00 committed by GitHub
parent 0cb4e8ec1c
commit 7227670142
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 54 additions and 33 deletions

View File

@ -17,6 +17,7 @@ import { useMemo, useState } from 'react';
import { api } from '../../App'; import { api } from '../../App';
import { UserRoles } from '../../enums/Roles'; import { UserRoles } from '../../enums/Roles';
import { cancelEvent } from '../../functions/events';
import { InvenTreeIcon } from '../../functions/icons'; import { InvenTreeIcon } from '../../functions/icons';
import { useUserState } from '../../states/UserState'; import { useUserState } from '../../states/UserState';
import { PartThumbTable } from '../../tables/part/PartThumbTable'; import { PartThumbTable } from '../../tables/part/PartThumbTable';
@ -267,9 +268,8 @@ function ImageActionButtons({
size="lg" size="lg"
tooltipAlignment="top" tooltipAlignment="top"
onClick={(event: any) => { onClick={(event: any) => {
event?.preventDefault(); cancelEvent(event);
event?.stopPropagation();
event?.nativeEvent?.stopImmediatePropagation();
modals.open({ modals.open({
title: <StylishText size="xl">{t`Select Image`}</StylishText>, title: <StylishText size="xl">{t`Select Image`}</StylishText>,
size: 'xxl', size: 'xxl',
@ -288,9 +288,7 @@ function ImageActionButtons({
size="lg" size="lg"
tooltipAlignment="top" tooltipAlignment="top"
onClick={(event: any) => { onClick={(event: any) => {
event?.preventDefault(); cancelEvent(event);
event?.stopPropagation();
event?.nativeEvent?.stopImmediatePropagation();
modals.open({ modals.open({
title: <StylishText size="xl">{t`Upload Image`}</StylishText>, title: <StylishText size="xl">{t`Upload Image`}</StylishText>,
children: ( children: (
@ -310,9 +308,7 @@ function ImageActionButtons({
size="lg" size="lg"
tooltipAlignment="top" tooltipAlignment="top"
onClick={(event: any) => { onClick={(event: any) => {
event?.preventDefault(); cancelEvent(event);
event?.stopPropagation();
event?.nativeEvent?.stopImmediatePropagation();
removeModal(apiPath, setImage); removeModal(apiPath, setImage);
}} }}
/> />
@ -349,9 +345,7 @@ export function DetailsImage(props: DetailImageProps) {
}, [props.imageActions]); }, [props.imageActions]);
const expandImage = (event: any) => { const expandImage = (event: any) => {
event?.preventDefault(); cancelEvent(event);
event?.stopPropagation();
event?.nativeEvent?.stopImmediatePropagation();
modals.open({ modals.open({
children: <ApiImage src={img} />, children: <ApiImage src={img} />,
withCloseButton: false withCloseButton: false

View File

@ -0,0 +1,6 @@
// Helper function to cancel event propagation
export function cancelEvent(event: any) {
event?.preventDefault();
event?.stopPropagation();
event?.nativeEvent?.stopImmediatePropagation();
}

View File

@ -2,6 +2,7 @@
* Common rendering functions for table column data. * Common rendering functions for table column data.
*/ */
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import { Anchor } from '@mantine/core';
import { Thumbnail } from '../components/images/Thumbnail'; import { Thumbnail } from '../components/images/Thumbnail';
import { ProgressBar } from '../components/items/ProgressBar'; import { ProgressBar } from '../components/items/ProgressBar';
@ -10,6 +11,7 @@ import { TableStatusRenderer } from '../components/render/StatusRenderer';
import { RenderOwner } from '../components/render/User'; import { RenderOwner } from '../components/render/User';
import { formatCurrency, renderDate } from '../defaults/formatters'; import { formatCurrency, renderDate } from '../defaults/formatters';
import { ModelType } from '../enums/ModelType'; import { ModelType } from '../enums/ModelType';
import { cancelEvent } from '../functions/events';
import { TableColumn } from './Column'; import { TableColumn } from './Column';
import { ProjectCodeHoverCard } from './TableHoverCard'; import { ProjectCodeHoverCard } from './TableHoverCard';
@ -55,11 +57,36 @@ export function DescriptionColumn({
}; };
} }
export function LinkColumn(): TableColumn { export function LinkColumn({
accessor = 'link'
}: {
accessor?: string;
}): TableColumn {
return { return {
accessor: 'link', accessor: accessor,
sortable: false sortable: false,
// TODO: Custom URL hyperlink renderer? render: (record: any) => {
let url = record[accessor];
if (!url) {
return '-';
}
return (
<Anchor
href={url}
target="_blank"
rel="noreferrer noopener"
onClick={(event: any) => {
cancelEvent(event);
window.open(url, '_blank', 'noopener,noreferrer');
}}
>
{url}
</Anchor>
);
}
}; };
} }

View File

@ -4,6 +4,7 @@ import { Menu } from '@mantine/core';
import { IconCopy, IconDots, IconEdit, IconTrash } from '@tabler/icons-react'; import { IconCopy, IconDots, IconEdit, IconTrash } from '@tabler/icons-react';
import { ReactNode, useMemo, useState } from 'react'; import { ReactNode, useMemo, useState } from 'react';
import { cancelEvent } from '../functions/events';
import { notYetImplemented } from '../functions/notifications'; import { notYetImplemented } from '../functions/notifications';
// Type definition for a table row action // Type definition for a table row action
@ -93,9 +94,7 @@ export function RowActions({
// Prevent default event handling // Prevent default event handling
// Ref: https://icflorescu.github.io/mantine-datatable/examples/links-or-buttons-inside-clickable-rows-or-cells // Ref: https://icflorescu.github.io/mantine-datatable/examples/links-or-buttons-inside-clickable-rows-or-cells
function openMenu(event: any) { function openMenu(event: any) {
event?.preventDefault(); cancelEvent(event);
event?.stopPropagation();
event?.nativeEvent?.stopImmediatePropagation();
setOpened(!opened); setOpened(!opened);
} }
@ -118,9 +117,7 @@ export function RowActions({
icon={action.icon} icon={action.icon}
onClick={(event) => { onClick={(event) => {
// Prevent clicking on the action from selecting the row itself // Prevent clicking on the action from selecting the row itself
event?.preventDefault(); cancelEvent(event);
event?.stopPropagation();
event?.nativeEvent?.stopImmediatePropagation();
if (action.onClick) { if (action.onClick) {
action.onClick(); action.onClick();

View File

@ -11,6 +11,7 @@ import { YesNoButton } from '../../components/items/YesNoButton';
import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType'; import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles'; import { UserRoles } from '../../enums/Roles';
import { cancelEvent } from '../../functions/events';
import { import {
useCreateApiFormModal, useCreateApiFormModal,
useEditApiFormModal useEditApiFormModal
@ -60,9 +61,7 @@ function ParameterCell({
} }
const handleClick = useCallback((event: any) => { const handleClick = useCallback((event: any) => {
event?.preventDefault(); cancelEvent(event);
event?.stopPropagation();
event?.nativeEvent?.stopImmediatePropagation();
onEdit(); onEdit();
}, []); }, []);

View File

@ -162,7 +162,7 @@ function partTableColumns(): TableColumn[] {
render: (record: any) => render: (record: any) =>
formatPriceRange(record.pricing_min, record.pricing_max) formatPriceRange(record.pricing_min, record.pricing_max)
}, },
LinkColumn() LinkColumn({})
]; ];
} }

View File

@ -54,7 +54,7 @@ export function ManufacturerPartTable({ params }: { params: any }): ReactNode {
sortable: true sortable: true
}, },
DescriptionColumn({}), DescriptionColumn({}),
LinkColumn() LinkColumn({})
]; ];
}, [params]); }, [params]);

View File

@ -26,6 +26,7 @@ import { useUserState } from '../../states/UserState';
import { import {
CurrencyColumn, CurrencyColumn,
LinkColumn, LinkColumn,
NoteColumn,
ReferenceColumn, ReferenceColumn,
TargetDateColumn, TargetDateColumn,
TotalPriceColumn TotalPriceColumn
@ -177,11 +178,8 @@ export function PurchaseOrderLineItemTable({
? RenderStockLocation({ instance: record.destination_detail }) ? RenderStockLocation({ instance: record.destination_detail })
: '-' : '-'
}, },
{ NoteColumn(),
accessor: 'notes', LinkColumn({})
title: t`Notes`
},
LinkColumn()
]; ];
}, [orderId, user]); }, [orderId, user]);

View File

@ -122,7 +122,7 @@ export function SupplierPartTable({ params }: { params: any }): ReactNode {
); );
} }
}, },
LinkColumn(), LinkColumn({}),
NoteColumn(), NoteColumn(),
{ {
accessor: 'available', accessor: 'available',