Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- `assets_identifier` attribute for the web component (#901)
- `code` attribute overriding content of `main.py`/`index.html` in the web component (#901)
- Web component methods to run, stop and rerun the code from the host page (#899)
- Enable web component to specify which output tabs are shown (#909)
- Return more verbose errors to web component (#915)

### Changed
Expand Down
2 changes: 1 addition & 1 deletion src/assets/stylesheets/EmbeddedViewer.scss
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
}
}

.--light {
#app.--light {
.embedded-viewer {
background-color: $rpf-white;
}
Expand Down
4 changes: 4 additions & 0 deletions src/assets/stylesheets/PythonRunner.scss
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,7 @@
}
}
}

.--light .output-panel--single, .--dark .output-panel--single {
border-block-end: none;
}
4 changes: 4 additions & 0 deletions src/assets/stylesheets/Tabs.scss
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@
padding: 0 $space-0-25 0 0;
}

&__tab-container--hidden {
display: none;
}

&__tab-panel--selected {
flex: 1;
display: flex;
Expand Down
11 changes: 9 additions & 2 deletions src/components/Editor/Output/Output.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import ExternalFiles from "../../ExternalFiles/ExternalFiles";
import RunnerFactory from "../Runners/RunnerFactory";
import RunBar from "../../RunButton/RunBar";

const Output = ({ embedded = false, browserPreview = false }) => {
const Output = ({
embedded = false,
browserPreview = false,
outputPanels = ["text", "visual"],
}) => {
const project = useSelector((state) => state.editor.project);
const isEmbedded =
useSelector((state) => state.editor.isEmbedded) || embedded;
Expand All @@ -17,7 +21,10 @@ const Output = ({ embedded = false, browserPreview = false }) => {
<>
<ExternalFiles />
<div className="proj-runner-container">
<RunnerFactory projectType={project.project_type} />
<RunnerFactory
projectType={project.project_type}
outputPanels={outputPanels}
/>
{!webComponent && isEmbedded && !isBrowserPreview && (
<RunBar embedded />
)}
Expand Down
105 changes: 65 additions & 40 deletions src/components/Editor/Runners/PythonRunner/PythonRunner.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import OutputViewToggle from "./OutputViewToggle";
import { SettingsContext } from "../../../../utils/settings";
import RunnerControls from "../../../RunButton/RunnerControls";
import { MOBILE_MEDIA_QUERY } from "../../../../utils/mediaQueryBreakpoints";
import classNames from "classnames";

const externalLibraries = {
"./pygal/__init__.js": {
Expand Down Expand Up @@ -53,7 +54,7 @@ const externalLibraries = {
},
};

const PythonRunner = () => {
const PythonRunner = ({ outputPanels = ["text", "visual"] }) => {
const projectCode = useSelector((state) => state.editor.project.components);
const projectIdentifier = useSelector(
(state) => state.editor.project.identifier,
Expand Down Expand Up @@ -127,11 +128,13 @@ const PythonRunner = () => {
const outf = (text) => {
if (text !== "") {
const node = output.current;
const div = document.createElement("span");
div.classList.add("pythonrunner-console-output-line");
div.innerHTML = new Option(text).innerHTML;
node.appendChild(div);
node.scrollTop = node.scrollHeight;
if (node) {
const div = document.createElement("span");
div.classList.add("pythonrunner-console-output-line");
div.innerHTML = new Option(text).innerHTML;
node.appendChild(div);
node.scrollTop = node.scrollHeight;
}
}
};

Expand Down Expand Up @@ -326,7 +329,9 @@ const PythonRunner = () => {
// clear previous output
dispatch(setError(""));
dispatch(setErrorDetails({}));
output.current.innerHTML = "";
if (output.current) {
output.current.innerHTML = "";
}
dispatch(setSenseHatEnabled(false));

var prog = projectCode[0].content;
Expand Down Expand Up @@ -389,54 +394,74 @@ const PythonRunner = () => {
}
}

const singleOutputPanel = outputPanels.length === 1;
const showVisualOutput = outputPanels.includes("visual");
const showTextOutput = outputPanels.includes("text");

const outputPanelClasses = (panelType) => {
return classNames("output-panel", `output-panel--${panelType}`, {
"output-panel--single": singleOutputPanel,
});
};

return (
<div className={`pythonrunner-container`}>
{isSplitView ? (
{isSplitView || singleOutputPanel ? (
<>
{hasVisualOutput ? (
<div className="output-panel output-panel--visual">
{hasVisualOutput && showVisualOutput && (
<div className={outputPanelClasses("visual")}>
<Tabs forceRenderTabPanel={true}>
<div className="react-tabs__tab-container">
<div
className={classNames("react-tabs__tab-container", {
"react-tabs__tab-container--hidden": singleOutputPanel,
})}
>
<TabList>
<Tab key={0}>
<span className="react-tabs__tab-text">
{t("output.visualOutput")}
</span>
</Tab>
</TabList>
{!isEmbedded && hasVisualOutput ? <OutputViewToggle /> : null}
{!isEmbedded && isMobile ? <RunnerControls skinny /> : null}
{!isEmbedded && hasVisualOutput && <OutputViewToggle />}
{!isEmbedded && isMobile && <RunnerControls skinny />}
</div>
<TabPanel key={0}>
<VisualOutputPane />
</TabPanel>
</Tabs>
</div>
) : null}
<div className="output-panel output-panel--text">
<Tabs forceRenderTabPanel={true}>
<div className="react-tabs__tab-container">
<TabList>
<Tab key={0}>
<span className="react-tabs__tab-text">
{t("output.textOutput")}
</span>
</Tab>
</TabList>
{!hasVisualOutput && !isEmbedded && isMobile ? (
<RunnerControls skinny />
) : null}
</div>
<ErrorMessage />
<TabPanel key={0}>
<pre
className={`pythonrunner-console pythonrunner-console--${settings.fontSize}`}
onClick={shiftFocusToInput}
ref={output}
></pre>
</TabPanel>
</Tabs>
</div>
)}
{showTextOutput && (
<div className={outputPanelClasses("text")}>
<Tabs forceRenderTabPanel={true}>
<div
className={classNames("react-tabs__tab-container", {
"react-tabs__tab-container--hidden": singleOutputPanel,
})}
>
<TabList>
<Tab key={0}>
<span className="react-tabs__tab-text">
{t("output.textOutput")}
</span>
</Tab>
</TabList>
{!hasVisualOutput && !isEmbedded && isMobile && (
<RunnerControls skinny />
)}
</div>
<ErrorMessage />
<TabPanel key={0}>
<pre
className={`pythonrunner-console pythonrunner-console--${settings.fontSize}`}
onClick={shiftFocusToInput}
ref={output}
></pre>
</TabPanel>
</Tabs>
</div>
)}
</>
) : (
<Tabs forceRenderTabPanel={true} defaultIndex={hasVisualOutput ? 0 : 1}>
Expand All @@ -455,8 +480,8 @@ const PythonRunner = () => {
</span>
</Tab>
</TabList>
{!isEmbedded && hasVisualOutput ? <OutputViewToggle /> : null}
{!isEmbedded && isMobile ? <RunnerControls skinny /> : null}
{!isEmbedded && hasVisualOutput && <OutputViewToggle />}
{!isEmbedded && isMobile && <RunnerControls skinny />}
</div>
{!isOutputOnly && <ErrorMessage />}
{hasVisualOutput ? (
Expand Down
6 changes: 4 additions & 2 deletions src/components/Editor/Runners/RunnerFactory.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from "react";
import PythonRunner from "./PythonRunner/PythonRunner";
import HtmlRunner from "./HtmlRunner/HtmlRunner";

const RunnerFactory = ({ projectType }) => {
const RunnerFactory = ({ projectType, outputPanels = ["text", "visual"] }) => {
const Runner = () => {
if (projectType === "html") {
return HtmlRunner;
Expand All @@ -12,7 +12,9 @@ const RunnerFactory = ({ projectType }) => {

const Selected = Runner();

return <Selected />;
const props = projectType === "html" ? {} : { outputPanels };

return <Selected {...props} />;
};

export default RunnerFactory;
7 changes: 6 additions & 1 deletion src/components/WebComponentProject/WebComponentProject.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const WebComponentProject = ({
withSidebar = false,
sidebarOptions = [],
outputOnly = false,
outputPanels = ["text", "visual"],
}) => {
const loading = useSelector((state) => state.editor.loading);
const project = useSelector((state) => state.editor.project);
Expand Down Expand Up @@ -94,7 +95,11 @@ const WebComponentProject = ({
{outputOnly && (
<div className="embedded-viewer">
{loading === "success" && (
<Output embedded={true} browserPreview={false} />
<Output
embedded={true}
browserPreview={false}
outputPanels={outputPanels}
/>
)}
</div>
)}
Expand Down
4 changes: 3 additions & 1 deletion src/containers/WebComponentLoader.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const WebComponentLoader = (props) => {
sidebarOptions = [],
theme,
outputOnly = false,
outputPanels = ["text", "visual"],
embedded = false,
hostStyles,
} = props;
Expand Down Expand Up @@ -156,6 +157,7 @@ const WebComponentLoader = (props) => {
withSidebar={withSidebar}
sidebarOptions={sidebarOptions}
outputOnly={outputOnly}
outputPanels={outputPanels}
/>
{errorModalShowing && <ErrorModal />}
{newFileModalShowing && <NewFileModal />}
Expand All @@ -166,7 +168,7 @@ const WebComponentLoader = (props) => {
</>
) : (
<>
<p>{t("webComponent.loading")}</p>;
<p>{t("webComponent.loading")}</p>
</>
);
};
Expand Down
8 changes: 7 additions & 1 deletion src/web-component.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class WebComponent extends HTMLElement {
"with_projectbar",
"with_sidebar",
"output_only",
"output_panels",
"sidebar_options",
"theme",
"embedded",
Expand All @@ -66,7 +67,12 @@ class WebComponent extends HTMLElement {
) {
value = newVal !== "false";
} else if (
["instructions", "sidebar_options", "host_styles"].includes(name)
[
"instructions",
"sidebar_options",
"host_styles",
"output_panels",
].includes(name)
) {
value = JSON.parse(newVal);
} else {
Expand Down