diff --git a/src/components/ProjectBar/ProjectBar.jsx b/src/components/ProjectBar/ProjectBar.jsx
index 1b790663e..33c331166 100644
--- a/src/components/ProjectBar/ProjectBar.jsx
+++ b/src/components/ProjectBar/ProjectBar.jsx
@@ -19,6 +19,7 @@ const ProjectBar = ({ nameEditable = true }) => {
const loading = useSelector((state) => state.editor.loading);
const lastSavedTime = useSelector((state) => state.editor.lastSavedTime);
const offlineEnabled = useSelector((state) => state.editor.offlineEnabled);
+ const saveDisabled = useSelector((state) => state.editor.saveDisabled);
const projectOwner = isOwner(user, project);
const readOnly = useSelector((state) => state.editor.readOnly);
const isOnline = useIsOnline();
@@ -39,7 +40,7 @@ const ProjectBar = ({ nameEditable = true }) => {
type="tertiary"
/>
- {!projectOwner && !readOnly && (
+ {!projectOwner && !readOnly && !saveDisabled && (
diff --git a/src/components/ProjectBar/ProjectBar.test.js b/src/components/ProjectBar/ProjectBar.test.js
index 46c7f0cfc..0db25b777 100644
--- a/src/components/ProjectBar/ProjectBar.test.js
+++ b/src/components/ProjectBar/ProjectBar.test.js
@@ -95,6 +95,25 @@ describe("When logged in and user owns project", () => {
});
});
+describe("When logged in and save is disabled", () => {
+ beforeEach(() => {
+ renderProjectBar({
+ editor: {
+ project,
+ saveDisabled: true,
+ lastSavedTime: new Date().getTime(),
+ },
+ auth: {
+ user,
+ },
+ });
+ });
+
+ test("Save button is not shown", () => {
+ expect(screen.queryByText("header.save")).not.toBeInTheDocument();
+ });
+});
+
describe("When logged in and no project identifier", () => {
const projectWithoutId = { ...project, identifier: null };
diff --git a/src/containers/WebComponentLoader.jsx b/src/containers/WebComponentLoader.jsx
index 0aef37da2..72198c689 100644
--- a/src/containers/WebComponentLoader.jsx
+++ b/src/containers/WebComponentLoader.jsx
@@ -5,6 +5,7 @@ import {
setSenseHatAlwaysEnabled,
setOfflineEnabled,
setFriendlyErrorsEnabled,
+ setSaveDisabled,
setLoadRemixDisabled,
setReactAppApiEndpoint,
setScratchApiEndpoint,
@@ -72,6 +73,7 @@ const WebComponentLoader = (props) => {
loadCache = true, // Always use cache unless explicitly disabled
initialProject = null,
offlineEnabled = false,
+ saveDisabled = false,
} = props;
const dispatch = useDispatch();
@@ -204,6 +206,10 @@ const WebComponentLoader = (props) => {
dispatch(setOfflineEnabled(offlineEnabled));
}, [offlineEnabled, dispatch]);
+ useEffect(() => {
+ dispatch(setSaveDisabled(saveDisabled));
+ }, [saveDisabled, dispatch]);
+
useEffect(() => {
// Create a script element to save the existing Prism object if there is one
const script = document.createElement("script");
diff --git a/src/redux/EditorSlice.js b/src/redux/EditorSlice.js
index abf7b5276..d6bd05c51 100644
--- a/src/redux/EditorSlice.js
+++ b/src/redux/EditorSlice.js
@@ -128,6 +128,7 @@ export const editorInitialState = {
scratchIframeProjectIdentifier: null,
friendlyErrorsEnabled: false,
friendlyError: null,
+ saveDisabled: false,
};
const isScratchProject = (state) =>
@@ -300,6 +301,9 @@ const EditorSlice = createSlice({
setFriendlyError: (state, action) => {
state.friendlyError = action.payload;
},
+ setSaveDisabled: (state, action) => {
+ state.saveDisabled = action.payload;
+ },
setLoadRemixDisabled: (state, action) => {
state.loadRemixDisabled = action.payload;
},
@@ -531,6 +535,7 @@ export const {
setSenseHatEnabled,
setFriendlyErrorsEnabled,
setLoadRemixDisabled,
+ setSaveDisabled,
setReactAppApiEndpoint,
setScratchApiEndpoint,
stopCodeRun,
diff --git a/src/redux/EditorSlice.test.js b/src/redux/EditorSlice.test.js
index 37c529f0f..6e4b9897d 100644
--- a/src/redux/EditorSlice.test.js
+++ b/src/redux/EditorSlice.test.js
@@ -23,6 +23,7 @@ import reducer, {
scratchSaveFailed,
setFriendlyErrorsEnabled,
setFriendlyError,
+ setSaveDisabled,
} from "./EditorSlice";
const mockCreateRemix = jest.fn();
@@ -128,6 +129,12 @@ test("Action setOfflineEnabled correctly sets offlineEnabled", () => {
);
});
+test("Action setSaveDisabled sets saveDisabled", () => {
+ const previousState = { saveDisabled: false };
+ const expectedState = { saveDisabled: true };
+ expect(reducer(previousState, setSaveDisabled(true))).toEqual(expectedState);
+});
+
test("Action addProjectComponent adds component to project with correct content", () => {
const previousState = {
project: {
diff --git a/src/web-component.js b/src/web-component.js
index aa9e90281..8f49316c7 100644
--- a/src/web-component.js
+++ b/src/web-component.js
@@ -81,6 +81,7 @@ class WebComponent extends HTMLElement {
"load_cache",
"offline_enabled",
"friendly_errors_enabled",
+ "save_disabled",
];
}
@@ -101,6 +102,7 @@ class WebComponent extends HTMLElement {
"load_cache",
"offline_enabled",
"friendly_errors_enabled",
+ "save_disabled",
];
const jsonAttrs = [
"instructions",