From ac066f72b23d5a78e071d3a07f7bfd8b1f587102 Mon Sep 17 00:00:00 2001 From: "create-issue-branch[bot]" <53036503+create-issue-branch[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 10:19:20 +0000 Subject: [PATCH 1/7] Create draft PR for #868 From ceb7f3754a1bc3d8314eb7e44a5a26ab922ecdbc Mon Sep 17 00:00:00 2001 From: Conor Date: Tue, 16 Jan 2024 18:00:42 +0000 Subject: [PATCH 2/7] allow separate laoading of assets and images by identifier --- .../WebComponentProject.jsx | 2 + src/containers/WebComponentLoader.jsx | 4 ++ src/hooks/useProject.js | 14 +++++ src/redux/EditorSlice.js | 4 +- src/utils/apiCallHandler.js | 59 +++++++++++++++++-- src/web-component.js | 2 + 6 files changed, 78 insertions(+), 7 deletions(-) diff --git a/src/components/WebComponentProject/WebComponentProject.jsx b/src/components/WebComponentProject/WebComponentProject.jsx index b608d66bb..b82eb9a5e 100644 --- a/src/components/WebComponentProject/WebComponentProject.jsx +++ b/src/components/WebComponentProject/WebComponentProject.jsx @@ -18,6 +18,7 @@ import { const WebComponentProject = ({ withProjectbar = false, withSidebar = false, + test=false, sidebarOptions = [], }) => { const project = useSelector((state) => state.editor.project); @@ -80,6 +81,7 @@ const WebComponentProject = ({ withProjectbar={withProjectbar} withSidebar={withSidebar} sidebarOptions={sidebarOptions} + test={test} /> )} diff --git a/src/containers/WebComponentLoader.jsx b/src/containers/WebComponentLoader.jsx index 273c13dda..f5442ded0 100644 --- a/src/containers/WebComponentLoader.jsx +++ b/src/containers/WebComponentLoader.jsx @@ -24,6 +24,8 @@ const WebComponentLoader = (props) => { const { authKey, identifier, + codeIdentifier, + assetIdentifier, code, senseHatAlwaysEnabled = false, instructions, @@ -94,6 +96,8 @@ const WebComponentLoader = (props) => { useProject({ projectIdentifier: projectIdentifier, + codeIdentifier, + assetIdentifier, code, accessToken: user?.access_token, loadRemix, diff --git a/src/hooks/useProject.js b/src/hooks/useProject.js index e349ddf85..043be07cf 100644 --- a/src/hooks/useProject.js +++ b/src/hooks/useProject.js @@ -7,6 +7,8 @@ import { useTranslation } from "react-i18next"; export const useProject = ({ projectIdentifier = null, + codeIdentifier = null, + assetIdentifier = null, code = null, accessToken = null, loadRemix = false, @@ -71,6 +73,18 @@ export const useProject = ({ return; } + if (codeIdentifier || assetIdentifier) { + dispatch( + syncProject("load")({ + codeIdentifier, + assetIdentifier, + locale: i18n.language, + accessToken: accessToken, + }), + ); + return; + } + const data = defaultPythonProject; dispatch(setProject(data)); } diff --git a/src/redux/EditorSlice.js b/src/redux/EditorSlice.js index ecded2a11..3f4300a76 100644 --- a/src/redux/EditorSlice.js +++ b/src/redux/EditorSlice.js @@ -18,13 +18,13 @@ export const syncProject = (actionName) => createAsyncThunk( `editor/${actionName}Project`, async ( - { project, identifier, locale, accessToken, autosave }, + { project, identifier, codeIdentifier, assetIdentifier, locale, accessToken, autosave }, { rejectWithValue }, ) => { let response; switch (actionName) { case "load": - response = await readProject(identifier, locale, accessToken); + response = await readProject(identifier, codeIdentifier, assetIdentifier, locale, accessToken); break; case "loadRemix": response = await loadRemix(identifier, accessToken); diff --git a/src/utils/apiCallHandler.js b/src/utils/apiCallHandler.js index d456b8166..92a190fe6 100644 --- a/src/utils/apiCallHandler.js +++ b/src/utils/apiCallHandler.js @@ -1,5 +1,6 @@ import axios from "axios"; import omit from "lodash/omit"; +import { defaultPythonProject } from "./defaultProjects"; const host = process.env.REACT_APP_API_ENDPOINT; @@ -68,12 +69,60 @@ export const createRemix = async (project, accessToken) => { ); }; -export const readProject = async (projectIdentifier, locale, accessToken) => { +export const readProject = async (projectIdentifier, codeIdentifier, assetIdentifier, locale, accessToken) => { const queryString = locale ? `?locale=${locale}` : ""; - return await get( - `${host}/api/projects/${projectIdentifier}${queryString}`, - headers(accessToken), - ); + + //todo, check if code and asset are same, check if normal identifier, load, merge, return + + if(projectIdentifier){ + return await get( + `${host}/api/projects/${projectIdentifier}${queryString}`, + headers(accessToken), + ); + } else { + //Load separate code and assets + + const loadCode = new Promise(async (resolve, reject) => { + if(!codeIdentifier) return resolve(defaultPythonProject); + + const code = await get( + `${host}/api/projects/${codeIdentifier}${queryString}`, + headers(accessToken), + ) + + resolve({ + components: code.data.components, + identifier: code.data.identifier, + locale: code.data.locale, + name: code.data.name, + project_type: code.data.project_type, + user_id: code.data.user_id + }) + }); + + const loadAssets = new Promise(async (resolve, reject) => { + if(!assetIdentifier) return resolve({image_list: []}) + + const assets = await get( + `${host}/api/projects/${assetIdentifier}/images`, + headers(accessToken), + ) + + resolve({ + image_list: assets.data.image_list, + }) + }); + + const result = await Promise.all([loadCode, loadAssets]).then(res => { + return res.reduce(function (acc, row) { + return {...acc, ...row}; + }, {}); + }) + + return { + data: result + } + } }; export const readProjectList = async (page, accessToken) => { diff --git a/src/web-component.js b/src/web-component.js index 9cdb605c9..c8ed8fe1f 100644 --- a/src/web-component.js +++ b/src/web-component.js @@ -39,6 +39,8 @@ class WebComponent extends HTMLElement { "host_styles", "auth_key", "identifier", + "code_identifier", + "asset_identifier", "code", "sense_hat_always_enabled", "instructions", From e45b7880e329d5c82dad9fb81c5360aa625b7c8b Mon Sep 17 00:00:00 2001 From: Scott Date: Mon, 15 Jan 2024 14:41:40 +0000 Subject: [PATCH 3/7] fix(copy): minor copy change to html add file modal --- CHANGELOG.md | 4 ++++ src/utils/i18n.js | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1f21a09a..3d12aab70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## Unreleased +### Changed + +- Minor copy changes to HTML add file modal + ## [0.21.1] - 2024-01-11 ### Added diff --git a/src/utils/i18n.js b/src/utils/i18n.js index 430aa2341..e66398ff2 100644 --- a/src/utils/i18n.js +++ b/src/utils/i18n.js @@ -158,7 +158,7 @@ i18n helpText: "Remember to add the file extension at the end of your file name, for example, {{examples}}", helpTextExample: { - html: "'file.html' or 'file.css'", + html: "'file.html', 'file.css' or 'file.js'", python: "'file.py'", }, inputLabel: "Name your file", From 2d5c2cd58710f1ee64948dd5095ba13ba2525005 Mon Sep 17 00:00:00 2001 From: "create-issue-branch[bot]" <53036503+create-issue-branch[bot]@users.noreply.github.com> Date: Tue, 16 Jan 2024 15:24:32 +0000 Subject: [PATCH 4/7] Un-spaghetti the HtmlRunner (#876) closes #733 --------- Co-authored-by: create-issue-branch[bot] <53036503+create-issue-branch[bot]@users.noreply.github.com> Co-authored-by: Magdalena Jadach Co-authored-by: Scott Co-authored-by: Scott Adams <74183390+sra405@users.noreply.github.com> --- CHANGELOG.md | 1 + .../Editor/Runners/HtmlRunner/HtmlRunner.jsx | 206 +++++++++--------- src/utils/externalLinkHelper.js | 49 +++++ 3 files changed, 156 insertions(+), 100 deletions(-) create mode 100644 src/utils/externalLinkHelper.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d12aab70..d3223d4b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Changed +- Untangle HTML runner (#876) - Project sidebar mobile structure and default to instructions behaviour (#823) - Auth web component from user in local storage (#852) - Save and download panel copy (#784) diff --git a/src/components/Editor/Runners/HtmlRunner/HtmlRunner.jsx b/src/components/Editor/Runners/HtmlRunner/HtmlRunner.jsx index aec8926a5..5cde9e2d1 100644 --- a/src/components/Editor/Runners/HtmlRunner/HtmlRunner.jsx +++ b/src/components/Editor/Runners/HtmlRunner/HtmlRunner.jsx @@ -7,12 +7,19 @@ import { useMediaQuery } from "react-responsive"; import mimeTypes from "mime-types"; import { - setError, setPage, showErrorModal, codeRunHandled, triggerCodeRun, } from "../../../../redux/EditorSlice"; + +import { + useExternalLinkState, + matchingRegexes, + allowedExternalLinks, + allowedInternalLinks, +} from "../../../../utils/externalLinkHelper"; + import { useTranslation } from "react-i18next"; import { Tab, TabList, TabPanel, Tabs } from "react-tabs"; import OpenInNewTabIcon from "../../../../assets/icons/open_in_new_tab.svg"; @@ -47,14 +54,6 @@ function HtmlRunner() { const dispatch = useDispatch(); const output = useRef(null); - const domain = `https://rpf.io/`; - const rpfDomain = new RegExp(`^${domain}`); - const allowedInternalLinks = [new RegExp(`^#[a-zA-Z0-9]+`)]; - const allowedExternalHrefs = [rpfDomain]; - - const matchingRegexes = (regexArray, testString) => { - return regexArray.some((reg) => reg.test(testString)); - }; const isMobile = useMediaQuery({ query: MOBILE_MEDIA_QUERY }); @@ -74,13 +73,20 @@ function HtmlRunner() { const [previewFile, setPreviewFile] = useState(defaultPreviewFile); const [runningFile, setRunningFile] = useState(previewFile); - const [externalLink, setExternalLink] = useState(); const showModal = () => { dispatch(showErrorModal()); eventListener(); }; + const { + externalLink, + setExternalLink, + handleAllowedExternalLink, + handleRegularExternalLink, + handleExternalLinkError, + } = useExternalLinkState(showModal); + const getBlobURL = (code, type) => { const blob = new Blob([code], { type }); return URL.createObjectURL(blob); @@ -118,15 +124,11 @@ function HtmlRunner() { window.addEventListener("message", (event) => { if (typeof event.data?.msg === "string") { if (event.data?.msg === "ERROR: External link") { - dispatch(setError("externalLink")); - showModal(); + handleExternalLinkError(showModal); } else if (event.data?.msg === "Allowed external link") { - setExternalLink(event.data.payload.linkTo); - dispatch(triggerCodeRun()); + handleAllowedExternalLink(event.data.payload.linkTo); } else { - setExternalLink(null); - setPreviewFile(`${event.data.payload.linkTo}.html`); - dispatch(triggerCodeRun()); + handleRegularExternalLink(event.data.payload.linkTo, setPreviewFile); } } }); @@ -194,107 +196,111 @@ function HtmlRunner() { } }, [runningFile]); - const runCode = () => { - setRunningFile(previewFile); - if (!externalLink) { - let indexPage = parse(focussedComponent(previewFile).content); - - const body = indexPage.querySelector("body") || indexPage; + const replaceHrefNodes = (indexPage, projectCode) => { + const hrefNodes = indexPage.querySelectorAll("[href]"); - const hrefNodes = indexPage.querySelectorAll("[href]"); + hrefNodes.forEach((hrefNode) => { + const projectFile = projectCode.find( + (file) => `${file.name}.${file.extension}` === hrefNode.attrs.href, + ); - // replace href's with blob urls - hrefNodes.forEach((hrefNode) => { - const projectFile = projectCode.filter( - (file) => `${file.name}.${file.extension}` === hrefNode.attrs.href, - ); + if (hrefNode.attrs?.target === "_blank") { + hrefNode.removeAttribute("target"); + } - // remove target blanks - if (hrefNode.attrs?.target === "_blank") { - hrefNode.removeAttribute("target"); - } + let onClick; - let onClick; - - if (!!projectFile.length) { - if (parentTag(hrefNode, "head")) { - const projectFileBlob = getBlobURL( - cssProjectImgs(projectFile[0]).content, - mimeTypes.lookup( - `${projectFile[0].name}.${projectFile[0].extension}`, - ), - ); - hrefNode.setAttribute("href", projectFileBlob); - } else { - // eslint-disable-next-line no-script-url - hrefNode.setAttribute("href", "javascript:void(0)"); - onClick = `window.parent.postMessage({msg: 'RELOAD', payload: { linkTo: '${projectFile[0].name}' }})`; - } - } else { - const matchingExternalHref = matchingRegexes( - allowedExternalHrefs, - hrefNode.attrs.href, - ); - const matchingInternalHref = matchingRegexes( - allowedInternalLinks, - hrefNode.attrs.href, + if (!!projectFile) { + if (parentTag(hrefNode, "head")) { + const projectFileBlob = getBlobURL( + cssProjectImgs(projectFile).content, + mimeTypes.lookup(`${projectFile.name}.${projectFile.extension}`), ); - if ( - !matchingInternalHref && - !matchingExternalHref && - !parentTag(hrefNode, "head") - ) { - // eslint-disable-next-line no-script-url - hrefNode.setAttribute("href", "javascript:void(0)"); - onClick = - "window.parent.postMessage({msg: 'ERROR: External link'})"; - } else if (matchingExternalHref) { - onClick = `window.parent.postMessage({msg: 'Allowed external link', payload: { linkTo: '${hrefNode.attrs.href}' }})`; - } + hrefNode.setAttribute("href", projectFileBlob); + } else { + // eslint-disable-next-line no-script-url + hrefNode.setAttribute("href", "javascript:void(0)"); + onClick = `window.parent.postMessage({msg: 'RELOAD', payload: { linkTo: '${projectFile.name}' }})`; } - - if (onClick) { - hrefNode.removeAttribute("target"); - hrefNode.setAttribute("onclick", onClick); + } else { + const matchingExternalHref = matchingRegexes( + allowedExternalLinks, + hrefNode.attrs.href, + ); + const matchingInternalHref = matchingRegexes( + allowedInternalLinks, + hrefNode.attrs.href, + ); + if ( + !matchingInternalHref && + !matchingExternalHref && + !parentTag(hrefNode, "head") + ) { + // eslint-disable-next-line no-script-url + hrefNode.setAttribute("href", "javascript:void(0)"); + onClick = "window.parent.postMessage({msg: 'ERROR: External link'})"; + } else if (matchingExternalHref) { + onClick = `window.parent.postMessage({msg: 'Allowed external link', payload: { linkTo: '${hrefNode.attrs.href}' }})`; } - }); + } - const replaceAttrsWithBlob = (attr = "src") => { - const srcNodes = indexPage.querySelectorAll(`[${attr}]`); - srcNodes.forEach((srcNode) => { - const projectImage = projectImages.filter( - (component) => component.filename === srcNode.attrs[attr], - ); - const projectFile = projectCode.filter( - (file) => `${file.name}.${file.extension}` === srcNode.attrs[attr], - ); - let src = ""; - if (projectImage.length) { - src = projectImage[0].url; - } else if (projectFile.length) { - src = getBlobURL( - projectFile[0].content, - mimeTypes.lookup( - `${projectFile[0].name}.${projectFile[0].extension}`, - ), - ); - } - srcNode.setAttribute(attr, src); - }); - }; - replaceAttrsWithBlob("src"); - replaceAttrsWithBlob("data-src"); + if (onClick) { + hrefNode.removeAttribute("target"); + hrefNode.setAttribute("onclick", onClick); + } + }); + }; + + const replaceSrcNodes = ( + indexPage, + projectImages, + projectCode, + attr = "src", + ) => { + const srcNodes = indexPage.querySelectorAll(`[${attr}]`); + + srcNodes.forEach((srcNode) => { + const projectImage = projectImages.find( + (component) => component.filename === srcNode.attrs[attr], + ); + const projectFile = projectCode.find( + (file) => `${file.name}.${file.extension}` === srcNode.attrs[attr], + ); + + let src = ""; + if (!!projectImage) { + src = projectImage.url; + } else if (!!projectFile) { + src = getBlobURL( + projectFile.content, + mimeTypes.lookup(`${projectFile.name}.${projectFile.extension}`), + ); + } + srcNode.setAttribute(attr, src); + }); + }; + + const runCode = () => { + setRunningFile(previewFile); + + if (!externalLink) { + const indexPage = parse(focussedComponent(previewFile).content); + const body = indexPage.querySelector("body") || indexPage; + + replaceHrefNodes(indexPage, projectCode); + replaceSrcNodes(indexPage, projectImages, projectCode); + replaceSrcNodes(indexPage, projectImages, projectCode, "data-src"); body.appendChild(parse(``)); const blob = getBlobURL(indexPage.toString(), "text/html"); output.current.src = blob; + if (codeRunTriggered) { dispatch(codeRunHandled()); } } else { output.current.src = externalLink; - dispatch(codeRunHandled()); } }; diff --git a/src/utils/externalLinkHelper.js b/src/utils/externalLinkHelper.js new file mode 100644 index 000000000..1be0eeee2 --- /dev/null +++ b/src/utils/externalLinkHelper.js @@ -0,0 +1,49 @@ +import { useState } from "react"; +import { useDispatch } from "react-redux"; + +import { setError, triggerCodeRun } from "../redux/EditorSlice"; + +const domain = `https://rpf.io/`; +const rpfDomain = new RegExp(`^${domain}`); +const allowedInternalLinks = [new RegExp(`^#[a-zA-Z0-9]+`)]; +const allowedExternalLinks = [rpfDomain]; + +const useExternalLinkState = (showModal) => { + const dispatch = useDispatch(); + const [externalLink, setExternalLink] = useState(); + + const handleAllowedExternalLink = (linkTo) => { + setExternalLink(linkTo); + dispatch(triggerCodeRun()); + }; + + const handleRegularExternalLink = (linkTo, setPreviewFile) => { + setExternalLink(null); + setPreviewFile(`${linkTo}.html`); + dispatch(triggerCodeRun()); + }; + + const handleExternalLinkError = () => { + dispatch(setError("externalLink")); + showModal(); + }; + + return { + externalLink, + setExternalLink, + handleAllowedExternalLink, + handleRegularExternalLink, + handleExternalLinkError, + }; +}; + +const matchingRegexes = (regexArray, testString) => { + return regexArray.some((reg) => reg.test(testString)); +}; + +export { + useExternalLinkState, + allowedExternalLinks, + allowedInternalLinks, + matchingRegexes, +}; From 8c5d9149e8dc4a4c121c8ae5b3bc3467133b7137 Mon Sep 17 00:00:00 2001 From: "create-issue-branch[bot]" <53036503+create-issue-branch[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 10:19:20 +0000 Subject: [PATCH 5/7] Create draft PR for #868 From 544657f985e4d0b521e2aa02a820ca0d04b6ac5c Mon Sep 17 00:00:00 2001 From: Conor Date: Wed, 17 Jan 2024 10:47:05 +0000 Subject: [PATCH 6/7] update prettier --- package.json | 2 +- .../WebComponentProject.jsx | 1 - src/redux/EditorSlice.js | 18 ++++++++-- src/utils/apiCallHandler.js | 34 +++++++++++-------- yarn.lock | 8 ++--- 5 files changed, 41 insertions(+), 22 deletions(-) diff --git a/package.json b/package.json index 0a10c382c..0124eadd7 100644 --- a/package.json +++ b/package.json @@ -164,7 +164,7 @@ "postcss-normalize": "8.0.1", "postcss-preset-env": "6.7.0", "postcss-safe-parser": "5.0.2", - "prettier": "^2.8.8", + "prettier": "^3.2.4", "react-dev-utils": "^11.0.3", "react-test-renderer": "^17.0.2", "redux-mock-store": "^1.5.4", diff --git a/src/components/WebComponentProject/WebComponentProject.jsx b/src/components/WebComponentProject/WebComponentProject.jsx index b82eb9a5e..b925a9a55 100644 --- a/src/components/WebComponentProject/WebComponentProject.jsx +++ b/src/components/WebComponentProject/WebComponentProject.jsx @@ -18,7 +18,6 @@ import { const WebComponentProject = ({ withProjectbar = false, withSidebar = false, - test=false, sidebarOptions = [], }) => { const project = useSelector((state) => state.editor.project); diff --git a/src/redux/EditorSlice.js b/src/redux/EditorSlice.js index 3f4300a76..617a73282 100644 --- a/src/redux/EditorSlice.js +++ b/src/redux/EditorSlice.js @@ -18,13 +18,27 @@ export const syncProject = (actionName) => createAsyncThunk( `editor/${actionName}Project`, async ( - { project, identifier, codeIdentifier, assetIdentifier, locale, accessToken, autosave }, + { + project, + identifier, + codeIdentifier, + assetIdentifier, + locale, + accessToken, + autosave, + }, { rejectWithValue }, ) => { let response; switch (actionName) { case "load": - response = await readProject(identifier, codeIdentifier, assetIdentifier, locale, accessToken); + response = await readProject( + identifier, + codeIdentifier, + assetIdentifier, + locale, + accessToken, + ); break; case "loadRemix": response = await loadRemix(identifier, accessToken); diff --git a/src/utils/apiCallHandler.js b/src/utils/apiCallHandler.js index 92a190fe6..8dacc4784 100644 --- a/src/utils/apiCallHandler.js +++ b/src/utils/apiCallHandler.js @@ -69,12 +69,18 @@ export const createRemix = async (project, accessToken) => { ); }; -export const readProject = async (projectIdentifier, codeIdentifier, assetIdentifier, locale, accessToken) => { +export const readProject = async ( + projectIdentifier, + codeIdentifier, + assetIdentifier, + locale, + accessToken, +) => { const queryString = locale ? `?locale=${locale}` : ""; //todo, check if code and asset are same, check if normal identifier, load, merge, return - if(projectIdentifier){ + if (projectIdentifier) { return await get( `${host}/api/projects/${projectIdentifier}${queryString}`, headers(accessToken), @@ -83,12 +89,12 @@ export const readProject = async (projectIdentifier, codeIdentifier, assetIdenti //Load separate code and assets const loadCode = new Promise(async (resolve, reject) => { - if(!codeIdentifier) return resolve(defaultPythonProject); + if (!codeIdentifier) return resolve(defaultPythonProject); const code = await get( `${host}/api/projects/${codeIdentifier}${queryString}`, headers(accessToken), - ) + ); resolve({ components: code.data.components, @@ -96,32 +102,32 @@ export const readProject = async (projectIdentifier, codeIdentifier, assetIdenti locale: code.data.locale, name: code.data.name, project_type: code.data.project_type, - user_id: code.data.user_id - }) + user_id: code.data.user_id, + }); }); const loadAssets = new Promise(async (resolve, reject) => { - if(!assetIdentifier) return resolve({image_list: []}) + if (!assetIdentifier) return resolve({ image_list: [] }); const assets = await get( `${host}/api/projects/${assetIdentifier}/images`, headers(accessToken), - ) + ); resolve({ image_list: assets.data.image_list, - }) + }); }); - const result = await Promise.all([loadCode, loadAssets]).then(res => { + const result = await Promise.all([loadCode, loadAssets]).then((res) => { return res.reduce(function (acc, row) { - return {...acc, ...row}; + return { ...acc, ...row }; }, {}); - }) + }); return { - data: result - } + data: result, + }; } }; diff --git a/yarn.lock b/yarn.lock index e0c4f6929..19d16346b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10938,10 +10938,10 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@^2.8.8: - version "2.8.8" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" - integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== +prettier@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.4.tgz#4723cadeac2ce7c9227de758e5ff9b14e075f283" + integrity sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ== pretty-bytes@^5.3.0, pretty-bytes@^5.6.0: version "5.6.0" From 9fa3af78e577278232e98850e6958a312b75481e Mon Sep 17 00:00:00 2001 From: Conor Date: Wed, 17 Jan 2024 11:38:22 +0000 Subject: [PATCH 7/7] remove unused prop --- src/components/WebComponentProject/WebComponentProject.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/WebComponentProject/WebComponentProject.jsx b/src/components/WebComponentProject/WebComponentProject.jsx index b925a9a55..b608d66bb 100644 --- a/src/components/WebComponentProject/WebComponentProject.jsx +++ b/src/components/WebComponentProject/WebComponentProject.jsx @@ -80,7 +80,6 @@ const WebComponentProject = ({ withProjectbar={withProjectbar} withSidebar={withSidebar} sidebarOptions={sidebarOptions} - test={test} /> )}