Skip to content

Commit

Permalink
Added a save button to DownloadPanel (#872)
Browse files Browse the repository at this point in the history
Allows mobile users to save their project and remix in place of auto
remixing (#843)
  • Loading branch information
sra405 authored Jan 12, 2024
1 parent 0ba2c54 commit 77b2268
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 2 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## Unreleased

### Added

- Download panel save button (#872)

### Changed

- Stack editor input and output panels based on container width (#869)
Expand Down
4 changes: 4 additions & 0 deletions src/assets/stylesheets/DownloadPanel.scss
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,7 @@
box-sizing: border-box;
margin: 0;
}

.download-panel__download-section {
margin-block-end: $space-1;
}
5 changes: 5 additions & 0 deletions src/components/Menus/Sidebar/DownloadPanel/DownloadPanel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import { useTranslation } from "react-i18next";
import { useSelector } from "react-redux";
import SidebarPanel from "../SidebarPanel";
import DownloadButton from "../../../DownloadButton/DownloadButton";
import SaveButton from "../../../SaveButton/SaveButton";
import DesignSystemButton from "../../../DesignSystemButton/DesignSystemButton";
import DownloadIcon from "../../../../assets/icons/download.svg";
import { isOwner } from "../../../../utils/projectHelpers";

import {
logInEvent,
Expand All @@ -15,6 +17,8 @@ import "../../../../assets/stylesheets/DownloadPanel.scss";
export const DownloadPanel = () => {
const { t } = useTranslation();
const user = useSelector((state) => state.auth.user);
const project = useSelector((state) => state.editor.project);
const projectOwner = isOwner(user, project);

const handleLogIn = () => {
if (window.plausible) {
Expand Down Expand Up @@ -64,6 +68,7 @@ export const DownloadPanel = () => {
fill
/>
</div>
{user && !projectOwner && <SaveButton fill />}
</SidebarPanel>
);
};
Expand Down
111 changes: 110 additions & 1 deletion src/components/Menus/Sidebar/DownloadPanel/DownloadPanel.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ describe("DownloadPanel", () => {
).toBeInTheDocument();
});

test("Does not render the save button", () => {
expect(container.queryByText("header.save")).not.toBeInTheDocument();
});

test("The download button initiates a download", async () => {
const webComponentDownloadButton = screen.getByText(
"downloadPanel.downloadButton",
Expand All @@ -122,7 +126,7 @@ describe("DownloadPanel", () => {
});
});

describe("When logged in", () => {
describe("When logged in and not the project owner", () => {
beforeEach(() => {
const middlewares = [];
const mockStore = configureStore(middlewares);
Expand All @@ -144,10 +148,14 @@ describe("DownloadPanel", () => {
},
],
},
loading: "success",
},
auth: {
user: {
access_token: "39a09671-be55-4847-baf5-8919a0c24a25",
profile: {
user: "some-user-id",
},
},
},
};
Expand Down Expand Up @@ -201,6 +209,107 @@ describe("DownloadPanel", () => {
).toBeInTheDocument();
});

test("Renders the save button", () => {
expect(container.getByText("header.save")).toBeInTheDocument();
});

test("The download button initiates a download", async () => {
const webComponentDownloadButton = screen.getByText(
"downloadPanel.downloadButton",
).parentElement;
fireEvent.click(webComponentDownloadButton);
await waitFor(() => expect(FileSaver.saveAs).toHaveBeenCalled());
});
});

describe("When logged in and the project owner", () => {
beforeEach(() => {
const middlewares = [];
const mockStore = configureStore(middlewares);
const initialState = {
editor: {
project: {
name: "My epic project",
identifier: "hello-world-project",
components: [
{
name: "main",
extension: "py",
content: "print('hello world')",
},
],
image_list: [
{
url: "a.com/b",
},
],
user_id: "some-user-id",
},
loading: "success",
},
auth: {
user: {
access_token: "39a09671-be55-4847-baf5-8919a0c24a25",
profile: {
user: "some-user-id",
},
},
},
};
const store = mockStore(initialState);

container = render(
<Provider store={store}>
<MemoryRouter>
<DownloadPanel />
</MemoryRouter>
</Provider>,
);
});
test("Renders the correct heading", () => {
expect(container.getByText("downloadPanel.heading")).toBeInTheDocument();
});

test("Does not render the log-in subtitle", () => {
expect(
container.queryByText("downloadPanel.logInTitle"),
).not.toBeInTheDocument();
});

test("Does not render the log-in hint", () => {
expect(
container.queryByText("downloadPanel.logInHint"),
).not.toBeInTheDocument();
});

test("Does not render the log-in button", () => {
expect(
container.queryByText("downloadPanel.logInButton"),
).not.toBeInTheDocument();
});

test("Does not render the sign-up button", () => {
expect(
container.queryByText("downloadPanel.signUpButton"),
).not.toBeInTheDocument();
});

test("Renders the download hint", () => {
expect(
container.getByText("downloadPanel.downloadHint"),
).toBeInTheDocument();
});

test("Renders the download button", () => {
expect(
container.getByText("downloadPanel.downloadButton"),
).toBeInTheDocument();
});

test("Does not render the save button", () => {
expect(container.queryByText("header.save")).not.toBeInTheDocument();
});

test("The download button initiates a download", async () => {
const webComponentDownloadButton = screen.getByText(
"downloadPanel.downloadButton",
Expand Down
3 changes: 2 additions & 1 deletion src/components/SaveButton/SaveButton.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import DesignSystemButton from "../DesignSystemButton/DesignSystemButton";
import SaveIcon from "../../assets/icons/save.svg";
import { triggerSave } from "../../redux/EditorSlice";

const SaveButton = ({ className, type }) => {
const SaveButton = ({ className, type, fill = false }) => {
const dispatch = useDispatch();
const { t } = useTranslation();

Expand Down Expand Up @@ -51,6 +51,7 @@ const SaveButton = ({ className, type }) => {
textAlways
icon={<SaveIcon />}
type={buttonType}
fill={fill}
/>
)
);
Expand Down

0 comments on commit 77b2268

Please sign in to comment.