Skip to content

Commit

Permalink
Merge pull request #872 from IPG-Automotive-UK/release/v7.8.0
Browse files Browse the repository at this point in the history
Release/v7.8.0
  • Loading branch information
syedsalehinipg authored May 24, 2024
2 parents 30accfe + 0e2713c commit 6b9e92c
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 21 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ipguk/react-ui",
"version": "7.7.1",
"version": "7.8.0-1",
"description": "React UI component library for IPG web applications",
"author": "IPG-Automotive-UK",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion src/FileUploader/FileUploader.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ type Story = StoryObj<typeof FileUploader>;
export const Default: Story = {
args: {
acceptedFiles: [],
dropzoneText: "Drag & drop a file here or click",
dropzoneText: "Drag & Drop a file here or browse",
filesLimit: 1,
isValidating: false,
maxFileSize: 1000000000,
Expand Down
8 changes: 4 additions & 4 deletions src/FileUploader/FileUploader.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,12 @@ describe("FileUploader", () => {
<FileUploader
selectedFiles={multipleFiles}
multiple={true}
dropzoneText={"Drag & drop file(s) here or click"}
dropzoneText={"Drag & Drop file(s) here or browse"}
/>
);
const dropzoneElement = screen.getByTestId("dropzone-base");
expect(dropzoneElement).toHaveTextContent(
"Drag & drop file(s) here or click"
"Drag & Drop file(s) here or browse"
);
const chips = container.querySelectorAll(".MuiChip-root");
expect(chips.length).toBe(2);
Expand All @@ -77,7 +77,7 @@ describe("FileUploader", () => {
<FileUploader
selectedFiles={multipleFiles}
multiple={true}
dropzoneText={"Drag & drop file(s) here or click"}
dropzoneText={"Drag & Drop file(s) here or browse"}
isValidating={true}
/>
);
Expand All @@ -90,7 +90,7 @@ describe("FileUploader", () => {
<FileUploader
selectedFiles={multipleFiles}
multiple={true}
dropzoneText={"Drag & drop file(s) here or click"}
dropzoneText={"Drag & Drop file(s) here or browse"}
isValidating={true}
/>
);
Expand Down
2 changes: 1 addition & 1 deletion src/FileUploader/FileUploader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import useUploader from "../Uploader/useUploader";
export default function FileUploader({
acceptedFiles,
error,
dropzoneText = "Drag & drop a file here or click",
dropzoneText = "Drag & Drop a file here or browse",
filesLimit = 1,
isValidating = false,
maxFileSize = Infinity,
Expand Down
13 changes: 12 additions & 1 deletion src/ImageUploader/ImageUploader.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ export default meta;
type Story = StoryObj<typeof ImageUploader>;
export const Default: Story = {
args: {
dropzoneText: "Drag 'n' drop an image file here, or click to select",
dropzoneText: "Drag & Drop an image file here or browse",
isUploading: false,
maxFileSize: 1000000000,
onAdd: () => {},
onDelete: () => {},
Expand All @@ -62,3 +63,13 @@ export const WithSingleFileSelected: Story = {
]
}
};

/**
* Story which shows the uploader in loading state with a single file selected.
*/
export const SingleFileLoading: Story = {
args: {
...WithSingleFileSelected.args,
isUploading: true
}
};
18 changes: 15 additions & 3 deletions src/ImageUploader/ImageUploader.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ describe("ImageUploader", () => {
const dropzoneElement = screen.getByTestId("dropzone-base");
expect(dropzoneElement).toBeInTheDocument();
expect(
screen.queryByText("Drag 'n' drop an image file here, or click to select")
screen.queryByText("Drag & Drop an image file here or browse")
).toBeInTheDocument();
});
// show delete button if only one file selected
Expand All @@ -34,13 +34,25 @@ describe("ImageUploader", () => {
const deleteButton = screen.getByRole("button", { name: /DeleteIcon/i });
expect(deleteButton).toBeInTheDocument();
});
// hide delete button when image loading
test("hide delete button when image loading", () => {
render(<ImageUploader selectedFiles={[singleFile]} isUploading={true} />);
const deleteButton = screen.queryByRole("button", { name: /delete/i });
expect(deleteButton).not.toBeInTheDocument();
});
// updates dropzone text when uploading single image
test("updates dropzone text when uploading single image", () => {
render(<ImageUploader selectedFiles={[singleFile]} isUploading />);
const dropzoneElement = screen.getByTestId("dropzone-base");
expect(dropzoneElement).toHaveTextContent("Uploading Image");
});
// show the selected image and hide dropzone text
test("show selected image", () => {
render(<ImageUploader selectedFiles={[singleFile]} />);
const img = screen.getByAltText("Preview of 1x1.png");
expect(img).toHaveAttribute("src", singleFile.data);
expect(
screen.queryByText("Drag 'n' drop an image file here, or click to select")
screen.queryByText("Drag & Drop an image file here or browse")
).not.toBeInTheDocument();
});

Expand Down Expand Up @@ -70,7 +82,7 @@ describe("ImageUploader", () => {

// check default text is displayed
expect(
screen.queryByText("Drag 'n' drop an image file here, or click to select")
screen.queryByText("Drag & Drop an image file here or browse")
).toBeVisible();

// check callback was called
Expand Down
21 changes: 15 additions & 6 deletions src/ImageUploader/ImageUploader.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Box, Stack, Typography, alpha } from "@mui/material";
import { Box, LinearProgress, Stack, Typography, alpha } from "@mui/material";

import FileUploadIcon from "@mui/icons-material/FileUpload";
import { ImageUploaderProps } from "./ImageUploader.types";
Expand All @@ -10,8 +10,9 @@ export default function ImageUploader({
title = "Upload Image",
titleVariant,
subText = "A default image will be used if no image is uploaded",
dropzoneText = "Drag 'n' drop an image file here, or click to select",
maxFileSize = 1000000,
dropzoneText = "Drag & Drop an image file here or browse",
isUploading = false,
maxFileSize = 10000000,
onAdd,
onDelete,
selectedFiles = [],
Expand Down Expand Up @@ -50,7 +51,7 @@ export default function ImageUploader({
titleVariant={titleVariant}
required={required}
subText={subText}
showDelete={selectedFiles.length > 0}
showDelete={!isUploading && selectedFiles.length > 0}
onDelete={() => handleDelete(selectedFiles[0])}
/>
<Box
Expand Down Expand Up @@ -98,11 +99,19 @@ export default function ImageUploader({
},
justifyContent: "center",
p: 2,
pointerEvenets: selectedFiles.length > 0 ? "none" : "auto"
pointerEvents:
isUploading || selectedFiles.length > 0 ? "none" : "auto"
})}
>
<input {...getInputProps()} />
{selectedFiles.length === 0 ? (
{isUploading ? (
<Stack className="dropzoneText">
<Typography fontSize="14px">Uploading Image</Typography>
<Box width={200}>
<LinearProgress />
</Box>
</Stack>
) : selectedFiles.length === 0 ? (
<Stack className="dropzoneText">
<FileUploadIcon />
<Typography fontSize="15px">
Expand Down
4 changes: 4 additions & 0 deletions src/ImageUploader/ImageUploader.types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ export type ImageUploaderProps = {
* Text to display in dropzone
*/
dropzoneText?: string;
/**
* Whether the component is in the loading state with the loading indicator and selection disabled.
*/
isUploading?: boolean;
/**
* Maximum file size (in bytes) that the dropzone will accept.
*/
Expand Down
17 changes: 13 additions & 4 deletions src/Uploader/useUploader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,21 @@ export default function useUploader({

// handle file drops that are rejected by showing the first error message as a rejection message
const onDropRejected = (fileRejection: FileRejection[]) => {
// replace any commas not followed by a whitespace character with a comma followed by a whitespace character
const message = fileRejection[0].errors[0].message;
const formattedMessage = message.replace(/,(?!\s)/g, ", ");
// get the error code
const errorCode = fileRejection[0].errors[0].code;

// get file size limit in MB
const bytesToMb = maxFileSize / 1024 / 1024;
const limitSize = `${bytesToMb.toFixed()} MB`;

// set error message based on error code
const errorMessage =
errorCode === "file-invalid-type"
? "File type must be a .gif, .jpg, .jpeg, .png, .webp"
: `File size exceeds the limit of ${limitSize}`;

// set error message
setRejectionMessage(formattedMessage);
setRejectionMessage(errorMessage);
};

// use react-dropzone hook
Expand Down

0 comments on commit 6b9e92c

Please sign in to comment.