From 947d2fd543bfda95c9217e050a2c526b0c387360 Mon Sep 17 00:00:00 2001 From: shmck Date: Sun, 28 Jun 2020 16:29:38 -0700 Subject: [PATCH 001/405] cleanup eslint config for web-app Signed-off-by: shmck --- .eslintrc.js | 1 + package.json | 1 + web-app/package.json | 8 +- web-app/yarn.lock | 246 ++----------------------------------------- yarn.lock | 12 +++ 5 files changed, 24 insertions(+), 244 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 686eec15..e849a5bd 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -2,6 +2,7 @@ module.exports = { parser: '@typescript-eslint/parser', // Specifies the ESLint parser plugins: ['prettier'], extends: [ + 'react-app', 'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin 'prettier/@typescript-eslint', // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier 'plugin:prettier/recommended', diff --git a/package.json b/package.json index 5959f499..56147ade 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ }, "devDependencies": { "eslint-config-prettier": "^6.11.0", + "eslint-config-react-app": "^5.2.1", "eslint-plugin-prettier": "^3.1.4", "prettier": "2.0.5", "vscode": "^1.1.37", diff --git a/web-app/package.json b/web-app/package.json index da4d79bb..6ccefb89 100644 --- a/web-app/package.json +++ b/web-app/package.json @@ -59,21 +59,15 @@ "@types/react": "^16.9.41", "@types/react-addons-css-transition-group": "^15.0.5", "@types/react-dom": "^16.9.8", - "@typescript-eslint/eslint-plugin": "^3.4.0", - "@typescript-eslint/parser": "^3.4.0", "babel-loader": "8.1.0", "babel-plugin-import": "^1.13.0", "customize-cra": "^1.0.0", - "eslint": "^7.3.1", - "eslint-config-prettier": "^6.11.0", - "eslint-plugin-prettier": "^3.1.4", "mini-css-extract-plugin": "^0.9.0", "node-sass": "^4.14.1", "prettier": "2.0.5", "react-app-rewired": "^2.1.6", "react-scripts": "^3.4.1", "sass-loader": "^8.0.2", - "typescript": "^3.9.5", - "typescript-eslint-parser": "^22.0.0" + "typescript": "^3.9.5" } } diff --git a/web-app/yarn.lock b/web-app/yarn.lock index 8713f15a..042b9ae9 100644 --- a/web-app/yarn.lock +++ b/web-app/yarn.lock @@ -2585,18 +2585,6 @@ regexpp "^3.0.0" tsutils "^3.17.1" -"@typescript-eslint/eslint-plugin@^3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.4.0.tgz#8378062e6be8a1d049259bdbcf27ce5dfbeee62b" - integrity sha512-wfkpiqaEVhZIuQRmudDszc01jC/YR7gMSxa6ulhggAe/Hs0KVIuo9wzvFiDbG3JD5pRFQoqnf4m7REDsUvBnMQ== - dependencies: - "@typescript-eslint/experimental-utils" "3.4.0" - debug "^4.1.1" - functional-red-black-tree "^1.0.1" - regexpp "^3.0.0" - semver "^7.3.2" - tsutils "^3.17.1" - "@typescript-eslint/experimental-utils@2.28.0": version "2.28.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.28.0.tgz#1fd0961cd8ef6522687b4c562647da6e71f8833d" @@ -2607,16 +2595,6 @@ eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/experimental-utils@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.4.0.tgz#8a44dfc6fb7f1d071937b390fe27608ebda122b8" - integrity sha512-rHPOjL43lOH1Opte4+dhC0a/+ks+8gOBwxXnyrZ/K4OTAChpSjP76fbI8Cglj7V5GouwVAGaK+xVwzqTyE/TPw== - dependencies: - "@types/json-schema" "^7.0.3" - "@typescript-eslint/typescript-estree" "3.4.0" - eslint-scope "^5.0.0" - eslint-utils "^2.0.0" - "@typescript-eslint/parser@^2.10.0": version "2.28.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.28.0.tgz#bb761286efd2b0714761cab9d0ee5847cf080385" @@ -2627,16 +2605,6 @@ "@typescript-eslint/typescript-estree" "2.28.0" eslint-visitor-keys "^1.1.0" -"@typescript-eslint/parser@^3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.4.0.tgz#fe52b68c5cb3bba3f5d875bd17adb70420d49d8d" - integrity sha512-ZUGI/de44L5x87uX5zM14UYcbn79HSXUR+kzcqU42gH0AgpdB/TjuJy3m4ezI7Q/jk3wTQd755mxSDLhQP79KA== - dependencies: - "@types/eslint-visitor-keys" "^1.0.0" - "@typescript-eslint/experimental-utils" "3.4.0" - "@typescript-eslint/typescript-estree" "3.4.0" - eslint-visitor-keys "^1.1.0" - "@typescript-eslint/typescript-estree@2.28.0": version "2.28.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.28.0.tgz#d34949099ff81092c36dc275b6a1ea580729ba00" @@ -2650,19 +2618,6 @@ semver "^6.3.0" tsutils "^3.17.1" -"@typescript-eslint/typescript-estree@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.4.0.tgz#6a787eb70b48969e4cd1ea67b057083f96dfee29" - integrity sha512-zKwLiybtt4uJb4mkG5q2t6+W7BuYx2IISiDNV+IY68VfoGwErDx/RfVI7SWL4gnZ2t1A1ytQQwZ+YOJbHHJ2rw== - dependencies: - debug "^4.1.1" - eslint-visitor-keys "^1.1.0" - glob "^7.1.6" - is-glob "^4.0.1" - lodash "^4.17.15" - semver "^7.3.2" - tsutils "^3.17.1" - "@webassemblyjs/ast@1.8.5": version "1.8.5" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359" @@ -3027,11 +2982,6 @@ acorn@^7.1.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.1.tgz#e35668de0b402f359de515c5482a1ab9f89a69bf" integrity sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg== -acorn@^7.2.0: - version "7.3.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.3.1.tgz#85010754db53c3fbaf3b9ea3e083aa5c5d147ffd" - integrity sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA== - address@1.1.2, address@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" @@ -3116,7 +3066,7 @@ ansi-align@^3.0.0: dependencies: string-width "^3.0.0" -ansi-colors@^3.0.0, ansi-colors@^3.2.1: +ansi-colors@^3.0.0: version "3.2.4" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== @@ -4348,14 +4298,6 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" - integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - character-entities-legacy@^1.0.0: version "1.1.4" resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" @@ -4906,15 +4848,6 @@ cross-spawn@^3.0.0: lru-cache "^4.0.1" which "^1.2.9" -cross-spawn@^7.0.2: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" @@ -5268,7 +5201,7 @@ deep-equal@^1.0.1, deep-equal@^1.1.1: object-keys "^1.1.1" regexp.prototype.flags "^1.2.0" -deep-is@^0.1.3, deep-is@~0.1.3: +deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= @@ -5697,13 +5630,6 @@ enhanced-resolve@^4.1.0: memory-fs "^0.5.0" tapable "^1.0.0" -enquirer@^2.3.5: - version "2.3.5" - resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.5.tgz#3ab2b838df0a9d8ab9e7dff235b0e8712ef92381" - integrity sha512-BNT1C08P9XD0vNg3J475yIUG+mVdp9T6towYFHUv897X0KoHBjB1shyrNmhmtHWKP17iSWgo7Gqh7BBuzLZMSA== - dependencies: - ansi-colors "^3.2.1" - entities@^1.1.1, entities@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" @@ -5835,13 +5761,6 @@ escodegen@^1.11.0, escodegen@^1.9.1: optionalDependencies: source-map "~0.6.1" -eslint-config-prettier@^6.11.0: - version "6.11.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz#f6d2238c1290d01c859a8b5c1f7d352a0b0da8b1" - integrity sha512-oB8cpLWSAjOVFEJhhyMZh6NOEOtBVziaqdDQ86+qhDHFbZXoRTM7pNSvFRfW/W/L/LrQ38C99J5CGuRBBzBsdA== - dependencies: - get-stdin "^6.0.0" - eslint-config-react-app@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-5.2.1.tgz#698bf7aeee27f0cea0139eaef261c7bf7dd623df" @@ -5916,13 +5835,6 @@ eslint-plugin-jsx-a11y@6.2.3: has "^1.0.3" jsx-ast-utils "^2.2.1" -eslint-plugin-prettier@^3.1.4: - version "3.1.4" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz#168ab43154e2ea57db992a2cd097c828171f75c2" - integrity sha512-jZDa8z76klRqo+TdGDTFJSavwbnWK2ZpqGKNZ+VvweMW516pDUMmQ2koXvxEE4JhzNvTv+radye/bWGBmA6jmg== - dependencies: - prettier-linter-helpers "^1.0.0" - eslint-plugin-react-hooks@^1.6.1: version "1.7.0" resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-1.7.0.tgz#6210b6d5a37205f0b92858f895a4e827020a7d04" @@ -5946,7 +5858,7 @@ eslint-plugin-react@7.19.0: string.prototype.matchall "^4.0.2" xregexp "^4.3.0" -eslint-scope@^4.0.0, eslint-scope@^4.0.3: +eslint-scope@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== @@ -5962,14 +5874,6 @@ eslint-scope@^5.0.0: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-scope@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.0.tgz#d0f971dfe59c69e0cada684b23d49dbf82600ce5" - integrity sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w== - dependencies: - esrecurse "^4.1.0" - estraverse "^4.1.1" - eslint-utils@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" @@ -5989,11 +5893,6 @@ eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== -eslint-visitor-keys@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.2.0.tgz#74415ac884874495f78ec2a97349525344c981fa" - integrity sha512-WFb4ihckKil6hu3Dp798xdzSfddwKKU3+nGniKF6HfeW6OLd2OUDEPP7TcHtB5+QXOKg2s6B2DaMPE1Nn/kxKQ== - eslint@^6.6.0: version "6.8.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" @@ -6037,48 +5936,6 @@ eslint@^6.6.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" -eslint@^7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.3.1.tgz#76392bd7e44468d046149ba128d1566c59acbe19" - integrity sha512-cQC/xj9bhWUcyi/RuMbRtC3I0eW8MH0jhRELSvpKYkWep3C6YZ2OkvcvJVUeO6gcunABmzptbXBuDoXsjHmfTA== - dependencies: - "@babel/code-frame" "^7.0.0" - ajv "^6.10.0" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.0.1" - doctrine "^3.0.0" - enquirer "^2.3.5" - eslint-scope "^5.1.0" - eslint-utils "^2.0.0" - eslint-visitor-keys "^1.2.0" - espree "^7.1.0" - esquery "^1.2.0" - esutils "^2.0.2" - file-entry-cache "^5.0.1" - functional-red-black-tree "^1.0.1" - glob-parent "^5.0.0" - globals "^12.1.0" - ignore "^4.0.6" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - js-yaml "^3.13.1" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash "^4.17.14" - minimatch "^3.0.4" - natural-compare "^1.4.0" - optionator "^0.9.1" - progress "^2.0.0" - regexpp "^3.1.0" - semver "^7.2.1" - strip-ansi "^6.0.0" - strip-json-comments "^3.1.0" - table "^5.2.3" - text-table "^0.2.0" - v8-compile-cache "^2.0.3" - espree@^6.1.2: version "6.2.1" resolved "https://registry.yarnpkg.com/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a" @@ -6088,21 +5945,12 @@ espree@^6.1.2: acorn-jsx "^5.2.0" eslint-visitor-keys "^1.1.0" -espree@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-7.1.0.tgz#a9c7f18a752056735bf1ba14cb1b70adc3a5ce1c" - integrity sha512-dcorZSyfmm4WTuTnE5Y7MEN1DyoPYy1ZR783QW1FJoenn7RailyWFsq/UL6ZAAA7uXurN9FIpYyUs3OfiIW+Qw== - dependencies: - acorn "^7.2.0" - acorn-jsx "^5.2.0" - eslint-visitor-keys "^1.2.0" - esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.0.1, esquery@^1.2.0: +esquery@^1.0.1: version "1.3.1" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57" integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== @@ -6315,11 +6163,6 @@ fast-deep-equal@^3.1.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA== -fast-diff@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" - integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== - fast-glob@^2.0.2: version "2.2.7" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" @@ -6342,7 +6185,7 @@ fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: +fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= @@ -6811,11 +6654,6 @@ get-stdin@^4.0.1: resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= -get-stdin@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" - integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== - get-stream@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -8772,14 +8610,6 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - lines-and-columns@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" @@ -8931,11 +8761,6 @@ lodash.throttle@^4.1.1: resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ= -lodash.unescape@4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c" - integrity sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw= - lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" @@ -9905,18 +9730,6 @@ optionator@^0.8.1, optionator@^0.8.3: type-check "~0.3.2" word-wrap "~1.2.3" -optionator@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" - integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== - dependencies: - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - word-wrap "^1.2.3" - original@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f" @@ -11048,11 +10861,6 @@ postcss@^7, postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, po source-map "^0.6.1" supports-color "^6.1.0" -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -11063,13 +10871,6 @@ prepend-http@^1.0.0: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= -prettier-linter-helpers@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" - integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== - dependencies: - fast-diff "^1.1.2" - prettier@2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4" @@ -11970,7 +11771,7 @@ regexpp@^2.0.1: resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== -regexpp@^3.0.0, regexpp@^3.1.0: +regexpp@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== @@ -12403,11 +12204,6 @@ selfsigned@^1.10.7: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" - integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== - semver@6.3.0, semver@^6.0.0, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" @@ -12418,7 +12214,7 @@ semver@7.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@^7.2.1, semver@^7.3.2: +semver@^7.3.2: version "7.3.2" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== @@ -13149,7 +12945,7 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" -strip-json-comments@^3.0.1, strip-json-comments@^3.1.0: +strip-json-comments@^3.0.1: version "3.1.0" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.0.tgz#7638d31422129ecf4457440009fba03f9f9ac180" integrity sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w== @@ -13534,13 +13330,6 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" @@ -13586,23 +13375,6 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript-eslint-parser@^22.0.0: - version "22.0.0" - resolved "https://registry.yarnpkg.com/typescript-eslint-parser/-/typescript-eslint-parser-22.0.0.tgz#f5e766c9b50711b03535e29a10b45f957e3c516a" - integrity sha512-pD8D7oTeRwWvFVxK3PaY6FYAiZsuRXFkIc2+1xkwCT3NduySgCgjeAkR5/dnIWecOiFVcEHf4ypXurF02Q6Z3Q== - dependencies: - eslint-scope "^4.0.0" - eslint-visitor-keys "^1.0.0" - typescript-estree "18.0.0" - -typescript-estree@18.0.0: - version "18.0.0" - resolved "https://registry.yarnpkg.com/typescript-estree/-/typescript-estree-18.0.0.tgz#a309f6c6502c64d74b3f88c205d871a9af0b1d40" - integrity sha512-HxTWrzFyYOPWA91Ij7xL9mNUVpGTKLH2KiaBn28CMbYgX2zgWdJqU9hO7Are+pAPAqY91NxAYoaAyDDZ3rLj2A== - dependencies: - lodash.unescape "4.0.1" - semver "5.5.0" - typescript@^3.9.5: version "3.9.5" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.5.tgz#586f0dba300cde8be52dd1ac4f7e1009c1b13f36" @@ -14148,7 +13920,7 @@ widest-line@^3.1.0: dependencies: string-width "^4.0.0" -word-wrap@^1.2.3, word-wrap@~1.2.3: +word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== diff --git a/yarn.lock b/yarn.lock index d9e32465..d82f6fc9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1286,6 +1286,11 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= +confusing-browser-globals@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz#72bc13b483c0276801681871d4898516f8f54fdd" + integrity sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw== + convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" @@ -1569,6 +1574,13 @@ eslint-config-prettier@^6.11.0: dependencies: get-stdin "^6.0.0" +eslint-config-react-app@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-5.2.1.tgz#698bf7aeee27f0cea0139eaef261c7bf7dd623df" + integrity sha512-pGIZ8t0mFLcV+6ZirRgYK6RVqUIKRIi9MmgzUEmrIknsn3AdO0I32asO86dJgloHq+9ZPl8UIg8mYrvgP5u2wQ== + dependencies: + confusing-browser-globals "^1.0.9" + eslint-plugin-prettier@^3.1.4: version "3.1.4" resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz#168ab43154e2ea57db992a2cd097c828171f75c2" From 9f5d3cb7954a0c89a586819b16c25ebbf6b28a6b Mon Sep 17 00:00:00 2001 From: shmck Date: Sun, 28 Jun 2020 21:43:25 -0700 Subject: [PATCH 002/405] hint state progress Signed-off-by: shmck --- .../Tutorial/{ => components}/ContentMenu.tsx | 2 +- .../containers/Tutorial/components/Hints.tsx | 14 +++-- .../containers/Tutorial/components/Level.tsx | 58 ++++++++++++++----- .../containers/Tutorial/components/Step.tsx | 8 ++- web-app/src/containers/Tutorial/index.tsx | 48 ++++++--------- 5 files changed, 80 insertions(+), 50 deletions(-) rename web-app/src/containers/Tutorial/{ => components}/ContentMenu.tsx (97%) diff --git a/web-app/src/containers/Tutorial/ContentMenu.tsx b/web-app/src/containers/Tutorial/components/ContentMenu.tsx similarity index 97% rename from web-app/src/containers/Tutorial/ContentMenu.tsx rename to web-app/src/containers/Tutorial/components/ContentMenu.tsx index 69e3329e..3399ed60 100644 --- a/web-app/src/containers/Tutorial/ContentMenu.tsx +++ b/web-app/src/containers/Tutorial/components/ContentMenu.tsx @@ -2,7 +2,7 @@ import * as React from 'react' import * as T from 'typings' import * as TT from 'typings/tutorial' import { Menu } from '@alifd/next' -import Icon from '../../components/Icon' +import Icon from '../../../components/Icon' interface Props { tutorial: TT.Tutorial diff --git a/web-app/src/containers/Tutorial/components/Hints.tsx b/web-app/src/containers/Tutorial/components/Hints.tsx index 7e45fe35..9de203ab 100644 --- a/web-app/src/containers/Tutorial/components/Hints.tsx +++ b/web-app/src/containers/Tutorial/components/Hints.tsx @@ -19,22 +19,26 @@ const styles = { interface Props { hints: string[] + hintIndex: number + setHintIndex(value: number): void } const Hints = (props: Props) => { - const [hintIndex, setHintIndex] = React.useState(-1) - const isFinalHint = props.hints.length - 1 === hintIndex + const isFinalHint = props.hints.length - 1 === props.hintIndex const nextHint = () => { - if (!isFinalHint) { - setHintIndex((currentHintIndex) => currentHintIndex + 1) + console.log('hintIndex') + console.log(props.hintIndex) + if (isFinalHint) { + return } + props.setHintIndex(props.hintIndex + 1) } return (
{/* only show revealed hints */} {props.hints.map((h, i) => { - return i <= hintIndex ? ( + return i <= props.hintIndex ? (
{h}
diff --git a/web-app/src/containers/Tutorial/components/Level.tsx b/web-app/src/containers/Tutorial/components/Level.tsx index b28382dd..b47419b7 100644 --- a/web-app/src/containers/Tutorial/components/Level.tsx +++ b/web-app/src/containers/Tutorial/components/Level.tsx @@ -8,6 +8,7 @@ import Button from '../../../components/Button' import Markdown from '../../../components/Markdown' import ProcessMessages from '../../../components/ProcessMessages' import NuxTutorial from '../../../components/NewUserExperience/NuxTutorial' +import ContentMenu from './ContentMenu' import Step from './Step' import { DISPLAY_RUN_TEST_BUTTON } from '../../../environment' @@ -87,42 +88,69 @@ const styles = { } interface Props { - menu: any - steps: Array - title: string + tutorial: TT.Tutorial index: number - content: string status: 'COMPLETE' | 'ACTIVE' | 'INCOMPLETE' + progress: T.Progress + position: T.Position processes: T.ProcessEvent[] testStatus: T.TestStatus | null onContinue(): void onRunTest(): void onLoadSolution(): void onOpenLogs(channel: string): void + displayHintsIndex: number[] + setHintsIndex(index: number, value: number): void } const Level = ({ - menu, - steps, - title, - content, + tutorial, index, status, + progress, + position, onContinue, onRunTest, onLoadSolution, onOpenLogs, processes, testStatus, + displayHintsIndex, + setHintsIndex, }: Props) => { - // @ts-ignore + const level = tutorial.levels[index] + + const [title, setTitle] = React.useState(level.title) + const [content, setContent] = React.useState(level.content) + + const menu = ( + + ) + + const steps: Array = level.steps.map((step: TT.Step) => { + // label step status for step component + let status: T.ProgressStatus = 'INCOMPLETE' + if (progress.steps[step.id]) { + status = 'COMPLETE' + } else if (step.id === position.stepId) { + status = 'ACTIVE' + } + return { ...step, status } + }) + + // current let currentStep = steps.findIndex((s) => s.status === 'ACTIVE') if (currentStep === -1) { currentStep = steps.length } const pageBottomRef = React.useRef(null) - const scrollToBottom = () => { // @ts-ignore pageBottomRef.current.scrollIntoView({ behavior: 'smooth' }) @@ -144,6 +172,7 @@ const Level = ({ {menu}
+

{title}

{content || ''} @@ -153,27 +182,30 @@ const Level = ({
Tasks
- {steps.map((step: (TT.Step & { status: T.ProgressStatus }) | null, index: number) => { + {steps.map((step: (TT.Step & { status: T.ProgressStatus }) | null, stepIndex: number) => { if (!step) { return null } let subtasks = null - if (step.setup.subtasks && testStatus?.summary) { + if (step?.setup?.subtasks && testStatus?.summary) { subtasks = Object.keys(testStatus.summary).map((testName: string) => ({ name: testName, // @ts-ignore typescript is wrong here pass: testStatus.summary[testName], })) } + const hints = step.hints return ( setHintsIndex(stepIndex, value)} /> ) })} diff --git a/web-app/src/containers/Tutorial/components/Step.tsx b/web-app/src/containers/Tutorial/components/Step.tsx index 5065685c..43782cd4 100644 --- a/web-app/src/containers/Tutorial/components/Step.tsx +++ b/web-app/src/containers/Tutorial/components/Step.tsx @@ -6,11 +6,13 @@ import Hints from './Hints' import Markdown from '../../../components/Markdown' interface Props { - order: number + index: number content: string status: T.ProgressStatus subtasks: { name: string; pass: boolean }[] | null hints?: string[] + hintIndex: number + setHintIndex(value: number): void onLoadSolution(): void } @@ -73,7 +75,9 @@ const Step = (props: Props) => { ) : null} {/* hints */} - {props.hints && props.hints.length ? : null} + {props.hints && props.hints.length ? ( + + ) : null}
diff --git a/web-app/src/containers/Tutorial/index.tsx b/web-app/src/containers/Tutorial/index.tsx index 6d6c31c3..ae4012b1 100644 --- a/web-app/src/containers/Tutorial/index.tsx +++ b/web-app/src/containers/Tutorial/index.tsx @@ -2,7 +2,6 @@ import * as React from 'react' import * as T from 'typings' import * as TT from 'typings/tutorial' import * as selectors from '../../services/selectors' -import ContentMenu from './ContentMenu' import Level from './components/Level' interface PageProps { @@ -14,10 +13,6 @@ const TutorialPage = (props: PageProps) => { const { position, progress, processes, testStatus } = props.context const tutorial = selectors.currentTutorial(props.context) - const levelData: TT.Level = selectors.currentLevel(props.context) - - const [title, setTitle] = React.useState(levelData.title) - const [content, setContent] = React.useState(levelData.content) const onContinue = (): void => { props.send({ @@ -40,39 +35,34 @@ const TutorialPage = (props: PageProps) => { props.send({ type: 'OPEN_LOGS', payload: { channel } }) } - const steps = levelData.steps.map((step: TT.Step) => { - // label step status for step component - let status: T.ProgressStatus = 'INCOMPLETE' - if (progress.steps[step.id]) { - status = 'COMPLETE' - } else if (step.id === position.stepId) { - status = 'ACTIVE' - } - return { ...step, status } - }) + const levelIndex = tutorial.levels.findIndex((l: TT.Level) => l.id === position.levelId) + const levelStatus = progress.levels[position.levelId] ? 'COMPLETE' : 'ACTIVE' + const { steps } = tutorial.levels[levelIndex] + const [displayHintsIndex, setDisplayHintsIndex] = React.useState(steps.map((s) => -1)) + + const setHintsIndex = (index: number, value: number) => { + return setDisplayHintsIndex((displayHintsIndex) => { + const next = [...displayHintsIndex] + next[index] = value + return next + }) + } return ( - } - index={tutorial.levels.findIndex((l: TT.Level) => l.id === position.levelId)} - steps={steps} - status={progress.levels[position.levelId] ? 'COMPLETE' : 'ACTIVE'} + tutorial={tutorial} + index={levelIndex} + status={levelStatus} + progress={progress} + position={position} onContinue={onContinue} onRunTest={onRunTest} onLoadSolution={onLoadSolution} onOpenLogs={onOpenLogs} processes={processes} testStatus={testStatus} + displayHintsIndex={displayHintsIndex} + setHintsIndex={setHintsIndex} /> ) } From 83a55b87e0634b89fb161065f6e2e1710f46762d Mon Sep 17 00:00:00 2001 From: shmck Date: Wed, 1 Jul 2020 08:51:50 -0700 Subject: [PATCH 003/405] route change progress Signed-off-by: shmck --- typings/index.d.ts | 2 +- web-app/src/Routes.tsx | 5 +-- web-app/src/components/Router/index.tsx | 2 +- .../containers/Tutorial/components/Hints.tsx | 2 -- .../containers/Tutorial/components/Level.tsx | 23 ++++++++++--- web-app/src/containers/Tutorial/index.tsx | 12 ------- web-app/src/services/state/machine.ts | 32 +++++++++---------- 7 files changed, 40 insertions(+), 38 deletions(-) diff --git a/typings/index.d.ts b/typings/index.d.ts index f7cf5095..3e2cc4b4 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -76,7 +76,6 @@ export interface MachineStateSchema { } Tutorial: { states: { - LoadNext: {} Level: { states: { Load: {} @@ -86,6 +85,7 @@ export interface MachineStateSchema { TestFail: {} StepNext: {} LevelComplete: {} + LoadNext: {} } } Completed: {} diff --git a/web-app/src/Routes.tsx b/web-app/src/Routes.tsx index 26460463..6d503ccb 100644 --- a/web-app/src/Routes.tsx +++ b/web-app/src/Routes.tsx @@ -20,6 +20,7 @@ const Routes = () => { ) } + console.log('RENDER') return ( @@ -37,10 +38,10 @@ const Routes = () => { {/* Tutorial */} - + - + {/* Completed */} diff --git a/web-app/src/components/Router/index.tsx b/web-app/src/components/Router/index.tsx index 8dda5bce..f641fb6b 100644 --- a/web-app/src/components/Router/index.tsx +++ b/web-app/src/components/Router/index.tsx @@ -30,7 +30,7 @@ const useRouter = (): Output => { send(action) } - logger(`STATE: ${JSON.stringify(state.value)}`) + console.log(`STATE: ${JSON.stringify(state.value)}`) // event bus listener React.useEffect(() => { diff --git a/web-app/src/containers/Tutorial/components/Hints.tsx b/web-app/src/containers/Tutorial/components/Hints.tsx index 9de203ab..3d66bc0e 100644 --- a/web-app/src/containers/Tutorial/components/Hints.tsx +++ b/web-app/src/containers/Tutorial/components/Hints.tsx @@ -26,8 +26,6 @@ interface Props { const Hints = (props: Props) => { const isFinalHint = props.hints.length - 1 === props.hintIndex const nextHint = () => { - console.log('hintIndex') - console.log(props.hintIndex) if (isFinalHint) { return } diff --git a/web-app/src/containers/Tutorial/components/Level.tsx b/web-app/src/containers/Tutorial/components/Level.tsx index b47419b7..2f7d2016 100644 --- a/web-app/src/containers/Tutorial/components/Level.tsx +++ b/web-app/src/containers/Tutorial/components/Level.tsx @@ -99,8 +99,6 @@ interface Props { onRunTest(): void onLoadSolution(): void onOpenLogs(channel: string): void - displayHintsIndex: number[] - setHintsIndex(index: number, value: number): void } const Level = ({ @@ -115,14 +113,31 @@ const Level = ({ onOpenLogs, processes, testStatus, - displayHintsIndex, - setHintsIndex, }: Props) => { const level = tutorial.levels[index] const [title, setTitle] = React.useState(level.title) const [content, setContent] = React.useState(level.content) + // hold state for hints for the level + const [displayHintsIndex, setDisplayHintsIndex] = React.useState([]) + const setHintsIndex = (index: number, value: number) => { + return setDisplayHintsIndex((displayHintsIndex) => { + const next = [...displayHintsIndex] + next[index] = value + return next + }) + } + React.useEffect(() => { + console.log(position.levelId) + console.log(JSON.stringify(position)) + // set the hints to empty on level starts + setDisplayHintsIndex(steps.map((s) => -1)) + return () => { + console.log('LEVEL UNMOUNTED') + } + }, [position.levelId]) + const menu = ( { const levelIndex = tutorial.levels.findIndex((l: TT.Level) => l.id === position.levelId) const levelStatus = progress.levels[position.levelId] ? 'COMPLETE' : 'ACTIVE' - const { steps } = tutorial.levels[levelIndex] - const [displayHintsIndex, setDisplayHintsIndex] = React.useState(steps.map((s) => -1)) - - const setHintsIndex = (index: number, value: number) => { - return setDisplayHintsIndex((displayHintsIndex) => { - const next = [...displayHintsIndex] - next[index] = value - return next - }) - } return ( { onOpenLogs={onOpenLogs} processes={processes} testStatus={testStatus} - displayHintsIndex={displayHintsIndex} - setHintsIndex={setHintsIndex} /> ) } diff --git a/web-app/src/services/state/machine.ts b/web-app/src/services/state/machine.ts index 26b4229f..4a7d1059 100644 --- a/web-app/src/services/state/machine.ts +++ b/web-app/src/services/state/machine.ts @@ -142,21 +142,6 @@ export const createMachine = (options: any) => { id: 'tutorial', initial: 'Level', states: { - LoadNext: { - id: 'tutorial-load-next', - onEntry: ['loadNext'], - on: { - NEXT_STEP: { - target: 'Level', - actions: ['updatePosition'], - }, - NEXT_LEVEL: { - target: 'Level', - actions: ['updatePosition'], - }, - COMPLETED: '#completed-tutorial', - }, - }, Level: { initial: 'Load', states: { @@ -228,11 +213,26 @@ export const createMachine = (options: any) => { onExit: ['syncLevelProgress'], on: { NEXT_LEVEL: { - target: '#tutorial-load-next', + target: 'LoadNext', actions: ['testClear', 'updatePosition'], }, }, }, + LoadNext: { + id: 'tutorial-load-next', + onEntry: ['loadNext'], + on: { + NEXT_STEP: { + target: 'Load', + actions: ['updatePosition'], + }, + NEXT_LEVEL: { + target: 'Load', + actions: ['updatePosition'], + }, + COMPLETED: '#completed-tutorial', + }, + }, }, }, Completed: { From 130757890804e22be9da752ca1320b91e6a887ee Mon Sep 17 00:00:00 2001 From: shmck Date: Wed, 1 Jul 2020 15:17:57 -0700 Subject: [PATCH 004/405] setup routes using objects and route strings Signed-off-by: shmck --- web-app/src/App.tsx | 5 +- web-app/src/Routes.tsx | 67 +++++------ web-app/src/components/Router/Route.tsx | 8 -- web-app/src/components/Router/index.tsx | 111 ++++++------------ .../src/services/state/useStateMachine.tsx | 64 ++++++++++ 5 files changed, 135 insertions(+), 120 deletions(-) delete mode 100644 web-app/src/components/Router/Route.tsx create mode 100644 web-app/src/services/state/useStateMachine.tsx diff --git a/web-app/src/App.tsx b/web-app/src/App.tsx index 3c296c87..9f490dec 100644 --- a/web-app/src/App.tsx +++ b/web-app/src/App.tsx @@ -2,12 +2,15 @@ import * as React from 'react' import { ConfigProvider } from '@alifd/next' import enUS from '@alifd/next/lib/locale/en-us' import ErrorBoundary from './components/ErrorBoundary' +import Workspace from './components/Workspace' import Routes from './Routes' const App = () => ( - + + + ) diff --git a/web-app/src/Routes.tsx b/web-app/src/Routes.tsx index 6d503ccb..384f5811 100644 --- a/web-app/src/Routes.tsx +++ b/web-app/src/Routes.tsx @@ -1,6 +1,6 @@ import * as React from 'react' -import useRouter from './components/Router' -import Workspace from './components/Workspace' +import useStateMachine from './services/state/useStateMachine' +import { Router, Route } from './components/Router' import ErrorView from './components/Error' import LoadingPage from './containers/Loading' import StartPage from './containers/Start' @@ -9,47 +9,40 @@ import CompletedPage from './containers/Tutorial/CompletedPage' import TutorialPage from './containers/Tutorial' const Routes = () => { - const { context, send, Router, Route } = useRouter() + const { context, route, send } = useStateMachine() // TODO: handle only full page errors if (context.error) { - return ( - - - - ) + return } - console.log('RENDER') return ( - - - {/* Setup */} - - - - - - - - - - - - - {/* Tutorial */} - - - - - - - {/* Completed */} - - - - - + + {/* Setup */} + + + + + + + + + + + + + {/* Tutorial */} + + + + + + + {/* Completed */} + + + + ) } diff --git a/web-app/src/components/Router/Route.tsx b/web-app/src/components/Router/Route.tsx deleted file mode 100644 index d73001df..00000000 --- a/web-app/src/components/Router/Route.tsx +++ /dev/null @@ -1,8 +0,0 @@ -interface Props { - children: any - path: string | string[] -} - -const Route = ({ children }: Props) => children - -export default Route diff --git a/web-app/src/components/Router/index.tsx b/web-app/src/components/Router/index.tsx index f641fb6b..1999b77c 100644 --- a/web-app/src/components/Router/index.tsx +++ b/web-app/src/components/Router/index.tsx @@ -1,87 +1,50 @@ import * as React from 'react' -import * as T from 'typings' -import { createMachine } from '../../services/state/machine' -import { useMachine } from '../../services/xstate-react' -import Route from './Route' import onError from '../../services/sentry/onError' -import logger from '../../services/logger' -interface Output { - context: T.MachineContext - send: (action: any) => void - Router: any - Route: any +interface RouterProps { + children: React.ReactChildren | React.ReactChildren[] + route: string } -declare let acquireVsCodeApi: any - -const editor = acquireVsCodeApi() -const editorSend = (action: T.Action) => { - logger(`TO EXT: "${action.type}"`) - return editor.postMessage(action) -} - -// router finds first state match of -const useRouter = (): Output => { - const [state, send] = useMachine(createMachine({ editorSend })) - - const sendWithLog = (action: T.Action): void => { - logger(`SEND: ${action.type}`, action) - send(action) +// check if a route string (eg. 'a.b.c') +// matches a paths object ({ a: { b: { c: true }}}) +const matches = (route: string, paths: object): boolean => { + const keys: string[] = route.split('.') + let current: any = paths || {} + // if the key throws, there is no match + for (const key of keys) { + const next = current[key] + if (next) { + current = next + continue + } else { + return false + } } + return true +} - console.log(`STATE: ${JSON.stringify(state.value)}`) - - // event bus listener - React.useEffect(() => { - const listener = 'message' - // propograte channel event to state machine - const handler = (event: any) => { - // NOTE: must call event.data, cannot destructure. VSCode acts odd - const action = event.data - // ignore browser events from plugins - if (action.source) { - return - } - sendWithLog(action) - } - window.addEventListener(listener, handler) - return () => { - window.removeEventListener(listener, handler) - } - }, []) +export const Router = ({ children, route }: RouterProps) => { + // @ts-ignore may accept string as well as element + const childArray: React.ReactElement[] = React.Children.toArray(children) + for (const child of childArray) { + // match path + const { paths } = child.props + let pathMatch = matches(route, paths) - const Router = ({ children }: any) => { - const childArray = React.Children.toArray(children) - for (const child of childArray) { - // match path - // @ts-ignore - const { path } = child.props - let pathMatch - if (typeof path === 'string') { - pathMatch = state.matches(path) - } else if (Array.isArray(path)) { - pathMatch = path.some((p) => state.matches(p)) - } else { - throw new Error(`Invalid route path ${JSON.stringify(path)}`) - } - if (pathMatch) { - // @ts-ignore - return child.props.children - } + if (pathMatch) { + return child.props.children } - const message = `No Route matches for ${JSON.stringify(state)}` - onError(new Error(message)) - console.warn(message) - return null } + const message = `No Route matches for "${JSON.stringify(route)}"` + onError(new Error(message)) + console.warn(message) + return null +} - return { - context: state.context, - send: sendWithLog, - Router, - Route, - } +interface RouteProps { + children: any + paths: object } -export default useRouter +export const Route = ({ children }: RouteProps) => children diff --git a/web-app/src/services/state/useStateMachine.tsx b/web-app/src/services/state/useStateMachine.tsx new file mode 100644 index 00000000..f71f5bf7 --- /dev/null +++ b/web-app/src/services/state/useStateMachine.tsx @@ -0,0 +1,64 @@ +import * as React from 'react' +import * as T from 'typings' +import { State } from 'xstate' +import { createMachine } from './machine' +import { useMachine } from '../xstate-react' +import logger from '../logger' + +interface Output { + context: T.MachineContext + route: string + send: (action: any) => void +} + +declare let acquireVsCodeApi: any + +const createRouteString = (routeObject: object) => { + let paths = [] + const key = Object.keys(routeObject)[0] +} + +const editor = acquireVsCodeApi() +const editorSend = (action: T.Action) => { + logger(`TO EXT: "${action.type}"`) + return editor.postMessage(action) +} + +// router finds first state match of +const useStateMachine = (): Output => { + const [state, send] = useMachine(createMachine({ editorSend })) + + const sendWithLog = (action: T.Action): void => { + logger(`SEND: ${action.type}`, action) + send(action) + } + + console.log(`STATE: ${JSON.stringify(state.value)}`) + + // event bus listener + React.useEffect(() => { + const listener = 'message' + // propograte channel event to state machine + const handler = (event: any) => { + // NOTE: must call event.data, cannot destructure. VSCode acts odd + const action = event.data + // ignore browser events from other extensions + if (action.source) { + return + } + sendWithLog(action) + } + window.addEventListener(listener, handler) + return () => { + window.removeEventListener(listener, handler) + } + }, []) + + return { + context: state.context, + route: '', + send: sendWithLog, + } +} + +export default useStateMachine From 4de3c42588e6000ce82c39ce1a45784da0c5331f Mon Sep 17 00:00:00 2001 From: shmck Date: Wed, 1 Jul 2020 15:36:46 -0700 Subject: [PATCH 005/405] router progress Signed-off-by: shmck --- .../src/services/state/routeString.test.ts | 16 +++++++++ .../src/services/state/useStateMachine.tsx | 33 +++++++++++++++---- 2 files changed, 42 insertions(+), 7 deletions(-) create mode 100644 web-app/src/services/state/routeString.test.ts diff --git a/web-app/src/services/state/routeString.test.ts b/web-app/src/services/state/routeString.test.ts new file mode 100644 index 00000000..e733d41f --- /dev/null +++ b/web-app/src/services/state/routeString.test.ts @@ -0,0 +1,16 @@ +import { createRouteString } from './useStateMachine' + +describe('route string', () => { + it('should take a single key route', () => { + const result = createRouteString('a') + expect(result).toBe('a') + }) + it('should take a 1 level nested key route', () => { + const result = createRouteString({ a: 'b' }) + expect(result).toBe('a.b') + }) + it('should take a 3 level nested key route', () => { + const result = createRouteString({ a: { b: { c: 'd' } } }) + expect(result).toBe('a.b.c.d') + }) +}) diff --git a/web-app/src/services/state/useStateMachine.tsx b/web-app/src/services/state/useStateMachine.tsx index f71f5bf7..f8217606 100644 --- a/web-app/src/services/state/useStateMachine.tsx +++ b/web-app/src/services/state/useStateMachine.tsx @@ -1,6 +1,5 @@ import * as React from 'react' import * as T from 'typings' -import { State } from 'xstate' import { createMachine } from './machine' import { useMachine } from '../xstate-react' import logger from '../logger' @@ -13,9 +12,27 @@ interface Output { declare let acquireVsCodeApi: any -const createRouteString = (routeObject: object) => { - let paths = [] - const key = Object.keys(routeObject)[0] +export const createRouteString = (route: object | string): string => { + if (typeof route === 'string') { + return route + } + const paths: string[] = [] + let current: object | string | undefined = route + while (current) { + // current is final string value + if (typeof current === 'string') { + paths.push(current) + break + } + + // current is object + const next: string = Object.keys(current)[0] + paths.push(next) + // @ts-ignore + current = current[next] + } + + return paths.join('.') } const editor = acquireVsCodeApi() @@ -33,8 +50,6 @@ const useStateMachine = (): Output => { send(action) } - console.log(`STATE: ${JSON.stringify(state.value)}`) - // event bus listener React.useEffect(() => { const listener = 'message' @@ -54,9 +69,13 @@ const useStateMachine = (): Output => { } }, []) + // convert route to a string to avoid unnecessary React re-renders on deeply nested objects + const route = createRouteString(state.value) + console.log(`STATE: ${route}`) + return { context: state.context, - route: '', + route, send: sendWithLog, } } From ce08fa6d7f99a79b79b1a75234769579303854df Mon Sep 17 00:00:00 2001 From: shmck Date: Wed, 1 Jul 2020 15:43:51 -0700 Subject: [PATCH 006/405] fix router edge case Signed-off-by: shmck --- web-app/src/Routes.tsx | 6 +++++- web-app/src/components/Router/index.tsx | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/web-app/src/Routes.tsx b/web-app/src/Routes.tsx index 384f5811..2753a653 100644 --- a/web-app/src/Routes.tsx +++ b/web-app/src/Routes.tsx @@ -8,6 +8,10 @@ import SelectTutorialPage from './containers/SelectTutorial' import CompletedPage from './containers/Tutorial/CompletedPage' import TutorialPage from './containers/Tutorial' +/* + * NOTE: due to a lack of URLs and a dependency on xstate + * we have to implement a custom router here + */ const Routes = () => { const { context, route, send } = useStateMachine() @@ -35,7 +39,7 @@ const Routes = () => { - + {/* Completed */} diff --git a/web-app/src/components/Router/index.tsx b/web-app/src/components/Router/index.tsx index 1999b77c..cf81e174 100644 --- a/web-app/src/components/Router/index.tsx +++ b/web-app/src/components/Router/index.tsx @@ -15,6 +15,10 @@ const matches = (route: string, paths: object): boolean => { for (const key of keys) { const next = current[key] if (next) { + // exit early if property value is true + if (next === true) { + return true + } current = next continue } else { From 7dc54c110362ec1fba860c02718ffe556e8de93d Mon Sep 17 00:00:00 2001 From: shmck Date: Wed, 1 Jul 2020 15:45:30 -0700 Subject: [PATCH 007/405] remove unnecessary debug logs Signed-off-by: shmck --- web-app/src/containers/Tutorial/components/Level.tsx | 5 ----- web-app/src/services/sentry/init.tsx | 3 ++- web-app/src/services/state/useStateMachine.tsx | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/web-app/src/containers/Tutorial/components/Level.tsx b/web-app/src/containers/Tutorial/components/Level.tsx index 2f7d2016..98a4e1a2 100644 --- a/web-app/src/containers/Tutorial/components/Level.tsx +++ b/web-app/src/containers/Tutorial/components/Level.tsx @@ -129,13 +129,8 @@ const Level = ({ }) } React.useEffect(() => { - console.log(position.levelId) - console.log(JSON.stringify(position)) // set the hints to empty on level starts setDisplayHintsIndex(steps.map((s) => -1)) - return () => { - console.log('LEVEL UNMOUNTED') - } }, [position.levelId]) const menu = ( diff --git a/web-app/src/services/sentry/init.tsx b/web-app/src/services/sentry/init.tsx index 8f71c272..7100a1a6 100644 --- a/web-app/src/services/sentry/init.tsx +++ b/web-app/src/services/sentry/init.tsx @@ -1,5 +1,6 @@ import * as sentry from '@sentry/browser' import { NODE_ENV, SENTRY_DSN } from '../../environment' +import logger from '../logger' try { if (SENTRY_DSN && NODE_ENV === 'production') { @@ -9,5 +10,5 @@ try { }) } } catch (error) { - console.log(`Error in Sentry init: ${error.message}`) + logger(`Error in Sentry init: ${error.message}`) } diff --git a/web-app/src/services/state/useStateMachine.tsx b/web-app/src/services/state/useStateMachine.tsx index f8217606..5b9ceda1 100644 --- a/web-app/src/services/state/useStateMachine.tsx +++ b/web-app/src/services/state/useStateMachine.tsx @@ -71,7 +71,7 @@ const useStateMachine = (): Output => { // convert route to a string to avoid unnecessary React re-renders on deeply nested objects const route = createRouteString(state.value) - console.log(`STATE: ${route}`) + logger(`STATE: "${route}"`) return { context: state.context, From aa496506a9cb91b31e1a2958df0b448f1b003d1b Mon Sep 17 00:00:00 2001 From: shmck Date: Wed, 1 Jul 2020 21:16:25 -0700 Subject: [PATCH 008/405] allow for empty level content Signed-off-by: shmck --- web-app/src/containers/Tutorial/components/Level.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/web-app/src/containers/Tutorial/components/Level.tsx b/web-app/src/containers/Tutorial/components/Level.tsx index 98a4e1a2..786de7a5 100644 --- a/web-app/src/containers/Tutorial/components/Level.tsx +++ b/web-app/src/containers/Tutorial/components/Level.tsx @@ -183,10 +183,12 @@ const Level = ({
-
-

{title}

- {content || ''} -
+ {content.length ? ( +
+

{title}

+ {content || ''} +
+ ) : null} {steps.length ? (
From 83b4899126798ad8f84db5506f84e09db4b38287 Mon Sep 17 00:00:00 2001 From: shmck Date: Fri, 3 Jul 2020 12:14:25 -0700 Subject: [PATCH 009/405] fix routeString tests Signed-off-by: shmck --- .../src/services/state/useStateMachine.tsx | 24 +------------------ .../state/{ => utils}/routeString.test.ts | 2 +- .../src/services/state/utils/routeString.ts | 24 +++++++++++++++++++ 3 files changed, 26 insertions(+), 24 deletions(-) rename web-app/src/services/state/{ => utils}/routeString.test.ts (89%) create mode 100644 web-app/src/services/state/utils/routeString.ts diff --git a/web-app/src/services/state/useStateMachine.tsx b/web-app/src/services/state/useStateMachine.tsx index 5b9ceda1..2404203d 100644 --- a/web-app/src/services/state/useStateMachine.tsx +++ b/web-app/src/services/state/useStateMachine.tsx @@ -2,6 +2,7 @@ import * as React from 'react' import * as T from 'typings' import { createMachine } from './machine' import { useMachine } from '../xstate-react' +import createRouteString from './utils/routeString' import logger from '../logger' interface Output { @@ -12,29 +13,6 @@ interface Output { declare let acquireVsCodeApi: any -export const createRouteString = (route: object | string): string => { - if (typeof route === 'string') { - return route - } - const paths: string[] = [] - let current: object | string | undefined = route - while (current) { - // current is final string value - if (typeof current === 'string') { - paths.push(current) - break - } - - // current is object - const next: string = Object.keys(current)[0] - paths.push(next) - // @ts-ignore - current = current[next] - } - - return paths.join('.') -} - const editor = acquireVsCodeApi() const editorSend = (action: T.Action) => { logger(`TO EXT: "${action.type}"`) diff --git a/web-app/src/services/state/routeString.test.ts b/web-app/src/services/state/utils/routeString.test.ts similarity index 89% rename from web-app/src/services/state/routeString.test.ts rename to web-app/src/services/state/utils/routeString.test.ts index e733d41f..459a7481 100644 --- a/web-app/src/services/state/routeString.test.ts +++ b/web-app/src/services/state/utils/routeString.test.ts @@ -1,4 +1,4 @@ -import { createRouteString } from './useStateMachine' +import createRouteString from './routeString' describe('route string', () => { it('should take a single key route', () => { diff --git a/web-app/src/services/state/utils/routeString.ts b/web-app/src/services/state/utils/routeString.ts new file mode 100644 index 00000000..c17ce7f7 --- /dev/null +++ b/web-app/src/services/state/utils/routeString.ts @@ -0,0 +1,24 @@ +const createRouteString = (route: object | string): string => { + if (typeof route === 'string') { + return route + } + const paths: string[] = [] + let current: object | string | undefined = route + while (current) { + // current is final string value + if (typeof current === 'string') { + paths.push(current) + break + } + + // current is object + const next: string = Object.keys(current)[0] + paths.push(next) + // @ts-ignore + current = current[next] + } + + return paths.join('.') +} + +export default createRouteString From d3ff8f9f7edce4d4147814ffa4b8fbce2e732210 Mon Sep 17 00:00:00 2001 From: shmck Date: Fri, 3 Jul 2020 13:35:15 -0700 Subject: [PATCH 010/405] subtask progress Signed-off-by: shmck --- src/channel/index.ts | 2 +- src/editor/commands.ts | 2 +- src/services/testRunner/index.ts | 31 ++++++++++++++++--- src/services/testRunner/parser.test.ts | 25 +++++++++++++++ src/services/testRunner/subtasks.ts | 24 ++++++++++++++ typings/tutorial.d.ts | 4 +-- .../containers/Tutorial/components/Level.tsx | 10 +++--- web-app/src/services/state/actions/editor.ts | 2 +- web-app/src/services/state/machine.ts | 2 +- 9 files changed, 85 insertions(+), 17 deletions(-) create mode 100644 src/services/testRunner/subtasks.ts diff --git a/src/channel/index.ts b/src/channel/index.ts index a29674ff..edf352de 100644 --- a/src/channel/index.ts +++ b/src/channel/index.ts @@ -306,7 +306,7 @@ class Channel implements Channel { await vscode.commands.executeCommand(COMMANDS.SET_CURRENT_POSITION, action.payload.position) await solutionActions({ actions: action.payload.actions, send: this.send }) // run test following solution to update position - vscode.commands.executeCommand(COMMANDS.RUN_TEST, { subtasks: true }) + vscode.commands.executeCommand(COMMANDS.RUN_TEST) return case 'EDITOR_SYNC_PROGRESS': // update progress when a level is deemed complete in the client diff --git a/src/editor/commands.ts b/src/editor/commands.ts index 84c175ae..2ba69a70 100644 --- a/src/editor/commands.ts +++ b/src/editor/commands.ts @@ -82,7 +82,7 @@ export const createCommands = ({ extensionPath, workspaceState }: CreateCommandP webview.send({ type: 'TEST_RUNNING', payload: { position } }) }, onLoadSubtasks: ({ summary }) => { - webview.send({ type: 'LOAD_TEST_SUBTASKS', payload: { summary } }) + webview.send({ type: 'LOAD_SUBTASK_RESULTS', payload: { summary } }) }, }) }, diff --git a/src/services/testRunner/index.ts b/src/services/testRunner/index.ts index 013c660a..617f7121 100644 --- a/src/services/testRunner/index.ts +++ b/src/services/testRunner/index.ts @@ -3,6 +3,7 @@ import * as TT from 'typings/tutorial' import { exec } from '../node' import logger from '../logger' import parser, { ParserOutput } from './parser' +import parseSubtasks from './subtasks' import { debounce, throttle } from './throttle' import onError from '../sentry/onError' import { clearOutput, addOutput } from './output' @@ -13,7 +14,7 @@ interface Callbacks { onFail(position: T.Position, failSummary: T.TestFail): void onRun(position: T.Position): void onError(position: T.Position): void - onLoadSubtasks({ summary }: { summary: { [testName: string]: boolean } }): void + onLoadSubtasks({ summary }: { summary: { [testId: number]: boolean } }): void } const failChannelName = 'CodeRoad (Tests)' @@ -28,7 +29,7 @@ interface TestRunnerParams { const createTestRunner = (data: TT.Tutorial, callbacks: Callbacks) => { const testRunnerConfig = data.config.testRunner const testRunnerFilterArg = testRunnerConfig.args?.filter - return async ({ position, onSuccess, subtasks }: TestRunnerParams): Promise => { + return async ({ position, onSuccess }: TestRunnerParams): Promise => { const startTime = throttle() // throttle time early if (!startTime) { @@ -37,8 +38,24 @@ const createTestRunner = (data: TT.Tutorial, callbacks: Callbacks) => { logger('------------------- RUN TEST -------------------') + // calculate level & step from position + const level: TT.Level | null = data.levels.find((l) => l.id === position.levelId) || null + if (!level) { + console.warn(`Level "${position.levelId}" not found`) + return + } + const step: TT.Step | null = level.steps.find((s) => s.id === position.stepId) || null + if (!step) { + console.warn(`Step "${position.stepId}" not found`) + return + } + + console.log('STEP') + console.log(JSON.stringify(step)) + // flag as running - if (!subtasks) { + // no need to flag subtasks as running + if (!step.setup?.subtasks) { callbacks.onRun(position) } @@ -81,8 +98,12 @@ const createTestRunner = (data: TT.Tutorial, callbacks: Callbacks) => { const tap: ParserOutput = parser(stdout || '') - if (subtasks) { - callbacks.onLoadSubtasks({ summary: tap.summary }) + if (step.setup.subtasks) { + const summary = parseSubtasks(tap.summary, position.stepId || '') + + console.log('---subtask summary') + console.log(summary) + callbacks.onLoadSubtasks({ summary }) // exit early return } diff --git a/src/services/testRunner/parser.test.ts b/src/services/testRunner/parser.test.ts index 1494d0fb..81e5a17f 100644 --- a/src/services/testRunner/parser.test.ts +++ b/src/services/testRunner/parser.test.ts @@ -269,3 +269,28 @@ not ok 2 test_add_one_number (tests.math_test.MathTest) }) }) }) + +describe('subtasks', () => { + it('should parse subtasks', () => { + const summary = { + 'SUBTASKS 1.1 :1 should add one number': true, + 'SUBTASKS 1.1 :2 should add two numbers': false, + 'SUBTASKS 1.1 :3 should add three numbers': false, + } + const subtaskRegex = /^SUBTASKS\s(?(\d+\.\d+))\s:(?\d+)\s/ + const subtaskSummary = {} + Object.keys(summary).forEach((key) => { + const match = key.match(subtaskRegex) + if (!!match) { + const { stepId, testId } = match.groups || {} + const testIndex = Number(testId) - 1 + subtaskSummary[testIndex] = summary[key] + } + }) + expect(subtaskSummary).toEqual({ + 0: true, + 1: false, + 2: false, + }) + }) +}) diff --git a/src/services/testRunner/subtasks.ts b/src/services/testRunner/subtasks.ts new file mode 100644 index 00000000..5d58bcf4 --- /dev/null +++ b/src/services/testRunner/subtasks.ts @@ -0,0 +1,24 @@ +interface Summary { + [key: string]: boolean +} + +// if a subtask matches the current stepId name +// in the format "SUBTASKS 1.1 :1" where 1.1 is the stepId & :1 is the testId +// values will be parsed and sent to the client +const parseSubtasks = (summary: Summary, expectedStepId: string | null): Summary => { + const subtaskRegex = /^SUBTASKS\s(?(\d+\.\d+))\s:(?\d+)\s/ + const subtaskSummary = {} + Object.keys(summary).forEach((key) => { + const match = key.match(subtaskRegex) + if (!!match) { + const { stepId, testId } = match.groups || {} + if (stepId === expectedStepId) { + const testIndex = Number(testId) - 1 + subtaskSummary[testIndex] = summary[key] + } + } + }) + return subtaskSummary +} + +export default parseSubtasks diff --git a/typings/tutorial.d.ts b/typings/tutorial.d.ts index 00dd1dfc..a6525e63 100644 --- a/typings/tutorial.d.ts +++ b/typings/tutorial.d.ts @@ -27,7 +27,7 @@ export type Step = { content: string setup: StepActions solution: Maybe - subtasks?: { [testName: string]: boolean } + subtasks?: { [index: number]: boolean } hints?: string[] } @@ -52,7 +52,7 @@ export type StepActions = { files?: string[] watchers?: string[] filter?: string - subtasks?: boolean + subtasks?: string[] } export interface TestRunnerArgs { diff --git a/web-app/src/containers/Tutorial/components/Level.tsx b/web-app/src/containers/Tutorial/components/Level.tsx index 786de7a5..27ff8c77 100644 --- a/web-app/src/containers/Tutorial/components/Level.tsx +++ b/web-app/src/containers/Tutorial/components/Level.tsx @@ -199,14 +199,12 @@ const Level = ({ return null } let subtasks = null - if (step?.setup?.subtasks && testStatus?.summary) { - subtasks = Object.keys(testStatus.summary).map((testName: string) => ({ - name: testName, - // @ts-ignore typescript is wrong here - pass: testStatus.summary[testName], + if (step?.setup?.subtasks) { + subtasks = step.setup.subtasks.map((subtask: string, subtaskIndex: number) => ({ + name: subtask, + pass: !!(testStatus?.summary ? testStatus.summary[subtaskIndex] : false), })) } - const hints = step.hints return ( ({ }) if (step.setup.subtasks) { - // load subtask data by running tests and parsing result + // load subtask summary by running tests and parsing result editorSend({ type: 'EDITOR_RUN_TEST', payload: { diff --git a/web-app/src/services/state/machine.ts b/web-app/src/services/state/machine.ts index 4a7d1059..d04c7918 100644 --- a/web-app/src/services/state/machine.ts +++ b/web-app/src/services/state/machine.ts @@ -155,7 +155,7 @@ export const createMachine = (options: any) => { Normal: { id: 'tutorial-level', on: { - LOAD_TEST_SUBTASKS: { + LOAD_SUBTASK_RESULTS: { actions: ['testSubtasks'], }, TEST_RUNNING: 'TestRunning', From 9556a84ceae54be3dae8a33e65db98a7344c4ada Mon Sep 17 00:00:00 2001 From: shmck Date: Sun, 5 Jul 2020 15:21:16 -0700 Subject: [PATCH 011/405] show pass subtask when task passes Signed-off-by: shmck --- src/services/testRunner/index.ts | 34 ++++++++----------- .../containers/Tutorial/components/Step.tsx | 2 +- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/services/testRunner/index.ts b/src/services/testRunner/index.ts index 617f7121..6362b3c1 100644 --- a/src/services/testRunner/index.ts +++ b/src/services/testRunner/index.ts @@ -50,14 +50,7 @@ const createTestRunner = (data: TT.Tutorial, callbacks: Callbacks) => { return } - console.log('STEP') - console.log(JSON.stringify(step)) - - // flag as running - // no need to flag subtasks as running - if (!step.setup?.subtasks) { - callbacks.onRun(position) - } + callbacks.onRun(position) let result: { stdout: string | undefined; stderr: string | undefined } try { @@ -98,16 +91,6 @@ const createTestRunner = (data: TT.Tutorial, callbacks: Callbacks) => { const tap: ParserOutput = parser(stdout || '') - if (step.setup.subtasks) { - const summary = parseSubtasks(tap.summary, position.stepId || '') - - console.log('---subtask summary') - console.log(summary) - callbacks.onLoadSubtasks({ summary }) - // exit early - return - } - addOutput({ channel: logChannelName, text: tap.logs.join('\n'), show: false }) if (stderr) { @@ -128,7 +111,18 @@ const createTestRunner = (data: TT.Tutorial, callbacks: Callbacks) => { description: firstFail.details || 'Unknown error', summary: tap.summary, } - callbacks.onFail(position, failSummary) + + if (step.setup.subtasks) { + const subtaskSummary = parseSubtasks(tap.summary, position.stepId || '') + + callbacks.onFail(position, { + ...failSummary, + summary: subtaskSummary, + }) + } else { + callbacks.onFail(position, failSummary) + } + const output = formatFailOutput(tap) addOutput({ channel: failChannelName, text: output, show: true }) return @@ -142,6 +136,7 @@ const createTestRunner = (data: TT.Tutorial, callbacks: Callbacks) => { // PASS if (tap.ok) { + console.log('running pass') clearOutput(failChannelName) callbacks.onSuccess(position) @@ -149,6 +144,7 @@ const createTestRunner = (data: TT.Tutorial, callbacks: Callbacks) => { if (onSuccess) { onSuccess() } + 5 } else { // should never get here onError(new Error(`Error with running test ${JSON.stringify(position)}`)) diff --git a/web-app/src/containers/Tutorial/components/Step.tsx b/web-app/src/containers/Tutorial/components/Step.tsx index 43782cd4..f68dd263 100644 --- a/web-app/src/containers/Tutorial/components/Step.tsx +++ b/web-app/src/containers/Tutorial/components/Step.tsx @@ -67,7 +67,7 @@ const Step = (props: Props) => {
    {props.subtasks.map((subtask) => (
  • - + {subtask.name}
  • From 5841bdd28c93e981a55c634f3aa54b7838453454 Mon Sep 17 00:00:00 2001 From: shmck Date: Sun, 5 Jul 2020 15:30:34 -0700 Subject: [PATCH 012/405] update changelog for 0.9.0 Signed-off-by: shmck --- CHANGELOG.md | 26 ++++++++++++++++++++ docs/docs/config-yml.md | 8 ------ docs/docs/create-a-practice-tutorial.md | 2 -- package.json | 2 +- web-app/package.json | 2 +- web-app/src/services/state/actions/editor.ts | 1 - web-app/stories/Level.stories.tsx | 1 - 7 files changed, 28 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53f64c46..67e920a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -175,3 +175,29 @@ A description of the task. - The second hint - The last hint ``` + +### [0.9.0] + +Change subtask format to include subtasks in markdown. + +Subtasks no longer need to be included in yaml, or require a filter. + +See an example at + +```md +### 1.1 + +A description of the task + +#### SUBTASKS + +- The first subtask +- The second subtask +``` + +Subtasks are then matched up with tests with names that match + +```text +SUBTASK 1.1 :1 test name +SUBTASK 1.2 :2 test name +``` diff --git a/docs/docs/config-yml.md b/docs/docs/config-yml.md index 9ad16b4d..b968014a 100644 --- a/docs/docs/config-yml.md +++ b/docs/docs/config-yml.md @@ -103,14 +103,6 @@ levels: - package.json commits: - commit8 - ## Example Four: Subtasks - - id: '1.4' - setup: - commands: - ## A filter is a regex that limits the test results - - filter: '^Example 2' - ## A feature that shows subtasks: all filtered active test names and the status of the tests (pass/fail). - - subtasks: true - id: '2' steps: - id: '2.1' diff --git a/docs/docs/create-a-practice-tutorial.md b/docs/docs/create-a-practice-tutorial.md index 0fdfeae6..d628e240 100644 --- a/docs/docs/create-a-practice-tutorial.md +++ b/docs/docs/create-a-practice-tutorial.md @@ -191,8 +191,6 @@ levels: - id: '1' steps: - id: '1.1' - setup: - subtasks: false ``` Replace the `repo uri` URL with your github repo, note that it's just the username and repo in the URL. This file links everything together. You can see the repo URL and the branch that you created. And the `1.` and `1.1` id's that match the markdown. You can also add commands that will run when a lesson is started, as well as a host of other things. diff --git a/package.json b/package.json index 56147ade..8cac0746 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "coderoad", - "version": "0.8.0", + "version": "0.9.0", "description": "Play interactive coding tutorials in your editor", "keywords": [ "tutorial", diff --git a/web-app/package.json b/web-app/package.json index 6ccefb89..59b8cdb3 100644 --- a/web-app/package.json +++ b/web-app/package.json @@ -1,6 +1,6 @@ { "name": "coderoad-app", - "version": "0.8.0", + "version": "0.9.0", "private": true, "scripts": { "build": "react-app-rewired build", diff --git a/web-app/src/services/state/actions/editor.ts b/web-app/src/services/state/actions/editor.ts index 48eba64a..a1642933 100644 --- a/web-app/src/services/state/actions/editor.ts +++ b/web-app/src/services/state/actions/editor.ts @@ -63,7 +63,6 @@ export default (editorSend: any) => ({ type: 'EDITOR_RUN_TEST', payload: { position: context.position, - subtasks: true, }, }) } diff --git a/web-app/stories/Level.stories.tsx b/web-app/stories/Level.stories.tsx index 767f978c..6e29d99d 100644 --- a/web-app/stories/Level.stories.tsx +++ b/web-app/stories/Level.stories.tsx @@ -133,7 +133,6 @@ storiesOf('Level', module) setup: { id: 'L1:S2:SETUP', commits: ['abcdefg'], - subtasks: true, filter: '^SomeTest', }, solution: { From d6742b67612f7e8efbad953f438933cc2ae8c18e Mon Sep 17 00:00:00 2001 From: shmck Date: Sun, 5 Jul 2020 15:35:01 -0700 Subject: [PATCH 013/405] cleanup from commits Signed-off-by: shmck --- src/services/testRunner/index.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/services/testRunner/index.ts b/src/services/testRunner/index.ts index 6362b3c1..af21447a 100644 --- a/src/services/testRunner/index.ts +++ b/src/services/testRunner/index.ts @@ -136,7 +136,6 @@ const createTestRunner = (data: TT.Tutorial, callbacks: Callbacks) => { // PASS if (tap.ok) { - console.log('running pass') clearOutput(failChannelName) callbacks.onSuccess(position) @@ -144,7 +143,6 @@ const createTestRunner = (data: TT.Tutorial, callbacks: Callbacks) => { if (onSuccess) { onSuccess() } - 5 } else { // should never get here onError(new Error(`Error with running test ${JSON.stringify(position)}`)) From ed664e341acb26cd91c0be4fbce35331d5a2bccd Mon Sep 17 00:00:00 2001 From: shmck Date: Sun, 5 Jul 2020 16:12:51 -0700 Subject: [PATCH 014/405] update subtask schema Signed-off-by: shmck --- src/services/testRunner/index.ts | 2 +- typings/tutorial.d.ts | 3 +-- web-app/src/containers/Tutorial/components/Level.tsx | 4 ++-- web-app/src/services/state/actions/editor.ts | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/services/testRunner/index.ts b/src/services/testRunner/index.ts index af21447a..0133da3b 100644 --- a/src/services/testRunner/index.ts +++ b/src/services/testRunner/index.ts @@ -112,7 +112,7 @@ const createTestRunner = (data: TT.Tutorial, callbacks: Callbacks) => { summary: tap.summary, } - if (step.setup.subtasks) { + if (step.subtasks) { const subtaskSummary = parseSubtasks(tap.summary, position.stepId || '') callbacks.onFail(position, { diff --git a/typings/tutorial.d.ts b/typings/tutorial.d.ts index a6525e63..e43aa884 100644 --- a/typings/tutorial.d.ts +++ b/typings/tutorial.d.ts @@ -27,8 +27,8 @@ export type Step = { content: string setup: StepActions solution: Maybe - subtasks?: { [index: number]: boolean } hints?: string[] + subtasks?: string[] } /** A tutorial for use in VSCode CodeRoad */ @@ -52,7 +52,6 @@ export type StepActions = { files?: string[] watchers?: string[] filter?: string - subtasks?: string[] } export interface TestRunnerArgs { diff --git a/web-app/src/containers/Tutorial/components/Level.tsx b/web-app/src/containers/Tutorial/components/Level.tsx index 27ff8c77..bc738d6d 100644 --- a/web-app/src/containers/Tutorial/components/Level.tsx +++ b/web-app/src/containers/Tutorial/components/Level.tsx @@ -199,8 +199,8 @@ const Level = ({ return null } let subtasks = null - if (step?.setup?.subtasks) { - subtasks = step.setup.subtasks.map((subtask: string, subtaskIndex: number) => ({ + if (step?.subtasks) { + subtasks = step.subtasks.map((subtask: string, subtaskIndex: number) => ({ name: subtask, pass: !!(testStatus?.summary ? testStatus.summary[subtaskIndex] : false), })) diff --git a/web-app/src/services/state/actions/editor.ts b/web-app/src/services/state/actions/editor.ts index a1642933..da0c09e3 100644 --- a/web-app/src/services/state/actions/editor.ts +++ b/web-app/src/services/state/actions/editor.ts @@ -57,7 +57,7 @@ export default (editorSend: any) => ({ }, }) - if (step.setup.subtasks) { + if (step.subtasks) { // load subtask summary by running tests and parsing result editorSend({ type: 'EDITOR_RUN_TEST', From 259f01e9909651e72dd955a6e8aa5c678afb46ed Mon Sep 17 00:00:00 2001 From: shmck Date: Sun, 5 Jul 2020 18:13:28 -0700 Subject: [PATCH 015/405] fix level stories Signed-off-by: shmck --- typings/tutorial.d.ts | 4 + .../Tutorial/components/ContentMenu.tsx | 8 +- .../containers/Tutorial/components/Level.tsx | 8 +- web-app/stories/Level.stories.tsx | 477 +++--------------- 4 files changed, 92 insertions(+), 405 deletions(-) diff --git a/typings/tutorial.d.ts b/typings/tutorial.d.ts index e43aa884..92d8ddbf 100644 --- a/typings/tutorial.d.ts +++ b/typings/tutorial.d.ts @@ -1,3 +1,5 @@ +import { ProgressStatus } from './index' + export type Maybe = T | null export type TutorialConfig = { @@ -19,6 +21,7 @@ export type Level = { setup?: Maybe /** A set of tasks for users linked to unit tests */ steps: Array + status?: ProgressStatus } /** A level task */ @@ -29,6 +32,7 @@ export type Step = { solution: Maybe hints?: string[] subtasks?: string[] + status?: ProgressStatus } /** A tutorial for use in VSCode CodeRoad */ diff --git a/web-app/src/containers/Tutorial/components/ContentMenu.tsx b/web-app/src/containers/Tutorial/components/ContentMenu.tsx index 3399ed60..b0924f3f 100644 --- a/web-app/src/containers/Tutorial/components/ContentMenu.tsx +++ b/web-app/src/containers/Tutorial/components/ContentMenu.tsx @@ -5,16 +5,16 @@ import { Menu } from '@alifd/next' import Icon from '../../../components/Icon' interface Props { - tutorial: TT.Tutorial + levels: TT.Level[] position: T.Position progress: T.Progress setTitle: (title: string) => void setContent: (content: string) => void } -const ContentMenu = ({ tutorial, position, progress, setTitle, setContent }: Props) => { +const ContentMenu = ({ levels, position, progress, setTitle, setContent }: Props) => { const setMenuContent = (levelId: string) => { - const selectedLevel: TT.Level | undefined = tutorial.levels.find((l: TT.Level) => l.id === levelId) + const selectedLevel: TT.Level | undefined = levels.find((l: TT.Level) => l.id === levelId) if (selectedLevel) { setTitle(selectedLevel.title) setContent(selectedLevel.content) @@ -22,7 +22,7 @@ const ContentMenu = ({ tutorial, position, progress, setTitle, setContent }: Pro } return ( - {tutorial.levels.map((level: TT.Level) => { + {levels.map((level: TT.Level) => { const isCurrent = level.id === position.levelId const isComplete = progress.levels[level.id] let icon diff --git a/web-app/src/containers/Tutorial/components/Level.tsx b/web-app/src/containers/Tutorial/components/Level.tsx index bc738d6d..4a254f47 100644 --- a/web-app/src/containers/Tutorial/components/Level.tsx +++ b/web-app/src/containers/Tutorial/components/Level.tsx @@ -88,7 +88,7 @@ const styles = { } interface Props { - tutorial: TT.Tutorial + tutorial: Exclude index: number status: 'COMPLETE' | 'ACTIVE' | 'INCOMPLETE' progress: T.Progress @@ -114,7 +114,9 @@ const Level = ({ processes, testStatus, }: Props) => { - const level = tutorial.levels[index] + const level: TT.Level = tutorial.levels[index] + + console.log(level) const [title, setTitle] = React.useState(level.title) const [content, setContent] = React.useState(level.content) @@ -135,7 +137,7 @@ const Level = ({ const menu = ( } -const menu = ( - - {[{ id: '1', title: 'First' }].map((level: TT.Level) => { - const icon = - return ( - - {icon}   {level.title} - - ) - })} - -) - -storiesOf('Level', module) - .addDecorator(SideBarDecorator) - .addDecorator(withKnobs) - .add('Level', () => { - const level = { - id: 'L1', - index: 0, +const tutorial: Partial = { + levels: [ + { + id: '1', title: 'A Title', - description: 'A summary of the level', - content: 'Some content here in markdown', - setup: null, - status: 'ACTIVE' as 'ACTIVE', - steps: [ - { - id: 'L1:S1', - title: 'First Step', - content: 'First step description', - setup: { - id: 'L1:S1:SETUP', - commits: ['abcdefg'], - }, - solution: { - id: 'L1:S1:SOLUTION', - commits: ['hijklmn'], - }, - status: 'COMPLETE', - }, - { - id: 'L1:S2', - title: 'Second Step', - content: 'Second step description', - setup: { - id: 'L1:S2:SETUP', - commits: ['abcdefg'], - }, - solution: { - id: 'L1:S2:SOLUTION', - commits: ['hijklmn'], - }, - status: 'ACTIVE', - }, - { - id: 'L1:S3', - title: 'Third Step', - content: 'Third step description', - setup: { - id: 'L1:S3:SETUP', - commits: ['abcdefg'], - }, - solution: { - id: 'L1:S3:SOLUTION', - commits: ['hijklmn'], - }, - status: 'INCOMPLETE', - }, - ], - } - return ( - - ) - }) - .add('Subtasks', () => { - const level = { - id: 'L1', - index: 0, - title: 'A Title', - description: 'A summary of the level', - content: 'Some content here in markdown', + summary: 'A summary of the level', + content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', setup: null, status: 'ACTIVE' as 'ACTIVE', steps: [ { - id: 'L1:S1', - title: 'First Step', - content: 'First step description', + id: '1.1', + content: 'Should support markdown test\n ```shell\nnpn install some-packagen```\nwhew it works!', setup: { - id: 'L1:S1:SETUP', commits: ['abcdefg'], }, solution: { - id: 'L1:S1:SOLUTION', commits: ['hijklmn'], }, status: 'COMPLETE', }, { - id: 'L1:S2', - title: 'Second Step', - content: 'Second step description', + id: '1.2', + content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', setup: { - id: 'L1:S2:SETUP', commits: ['abcdefg'], - filter: '^SomeTest', }, solution: { - id: 'L1:S2:SOLUTION', commits: ['hijklmn'], }, status: 'ACTIVE', }, { - id: 'L1:S3', - title: 'Third Step', - content: 'Third step description', + id: '1.3', + content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', setup: { - id: 'L1:S3:SETUP', commits: ['abcdefg'], }, solution: { - id: 'L1:S3:SOLUTION', commits: ['hijklmn'], }, status: 'INCOMPLETE', }, ], - } - const testStatus: T.TestStatus = { - type: 'error', - title: 'Test Failed because X', - summary: { - 'The first task in a set of multiple subtasks': false, - 'The second task out of a bunch of subtasks': true, - 'The third and final task that has more text and might even wrap around because the text just keeps rambling on longer than anyone would conceivably want to read': false, - }, - } - return ( - - ) - }) - .add('Level 2', () => { - const level = { - id: 'L1', - index: 1, - title: 'A Title', - description: 'A description', - content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', - setup: { commits: ['77e57cd'], commands: ['npm install'], files: [] }, - status: 'ACTIVE' as 'ACTIVE', - steps: [ - { - id: 'L1:S1', - content: 'Should support markdown test\n ```shell\nnpn install some-packagen```\nwhew it works!', - setup: { commits: ['a4679b1'], commands: [], files: ['package.json'] }, - solution: { - commits: ['7c64508'], - commands: ['npm install'], - files: ['package.json'], - }, - status: 'COMPLETE', - }, - { - id: 'L1:S2', - content: 'Should support markdown test\n ```ts\nvar a = 1\n```\nwhew it works!', - setup: { commits: ['8a8a5cb'], commands: [], files: ['src/main.ts'] }, - solution: { commits: ['c2f7973'], commands: [], files: ['src/main.ts'] }, - status: 'COMPLETE', - }, - { - id: 'L1:S3', - content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', - setup: { commits: ['992bcb1'], commands: [], files: ['src/main.ts'] }, - solution: { commits: ['1b92779'], commands: [], files: ['src/main.ts'] }, - status: 'COMPLETE', - }, - { - id: 'L1:S4', - content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', - setup: { commits: ['be32adb'], commands: [], files: ['src/main.ts'] }, - solution: { commits: ['7fe26cb'], commands: [], files: ['src/main.ts'] }, - status: 'COMPLETE', - }, - ], - } - return ( - - ) - }) - .add('FakeBook API L1', () => { - const level = { - id: 'L1', - title: 'Server Setup', - description: 'Configure a GraphQL server using Apollo Server.', - content: - 'Apollo Server is a popular and easy to configure GraphQL server.\n[Apollo Server](https://www.apollographql.com/docs/apollo-server/ee7fbac9c0ca5b1dd6aef886bb695e63/index-diagram.svg)\nBy the end of this lesson you should have your own working server started.', - setup: { - commits: ['6adeb95'], - commands: ['npm install'], - }, - status: 'ACTIVE' as 'ACTIVE', - steps: [ - { - id: 'L1:S1', - content: - 'Start by installing the apollo server dependencies. In a terminal, run:\n ```shell\nnpm install --save apollo-server graphql\n```', - setup: { - files: ['package.json'], - commits: ['b904b87'], - watchers: ['./node_modules/{apollo-server,graphql}/package.json'], - }, - solution: { - files: ['package.json'], - commits: ['ad87a86'], - commands: ['npm install'], - }, - }, - { - id: 'L1:S2', - content: - 'Setup your Apollo Server in `src/main.ts`. Notice that the GraphQL requires two elements: `typeDefs` & `resolvers` - more on these later.\nConfigure the server in the following way:\n```ts\nexport const server = new ApolloServer({\n typeDefs,\n resolvers,\n})\n```', - setup: { - files: ['src/main.ts'], - commits: ['13d8c60'], - }, - solution: { - files: ['src/main.ts'], - commits: ['3dd3500'], - }, - }, - { - id: 'L1:S3', - content: - 'Internally, Apollo is really running an [Express](https://expressjs.com/) server.\nTo start the server call `listen`.\n ```shell\nserver.listen(4000)\n```', - setup: { - files: ['src/main.ts'], - commits: ['1d55cc5'], - }, - solution: { - files: ['src/main.ts'], - commits: ['c92311f'], - }, - }, - { - id: 'L1:S4', - content: - 'GraphQL playground is a UI for viewing your schema & docs and testing queries.\nThe playground can be easily configured, just specify `playground: true` in the config.\n```js\nApolloServer({\n /*...*/\n playground: true,\n})\n```\nVisit http://localhost:4000/graphql to see the playground in action.', - setup: { - files: ['src/main.ts'], - commits: ['50da94e'], - }, - solution: { - files: ['src/main.ts'], - commits: ['865b805'], - }, - }, - ], - } - return ( - - ) - }) - .add('FakeBook API L2', () => { - const level = { - id: 'L2', - title: 'TypeDefs & Resolvers', - description: 'Build endpoints for a User', - content: - 'TypeDefs & Resolvers are the building blocks of GraphQL.\nTypeDefs are the "what", they spell out the shape of the graph. Think of typeDefs like a blueprint.\nResolvers define the "how" and "where", as in how the data is put into the graph and where it comes from.\nNote that there are a few special typeDefs you should know about, but we can start with one: `Query`. `Query` is the entry point for requests.\n', - setup: { - commits: ['0d7543c'], - commands: ['npm install'], - }, - status: 'ACTIVE' as 'ACTIVE', - steps: [ - { - id: 'L2:S1', - content: - 'Start by defining **typeDefs** for the current user, we can call the user `Viewer`.\n```\ntype Query {\n viewer: User\n}\n```\nBut now you will have to define what `User` is below.\n```\ntype User {\n id: ID!\n firstName: String\n lastName: String\n}\n```', - setup: { - files: ['src/typeDefs.ts'], - commits: ['76890db'], - }, - solution: { - commits: ['c5ee208'], - }, - }, - { - id: 'L2:S2', - content: - 'Now that we have typeDefs for `Viewer` and `User` we can define the **resolvers**.\nNotice there is user data located in the `src/data/users.ts` file. Import it.\n```ts\nimport users from "./data/users"\n```\nJust to keep things simple, you can resolve the `viewer` as the user with an id of `1`.\n```ts\nviewer() {\n return users.find(user => user.id === "1")\n}\n```\nRun the server and try your solution in the Playground to see if it worked. The query should look something like\n```\nquery {\n viewer\n}\n```\nHow can it work without resolving the User?', - setup: { - files: ['src/resolvers.ts'], - commits: ['646f930'], - }, - solution: { - commits: ['f382098'], - }, - }, - { - id: 'L2:S3', - content: - 'In GraphQL we follow a process: typeDefs then resolvers. We can practice the pattern\nAdd a list of friends to the user typeDef.\n```\ntype User {\n id: ID!\n firstName: String\n lastName: String\n friends: [User]\n }\n```\nNote that a typesDef can even call itself!', - setup: { - files: ['src/typeDefs.ts'], - commits: ['f00e6e6'], - }, - solution: { - commits: ['04fb044'], - }, - }, - { - id: 'L2:S3', - content: - 'Next we can load the friends with resolvers. If you look in `src/data/users` you can see that users are stored as user ids.\n```json\n{\n id: 1,\n jsonfriends: [ "19", "22", "30" ]\n}\n```\nWe need to tell graphql to resolve the user ids on friends. We can use the first param passed into resolvers - often called **parent**. The parent `Viewer` passes params down to the child `User` which uses the ids to resolve the next users.\n```ts\nUser: {\n friends(parent) {\n const userFriends = parent.friends\n return users.filter(user => userFriends.includes(user.id))\n }\n}\n```', - setup: { - files: ['src/resolvers.ts'], - commits: ['932a621'], - }, - solution: { - commits: ['bd79f75'], - }, - }, - ], - } - return ( - - ) - }) - .add('No steps', () => { - const level = { - id: 'L1', - index: 0, - title: 'A Title', - description: 'A summary of the level', - content: 'Some content here in markdown', - setup: null, - status: 'ACTIVE' as 'ACTIVE', - steps: [], - } - return ( - - ) - }) + }, + ], +} + +storiesOf('Level', module) + .addDecorator(SideBarDecorator) + .addDecorator(withKnobs) + .add('Level', () => ( + + )) + .add('Level 2', () => ( + + )) + .add('No steps', () => ( + + )) + .add('No lesson', () => ( + + )) From 209b07bf00c92c75a319c0176a2f96c3e00070a6 Mon Sep 17 00:00:00 2001 From: shmck Date: Sat, 11 Jul 2020 09:17:17 -0700 Subject: [PATCH 016/405] remove level headers Signed-off-by: shmck --- .../containers/Tutorial/components/Level.tsx | 37 +++++++++---------- web-app/stories/Level.stories.tsx | 14 ++++++- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/web-app/src/containers/Tutorial/components/Level.tsx b/web-app/src/containers/Tutorial/components/Level.tsx index 4a254f47..c4fe0d04 100644 --- a/web-app/src/containers/Tutorial/components/Level.tsx +++ b/web-app/src/containers/Tutorial/components/Level.tsx @@ -7,7 +7,6 @@ import Icon from '../../../components/Icon' import Button from '../../../components/Button' import Markdown from '../../../components/Markdown' import ProcessMessages from '../../../components/ProcessMessages' -import NuxTutorial from '../../../components/NewUserExperience/NuxTutorial' import ContentMenu from './ContentMenu' import Step from './Step' import { DISPLAY_RUN_TEST_BUTTON } from '../../../environment' @@ -43,6 +42,10 @@ const styles = { padding: '0rem 1rem', paddingBottom: '1rem', }, + separator: { + height: 0, + borderBottom: '1px solid rgba(0, 0, 0, 0.1)', + }, tasks: {}, steps: { padding: '1rem 1rem', @@ -171,20 +174,19 @@ const Level = ({ return (
    +
    + + {tutorial.summary.title} + + } + triggerType="click" + > + {menu} + +
    -
    - - Learn - - } - triggerType="click" - > - {menu} - -
    - {content.length ? (

    {title}

    @@ -192,9 +194,10 @@ const Level = ({
    ) : null} + {content.length && steps.length ?
    : null} + {steps.length ? (
    -
    Tasks
    {steps.map((step: (TT.Step & { status: T.ProgressStatus }) | null, stepIndex: number) => { if (!step) { @@ -233,10 +236,6 @@ const Level = ({
    )} -
    - -
    -
    {DISPLAY_RUN_TEST_BUTTON && status !== 'COMPLETE' ? ( - ) : null} - - ) - } +const ProcessMessages = ({ processes }: Props) => { if (!processes.length) { return null } diff --git a/web-app/src/components/TestMessage/index.tsx b/web-app/src/components/TestMessage/index.tsx new file mode 100644 index 00000000..300382c3 --- /dev/null +++ b/web-app/src/components/TestMessage/index.tsx @@ -0,0 +1,49 @@ +import * as React from 'react' +import Icon from '../Icon' +import { css, jsx } from '@emotion/core' + +const styles = { + container: { + backgroundColor: '#fff3e0', + padding: '0.5rem', + animationDuration: '0.3s', + animationTimingFunction: 'ease-in-out', + borderTopLeftRadius: '4px', + borderTopRightRadius: '4px', + color: 'rgb(51, 51, 51)', + fontSize: '0.8rem', + }, + icon: { + color: '#ff9300', + }, + content: { + marginLeft: '0.5rem', + }, +} + +interface Props { + message?: string +} + +const TestMessage = (props: Props) => { + const [visible, setVisible] = React.useState(true) + + React.useEffect(() => { + setVisible(true) + const timeout = setTimeout(() => { + setVisible(false) + }, 4500) + return () => { + clearTimeout(timeout) + } + }, [props.message]) + + return visible && props.message ? ( +
    + + {props.message} +
    + ) : null +} + +export default TestMessage diff --git a/web-app/src/containers/Tutorial/components/Level.tsx b/web-app/src/containers/Tutorial/components/Level.tsx index c4fe0d04..8e626418 100644 --- a/web-app/src/containers/Tutorial/components/Level.tsx +++ b/web-app/src/containers/Tutorial/components/Level.tsx @@ -7,6 +7,7 @@ import Icon from '../../../components/Icon' import Button from '../../../components/Button' import Markdown from '../../../components/Markdown' import ProcessMessages from '../../../components/ProcessMessages' +import TestMessage from '../../../components/TestMessage' import ContentMenu from './ContentMenu' import Step from './Step' import { DISPLAY_RUN_TEST_BUTTON } from '../../../environment' @@ -58,15 +59,17 @@ const styles = { processes: { padding: '0 1rem', position: 'fixed' as 'fixed', - bottom: '4rem', + bottom: '2rem', left: 0, right: 0, + top: 'auto', }, - nux: { - position: 'fixed' as 'fixed', + testMessage: { + position: 'absolute' as 'absolute', + top: 'auto', bottom: '2rem', - left: 0, - right: 0, + left: '5px', + right: '5px', }, footer: { display: 'flex' as 'flex', @@ -119,8 +122,6 @@ const Level = ({ }: Props) => { const level: TT.Level = tutorial.levels[index] - console.log(level) - const [title, setTitle] = React.useState(level.title) const [content, setContent] = React.useState(level.content) @@ -230,13 +231,20 @@ const Level = ({
    - {((testStatus && testStatus.type !== 'hidden') || processes.length > 0) && ( -
    - -
    - )} -
    + {/* Process Modal */} + {processes.length > 0 && ( +
    + +
    + )} + {/* Test Fail Modal */} + {testStatus && testStatus.type === 'warning' && ( +
    + +
    + )} + {DISPLAY_RUN_TEST_BUTTON && status !== 'COMPLETE' ? ( - ) : ( - - {typeof index === 'number' ? `${index + 1}. ` : ''} - {title} - - )} + ) : null} {status === 'COMPLETE' || !steps.length ? ( + {tutorial.summary.title} +
    { processes={processes} testStatus={testStatus} /> + + Menu content here +
    ) } diff --git a/web-app/stories/Tutorial.stories.tsx b/web-app/stories/Tutorial.stories.tsx new file mode 100644 index 00000000..c5d40201 --- /dev/null +++ b/web-app/stories/Tutorial.stories.tsx @@ -0,0 +1,92 @@ +import { action } from '@storybook/addon-actions' +import { withKnobs } from '@storybook/addon-knobs' +import { storiesOf } from '@storybook/react' +import React from 'react' +import * as T from '../../typings' +import * as TT from '../../typings/tutorial' +import Tutorial from '../src/containers/Tutorial' +import SideBarDecorator from './utils/SideBarDecorator' + +type ModifiedLevel = TT.Level & { + status: T.ProgressStatus + index: number + steps: Array +} + +const context: Partial = { + env: { machineId: '', sessionId: '', token: '' }, + error: null, + position: { levelId: '1', stepId: '1.1' }, + progress: { levels: {}, steps: {}, complete: false }, + processes: [], + testStatus: null, + tutorial: { + id: '', + version: '0.1.0', + config: { + appVersions: { vscode: '0.1.0' }, + testRunner: { + command: '', + args: { tap: '' }, + }, + repo: { + branch: '', + uri: '', + }, + }, + summary: { + title: 'Example Title', + description: 'An example description', + }, + levels: [ + { + id: '1', + title: 'A Title', + summary: 'A summary of the level', + content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', + setup: null, + status: 'ACTIVE' as 'ACTIVE', + steps: [ + { + id: '1.1', + content: 'Should support markdown test\n ```shell\nnpn install some-packagen```\nwhew it works!', + setup: { + commits: ['abcdefg'], + }, + solution: { + commits: ['hijklmn'], + }, + status: 'COMPLETE', + }, + { + id: '1.2', + content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', + setup: { + commits: ['abcdefg'], + }, + solution: { + commits: ['hijklmn'], + }, + status: 'ACTIVE', + }, + { + id: '1.3', + content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', + setup: { + commits: ['abcdefg'], + }, + solution: { + commits: ['hijklmn'], + }, + status: 'INCOMPLETE', + }, + ], + }, + ], + }, +} + +storiesOf('Tutorial', module) + .addDecorator(SideBarDecorator) + .addDecorator(withKnobs) + .add('Example', () => ) From 511ac1274259aa617dea2e264c3471cef4e6a775 Mon Sep 17 00:00:00 2001 From: shmck Date: Sat, 11 Jul 2020 11:36:08 -0700 Subject: [PATCH 023/405] menu button Signed-off-by: shmck --- web-app/src/containers/Tutorial/index.tsx | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/web-app/src/containers/Tutorial/index.tsx b/web-app/src/containers/Tutorial/index.tsx index 7dbcbf71..69e7f544 100644 --- a/web-app/src/containers/Tutorial/index.tsx +++ b/web-app/src/containers/Tutorial/index.tsx @@ -1,7 +1,7 @@ import * as React from 'react' import * as T from 'typings' import * as TT from 'typings/tutorial' -import { Button, Drawer } from '@alifd/next' +import { Drawer } from '@alifd/next' import * as selectors from '../../services/selectors' import Level from './components/Level' import Icon from '../../components/Icon' @@ -10,12 +10,15 @@ const styles = { header: { display: 'flex' as 'flex', alignItems: 'center', - justifyContent: 'space-between', + justifyContent: 'flex-start', height: '2rem', backgroundColor: '#EBEBEB', fontSize: '1rem', lineHeight: '1rem', - padding: '10px 1rem', + padding: '10px 0.4rem', + }, + title: { + marginLeft: '0.5rem', }, learn: { textDecoration: 'none', @@ -65,10 +68,10 @@ const TutorialPage = (props: PageProps) => { return (
    - - {tutorial.summary.title} + setMenuVisible(!menuVisible)}> + + + {tutorial.summary.title}
    Date: Sat, 11 Jul 2020 12:56:00 -0700 Subject: [PATCH 024/405] setup side menu with options Signed-off-by: shmck --- .../Tutorial/components/SideMenu.tsx | 57 +++++++++++++++++++ web-app/src/containers/Tutorial/index.tsx | 10 +--- 2 files changed, 59 insertions(+), 8 deletions(-) create mode 100644 web-app/src/containers/Tutorial/components/SideMenu.tsx diff --git a/web-app/src/containers/Tutorial/components/SideMenu.tsx b/web-app/src/containers/Tutorial/components/SideMenu.tsx new file mode 100644 index 00000000..ab3b5e43 --- /dev/null +++ b/web-app/src/containers/Tutorial/components/SideMenu.tsx @@ -0,0 +1,57 @@ +import * as React from 'react' +import { Menu, Icon, Drawer } from '@alifd/next' + +const { Item, Divider } = Menu + +const styles = { + drawer: { + padding: 0, + }, + menu: { + margin: 0, + height: '100%', + }, + itemText: { + marginLeft: '0.5rem', + }, +} + +interface Props { + visible: boolean + toggleVisible(visible: boolean): void +} + +const SideMenu = (props: Props) => { + const onMenuClose = () => { + props.toggleVisible(false) + } + return ( + + + + + Review + + {/* + + + Help + */} + + + + Settings + + + + ) +} + +export default SideMenu diff --git a/web-app/src/containers/Tutorial/index.tsx b/web-app/src/containers/Tutorial/index.tsx index 69e7f544..0d3cbca3 100644 --- a/web-app/src/containers/Tutorial/index.tsx +++ b/web-app/src/containers/Tutorial/index.tsx @@ -1,8 +1,8 @@ import * as React from 'react' import * as T from 'typings' import * as TT from 'typings/tutorial' -import { Drawer } from '@alifd/next' import * as selectors from '../../services/selectors' +import SideMenu from './components/SideMenu' import Level from './components/Level' import Icon from '../../components/Icon' @@ -61,10 +61,6 @@ const TutorialPage = (props: PageProps) => { const levelStatus = progress.levels[position.levelId] ? 'COMPLETE' : 'ACTIVE' const [menuVisible, setMenuVisible] = React.useState(false) - const onMenuClose = () => { - setMenuVisible(false) - } - return (
    @@ -86,9 +82,7 @@ const TutorialPage = (props: PageProps) => { processes={processes} testStatus={testStatus} /> - - Menu content here - +
    ) } From 6cdcc6afe4417f69ad4f0cb486c0f549dd8d3bec Mon Sep 17 00:00:00 2001 From: shmck Date: Sat, 11 Jul 2020 13:38:16 -0700 Subject: [PATCH 025/405] refactor level Signed-off-by: shmck --- .../containers/Tutorial/components/Level.tsx | 104 +-------------- .../Tutorial/components/SideMenu.tsx | 15 ++- .../containers/Tutorial/components/Step.tsx | 3 - .../containers/Tutorial/containers/Review.tsx | 13 ++ .../Tutorial/containers/Settings.tsx | 13 ++ web-app/src/containers/Tutorial/index.tsx | 125 +++++++++++++++--- web-app/stories/Level.stories.tsx | 106 +++++++-------- web-app/stories/Step.stories.tsx | 5 - 8 files changed, 193 insertions(+), 191 deletions(-) create mode 100644 web-app/src/containers/Tutorial/containers/Review.tsx create mode 100644 web-app/src/containers/Tutorial/containers/Settings.tsx diff --git a/web-app/src/containers/Tutorial/components/Level.tsx b/web-app/src/containers/Tutorial/components/Level.tsx index a8b44736..b15efa1b 100644 --- a/web-app/src/containers/Tutorial/components/Level.tsx +++ b/web-app/src/containers/Tutorial/components/Level.tsx @@ -2,12 +2,8 @@ import * as React from 'react' import * as T from 'typings' import * as TT from 'typings/tutorial' import { css, jsx } from '@emotion/core' -import Button from '../../../components/Button' import Markdown from '../../../components/Markdown' -import ProcessMessages from '../../../components/ProcessMessages' -import TestMessage from '../../../components/TestMessage' import Step from './Step' -import { DISPLAY_RUN_TEST_BUTTON } from '../../../environment' const styles = { page: { @@ -40,46 +36,11 @@ const styles = { fontWeight: 'bold' as 'bold', lineHeight: '1.2rem', }, - processes: { - padding: '0 1rem', - position: 'fixed' as 'fixed', - bottom: '2rem', - left: 0, - right: 0, - top: 'auto', - }, - testMessage: { - position: 'absolute' as 'absolute', - top: 'auto', - bottom: '2rem', - left: '5px', - right: '5px', - }, - footer: { - display: 'flex' as 'flex', - flexDirection: 'row' as 'row', - justifyContent: 'space-between', - alignItems: 'center', - height: '2rem', - backgroundColor: 'black', - fontSize: '1rem', - lineHeight: '1rem', - padding: '10px 1rem', - position: 'fixed' as 'fixed', - bottom: 0, - left: 0, - right: 0, - color: 'white', - }, - taskCount: { - fontSize: '0.8rem', - opacity: 0.9, - }, } interface Props { - tutorial: Exclude - index: number + level: TT.Level + currentStep: number status: 'COMPLETE' | 'ACTIVE' | 'INCOMPLETE' progress: T.Progress position: T.Position @@ -91,21 +52,7 @@ interface Props { onOpenLogs(channel: string): void } -const Level = ({ - tutorial, - index, - status, - progress, - position, - onContinue, - onRunTest, - onLoadSolution, - onOpenLogs, - processes, - testStatus, -}: Props) => { - const level: TT.Level = tutorial.levels[index] - +const Level = ({ level, progress, position, onLoadSolution, currentStep, testStatus }: Props) => { // hold state for hints for the level const [displayHintsIndex, setDisplayHintsIndex] = React.useState([]) const setHintsIndex = (index: number, value: number) => { @@ -117,10 +64,10 @@ const Level = ({ } React.useEffect(() => { // set the hints to empty on level starts - setDisplayHintsIndex(steps.map((s) => -1)) + setDisplayHintsIndex(level.steps.map((s: TT.Step) => -1)) }, [position.levelId]) - const steps: Array = level.steps.map((step: TT.Step) => { + const steps: TT.Step[] = level.steps.map((step: TT.Step) => { // label step status for step component let status: T.ProgressStatus = 'INCOMPLETE' if (progress.steps[step.id]) { @@ -132,10 +79,6 @@ const Level = ({ }) // current - let currentStep = steps.findIndex((s) => s.status === 'ACTIVE') - if (currentStep === -1) { - currentStep = steps.length - } const pageBottomRef = React.useRef(null) const scrollToBottom = () => { @@ -159,7 +102,7 @@ const Level = ({ {steps.length ? (
    - {steps.map((step: (TT.Step & { status: T.ProgressStatus }) | null, stepIndex: number) => { + {steps.map((step: TT.Step | null, stepIndex: number) => { if (!step) { return null } @@ -173,8 +116,7 @@ const Level = ({ return ( - -
    - {/* Process Modal */} - {processes.length > 0 && ( -
    - -
    - )} - {/* Test Fail Modal */} - {testStatus && testStatus.type === 'warning' && ( -
    - -
    - )} - - {DISPLAY_RUN_TEST_BUTTON && status !== 'COMPLETE' ? ( - - ) : null} - - {status === 'COMPLETE' || !steps.length ? ( - - ) : ( - - {currentStep} of {steps.length} tasks - - )} - -
    ) diff --git a/web-app/src/containers/Tutorial/components/SideMenu.tsx b/web-app/src/containers/Tutorial/components/SideMenu.tsx index ab3b5e43..8cd6817d 100644 --- a/web-app/src/containers/Tutorial/components/SideMenu.tsx +++ b/web-app/src/containers/Tutorial/components/SideMenu.tsx @@ -19,6 +19,8 @@ const styles = { interface Props { visible: boolean toggleVisible(visible: boolean): void + page: 'level' | 'settings' | 'review' + setPage(page: 'level' | 'settings' | 'review'): void } const SideMenu = (props: Props) => { @@ -35,17 +37,16 @@ const SideMenu = (props: Props) => { onClose={onMenuClose} > - + props.setPage('level')}> + + Level + + props.setPage('review')}> Review - {/* - - - Help - */} - + props.setPage('review')}> Settings diff --git a/web-app/src/containers/Tutorial/components/Step.tsx b/web-app/src/containers/Tutorial/components/Step.tsx index edcf667e..065c22f1 100644 --- a/web-app/src/containers/Tutorial/components/Step.tsx +++ b/web-app/src/containers/Tutorial/components/Step.tsx @@ -2,12 +2,10 @@ import * as React from 'react' import * as T from 'typings' import { css, jsx } from '@emotion/core' import TestStatusIcon from './TestStatusIcon' -import Icon from '../../../components/Icon' import Hints from './Hints' import Markdown from '../../../components/Markdown' interface Props { - index: number content: string status: T.ProgressStatus subtasks: { name: string; pass: boolean }[] | null @@ -76,7 +74,6 @@ const Step = (props: Props) => { return (
  • - {subtask.name}
  • ) diff --git a/web-app/src/containers/Tutorial/containers/Review.tsx b/web-app/src/containers/Tutorial/containers/Review.tsx new file mode 100644 index 00000000..9de8aad9 --- /dev/null +++ b/web-app/src/containers/Tutorial/containers/Review.tsx @@ -0,0 +1,13 @@ +import * as React from 'react' + +const styles = { + container: { + padding: '1rem', + }, +} + +const ReviewPage = () => { + return
    Review Coming soon...
    +} + +export default ReviewPage diff --git a/web-app/src/containers/Tutorial/containers/Settings.tsx b/web-app/src/containers/Tutorial/containers/Settings.tsx new file mode 100644 index 00000000..ab653975 --- /dev/null +++ b/web-app/src/containers/Tutorial/containers/Settings.tsx @@ -0,0 +1,13 @@ +import * as React from 'react' + +const styles = { + container: { + padding: '1rem', + }, +} + +const SettingsPage = () => { + return
    Settings coming soon...
    +} + +export default SettingsPage diff --git a/web-app/src/containers/Tutorial/index.tsx b/web-app/src/containers/Tutorial/index.tsx index 0d3cbca3..77f330de 100644 --- a/web-app/src/containers/Tutorial/index.tsx +++ b/web-app/src/containers/Tutorial/index.tsx @@ -5,6 +5,12 @@ import * as selectors from '../../services/selectors' import SideMenu from './components/SideMenu' import Level from './components/Level' import Icon from '../../components/Icon' +import SettingsPage from './containers/Settings' +import ReviewPage from './containers/Review' +import Button from '../../components/Button' +import ProcessMessages from '../../components/ProcessMessages' +import TestMessage from '../../components/TestMessage' +import { DISPLAY_RUN_TEST_BUTTON } from '../../environment' const styles = { header: { @@ -24,6 +30,41 @@ const styles = { textDecoration: 'none', color: 'inherit', }, + footer: { + display: 'flex' as 'flex', + flexDirection: 'row' as 'row', + justifyContent: 'space-between', + alignItems: 'center', + height: '2rem', + backgroundColor: 'black', + fontSize: '1rem', + lineHeight: '1rem', + padding: '10px 1rem', + position: 'fixed' as 'fixed', + bottom: 0, + left: 0, + right: 0, + color: 'white', + }, + taskCount: { + fontSize: '0.8rem', + opacity: 0.9, + }, + processes: { + padding: '0 1rem', + position: 'fixed' as 'fixed', + bottom: '2rem', + left: 0, + right: 0, + top: 'auto', + }, + testMessage: { + position: 'absolute' as 'absolute', + top: 'auto', + bottom: '2rem', + left: '5px', + right: '5px', + }, } interface PageProps { @@ -59,30 +100,76 @@ const TutorialPage = (props: PageProps) => { const levelIndex = tutorial.levels.findIndex((l: TT.Level) => l.id === position.levelId) const levelStatus = progress.levels[position.levelId] ? 'COMPLETE' : 'ACTIVE' + const level: TT.Level = tutorial.levels[levelIndex] const [menuVisible, setMenuVisible] = React.useState(false) + const [page, setPage] = React.useState<'level' | 'settings' | 'review'>('level') + + let currentStep = level.steps.findIndex((s: TT.Step) => s.status === 'ACTIVE') + if (currentStep === -1) { + currentStep = level.steps.length + } + return (
    -
    - setMenuVisible(!menuVisible)}> - - - {tutorial.summary.title} +
    +
    + setMenuVisible(!menuVisible)}> + + + {tutorial.summary.title} +
    + + {page === 'level' && ( + + )} + {page === 'settings' && } + {page === 'review' && } +
    +
    + {/* Process Modal */} + {processes.length > 0 && ( +
    + +
    + )} + {/* Test Fail Modal */} + {testStatus && testStatus.type === 'warning' && ( +
    + +
    + )} + + {DISPLAY_RUN_TEST_BUTTON && levelStatus !== 'COMPLETE' ? ( + + ) : null} + + {levelStatus === 'COMPLETE' || !level.steps.length ? ( + + ) : ( + + {currentStep} of {level.steps.length} tasks + + )} +
    - - +
    ) } diff --git a/web-app/stories/Level.stories.tsx b/web-app/stories/Level.stories.tsx index 2459ac2a..d1c81cfc 100644 --- a/web-app/stories/Level.stories.tsx +++ b/web-app/stories/Level.stories.tsx @@ -13,54 +13,46 @@ type ModifiedLevel = TT.Level & { steps: Array } -const tutorial: Partial = { - summary: { - title: 'Example Title', - description: 'An example description', - }, - levels: [ +const level = { + id: '1', + title: 'A Title', + summary: 'A summary of the level', + content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', + setup: null, + status: 'ACTIVE' as 'ACTIVE', + steps: [ { - id: '1', - title: 'A Title', - summary: 'A summary of the level', + id: '1.1', + content: 'Should support markdown test\n ```shell\nnpn install some-packagen```\nwhew it works!', + setup: { + commits: ['abcdefg'], + }, + solution: { + commits: ['hijklmn'], + }, + status: 'COMPLETE', + }, + { + id: '1.2', + content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', + setup: { + commits: ['abcdefg'], + }, + solution: { + commits: ['hijklmn'], + }, + status: 'ACTIVE', + }, + { + id: '1.3', content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', - setup: null, - status: 'ACTIVE' as 'ACTIVE', - steps: [ - { - id: '1.1', - content: 'Should support markdown test\n ```shell\nnpn install some-packagen```\nwhew it works!', - setup: { - commits: ['abcdefg'], - }, - solution: { - commits: ['hijklmn'], - }, - status: 'COMPLETE', - }, - { - id: '1.2', - content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', - setup: { - commits: ['abcdefg'], - }, - solution: { - commits: ['hijklmn'], - }, - status: 'ACTIVE', - }, - { - id: '1.3', - content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', - setup: { - commits: ['abcdefg'], - }, - solution: { - commits: ['hijklmn'], - }, - status: 'INCOMPLETE', - }, - ], + setup: { + commits: ['abcdefg'], + }, + solution: { + commits: ['hijklmn'], + }, + status: 'INCOMPLETE', }, ], } @@ -70,8 +62,8 @@ storiesOf('Level', module) .addDecorator(withKnobs) .add('Level', () => ( ( ( ( ( ( ( ( ( Date: Sat, 11 Jul 2020 13:42:56 -0700 Subject: [PATCH 026/405] highlight menu items Signed-off-by: shmck --- .../Tutorial/components/SideMenu.tsx | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/web-app/src/containers/Tutorial/components/SideMenu.tsx b/web-app/src/containers/Tutorial/components/SideMenu.tsx index 8cd6817d..0a8204d8 100644 --- a/web-app/src/containers/Tutorial/components/SideMenu.tsx +++ b/web-app/src/containers/Tutorial/components/SideMenu.tsx @@ -11,6 +11,10 @@ const styles = { margin: 0, height: '100%', }, + active: { + color: 'white', + backgroundColor: 'rgb(85, 132, 255)', + }, itemText: { marginLeft: '0.5rem', }, @@ -37,16 +41,31 @@ const SideMenu = (props: Props) => { onClose={onMenuClose} > - props.setPage('level')}> + props.setPage('level')} + > Level - props.setPage('review')}> + props.setPage('review')} + > Review - props.setPage('review')}> + props.setPage('settings')} + > Settings From 8b83f53beaf303a0310ef7cc45084af414c5e5f8 Mon Sep 17 00:00:00 2001 From: shmck Date: Sat, 11 Jul 2020 13:48:55 -0700 Subject: [PATCH 027/405] refactor level content Signed-off-by: shmck --- .../Tutorial/components/Content.tsx | 33 +++++++++++++++++++ .../containers/Tutorial/components/Level.tsx | 9 ++--- 2 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 web-app/src/containers/Tutorial/components/Content.tsx diff --git a/web-app/src/containers/Tutorial/components/Content.tsx b/web-app/src/containers/Tutorial/components/Content.tsx new file mode 100644 index 00000000..7b7a36d2 --- /dev/null +++ b/web-app/src/containers/Tutorial/components/Content.tsx @@ -0,0 +1,33 @@ +import * as React from 'react' +import Markdown from '../../../components/Markdown' + +const styles = { + text: { + padding: '0rem 1rem', + paddingBottom: '1rem', + }, + title: { + fontSize: '1.2rem', + fontWeight: 'bold' as 'bold', + lineHeight: '1.2rem', + }, +} + +interface Props { + title: string + content: string +} + +const Content = (props: Props) => { + if (!props.content.length) { + return null + } + return ( +
    +

    {props.title}

    + {props.content || ''} +
    + ) +} + +export default Content diff --git a/web-app/src/containers/Tutorial/components/Level.tsx b/web-app/src/containers/Tutorial/components/Level.tsx index b15efa1b..332bea6b 100644 --- a/web-app/src/containers/Tutorial/components/Level.tsx +++ b/web-app/src/containers/Tutorial/components/Level.tsx @@ -2,7 +2,7 @@ import * as React from 'react' import * as T from 'typings' import * as TT from 'typings/tutorial' import { css, jsx } from '@emotion/core' -import Markdown from '../../../components/Markdown' +import Content from './Content' import Step from './Step' const styles = { @@ -90,12 +90,7 @@ const Level = ({ level, progress, position, onLoadSolution, currentStep, testSta return (
    - {level.content.length ? ( -
    -

    {level.title}

    - {level.content || ''} -
    - ) : null} + {level.content.length && steps.length ?
    : null} From 8ec1bcf6df8c6478fc24d9295eae3485e4ce7a8c Mon Sep 17 00:00:00 2001 From: shmck Date: Sat, 11 Jul 2020 13:57:08 -0700 Subject: [PATCH 028/405] list levels in Review Signed-off-by: shmck --- .../containers/Tutorial/containers/Review.tsx | 20 +++++++++++++++++-- web-app/src/containers/Tutorial/index.tsx | 2 +- web-app/stories/Level.stories.tsx | 2 +- web-app/stories/Tutorial.stories.tsx | 2 +- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/web-app/src/containers/Tutorial/containers/Review.tsx b/web-app/src/containers/Tutorial/containers/Review.tsx index 9de8aad9..afa2101f 100644 --- a/web-app/src/containers/Tutorial/containers/Review.tsx +++ b/web-app/src/containers/Tutorial/containers/Review.tsx @@ -1,13 +1,29 @@ import * as React from 'react' +import * as TT from 'typings/tutorial' +import Content from '../components/Content' + +interface Props { + levels: TT.Level[] +} const styles = { container: { padding: '1rem', + display: 'flex' as 'flex', + flexDirection: 'column' as 'column', }, } -const ReviewPage = () => { - return
    Review Coming soon...
    +const ReviewPage = (props: Props) => { + return ( +
    + {props.levels.map((level: TT.Level) => ( +
    + +
    + ))} +
    + ) } export default ReviewPage diff --git a/web-app/src/containers/Tutorial/index.tsx b/web-app/src/containers/Tutorial/index.tsx index 77f330de..05c971f0 100644 --- a/web-app/src/containers/Tutorial/index.tsx +++ b/web-app/src/containers/Tutorial/index.tsx @@ -136,7 +136,7 @@ const TutorialPage = (props: PageProps) => { /> )} {page === 'settings' && } - {page === 'review' && } + {page === 'review' && }
    {/* Process Modal */} diff --git a/web-app/stories/Level.stories.tsx b/web-app/stories/Level.stories.tsx index d1c81cfc..edcf5b58 100644 --- a/web-app/stories/Level.stories.tsx +++ b/web-app/stories/Level.stories.tsx @@ -23,7 +23,7 @@ const level = { steps: [ { id: '1.1', - content: 'Should support markdown test\n ```shell\nnpn install some-packagen```\nwhew it works!', + content: 'Should support markdown test\n ```shell\nnpn install some-package\n```\nwhew it works!', setup: { commits: ['abcdefg'], }, diff --git a/web-app/stories/Tutorial.stories.tsx b/web-app/stories/Tutorial.stories.tsx index c5d40201..d771fbb9 100644 --- a/web-app/stories/Tutorial.stories.tsx +++ b/web-app/stories/Tutorial.stories.tsx @@ -49,7 +49,7 @@ const context: Partial = { steps: [ { id: '1.1', - content: 'Should support markdown test\n ```shell\nnpn install some-packagen```\nwhew it works!', + content: 'Should support markdown test\n ```shell\nnpn install some-package\n```\nwhew it works!', setup: { commits: ['abcdefg'], }, From d2471141bba2c0a17fd559adb441c950e3518297 Mon Sep 17 00:00:00 2001 From: shmck Date: Sat, 11 Jul 2020 13:59:18 -0700 Subject: [PATCH 029/405] close side menu on click Signed-off-by: shmck --- .../containers/Tutorial/components/SideMenu.tsx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/web-app/src/containers/Tutorial/components/SideMenu.tsx b/web-app/src/containers/Tutorial/components/SideMenu.tsx index 0a8204d8..82400d49 100644 --- a/web-app/src/containers/Tutorial/components/SideMenu.tsx +++ b/web-app/src/containers/Tutorial/components/SideMenu.tsx @@ -45,7 +45,10 @@ const SideMenu = (props: Props) => { key="level" disabled={props.page === 'level'} style={props.page === 'level' ? styles.active : {}} - onClick={() => props.setPage('level')} + onClick={() => { + onMenuClose() + props.setPage('level') + }} > Level @@ -54,7 +57,10 @@ const SideMenu = (props: Props) => { key="review" disabled={props.page === 'review'} style={props.page === 'review' ? styles.active : {}} - onClick={() => props.setPage('review')} + onClick={() => { + onMenuClose() + props.setPage('review') + }} > Review @@ -64,7 +70,10 @@ const SideMenu = (props: Props) => { key="settings" disabled={props.page === 'settings'} style={props.page === 'settings' ? styles.active : {}} - onClick={() => props.setPage('settings')} + onClick={() => { + onMenuClose() + props.setPage('settings') + }} > Settings From 786918655fec6d41c7d61285765c15faad526ef1 Mon Sep 17 00:00:00 2001 From: shmck Date: Sat, 11 Jul 2020 15:22:11 -0700 Subject: [PATCH 030/405] show content in review Signed-off-by: shmck --- .../containers/Tutorial/components/Hints.tsx | 3 + .../containers/Tutorial/components/Level.tsx | 49 +----- .../containers/Tutorial/components/Step.tsx | 9 - .../containers/Tutorial/components/Steps.tsx | 52 ++++++ .../containers/Tutorial/containers/Review.tsx | 26 ++- web-app/src/containers/Tutorial/index.tsx | 18 +- web-app/stories/Level.stories.tsx | 24 --- web-app/stories/Review.stories.tsx | 157 ++++++++++++++++++ web-app/stories/Step.stories.tsx | 42 +---- 9 files changed, 255 insertions(+), 125 deletions(-) create mode 100644 web-app/src/containers/Tutorial/components/Steps.tsx create mode 100644 web-app/stories/Review.stories.tsx diff --git a/web-app/src/containers/Tutorial/components/Hints.tsx b/web-app/src/containers/Tutorial/components/Hints.tsx index 345cc5b9..c074b2a0 100644 --- a/web-app/src/containers/Tutorial/components/Hints.tsx +++ b/web-app/src/containers/Tutorial/components/Hints.tsx @@ -25,6 +25,9 @@ interface Props { } const Hints = (props: Props) => { + if (!props.hints || !props.hints.length) { + return null + } const isFinalHint = props.hints.length - 1 === props.hintIndex const nextHint = () => { if (isFinalHint) { diff --git a/web-app/src/containers/Tutorial/components/Level.tsx b/web-app/src/containers/Tutorial/components/Level.tsx index 332bea6b..0a04e29c 100644 --- a/web-app/src/containers/Tutorial/components/Level.tsx +++ b/web-app/src/containers/Tutorial/components/Level.tsx @@ -3,7 +3,7 @@ import * as T from 'typings' import * as TT from 'typings/tutorial' import { css, jsx } from '@emotion/core' import Content from './Content' -import Step from './Step' +import Steps from './Steps' const styles = { page: { @@ -27,10 +27,7 @@ const styles = { height: 0, borderBottom: '1px solid rgba(0, 0, 0, 0.1)', }, - tasks: {}, - steps: { - padding: '1rem 1rem', - }, + title: { fontSize: '1.2rem', fontWeight: 'bold' as 'bold', @@ -46,13 +43,9 @@ interface Props { position: T.Position processes: T.ProcessEvent[] testStatus: T.TestStatus | null - onContinue(): void - onRunTest(): void - onLoadSolution(): void - onOpenLogs(channel: string): void } -const Level = ({ level, progress, position, onLoadSolution, currentStep, testStatus }: Props) => { +const Level = ({ level, progress, position, currentStep, testStatus }: Props) => { // hold state for hints for the level const [displayHintsIndex, setDisplayHintsIndex] = React.useState([]) const setHintsIndex = (index: number, value: number) => { @@ -94,36 +87,12 @@ const Level = ({ level, progress, position, onLoadSolution, currentStep, testSta {level.content.length && steps.length ?
    : null} - {steps.length ? ( -
    -
    - {steps.map((step: TT.Step | null, stepIndex: number) => { - if (!step) { - return null - } - let subtasks = null - if (step?.subtasks) { - subtasks = step.subtasks.map((subtask: string, subtaskIndex: number) => ({ - name: subtask, - pass: !!(testStatus?.summary ? testStatus.summary[subtaskIndex] : false), - })) - } - return ( - setHintsIndex(stepIndex, value)} - /> - ) - })} -
    -
    - ) : null} +
    diff --git a/web-app/src/containers/Tutorial/components/Step.tsx b/web-app/src/containers/Tutorial/components/Step.tsx index 065c22f1..435da5be 100644 --- a/web-app/src/containers/Tutorial/components/Step.tsx +++ b/web-app/src/containers/Tutorial/components/Step.tsx @@ -2,17 +2,12 @@ import * as React from 'react' import * as T from 'typings' import { css, jsx } from '@emotion/core' import TestStatusIcon from './TestStatusIcon' -import Hints from './Hints' import Markdown from '../../../components/Markdown' interface Props { content: string status: T.ProgressStatus subtasks: { name: string; pass: boolean }[] | null - hints?: string[] - hintIndex: number - setHintIndex(value: number): void - onLoadSolution(): void } const styles = { @@ -80,10 +75,6 @@ const Step = (props: Props) => { })}
) : null} - {/* hints */} - {props.hints && props.hints.length ? ( - - ) : null}
diff --git a/web-app/src/containers/Tutorial/components/Steps.tsx b/web-app/src/containers/Tutorial/components/Steps.tsx new file mode 100644 index 00000000..db803b2a --- /dev/null +++ b/web-app/src/containers/Tutorial/components/Steps.tsx @@ -0,0 +1,52 @@ +import * as React from 'react' +import * as T from 'typings' +import * as TT from 'typings/tutorial' +import Step from './Step' +import Hints from './Hints' + +interface Props { + steps: TT.Step[] + testStatus: T.TestStatus | null + displayHintsIndex: number[] + setHintsIndex(stepIndex: number, value: number): void +} + +const styles = { + steps: { + padding: '1rem 1rem', + }, +} + +const Steps = (props: Props) => { + if (!props.steps.length) { + return null + } + return ( +
+ {props.steps.map((step: TT.Step | null, stepIndex: number) => { + if (!step) { + return null + } + let subtasks = null + if (step?.subtasks) { + subtasks = step.subtasks.map((subtask: string, subtaskIndex: number) => ({ + name: subtask, + pass: !!(props.testStatus?.summary ? props.testStatus.summary[subtaskIndex] : false), + })) + } + return ( + <> + + props.setHintsIndex(stepIndex, value)} + /> + + ) + })} +
+ ) +} + +export default Steps diff --git a/web-app/src/containers/Tutorial/containers/Review.tsx b/web-app/src/containers/Tutorial/containers/Review.tsx index afa2101f..70217df7 100644 --- a/web-app/src/containers/Tutorial/containers/Review.tsx +++ b/web-app/src/containers/Tutorial/containers/Review.tsx @@ -1,14 +1,17 @@ import * as React from 'react' +import * as T from 'typings' import * as TT from 'typings/tutorial' +import Steps from '../components/Steps' import Content from '../components/Content' interface Props { levels: TT.Level[] + progress: T.Progress + testStatus: T.TestStatus } const styles = { container: { - padding: '1rem', display: 'flex' as 'flex', flexDirection: 'column' as 'column', }, @@ -17,11 +20,22 @@ const styles = { const ReviewPage = (props: Props) => { return (
- {props.levels.map((level: TT.Level) => ( -
- -
- ))} + {props.levels.map((level: TT.Level, index: number) => { + return ( + <> +
+ + -1)} + setHintsIndex={() => {}} + /> +
+ {index < props.levels.length - 1 ?
: null} + + ) + })}
) } diff --git a/web-app/src/containers/Tutorial/index.tsx b/web-app/src/containers/Tutorial/index.tsx index 05c971f0..e41b2ad0 100644 --- a/web-app/src/containers/Tutorial/index.tsx +++ b/web-app/src/containers/Tutorial/index.tsx @@ -86,17 +86,17 @@ const TutorialPage = (props: PageProps) => { }) } - const onLoadSolution = (): void => { - props.send({ type: 'STEP_SOLUTION_LOAD' }) - } + // const onLoadSolution = (): void => { + // props.send({ type: 'STEP_SOLUTION_LOAD' }) + // } const onRunTest = (): void => { props.send({ type: 'RUN_TEST' }) } - const onOpenLogs = (channel: string): void => { - props.send({ type: 'OPEN_LOGS', payload: { channel } }) - } + // const onOpenLogs = (channel: string): void => { + // props.send({ type: 'OPEN_LOGS', payload: { channel } }) + // } const levelIndex = tutorial.levels.findIndex((l: TT.Level) => l.id === position.levelId) const levelStatus = progress.levels[position.levelId] ? 'COMPLETE' : 'ACTIVE' @@ -127,16 +127,12 @@ const TutorialPage = (props: PageProps) => { status={levelStatus} progress={progress} position={position} - onContinue={onContinue} - onRunTest={onRunTest} - onLoadSolution={onLoadSolution} - onOpenLogs={onOpenLogs} processes={processes} testStatus={testStatus} /> )} {page === 'settings' && } - {page === 'review' && } + {page === 'review' && }
{/* Process Modal */} diff --git a/web-app/stories/Level.stories.tsx b/web-app/stories/Level.stories.tsx index edcf5b58..14f7b72c 100644 --- a/web-app/stories/Level.stories.tsx +++ b/web-app/stories/Level.stories.tsx @@ -2,17 +2,9 @@ import { action } from '@storybook/addon-actions' import { withKnobs } from '@storybook/addon-knobs' import { storiesOf } from '@storybook/react' import React from 'react' -import * as T from '../../typings' -import * as TT from '../../typings/tutorial' import Level from '../src/containers/Tutorial/components/Level' import SideBarDecorator from './utils/SideBarDecorator' -type ModifiedLevel = TT.Level & { - status: T.ProgressStatus - index: number - steps: Array -} - const level = { id: '1', title: 'A Title', @@ -69,10 +61,6 @@ storiesOf('Level', module) progress={{ levels: {}, steps: {} }} processes={[]} testStatus={null} - onRunTest={action('onRunTest')} - onOpenLogs={action('onOpenLogs')} - onContinue={action('onContinue')} - onLoadSolution={action('onLoadSolution')} /> )) .add('Level 2', () => ( @@ -84,10 +72,6 @@ storiesOf('Level', module) progress={{ levels: {}, steps: { '1.1': true } }} processes={[]} testStatus={null} - onRunTest={action('onRunTest')} - onOpenLogs={action('onOpenLogs')} - onContinue={action('onContinue')} - onLoadSolution={action('onLoadSolution')} /> )) .add('No steps', () => ( @@ -99,10 +83,6 @@ storiesOf('Level', module) progress={{ levels: {}, steps: {} }} processes={[]} testStatus={null} - onRunTest={action('onRunTest')} - onOpenLogs={action('onOpenLogs')} - onContinue={action('onContinue')} - onLoadSolution={action('onLoadSolution')} /> )) .add('No lesson', () => ( @@ -114,9 +94,5 @@ storiesOf('Level', module) progress={{ levels: {}, steps: {} }} processes={[]} testStatus={null} - onRunTest={action('onRunTest')} - onOpenLogs={action('onOpenLogs')} - onContinue={action('onContinue')} - onLoadSolution={action('onLoadSolution')} /> )) diff --git a/web-app/stories/Review.stories.tsx b/web-app/stories/Review.stories.tsx new file mode 100644 index 00000000..b2d77502 --- /dev/null +++ b/web-app/stories/Review.stories.tsx @@ -0,0 +1,157 @@ +import { action } from '@storybook/addon-actions' +import { withKnobs } from '@storybook/addon-knobs' +import { storiesOf } from '@storybook/react' +import React from 'react' +import Review from '../src/containers/Tutorial/containers/Review' +import SideBarDecorator from './utils/SideBarDecorator' + +const levels = [ + { + id: '1', + title: 'First Level', + summary: 'A summary of the first level', + content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', + setup: null, + status: 'COMPLETE' as 'COMPLETE', + steps: [ + { + id: '1.1', + content: 'Should support markdown test\n ```shell\nnpn install some-package\n```\nwhew it works!', + setup: { + commits: ['abcdefg'], + }, + solution: { + commits: ['hijklmn'], + }, + status: 'COMPLETE', + hints: ['First Hint', 'Second Hint'], + }, + { + id: '1.2', + content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', + setup: { + commits: ['abcdefg'], + }, + solution: { + commits: ['hijklmn'], + }, + status: 'COMPLETE', + }, + { + id: '1.3', + content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', + setup: { + commits: ['abcdefg'], + }, + solution: { + commits: ['hijklmn'], + }, + status: 'COMPLETE', + }, + ], + }, + { + id: '2', + title: 'The Second Level', + summary: 'A summary of the 2nd level', + content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', + setup: null, + status: 'ACTIVE' as 'ACTIVE', + steps: [ + { + id: '2.1', + content: 'Should support markdown test\n ```shell\nnpn install some-package\n```\nwhew it works!', + setup: { + commits: ['abcdefg'], + }, + solution: { + commits: ['hijklmn'], + }, + status: 'COMPLETE', + }, + { + id: '2.2', + content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', + setup: { + commits: ['abcdefg'], + }, + solution: { + commits: ['hijklmn'], + }, + status: 'ACTIVE', + }, + { + id: '2.3', + content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', + setup: { + commits: ['abcdefg'], + }, + solution: { + commits: ['hijklmn'], + }, + status: 'INCOMPLETE', + }, + ], + }, + { + id: '3', + title: 'A Third Level', + summary: 'A summary of the 3rd level', + content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', + setup: null, + status: 'INCOMPLETE', + steps: [ + { + id: '3.1', + content: 'Should support markdown test\n ```shell\nnpn install some-package\n```\nwhew it works!', + setup: { + commits: ['abcdefg'], + }, + solution: { + commits: ['hijklmn'], + }, + status: 'INCOMPLETE', + }, + { + id: '3.2', + content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', + setup: { + commits: ['abcdefg'], + }, + solution: { + commits: ['hijklmn'], + }, + status: 'INCOMPLETE', + }, + { + id: '3.3', + content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', + setup: { + commits: ['abcdefg'], + }, + solution: { + commits: ['hijklmn'], + }, + status: 'INCOMPLETE', + }, + ], + }, +] + +storiesOf('Review', module) + .addDecorator(SideBarDecorator) + .addDecorator(withKnobs) + .add('Example', () => { + const progress = { + levels: { + '1': true, + }, + steps: { + '1.1': true, + '1.2': true, + '1.3': true, + '2.1': true, + }, + } + return + }) diff --git a/web-app/stories/Step.stories.tsx b/web-app/stories/Step.stories.tsx index d257ea34..0ff50789 100644 --- a/web-app/stories/Step.stories.tsx +++ b/web-app/stories/Step.stories.tsx @@ -3,6 +3,7 @@ import { select, text, withKnobs } from '@storybook/addon-knobs' import { storiesOf } from '@storybook/react' import React from 'react' import Step from '../src/containers/Tutorial/components/Step' +import Hints from '../src/containers/Tutorial/components/Hints' import SideBarDecorator from './utils/SideBarDecorator' const stepText = @@ -58,41 +59,19 @@ const paragraphText = ` storiesOf('Step', module) .addDecorator(SideBarDecorator) .addDecorator(withKnobs) - .add('Active Step', () => ( - - )) - .add('Fail Step', () => ( - - )) + .add('Active Step', () => ) + .add('Fail Step', () => ) .add('Step Markdown', () => ( )) .add('Subtasks', () => ( )) .add('Hints', () => ( - + <> + + + )) From 7418c15eceab870b6d47739af34ac9fc8f8cb23e Mon Sep 17 00:00:00 2001 From: shmck Date: Sat, 11 Jul 2020 15:48:20 -0700 Subject: [PATCH 031/405] add task progress indicator Signed-off-by: shmck --- web-app/src/containers/Tutorial/index.tsx | 47 +++++++++++++++++------ 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/web-app/src/containers/Tutorial/index.tsx b/web-app/src/containers/Tutorial/index.tsx index e41b2ad0..9c96374e 100644 --- a/web-app/src/containers/Tutorial/index.tsx +++ b/web-app/src/containers/Tutorial/index.tsx @@ -10,6 +10,7 @@ import ReviewPage from './containers/Review' import Button from '../../components/Button' import ProcessMessages from '../../components/ProcessMessages' import TestMessage from '../../components/TestMessage' +import { Progress } from '@alifd/next' import { DISPLAY_RUN_TEST_BUTTON } from '../../environment' const styles = { @@ -39,16 +40,19 @@ const styles = { backgroundColor: 'black', fontSize: '1rem', lineHeight: '1rem', - padding: '10px 1rem', + padding: '10px 0rem', position: 'fixed' as 'fixed', bottom: 0, left: 0, right: 0, color: 'white', }, - taskCount: { - fontSize: '0.8rem', - opacity: 0.9, + taskProgress: { + display: 'flex' as 'flex', + justifyContent: 'flex-end' as 'flex-end', + alignItems: 'center' as 'center', + width: '10rem', + color: 'white', }, processes: { padding: '0 1rem', @@ -147,23 +151,42 @@ const TutorialPage = (props: PageProps) => {
)} - + {/* Left */} {DISPLAY_RUN_TEST_BUTTON && levelStatus !== 'COMPLETE' ? ( - - ) : null} - + ) : ( +
+ )} + + {/* Center */} +
+ + {/* Right */} +
{levelStatus === 'COMPLETE' || !level.steps.length ? ( ) : ( - - {currentStep} of {level.steps.length} tasks - + { + return ( + + {currentStep} of {level.steps.length} + + ) + }} + /> )} - +
From 041a760c6038db92f5e24d8bfc7adcf785e67d3f Mon Sep 17 00:00:00 2001 From: shmck Date: Sat, 11 Jul 2020 15:52:23 -0700 Subject: [PATCH 032/405] cleanup tutorial example Signed-off-by: shmck --- web-app/stories/Tutorial.stories.tsx | 99 ++++++++++++++++++++++++++-- 1 file changed, 93 insertions(+), 6 deletions(-) diff --git a/web-app/stories/Tutorial.stories.tsx b/web-app/stories/Tutorial.stories.tsx index d771fbb9..6824057e 100644 --- a/web-app/stories/Tutorial.stories.tsx +++ b/web-app/stories/Tutorial.stories.tsx @@ -16,8 +16,8 @@ type ModifiedLevel = TT.Level & { const context: Partial = { env: { machineId: '', sessionId: '', token: '' }, error: null, - position: { levelId: '1', stepId: '1.1' }, - progress: { levels: {}, steps: {}, complete: false }, + position: { levelId: '2', stepId: '2.2' }, + progress: { levels: { '1': true }, steps: { '1.1': true, '1.2': true, '1.3': true, '2.1': true }, complete: false }, processes: [], testStatus: null, tutorial: { @@ -41,11 +41,11 @@ const context: Partial = { levels: [ { id: '1', - title: 'A Title', - summary: 'A summary of the level', + title: 'First Level', + summary: 'A summary of the first level', content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', setup: null, - status: 'ACTIVE' as 'ACTIVE', + status: 'COMPLETE' as 'COMPLETE', steps: [ { id: '1.1', @@ -57,6 +57,7 @@ const context: Partial = { commits: ['hijklmn'], }, status: 'COMPLETE', + hints: ['First Hint', 'Second Hint'], }, { id: '1.2', @@ -67,7 +68,7 @@ const context: Partial = { solution: { commits: ['hijklmn'], }, - status: 'ACTIVE', + status: 'COMPLETE', }, { id: '1.3', @@ -78,6 +79,92 @@ const context: Partial = { solution: { commits: ['hijklmn'], }, + status: 'COMPLETE', + }, + ], + }, + { + id: '2', + title: 'The Second Level', + summary: 'A summary of the 2nd level', + content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', + setup: null, + status: 'ACTIVE' as 'ACTIVE', + steps: [ + { + id: '2.1', + content: 'Should support markdown test\n ```shell\nnpn install some-package\n```\nwhew it works!', + setup: { + commits: ['abcdefg'], + }, + solution: { + commits: ['hijklmn'], + }, + status: 'COMPLETE', + }, + { + id: '2.2', + content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', + setup: { + commits: ['abcdefg'], + }, + solution: { + commits: ['hijklmn'], + }, + status: 'ACTIVE', + }, + { + id: '2.3', + content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', + setup: { + commits: ['abcdefg'], + }, + solution: { + commits: ['hijklmn'], + }, + status: 'INCOMPLETE', + }, + ], + }, + { + id: '3', + title: 'A Third Level', + summary: 'A summary of the 3rd level', + content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', + setup: null, + status: 'INCOMPLETE', + steps: [ + { + id: '3.1', + content: 'Should support markdown test\n ```shell\nnpn install some-package\n```\nwhew it works!', + setup: { + commits: ['abcdefg'], + }, + solution: { + commits: ['hijklmn'], + }, + status: 'INCOMPLETE', + }, + { + id: '3.2', + content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', + setup: { + commits: ['abcdefg'], + }, + solution: { + commits: ['hijklmn'], + }, + status: 'INCOMPLETE', + }, + { + id: '3.3', + content: 'Should support markdown test\n ```js\nvar a = 1\n```\nwhew it works!', + setup: { + commits: ['abcdefg'], + }, + solution: { + commits: ['hijklmn'], + }, status: 'INCOMPLETE', }, ], From 3a0575e80706815e95f622664b9656a6d94bab43 Mon Sep 17 00:00:00 2001 From: shmck Date: Sat, 11 Jul 2020 16:28:07 -0700 Subject: [PATCH 033/405] format levels/steps/subtasks in fn Signed-off-by: shmck --- .../containers/Tutorial/components/Level.tsx | 34 ++--------- .../containers/Tutorial/components/Steps.tsx | 13 +--- .../containers/Tutorial/containers/Review.tsx | 9 +-- .../src/containers/Tutorial/formatLevels.ts | 60 +++++++++++++++++++ web-app/src/containers/Tutorial/index.tsx | 50 ++++++---------- 5 files changed, 88 insertions(+), 78 deletions(-) create mode 100644 web-app/src/containers/Tutorial/formatLevels.ts diff --git a/web-app/src/containers/Tutorial/components/Level.tsx b/web-app/src/containers/Tutorial/components/Level.tsx index 0a04e29c..f047943a 100644 --- a/web-app/src/containers/Tutorial/components/Level.tsx +++ b/web-app/src/containers/Tutorial/components/Level.tsx @@ -37,15 +37,9 @@ const styles = { interface Props { level: TT.Level - currentStep: number - status: 'COMPLETE' | 'ACTIVE' | 'INCOMPLETE' - progress: T.Progress - position: T.Position - processes: T.ProcessEvent[] - testStatus: T.TestStatus | null } -const Level = ({ level, progress, position, currentStep, testStatus }: Props) => { +const Level = ({ level }: Props) => { // hold state for hints for the level const [displayHintsIndex, setDisplayHintsIndex] = React.useState([]) const setHintsIndex = (index: number, value: number) => { @@ -58,41 +52,23 @@ const Level = ({ level, progress, position, currentStep, testStatus }: Props) => React.useEffect(() => { // set the hints to empty on level starts setDisplayHintsIndex(level.steps.map((s: TT.Step) => -1)) - }, [position.levelId]) - - const steps: TT.Step[] = level.steps.map((step: TT.Step) => { - // label step status for step component - let status: T.ProgressStatus = 'INCOMPLETE' - if (progress.steps[step.id]) { - status = 'COMPLETE' - } else if (step.id === position.stepId) { - status = 'ACTIVE' - } - return { ...step, status } - }) - - // current + }, [level.id]) const pageBottomRef = React.useRef(null) const scrollToBottom = () => { // @ts-ignore pageBottomRef.current.scrollIntoView({ behavior: 'smooth' }) } - React.useEffect(scrollToBottom, [currentStep]) + React.useEffect(scrollToBottom, [level.id]) return (
- {level.content.length && steps.length ?
: null} + {level.content.length && level.steps.length ?
: null} - +
diff --git a/web-app/src/containers/Tutorial/components/Steps.tsx b/web-app/src/containers/Tutorial/components/Steps.tsx index db803b2a..7913cea2 100644 --- a/web-app/src/containers/Tutorial/components/Steps.tsx +++ b/web-app/src/containers/Tutorial/components/Steps.tsx @@ -6,7 +6,6 @@ import Hints from './Hints' interface Props { steps: TT.Step[] - testStatus: T.TestStatus | null displayHintsIndex: number[] setHintsIndex(stepIndex: number, value: number): void } @@ -23,20 +22,14 @@ const Steps = (props: Props) => { } return (
- {props.steps.map((step: TT.Step | null, stepIndex: number) => { + {/* @ts-ignore typings are different between UI & data */} + {props.steps.map((step: TT.Step & { subtasks: null | { name: string; pass: boolean }[] }, stepIndex: number) => { if (!step) { return null } - let subtasks = null - if (step?.subtasks) { - subtasks = step.subtasks.map((subtask: string, subtaskIndex: number) => ({ - name: subtask, - pass: !!(props.testStatus?.summary ? props.testStatus.summary[subtaskIndex] : false), - })) - } return ( <> - + { <>
- -1)} - setHintsIndex={() => {}} - /> + -1)} setHintsIndex={() => {}} />
{index < props.levels.length - 1 ?
: null} diff --git a/web-app/src/containers/Tutorial/formatLevels.ts b/web-app/src/containers/Tutorial/formatLevels.ts new file mode 100644 index 00000000..a8439a15 --- /dev/null +++ b/web-app/src/containers/Tutorial/formatLevels.ts @@ -0,0 +1,60 @@ +import * as T from 'typings' +import * as TT from 'typings/tutorial' + +interface Props { + progress: T.Progress + position: T.Position + levels: TT.Level[] + testStatus: T.TestStatus | null +} + +/* + * Format levels to include: + * - level.status = 'ACTIVE' | 'COMPLETE' | 'INCOMPLETE' + * - step.status = 'ACTIVE' | 'COMPLETE' | 'INCOMPLETE' | 'FAIL' + * - step.subtasks as { name: string, pass: boolean }[] + */ +const formatLevels = ({ + progress, + position, + levels, + testStatus, +}: Props): { levels: TT.Level[]; level: TT.Level; stepIndex: number } => { + // clone levels + const formattedLevels = [...levels] + + const level = formattedLevels.find((l: TT.Level) => l.id === position.levelId) + + if (!level) { + throw new Error(`Level "${position.levelId}" not found`) + } + + // add level status + level.status = progress.levels[position.levelId] ? 'COMPLETE' : 'ACTIVE' + + // add step status + level.steps = level.steps.map((step: TT.Step) => { + // label step status for step component + let status: T.ProgressStatus = 'INCOMPLETE' + if (progress.steps[step.id]) { + status = 'COMPLETE' + } else if (step.id === position.stepId) { + status = 'ACTIVE' + if (step.subtasks && step.subtasks) { + step.subtasks.map((subtask: string, subtaskIndex: number) => ({ + name: subtask, + pass: !!(testStatus?.summary ? testStatus.summary[subtaskIndex] : false), + })) + } + } + return { ...step, status } + }) + + let stepIndex = level.steps.findIndex((s: TT.Step) => s.status === 'ACTIVE') + if (stepIndex === -1) { + stepIndex = level.steps.length + } + return { levels: formattedLevels, level, stepIndex } +} + +export default formatLevels diff --git a/web-app/src/containers/Tutorial/index.tsx b/web-app/src/containers/Tutorial/index.tsx index 9c96374e..1f243faa 100644 --- a/web-app/src/containers/Tutorial/index.tsx +++ b/web-app/src/containers/Tutorial/index.tsx @@ -12,6 +12,7 @@ import ProcessMessages from '../../components/ProcessMessages' import TestMessage from '../../components/TestMessage' import { Progress } from '@alifd/next' import { DISPLAY_RUN_TEST_BUTTON } from '../../environment' +import formatLevels from './formatLevels' const styles = { header: { @@ -76,6 +77,12 @@ interface PageProps { send(action: T.Action): void } +/** + * NOTE: Unused commands + * { type: 'STEP_SOLUTION_LOAD' } + * { type: 'OPEN_LOGS', payload: { channel } } + */ + const TutorialPage = (props: PageProps) => { const { position, progress, processes, testStatus } = props.context @@ -90,29 +97,20 @@ const TutorialPage = (props: PageProps) => { }) } - // const onLoadSolution = (): void => { - // props.send({ type: 'STEP_SOLUTION_LOAD' }) - // } - const onRunTest = (): void => { props.send({ type: 'RUN_TEST' }) } - // const onOpenLogs = (channel: string): void => { - // props.send({ type: 'OPEN_LOGS', payload: { channel } }) - // } - - const levelIndex = tutorial.levels.findIndex((l: TT.Level) => l.id === position.levelId) - const levelStatus = progress.levels[position.levelId] ? 'COMPLETE' : 'ACTIVE' - const level: TT.Level = tutorial.levels[levelIndex] const [menuVisible, setMenuVisible] = React.useState(false) const [page, setPage] = React.useState<'level' | 'settings' | 'review'>('level') - let currentStep = level.steps.findIndex((s: TT.Step) => s.status === 'ACTIVE') - if (currentStep === -1) { - currentStep = level.steps.length - } + const { level, levels, stepIndex } = formatLevels({ + progress, + position, + levels: tutorial.levels, + testStatus, + }) return (
@@ -124,19 +122,9 @@ const TutorialPage = (props: PageProps) => { {tutorial.summary.title}
- {page === 'level' && ( - - )} + {page === 'level' && } {page === 'settings' && } - {page === 'review' && } + {page === 'review' && }
{/* Process Modal */} @@ -152,7 +140,7 @@ const TutorialPage = (props: PageProps) => {
)} {/* Left */} - {DISPLAY_RUN_TEST_BUTTON && levelStatus !== 'COMPLETE' ? ( + {DISPLAY_RUN_TEST_BUTTON && level.status !== 'COMPLETE' ? ( @@ -165,7 +153,7 @@ const TutorialPage = (props: PageProps) => { {/* Right */}
- {levelStatus === 'COMPLETE' || !level.steps.length ? ( + {level.status === 'COMPLETE' || !level.steps.length ? ( @@ -173,14 +161,14 @@ const TutorialPage = (props: PageProps) => { { return ( - {currentStep} of {level.steps.length} + {stepIndex} of {level.steps.length} ) }} From 2e894ce4bbe2a904a94ba7a7e482d4f0c6f956cb Mon Sep 17 00:00:00 2001 From: shmck Date: Sat, 11 Jul 2020 16:43:40 -0700 Subject: [PATCH 034/405] refactoring level data Signed-off-by: shmck --- .../containers/Tutorial/components/Level.tsx | 18 ++------ .../containers/Tutorial/containers/Review.tsx | 1 + web-app/src/containers/Tutorial/index.tsx | 18 +++++++- web-app/stories/Level.stories.tsx | 46 ++----------------- 4 files changed, 25 insertions(+), 58 deletions(-) diff --git a/web-app/src/containers/Tutorial/components/Level.tsx b/web-app/src/containers/Tutorial/components/Level.tsx index f047943a..ca862e4b 100644 --- a/web-app/src/containers/Tutorial/components/Level.tsx +++ b/web-app/src/containers/Tutorial/components/Level.tsx @@ -37,23 +37,11 @@ const styles = { interface Props { level: TT.Level + setHintsIndex(stepIndex: number, value: number): void + displayHintsIndex: number[] } -const Level = ({ level }: Props) => { - // hold state for hints for the level - const [displayHintsIndex, setDisplayHintsIndex] = React.useState([]) - const setHintsIndex = (index: number, value: number) => { - return setDisplayHintsIndex((displayHintsIndex) => { - const next = [...displayHintsIndex] - next[index] = value - return next - }) - } - React.useEffect(() => { - // set the hints to empty on level starts - setDisplayHintsIndex(level.steps.map((s: TT.Step) => -1)) - }, [level.id]) - +const Level = ({ level, setHintsIndex, displayHintsIndex }: Props) => { const pageBottomRef = React.useRef(null) const scrollToBottom = () => { // @ts-ignore diff --git a/web-app/src/containers/Tutorial/containers/Review.tsx b/web-app/src/containers/Tutorial/containers/Review.tsx index 4aa2e623..12e043ce 100644 --- a/web-app/src/containers/Tutorial/containers/Review.tsx +++ b/web-app/src/containers/Tutorial/containers/Review.tsx @@ -25,6 +25,7 @@ const ReviewPage = (props: Props) => { -1)} setHintsIndex={() => {}} />
+ {/* divider */} {index < props.levels.length - 1 ?
: null} ) diff --git a/web-app/src/containers/Tutorial/index.tsx b/web-app/src/containers/Tutorial/index.tsx index 1f243faa..e6e331e5 100644 --- a/web-app/src/containers/Tutorial/index.tsx +++ b/web-app/src/containers/Tutorial/index.tsx @@ -85,6 +85,15 @@ interface PageProps { const TutorialPage = (props: PageProps) => { const { position, progress, processes, testStatus } = props.context + // hold state for hints for the level + const [displayHintsIndex, setDisplayHintsIndex] = React.useState([]) + const setHintsIndex = (index: number, value: number) => { + return setDisplayHintsIndex((displayHintsIndex) => { + const next = [...displayHintsIndex] + next[index] = value + return next + }) + } const tutorial = selectors.currentTutorial(props.context) @@ -112,6 +121,11 @@ const TutorialPage = (props: PageProps) => { testStatus, }) + React.useEffect(() => { + // set the hints to empty on level starts + setDisplayHintsIndex(level.steps.map((s: TT.Step) => -1)) + }, [level.id]) + return (
@@ -122,7 +136,9 @@ const TutorialPage = (props: PageProps) => { {tutorial.summary.title}
- {page === 'level' && } + {page === 'level' && ( + + )} {page === 'settings' && } {page === 'review' && }
diff --git a/web-app/stories/Level.stories.tsx b/web-app/stories/Level.stories.tsx index 14f7b72c..3eada142 100644 --- a/web-app/stories/Level.stories.tsx +++ b/web-app/stories/Level.stories.tsx @@ -52,47 +52,9 @@ const level = { storiesOf('Level', module) .addDecorator(SideBarDecorator) .addDecorator(withKnobs) - .add('Level', () => ( - - )) - .add('Level 2', () => ( - - )) + .add('Level', () => ) + .add('Level 2', () => ) .add('No steps', () => ( - - )) - .add('No lesson', () => ( - + )) + .add('No lesson', () => ) From ae0c0b1c5c14c7bc38f57c5f09aa5b610950136b Mon Sep 17 00:00:00 2001 From: shmck Date: Sat, 11 Jul 2020 16:54:35 -0700 Subject: [PATCH 035/405] refactor hints Signed-off-by: shmck --- .../containers/Tutorial/components/Hints.tsx | 20 +++++++++++-------- .../containers/Tutorial/components/Level.tsx | 6 ++---- .../containers/Tutorial/components/Steps.tsx | 14 ++++--------- .../containers/Tutorial/containers/Review.tsx | 2 +- web-app/src/containers/Tutorial/index.tsx | 20 ++----------------- web-app/stories/Level.stories.tsx | 2 ++ web-app/stories/Tutorial.stories.tsx | 2 ++ 7 files changed, 25 insertions(+), 41 deletions(-) diff --git a/web-app/src/containers/Tutorial/components/Hints.tsx b/web-app/src/containers/Tutorial/components/Hints.tsx index c074b2a0..e5035c60 100644 --- a/web-app/src/containers/Tutorial/components/Hints.tsx +++ b/web-app/src/containers/Tutorial/components/Hints.tsx @@ -20,29 +20,33 @@ const styles = { interface Props { hints: string[] - hintIndex: number - setHintIndex(value: number): void } const Hints = (props: Props) => { + // hold state for hints for the level + const [hintIndex, setHintIndex] = React.useState(-1) + if (!props.hints || !props.hints.length) { return null } - const isFinalHint = props.hints.length - 1 === props.hintIndex + + const isFinalHint = props.hints.length - 1 === hintIndex + const nextHint = () => { if (isFinalHint) { return } - props.setHintIndex(props.hintIndex + 1) + setHintIndex(hintIndex + 1) } + return (
{/* only show revealed hints */} - {props.hints.map((h, i) => { - return i <= props.hintIndex ? ( -
- {h} + {props.hints.map((hint, index) => { + return index <= hintIndex ? ( +
+ {hint}
) : null })} diff --git a/web-app/src/containers/Tutorial/components/Level.tsx b/web-app/src/containers/Tutorial/components/Level.tsx index ca862e4b..680d46c2 100644 --- a/web-app/src/containers/Tutorial/components/Level.tsx +++ b/web-app/src/containers/Tutorial/components/Level.tsx @@ -37,11 +37,9 @@ const styles = { interface Props { level: TT.Level - setHintsIndex(stepIndex: number, value: number): void - displayHintsIndex: number[] } -const Level = ({ level, setHintsIndex, displayHintsIndex }: Props) => { +const Level = ({ level }: Props) => { const pageBottomRef = React.useRef(null) const scrollToBottom = () => { // @ts-ignore @@ -56,7 +54,7 @@ const Level = ({ level, setHintsIndex, displayHintsIndex }: Props) => { {level.content.length && level.steps.length ?
: null} - +
diff --git a/web-app/src/containers/Tutorial/components/Steps.tsx b/web-app/src/containers/Tutorial/components/Steps.tsx index 7913cea2..2ee26bcb 100644 --- a/web-app/src/containers/Tutorial/components/Steps.tsx +++ b/web-app/src/containers/Tutorial/components/Steps.tsx @@ -6,8 +6,6 @@ import Hints from './Hints' interface Props { steps: TT.Step[] - displayHintsIndex: number[] - setHintsIndex(stepIndex: number, value: number): void } const styles = { @@ -23,19 +21,15 @@ const Steps = (props: Props) => { return (
{/* @ts-ignore typings are different between UI & data */} - {props.steps.map((step: TT.Step & { subtasks: null | { name: string; pass: boolean }[] }, stepIndex: number) => { + {props.steps.map((step: TT.Step & { subtasks: null | { name: string; pass: boolean }[] }) => { if (!step) { return null } return ( - <> +
- props.setHintsIndex(stepIndex, value)} - /> - + +
) })}
diff --git a/web-app/src/containers/Tutorial/containers/Review.tsx b/web-app/src/containers/Tutorial/containers/Review.tsx index 12e043ce..dea45abd 100644 --- a/web-app/src/containers/Tutorial/containers/Review.tsx +++ b/web-app/src/containers/Tutorial/containers/Review.tsx @@ -23,7 +23,7 @@ const ReviewPage = (props: Props) => { <>
- -1)} setHintsIndex={() => {}} /> +
{/* divider */} {index < props.levels.length - 1 ?
: null} diff --git a/web-app/src/containers/Tutorial/index.tsx b/web-app/src/containers/Tutorial/index.tsx index e6e331e5..c240ac28 100644 --- a/web-app/src/containers/Tutorial/index.tsx +++ b/web-app/src/containers/Tutorial/index.tsx @@ -85,15 +85,6 @@ interface PageProps { const TutorialPage = (props: PageProps) => { const { position, progress, processes, testStatus } = props.context - // hold state for hints for the level - const [displayHintsIndex, setDisplayHintsIndex] = React.useState([]) - const setHintsIndex = (index: number, value: number) => { - return setDisplayHintsIndex((displayHintsIndex) => { - const next = [...displayHintsIndex] - next[index] = value - return next - }) - } const tutorial = selectors.currentTutorial(props.context) @@ -121,11 +112,6 @@ const TutorialPage = (props: PageProps) => { testStatus, }) - React.useEffect(() => { - // set the hints to empty on level starts - setDisplayHintsIndex(level.steps.map((s: TT.Step) => -1)) - }, [level.id]) - return (
@@ -136,9 +122,7 @@ const TutorialPage = (props: PageProps) => { {tutorial.summary.title}
- {page === 'level' && ( - - )} + {page === 'level' && } {page === 'settings' && } {page === 'review' && }
@@ -181,7 +165,7 @@ const TutorialPage = (props: PageProps) => { shape="line" color="rgb(85, 132, 255)" css={styles.taskProgress} - textRender={(percent: number) => { + textRender={() => { return ( {stepIndex} of {level.steps.length} diff --git a/web-app/stories/Level.stories.tsx b/web-app/stories/Level.stories.tsx index 3eada142..b0ed1592 100644 --- a/web-app/stories/Level.stories.tsx +++ b/web-app/stories/Level.stories.tsx @@ -23,6 +23,7 @@ const level = { commits: ['hijklmn'], }, status: 'COMPLETE', + hints: ['first hint', 'second hint'], }, { id: '1.2', @@ -34,6 +35,7 @@ const level = { commits: ['hijklmn'], }, status: 'ACTIVE', + hints: ['more hint action', 'another second hint'], }, { id: '1.3', diff --git a/web-app/stories/Tutorial.stories.tsx b/web-app/stories/Tutorial.stories.tsx index 6824057e..ff5be851 100644 --- a/web-app/stories/Tutorial.stories.tsx +++ b/web-app/stories/Tutorial.stories.tsx @@ -101,6 +101,7 @@ const context: Partial = { commits: ['hijklmn'], }, status: 'COMPLETE', + hints: ['first hint', 'second hint'], }, { id: '2.2', @@ -112,6 +113,7 @@ const context: Partial = { commits: ['hijklmn'], }, status: 'ACTIVE', + hints: ['another hint', 'another other hint'], }, { id: '2.3', From 9ad206969d67c9668c74b141522bef6afd5de492 Mon Sep 17 00:00:00 2001 From: shmck Date: Sat, 11 Jul 2020 17:33:59 -0700 Subject: [PATCH 036/405] number hints Signed-off-by: shmck --- web-app/src/components/Markdown/index.tsx | 3 --- web-app/src/containers/Tutorial/components/Hints.tsx | 11 ++++++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/web-app/src/components/Markdown/index.tsx b/web-app/src/components/Markdown/index.tsx index 3b9e2ffe..d5d1943a 100644 --- a/web-app/src/components/Markdown/index.tsx +++ b/web-app/src/components/Markdown/index.tsx @@ -1,8 +1,5 @@ import MarkdownIt from 'markdown-it' -// @ts-ignore no types for package - import Prism from 'prismjs' - // @ts-ignore no types for package import markdownEmoji from 'markdown-it-emoji' import * as React from 'react' diff --git a/web-app/src/containers/Tutorial/components/Hints.tsx b/web-app/src/containers/Tutorial/components/Hints.tsx index e5035c60..dfff3ff0 100644 --- a/web-app/src/containers/Tutorial/components/Hints.tsx +++ b/web-app/src/containers/Tutorial/components/Hints.tsx @@ -14,6 +14,7 @@ const styles = { marginBottom: '0.5rem', backgroundColor: 'rgba(255,229,100,0.3)', borderLeft: '#ffe564', + borderRadius: '2px', padding: '0 0.5rem', }, } @@ -44,11 +45,15 @@ const Hints = (props: Props) => {
{/* only show revealed hints */} {props.hints.map((hint, index) => { - return index <= hintIndex ? ( + if (index > hintIndex) { + // hint not yet revealed + return null + } + return (
- {hint} + {`${index + 1}. ${hint}`}
- ) : null + ) })}
) : ( From 6396e50aeb406ad77c3d4930c15855169499e777 Mon Sep 17 00:00:00 2001 From: shmck Date: Sat, 11 Jul 2020 20:50:13 -0700 Subject: [PATCH 038/405] fix missing icons Signed-off-by: shmck --- web-app/src/resources/fonts/next-icon.svg | 114 +++++++++++--------- web-app/src/resources/fonts/next-icon.woff2 | Bin 5600 -> 6116 bytes 2 files changed, 63 insertions(+), 51 deletions(-) diff --git a/web-app/src/resources/fonts/next-icon.svg b/web-app/src/resources/fonts/next-icon.svg index cb348dc4..7c731f60 100644 --- a/web-app/src/resources/fonts/next-icon.svg +++ b/web-app/src/resources/fonts/next-icon.svg @@ -20,160 +20,172 @@ Created by iconfont /> - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + diff --git a/web-app/src/resources/fonts/next-icon.woff2 b/web-app/src/resources/fonts/next-icon.woff2 index 0aa04583002b020dbdfd767a5158b84c154b0acf..f88da21febbcae7101bfe63c8fc833940a9c2bcb 100644 GIT binary patch literal 6116 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 literal 5600 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ҷ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 From 0c1405d3f449af4cbb12d7d7959dbb525c7bcf83 Mon Sep 17 00:00:00 2001 From: shmck Date: Sat, 11 Jul 2020 20:51:19 -0700 Subject: [PATCH 039/405] update deps Signed-off-by: shmck --- package.json | 16 +- src/channel/index.ts | 1 - web-app/package.json | 18 +- web-app/yarn.lock | 470 ++++++++++++++++++------------------------- yarn.lock | 233 ++++++++++++--------- 5 files changed, 349 insertions(+), 389 deletions(-) diff --git a/package.json b/package.json index 8cac0746..12ddba41 100644 --- a/package.json +++ b/package.json @@ -34,25 +34,25 @@ "watch": "tsc -watch -p ./" }, "dependencies": { - "@sentry/node": "^5.18.1", + "@sentry/node": "^5.19.1", "@types/assert": "^1.5.1", - "@types/jest": "^26.0.3", + "@types/jest": "^26.0.4", "@types/jsdom": "^16.2.3", - "@types/node": "^14.0.14", + "@types/node": "^14.0.22", "@types/node-fetch": "^2.5.7", "@types/semver": "^7.3.1", - "@typescript-eslint/eslint-plugin": "^3.4.0", - "@typescript-eslint/parser": "^3.4.0", + "@typescript-eslint/eslint-plugin": "^3.6.0", + "@typescript-eslint/parser": "^3.6.0", "chokidar": "^3.4.0", "dotenv": "^8.2.0", - "eslint": "^7.3.1", + "eslint": "^7.4.0", "git-url-parse": "^11.1.2", "jest": "^26.1.0", - "jsdom": "^16.2.2", + "jsdom": "^16.3.0", "node-fetch": "^2.6.0", "semver": "^7.3.2", "ts-jest": "^26.1.1", - "typescript": "^3.9.5" + "typescript": "^3.9.6" }, "devDependencies": { "eslint-config-prettier": "^6.11.0", diff --git a/src/channel/index.ts b/src/channel/index.ts index edf352de..00e9f202 100644 --- a/src/channel/index.ts +++ b/src/channel/index.ts @@ -351,7 +351,6 @@ class Channel implements Channel { switch (actionType) { case 'TEST_PASS': - console.log('TEST_PASS', action) const tutorial = this.context.tutorial.get() if (!tutorial) { throw new Error('Error with current tutorial. Tutorial may be missing an id.') diff --git a/web-app/package.json b/web-app/package.json index 59b8cdb3..ee9be258 100644 --- a/web-app/package.json +++ b/web-app/package.json @@ -25,11 +25,11 @@ "extends": "react-app" }, "dependencies": { - "@alifd/next": "^1.20.14", + "@alifd/next": "^1.20.18", "@alifd/theme-4": "^0.3.1", "@emotion/babel-preset-css-prop": "^10.0.27", "@emotion/core": "^10.0.28", - "@sentry/browser": "^5.18.1", + "@sentry/browser": "^5.19.1", "js-yaml": "^3.14.0", "markdown-it": "^11.0.0", "markdown-it-emoji": "^1.4.0", @@ -39,24 +39,24 @@ "react-addons-css-transition-group": "^15.6.2", "react-dom": "^16.13.1", "reselect": "^4.0.0", - "xstate": "^4.10.0" + "xstate": "^4.11.0" }, "devDependencies": { - "@babel/core": "^7.10.3", + "@babel/core": "^7.10.4", "@storybook/addon-actions": "^5.3.19", "@storybook/addon-knobs": "^5.3.19", "@storybook/addon-links": "^5.3.19", "@storybook/addons": "^5.3.19", - "@storybook/preset-create-react-app": "^3.1.2", + "@storybook/preset-create-react-app": "^3.1.4", "@storybook/react": "^5.3.19", "@types/graphql": "^14.5.0", "@types/highlight.js": "^9.12.4", - "@types/jest": "^26.0.3", + "@types/jest": "^26.0.4", "@types/js-yaml": "^3.12.5", "@types/markdown-it": "^10.0.1", - "@types/node": "^14.0.14", + "@types/node": "^14.0.22", "@types/prismjs": "^1.16.1", - "@types/react": "^16.9.41", + "@types/react": "^16.9.43", "@types/react-addons-css-transition-group": "^15.0.5", "@types/react-dom": "^16.9.8", "babel-loader": "8.1.0", @@ -68,6 +68,6 @@ "react-app-rewired": "^2.1.6", "react-scripts": "^3.4.1", "sass-loader": "^8.0.2", - "typescript": "^3.9.5" + "typescript": "^3.9.6" } } diff --git a/web-app/yarn.lock b/web-app/yarn.lock index 042b9ae9..10f4dbb1 100644 --- a/web-app/yarn.lock +++ b/web-app/yarn.lock @@ -10,10 +10,10 @@ "@alifd/validate" "^1.2.0" prop-types "^15.5.8" -"@alifd/next@^1.20.14": - version "1.20.14" - resolved "https://registry.yarnpkg.com/@alifd/next/-/next-1.20.14.tgz#d8ea3a91973636b74f89a7a5e0b98d6083401891" - integrity sha512-luzc2xYtnrPG597pfCcalcpDm36oW6XR0hz0pPiTMUWOy45w/VcpmtHe8OUynYH46I3FaaNgcPe2SAcGIxvyRw== +"@alifd/next@^1.20.18": + version "1.20.18" + resolved "https://registry.yarnpkg.com/@alifd/next/-/next-1.20.18.tgz#355d02a8ce3fe7996e52ee0295d696c8a9032060" + integrity sha512-acwDvwxQFmuheMtwHcxWqwcWrPQtNDimddzK5ZV9lthonCsEWikhZq+MCKYl/UbXRuSUnnLRApAkULOrDXqeBg== dependencies: "@alifd/field" "~1.4.1" "@alifd/validate" "~1.2.0" @@ -66,19 +66,12 @@ dependencies: "@babel/highlight" "^7.8.3" -"@babel/code-frame@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.1.tgz#d5481c5095daa1c57e16e54c6f9198443afb49ff" - integrity sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw== +"@babel/code-frame@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" + integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== dependencies: - "@babel/highlight" "^7.10.1" - -"@babel/code-frame@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.3.tgz#324bcfd8d35cd3d47dae18cde63d752086435e9a" - integrity sha512-fDx9eNW0qz0WkUeqL6tXEXzVlPh6Y5aCDEZesl0xBGA8ndRukX91Uk44ZqnkECp01NAZUdCAl+aiQNGi0k88Eg== - dependencies: - "@babel/highlight" "^7.10.3" + "@babel/highlight" "^7.10.4" "@babel/compat-data@^7.8.6", "@babel/compat-data@^7.9.0": version "7.9.0" @@ -111,19 +104,19 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.3.tgz#73b0e8ddeec1e3fdd7a2de587a60e17c440ec77e" - integrity sha512-5YqWxYE3pyhIi84L84YcwjeEgS+fa7ZjK6IBVGTjDVfm64njkR2lfDhVR5OudLk8x2GK59YoSyVv+L/03k1q9w== - dependencies: - "@babel/code-frame" "^7.10.3" - "@babel/generator" "^7.10.3" - "@babel/helper-module-transforms" "^7.10.1" - "@babel/helpers" "^7.10.1" - "@babel/parser" "^7.10.3" - "@babel/template" "^7.10.3" - "@babel/traverse" "^7.10.3" - "@babel/types" "^7.10.3" +"@babel/core@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.4.tgz#780e8b83e496152f8dd7df63892b2e052bf1d51d" + integrity sha512-3A0tS0HWpy4XujGc7QtOIHTeNwUgWaZc/WuS5YQrfhU67jnVmsD6OGPc1AKHH0LJHQICGncy3+YUjIhVlfDdcA== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.10.4" + "@babel/helper-module-transforms" "^7.10.4" + "@babel/helpers" "^7.10.4" + "@babel/parser" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.1" @@ -133,22 +126,12 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.10.1": - version "7.10.2" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.2.tgz#0fa5b5b2389db8bfdfcc3492b551ee20f5dd69a9" - integrity sha512-AxfBNHNu99DTMvlUPlt1h2+Hn7knPpH5ayJ8OqDWSeLld+Fi2AYBTC/IejWDM9Edcii4UzZRCsbUt0WlSDsDsA== - dependencies: - "@babel/types" "^7.10.2" - jsesc "^2.5.1" - lodash "^4.17.13" - source-map "^0.5.0" - -"@babel/generator@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.3.tgz#32b9a0d963a71d7a54f5f6c15659c3dbc2a523a5" - integrity sha512-drt8MUHbEqRzNR0xnF8nMehbY11b1SDkRw03PSNH/3Rb2Z35oxkddVSi3rcaak0YJQ86PCuE7Qx1jSFhbLNBMA== +"@babel/generator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.4.tgz#e49eeed9fe114b62fa5b181856a43a5e32f5f243" + integrity sha512-toLIHUIAgcQygFZRAQcsLQV3CBuX6yOIru1kJk/qqqvcRmZrYe6WavZTSG+bB8MxhnL9YPf+pKQfuiP161q7ng== dependencies: - "@babel/types" "^7.10.3" + "@babel/types" "^7.10.4" jsesc "^2.5.1" lodash "^4.17.13" source-map "^0.5.0" @@ -244,23 +227,14 @@ "@babel/traverse" "^7.8.3" "@babel/types" "^7.8.3" -"@babel/helper-function-name@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.1.tgz#92bd63829bfc9215aca9d9defa85f56b539454f4" - integrity sha512-fcpumwhs3YyZ/ttd5Rz0xn0TpIwVkN7X0V38B9TWNfVF42KEkhkAAuPCQ3oXmtTRtiPJrmZ0TrfS0GKF0eMaRQ== - dependencies: - "@babel/helper-get-function-arity" "^7.10.1" - "@babel/template" "^7.10.1" - "@babel/types" "^7.10.1" - -"@babel/helper-function-name@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.3.tgz#79316cd75a9fa25ba9787ff54544307ed444f197" - integrity sha512-FvSj2aiOd8zbeqijjgqdMDSyxsGHaMt5Tr0XjQsGKHD3/1FP3wksjnLAWzxw7lvXiej8W1Jt47SKTZ6upQNiRw== +"@babel/helper-function-name@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" + integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ== dependencies: - "@babel/helper-get-function-arity" "^7.10.3" - "@babel/template" "^7.10.3" - "@babel/types" "^7.10.3" + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" "@babel/helper-function-name@^7.8.3", "@babel/helper-function-name@^7.9.5": version "7.9.5" @@ -271,19 +245,12 @@ "@babel/template" "^7.8.3" "@babel/types" "^7.9.5" -"@babel/helper-get-function-arity@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.1.tgz#7303390a81ba7cb59613895a192b93850e373f7d" - integrity sha512-F5qdXkYGOQUb0hpRaPoetF9AnsXknKjWMZ+wmsIRsp5ge5sFh4c3h1eH2pRTTuy9KKAA2+TTYomGXAtEL2fQEw== - dependencies: - "@babel/types" "^7.10.1" - -"@babel/helper-get-function-arity@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.3.tgz#3a28f7b28ccc7719eacd9223b659fdf162e4c45e" - integrity sha512-iUD/gFsR+M6uiy69JA6fzM5seno8oE85IYZdbVVEuQaZlEzMO2MXblh+KSPJgsZAUx0EEbWXU0yJaW7C9CdAVg== +"@babel/helper-get-function-arity@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2" + integrity sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A== dependencies: - "@babel/types" "^7.10.3" + "@babel/types" "^7.10.4" "@babel/helper-get-function-arity@^7.8.3": version "7.8.3" @@ -299,12 +266,12 @@ dependencies: "@babel/types" "^7.8.3" -"@babel/helper-member-expression-to-functions@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.1.tgz#432967fd7e12a4afef66c4687d4ca22bc0456f15" - integrity sha512-u7XLXeM2n50gb6PWJ9hoO5oO7JFPaZtrh35t8RqKLT1jFKj9IWeD1zrcrYp1q1qiZTdEarfDWfTIP8nGsu0h5g== +"@babel/helper-member-expression-to-functions@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.4.tgz#7cd04b57dfcf82fce9aeae7d4e4452fa31b8c7c4" + integrity sha512-m5j85pK/KZhuSdM/8cHUABQTAslV47OjfIB9Cc7P+PvlAoBzdb79BGNfw8RhT5Mq3p+xGd0ZfAKixbrUZx0C7A== dependencies: - "@babel/types" "^7.10.1" + "@babel/types" "^7.10.4" "@babel/helper-member-expression-to-functions@^7.8.3": version "7.8.3" @@ -320,24 +287,24 @@ dependencies: "@babel/types" "^7.8.3" -"@babel/helper-module-imports@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.1.tgz#dd331bd45bccc566ce77004e9d05fe17add13876" - integrity sha512-SFxgwYmZ3HZPyZwJRiVNLRHWuW2OgE5k2nrVs6D9Iv4PPnXVffuEHy83Sfx/l4SqF+5kyJXjAyUmrG7tNm+qVg== +"@babel/helper-module-imports@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz#4c5c54be04bd31670a7382797d75b9fa2e5b5620" + integrity sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw== dependencies: - "@babel/types" "^7.10.1" + "@babel/types" "^7.10.4" -"@babel/helper-module-transforms@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.10.1.tgz#24e2f08ee6832c60b157bb0936c86bef7210c622" - integrity sha512-RLHRCAzyJe7Q7sF4oy2cB+kRnU4wDZY/H2xJFGof+M+SJEGhZsb+GFj5j1AD8NiSaVBJ+Pf0/WObiXu/zxWpFg== +"@babel/helper-module-transforms@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.10.4.tgz#ca1f01fdb84e48c24d7506bb818c961f1da8805d" + integrity sha512-Er2FQX0oa3nV7eM1o0tNCTx7izmQtwAQsIiaLRWtavAAEcskb0XJ5OjJbVrYXWOTr8om921Scabn4/tzlx7j1Q== dependencies: - "@babel/helper-module-imports" "^7.10.1" - "@babel/helper-replace-supers" "^7.10.1" - "@babel/helper-simple-access" "^7.10.1" - "@babel/helper-split-export-declaration" "^7.10.1" - "@babel/template" "^7.10.1" - "@babel/types" "^7.10.1" + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-simple-access" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" lodash "^4.17.13" "@babel/helper-module-transforms@^7.9.0": @@ -353,12 +320,12 @@ "@babel/types" "^7.9.0" lodash "^4.17.13" -"@babel/helper-optimise-call-expression@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.1.tgz#b4a1f2561870ce1247ceddb02a3860fa96d72543" - integrity sha512-a0DjNS1prnBsoKx83dP2falChcs7p3i8VMzdrSbfLhuQra/2ENC4sbri34dz/rWmDADsmF1q5GbfaXydh0Jbjg== +"@babel/helper-optimise-call-expression@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673" + integrity sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg== dependencies: - "@babel/types" "^7.10.1" + "@babel/types" "^7.10.4" "@babel/helper-optimise-call-expression@^7.8.3": version "7.8.3" @@ -390,15 +357,15 @@ "@babel/traverse" "^7.8.3" "@babel/types" "^7.8.3" -"@babel/helper-replace-supers@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.1.tgz#ec6859d20c5d8087f6a2dc4e014db7228975f13d" - integrity sha512-SOwJzEfpuQwInzzQJGjGaiG578UYmyi2Xw668klPWV5n07B73S0a9btjLk/52Mlcxa+5AdIYqws1KyXRfMoB7A== +"@babel/helper-replace-supers@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz#d585cd9388ea06e6031e4cd44b6713cbead9e6cf" + integrity sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A== dependencies: - "@babel/helper-member-expression-to-functions" "^7.10.1" - "@babel/helper-optimise-call-expression" "^7.10.1" - "@babel/traverse" "^7.10.1" - "@babel/types" "^7.10.1" + "@babel/helper-member-expression-to-functions" "^7.10.4" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" "@babel/helper-replace-supers@^7.8.3", "@babel/helper-replace-supers@^7.8.6": version "7.8.6" @@ -410,13 +377,13 @@ "@babel/traverse" "^7.8.6" "@babel/types" "^7.8.6" -"@babel/helper-simple-access@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.1.tgz#08fb7e22ace9eb8326f7e3920a1c2052f13d851e" - integrity sha512-VSWpWzRzn9VtgMJBIWTZ+GP107kZdQ4YplJlCmIrjoLVSi/0upixezHCDG8kpPVTBJpKfxTH01wDhh+jS2zKbw== +"@babel/helper-simple-access@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz#0f5ccda2945277a2a7a2d3a821e15395edcf3461" + integrity sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw== dependencies: - "@babel/template" "^7.10.1" - "@babel/types" "^7.10.1" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" "@babel/helper-simple-access@^7.8.3": version "7.8.3" @@ -426,12 +393,12 @@ "@babel/template" "^7.8.3" "@babel/types" "^7.8.3" -"@babel/helper-split-export-declaration@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.1.tgz#c6f4be1cbc15e3a868e4c64a17d5d31d754da35f" - integrity sha512-UQ1LVBPrYdbchNhLwj6fetj46BcFwfS4NllJo/1aJsT+1dLTEnXJL0qHqtY7gPzF8S2fXBJamf1biAXV3X077g== +"@babel/helper-split-export-declaration@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz#2c70576eaa3b5609b24cb99db2888cc3fc4251d1" + integrity sha512-pySBTeoUff56fL5CBU2hWm9TesA4r/rOkI9DyJLvvgz09MB9YtfIYe3iBriVaYNaPe+Alua0vBIOVOLs2buWhg== dependencies: - "@babel/types" "^7.10.1" + "@babel/types" "^7.10.4" "@babel/helper-split-export-declaration@^7.8.3": version "7.8.3" @@ -440,15 +407,10 @@ dependencies: "@babel/types" "^7.8.3" -"@babel/helper-validator-identifier@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz#5770b0c1a826c4f53f5ede5e153163e0318e94b5" - integrity sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw== - -"@babel/helper-validator-identifier@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.3.tgz#60d9847f98c4cea1b279e005fdb7c28be5412d15" - integrity sha512-bU8JvtlYpJSBPuj1VUmKpFGaDZuLxASky3LhaKj3bmpSTY6VWooSM8msk+Z0CZoErFye2tlABF6yDkT3FOPAXw== +"@babel/helper-validator-identifier@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" + integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== "@babel/helper-validator-identifier@^7.9.0", "@babel/helper-validator-identifier@^7.9.5": version "7.9.5" @@ -465,14 +427,14 @@ "@babel/traverse" "^7.8.3" "@babel/types" "^7.8.3" -"@babel/helpers@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.1.tgz#a6827b7cb975c9d9cef5fd61d919f60d8844a973" - integrity sha512-muQNHF+IdU6wGgkaJyhhEmI54MOZBKsFfsXFhboz1ybwJ1Kl7IHlbm2a++4jwrmY5UYsgitt5lfqo1wMFcHmyw== +"@babel/helpers@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.4.tgz#2abeb0d721aff7c0a97376b9e1f6f65d7a475044" + integrity sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA== dependencies: - "@babel/template" "^7.10.1" - "@babel/traverse" "^7.10.1" - "@babel/types" "^7.10.1" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" "@babel/helpers@^7.9.0": version "7.9.2" @@ -492,21 +454,12 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/highlight@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.1.tgz#841d098ba613ba1a427a2b383d79e35552c38ae0" - integrity sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg== - dependencies: - "@babel/helper-validator-identifier" "^7.10.1" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/highlight@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.3.tgz#c633bb34adf07c5c13156692f5922c81ec53f28d" - integrity sha512-Ih9B/u7AtgEnySE2L2F0Xm0GaM729XqqLfHkalTsbjXGyqmf/6M0Cu0WpvqueUlW+xk88BHw9Nkpj49naU+vWw== +"@babel/highlight@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" + integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== dependencies: - "@babel/helper-validator-identifier" "^7.10.3" + "@babel/helper-validator-identifier" "^7.10.4" chalk "^2.0.0" js-tokens "^4.0.0" @@ -515,15 +468,10 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.4.tgz#68a35e6b0319bbc014465be43828300113f2f2e8" integrity sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA== -"@babel/parser@^7.10.1": - version "7.10.2" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.2.tgz#871807f10442b92ff97e4783b9b54f6a0ca812d0" - integrity sha512-PApSXlNMJyB4JiGVhCOlzKIif+TKFTvu0aQAhnTvfP/z3vVSN6ZypH5bfUNwFXXjRQtUEBNFd2PtmCmG2Py3qQ== - -"@babel/parser@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.3.tgz#7e71d892b0d6e7d04a1af4c3c79d72c1f10f5315" - integrity sha512-oJtNJCMFdIMwXGmx+KxuaD7i3b8uS7TTFYW/FNG2BT8m+fmGHoiPYoH0Pe3gya07WuFmM5FCDIr1x0irkD/hyA== +"@babel/parser@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.4.tgz#9eedf27e1998d87739fb5028a5120557c06a1a64" + integrity sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA== "@babel/plugin-proposal-async-generator-functions@^7.8.3": version "7.8.3" @@ -1232,23 +1180,14 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/template@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.1.tgz#e167154a94cb5f14b28dc58f5356d2162f539811" - integrity sha512-OQDg6SqvFSsc9A0ej6SKINWrpJiNonRIniYondK2ViKhB06i3c0s+76XUft71iqBEe9S1OKsHwPAjfHnuvnCig== - dependencies: - "@babel/code-frame" "^7.10.1" - "@babel/parser" "^7.10.1" - "@babel/types" "^7.10.1" - -"@babel/template@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.3.tgz#4d13bc8e30bf95b0ce9d175d30306f42a2c9a7b8" - integrity sha512-5BjI4gdtD+9fHZUsaxPHPNpwa+xRkDO7c7JbhYn2afvrkDu5SfAAbi9AIMXw2xEhO/BR35TqiW97IqNvCo/GqA== +"@babel/template@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" + integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA== dependencies: - "@babel/code-frame" "^7.10.3" - "@babel/parser" "^7.10.3" - "@babel/types" "^7.10.3" + "@babel/code-frame" "^7.10.4" + "@babel/parser" "^7.10.4" + "@babel/types" "^7.10.4" "@babel/template@^7.4.0", "@babel/template@^7.8.3", "@babel/template@^7.8.6": version "7.8.6" @@ -1274,32 +1213,17 @@ globals "^11.1.0" lodash "^4.17.13" -"@babel/traverse@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.1.tgz#bbcef3031e4152a6c0b50147f4958df54ca0dd27" - integrity sha512-C/cTuXeKt85K+p08jN6vMDz8vSV0vZcI0wmQ36o6mjbuo++kPMdpOYw23W2XH04dbRt9/nMEfA4W3eR21CD+TQ== - dependencies: - "@babel/code-frame" "^7.10.1" - "@babel/generator" "^7.10.1" - "@babel/helper-function-name" "^7.10.1" - "@babel/helper-split-export-declaration" "^7.10.1" - "@babel/parser" "^7.10.1" - "@babel/types" "^7.10.1" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.13" - -"@babel/traverse@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.3.tgz#0b01731794aa7b77b214bcd96661f18281155d7e" - integrity sha512-qO6623eBFhuPm0TmmrUFMT1FulCmsSeJuVGhiLodk2raUDFhhTECLd9E9jC4LBIWziqt4wgF6KuXE4d+Jz9yug== - dependencies: - "@babel/code-frame" "^7.10.3" - "@babel/generator" "^7.10.3" - "@babel/helper-function-name" "^7.10.3" - "@babel/helper-split-export-declaration" "^7.10.1" - "@babel/parser" "^7.10.3" - "@babel/types" "^7.10.3" +"@babel/traverse@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.4.tgz#e642e5395a3b09cc95c8e74a27432b484b697818" + integrity sha512-aSy7p5THgSYm4YyxNGz6jZpXf+Ok40QF3aA2LyIONkDHpAcJzDUqlCKXv6peqYUs2gmic849C/t2HKw2a2K20Q== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.10.4" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" + "@babel/parser" "^7.10.4" + "@babel/types" "^7.10.4" debug "^4.1.0" globals "^11.1.0" lodash "^4.17.13" @@ -1313,21 +1237,12 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" -"@babel/types@^7.10.1", "@babel/types@^7.10.2": - version "7.10.2" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.2.tgz#30283be31cad0dbf6fb00bd40641ca0ea675172d" - integrity sha512-AD3AwWBSz0AWF0AkCN9VPiWrvldXq+/e3cHa4J89vo4ymjz1XwrBFFVZmkJTsQIPNk+ZVomPSXUJqq8yyjZsng== +"@babel/types@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.4.tgz#369517188352e18219981efd156bfdb199fff1ee" + integrity sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg== dependencies: - "@babel/helper-validator-identifier" "^7.10.1" - lodash "^4.17.13" - to-fast-properties "^2.0.0" - -"@babel/types@^7.10.3": - version "7.10.3" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.3.tgz#6535e3b79fea86a6b09e012ea8528f935099de8e" - integrity sha512-nZxaJhBXBQ8HVoIcGsf9qWep3Oh3jCENK54V4mRF7qaJabVsAYdbTtmSD8WmAp1R6ytPiu5apMwSXyxB1WlaBA== - dependencies: - "@babel/helper-validator-identifier" "^7.10.3" + "@babel/helper-validator-identifier" "^7.10.4" lodash "^4.17.13" to-fast-properties "^2.0.0" @@ -1686,56 +1601,56 @@ prop-types "^15.6.1" react-lifecycles-compat "^3.0.4" -"@sentry/browser@^5.18.1": - version "5.18.1" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.18.1.tgz#6a2ebe8f4ba88b2e98ccc91442e1dcb37b2df988" - integrity sha512-U1w0d5kRMsfzMYwWn4+awDKfBEI5lxhHa0bMChSpj5z/dWiz/e0mikZ9gCoF+ZNqkXJ92l/3r9gRz+SIsn5ZoA== +"@sentry/browser@^5.19.1": + version "5.19.1" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.19.1.tgz#b22f36fc71f36719ad352a54e6b31722622128c0" + integrity sha512-Aon5Nc2n8sIXKg6Xbr4RM3/Xs7vFpXksL56z3yIuGrmpCM8ToQ25/tQv8h+anYi72x5bn1npzaXB/NwU1Qwfhg== dependencies: - "@sentry/core" "5.18.1" - "@sentry/types" "5.18.1" - "@sentry/utils" "5.18.1" + "@sentry/core" "5.19.1" + "@sentry/types" "5.19.1" + "@sentry/utils" "5.19.1" tslib "^1.9.3" -"@sentry/core@5.18.1": - version "5.18.1" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.18.1.tgz#c2aa7ef9054e372d006d32234969711234d2bb02" - integrity sha512-nC2aK6gwVIBVysmtdFHxYJyuChIHtkv7TnvmwgA5788L/HWo7E3R+Rd8Tf2npvp/aP+kmNITNbc5CIIqwGPaqQ== +"@sentry/core@5.19.1": + version "5.19.1" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.19.1.tgz#f5ff7feb1118035f75f1d0bc2a76e2b040d2aa8e" + integrity sha512-BGGxjeT95Og/hloBhQXAVcndVXPmIU6drtF3oKRT12cBpiG965xEDEUwiJVvyb5MAvojdVEZBK2LURUFY/d7Zw== dependencies: - "@sentry/hub" "5.18.1" - "@sentry/minimal" "5.18.1" - "@sentry/types" "5.18.1" - "@sentry/utils" "5.18.1" + "@sentry/hub" "5.19.1" + "@sentry/minimal" "5.19.1" + "@sentry/types" "5.19.1" + "@sentry/utils" "5.19.1" tslib "^1.9.3" -"@sentry/hub@5.18.1": - version "5.18.1" - resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.18.1.tgz#4c2f642e29a320885692b902fba89e57a9906e64" - integrity sha512-dFnaj1fQRT74EhoF8MXJ23K3svt11zEF6CS3cdMrkSzfRbAHjyza7KT2AJHUeF6gtH2BZzqsSw+FnfAke0HGIg== +"@sentry/hub@5.19.1": + version "5.19.1" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.19.1.tgz#f3bc8500680974ce43c1eedcd8e90696cc18b306" + integrity sha512-XjfbNGWVeDsP38alm5Cm08YPIw5Hu6HbPkw7a3y1piViTrg4HdtsE+ZJqq0YcURo2RTpg6Ks6coCS/zJxIPygQ== dependencies: - "@sentry/types" "5.18.1" - "@sentry/utils" "5.18.1" + "@sentry/types" "5.19.1" + "@sentry/utils" "5.19.1" tslib "^1.9.3" -"@sentry/minimal@5.18.1": - version "5.18.1" - resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.18.1.tgz#8de01e87c5f5c6e74b707849202150cd4b316ee0" - integrity sha512-St2bjcZ5FFiH+bYkWoEPlEb0w38YSvftnjJTvZyk05SCdsF7HkGfoBeFmztwBf1VLQPYt3ojny14L6KDAvOTpw== +"@sentry/minimal@5.19.1": + version "5.19.1" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.19.1.tgz#04043d93a7dc90cbed1a31d80f6bf59688ea3100" + integrity sha512-pgNfsaCroEsC8gv+NqmPTIkj4wyK6ZgYLV12IT4k2oJLkGyg45TSAKabyB7oEP5jsj8sRzm8tDomu8M4HpaCHg== dependencies: - "@sentry/hub" "5.18.1" - "@sentry/types" "5.18.1" + "@sentry/hub" "5.19.1" + "@sentry/types" "5.19.1" tslib "^1.9.3" -"@sentry/types@5.18.1": - version "5.18.1" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.18.1.tgz#9d72254262f28e966b06371c5b3833de8f0253b8" - integrity sha512-y5YTkRFC4Y7r4GHrvin6aZLBpQIGdMZRq78f/s7IIEZrmWYbVKsK4dyJht6pOsUdEaxeYpsu3okIA0bqmthSJA== +"@sentry/types@5.19.1": + version "5.19.1" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.19.1.tgz#8762f668d3fc2416fbde31d15d13009544caeb54" + integrity sha512-M5MhTLnjqYFwxMwcFPBpBgYQqI9hCvtVuj/A+NvcBHpe7VWOXdn/Sys+zD6C76DWGFYQdw3OWCsZimP24dL8mA== -"@sentry/utils@5.18.1": - version "5.18.1" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.18.1.tgz#c9880056793ae77d651db0dae76a08a8a0b31eac" - integrity sha512-P4lt6NauCBWASaP6R5kfOmc24imbD32G5FeWqK7vHftIphOJ0X7OZfh93DJPs3e5RIvW3YCywUsa7MpTH5/ClA== +"@sentry/utils@5.19.1": + version "5.19.1" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.19.1.tgz#e1134db40e4bb9732251e515721cec7ee94d4d9c" + integrity sha512-neUiNBnZSHjWTZWy2QV02EHTx1C2L3DBPzRXlh0ca5xrI7LMBLmhkHlhebn1E5ky3PW1teqZTgmh0jZoL99TEA== dependencies: - "@sentry/types" "5.18.1" + "@sentry/types" "5.19.1" tslib "^1.9.3" "@storybook/addon-actions@^5.3.19": @@ -2005,7 +1920,7 @@ dependencies: lodash "^4.17.15" -"@storybook/node-logger@*", "@storybook/node-logger@5.3.19": +"@storybook/node-logger@5.3.19": version "5.3.19" resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-5.3.19.tgz#c414e4d3781aeb06298715220012f552a36dff29" integrity sha512-hKshig/u5Nj9fWy0OsyU04yqCxr0A9pydOHIassr4fpLAaePIN2YvqCqE2V+TxQHjZUnowSSIhbXrGt0DI5q2A== @@ -2017,17 +1932,16 @@ pretty-hrtime "^1.0.3" regenerator-runtime "^0.13.3" -"@storybook/preset-create-react-app@^3.1.2": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@storybook/preset-create-react-app/-/preset-create-react-app-3.1.2.tgz#7413186cf2843fc2a49cd65e59c4380a72ad93ce" - integrity sha512-MjOus6mH/F/TikTPR3lWiuaR6hhhray2Yr2jV++Qg1/fS3yyADTyNZQZyc+TOc+SdKNTZ706H8+zn7RcjD9vGg== +"@storybook/preset-create-react-app@^3.1.4": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@storybook/preset-create-react-app/-/preset-create-react-app-3.1.4.tgz#64bb674f69fe860ef1a4909e686775adf6c05fdd" + integrity sha512-VwzGCvv+HnEDXxSwF6ITRIZ4EaMhiMu1Mxrwm+nb49XTT2VME8VTzmbDjrdpZXPXUJrwLYmvqzaBT/qGZoMlgA== dependencies: - "@storybook/node-logger" "*" "@types/babel__core" "^7.1.7" "@types/webpack" "^4.41.13" babel-plugin-react-docgen "^4.1.0" pnp-webpack-plugin "^1.6.4" - react-docgen-typescript-plugin "^0.4.0" + react-docgen-typescript-plugin "^0.5.0" semver "^7.3.2" "@storybook/react@^5.3.19": @@ -2353,10 +2267,10 @@ "@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-report" "*" -"@types/jest@^26.0.3": - version "26.0.3" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.3.tgz#79534e0e94857171c0edc596db0ebe7cb7863251" - integrity sha512-v89ga1clpVL/Y1+YI0eIu1VMW+KU7Xl8PhylVtDKVWaSUHBHYPLXMQGBdrpHewaKoTvlXkksbYqPgz8b4cmRZg== +"@types/jest@^26.0.4": + version "26.0.4" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.4.tgz#d2e513e85aca16992816f192582b5e67b0b15efb" + integrity sha512-4fQNItvelbNA9+sFgU+fhJo8ZFF+AS4Egk3GWwCW2jFtViukXbnztccafAdLhzE/0EiCogljtQQXP8aQ9J7sFg== dependencies: jest-diff "^25.2.1" pretty-format "^25.2.1" @@ -2399,10 +2313,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.0.tgz#30d2d09f623fe32cde9cb582c7a6eda2788ce4a8" integrity sha512-WE4IOAC6r/yBZss1oQGM5zs2D7RuKR6Q+w+X2SouPofnWn+LbCqClRyhO3ZE7Ix8nmFgo/oVuuE01cJT2XB13A== -"@types/node@^14.0.14": - version "14.0.14" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.14.tgz#24a0b5959f16ac141aeb0c5b3cd7a15b7c64cbce" - integrity sha512-syUgf67ZQpaJj01/tRTknkMNoBBLWJOBODF0Zm4NrXmiSuxjymFrxnTu1QVYRubhVkRcZLYZG8STTwJRdVm/WQ== +"@types/node@^14.0.22": + version "14.0.22" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.22.tgz#23ea4d88189cec7d58f9e6b66f786b215eb61bdc" + integrity sha512-emeGcJvdiZ4Z3ohbmw93E/64jRzUHAItSHt8nF7M4TGgQTiWqFVGB8KNpLGFmUHmHLvjvBgFwVlqNcq+VuGv9g== "@types/npmlog@^4.1.2": version "4.1.2" @@ -2488,10 +2402,10 @@ "@types/prop-types" "*" csstype "^2.2.0" -"@types/react@^16.9.41": - version "16.9.41" - resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.41.tgz#925137ee4d2ff406a0ecf29e8e9237390844002e" - integrity sha512-6cFei7F7L4wwuM+IND/Q2cV1koQUvJ8iSV+Gwn0c3kvABZ691g7sp3hfEQHOUBJtccl1gPi+EyNjMIl9nGA0ug== +"@types/react@^16.9.43": + version "16.9.43" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.43.tgz#c287f23f6189666ee3bebc2eb8d0f84bcb6cdb6b" + integrity sha512-PxshAFcnJqIWYpJbLPriClH53Z2WlJcVZE+NP2etUtWQs2s7yIMj3/LDKZT/5CHJ/F62iyjVCDu2H3jHEXIxSg== dependencies: "@types/prop-types" "*" csstype "^2.2.0" @@ -11287,10 +11201,10 @@ react-docgen-typescript-loader@^3.7.2: loader-utils "^1.2.3" react-docgen-typescript "^1.15.0" -react-docgen-typescript-plugin@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/react-docgen-typescript-plugin/-/react-docgen-typescript-plugin-0.4.1.tgz#58666c4b4f213ed03d49a92e5d9c4460afb53bec" - integrity sha512-+uoMqPWqPnC4+3xIz3e+AIJeJ07HZ1Y4jqziQ+xaRoxp9/RRR6XZK1hM5BRZmaMO2gN65I/jaFcxgaa/uzAtfQ== +react-docgen-typescript-plugin@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/react-docgen-typescript-plugin/-/react-docgen-typescript-plugin-0.5.1.tgz#383a4e92e6da07844aebb0927af7766f827b50bc" + integrity sha512-zBxrg3+N0UgcT3NGnrUEhAjmr3DMQq8XsKZweWpRfDAW9BnvSOoVVbKUvdq0elTokkHABIpk6Q626kwzYr4J3Q== dependencies: debug "^4.1.1" endent "^2.0.1" @@ -13375,10 +13289,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@^3.9.5: - version "3.9.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.5.tgz#586f0dba300cde8be52dd1ac4f7e1009c1b13f36" - integrity sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ== +typescript@^3.9.6: + version "3.9.6" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.6.tgz#8f3e0198a34c3ae17091b35571d3afd31999365a" + integrity sha512-Pspx3oKAPJtjNwE92YS05HQoY7z2SFyOpHo9MqJor3BXAGNaPUs83CuVp9VISFkSjyRfiTpmKuAYGJB7S7hOxw== uc.micro@^1.0.1, uc.micro@^1.0.5: version "1.0.6" @@ -14143,10 +14057,10 @@ xregexp@^4.3.0: dependencies: "@babel/runtime-corejs3" "^7.8.3" -xstate@^4.10.0: - version "4.10.0" - resolved "https://registry.yarnpkg.com/xstate/-/xstate-4.10.0.tgz#f87e4ef593fe40300b8eec50a5d9f0763aa4f622" - integrity sha512-nncQ9gW+xgk5iUEvpBOXhbzSCS0uwzzT4bOAXxo6oUoALgbxzqEyMmaMYwuvOHrabDTdMJYnF+xe2XD8RRgWmA== +xstate@^4.11.0: + version "4.11.0" + resolved "https://registry.yarnpkg.com/xstate/-/xstate-4.11.0.tgz#dc0bd31079fe22918c2c27c118d6310bef3dcd9e" + integrity sha512-v+S3jF2YrM2tFOit8o7+4N3FuFd9IIGcIKHyfHeeNjMlmNmwuiv/IbY9uw7ECifx7H/A9aGLcxPSr0jdjTGDww== xtend@^4.0.0, xtend@~4.0.1: version "4.0.2" diff --git a/yarn.lock b/yarn.lock index d82f6fc9..6fe7ddab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -465,83 +465,83 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" -"@sentry/apm@5.18.1": - version "5.18.1" - resolved "https://registry.yarnpkg.com/@sentry/apm/-/apm-5.18.1.tgz#2736ea6cc30ffe093850a2c9ef3b7801a2873a74" - integrity sha512-UcfEgECz7/X9l/3OoUwVCIpSb0RqyUAd/yRCRGF5Lh7kaqaYi1HbatkYUTDEnhOhaEXYtXUvRXPmRD1zMukqsw== - dependencies: - "@sentry/browser" "5.18.1" - "@sentry/hub" "5.18.1" - "@sentry/minimal" "5.18.1" - "@sentry/types" "5.18.1" - "@sentry/utils" "5.18.1" +"@sentry/apm@5.19.1": + version "5.19.1" + resolved "https://registry.yarnpkg.com/@sentry/apm/-/apm-5.19.1.tgz#cdd1d68075b2c904473d32b8e933ad292c2e3628" + integrity sha512-ueW0ulXBIbbVpM6YwUtZKtxvYxoMEYywNbN7hWjECRWBjKSCuIl6sE92uUgv7UvpmBL5f2hE+NufCSvp/RVZjg== + dependencies: + "@sentry/browser" "5.19.1" + "@sentry/hub" "5.19.1" + "@sentry/minimal" "5.19.1" + "@sentry/types" "5.19.1" + "@sentry/utils" "5.19.1" tslib "^1.9.3" -"@sentry/browser@5.18.1": - version "5.18.1" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.18.1.tgz#6a2ebe8f4ba88b2e98ccc91442e1dcb37b2df988" - integrity sha512-U1w0d5kRMsfzMYwWn4+awDKfBEI5lxhHa0bMChSpj5z/dWiz/e0mikZ9gCoF+ZNqkXJ92l/3r9gRz+SIsn5ZoA== +"@sentry/browser@5.19.1": + version "5.19.1" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.19.1.tgz#b22f36fc71f36719ad352a54e6b31722622128c0" + integrity sha512-Aon5Nc2n8sIXKg6Xbr4RM3/Xs7vFpXksL56z3yIuGrmpCM8ToQ25/tQv8h+anYi72x5bn1npzaXB/NwU1Qwfhg== dependencies: - "@sentry/core" "5.18.1" - "@sentry/types" "5.18.1" - "@sentry/utils" "5.18.1" + "@sentry/core" "5.19.1" + "@sentry/types" "5.19.1" + "@sentry/utils" "5.19.1" tslib "^1.9.3" -"@sentry/core@5.18.1": - version "5.18.1" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.18.1.tgz#c2aa7ef9054e372d006d32234969711234d2bb02" - integrity sha512-nC2aK6gwVIBVysmtdFHxYJyuChIHtkv7TnvmwgA5788L/HWo7E3R+Rd8Tf2npvp/aP+kmNITNbc5CIIqwGPaqQ== +"@sentry/core@5.19.1": + version "5.19.1" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.19.1.tgz#f5ff7feb1118035f75f1d0bc2a76e2b040d2aa8e" + integrity sha512-BGGxjeT95Og/hloBhQXAVcndVXPmIU6drtF3oKRT12cBpiG965xEDEUwiJVvyb5MAvojdVEZBK2LURUFY/d7Zw== dependencies: - "@sentry/hub" "5.18.1" - "@sentry/minimal" "5.18.1" - "@sentry/types" "5.18.1" - "@sentry/utils" "5.18.1" + "@sentry/hub" "5.19.1" + "@sentry/minimal" "5.19.1" + "@sentry/types" "5.19.1" + "@sentry/utils" "5.19.1" tslib "^1.9.3" -"@sentry/hub@5.18.1": - version "5.18.1" - resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.18.1.tgz#4c2f642e29a320885692b902fba89e57a9906e64" - integrity sha512-dFnaj1fQRT74EhoF8MXJ23K3svt11zEF6CS3cdMrkSzfRbAHjyza7KT2AJHUeF6gtH2BZzqsSw+FnfAke0HGIg== +"@sentry/hub@5.19.1": + version "5.19.1" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.19.1.tgz#f3bc8500680974ce43c1eedcd8e90696cc18b306" + integrity sha512-XjfbNGWVeDsP38alm5Cm08YPIw5Hu6HbPkw7a3y1piViTrg4HdtsE+ZJqq0YcURo2RTpg6Ks6coCS/zJxIPygQ== dependencies: - "@sentry/types" "5.18.1" - "@sentry/utils" "5.18.1" + "@sentry/types" "5.19.1" + "@sentry/utils" "5.19.1" tslib "^1.9.3" -"@sentry/minimal@5.18.1": - version "5.18.1" - resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.18.1.tgz#8de01e87c5f5c6e74b707849202150cd4b316ee0" - integrity sha512-St2bjcZ5FFiH+bYkWoEPlEb0w38YSvftnjJTvZyk05SCdsF7HkGfoBeFmztwBf1VLQPYt3ojny14L6KDAvOTpw== +"@sentry/minimal@5.19.1": + version "5.19.1" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.19.1.tgz#04043d93a7dc90cbed1a31d80f6bf59688ea3100" + integrity sha512-pgNfsaCroEsC8gv+NqmPTIkj4wyK6ZgYLV12IT4k2oJLkGyg45TSAKabyB7oEP5jsj8sRzm8tDomu8M4HpaCHg== dependencies: - "@sentry/hub" "5.18.1" - "@sentry/types" "5.18.1" + "@sentry/hub" "5.19.1" + "@sentry/types" "5.19.1" tslib "^1.9.3" -"@sentry/node@^5.18.1": - version "5.18.1" - resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.18.1.tgz#9c126735e7a27a9353ff9ecc71059e8781657f8c" - integrity sha512-faIKb/1i0MYKkWL6crtnIuw1WTwvnQZFaOX4zjZeqZ+z7Q72YfnLWMTaJMe8Q38P/obWf75YRffIJrezkT9lXw== +"@sentry/node@^5.19.1": + version "5.19.1" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.19.1.tgz#6b0f0972c118e99b72c46b516288661e39d3161e" + integrity sha512-BW5jxC1rssGIotmO78k8AZwtv8gHNWsQ+Jh6VZjOG0lMSD8wbBlEvF/97K2WwzaFLPj5UuEhRmQgLtC4NCrXbw== dependencies: - "@sentry/apm" "5.18.1" - "@sentry/core" "5.18.1" - "@sentry/hub" "5.18.1" - "@sentry/types" "5.18.1" - "@sentry/utils" "5.18.1" + "@sentry/apm" "5.19.1" + "@sentry/core" "5.19.1" + "@sentry/hub" "5.19.1" + "@sentry/types" "5.19.1" + "@sentry/utils" "5.19.1" cookie "^0.3.1" https-proxy-agent "^4.0.0" lru_map "^0.3.3" tslib "^1.9.3" -"@sentry/types@5.18.1": - version "5.18.1" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.18.1.tgz#9d72254262f28e966b06371c5b3833de8f0253b8" - integrity sha512-y5YTkRFC4Y7r4GHrvin6aZLBpQIGdMZRq78f/s7IIEZrmWYbVKsK4dyJht6pOsUdEaxeYpsu3okIA0bqmthSJA== +"@sentry/types@5.19.1": + version "5.19.1" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.19.1.tgz#8762f668d3fc2416fbde31d15d13009544caeb54" + integrity sha512-M5MhTLnjqYFwxMwcFPBpBgYQqI9hCvtVuj/A+NvcBHpe7VWOXdn/Sys+zD6C76DWGFYQdw3OWCsZimP24dL8mA== -"@sentry/utils@5.18.1": - version "5.18.1" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.18.1.tgz#c9880056793ae77d651db0dae76a08a8a0b31eac" - integrity sha512-P4lt6NauCBWASaP6R5kfOmc24imbD32G5FeWqK7vHftIphOJ0X7OZfh93DJPs3e5RIvW3YCywUsa7MpTH5/ClA== +"@sentry/utils@5.19.1": + version "5.19.1" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.19.1.tgz#e1134db40e4bb9732251e515721cec7ee94d4d9c" + integrity sha512-neUiNBnZSHjWTZWy2QV02EHTx1C2L3DBPzRXlh0ca5xrI7LMBLmhkHlhebn1E5ky3PW1teqZTgmh0jZoL99TEA== dependencies: - "@sentry/types" "5.18.1" + "@sentry/types" "5.19.1" tslib "^1.9.3" "@sinonjs/commons@^1.7.0": @@ -649,10 +649,10 @@ "@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-report" "*" -"@types/jest@^26.0.3": - version "26.0.3" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.3.tgz#79534e0e94857171c0edc596db0ebe7cb7863251" - integrity sha512-v89ga1clpVL/Y1+YI0eIu1VMW+KU7Xl8PhylVtDKVWaSUHBHYPLXMQGBdrpHewaKoTvlXkksbYqPgz8b4cmRZg== +"@types/jest@^26.0.4": + version "26.0.4" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.4.tgz#d2e513e85aca16992816f192582b5e67b0b15efb" + integrity sha512-4fQNItvelbNA9+sFgU+fhJo8ZFF+AS4Egk3GWwCW2jFtViukXbnztccafAdLhzE/0EiCogljtQQXP8aQ9J7sFg== dependencies: jest-diff "^25.2.1" pretty-format "^25.2.1" @@ -684,10 +684,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.0.tgz#30d2d09f623fe32cde9cb582c7a6eda2788ce4a8" integrity sha512-WE4IOAC6r/yBZss1oQGM5zs2D7RuKR6Q+w+X2SouPofnWn+LbCqClRyhO3ZE7Ix8nmFgo/oVuuE01cJT2XB13A== -"@types/node@^14.0.14": - version "14.0.14" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.14.tgz#24a0b5959f16ac141aeb0c5b3cd7a15b7c64cbce" - integrity sha512-syUgf67ZQpaJj01/tRTknkMNoBBLWJOBODF0Zm4NrXmiSuxjymFrxnTu1QVYRubhVkRcZLYZG8STTwJRdVm/WQ== +"@types/node@^14.0.22": + version "14.0.22" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.22.tgz#23ea4d88189cec7d58f9e6b66f786b215eb61bdc" + integrity sha512-emeGcJvdiZ4Z3ohbmw93E/64jRzUHAItSHt8nF7M4TGgQTiWqFVGB8KNpLGFmUHmHLvjvBgFwVlqNcq+VuGv9g== "@types/normalize-package-data@^2.4.0": version "2.4.0" @@ -733,51 +733,66 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.4.0.tgz#8378062e6be8a1d049259bdbcf27ce5dfbeee62b" - integrity sha512-wfkpiqaEVhZIuQRmudDszc01jC/YR7gMSxa6ulhggAe/Hs0KVIuo9wzvFiDbG3JD5pRFQoqnf4m7REDsUvBnMQ== +"@typescript-eslint/eslint-plugin@^3.6.0": + version "3.6.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.6.0.tgz#ba2b6cae478b8fca3f2e58ff1313e4198eea2d8a" + integrity sha512-ubHlHVt1lsPQB/CZdEov9XuOFhNG9YRC//kuiS1cMQI6Bs1SsqKrEmZnpgRwthGR09/kEDtr9MywlqXyyYd8GA== dependencies: - "@typescript-eslint/experimental-utils" "3.4.0" + "@typescript-eslint/experimental-utils" "3.6.0" debug "^4.1.1" functional-red-black-tree "^1.0.1" regexpp "^3.0.0" semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.4.0.tgz#8a44dfc6fb7f1d071937b390fe27608ebda122b8" - integrity sha512-rHPOjL43lOH1Opte4+dhC0a/+ks+8gOBwxXnyrZ/K4OTAChpSjP76fbI8Cglj7V5GouwVAGaK+xVwzqTyE/TPw== +"@typescript-eslint/experimental-utils@3.6.0": + version "3.6.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.6.0.tgz#0138152d66e3e53a6340f606793fb257bf2d76a1" + integrity sha512-4Vdf2hvYMUnTdkCNZu+yYlFtL2v+N2R7JOynIOkFbPjf9o9wQvRwRkzUdWlFd2YiiUwJLbuuLnl5civNg5ykOQ== dependencies: "@types/json-schema" "^7.0.3" - "@typescript-eslint/typescript-estree" "3.4.0" + "@typescript-eslint/types" "3.6.0" + "@typescript-eslint/typescript-estree" "3.6.0" eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@^3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.4.0.tgz#fe52b68c5cb3bba3f5d875bd17adb70420d49d8d" - integrity sha512-ZUGI/de44L5x87uX5zM14UYcbn79HSXUR+kzcqU42gH0AgpdB/TjuJy3m4ezI7Q/jk3wTQd755mxSDLhQP79KA== +"@typescript-eslint/parser@^3.6.0": + version "3.6.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.6.0.tgz#79b5232e1a2d06f1fc745942b690cd87aca7b60e" + integrity sha512-taghDxuLhbDAD1U5Fk8vF+MnR0yiFE9Z3v2/bYScFb0N1I9SK8eKHkdJl1DAD48OGFDMFTeOTX0z7g0W6SYUXw== dependencies: "@types/eslint-visitor-keys" "^1.0.0" - "@typescript-eslint/experimental-utils" "3.4.0" - "@typescript-eslint/typescript-estree" "3.4.0" + "@typescript-eslint/experimental-utils" "3.6.0" + "@typescript-eslint/types" "3.6.0" + "@typescript-eslint/typescript-estree" "3.6.0" eslint-visitor-keys "^1.1.0" -"@typescript-eslint/typescript-estree@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.4.0.tgz#6a787eb70b48969e4cd1ea67b057083f96dfee29" - integrity sha512-zKwLiybtt4uJb4mkG5q2t6+W7BuYx2IISiDNV+IY68VfoGwErDx/RfVI7SWL4gnZ2t1A1ytQQwZ+YOJbHHJ2rw== +"@typescript-eslint/types@3.6.0": + version "3.6.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.6.0.tgz#4bd6eee55d2f9d35a4b36c4804be1880bf68f7bc" + integrity sha512-JwVj74ohUSt0ZPG+LZ7hb95fW8DFOqBuR6gE7qzq55KDI3BepqsCtHfBIoa0+Xi1AI7fq5nCu2VQL8z4eYftqg== + +"@typescript-eslint/typescript-estree@3.6.0": + version "3.6.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.6.0.tgz#9b4cab43f1192b64ff51530815b8919f166ce177" + integrity sha512-G57NDSABHjvob7zVV09ehWyD1K6/YUKjz5+AufObFyjNO4DVmKejj47MHjVHHlZZKgmpJD2yyH9lfCXHrPITFg== dependencies: + "@typescript-eslint/types" "3.6.0" + "@typescript-eslint/visitor-keys" "3.6.0" debug "^4.1.1" - eslint-visitor-keys "^1.1.0" glob "^7.1.6" is-glob "^4.0.1" lodash "^4.17.15" semver "^7.3.2" tsutils "^3.17.1" +"@typescript-eslint/visitor-keys@3.6.0": + version "3.6.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.6.0.tgz#44185eb0cc47651034faa95c5e2e8b314ecebb26" + integrity sha512-p1izllL2Ubwunite0ITjubuMQRBGgjdVYwyG7lXPX8GbrA6qF0uwSRz9MnXZaHMxID4948gX0Ez8v9tUDi/KfQ== + dependencies: + eslint-visitor-keys "^1.1.0" + abab@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a" @@ -1621,10 +1636,10 @@ eslint-visitor-keys@^1.2.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.2.0.tgz#74415ac884874495f78ec2a97349525344c981fa" integrity sha512-WFb4ihckKil6hu3Dp798xdzSfddwKKU3+nGniKF6HfeW6OLd2OUDEPP7TcHtB5+QXOKg2s6B2DaMPE1Nn/kxKQ== -eslint@^7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.3.1.tgz#76392bd7e44468d046149ba128d1566c59acbe19" - integrity sha512-cQC/xj9bhWUcyi/RuMbRtC3I0eW8MH0jhRELSvpKYkWep3C6YZ2OkvcvJVUeO6gcunABmzptbXBuDoXsjHmfTA== +eslint@^7.4.0: + version "7.4.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.4.0.tgz#4e35a2697e6c1972f9d6ef2b690ad319f80f206f" + integrity sha512-gU+lxhlPHu45H3JkEGgYhWhkR9wLHHEXC9FbWFnTlEkbKyZKWgWRLgf61E8zWmBuI6g5xKBph9ltg3NtZMVF8g== dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.10.0" @@ -2903,6 +2918,38 @@ jsdom@^16.2.2: ws "^7.2.3" xml-name-validator "^3.0.0" +jsdom@^16.3.0: + version "16.3.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.3.0.tgz#75690b7dac36c67be49c336dcd7219bbbed0810c" + integrity sha512-zggeX5UuEknpdZzv15+MS1dPYG0J/TftiiNunOeNxSl3qr8Z6cIlQpN0IdJa44z9aFxZRIVqRncvEhQ7X5DtZg== + dependencies: + abab "^2.0.3" + acorn "^7.1.1" + acorn-globals "^6.0.0" + cssom "^0.4.4" + cssstyle "^2.2.0" + data-urls "^2.0.0" + decimal.js "^10.2.0" + domexception "^2.0.1" + escodegen "^1.14.1" + html-encoding-sniffer "^2.0.1" + is-potential-custom-element-name "^1.0.0" + nwsapi "^2.2.0" + parse5 "5.1.1" + request "^2.88.2" + request-promise-native "^1.0.8" + saxes "^5.0.0" + symbol-tree "^3.2.4" + tough-cookie "^3.0.1" + w3c-hr-time "^1.0.2" + w3c-xmlserializer "^2.0.0" + webidl-conversions "^6.1.0" + whatwg-encoding "^1.0.5" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.0.0" + ws "^7.2.3" + xml-name-validator "^3.0.0" + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -4285,10 +4332,10 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typescript@^3.9.5: - version "3.9.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.5.tgz#586f0dba300cde8be52dd1ac4f7e1009c1b13f36" - integrity sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ== +typescript@^3.9.6: + version "3.9.6" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.6.tgz#8f3e0198a34c3ae17091b35571d3afd31999365a" + integrity sha512-Pspx3oKAPJtjNwE92YS05HQoY7z2SFyOpHo9MqJor3BXAGNaPUs83CuVp9VISFkSjyRfiTpmKuAYGJB7S7hOxw== union-value@^1.0.0: version "1.0.1" @@ -4422,7 +4469,7 @@ webidl-conversions@^5.0.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== -webidl-conversions@^6.0.0: +webidl-conversions@^6.0.0, webidl-conversions@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== From 261d4a320f372f2bfc3a5238262e4ee236f40795 Mon Sep 17 00:00:00 2001 From: shmck Date: Sat, 11 Jul 2020 21:00:52 -0700 Subject: [PATCH 040/405] display all review level/steps Signed-off-by: shmck --- web-app/src/containers/Tutorial/components/Step.tsx | 3 ++- web-app/src/containers/Tutorial/components/Steps.tsx | 9 ++++++++- .../containers/Tutorial/components/TestStatusIcon.tsx | 6 +++++- web-app/src/containers/Tutorial/containers/Review.tsx | 2 +- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/web-app/src/containers/Tutorial/components/Step.tsx b/web-app/src/containers/Tutorial/components/Step.tsx index 435da5be..ed5d50bf 100644 --- a/web-app/src/containers/Tutorial/components/Step.tsx +++ b/web-app/src/containers/Tutorial/components/Step.tsx @@ -8,6 +8,7 @@ interface Props { content: string status: T.ProgressStatus subtasks: { name: string; pass: boolean }[] | null + displayAll: boolean } const styles = { @@ -40,7 +41,7 @@ const styles = { } const Step = (props: Props) => { - const showStep = props.status !== 'INCOMPLETE' + const showStep = props.displayAll || props.status !== 'INCOMPLETE' if (!showStep) { return null } diff --git a/web-app/src/containers/Tutorial/components/Steps.tsx b/web-app/src/containers/Tutorial/components/Steps.tsx index 2ee26bcb..a8cd3f75 100644 --- a/web-app/src/containers/Tutorial/components/Steps.tsx +++ b/web-app/src/containers/Tutorial/components/Steps.tsx @@ -6,6 +6,7 @@ import Hints from './Hints' interface Props { steps: TT.Step[] + displayAll: boolean } const styles = { @@ -27,7 +28,13 @@ const Steps = (props: Props) => { } return (
- +
) diff --git a/web-app/src/containers/Tutorial/components/TestStatusIcon.tsx b/web-app/src/containers/Tutorial/components/TestStatusIcon.tsx index a6d6bcb1..c62be991 100644 --- a/web-app/src/containers/Tutorial/components/TestStatusIcon.tsx +++ b/web-app/src/containers/Tutorial/components/TestStatusIcon.tsx @@ -19,12 +19,16 @@ const styles = { icon: 'warning', color: '#ff9300', }, + incomplete: { + icon: 'lock', + color: 'lightgrey', + }, } const TestStatusIcon = (props: Props) => { // @ts-ignore const style: { icon: string; color: string } = styles[props.status.toLowerCase()] - return + return } export default TestStatusIcon diff --git a/web-app/src/containers/Tutorial/containers/Review.tsx b/web-app/src/containers/Tutorial/containers/Review.tsx index e29a41be..95b5d910 100644 --- a/web-app/src/containers/Tutorial/containers/Review.tsx +++ b/web-app/src/containers/Tutorial/containers/Review.tsx @@ -35,7 +35,7 @@ const ReviewPage = (props: Props) => {
- +
{/* divider */} {index < props.levels.length - 1 ?
: null} From daaea858d4c64f357f3654302b4796f3811a80fd Mon Sep 17 00:00:00 2001 From: shmck Date: Sat, 11 Jul 2020 21:02:46 -0700 Subject: [PATCH 041/405] temp remove settings until ready Signed-off-by: shmck --- web-app/src/containers/Tutorial/components/SideMenu.tsx | 4 ++-- web-app/src/containers/Tutorial/index.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/web-app/src/containers/Tutorial/components/SideMenu.tsx b/web-app/src/containers/Tutorial/components/SideMenu.tsx index 82400d49..08e83170 100644 --- a/web-app/src/containers/Tutorial/components/SideMenu.tsx +++ b/web-app/src/containers/Tutorial/components/SideMenu.tsx @@ -65,7 +65,7 @@ const SideMenu = (props: Props) => { Review - + {/* { > Settings - + */} ) diff --git a/web-app/src/containers/Tutorial/index.tsx b/web-app/src/containers/Tutorial/index.tsx index 52617548..473e1bd3 100644 --- a/web-app/src/containers/Tutorial/index.tsx +++ b/web-app/src/containers/Tutorial/index.tsx @@ -122,8 +122,8 @@ const TutorialPage = (props: PageProps) => {
{page === 'level' && } - {page === 'settings' && } {page === 'review' && } + {/* {page === 'settings' && } */}
{/* Process Modal */} From 7bac4181e5a22acf98cd3a4d0f1312559efc18be Mon Sep 17 00:00:00 2001 From: shmck Date: Sat, 11 Jul 2020 22:03:47 -0700 Subject: [PATCH 042/405] cleanup levelUI & stepUI typings Signed-off-by: shmck --- typings/index.d.ts | 22 ++++++ typings/tutorial.d.ts | 1 - .../containers/Tutorial/components/Level.tsx | 5 +- .../containers/Tutorial/components/Step.tsx | 11 +-- .../containers/Tutorial/components/Steps.tsx | 11 ++- .../src/containers/Tutorial/formatLevels.ts | 75 +++++++++++-------- web-app/src/containers/Tutorial/index.tsx | 5 +- web-app/src/containers/Tutorial/style.css | 4 + 8 files changed, 80 insertions(+), 54 deletions(-) create mode 100644 web-app/src/containers/Tutorial/style.css diff --git a/typings/index.d.ts b/typings/index.d.ts index 0414b735..122fb736 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1,6 +1,28 @@ import * as E from './error' import * as TT from './tutorial' +export type LevelUI = { + id: string + title: string + /** A summary of the level */ + summary: string + /** The lesson content of the level, parsed as markdown */ + content: string + /** A set of tasks for users linked to unit tests */ + steps: StepUI[] + status: ProgressStatus +} + +export type StepUI = { + id: string + content: string + status: ProgressStatus + hints?: string[] + subtasks?: SubtaskUI[] +} + +export type SubtaskUI = { name: string; status: ProgressStatus } + export type ProgressStatus = 'ACTIVE' | 'COMPLETE' | 'INCOMPLETE' | 'FAIL' export interface Progress { diff --git a/typings/tutorial.d.ts b/typings/tutorial.d.ts index 92d8ddbf..8dc5d6b3 100644 --- a/typings/tutorial.d.ts +++ b/typings/tutorial.d.ts @@ -32,7 +32,6 @@ export type Step = { solution: Maybe hints?: string[] subtasks?: string[] - status?: ProgressStatus } /** A tutorial for use in VSCode CodeRoad */ diff --git a/web-app/src/containers/Tutorial/components/Level.tsx b/web-app/src/containers/Tutorial/components/Level.tsx index 680d46c2..a7ef0415 100644 --- a/web-app/src/containers/Tutorial/components/Level.tsx +++ b/web-app/src/containers/Tutorial/components/Level.tsx @@ -1,6 +1,5 @@ import * as React from 'react' import * as T from 'typings' -import * as TT from 'typings/tutorial' import { css, jsx } from '@emotion/core' import Content from './Content' import Steps from './Steps' @@ -35,8 +34,8 @@ const styles = { }, } -interface Props { - level: TT.Level +type Props = { + level: T.LevelUI } const Level = ({ level }: Props) => { diff --git a/web-app/src/containers/Tutorial/components/Step.tsx b/web-app/src/containers/Tutorial/components/Step.tsx index ed5d50bf..f4cf01d3 100644 --- a/web-app/src/containers/Tutorial/components/Step.tsx +++ b/web-app/src/containers/Tutorial/components/Step.tsx @@ -7,7 +7,7 @@ import Markdown from '../../../components/Markdown' interface Props { content: string status: T.ProgressStatus - subtasks: { name: string; pass: boolean }[] | null + subtasks?: T.SubtaskUI[] displayAll: boolean } @@ -60,16 +60,9 @@ const Step = (props: Props) => { {props.subtasks ? (