This project was bootstrapped with Create React App but the app has been ejected so build scripts etc. are all in the repo now.
The app uses the dotenv
package to provide access to environment variables.
Copy the example files into the correct place:
cp .env.example .env
Variables for the web component can be placed in .env
.
The app requires a Git token for access to private repos (currently limited to design-system-react
).
- Generated a token here, it'll be prefixed with
ghp_
: https://github.com/settings/tokens - Add a line to the bottom of
~/.npmrc
(this is in addition to the one in the repo)://npm.pkg.github.com/:_authToken=<github_token>
This will then be mounted as a secret in docker, and used to authenticate against the package repo.
In the project directory, you can run:
Runs the app in the development mode.
Open http://localhost:3011 to view it in the browser.
The page will reload if you make edits.
You will also see any lint errors in the console.
Launches the test runner in the interactive watch mode.
See the section about running tests for more information.
Builds the app for production to the build
folder.
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.
Your app is ready to be deployed!
See the section about deployment for more information.
Automated unit tests can be run via the yarn test
command. These unit tests are written using the JavaScript testing framework Jest
and make use of the tools provided by the React Testing Library. Automated accessibility testing for components is available via the jest-axe
library. This can be achieved using the haveNoViolations
matcher provided by jest-axe
, although this does not guarantee that the tested components have no accessibility issues.
Integration testing is carried out via cypress
and can be run using:
yarn exec cypress run
to run in the CLIyarn exec cypress open
to run in the GUI
Currently, there are basic cypress
tests for the standalone editor site, the web component and Mission Zero-related functionality. These can be found in the cypress/e2e
directory. Screenshots and videos related to the most recent cypress
test run can be found in cypress/screenshots
and cypress/videos
respectively.
The repo includes the Editor Web Component which shares components with the editor application but has a separate build process.
The web component can be included in a page by using the <editor-wc>
HTML element. It takes the following attributes
code
: A preset blob of code to show in the editor pane (overrides content ofmain.py
/index.html
)sense_hat_always_enabled
: Show the Astro Pi Sense HAT emulator on page loadload_remix_disabled
: Do not load a logged-in user's remixed version of the project specified byidentifier
even if one exists (defaults tofalse
)project_name_editable
: Allow the user to edit the project name in the project bar (defaults tofalse
)output_only
: Only display the output panel (defaults tofalse
)assets_identifier
: Load assets (not code) from this project identifieroutput_panels
: Array of panel names to display (defaults to["text", "visual"]
)embedded
: Enable embedded mode which hides some functionality (defaults tofalse
)output_split_view
: Start with split view in output panel (defaults tofalse
, i.e. tabbed view)
It is possible to add query strings to control how the web component is configured. Any HTML attribute can be set on the query string, including class
, style
etc.
For example, to load the page with the Sense Hat always showing, add ?sense_hat_always_enabled
to the URL
There are several mechanisms that can be utilised to style part or all of the web component. Due to the nature of the web component, styles can either be applied to the web component itself or to the page that contains the web component.
Internal styles can be utilised and shared between the standalone editor and the web component. These styles are passed to the web component via the style
attribute as a string and can be found in WebComponentProject.js
which uses InternalStyles.scss
and ExternalStyles.scss
to style the web component.
Internal styles can be utilised due to a --scale-factor
being set on font size and spacing variables and an update to the base font size being set at the appropriate size i.e. in WebComponent.scss. This enables the use of the existing font and spacing variables as well as the em
unit, allowing the web component to utilise the same definitions as the standalone editor.
NB due to rem
using the font-size
from the root it is unable to be overwritten in the shadow root so it should be avoided. Wherever possible use the existing calculations with the --scale-factor
or em
(however beware of nested relative sizing).
Styles from the parent application can be passed to the web component in a few different ways:
-
The web component utilises a shadow DOM, this creates a shadow root element in the DOM which is separate from the main DOM. It does however copy and create a new DOM tree from the main DOM with all styles applied to the root in the main DOM available in the shadow root.
-
A class can be applied to the custom element
wc-editor
which allows the parent application to style the web component container. This can be done by using theclass
attribute on the custom element. NB This attribute isclass
NOTclassName
. -
Other styles from the parent application will not be inherited by the web component. However, the web component can be styled by the parent application by using the
::part
pseudo-element selector. This allows the parent application to style the web component by targeting the web component's shadow DOM. For example, the following CSS will style the web component's#root
element (due to the part attribute definition in web-component.js):
::part(editor-root) {
// allows variables to be passed into the shadow dom
@include sauce-theme-primary-vars();
@include sauce-theme-secondary-vars();
// allows you to set custom variables inside the shadow dom
--editor-primary-theme: var(--theme-primary);
--editor-secondary-theme: var(--theme-secondary);
// background: var(--theme-secondary); // variables can then be applied inside the shadow dom
// enables the parent application to control the size of the web components root element
display: block;
flex: 1 1 auto;
max-block-size: 100dvh;
}
Classes from the stringified HTML passed to the web component in the instructions
attribute are being used to style the project steps in the instructions panel.
Styles for the task block can be applied as follows:
<h2 class="c-project-heading--task">Task heading</h2>
<div class="c-project-task">{task content here}</div>
There are three types of callout: tip, debugging and generic. The green tip callout is generated as follows:
<div class="c-project-callout c-project-callout--tip">
<h3>{Tip title}</h3>
{tip content here}
</div>
The red debugging callout is generated as follows:
<div class="c-project-callout c-project-callout--debug">
<h3>{Debugging title}</h3>
{debugging content here}
</div>
The blue generic callout is the default if no modifier is specifed:
<div class="c-project-callout">{callout content here}</div>
This class renders a bordered div
with monospaced text that resembles Python output. Other font styles and images are not yet supported.
<div class="c-project-output">{output content}</div>
Python code snippets are styled and syntax-highlighted using the language-python
class:
<code class="language-python">print('hello world')</code>
Deployment is managed through Github actions. The UI is deployed to staging and production environments via an S3 bucket. This requires the following environment variables to be set
AWS_ACCESS_KEY_ID
AWS_REGION
AWS_S3_BUCKET
AWS_SECRET_ACCESS_KEY
Other variables that pertain to the app, rather than its deployment are set with defaults in the build-and-deploy workflow. These are also in .env.example
.
Currently the build is deployed to both S3 and Heroku. The PR should get updated with the Heroku URL, and the web component demo is at /web-component.html
on the Heroku review app domain.
A new release of editor-ui
is created via following process:
- Create a branch on Github for the release.
- Update
CHANGELOG.md
with new version number and date in the list of changes underUnreleased
. - At the bottom of
CHANGELOG.md
, add a link for the new version and update theUnreleased
link to point to the latest version…HEAD
. - Update the version number in
package.json
to the new version number. - Push these changes to the release branch on Github.
- Create a PR on Github for the release branch and put the
CHANGELOG
diff for the new release in the description. - Get someone to approve the PR and then merge.
- Within the releases tab, create a new tag with the version number of the new release with the target set to
main
. - Give the release the same name as the tag and paste the
CHANGELOG
diff in the description. - Set the release to be the latest release and publish.
- Go to Cloudflare and under
Workers > KV
selecteditor
and change theproduction-ref
toreleases/<new_version_number>
. - Go to
editor.raspberrypi.org
to see the new changes on production... 🚀