diff --git a/.circleci/config.yml b/.circleci/config.yml index 0fd545f7a..84e7f3694 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -8,92 +8,74 @@ aliases: username: $DOCKERHUB_USERNAME password: $DOCKERHUB_PASSWORD working_directory: ~/repo - - &save_git_cache - save_cache: - paths: - - .git - key: v1-git-{{ .Revision }} - - &restore_git_cache - restore_cache: - keys: - - v1-git-{{ .Revision }} - - v1-git- - - &save_npm_cache - save_cache: - paths: - - node_modules - key: v1-npm-{{ checksum "package-lock.json" }} - - &restore_npm_cache - restore_cache: - keys: - - v1-npm-{{ checksum "package-lock.json" }} - - &save_build_cache - save_cache: - paths: - - ./build - - ./intl - key: v1-build-{{ .Revision }} - - &restore_build_cache - restore_cache: - keys: - - v1-build-{{ .Revision }} - - v1-build- - - &build_no_cache + - &setup + name: "setup" + command: | + npm --production=false ci + mkdir ./test/results + - &lint + name: "run lint tests" + command: | + npm run test:lint:ci + - &build + name: "run npm build" + command: | + WWW_VERSION=${CIRCLE_SHA1:0:5} npm run build + - &unit + name: "Run unit tests" + command: | + JEST_JUNIT_OUTPUT_NAME=unit-jest-results.xml npm run test:unit:jest:unit -- --reporters=jest-junit + JEST_JUNIT_OUTPUT_NAME=localization-jest-results.xml npm run test:unit:jest:localization -- --reporters=jest-junit + npm run test:unit:tap -- --output-file ./test/results/unit-raw.tap + npm run test:unit:convertReportToXunit + - &setup_python + name: "setup python" + command: | + curl https://bootstrap.pypa.io/pip/3.5/get-pip.py -o get-pip.py + python3 get-pip.py pip==21.0.1 + pip install s3cmd==2.1.0 + - &deploy + name: "deploy" + command: | + npm run deploy + - &integration + name: "integration tests with Jest" + command: | + JEST_JUNIT_OUTPUT_NAME=integration-jest-results.xml npm run test:integration:remote -- --reporters=jest-junit + - &build_no_deploy <<: *defaults resource_class: large steps: - checkout - run: - name: "setup" - command: | - npm --production=false ci - mkdir ./test/results + <<: *setup - run: - name: "run lint tests" - command: | - npm run test:lint:ci + <<: *lint - run: - name: "run npm build" - command: | - WWW_VERSION=${CIRCLE_SHA1:0:5} npm run build + <<: *build - run: - name: "Run unit tests" - command: | - JEST_JUNIT_OUTPUT_NAME=unit-jest-results.xml npm run test:unit:jest:unit -- --reporters=jest-junit - JEST_JUNIT_OUTPUT_NAME=localization-jest-results.xml npm run test:unit:jest:localization -- --reporters=jest-junit - npm run test:unit:tap -- --output-file ./test/results/unit-raw.tap - npm run test:unit:convertReportToXunit + <<: *unit - store_test_results: path: test/results - - &build + - &build_and_deploy <<: *defaults resource_class: large steps: - - *restore_git_cache - checkout - run: - name: "setup" - command: | - npm --production=false ci - mkdir ./test/results + <<: *setup - run: - name: "run lint tests" - command: | - npm run test:lint:ci + <<: *lint - run: - name: "run npm build" - command: | - WWW_VERSION=${CIRCLE_SHA1:0:5} npm run build + <<: *build - run: - name: "Run unit tests" - command: | - JEST_JUNIT_OUTPUT_NAME=unit-jest-results.xml npm run test:unit:jest:unit -- --reporters=jest-junit - JEST_JUNIT_OUTPUT_NAME=localization-jest-results.xml npm run test:unit:jest:localization -- --reporters=jest-junit - npm run test:unit:tap -- --output-file ./test/results/unit-raw.tap - npm run test:unit:convertReportToXunit - - *save_npm_cache - - *save_git_cache - - *save_build_cache + <<: *unit + - run: + <<: *setup_python + - run: + <<: *deploy + - run: + <<: *integration - store_test_results: path: test/results - run: @@ -101,35 +83,6 @@ aliases: command: tar -cvzf build.tar build - store_artifacts: path: build.tar - - &deploy - <<: *defaults - steps: - - *restore_git_cache - - checkout - - *restore_npm_cache - - *restore_build_cache - - run: - name: "setup python" - command: | - curl https://bootstrap.pypa.io/pip/3.5/get-pip.py -o get-pip.py - python3 get-pip.py pip==21.0.1 - pip install s3cmd==2.1.0 - - run: - name: "deploy" - command: | - npm run deploy - - &integration_jest - <<: *defaults - steps: - - *restore_git_cache - - checkout - - *restore_npm_cache - - run: - name: "integration tests with Jest" - command: | - JEST_JUNIT_OUTPUT_NAME=integration-jest-results.xml npm run test:integration:remote -- --reporters=jest-junit - - store_test_results: - path: test/results - &update-translations <<: *defaults steps: @@ -141,28 +94,21 @@ aliases: name: "run i18n script" command: npm run i18n:push +# build-test-deploy requires two separately named jobs jobs: - build-staging: - <<: *build - build-production: - <<: *build - deploy-staging: - <<: *deploy - deploy-production: - <<: *deploy - integration-staging-jest: - <<: *integration_jest - integration-production-jest: - <<: *integration_jest + build-and-deploy-staging: + <<: *build_and_deploy + build-and-deploy-production: + <<: *build_and_deploy update-translations: <<: *update-translations - build-no-cache: - <<: *build_no_cache + build-no-deploy: + <<: *build_no_deploy workflows: build-test-deploy: jobs: - - build-staging: + - build-and-deploy-staging: context: - scratch-www-all - scratch-www-staging @@ -172,7 +118,7 @@ workflows: - develop - /^hotfix\/.*/ - /^release\/.*/ - - build-production: + - build-and-deploy-production: context: - scratch-www-all - scratch-www-production @@ -180,50 +126,6 @@ workflows: branches: only: - master - - deploy-staging: - context: - - scratch-www-all - - scratch-www-staging - requires: - - build-staging - filters: - branches: - only: - - develop - - /^hotfix\/.*/ - - /^release\/.*/ - - deploy-production: - context: - - scratch-www-all - - scratch-www-production - requires: - - build-production - filters: - branches: - only: - - master - - integration-staging-jest: - context: - - scratch-www-all - - scratch-www-staging - requires: - - deploy-staging - filters: - branches: - only: - - develop - - /^hotfix\/.*/ - - /^release\/.*/ - - integration-production-jest: - context: - - scratch-www-all - - scratch-www-production - requires: - - deploy-production - filters: - branches: - only: - - master Update-translations: triggers: - schedule: # every evening at 7pm EST (8pm EDT, Midnight UTC) @@ -242,7 +144,7 @@ workflows: - develop build-test-no-deploy: jobs: - - build-no-cache: + - build-no-deploy: filters: branches: ignore: diff --git a/package-lock.json b/package-lock.json index d5e4340fa..c4e029dbf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4509,9 +4509,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001300", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001300.tgz", - "integrity": "sha512-cVjiJHWGcNlJi8TZVKNMnvMid3Z3TTdDHmLDzlOdIiZq138Exvo0G+G0wTdVYolxKb4AYwC+38pxodiInVtJSA==", + "version": "1.0.30001305", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001305.tgz", + "integrity": "sha512-p7d9YQMji8haf0f+5rbcv9WlQ+N5jMPfRAnUmZRlNxsNeBO3Yr7RYG6M2uTY1h9tCVdlkJg6YNNc4kiAiBLdWA==", "dev": true }, "canvas-fit": { @@ -20578,9 +20578,9 @@ } }, "scratch-gui": { - "version": "0.1.0-prerelease.20220118124756", - "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20220118124756.tgz", - "integrity": "sha512-dyF9po7oRRIjslNFZoRa6I46YtKf5qeOEbDYk/bmqHdcr6MqnqVv6fV9je8PuBNCY9La/PbpPmbG2KsEr+Z37g==", + "version": "0.1.0-prerelease.20220202135032", + "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20220202135032.tgz", + "integrity": "sha512-OelxP2ULGnLz0f2Y10rdZ2cAipM2Iho8ZJYewesevOs3KhZKQguyj+b0D3T2fTxnU8CXKq36dpt7oGFGxJcPLg==", "dev": true, "requires": { "arraybuffer-loader": "^1.0.6", @@ -20789,9 +20789,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.4.47", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.47.tgz", - "integrity": "sha512-ZHc8i3/cgeCRK/vC7W2htAG6JqUmOUgDNn/f9yY9J8UjfLjwzwOVEt4MWmgJAdvmxyrsR5KIFA/6+kUHGY0eUA==", + "version": "1.4.61", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.61.tgz", + "integrity": "sha512-kpzCOOFlx63C9qKRyIDEsKIUgzoe98ump7T4gU+/OLzj8gYkkWf2SIyBjhTSE0keAjMAp3i7C262YtkQOMYrGw==", "dev": true }, "has-flag": { @@ -20994,6 +20994,18 @@ "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", "dev": true }, + "scratch-l10n": { + "version": "3.14.20220118031528", + "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.14.20220118031528.tgz", + "integrity": "sha512-y5Mzi+r6hxZ3kfax3aXhfiJwJIfN8FHdcvLd0E46KqUjpbvbs1TTUZjWBQdV9SmWAwii8L7U0z+1iWN4+K7W+A==", + "dev": true, + "requires": { + "@babel/cli": "^7.1.2", + "@babel/core": "^7.1.2", + "babel-plugin-react-intl": "^3.0.1", + "transifex": "1.6.6" + } + }, "scratch-storage": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/scratch-storage/-/scratch-storage-1.3.5.tgz", @@ -21060,9 +21072,9 @@ } }, "scratch-l10n": { - "version": "3.14.20220118031528", - "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.14.20220118031528.tgz", - "integrity": "sha512-y5Mzi+r6hxZ3kfax3aXhfiJwJIfN8FHdcvLd0E46KqUjpbvbs1TTUZjWBQdV9SmWAwii8L7U0z+1iWN4+K7W+A==", + "version": "3.14.20220202031539", + "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.14.20220202031539.tgz", + "integrity": "sha512-OBMVkfjuRpfOTF9+u9JrKyrJEIlvRbJzYd9KxiSvJLjF8BsdS4fALJDa8Yl4GX0w/DInSHt+iiO8xgtdf7WjgQ==", "dev": true, "requires": { "@babel/cli": "^7.1.2", diff --git a/package.json b/package.json index 133adc70d..e01ee74d4 100644 --- a/package.json +++ b/package.json @@ -127,8 +127,8 @@ "redux-thunk": "2.0.1", "regenerator-runtime": "0.13.9", "sass-loader": "6.0.6", - "scratch-gui": "0.1.0-prerelease.20220118124756", - "scratch-l10n": "3.14.20220118031528", + "scratch-gui": "0.1.0-prerelease.20220202135032", + "scratch-l10n": "3.14.20220202031539", "selenium-webdriver": "4.1.0", "slick-carousel": "1.6.0", "style-loader": "0.12.3", diff --git a/src/components/forms/radio-group.jsx b/src/components/forms/radio-group.jsx index 168f0a926..608748b0a 100644 --- a/src/components/forms/radio-group.jsx +++ b/src/components/forms/radio-group.jsx @@ -11,7 +11,7 @@ require('./radio-group.scss'); const RadioGroup = props => ( ); diff --git a/src/components/registration/steps.jsx b/src/components/registration/steps.jsx index da8fcd1aa..8dc4d9d4a 100644 --- a/src/components/registration/steps.jsx +++ b/src/components/registration/steps.jsx @@ -792,7 +792,7 @@ class OrganizationStep extends React.Component { }} />
- +

