Skip to content

Commit

Permalink
fix(dashboard): Cleanup unsafe accesses to possibly undefined values …
Browse files Browse the repository at this point in the history
…in order timeline (#10454)

**What**
- Fixes an unsafe access to a field that may be undefined if an order was created through a custom workflow.
  • Loading branch information
kasperkristensen authored Dec 5, 2024
1 parent a7ad809 commit 2b455b1
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 76 deletions.
5 changes: 5 additions & 0 deletions .changeset/spicy-carrots-itch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@medusajs/dashboard": patch
---

fix(dashboard): Cleanup unsafe accesses to possibly undefined values in order timeline
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { Button, IconButton, Text, Tooltip, clx, usePrompt } from "@medusajs/ui"
import { Button, Text, Tooltip, clx, usePrompt } from "@medusajs/ui"
import * as Collapsible from "@radix-ui/react-collapsible"

import { PropsWithChildren, ReactNode, useMemo, useState } from "react"
import { Link } from "react-router-dom"

import { XMarkMini } from "@medusajs/icons"
import {
AdminClaim,
AdminExchange,
Expand All @@ -16,6 +14,7 @@ import {
import { useTranslation } from "react-i18next"

import { AdminOrderLineItem } from "@medusajs/types"
import { By } from "../../../../../components/common/user-link"
import {
useCancelOrderTransfer,
useCustomer,
Expand All @@ -29,12 +28,11 @@ import {
} from "../../../../../hooks/api/exchanges"
import { useCancelReturn, useReturns } from "../../../../../hooks/api/returns"
import { useDate } from "../../../../../hooks/use-date"
import { getFormattedAddress } from "../../../../../lib/addresses"
import { getStylizedAmount } from "../../../../../lib/money-amount-helpers"
import { getPaymentsFromOrder } from "../order-payment-section"
import ActivityItems from "./activity-items"
import { By, UserLink } from "../../../../../components/common/user-link"
import ChangeDetailsTooltip from "./change-details-tooltip"
import { getFormattedAddress } from "../../../../../lib/addresses"

type OrderTimelineProps = {
order: AdminOrder
Expand Down Expand Up @@ -394,12 +392,12 @@ const useActivityItems = (order: AdminOrder): Activity[] => {
edit.status === "requested"
? edit.requested_at
: edit.status === "confirmed"
? edit.confirmed_at
: edit.status === "declined"
? edit.declined_at
: edit.status === "canceled"
? edit.canceled_at
: edit.created_at,
? edit.confirmed_at
: edit.status === "declined"
? edit.declined_at
: edit.status === "canceled"
? edit.canceled_at
: edit.created_at,
children: isConfirmed ? <OrderEditBody edit={edit} /> : null,
})
}
Expand Down Expand Up @@ -455,7 +453,7 @@ const useActivityItems = (order: AdminOrder): Activity[] => {
),
timestamp: update.created_at,
children: (
<div className="mt-2 flex text-sm gap-x-2 text-ui-fg-subtle">
<div className="text-ui-fg-subtle mt-2 flex gap-x-2 text-sm">
{t("fields.by")} <By id={update.created_by} />
</div>
),
Expand All @@ -477,7 +475,7 @@ const useActivityItems = (order: AdminOrder): Activity[] => {
),
timestamp: update.created_at,
children: (
<div className="mt-2 flex text-sm gap-x-2 text-ui-fg-subtle">
<div className="text-ui-fg-subtle mt-2 flex gap-x-2 text-sm">
{t("fields.by")} <By id={update.created_by} />
</div>
),
Expand All @@ -495,7 +493,7 @@ const useActivityItems = (order: AdminOrder): Activity[] => {
),
timestamp: update.created_at,
children: (
<div className="mt-2 flex text-sm gap-x-2 text-ui-fg-subtle">
<div className="text-ui-fg-subtle mt-2 flex gap-x-2 text-sm">
{t("fields.by")} <By id={update.created_by} />
</div>
),
Expand Down Expand Up @@ -674,64 +672,67 @@ const OrderActivityCollapsible = ({
)
}

const NoteBody = ({ note }: { note: Note }) => {
const { t } = useTranslation()
const prompt = usePrompt()

const { first_name, last_name, email } = note.author || {}
const name = [first_name, last_name].filter(Boolean).join(" ")

const byLine = t("orders.activity.events.note.byLine", {
author: name || email,
})

const { mutateAsync } = {} // useAdminDeleteNote(note.id)

const handleDelete = async () => {
const res = await prompt({
title: t("general.areYouSure"),
description: "This action cannot be undone",
confirmText: t("actions.delete"),
cancelText: t("actions.cancel"),
})

if (!res) {
return
}

await mutateAsync()
}

return (
<div className="flex flex-col gap-y-2 pt-2">
<div className="bg-ui-bg-component shadow-borders-base group grid grid-cols-[1fr_20px] items-start gap-x-2 text-pretty rounded-r-2xl rounded-bl-md rounded-tl-xl px-3 py-1.5">
<div className="flex h-full min-h-7 items-center">
<Text size="xsmall" className="text-ui-fg-subtle">
{note.value}
</Text>
</div>
<IconButton
size="small"
variant="transparent"
className="transition-fg invisible opacity-0 group-hover:visible group-hover:opacity-100"
type="button"
onClick={handleDelete}
>
<span className="sr-only">
{t("orders.activity.comment.deleteButtonText")}
</span>
<XMarkMini className="text-ui-fg-muted" />
</IconButton>
</div>
<Link
to={`/settings/users/${note.author_id}`}
className="text-ui-fg-subtle hover:text-ui-fg-base transition-fg w-fit"
>
<Text size="small">{byLine}</Text>
</Link>
</div>
)
}
/**
* TODO: Add once notes are supported.
*/
// const NoteBody = ({ note }: { note: Note }) => {
// const { t } = useTranslation()
// const prompt = usePrompt()

// const { first_name, last_name, email } = note.author || {}
// const name = [first_name, last_name].filter(Boolean).join(" ")

// const byLine = t("orders.activity.events.note.byLine", {
// author: name || email,
// })

// const { mutateAsync } = {} // useAdminDeleteNote(note.id)

// const handleDelete = async () => {
// const res = await prompt({
// title: t("general.areYouSure"),
// description: "This action cannot be undone",
// confirmText: t("actions.delete"),
// cancelText: t("actions.cancel"),
// })

// if (!res) {
// return
// }

// await mutateAsync()
// }

// return (
// <div className="flex flex-col gap-y-2 pt-2">
// <div className="bg-ui-bg-component shadow-borders-base group grid grid-cols-[1fr_20px] items-start gap-x-2 text-pretty rounded-r-2xl rounded-bl-md rounded-tl-xl px-3 py-1.5">
// <div className="flex h-full min-h-7 items-center">
// <Text size="xsmall" className="text-ui-fg-subtle">
// {note.value}
// </Text>
// </div>
// <IconButton
// size="small"
// variant="transparent"
// className="transition-fg invisible opacity-0 group-hover:visible group-hover:opacity-100"
// type="button"
// onClick={handleDelete}
// >
// <span className="sr-only">
// {t("orders.activity.comment.deleteButtonText")}
// </span>
// <XMarkMini className="text-ui-fg-muted" />
// </IconButton>
// </div>
// <Link
// to={`/settings/users/${note.author_id}`}
// className="text-ui-fg-subtle hover:text-ui-fg-base transition-fg w-fit"
// >
// <Text size="small">{byLine}</Text>
// </Link>
// </div>
// )
// }

const FulfillmentCreatedBody = ({
fulfillment,
Expand Down Expand Up @@ -1085,11 +1086,15 @@ function getMissingLineItemIds(order: AdminOrder, changes: AdminOrderChange[]) {

changes.forEach((change) => {
change.actions.forEach((action) => {
if (!action.details?.reference_id) {
return
}

if (
(action.details!.reference_id as string).startsWith("ordli_") &&
!existingItemsMap.has(action.details!.reference_id as string)
(action.details.reference_id as string).startsWith("ordli_") &&
!existingItemsMap.has(action.details.reference_id as string)
) {
retIds.add(action.details!.reference_id as string)
retIds.add(action.details.reference_id as string)
}
})
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

import { RouteFocusModal } from "../../../components/modals"
import { CreateShippingProfileForm } from "./components/create-shipping-profile-form"

Expand Down

0 comments on commit 2b455b1

Please sign in to comment.