diff --git a/.changeset/sixty-lions-impress.md b/.changeset/sixty-lions-impress.md new file mode 100644 index 00000000000..83d75632f82 --- /dev/null +++ b/.changeset/sixty-lions-impress.md @@ -0,0 +1,5 @@ +--- +"saleor-dashboard": patch +--- + +You can now hover over each row in product datagrid and hover effect will be fast and smooth diff --git a/src/collections/components/CollectionListDatagrid/datagrid.ts b/src/collections/components/CollectionListDatagrid/datagrid.ts index c02423415f1..2b9881fa19b 100644 --- a/src/collections/components/CollectionListDatagrid/datagrid.ts +++ b/src/collections/components/CollectionListDatagrid/datagrid.ts @@ -93,6 +93,7 @@ export const createGetCellContent = ], [label], { + cursor: "pointer", readonly: true, allowOverlay: false, }, diff --git a/src/components/Datagrid/Datagrid.tsx b/src/components/Datagrid/Datagrid.tsx index a254f341c15..071acc0c75a 100644 --- a/src/components/Datagrid/Datagrid.tsx +++ b/src/components/Datagrid/Datagrid.tsx @@ -1,6 +1,5 @@ import "@glideapps/glide-data-grid/dist/index.css"; -import { getAppMountUri } from "@dashboard/config"; import useNavigator from "@dashboard/hooks/useNavigator"; import { usePreventHistoryBack } from "@dashboard/hooks/usePreventHistoryBack"; import DataEditor, { @@ -10,7 +9,6 @@ import DataEditor, { EditableGridCell, GridCell, GridColumn, - GridMouseEventArgs, GridSelection, HeaderClickedEventArgs, Item, @@ -46,6 +44,8 @@ import useDatagridChange, { } from "./hooks/useDatagridChange"; import { useFullScreenMode } from "./hooks/useFullScreenMode"; import { usePortalClasses } from "./hooks/usePortalClasses"; +import { useRowAnchor } from "./hooks/useRowAnchor"; +import { useRowHover } from "./hooks/useRowHover"; import { useScrollRight } from "./hooks/useScrollRight"; import { useTooltipContainer } from "./hooks/useTooltipContainer"; import useStyles, { @@ -144,8 +144,6 @@ export const Datagrid: React.FC = ({ const datagridTheme = useDatagridTheme(readonly, readonly); const editor = useRef(null); const customRenderers = useCustomCellRenderers(); - - const hackARef = useRef(null); const navigate = useNavigator(); const { scrolledToRight, scroller } = useScrollRight(); @@ -156,9 +154,18 @@ export const Datagrid: React.FC = ({ const { clearTooltip, tooltip, setTooltip } = useTooltipContainer(); const [selection, setSelection] = useState(); - const [hoverRow, setHoverRow] = useState(undefined); const [areCellsDirty, setCellsDirty] = useState(true); + const { rowAnchorRef, setRowAnchorRef, setAnchorPosition } = useRowAnchor({ + getRowAnchorUrl: rowAnchor, + rowMarkers, + }); + + const { handleRowHover, hoverRow } = useRowHover({ + hasRowHover, + onRowHover: setAnchorPosition, + }); + // Allow to listen to which row is selected and notfiy parent component useEffect(() => { if (onRowSelectionChange && selection) { @@ -275,40 +282,6 @@ export const Datagrid: React.FC = ({ [onCellEdited, availableColumns], ); - const handleRowHover = useCallback( - (args: GridMouseEventArgs) => { - if (hasRowHover) { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const [_, row] = args.location; - setHoverRow(args.kind !== "cell" ? undefined : row); - } - - // the code below is responsible for adding native element when hovering over rows in the datagrid - // this makes it possible to open links in a new tab and copy them - if (args.kind !== "cell" || !hackARef.current || !rowAnchor) { - return; - } - const href = rowAnchor(args.location); - - if (!href) { - return; - } - - if (preventRowClickOnSelectionCheckbox(rowMarkers, args.location[0])) { - return; - } - - hackARef.current.style.left = `${window.scrollX + args.bounds.x}px`; - hackARef.current.style.width = `${args.bounds.width}px`; - hackARef.current.style.top = `${window.scrollY + args.bounds.y}px`; - hackARef.current.style.height = `${args.bounds.height}px`; - hackARef.current.href = - getAppMountUri() + (href.startsWith("/") ? href.slice(1) : href); - hackARef.current.dataset.reactRouterPath = href; - }, - [hasRowHover, rowAnchor, rowMarkers], - ); - const handleCellClick = useCallback( (item: Item, args: CellClickedEventArgs) => { if (preventRowClickOnSelectionCheckbox(rowMarkers, item[0])) { @@ -321,11 +294,11 @@ export const Datagrid: React.FC = ({ handleRowHover(args); - if (hackARef.current) { - hackARef.current.click(); + if (rowAnchorRef.current) { + rowAnchorRef.current.click(); } }, - [rowMarkers, onRowClick, handleRowHover], + [rowMarkers, onRowClick, handleRowHover, rowAnchorRef], ); const handleGridSelectionChange = (gridSelection: GridSelection) => { @@ -438,17 +411,17 @@ export const Datagrid: React.FC = ({ clearTimeout(timer); } - if (hackARef.current) { - hackARef.current.style.display = "none"; + if (rowAnchorRef.current) { + rowAnchorRef.current.style.display = "none"; } timer = setTimeout(() => { - if (hackARef.current) { - hackARef.current.style.display = "block"; + if (rowAnchorRef.current) { + rowAnchorRef.current.style.display = "block"; } }, 100); }; })(), - [hackARef], + [rowAnchorRef], ); if (loading) { @@ -611,7 +584,7 @@ export const Datagrid: React.FC = ({ /> {rowAnchor && ( ; -export const dateCellRenderer = (locale: Locale): CustomRenderer => ({ - kind: GridCellKind.Custom, - isMatch: (c): c is DateCell => (c.data as any).kind === "date-cell", - draw: (args, cell) => { - const { ctx, theme, rect } = args; - const { value } = cell.data; - - if (value === numberCellEmptyValue) return; - - const date = new Date(value); - - if (isNaN(date?.getTime())) { - // invalid date object - return; - } - - const dateFormats = { - full: new Intl.DateTimeFormat(locale, { - dateStyle: "full", - }).format(date), - long: new Intl.DateTimeFormat(locale, { - dateStyle: "long", - }).format(date), - short: new Intl.DateTimeFormat(locale, { - dateStyle: "short", - }).format(date), - }; - - const time = new Intl.DateTimeFormat(locale, { - timeStyle: "short", - }).format(date); - - ctx.textAlign = "left"; - let justifyToRight = true; - - const candidateFormats = [ - { - format: dateFormats.full, - width: ctx.measureText(`${dateFormats.full} ${time}`).width, - }, - { - format: dateFormats.long, - width: ctx.measureText(`${dateFormats.long} ${time}`).width, - }, - { - format: dateFormats.short, - width: ctx.measureText(`${dateFormats.short} ${time}`).width, - }, - ]; - - const cellWidth = rect.width - theme.cellHorizontalPadding * 2; - let displayDate: string | undefined = dateFormats.full; - - if (cellWidth < candidateFormats[0].width) { - displayDate = candidateFormats.find( - format => format.width <= cellWidth, - )?.format; - if (!displayDate) { - displayDate = dateFormats.short; - justifyToRight = false; +interface DateFormaters { + full: Intl.DateTimeFormat; + long: Intl.DateTimeFormat; + short: Intl.DateTimeFormat; +} + +export const dateCellRenderer = (locale: Locale): CustomRenderer => { + const dateFormaters: DateFormaters = { + full: new Intl.DateTimeFormat(locale, { + dateStyle: "full", + }), + long: new Intl.DateTimeFormat(locale, { + dateStyle: "long", + }), + short: new Intl.DateTimeFormat(locale, { + dateStyle: "short", + }), + }; + + const timeFromater = new Intl.DateTimeFormat(locale, { + timeStyle: "short", + }); + + return { + kind: GridCellKind.Custom, + isMatch: (c): c is DateCell => (c.data as any).kind === "date-cell", + draw: (args, cell) => { + const { ctx, theme, rect } = args; + const { value } = cell.data; + + if (value === numberCellEmptyValue) return; + + const date = new Date(value); + + if (isNaN(date?.getTime())) { + // invalid date object + return; } - } - - ctx.fillStyle = theme.textDark; - - ctx.fillText( - displayDate, - rect.x + theme.cellHorizontalPadding, - rect.y + rect.height / 2 + getMiddleCenterBias(ctx, theme), - ); - - ctx.fillStyle = theme.textLight; - ctx.textAlign = justifyToRight ? "right" : "left"; - ctx.fillText( - time, - justifyToRight - ? rect.x + rect.width - theme.cellHorizontalPadding - : rect.x + - theme.cellHorizontalPadding + - ctx.measureText(displayDate).width + - 5, - rect.y + rect.height / 2 + getMiddleCenterBias(ctx, theme), - ); - - return true; - }, -}); + + const cellWidth = getCellWidth(rect, theme); + const textY = getCellMiddleY(ctx, rect, theme); + const textXStart = getCellX(rect, theme); + + const displayTime = timeFromater.format(date); + + const { displayDate, justifyToRight } = formatDate({ + date, + formaters: dateFormaters, + time: displayTime, + ctx, + cellWidth, + }); + + drawText({ + ctx, + text: displayDate, + x: textXStart, + y: textY, + align: "left", + color: theme.textDark, + }); + + const dateTextXEnd = textXStart + ctx.measureText(displayDate).width; + + drawText({ + ctx, + text: displayTime, + x: calculateTimeX({ rect, theme, justifyToRight, dateTextXEnd }), + y: textY, + align: justifyToRight ? "right" : "left", + color: theme.textLight, + }); + + return true; + }, + }; +}; + +function formatDate({ + cellWidth, + ctx, + date, + formaters, + time, +}: { + date: Date; + formaters: DateFormaters; + time: string; + ctx: CanvasRenderingContext2D; + cellWidth: number; +}): { displayDate: string; justifyToRight: boolean } { + const fullFormater = formaters.full.format(date); + const longFormater = formaters.long.format(date); + const shortFormater = formaters.short.format(date); + + if (cellWidth >= getTextWidth(ctx, fullFormater, time)) { + return { displayDate: fullFormater, justifyToRight: true }; + } + + const candidateFormats = [ + { + format: longFormater, + width: getTextWidth(ctx, longFormater, time), + }, + { + format: shortFormater, + width: getTextWidth(ctx, shortFormater, time), + }, + ]; + + const displayFormat = candidateFormats.find( + format => format.width <= cellWidth, + )?.format; + + if (!displayFormat) { + return { displayDate: shortFormater, justifyToRight: false }; + } + + return { displayDate: displayFormat, justifyToRight: true }; +} + +function drawText({ + align, + color, + ctx, + text, + x, + y, +}: { + ctx: CanvasRenderingContext2D; + text: string; + x: number; + y: number; + align: CanvasTextAlign; + color: string; +}) { + ctx.fillStyle = color; + ctx.textAlign = align; + ctx.fillText(text, x, y); +} + +function getCellMiddleY( + ctx: CanvasRenderingContext2D, + rect: Rectangle, + theme: Theme, +) { + const bias = getMiddleCenterBias(ctx, theme); + + return rect.y + rect.height / 2 + bias; +} + +function getCellWidth(rect: Rectangle, theme: Theme) { + return rect.width - theme.cellHorizontalPadding * 2; +} + +function getCellX(rect: Rectangle, theme: Theme) { + return rect.x + theme.cellHorizontalPadding; +} + +function getTextWidth( + ctx: CanvasRenderingContext2D, + date: string, + time: string, +) { + return ctx.measureText(`${date} ${time}`).width; +} + +function calculateTimeX({ + rect, + justifyToRight, + theme, + dateTextXEnd, +}: { + rect: Rectangle; + theme: Theme; + justifyToRight: boolean; + dateTextXEnd: number; +}) { + if (justifyToRight) { + return rect.x + rect.width - theme.cellHorizontalPadding; + } + + return dateTextXEnd + 5; +} diff --git a/src/components/Datagrid/customCells/ThumbnailCell.tsx b/src/components/Datagrid/customCells/ThumbnailCell.tsx index 14971c780ea..bd09ad34134 100644 --- a/src/components/Datagrid/customCells/ThumbnailCell.tsx +++ b/src/components/Datagrid/customCells/ThumbnailCell.tsx @@ -34,22 +34,20 @@ export const thumbnailCellRenderer: CustomRenderer = { ctx.save(); if (imageResult !== undefined && image) { - ctx.save(); roundedImage(ctx, drawX, drawY, size, size, 4); ctx.strokeStyle = theme.borderColor; ctx.stroke(); ctx.clip(); ctx.drawImage(imageResult, drawX, drawY, size, size); - ctx.restore(); } else { - ctx.save(); ctx.beginPath(); roundedImage(ctx, drawX, drawY, size, size, 4); ctx.fillStyle = theme.borderColor; ctx.fill(); - ctx.restore(); } + ctx.restore(); + if (name !== undefined) { ctx.fillStyle = theme.textDark; ctx.fillText( @@ -59,8 +57,6 @@ export const thumbnailCellRenderer: CustomRenderer = { ); } - ctx.restore(); - return true; }, diff --git a/src/components/Datagrid/hooks/useRowAnchor.ts b/src/components/Datagrid/hooks/useRowAnchor.ts new file mode 100644 index 00000000000..6ba052ce4cb --- /dev/null +++ b/src/components/Datagrid/hooks/useRowAnchor.ts @@ -0,0 +1,59 @@ +import { getAppMountUri } from "@dashboard/config"; +import useDebounce from "@dashboard/hooks/useDebounce"; +import { + DataEditorProps, + GridMouseEventArgs, + Item, +} from "@glideapps/glide-data-grid"; +import { useCallback, useRef } from "react"; + +import { preventRowClickOnSelectionCheckbox } from "../utils"; + +const DEBOUNCE_TIME = 100; + +export const useRowAnchor = ({ + getRowAnchorUrl, + rowMarkers, +}: { + getRowAnchorUrl?: (item: Item) => string; + rowMarkers?: DataEditorProps["rowMarkers"]; +}) => { + const rowAnchorRef = useRef(null); + + const setRowAnchorRef = useCallback((element: HTMLAnchorElement) => { + rowAnchorRef.current = element; + }, []); + + const setAnchorPosition = useCallback( + useDebounce((args: GridMouseEventArgs) => { + if (args.kind !== "cell" || !rowAnchorRef.current || !getRowAnchorUrl) { + return; + } + + const href = getRowAnchorUrl(args.location); + + if (!href) { + return; + } + + if (preventRowClickOnSelectionCheckbox(rowMarkers, args.location[0])) { + return; + } + + rowAnchorRef.current.style.left = `${window.scrollX + args.bounds.x}px`; + rowAnchorRef.current.style.width = `${args.bounds.width}px`; + rowAnchorRef.current.style.top = `${window.scrollY + args.bounds.y}px`; + rowAnchorRef.current.style.height = `${args.bounds.height}px`; + rowAnchorRef.current.href = + getAppMountUri() + (href.startsWith("/") ? href.slice(1) : href); + rowAnchorRef.current.dataset.reactRouterPath = href; + }, DEBOUNCE_TIME), + [getRowAnchorUrl, rowMarkers], + ); + + return { + rowAnchorRef, + setRowAnchorRef, + setAnchorPosition, + }; +}; diff --git a/src/components/Datagrid/hooks/useRowHover.ts b/src/components/Datagrid/hooks/useRowHover.ts new file mode 100644 index 00000000000..3e5e96172cf --- /dev/null +++ b/src/components/Datagrid/hooks/useRowHover.ts @@ -0,0 +1,31 @@ +import { GridMouseEventArgs } from "@glideapps/glide-data-grid"; +import { useCallback, useState } from "react"; + +export const useRowHover = ({ + hasRowHover, + onRowHover, +}: { + hasRowHover?: boolean; + onRowHover?: (args: GridMouseEventArgs) => void; +}) => { + const [hoverRow, setHoverRow] = useState(undefined); + + const handleRowHover = useCallback( + (args: GridMouseEventArgs) => { + if (hasRowHover) { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [_, row] = args.location; + + setHoverRow(args.kind !== "cell" ? undefined : row); + } + + onRowHover?.(args); + }, + [hasRowHover, onRowHover], + ); + + return { + hoverRow, + handleRowHover, + }; +}; diff --git a/src/discounts/components/DiscountListDatagrid/datagrid.ts b/src/discounts/components/DiscountListDatagrid/datagrid.ts index c3a6ab54bbb..d34ae660b4b 100644 --- a/src/discounts/components/DiscountListDatagrid/datagrid.ts +++ b/src/discounts/components/DiscountListDatagrid/datagrid.ts @@ -45,6 +45,8 @@ export const dicountListStaticColumnsAdapter = ( icon: getColumnSortDirectionIcon(sort, column.id), })); +const COMMON_CELL_PROPS: Partial = { cursor: "pointer" }; + export const createGetCellContent = ({ promotions, @@ -68,11 +70,11 @@ export const createGetCellContent = return readonlyTextCell(rowData.name); case "startDate": return rowData.startDate - ? dateCell(rowData.startDate) + ? dateCell(rowData.startDate, COMMON_CELL_PROPS) : readonlyTextCell(PLACEHOLDER); case "endDate": return rowData.endDate - ? dateCell(rowData.endDate) + ? dateCell(rowData.endDate, COMMON_CELL_PROPS) : readonlyTextCell(PLACEHOLDER); case "type": return readonlyTextCell(getDiscountType(rowData, intl)); diff --git a/src/discounts/components/VoucherListDatagrid/datagrid.ts b/src/discounts/components/VoucherListDatagrid/datagrid.ts index c0634e5d520..5fd07f7500c 100644 --- a/src/discounts/components/VoucherListDatagrid/datagrid.ts +++ b/src/discounts/components/VoucherListDatagrid/datagrid.ts @@ -90,6 +90,7 @@ export const createGetCellContent = channel?.minSpent?.amount ?? null, channel?.minSpent?.currency ?? "", { + cursor: "pointer", readonly: true, }, ) @@ -134,6 +135,7 @@ function getVoucherValueCell( if (voucher?.discountValueType === "FIXED") { return moneyCell(channel?.discountValue, channel?.currency ?? "", { + cursor: "pointer", readonly: true, }); } diff --git a/src/giftCards/GiftCardsList/GiftCardsListDatagrid/datagrid.ts b/src/giftCards/GiftCardsList/GiftCardsListDatagrid/datagrid.ts index 7ad50472875..30f933d31c2 100644 --- a/src/giftCards/GiftCardsList/GiftCardsListDatagrid/datagrid.ts +++ b/src/giftCards/GiftCardsList/GiftCardsListDatagrid/datagrid.ts @@ -61,6 +61,8 @@ export const getColumns = ( icon: sort ? getColumnSortDirectionIcon(sort, column.id) : undefined, })); +const COMMON_CELL_PROPS: Partial = { cursor: "pointer" }; + export const createGetCellContent = ( categories: Array< @@ -104,6 +106,7 @@ export const createGetCellContent = }, ], [intl.formatMessage(messages.active)], + COMMON_CELL_PROPS, ); } @@ -119,6 +122,7 @@ export const createGetCellContent = }, ], [statusLabel], + COMMON_CELL_PROPS, ); } case "tag": @@ -137,6 +141,7 @@ export const createGetCellContent = return moneyCell( rowData.currentBalance.amount, rowData.currentBalance.currency, + COMMON_CELL_PROPS, ); default: return readonlyTextCell("", false); diff --git a/src/orders/components/OrderDraftListDatagrid/datagrid.ts b/src/orders/components/OrderDraftListDatagrid/datagrid.ts index e63ee29fb3f..973622df63d 100644 --- a/src/orders/components/OrderDraftListDatagrid/datagrid.ts +++ b/src/orders/components/OrderDraftListDatagrid/datagrid.ts @@ -75,6 +75,7 @@ export const createGetCellContent = rowData.total?.gross?.amount ?? 0, rowData.total?.gross?.currency ?? "", { + cursor: "pointer", readonly: true, }, ); diff --git a/src/orders/components/OrderListDatagrid/datagrid.ts b/src/orders/components/OrderListDatagrid/datagrid.ts index 593dd97e070..15f9ffe05d0 100644 --- a/src/orders/components/OrderListDatagrid/datagrid.ts +++ b/src/orders/components/OrderListDatagrid/datagrid.ts @@ -111,10 +111,12 @@ export const useGetCellContent = ({ columns, orders }: GetCellContentProps) => { }; }; +const COMMON_CELL_PROPS: Partial = { cursor: "pointer" }; + export function getDateCellContent( rowData: RelayToFlat[number], ) { - return dateCell(rowData?.created); + return dateCell(rowData?.created, COMMON_CELL_PROPS); } export function getCustomerCellContent( @@ -145,7 +147,8 @@ export function getStatusCellContent( status: orderStatus.status, currentTheme, }); - return pillCell(orderStatus.localized, color); + + return pillCell(orderStatus.localized, color, COMMON_CELL_PROPS); } return readonlyTextCell("-"); @@ -163,7 +166,8 @@ export function getPaymentCellContent( status: paymentStatus.status, currentTheme, }); - return pillCell(paymentStatus.localized, color); + + return pillCell(paymentStatus.localized, color, COMMON_CELL_PROPS); } return readonlyTextCell("-"); @@ -173,9 +177,11 @@ export function getTotalCellContent( rowData: RelayToFlat[number], ) { if (rowData?.total?.gross) { - return moneyCell(rowData.total.gross.amount, rowData.total.gross.currency, { - cursor: "pointer", - }); + return moneyCell( + rowData.total.gross.amount, + rowData.total.gross.currency, + COMMON_CELL_PROPS, + ); } return readonlyTextCell("-"); diff --git a/src/pages/components/PageListDatagrid/datagrid.ts b/src/pages/components/PageListDatagrid/datagrid.ts index fb947644693..0b8d3ff8693 100644 --- a/src/pages/components/PageListDatagrid/datagrid.ts +++ b/src/pages/components/PageListDatagrid/datagrid.ts @@ -80,6 +80,7 @@ export const createGetCellContent = }, ], [tag], + { cursor: "pointer" }, ); } default: diff --git a/src/products/components/ProductListDatagrid/datagrid.ts b/src/products/components/ProductListDatagrid/datagrid.ts index 24490db7c13..24f51e0823a 100644 --- a/src/products/components/ProductListDatagrid/datagrid.ts +++ b/src/products/components/ProductListDatagrid/datagrid.ts @@ -37,7 +37,7 @@ import { ProductListUrlSortField } from "@dashboard/products/urls"; import { RelayToFlat, Sort } from "@dashboard/types"; import { getColumnSortDirectionIcon } from "@dashboard/utils/columns/getColumnSortDirectionIcon"; import { mapEdgesToItems } from "@dashboard/utils/maps"; -import { Item } from "@glideapps/glide-data-grid"; +import { GridCell, Item } from "@glideapps/glide-data-grid"; import { DefaultTheme } from "@saleor/macaw-ui-next"; import { IntlShape } from "react-intl"; @@ -228,10 +228,12 @@ export function createGetCellContent({ }; } +const COMMON_CELL_PROPS: Partial = { cursor: "pointer" }; + function getDateCellContent( rowData: RelayToFlat[number], ) { - return dateCell(rowData?.updatedAt); + return dateCell(rowData?.updatedAt, COMMON_CELL_PROPS); } function getProductTypeCellContent( theme: DefaultTheme, @@ -242,7 +244,8 @@ function getProductTypeCellContent( theme === "defaultDark" ? hueToPillColorDark(hue) : hueToPillColorLight(hue); - return pillCell(rowData.productType?.name, color); + + return pillCell(rowData.productType?.name, color, COMMON_CELL_PROPS); } function getCategoryCellContent( @@ -250,7 +253,7 @@ function getCategoryCellContent( rowData: RelayToFlat[number], ) { if (!rowData.category) { - return readonlyTextCell("-"); + return readonlyTextCell("-", true); } const hue = stringToHue(rowData.category?.name); @@ -258,7 +261,8 @@ function getCategoryCellContent( theme === "defaultDark" ? hueToPillColorDark(hue) : hueToPillColorLight(hue); - return pillCell(rowData.category?.name, color); + + return pillCell(rowData.category?.name, color, COMMON_CELL_PROPS); } function getCollectionsCellContent( @@ -266,7 +270,7 @@ function getCollectionsCellContent( rowData: RelayToFlat[number], ) { if (rowData.collections === undefined || rowData.collections.length === 0) { - return readonlyTextCell("-"); + return readonlyTextCell("-", true); } const tags = rowData.collections.map(collection => { @@ -284,7 +288,7 @@ function getCollectionsCellContent( tags, tags.map(tag => tag.tag), { - readonly: true, + ...COMMON_CELL_PROPS, allowOverlay: false, }, ); @@ -301,6 +305,7 @@ function getAvailabilityCellContent( return statusCell( getChannelAvailabilityStatus(selectedChannnel), intl.formatMessage(getChannelAvailabilityLabel(selectedChannnel)), + COMMON_CELL_PROPS, ); } @@ -310,9 +315,14 @@ function getAvailabilityCellContent( intl.formatMessage(messages.dropdownLabel, { channelCount: rowData?.channelListings?.length, }), + COMMON_CELL_PROPS, ); } else { - return statusCell("error", intl.formatMessage(messages.noChannels)); + return statusCell( + "error", + intl.formatMessage(messages.noChannels), + COMMON_CELL_PROPS, + ); } } @@ -324,10 +334,10 @@ function getDescriptionCellContent( const value = change ?? rowData?.[columnId] ?? ""; if (!value) { - return readonlyTextCell(""); + return readonlyTextCell("", true); } - return readonlyTextCell(getDescriptionValue(value)); + return readonlyTextCell(getDescriptionValue(value), true); } function getNameCellContent( @@ -335,9 +345,8 @@ function getNameCellContent( rowData: RelayToFlat[number], ) { const name = change?.name ?? rowData?.name ?? ""; - return thumbnailCell(name, rowData?.thumbnail?.url ?? "", { - cursor: "pointer", - }); + + return thumbnailCell(name, rowData?.thumbnail?.url ?? "", COMMON_CELL_PROPS); } function getPriceCellContent( @@ -351,7 +360,9 @@ function getPriceCellContent( const price = from?.amount === to?.amount ? from?.amount : [from?.amount, to?.amount]; - return from ? moneyCell(price, from?.currency || "") : readonlyTextCell("–"); + return from + ? moneyCell(price, from?.currency || "", COMMON_CELL_PROPS) + : readonlyTextCell("–", true); } function getAttributeCellContent( diff --git a/src/staff/components/StaffListDatagrid/datagrid.ts b/src/staff/components/StaffListDatagrid/datagrid.ts index 985e12b493f..0256003c925 100644 --- a/src/staff/components/StaffListDatagrid/datagrid.ts +++ b/src/staff/components/StaffListDatagrid/datagrid.ts @@ -95,6 +95,7 @@ export const createGetCellContent = { readonly: true, allowOverlay: false, + cursor: "pointer", }, ); }