diff --git a/package-lock.json b/package-lock.json index 7f5fd339b..2e6b893e4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,7 +43,7 @@ "babel-preset-react": "6.24.1", "bowser": "1.9.4", "canvas": "2.9.0", - "chromedriver": "105.0.0", + "chromedriver": "114.0.3", "classnames": "2.2.5", "cookie": "0.4.1", "copy-webpack-plugin": "6.4.1", @@ -101,8 +101,8 @@ "regenerator-runtime": "0.13.9", "sass": "1.49.7", "sass-loader": "10.2.1", - "scratch-gui": "2.0.77", - "scratch-l10n": "3.15.20230718032211", + "scratch-gui": "2.0.80", + "scratch-l10n": "3.15.20230801032207", "selenium-webdriver": "4.1.0", "slick-carousel": "1.6.0", "style-loader": "0.12.3", @@ -1897,9 +1897,9 @@ } }, "node_modules/@testim/chrome-version": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.2.tgz", - "integrity": "sha512-1c4ZOETSRpI0iBfIFUqU4KqwBAB2lHUAlBjZz/YqOHqwM9dTTzjV6Km0ZkiEiSCx/tLr1BtESIKyWWMww+RUqw==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.3.tgz", + "integrity": "sha512-g697J3WxV/Zytemz8aTuKjTGYtta9+02kva3C1xc7KXB8GdbfE1akGJIsZLyY/FSh2QrnE+fiB7vmWU3XNcb6A==", "dev": true }, "node_modules/@transifex/api": { @@ -3025,13 +3025,14 @@ "dev": true }, "node_modules/axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", "dev": true, "dependencies": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, "node_modules/axios/node_modules/form-data": { @@ -5368,17 +5369,17 @@ } }, "node_modules/chromedriver": { - "version": "105.0.0", - "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-105.0.0.tgz", - "integrity": "sha512-BX3GOUW5m6eiW9cVVF8hw+EFxvrGqYCxbwOqnpk8PjbNFqL5xjy7yel+e6ilJPjckAYFutMKs8XJvOs/W85vvg==", + "version": "114.0.3", + "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-114.0.3.tgz", + "integrity": "sha512-Qy5kqsAUrCDwpovM5pIWFkb3X3IgJLoorigwFEDgC1boL094svny3N7yw06marJHAuyX4CE/hhd25RarIcKvKg==", "dev": true, "hasInstallScript": true, "dependencies": { - "@testim/chrome-version": "^1.1.2", - "axios": "^0.27.2", - "del": "^6.0.0", + "@testim/chrome-version": "^1.1.3", + "axios": "^1.4.0", + "compare-versions": "^6.0.0", "extract-zip": "^2.0.1", - "https-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", "proxy-from-env": "^1.1.0", "tcp-port-used": "^1.0.1" }, @@ -5386,7 +5387,7 @@ "chromedriver": "bin/chromedriver" }, "engines": { - "node": ">=10" + "node": ">=16" } }, "node_modules/cipher-base": { @@ -5755,6 +5756,12 @@ "compare-cell": "^1.0.0" } }, + "node_modules/compare-versions": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.0.0.tgz", + "integrity": "sha512-s2MzYxfRsE9f/ow8hjn7ysa7pod1xhHdQMsgiJtKx6XSNf4x2N1KG4fjrkUmXcP/e9Y2ZX4zB6sHIso0Lm6evQ==", + "dev": true + }, "node_modules/component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", @@ -7657,158 +7664,6 @@ "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", "dev": true }, - "node_modules/del": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", - "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", - "dev": true, - "dependencies": { - "globby": "^11.0.1", - "graceful-fs": "^4.2.4", - "is-glob": "^4.0.1", - "is-path-cwd": "^2.2.0", - "is-path-inside": "^3.0.2", - "p-map": "^4.0.0", - "rimraf": "^3.0.2", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/del/node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/del/node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/del/node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/del/node_modules/globby": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/del/node_modules/graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", - "dev": true - }, - "node_modules/del/node_modules/ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/del/node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del/node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del/node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/del/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/del/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/delaunay-triangulate": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/delaunay-triangulate/-/delaunay-triangulate-1.1.6.tgz", @@ -12681,9 +12536,9 @@ "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" }, "node_modules/https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "dev": true, "dependencies": { "agent-base": "6", @@ -13581,24 +13436,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -23520,10 +23357,28 @@ "scratch-l10n": "3.15.20230718032211" } }, + "node_modules/scratch-blocks/node_modules/scratch-l10n": { + "version": "3.15.20230718032211", + "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.15.20230718032211.tgz", + "integrity": "sha512-USFDniZJP3QpTnBKKXBNw7w0jjvx6qCP5bWkNEF/xRIypSywJ1O2Os9CSSzm3tq7lHqXJRD5XVfxgvC+H0Xp2A==", + "dev": true, + "dependencies": { + "@babel/cli": "^7.1.2", + "@babel/core": "^7.1.2", + "@transifex/api": "4.2.5", + "babel-plugin-react-intl": "^3.0.1", + "download": "^8.0.0", + "transifex": "1.6.6" + }, + "bin": { + "build-i18n-src": "scripts/build-i18n-src.js", + "tx-push-src": "scripts/tx-push-src.js" + } + }, "node_modules/scratch-gui": { - "version": "2.0.77", - "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-2.0.77.tgz", - "integrity": "sha512-saaYzmcM0aeD3busS8xt91s4vdtLhom30FYxIVu8+YIbvoPeFChwE3c5b/PqeUgiprpubHs8K4UhDnzTfTYe0A==", + "version": "2.0.80", + "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-2.0.80.tgz", + "integrity": "sha512-MTL7hGcTo8xVp7MR78RKMcBQnFTaem72oradRbpfSQkM0X4yDaM8FmqxYHle5laxA5CoL2WdfRLs01CgmsJ2kg==", "dev": true, "dependencies": { "@microbit/microbit-universal-hex": "0.2.2", @@ -23579,13 +23434,13 @@ "redux-throttle": "0.1.1", "scratch-audio": "0.1.0-prerelease.20221123180128", "scratch-blocks": "0.2.0-prerelease.20230718081157", - "scratch-l10n": "3.15.20230718032211", - "scratch-paint": "2.0.21", + "scratch-l10n": "3.15.20230801032207", + "scratch-paint": "2.0.23", "scratch-render": "0.1.0-prerelease.20230710194419", "scratch-render-fonts": "1.0.0-prerelease.20221102164332", "scratch-storage": "2.2.1", "scratch-svg-renderer": "0.2.0-prerelease.20230710144521", - "scratch-vm": "1.5.90", + "scratch-vm": "1.5.92", "startaudiocontext": "1.2.1", "style-loader": "^0.23.0", "text-encoding": "0.7.0", @@ -23935,9 +23790,9 @@ } }, "node_modules/scratch-gui/node_modules/scratch-paint": { - "version": "2.0.21", - "resolved": "https://registry.npmjs.org/scratch-paint/-/scratch-paint-2.0.21.tgz", - "integrity": "sha512-LoEUU53rO5zJSp4dGOvAg0jFXkd/jiloETr2yz2AcNizCbPhWnQ0fz7bRR+pOEHzkMOsJk4rapfeSSyI1ed1VA==", + "version": "2.0.23", + "resolved": "https://registry.npmjs.org/scratch-paint/-/scratch-paint-2.0.23.tgz", + "integrity": "sha512-e7/wOnzzfUCNwpo3bIZc+zHaSWKHgsk5wM68eXDDlyToYbsybmpaz+cNJBLQ3kjQeKa1Co9fNnsfAatJPrcV9Q==", "dev": true, "dependencies": { "@scratch/paper": "0.11.20200728195508", @@ -24004,9 +23859,9 @@ } }, "node_modules/scratch-gui/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", + "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==", "dev": true, "peer": true }, @@ -24023,9 +23878,9 @@ } }, "node_modules/scratch-l10n": { - "version": "3.15.20230718032211", - "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.15.20230718032211.tgz", - "integrity": "sha512-USFDniZJP3QpTnBKKXBNw7w0jjvx6qCP5bWkNEF/xRIypSywJ1O2Os9CSSzm3tq7lHqXJRD5XVfxgvC+H0Xp2A==", + "version": "3.15.20230801032207", + "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.15.20230801032207.tgz", + "integrity": "sha512-q2ALpTqN08z+cxVvQjAhjz3ONOsMpVwMI4qqiYJkIVYjpA6gkXmSPEfQ9gstiIlREcKVyQB1Me7RMWqdy+ncJg==", "dev": true, "dependencies": { "@babel/cli": "^7.1.2", @@ -24226,9 +24081,9 @@ "dev": true }, "node_modules/scratch-vm": { - "version": "1.5.90", - "resolved": "https://registry.npmjs.org/scratch-vm/-/scratch-vm-1.5.90.tgz", - "integrity": "sha512-YfxsYhF8pS9VJMJVGQdE17QU0B76Zm+HDeI+7bxqqrSSNbxylRPr4wJS8juTY2RJgiYQZ0ajAHBGB8cNk7+vIA==", + "version": "1.5.92", + "resolved": "https://registry.npmjs.org/scratch-vm/-/scratch-vm-1.5.92.tgz", + "integrity": "sha512-c6jyS+cq70K36DxvqzBYdLok0Sky4Y1ZovAJWxtocw9HnspxCzDnOoAiHcJIZhj4i/gXEDMiV8N3WjpOX2cvNg==", "dev": true, "dependencies": { "@vernier/godirect": "1.5.0", diff --git a/package.json b/package.json index 451dc08d5..fa4f97b3f 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "babel-preset-react": "6.24.1", "bowser": "1.9.4", "canvas": "2.9.0", - "chromedriver": "105.0.0", + "chromedriver": "114.0.3", "classnames": "2.2.5", "cookie": "0.4.1", "copy-webpack-plugin": "6.4.1", @@ -136,8 +136,8 @@ "regenerator-runtime": "0.13.9", "sass": "1.49.7", "sass-loader": "10.2.1", - "scratch-gui": "2.0.77", - "scratch-l10n": "3.15.20230718032211", + "scratch-gui": "2.0.80", + "scratch-l10n": "3.15.20230801032207", "selenium-webdriver": "4.1.0", "slick-carousel": "1.6.0", "style-loader": "0.12.3", diff --git a/src/components/extension-landing/extension-requirements.jsx b/src/components/extension-landing/extension-requirements.jsx index ce9281396..27620e277 100644 --- a/src/components/extension-landing/extension-requirements.jsx +++ b/src/components/extension-landing/extension-requirements.jsx @@ -27,7 +27,7 @@ const ExtensionRequirements = props => ( alt="" src="/svgs/extensions/mac.svg" /> - macOS 10.13+ + macOS 10.15+ )} {!props.hideChromeOS && ( diff --git a/src/components/extension-landing/extension-troubleshooting.jsx b/src/components/extension-landing/extension-troubleshooting.jsx index c06ee17c2..737ce4505 100644 --- a/src/components/extension-landing/extension-troubleshooting.jsx +++ b/src/components/extension-landing/extension-troubleshooting.jsx @@ -4,6 +4,9 @@ const React = require('react'); const ExtensionSection = require('./extension-section.jsx'); +const OS_ENUM = require('../../lib/os-enum.js'); +const {isDownloaded} = require('../install-scratch/install-util.js'); + // TODO: after the Scratch Conference 2022, migrate from the individual extension landing pages all the // troubleshooting steps which are common to all extensions. const ExtensionTroubleshooting = props => { @@ -17,14 +20,24 @@ const ExtensionTroubleshooting = props => { id="extensions.troubleshootingTitle" values={sharedValues} /> -