@@ -833,7 +833,7 @@ class OrganizationStep extends React.Component { />
- +

diff --git a/src/components/registration/steps.scss b/src/components/registration/steps.scss index a2cc34a58..1dd988309 100644 --- a/src/components/registration/steps.scss +++ b/src/components/registration/steps.scss @@ -26,6 +26,18 @@ } } + .row { + label { + font-weight: bold; + } + + .checkbox { + label { + font-weight: 300; + } + } + } + .help-text { margin: .25rem 0; text-align: left; @@ -66,6 +78,10 @@ &.demographics-step { .radio { margin: 1.5rem 1.5rem 0 0; + + label { + font-weight: 300; + } } input[type="radio"] { diff --git a/src/views/ethics/ethics.jsx b/src/views/ethics/ethics.jsx index 5c8419ea9..f6317be29 100644 --- a/src/views/ethics/ethics.jsx +++ b/src/views/ethics/ethics.jsx @@ -25,6 +25,11 @@ const Ethics = () => ( + ), + researchEmailLink: ( + + research@scratchfoundation.org + ) }} />

diff --git a/src/views/ethics/l10n.json b/src/views/ethics/l10n.json index 380a9aa94..db30d8b92 100644 --- a/src/views/ethics/l10n.json +++ b/src/views/ethics/l10n.json @@ -1,11 +1,11 @@ { "ethics.title": "Scratch Foundation Research Code of Ethics", - "ethics.intro1": "At the Scratch Foundation, our mission is to provide young people with digital tools and equitable opportunities to imagine, create, share, and learn. The Scratch platform is a free, safe, playful learning environment that engages all children in thinking creatively, reasoning systematically, and working collaboratively — essential skills for everyone in today's society. We work with educators and families to support children in this playful learning environment.", - "ethics.intro2": "This Code of Ethics guides Scratch Foundation employees and affiliates as they conduct research and evaluation in support of the efforts to improve the platform, user experience, teaching and learning outcomes, and grant-funded work. All research and evaluation work at the Foundation adheres to the following principles.", - "ethics.principle1Title": "Principle 1: Protect our users.", - "ethics.principle1": "{title} Scratch Foundation employees and contractors respect the privacy and confidentiality of users. Employees and contractors will not disclose any personally identifiable information about any user without the permission of the user or (if a minor) the user’s parent or guardian.", - "ethics.principle2Title": "Principle 2: Lead with honesty.", - "ethics.principle2": "{title} When collecting data, Foundation staff and contractors will disclose the objective, rationale, ways in which we safeguard data, and relevant Foundation contact information for anyone who requests that information.", - "ethics.principle3Title": "Principle 3. Adhere to the law.", - "ethics.principle3": "{title} Foundation staff and contractors will adhere to the spirit and letter of the law, particularly with regard to digital privacy policies such as (but not limited to) the Scratch Privacy Policy and the General Data Protection Regulation (GDPR)." + "ethics.intro1": "At the Scratch Foundation, our mission is to provide young people with digital tools and opportunities to imagine, create, share, and learn. The Scratch platform is a free, safe, playful learning environment that engages all children in thinking creatively, reasoning systematically, and working collaboratively — essential skills for everyone in today's society. We work with educators and families to support children in this playful learning environment.", + "ethics.intro2": "This Code of Ethics guides Scratch Foundation employees and affiliates as they conduct research and evaluation in support of the efforts to improve the platform, participant experience, teaching and learning outcomes, and grant-funded work. All research and evaluation work at the Foundation adheres to the following principles.", + "ethics.principle1Title": "Principle 1: Protect our participants.", + "ethics.principle1": "{title} Scratch Foundation employees and contractors respect the privacy and confidentiality of participants. Employees and contractors will not disclose any personally identifiable information about any participant without the permission of the participant and (if a minor) the participant’s parent or guardian. Additionally, we will avoid causing harm to participants and seek to maximize the benefits of participation. Participation in research activities is always voluntary; contact us at {researchEmailLink} to opt-out.", + "ethics.principle2Title": "Principle 2: Lead with transparency.", + "ethics.principle2": "{title} When collecting data, Foundation staff and contractors will disclose the objective, participation requirements (including time and effort), any possible participation-related risks, ways in which we will safeguard and report the data, ways in which participants can opt out, and relevant Foundation contact information. ", + "ethics.principle3Title": "Principle 3. Embrace data-stewardship.", + "ethics.principle3": "{title} Foundation staff and contractors will ensure data security and compliance with digital privacy policies such as (but not limited to) the Scratch Privacy Policy and the General Data Protection Regulation (GDPR). " } diff --git a/webpack.config.js b/webpack.config.js index 87a89ab73..bb2678140 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -8,6 +8,7 @@ const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPl const CopyWebpackPlugin = require('copy-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); +const TerserPlugin = require('terser-webpack-plugin'); // PostCss const autoprefixer = require('autoprefixer'); @@ -141,7 +142,12 @@ module.exports = { minChunks: pageRoutes.length // Extract only chunks common to all html pages } } - } + }, + minimizer: [ + new TerserPlugin({ + parallel: 4 + }) + ] }, plugins: [ new MiniCssExtractPlugin(),