Skip to content

Commit

Permalink
feat: first pass reordering uploaded files to show most recent first
Browse files Browse the repository at this point in the history
- Reverse the order to have the most recently uploaded file first.
-  First pass at introducing a test to check this change
  • Loading branch information
Mike-Heneghan committed Oct 20, 2023
1 parent f7b84f3 commit 9baab7d
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 36 deletions.
29 changes: 19 additions & 10 deletions editor.planx.uk/src/@planx/components/FileUploadAndLabel/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { fileLabelSchema } from "./schema";
interface FileTaggingModalProps {
uploadedFiles: FileUploadSlot[];
fileList: FileList;
orderByMostRecentlyUploaded: boolean;
setFileList: (value: React.SetStateAction<FileList>) => void;
setShowModal: (value: React.SetStateAction<boolean>) => void;
}
Expand All @@ -52,6 +53,7 @@ const ListHeader = styled(Box)(({ theme }) => ({
export const FileTaggingModal = ({
uploadedFiles,
fileList,
orderByMostRecentlyUploaded,
setFileList,
setShowModal,
}: FileTaggingModalProps) => {
Expand All @@ -71,6 +73,22 @@ export const FileTaggingModal = ({
.catch((err) => setError(err.message));
};

const returnUploadedFileCardsAndSelects = () => {
const uploadedFileCardsAndSelects = uploadedFiles.map((slot) => (
<Box sx={{ mb: 4 }} key={`tags-per-file-container-${slot.id}`}>
<UploadedFileCard {...slot} key={slot.id} />
<SelectMultiple
uploadedFile={slot}
fileList={fileList}
setFileList={setFileList}
/>
</Box>
));
return orderByMostRecentlyUploaded
? uploadedFileCardsAndSelects.reverse()
: uploadedFileCardsAndSelects;
};

return (
<Dialog
open
Expand All @@ -95,16 +113,7 @@ export const FileTaggingModal = ({
Tell us what these files show
</Typography>
</Box>
{uploadedFiles.map((slot) => (
<Box sx={{ mb: 4 }} key={`tags-per-file-container-${slot.id}`}>
<UploadedFileCard {...slot} key={slot.id} />
<SelectMultiple
uploadedFile={slot}
fileList={fileList}
setFileList={setFileList}
/>
</Box>
))}
{returnUploadedFileCardsAndSelects()}
</DialogContent>
<DialogActions
sx={{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,125 @@ describe("Adding tags and syncing state", () => {
);
expect(error).toBeVisible();
});

test("Uploaded file cards are displayed in most recently uploaded first", async () => {
const handleSubmit = jest.fn();
const { user } = setup(
<FileUploadAndLabelComponent
title="Test title"
handleSubmit={handleSubmit}
fileTypes={mockFileTypesUniqueKeys}
/>,
);

// No file requirements have been satisfied yet
let incompleteIcons = screen.getAllByTestId("incomplete-icon");
expect(incompleteIcons).toHaveLength(2);

// Upload first file
mockedAxios.post.mockResolvedValue({
data: {
file_type: "image/png",
fileUrl: "https://api.editor.planx.dev/file/private/gws7l5d1/test1.jpg",
},
});

const file1 = new File(["test1"], "test1.png", { type: "image/png" });
const input = screen.getByTestId("upload-input");
await user.upload(input, [file1]);

// Modal opened automatically
const fileTaggingModal = await within(document.body).findByTestId(
"file-tagging-dialog",
);

// The number of selects in the modal matches the number of uploaded files
const selects = await within(document.body).findAllByTestId("select");
expect(selects).toHaveLength(1);

const submitModalButton = await within(fileTaggingModal).findByText("Done");
expect(submitModalButton).toBeVisible();

// Apply tag to this file
fireEvent.change(selects[0], { target: { value: "Roof plan" } });

// Close modal successfully
user.click(submitModalButton);
await waitFor(() => expect(fileTaggingModal).not.toBeVisible());

// Uploaded file displayed as card with chip tags
expect(screen.getByText("test1.png")).toBeVisible();
const chips = screen.getAllByTestId("uploaded-file-chip");
expect(chips).toHaveLength(1);
expect(chips[0]).toHaveTextContent("Roof plan");

// Requirements list reflects successfully tagged uploads
const completeIcons = screen.getAllByTestId("complete-icon");
expect(completeIcons).toHaveLength(1);
incompleteIcons = screen.getAllByTestId("incomplete-icon");
expect(incompleteIcons).toHaveLength(1);

// Upload second file
mockedAxios.post.mockResolvedValue({
data: {
file_type: "image/png",
fileUrl: "https://api.editor.planx.dev/file/private/gws7l5d1/test2.jpg",
},
});

const file2 = new File(["test2"], "test2.png", { type: "image/png" });
const theInput = screen.getByTestId("upload-input");
await user.upload(theInput, [file2]);

const theModal = await within(document.body).findByTestId(
"file-tagging-dialog",
);
expect(theModal).toBeVisible();

const modalUploadedFileCards = await within(theModal).getAllByTestId(
"uploaded-file-card",
);
expect(modalUploadedFileCards[0]).toHaveTextContent("test2.png");
expect(modalUploadedFileCards[1]).toHaveTextContent("test1.png");

const newSelects = await within(document.body).findAllByTestId("select");
expect(newSelects).toHaveLength(2);

const newSubmitModalButton = await within(theModal).findByText("Done");
expect(newSubmitModalButton).toBeVisible();

// Apply tag to second file
fireEvent.change(newSelects[0], {
target: { value: "Heritage statement" },
});

// Close modal successfully
user.click(newSubmitModalButton);
await waitFor(() => expect(theModal).not.toBeVisible());

// Second uploaded file displayed
expect(screen.getByText("test2.png")).toBeVisible();

// Has expected chips in expected order
const newChips = screen.getAllByTestId("uploaded-file-chip");
expect(newChips).toHaveLength(2);
expect(newChips[0]).toHaveTextContent("Heritage statement");
expect(newChips[1]).toHaveTextContent("Roof plan");

// Has expected file cards in expected order
const fileCards = screen.getAllByTestId("uploaded-file-card");
expect(fileCards[0]).toHaveTextContent("test2.png");
expect(fileCards[1]).toHaveTextContent("test1.png");

// Requirements list reflects successfully tagged uploads
const theCompleteIcons = screen.getAllByTestId("complete-icon");
expect(theCompleteIcons).toHaveLength(2);

// "Continue" onto to the next node
expect(screen.getByText("Continue")).toBeEnabled();
await user.click(screen.getByText("Continue"));
expect(handleSubmit).toHaveBeenCalledTimes(1);
});
});

describe("Error handling", () => {
Expand Down
49 changes: 26 additions & 23 deletions editor.planx.uk/src/@planx/components/FileUploadAndLabel/Public.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ function Component(props: Props) {
}, []);

const [slots, setSlots] = useState<FileUploadSlot[]>([]);
const orderByMostRecentlyUploaded = true;

// Track number of slots, and open modal when this increases
const previousSlotCount = usePrevious(slots.length);
Expand Down Expand Up @@ -147,6 +148,29 @@ function Component(props: Props) {
}
};

const returnUploadedFileCards = () => {
const uploadedFileCards = slots.map((slot) => {
return (
<UploadedFileCard
{...slot}
key={slot.id}
tags={getTagsForSlot(slot.id, fileList)}
onChange={onUploadedFileCardChange}
removeFile={() => {
setSlots(
slots.filter((currentSlot) => currentSlot.file !== slot.file),
);
setFileUploadStatus(`${slot.file.path} was deleted`);
removeSlots(getTagsForSlot(slot.id, fileList), slot, fileList);
}}
/>
);
});
return orderByMostRecentlyUploaded
? uploadedFileCards.reverse()
: uploadedFileCards;
};

return (
<Card
handleSubmit={props.hideDropZone ? props.handleSubmit : validateAndSubmit}
Expand Down Expand Up @@ -220,31 +244,10 @@ function Component(props: Props) {
fileList={fileList}
setFileList={setFileList}
setShowModal={setShowModal}
orderByMostRecentlyUploaded={orderByMostRecentlyUploaded}
/>
)}
{slots.map((slot) => {
return (
<UploadedFileCard
{...slot}
key={slot.id}
tags={getTagsForSlot(slot.id, fileList)}
onChange={onUploadedFileCardChange}
removeFile={() => {
setSlots(
slots.filter(
(currentSlot) => currentSlot.file !== slot.file,
),
);
setFileUploadStatus(`${slot.file.path} was deleted`);
removeSlots(
getTagsForSlot(slot.id, fileList),
slot,
fileList,
);
}}
/>
);
})}
{returnUploadedFileCards()}
</Box>
</ErrorWrapper>
</FullWidthWrapper>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,6 @@ export const addOrAppendSlots = (
const categories = Object.keys(updatedFileList) as Array<
keyof typeof updatedFileList
>;

tags.forEach((tag) => {
categories.forEach((category) => {
const index = updatedFileList[category].findIndex(
Expand All @@ -359,7 +358,6 @@ export const addOrAppendSlots = (
}
});
});

return updatedFileList;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export const UploadedFileCard: React.FC<Props> = ({
tags,
}) => (
<Root>
<FileCard>
<FileCard data-testid={"uploaded-file-card"}>
<ProgressBar
width={`${Math.min(Math.ceil(progress * 100), 100)}%`}
role="progressbar"
Expand Down

0 comments on commit 9baab7d

Please sign in to comment.