-

+ {(isDownloaded(props.currentOS)) && ( +

+

+

+

)} {props.children} {!props.scratchLinkOnly && ( @@ -44,6 +57,7 @@ const ExtensionTroubleshooting = props => { ExtensionTroubleshooting.propTypes = { children: PropTypes.node, + currentOS: PropTypes.string.isRequired, deviceName: PropTypes.string.isRequired, deviceNameShort: PropTypes.string, scratchLinkOnly: PropTypes.bool diff --git a/src/components/extension-landing/install-scratch-link.jsx b/src/components/extension-landing/install-scratch-link.jsx index 9c6418b6a..a50354436 100644 --- a/src/components/extension-landing/install-scratch-link.jsx +++ b/src/components/extension-landing/install-scratch-link.jsx @@ -75,11 +75,6 @@ const InstallScratchLink = ({ }-toolbar.png`} /> -

{ body.user.banned && banGoodListPaths.every(goodPath => window.location.pathname.indexOf(goodPath) === -1) ) { - window.location = '/accounts/banned-response/'; + if (body.user.banned_status === 'far_banned'){ + window.location = '/accounts/bad-username/'; + } else { + window.location = '/accounts/banned-response/'; + } return; } else if ( body.flags && diff --git a/src/routes.json b/src/routes.json index 06e47904d..e7a033616 100644 --- a/src/routes.json +++ b/src/routes.json @@ -430,6 +430,13 @@ "view": "microbit/microbit", "title": "micro:bit" }, + { + "name": "bad-username-splash", + "pattern": "^/accounts/bad-username/?(\\?.*)?$", + "routeAlias": "/accounts/bad-username/?$", + "view": "bad-username-splash/bad-username-splash", + "title": "Account Blocked" + }, { "name": "vernier", "pattern": "^/vernier/?(\\?.*)?$", diff --git a/src/views/bad-username-splash/bad-username-splash.jsx b/src/views/bad-username-splash/bad-username-splash.jsx new file mode 100644 index 000000000..4c5e2e40e --- /dev/null +++ b/src/views/bad-username-splash/bad-username-splash.jsx @@ -0,0 +1,293 @@ +const injectIntl = require('react-intl').injectIntl; +const React = require('react'); +const FormattedMessage = require('react-intl').FormattedMessage; +import {connect} from 'react-redux'; +import {selectUser, selectHasFetchedSession} from '../../redux/session'; +const messageActions = require('../../redux/messages.js'); +const JoinFlowStep = require('../../components/join-flow/join-flow-step.jsx'); +const FormikInput = require('../../components/formik-forms/formik-input.jsx'); +import {Formik} from 'formik'; +const PropTypes = require('prop-types'); + +const Page = require('../../components/page/www/page.jsx'); +const render = require('../../lib/render.jsx'); +const api = require('../../lib/api'); +import bannedIcon from './blocked-account.svg'; + +require('../../components/extension-landing/extension-landing.scss'); +require('./bad-username-splash.scss'); + +const validateNewUsernameForm = values => { + const errors = {}; + if (values.canValidate && (values.newUsername !== values.newUsernameConfirm && values.newUsernameConfirm !== '')){ + errors.newUsernameConfirm = "usernames don't match"; + } + return errors; +}; + +const PIIUsernameMessage = 'username appears to contain personal information'; +const BadUsernameMessage = 'an inappropriate username'; + +const BannedSplash = ({hasSession, user, adminMessages, getAdminMessages}) => { + + const [unauthorizedError, setUnauthorizedError] = React.useState(false); + const [badUsernameError, setBadUsernameError] = React.useState(false); + const [apiError, setAPIError] = React.useState(false); + + const latestAdminMessage = adminMessages && adminMessages[0] && adminMessages[0].message; + + React.useEffect(() => { + if (user && user.username && user.token){ + getAdminMessages(user.username, user.token); + } + }, [user]); + + const handleUpdateUsernameUnbanSubmit = (formData, formikBag) => { + setUnauthorizedError(false); + setBadUsernameError(false); + setAPIError(false); + formikBag.setSubmitting(false); // formik makes us do this ourselves + + api({ + host: '', + uri: '/accounts/update_username/', + method: 'post', + useCsrf: true, + json: { + new_username: formData.newUsername, + username: formData.username, + password: formData.password + } + }, (err, body, res) => { + if (res.body.error === 'Unauthorized'){ + setUnauthorizedError('error message for unauthorized access'); + } else if (res.body.error === 'Invalid username'){ + setBadUsernameError('error message for invalid username'); + } else if (res.body.error){ + setAPIError('error message for API error'); + } else { + window.location = '/'; + } + }); + }; + + if (hasSession && (!user || !user.banned)){ + window.location = '/'; + } + + if (user && user.banned){ + return (
+
+
+
+ + +

+
+

+ + {latestAdminMessage && latestAdminMessage.includes(PIIUsernameMessage) && + (
+

+

+

+
) + } + {latestAdminMessage && latestAdminMessage.includes(BadUsernameMessage) && + (
+

+

+

+ + + ) + }} + />

+
) + } +
+ +
+ + {({ + errors, + handleSubmit, + isSubmitting, + setFieldError, + setFieldTouched, + setFieldValue, + validateForm + }) => ( + + + + ) + }} + />} + innerClassName="change-username-inner" + outerClassName="change-username-outer" + title={} + waiting={isSubmitting} + onSubmit={handleSubmit} + nextButton={} + > +
+ Create a new username + { + setFieldValue('newUsername', e.target.value.substring(0, 30)); + setFieldValue('canValidate', false); + setFieldTouched('newUsername'); + setFieldError('newUsername', null); + }} + /> + { + setFieldValue('newUsernameConfirm', e.target.value.substring(0, 30)); + setFieldTouched('newUsernameConfirm'); + setFieldError('newUsernameConfirm', null); + setFieldValue('canValidate', false); + }} + onBlur={() => { + setFieldValue('canValidate', true).then(validateForm()); + }} + /> + Password + { + setFieldValue('password', e.target.value); + setFieldTouched('password'); + setFieldError('password', null); + }} + /> +
+
)} +
+
+
+
+
+
+ +
+ {adminMessages.map(message => ( +
+
+ {new Date(message.datetime_created).toDateString()} +
+ {/* eslint-disable-next-line react/no-danger */} +
+
+ ))} +
+
+ ); + } + return
; +}; + +BannedSplash.propTypes = { + user: PropTypes.shape({ + username: PropTypes.string, + banned: PropTypes.bool, + token: PropTypes.string + }), + hasSession: PropTypes.bool, + adminMessages: PropTypes.arrayOf(PropTypes.shape({ + id: PropTypes.number.isRequired, + datetimeCreated: PropTypes.string.isRequired, + message: PropTypes.string.isRequired + })), + getAdminMessages: PropTypes.func +}; + +const ConnectedBannedSplash = connect( + state => ({ + user: selectUser(state), + hasSession: selectHasFetchedSession(state), + adminMessages: state.messages.messages && + state.messages.messages.admin && + state.messages.messages.admin.sort((a, b) => + (b.id - a.id) + ) + }), + dispatch => ({ + getAdminMessages: (username, token) => { + dispatch(messageActions.getAdminMessages( + username, token, 0 + )); + } + }) +)(BannedSplash); + + +const WrappedBannedSplash = injectIntl(ConnectedBannedSplash); + +render(, document.getElementById('app'), + {messages: messageActions.messagesReducer}); diff --git a/src/views/bad-username-splash/bad-username-splash.scss b/src/views/bad-username-splash/bad-username-splash.scss new file mode 100644 index 000000000..8a858aa58 --- /dev/null +++ b/src/views/bad-username-splash/bad-username-splash.scss @@ -0,0 +1,134 @@ +@import "../../colors"; +@import "../../frameless"; + +.validation-left { + transform: translate(-20.5rem, 0); +} + +@media #{$intermediate-and-smaller} { + .validation-full-width-input { + box-sizing: border-box; + transform: unset; + margin-bottom: .75rem; + max-width: 100%; + } +} + +.inline{ + display:inline; +} + +#bad-username-splash{ + display: flex; + flex-direction: column; + align-items: center; +} + +#force-account-rename{ + width: 100%; + display: flex; + justify-content: center; + + #force-account-rename-inner{ + max-width: 1094px; + display: flex; + flex-direction: row; + @media only screen and (max-width: 800px) { + flex-direction: column; + } + + text-align: left; + + input{ + box-sizing: border-box; + width: 100%; + } + } + background-color: #575E75; + .col{ + padding: 40px; + flex: 1; + } +} + + +#admin-message-list{ + display: inline-block; + padding: 25px; + max-width: 1094px; + + #admin-message-list-title{ + text-align: left; + } +} + +.admin-message{ + text-align: left; + .admin-message-date{ + color: #575E75; + font-size: 12px; + padding-bottom: 10px; + } + text-align: left; + border-radius: 8px; + padding: 16px; + background-color: #E5F0FF; + margin: 10px; +} + +#force-account-rename-text{ + h1, h3, p{ + color: white; + } +} + +.empty{ + text-align: left; + + .admin-message{ + margin: 10px; + } +} + +.banned-message-box{ + margin: 20px; + text-align: left; +} + +.join-flow-outer-content{ + background-color: white; + border-radius: 16px; + color: #575e75; + max-width: 468px; + min-height: auto !important; + @media only screen and (max-width: 800px) { + margin: auto; + } +} + +.banned-icon{ + margin-right: 10px; + padding-top: 10px; + margin-bottom: -3px; +} + +.modal-flush-bottom-button{ + background-color: #855CD6; +} +.modal-flush-bottom-button:hover{ + background-color: #855CD6; +} + +.join-flow-outer-content{ + border: solid 4px #818698; + border-radius: 21px; +} + +.mt5{ + margin-top: 5px; +} + +.white-underline-link{ + color: white !important; + text-decoration: underline !important; +} \ No newline at end of file diff --git a/src/views/bad-username-splash/blocked-account.svg b/src/views/bad-username-splash/blocked-account.svg new file mode 100644 index 000000000..897a34da9 --- /dev/null +++ b/src/views/bad-username-splash/blocked-account.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/views/boost/boost.jsx b/src/views/boost/boost.jsx index 9f86be639..0dff27d8d 100644 --- a/src/views/boost/boost.jsx +++ b/src/views/boost/boost.jsx @@ -193,7 +193,10 @@ class Boost extends ExtensionLanding { /> - + {isDownloaded(this.state.OS) && (

diff --git a/src/views/download/scratch-link/download.jsx b/src/views/download/scratch-link/download.jsx index 94e7e4c0e..5cff4263c 100644 --- a/src/views/download/scratch-link/download.jsx +++ b/src/views/download/scratch-link/download.jsx @@ -103,6 +103,7 @@ const ScratchLink = ({intl}) => {
diff --git a/src/views/ev3/ev3.jsx b/src/views/ev3/ev3.jsx index cb9eb76e8..37aba205f 100644 --- a/src/views/ev3/ev3.jsx +++ b/src/views/ev3/ev3.jsx @@ -283,6 +283,7 @@ class EV3 extends ExtensionLanding { @@ -315,6 +316,7 @@ class EV3 extends ExtensionLanding { />

+

diff --git a/src/views/microbit/microbit.jsx b/src/views/microbit/microbit.jsx index c53b3f6f7..c2ba778ab 100644 --- a/src/views/microbit/microbit.jsx +++ b/src/views/microbit/microbit.jsx @@ -319,7 +319,10 @@ class MicroBit extends ExtensionLanding {


- + {isDownloaded(this.state.OS) && (

diff --git a/src/views/wedo2/wedo2.jsx b/src/views/wedo2/wedo2.jsx index c42e52ec9..18138b52d 100644 --- a/src/views/wedo2/wedo2.jsx +++ b/src/views/wedo2/wedo2.jsx @@ -192,7 +192,10 @@ class Wedo2 extends ExtensionLanding { /> - + {isDownloaded(this.state.OS) && (

diff --git a/static/images/scratchlink/mac-toolbar.png b/static/images/scratchlink/mac-toolbar.png index 045131070..58e70c9f6 100644 Binary files a/static/images/scratchlink/mac-toolbar.png and b/static/images/scratchlink/mac-toolbar.png differ diff --git a/test/unit/components/extension-requirements.test.jsx b/test/unit/components/extension-requirements.test.jsx index 22b566c0e..a0b460544 100644 --- a/test/unit/components/extension-requirements.test.jsx +++ b/test/unit/components/extension-requirements.test.jsx @@ -10,7 +10,7 @@ describe('ExtensionRequirements', () => { const requirements = component.find('.extension-requirements span').map(span => span.text()); expect(requirements).toEqual( - ['Windows 10 version 1709+', 'macOS 10.13+', 'ChromeOS', 'Android 6.0+', 'Bluetooth', 'Scratch Link'] + ['Windows 10 version 1709+', 'macOS 10.15+', 'ChromeOS', 'Android 6.0+', 'Bluetooth', 'Scratch Link'] ); });