From f831b7db372389925bb4ee4612411d7a83e2f911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frane=20Poli=C4=87?= <16856471+fPolic@users.noreply.github.com> Date: Tue, 21 Mar 2023 16:13:39 +0100 Subject: [PATCH] fix(admin-ui): show failure reason for batch jobs (#3526) * fix: display error messages for batch jobs * feat: add changesets * feat: tooltip size, load more jobs --------- Co-authored-by: fPolic Co-authored-by: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com> --- .changeset/thirty-shrimps-fly.md | 5 ++ .../temp/price-list-import-template.csv | 3 + .../public/temp/product-import-template.csv | 6 ++ .../ui/src/components/atoms/tooltip/index.tsx | 4 +- .../molecules/batch-job-file-card/index.tsx | 37 +++++++- .../batch-jobs-activity-list/index.tsx | 13 ++- .../organisms/upload-modal/index.tsx | 90 +++++++++++-------- .../src/domain/products/batch-job/import.tsx | 4 +- .../ui/src/providers/polling-provider.tsx | 2 +- 9 files changed, 117 insertions(+), 47 deletions(-) create mode 100644 .changeset/thirty-shrimps-fly.md create mode 100644 packages/admin-ui/ui/public/temp/price-list-import-template.csv create mode 100644 packages/admin-ui/ui/public/temp/product-import-template.csv diff --git a/.changeset/thirty-shrimps-fly.md b/.changeset/thirty-shrimps-fly.md new file mode 100644 index 0000000000..75dafd7424 --- /dev/null +++ b/.changeset/thirty-shrimps-fly.md @@ -0,0 +1,5 @@ +--- +"@medusajs/admin-ui": patch +--- + +fix(admin-ui): display error messages for batch jobs diff --git a/packages/admin-ui/ui/public/temp/price-list-import-template.csv b/packages/admin-ui/ui/public/temp/price-list-import-template.csv new file mode 100644 index 0000000000..bc812524a2 --- /dev/null +++ b/packages/admin-ui/ui/public/temp/price-list-import-template.csv @@ -0,0 +1,3 @@ +Product Variant ID,SKU,Price EUR,Price NA [USD] +,MEDUSA-SWEAT-SMALL,15,13.5 +variant_1234,,15,13.5 diff --git a/packages/admin-ui/ui/public/temp/product-import-template.csv b/packages/admin-ui/ui/public/temp/product-import-template.csv new file mode 100644 index 0000000000..9804745c2f --- /dev/null +++ b/packages/admin-ui/ui/public/temp/product-import-template.csv @@ -0,0 +1,6 @@ +Product Id;Product Handle;Product Title;Product Subtitle;Product Description;Product Status;Product Thumbnail;Product Weight;Product Length;Product Width;Product Height;Product HS Code;Product Origin Country;Product MID Code;Product Material;Product Collection Title;Product Collection Handle;Product Type;Product Tags;Product Discountable;Product External Id;Product Profile Name;Product Profile Type;Variant Id;Variant Title;Variant SKU;Variant Barcode;Variant Inventory Quantity;Variant Allow Backorder;Variant Manage Inventory;Variant Weight;Variant Length;Variant Width;Variant Height;Variant HS Code;Variant Origin Country;Variant MID Code;Variant Material;Price EUR;Price USD;Option 1 Name;Option 1 Value;Image 1 Url;Image 2 Url +;coffee-mug-v2;Medusa Coffee Mug;;Every programmer's best friend.;published;https://medusa-public-images.s3.eu-west-1.amazonaws.com/coffee-mug.png;400;;;;;;;;;;;;true;;;;;One Size;;;100;false;true;;;;;;;;;1000;1200;Size;One Size;https://medusa-public-images.s3.eu-west-1.amazonaws.com/coffee-mug.png; +;sweatpants-v2;Medusa Sweatpants;;Reimagine the feeling of classic sweatpants. With our cotton sweatpants, everyday essentials no longer have to be ordinary.;published;https://medusa-public-images.s3.eu-west-1.amazonaws.com/sweatpants-gray-front.png;400;;;;;;;;;;;;true;;;;;S;;;100;false;true;;;;;;;;;2950;3350;Size;S;https://medusa-public-images.s3.eu-west-1.amazonaws.com/sweatpants-gray-front.png;https://medusa-public-images.s3.eu-west-1.amazonaws.com/sweatpants-gray-back.png +;sweatpants-v2;Medusa Sweatpants;;Reimagine the feeling of classic sweatpants. With our cotton sweatpants, everyday essentials no longer have to be ordinary.;published;https://medusa-public-images.s3.eu-west-1.amazonaws.com/sweatpants-gray-front.png;400;;;;;;;;;;;;true;;;;;M;;;100;false;true;;;;;;;;;2950;3350;Size;M;https://medusa-public-images.s3.eu-west-1.amazonaws.com/sweatpants-gray-front.png;https://medusa-public-images.s3.eu-west-1.amazonaws.com/sweatpants-gray-back.png +;sweatpants-v2;Medusa Sweatpants;;Reimagine the feeling of classic sweatpants. With our cotton sweatpants, everyday essentials no longer have to be ordinary.;published;https://medusa-public-images.s3.eu-west-1.amazonaws.com/sweatpants-gray-front.png;400;;;;;;;;;;;;true;;;;;L;;;100;false;true;;;;;;;;;2950;3350;Size;L;https://medusa-public-images.s3.eu-west-1.amazonaws.com/sweatpants-gray-front.png;https://medusa-public-images.s3.eu-west-1.amazonaws.com/sweatpants-gray-back.png +;sweatpants-v2;Medusa Sweatpants;;Reimagine the feeling of classic sweatpants. With our cotton sweatpants, everyday essentials no longer have to be ordinary.;published;https://medusa-public-images.s3.eu-west-1.amazonaws.com/sweatpants-gray-front.png;400;;;;;;;;;;;;true;;;;;XL;;;100;false;true;;;;;;;;;2950;3350;Size;XL;https://medusa-public-images.s3.eu-west-1.amazonaws.com/sweatpants-gray-front.png;https://medusa-public-images.s3.eu-west-1.amazonaws.com/sweatpants-gray-back.png diff --git a/packages/admin-ui/ui/src/components/atoms/tooltip/index.tsx b/packages/admin-ui/ui/src/components/atoms/tooltip/index.tsx index 898169afcd..a279a817c4 100644 --- a/packages/admin-ui/ui/src/components/atoms/tooltip/index.tsx +++ b/packages/admin-ui/ui/src/components/atoms/tooltip/index.tsx @@ -10,6 +10,7 @@ export type TooltipProps = RadixTooltip.TooltipContentProps & content: React.ReactNode side?: "bottom" | "left" | "top" | "right" onClick?: React.ButtonHTMLAttributes["onClick"] + maxWidth?: number } const Tooltip = ({ @@ -19,6 +20,7 @@ const Tooltip = ({ defaultOpen, onOpenChange, delayDuration, + maxWidth = 220, className, side, onClick, @@ -43,10 +45,10 @@ const Tooltip = ({ "inter-small-semibold text-grey-50", "bg-grey-0 shadow-dropdown rounded-rounded py-2 px-3", "border-grey-20 border border-solid", - "max-w-[220px]", className )} {...props} + style={{ ...props.style, maxWidth }} > {content} diff --git a/packages/admin-ui/ui/src/components/molecules/batch-job-file-card/index.tsx b/packages/admin-ui/ui/src/components/molecules/batch-job-file-card/index.tsx index f643393ca9..6b0530552c 100644 --- a/packages/admin-ui/ui/src/components/molecules/batch-job-file-card/index.tsx +++ b/packages/admin-ui/ui/src/components/molecules/batch-job-file-card/index.tsx @@ -1,13 +1,25 @@ import { ReactNode } from "react" +import clsx from "clsx" + +import Tooltip from "../../atoms/tooltip" type Props = { fileName: string fileSize?: string + errorMessage?: string + hasError?: boolean icon?: ReactNode onClick?: () => void } -const BatchJobFileCard = ({ fileName, fileSize, icon, onClick }: Props) => { +const BatchJobFileCard = ({ + fileName, + fileSize, + icon, + onClick, + hasError, + errorMessage, +}: Props) => { const preparedOnClick = onClick ?? (() => void 0) return ( @@ -27,9 +39,26 @@ const BatchJobFileCard = ({ fileName, fileSize, icon, onClick }: Props) => { {fileName} - {!!fileSize && ( -
{fileSize}
- )} + {errorMessage} + ) : null + } + > + {!!fileSize && ( +
+ {fileSize} +
+ )} +
) diff --git a/packages/admin-ui/ui/src/components/organisms/batch-jobs-activity-list/index.tsx b/packages/admin-ui/ui/src/components/organisms/batch-jobs-activity-list/index.tsx index 2643d91298..4bdc7689dd 100644 --- a/packages/admin-ui/ui/src/components/organisms/batch-jobs-activity-list/index.tsx +++ b/packages/admin-ui/ui/src/components/organisms/batch-jobs-activity-list/index.tsx @@ -19,6 +19,7 @@ import MedusaIcon from "../../fundamentals/icons/medusa-icon" import { ActivityCard } from "../../molecules/activity-card" import BatchJobFileCard from "../../molecules/batch-job-file-card" import { batchJobDescriptionBuilder, BatchJobOperation } from "./utils" +import CrossIcon from "../../fundamentals/icons/cross-icon" /** * Retrieve a batch job and refresh the data depending on the last batch job status @@ -97,6 +98,8 @@ const BatchJobActivityCard = (props: { batchJob: BatchJob }) => { batchJob.status !== "failed" && batchJob.status !== "canceled" + const hasError = batchJob.status === "failed" + const canDownload = batchJob.status === "completed" && batchJob.result?.file_key @@ -157,7 +160,11 @@ const BatchJobActivityCard = (props: { batchJob: BatchJob }) => { const icon = batchJob.status !== "completed" && batchJob.status !== "canceled" ? ( - + batchJob.status === "failed" ? ( + + ) : ( + + ) ) : ( { preprocessing: `Preparing ${operation.toLowerCase()}...`, processing: `Processing ${operation.toLowerCase()}...`, completed: `Successful ${operation.toLowerCase()}`, - failed: `Failed batch ${operation.toLowerCase()} job`, + failed: `Job failed`, canceled: `Canceled batch ${operation.toLowerCase()} job`, }[batchJob.status] @@ -185,6 +192,8 @@ const BatchJobActivityCard = (props: { batchJob: BatchJob }) => { fileName={fileName} icon={icon} fileSize={fileSize} + hasError={hasError} + errorMessage={batchJob?.result?.errors?.join(" \n")} /> ) } diff --git a/packages/admin-ui/ui/src/components/organisms/upload-modal/index.tsx b/packages/admin-ui/ui/src/components/organisms/upload-modal/index.tsx index f196007a22..0cbdbd94ff 100644 --- a/packages/admin-ui/ui/src/components/organisms/upload-modal/index.tsx +++ b/packages/admin-ui/ui/src/components/organisms/upload-modal/index.tsx @@ -1,4 +1,5 @@ import { ReactNode, useState } from "react" +import clsx from "clsx" import Button from "../../fundamentals/button" import CheckCircleIcon from "../../fundamentals/icons/check-circle-icon" @@ -8,12 +9,13 @@ import FileIcon from "../../fundamentals/icons/file-icon" import Modal from "../../molecules/modal" import TrashIcon from "../../fundamentals/icons/trash-icon" import WarningCircleIcon from "../../fundamentals/icons/warning-circle" -import XCircleIcon from "../../fundamentals/icons/x-circle-icon" -import clsx from "clsx" +import Tooltip from "../../atoms/tooltip" type FileSummaryProps = { name: string size: number + hasError?: boolean + errorMessage?: string action: ReactNode progress?: number status?: string @@ -23,7 +25,7 @@ type FileSummaryProps = { * Render an upload file summary (& upload progress). */ function FileSummary(props: FileSummaryProps) { - const { action, name, progress, size, status } = props + const { action, name, progress, size, status, hasError, errorMessage } = props const formattedSize = size / 1024 < 10 @@ -32,32 +34,46 @@ function FileSummary(props: FileSummaryProps) { return (
-
-
-
- -
- -
-
{name}
-
- {status || formattedSize} + {errorMessage} + ) : null + } + > +
+
+
+
-
-
{action}
-
+
+
{name}
+
+ {status || formattedSize} +
+
+ +
{action}
+
+
) } type UploadSummaryProps = { - creations: number - updates: number - rejections?: number + creations?: number + updates?: number type: string } @@ -65,25 +81,18 @@ type UploadSummaryProps = { * Render a batch update request summary. */ function UploadSummary(props: UploadSummaryProps) { - const { creations, updates, rejections, type } = props + const { creations, updates, type } = props return (
- {creations}  new {type} + {creations || 0}  new{" "} + {type} +
+
+ + {updates || 0}  updates
- {updates && ( -
- - {updates}  updates -
- )} - {rejections && ( -
- - {rejections}  rejections -
- )}
) } @@ -155,6 +164,8 @@ function DropArea(props: DropAreaProps) { type UploadModalProps = { type: string status?: string + hasError?: boolean + errorMessage?: string fileTitle: string description1Text: string description2Title: string @@ -184,8 +195,9 @@ function UploadModal(props: UploadModalProps) { onSubmit, onFileRemove, templateLink, - progress, summary, + hasError, + errorMessage, status, type, } = props @@ -237,6 +249,8 @@ function UploadModal(props: UploadModalProps) { size={size!} name={name!} status={status} + hasError={hasError} + errorMessage={errorMessage} // progress={progress} // TODO: change this to actual progress once this we can track upload progress={100} @@ -284,7 +298,7 @@ function UploadModal(props: UploadModalProps) {