From dc8266759a203677745a4fd990a08bb3efea51f2 Mon Sep 17 00:00:00 2001 From: Apostolof Date: Mon, 2 Nov 2020 22:26:51 +0200 Subject: [PATCH 001/150] Restore eslint configuration --- packages/concordia-app/.eslintrc.js | 46 ++++++++ packages/concordia-app/package.json | 11 +- packages/concordia-contracts/.eslintignore | 1 + packages/concordia-contracts/.eslintrc.js | 50 +++++++++ packages/concordia-contracts/.solhint.json | 3 + packages/concordia-contracts/package.json | 5 + yarn.lock | 116 ++++++++++++++------- 7 files changed, 188 insertions(+), 44 deletions(-) create mode 100644 packages/concordia-app/.eslintrc.js create mode 100644 packages/concordia-contracts/.eslintignore create mode 100644 packages/concordia-contracts/.eslintrc.js create mode 100644 packages/concordia-contracts/.solhint.json diff --git a/packages/concordia-app/.eslintrc.js b/packages/concordia-app/.eslintrc.js new file mode 100644 index 0000000..c2321b9 --- /dev/null +++ b/packages/concordia-app/.eslintrc.js @@ -0,0 +1,46 @@ +module.exports = { + 'env': { + 'browser': true, + 'es6': true, + 'jest': true + }, + 'extends': [ + 'plugin:react/recommended', + 'airbnb' + ], + 'globals': { + 'Atomics': 'readonly', + 'SharedArrayBuffer': 'readonly' + }, + 'parserOptions': { + 'ecmaFeatures': { + 'jsx': true + }, + 'ecmaVersion': 2018, + 'sourceType': 'module' + }, + 'plugins': [ + 'react' + ], + 'rules': { + "indent": ["error", 4], + "react/jsx-indent": ["error", 4], + "react/jsx-indent-props": ["error", 4], + 'react/jsx-filename-extension': 'off', + 'react/jsx-props-no-spreading': 'off', + 'import/extensions': 'off', + 'react/require-default-props': 'off', + 'react/prop-types': 'off', + 'max-len': ['warn', {'code': 120, 'tabWidth': 4}], + 'no-unused-vars': 'warn', + 'no-console': 'warn', + 'no-shadow': 'warn', + }, + 'settings': { + 'import/resolver': { + 'node': { + 'extensions': ['.js', '.jsx'] + } + } + }, +}; diff --git a/packages/concordia-app/package.json b/packages/concordia-app/package.json index 53a2c0b..65c1b25 100644 --- a/packages/concordia-app/package.json +++ b/packages/concordia-app/package.json @@ -8,10 +8,8 @@ "test": "react-scripts test", "eject": "react-scripts eject", "postinstall": "patch-package", - "analyze": "source-map-explorer 'build/static/js/*.js'" - }, - "eslintConfig": { - "extends": "react-app" + "analyze": "source-map-explorer 'build/static/js/*.js'", + "lint": "yarn run eslint . --format table" }, "browserslist": { "production": [ @@ -45,6 +43,11 @@ "web3": "1.3.0" }, "devDependencies": { + "eslint": "6.8.0", + "eslint-config-airbnb": "18.1.0", + "eslint-plugin-import": "2.20.2", + "eslint-plugin-jsx-a11y": "6.2.3", + "eslint-plugin-react": "7.19.0", "patch-package": "~6.2.2", "postinstall-postinstall": "~2.1.0", "source-map-explorer": "~2.5.0" diff --git a/packages/concordia-contracts/.eslintignore b/packages/concordia-contracts/.eslintignore new file mode 100644 index 0000000..a007fea --- /dev/null +++ b/packages/concordia-contracts/.eslintignore @@ -0,0 +1 @@ +build/* diff --git a/packages/concordia-contracts/.eslintrc.js b/packages/concordia-contracts/.eslintrc.js new file mode 100644 index 0000000..8261734 --- /dev/null +++ b/packages/concordia-contracts/.eslintrc.js @@ -0,0 +1,50 @@ +module.exports = { + 'env': { + 'browser': true, + 'es6': true, + 'jest': true + }, + 'extends': [ + 'plugin:react/recommended', + 'airbnb' + ], + 'globals': { + 'Atomics': 'readonly', + 'SharedArrayBuffer': 'readonly', + 'artifacts': 'readonly', + 'require': 'readonly', + 'contract': 'readonly', + 'assert': 'readonly' + }, + 'parserOptions': { + 'ecmaFeatures': { + 'jsx': true + }, + 'ecmaVersion': 2018, + 'sourceType': 'module' + }, + 'plugins': [ + 'react' + ], + 'rules': { + "indent": ["error", 4], + "react/jsx-indent": ["error", 4], + "react/jsx-indent-props": ["error", 4], + 'react/jsx-filename-extension': 'off', + 'react/jsx-props-no-spreading': 'off', + 'import/extensions': 'off', + 'react/require-default-props': 'off', + 'react/prop-types': 'off', + 'max-len': ['warn', {'code': 120, 'tabWidth': 4}], + 'no-unused-vars': 'warn', + 'no-console': 'warn', + 'no-shadow': 'warn', + }, + 'settings': { + 'import/resolver': { + 'node': { + 'extensions': ['.js', '.jsx'] + } + } + }, +}; diff --git a/packages/concordia-contracts/.solhint.json b/packages/concordia-contracts/.solhint.json new file mode 100644 index 0000000..d7c3de9 --- /dev/null +++ b/packages/concordia-contracts/.solhint.json @@ -0,0 +1,3 @@ +{ + "extends": "solhint:default" +} diff --git a/packages/concordia-contracts/package.json b/packages/concordia-contracts/package.json index 373e3b2..8ef2107 100644 --- a/packages/concordia-contracts/package.json +++ b/packages/concordia-contracts/package.json @@ -17,6 +17,11 @@ "truffle": "~5.1.45" }, "devDependencies": { + "eslint": "6.8.0", + "eslint-config-airbnb": "18.1.0", + "eslint-plugin-import": "2.20.2", + "eslint-plugin-jsx-a11y": "6.2.3", + "eslint-plugin-react": "7.19.0", "solhint": "~3.2.0" } } diff --git a/yarn.lock b/yarn.lock index 7c283b6..c651b92 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5843,6 +5843,24 @@ escodegen@^1.11.0, escodegen@^1.9.1: optionalDependencies: source-map "~0.6.1" +eslint-config-airbnb-base@^14.1.0: + version "14.2.0" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.0.tgz#fe89c24b3f9dc8008c9c0d0d88c28f95ed65e9c4" + integrity sha512-Snswd5oC6nJaevs3nZoLSTvGJBvzTfnBqOIArkf3cbyTyq9UD79wOk8s+RiL6bhca0p/eRO6veczhf6A/7Jy8Q== + dependencies: + confusing-browser-globals "^1.0.9" + object.assign "^4.1.0" + object.entries "^1.1.2" + +eslint-config-airbnb@18.1.0: + version "18.1.0" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-18.1.0.tgz#724d7e93dadd2169492ff5363c5aaa779e01257d" + integrity sha512-kZFuQC/MPnH7KJp6v95xsLBf63G/w7YqdPfQ0MUanxQ7zcKUNG8j+sSY860g3NwCBOa62apw16J6pRN+AOgXzw== + dependencies: + eslint-config-airbnb-base "^14.1.0" + object.assign "^4.1.0" + object.entries "^1.1.1" + 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" @@ -5902,6 +5920,24 @@ eslint-plugin-import@2.20.1: read-pkg-up "^2.0.0" resolve "^1.12.0" +eslint-plugin-import@2.20.2: + version "2.20.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.20.2.tgz#91fc3807ce08be4837141272c8b99073906e588d" + integrity sha512-FObidqpXrR8OnCh4iNsxy+WACztJLXAHBO5hK79T1Hc77PgQZkyDGA5Ag9xAvRpglvLNxhH/zSmZ70/pZ31dHg== + dependencies: + array-includes "^3.0.3" + array.prototype.flat "^1.2.1" + contains-path "^0.1.0" + debug "^2.6.9" + doctrine "1.5.0" + eslint-import-resolver-node "^0.3.2" + eslint-module-utils "^2.4.1" + has "^1.0.3" + minimatch "^3.0.4" + object.values "^1.1.0" + read-pkg-up "^2.0.0" + resolve "^1.12.0" + eslint-plugin-jsx-a11y@6.2.3: version "6.2.3" resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.2.3.tgz#b872a09d5de51af70a97db1eea7dc933043708aa" @@ -5975,90 +6011,90 @@ eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== -eslint@^5.6.0: - version "5.16.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" - integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== +eslint@6.8.0, eslint@^6.6.0: + version "6.8.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" + integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig== dependencies: "@babel/code-frame" "^7.0.0" - ajv "^6.9.1" + ajv "^6.10.0" chalk "^2.1.0" cross-spawn "^6.0.5" debug "^4.0.1" doctrine "^3.0.0" - eslint-scope "^4.0.3" - eslint-utils "^1.3.1" - eslint-visitor-keys "^1.0.0" - espree "^5.0.1" + eslint-scope "^5.0.0" + eslint-utils "^1.4.3" + eslint-visitor-keys "^1.1.0" + espree "^6.1.2" esquery "^1.0.1" esutils "^2.0.2" file-entry-cache "^5.0.1" functional-red-black-tree "^1.0.1" - glob "^7.1.2" - globals "^11.7.0" + glob-parent "^5.0.0" + globals "^12.1.0" ignore "^4.0.6" import-fresh "^3.0.0" imurmurhash "^0.1.4" - inquirer "^6.2.2" - js-yaml "^3.13.0" + inquirer "^7.0.0" + is-glob "^4.0.0" + js-yaml "^3.13.1" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.3.0" - lodash "^4.17.11" + lodash "^4.17.14" minimatch "^3.0.4" mkdirp "^0.5.1" natural-compare "^1.4.0" - optionator "^0.8.2" - path-is-inside "^1.0.2" + optionator "^0.8.3" progress "^2.0.0" regexpp "^2.0.1" - semver "^5.5.1" - strip-ansi "^4.0.0" - strip-json-comments "^2.0.1" + semver "^6.1.2" + strip-ansi "^5.2.0" + strip-json-comments "^3.0.1" table "^5.2.3" text-table "^0.2.0" + v8-compile-cache "^2.0.3" -eslint@^6.6.0: - version "6.8.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" - integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig== +eslint@^5.6.0: + version "5.16.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" + integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== dependencies: "@babel/code-frame" "^7.0.0" - ajv "^6.10.0" + ajv "^6.9.1" chalk "^2.1.0" cross-spawn "^6.0.5" debug "^4.0.1" doctrine "^3.0.0" - eslint-scope "^5.0.0" - eslint-utils "^1.4.3" - eslint-visitor-keys "^1.1.0" - espree "^6.1.2" + eslint-scope "^4.0.3" + eslint-utils "^1.3.1" + eslint-visitor-keys "^1.0.0" + espree "^5.0.1" esquery "^1.0.1" 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" + glob "^7.1.2" + globals "^11.7.0" ignore "^4.0.6" import-fresh "^3.0.0" imurmurhash "^0.1.4" - inquirer "^7.0.0" - is-glob "^4.0.0" - js-yaml "^3.13.1" + inquirer "^6.2.2" + js-yaml "^3.13.0" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.3.0" - lodash "^4.17.14" + lodash "^4.17.11" minimatch "^3.0.4" mkdirp "^0.5.1" natural-compare "^1.4.0" - optionator "^0.8.3" + optionator "^0.8.2" + path-is-inside "^1.0.2" progress "^2.0.0" regexpp "^2.0.1" - semver "^6.1.2" - strip-ansi "^5.2.0" - strip-json-comments "^3.0.1" + semver "^5.5.1" + strip-ansi "^4.0.0" + strip-json-comments "^2.0.1" table "^5.2.3" text-table "^0.2.0" - v8-compile-cache "^2.0.3" espree@^5.0.1: version "5.0.1" @@ -11949,7 +11985,7 @@ object.assign@^4.1.0: has-symbols "^1.0.1" object-keys "^1.1.1" -object.entries@^1.1.0, object.entries@^1.1.1: +object.entries@^1.1.0, object.entries@^1.1.1, object.entries@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.2.tgz#bc73f00acb6b6bb16c203434b10f9a7e797d3add" integrity sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA== From 498f20516e31c9b9973b6f07121c0f9207647105 Mon Sep 17 00:00:00 2001 From: Apostolof Date: Mon, 2 Nov 2020 22:27:20 +0200 Subject: [PATCH 002/150] Fix lint issues in contracts --- packages/concordia-contracts/index.js | 2 +- .../migrations/1_initial_migration.js | 1 + .../migrations/2_deploy_contracts.js | 1 + .../concordia-contracts/truffle-config.js | 40 +++++++++---------- 4 files changed, 23 insertions(+), 21 deletions(-) diff --git a/packages/concordia-contracts/index.js b/packages/concordia-contracts/index.js index c9b676f..7440d0d 100644 --- a/packages/concordia-contracts/index.js +++ b/packages/concordia-contracts/index.js @@ -9,5 +9,5 @@ try { } module.exports = { - contracts: [Forum] + contracts: [Forum], }; diff --git a/packages/concordia-contracts/migrations/1_initial_migration.js b/packages/concordia-contracts/migrations/1_initial_migration.js index f28d653..2565467 100644 --- a/packages/concordia-contracts/migrations/1_initial_migration.js +++ b/packages/concordia-contracts/migrations/1_initial_migration.js @@ -1,5 +1,6 @@ const Migrations = artifacts.require('./Migrations.sol'); +// eslint-disable-next-line func-names module.exports = function (deployer) { deployer.deploy(Migrations); }; diff --git a/packages/concordia-contracts/migrations/2_deploy_contracts.js b/packages/concordia-contracts/migrations/2_deploy_contracts.js index 616b16e..c94e2cb 100644 --- a/packages/concordia-contracts/migrations/2_deploy_contracts.js +++ b/packages/concordia-contracts/migrations/2_deploy_contracts.js @@ -1,5 +1,6 @@ const Forum = artifacts.require('Forum'); +// eslint-disable-next-line func-names module.exports = function (deployer) { deployer.deploy(Forum); }; diff --git a/packages/concordia-contracts/truffle-config.js b/packages/concordia-contracts/truffle-config.js index 7dd0968..ab6d593 100644 --- a/packages/concordia-contracts/truffle-config.js +++ b/packages/concordia-contracts/truffle-config.js @@ -1,27 +1,27 @@ -const path = require("path"); +const path = require('path'); const { GANACHE_HOST } = process.env; const { GANACHE_PORT } = process.env; module.exports = { - // See - // to customize your Truffle configuration! - compilers: { - solc: { - version: "0.7.1" - } - }, - contracts_build_directory: path.join(__dirname, 'build/'), - networks: { - develop: { - host: GANACHE_HOST || '127.0.0.1', - port: GANACHE_PORT || '8545', - network_id: '*', + // See + // to customize your Truffle configuration! + compilers: { + solc: { + version: '0.7.1', + }, + }, + contracts_build_directory: path.join(__dirname, 'build/'), + networks: { + develop: { + host: GANACHE_HOST || '127.0.0.1', + port: GANACHE_PORT || '8545', + network_id: '*', + }, + test: { + host: GANACHE_HOST || '127.0.0.1', + port: GANACHE_PORT || '8546', + network_id: '*', + }, }, - test: { - host: GANACHE_HOST || '127.0.0.1', - port: GANACHE_PORT || '8546', - network_id: '*', - } - } }; From adc3fbb9a286ae56d503b2b7225f977b84231344 Mon Sep 17 00:00:00 2001 From: Apostolof Date: Mon, 2 Nov 2020 23:30:42 +0200 Subject: [PATCH 003/150] Update eslintrc files --- packages/concordia-app/.eslintrc.js | 13 +++++++++---- packages/concordia-contracts/.eslintrc.js | 11 ++--------- yarn.lock | 2 +- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/packages/concordia-app/.eslintrc.js b/packages/concordia-app/.eslintrc.js index c2321b9..db831ff 100644 --- a/packages/concordia-app/.eslintrc.js +++ b/packages/concordia-app/.eslintrc.js @@ -23,18 +23,23 @@ module.exports = { 'react' ], 'rules': { - "indent": ["error", 4], - "react/jsx-indent": ["error", 4], - "react/jsx-indent-props": ["error", 4], - 'react/jsx-filename-extension': 'off', 'react/jsx-props-no-spreading': 'off', 'import/extensions': 'off', + "react/jsx-indent": [ + 'error', + 4, + { + checkAttributes: true, + indentLogicalExpressions: true + } + ], 'react/require-default-props': 'off', 'react/prop-types': 'off', 'max-len': ['warn', {'code': 120, 'tabWidth': 4}], 'no-unused-vars': 'warn', 'no-console': 'warn', 'no-shadow': 'warn', + "no-multi-str": "warn" }, 'settings': { 'import/resolver': { diff --git a/packages/concordia-contracts/.eslintrc.js b/packages/concordia-contracts/.eslintrc.js index 8261734..3b8b151 100644 --- a/packages/concordia-contracts/.eslintrc.js +++ b/packages/concordia-contracts/.eslintrc.js @@ -17,9 +17,6 @@ module.exports = { 'assert': 'readonly' }, 'parserOptions': { - 'ecmaFeatures': { - 'jsx': true - }, 'ecmaVersion': 2018, 'sourceType': 'module' }, @@ -27,11 +24,6 @@ module.exports = { 'react' ], 'rules': { - "indent": ["error", 4], - "react/jsx-indent": ["error", 4], - "react/jsx-indent-props": ["error", 4], - 'react/jsx-filename-extension': 'off', - 'react/jsx-props-no-spreading': 'off', 'import/extensions': 'off', 'react/require-default-props': 'off', 'react/prop-types': 'off', @@ -39,11 +31,12 @@ module.exports = { 'no-unused-vars': 'warn', 'no-console': 'warn', 'no-shadow': 'warn', + "no-multi-str": "warn" }, 'settings': { 'import/resolver': { 'node': { - 'extensions': ['.js', '.jsx'] + 'extensions': ['.js'] } } }, diff --git a/yarn.lock b/yarn.lock index c651b92..48aaf59 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3277,7 +3277,7 @@ babel-code-frame@^6.22.0: esutils "^2.0.2" js-tokens "^3.0.2" -babel-eslint@10.1.0: +babel-eslint@10.1.0, babel-eslint@^10.0.0: version "10.1.0" resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg== From 40925e2a7ae229cad9b94d06052670e3b94f8c9b Mon Sep 17 00:00:00 2001 From: Apostolof Date: Mon, 2 Nov 2020 23:31:01 +0200 Subject: [PATCH 004/150] Fix lint issues --- packages/concordia-app/package.json | 2 +- packages/concordia-app/src/components/App.jsx | 37 ++- .../src/components/AppContext.js | 72 ----- .../src/components/AppContext.jsx | 81 ++++++ .../src/components/CoreLayoutContainer.jsx | 26 +- .../src/components/HomeContainer.jsx | 8 +- .../src/components/LoadingComponent.jsx | 102 ++++--- .../src/components/LoadingContainer.jsx | 269 ++++++++++-------- .../src/components/MenuComponent.jsx | 55 ++-- .../concordia-app/src/components/NotFound.jsx | 2 +- .../src/components/SignUpForm.jsx | 235 +++++++-------- .../concordia-app/src/{index.js => index.jsx} | 19 +- .../src/options/breezeOptions.js | 66 ++--- .../src/options/drizzleOptions.js | 18 +- .../concordia-app/src/options/web3Options.js | 2 +- .../concordia-app/src/orbit/levelUtils.js | 14 +- .../concordia-app/src/orbit/orbitUtils.js | 14 +- .../src/orbit/ΕthereumIdentityProvider.js | 170 +++++------ .../src/redux/reducers/userReducer.js | 38 +-- .../src/redux/sagas/orbitSaga.js | 29 +- .../concordia-app/src/redux/sagas/rootSaga.js | 24 +- .../concordia-app/src/redux/sagas/userSaga.js | 65 ++--- packages/concordia-app/src/redux/store.js | 19 +- .../concordia-app/src/utils/serviceWorker.js | 38 +-- packages/concordia-contracts/index.js | 10 +- .../migrations/1_initial_migration.js | 2 +- .../migrations/2_deploy_contracts.js | 2 +- .../concordia-contracts/truffle-config.js | 36 +-- 28 files changed, 748 insertions(+), 707 deletions(-) delete mode 100644 packages/concordia-app/src/components/AppContext.js create mode 100644 packages/concordia-app/src/components/AppContext.jsx rename packages/concordia-app/src/{index.js => index.jsx} (58%) diff --git a/packages/concordia-app/package.json b/packages/concordia-app/package.json index 65c1b25..0e039b8 100644 --- a/packages/concordia-app/package.json +++ b/packages/concordia-app/package.json @@ -9,7 +9,7 @@ "eject": "react-scripts eject", "postinstall": "patch-package", "analyze": "source-map-explorer 'build/static/js/*.js'", - "lint": "yarn run eslint . --format table" + "lint": "yarn run eslint --ext js,jsx . --format table" }, "browserslist": { "production": [ diff --git a/packages/concordia-app/src/components/App.jsx b/packages/concordia-app/src/components/App.jsx index 4086e07..88704c8 100644 --- a/packages/concordia-app/src/components/App.jsx +++ b/packages/concordia-app/src/components/App.jsx @@ -1,34 +1,33 @@ -import React from 'react' -import { Provider } from 'react-redux' -import { BrowserRouter as Router, Route, Switch } from 'react-router-dom' -import LoadingContainer from './LoadingContainer' -import PropTypes from 'prop-types' +import React from 'react'; +import { Provider } from 'react-redux'; +import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'; +import PropTypes from 'prop-types'; +import LoadingContainer from './LoadingContainer'; // CSS import '../assets/css/app.css'; import CoreLayoutContainer from './CoreLayoutContainer'; import HomeContainer from './HomeContainer'; -import NotFound from '../components/NotFound'; - +import NotFound from './NotFound'; const App = ({ store }) => ( - - - - - - - - + + + + + + + + -) +); App.propTypes = { - store: PropTypes.object.isRequired -} + store: PropTypes.object.isRequired, +}; -export default App +export default App; diff --git a/packages/concordia-app/src/components/AppContext.js b/packages/concordia-app/src/components/AppContext.js deleted file mode 100644 index 5534716..0000000 --- a/packages/concordia-app/src/components/AppContext.js +++ /dev/null @@ -1,72 +0,0 @@ -// Modified version of https://github.com/trufflesuite/drizzle/blob/develop/packages/react-plugin/src/DrizzleContext.js -import React from "react"; - -const Context = React.createContext(); - -class Provider extends React.Component { - state = { - drizzleState: null, - drizzleInitialized: false, - breezeState: null, - breezeInitialized: false - }; - - componentDidMount() { - const { drizzle, breeze } = this.props; - // subscribe to changes in the store, keep state up-to-date - this.unsubscribe = drizzle.store.subscribe(() => { - const drizzleState = drizzle.store.getState(); - const breezeState = breeze.store.getState(); - - if (drizzleState.drizzleStatus.initialized) { - this.setState({ - drizzleState, - drizzleInitialized: true - }); - } - if (breezeState.breezeStatus.initialized) { - this.setState({ - breezeState: breezeState, - breezeInitialized: true - }); - } - }); - - this.unsubscribe = breeze.store.subscribe(() => { - const breezeState = breeze.store.getState(); - if (breezeState.breezeStatus.initialized) { - this.setState({ - breezeState: breezeState, - breezeInitialized: true - }); - } - }); - } - - componentWillUnmount() { - this.unsubscribe(); - } - - render() { - return ( - - {this.props.children} - - ); - } -} - -export default { - Context: Context, - Consumer: Context.Consumer, - Provider -}; diff --git a/packages/concordia-app/src/components/AppContext.jsx b/packages/concordia-app/src/components/AppContext.jsx new file mode 100644 index 0000000..6b8b739 --- /dev/null +++ b/packages/concordia-app/src/components/AppContext.jsx @@ -0,0 +1,81 @@ +// Modified version of https://github.com/trufflesuite/drizzle/blob/develop/packages/react-plugin/src/DrizzleContext.js +import React from 'react'; + +const Context = React.createContext(); + +class Provider extends React.Component { + constructor(props) { + super(props); + + this.state = { + drizzleState: null, + drizzleInitialized: false, + breezeState: null, + breezeInitialized: false, + }; + } + + componentDidMount() { + const { drizzle, breeze } = this.props; + // subscribe to changes in the store, keep state up-to-date + this.unsubscribe = drizzle.store.subscribe(() => { + const drizzleState = drizzle.store.getState(); + const breezeState = breeze.store.getState(); + + if (drizzleState.drizzleStatus.initialized) { + this.setState({ + drizzleState, + drizzleInitialized: true, + }); + } + if (breezeState.breezeStatus.initialized) { + this.setState({ + breezeState, + breezeInitialized: true, + }); + } + }); + + this.unsubscribe = breeze.store.subscribe(() => { + const breezeState = breeze.store.getState(); + if (breezeState.breezeStatus.initialized) { + this.setState({ + breezeState, + breezeInitialized: true, + }); + } + }); + } + + componentWillUnmount() { + this.unsubscribe(); + } + + render() { + const { + drizzleState, drizzleInitialized, breezeState, breezeInitialized, + } = this.state; + const { drizzle, breeze, children } = this.props; + + return ( + + {children} + + ); + } +} + +export default { + Context, + Consumer: Context.Consumer, + Provider, +}; diff --git a/packages/concordia-app/src/components/CoreLayoutContainer.jsx b/packages/concordia-app/src/components/CoreLayoutContainer.jsx index 4a72130..5da971e 100644 --- a/packages/concordia-app/src/components/CoreLayoutContainer.jsx +++ b/packages/concordia-app/src/components/CoreLayoutContainer.jsx @@ -1,19 +1,21 @@ -import React, { Component } from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; import MenuComponent from './MenuComponent'; -export default class CoreLayout extends Component { - render() { - return ( -
- - {this.props.children} -
- ) - } -} +const CoreLayout = (props) => { + const { children } = props; + + return ( +
+ + {children} +
+ ); +}; CoreLayout.propTypes = { - children: PropTypes.element.isRequired + children: PropTypes.element.isRequired, }; + +export default CoreLayout; diff --git a/packages/concordia-app/src/components/HomeContainer.jsx b/packages/concordia-app/src/components/HomeContainer.jsx index 6fdafbb..d11b3f4 100644 --- a/packages/concordia-app/src/components/HomeContainer.jsx +++ b/packages/concordia-app/src/components/HomeContainer.jsx @@ -1,9 +1,5 @@ -import React, { Component } from 'react'; +import React from 'react'; -class HomeContainer extends Component { - render() { - return(

TODO: Home Container

); - } -} +const HomeContainer = () => (

TODO: Home Container

); export default HomeContainer; diff --git a/packages/concordia-app/src/components/LoadingComponent.jsx b/packages/concordia-app/src/components/LoadingComponent.jsx index 6f4ab70..7472b65 100644 --- a/packages/concordia-app/src/components/LoadingComponent.jsx +++ b/packages/concordia-app/src/components/LoadingComponent.jsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; import { Container, Progress } from 'semantic-ui-react'; @@ -7,67 +7,61 @@ import { Container, Progress } from 'semantic-ui-react'; import '../assets/css/loading-component.css'; // Images -import ethereum_logo from '../assets/images/ethereum_logo.svg'; -import ipfs_logo from '../assets/images/ipfs_logo.svg'; -import orbitdb_logo from '../assets/images/orbitdb_logo.png'; -import app_logo from '../assets/images/app_logo.png'; +import ethereumLogo from '../assets/images/ethereum_logo.svg'; +import ipfsLogo from '../assets/images/ipfs_logo.svg'; +import orbitdbLogo from '../assets/images/orbitdb_logo.png'; +import appLogo from '../assets/images/app_logo.png'; -class LoadingComponent extends Component { - render(){ - const { image_type, message_list, progress_type } = this.props ; - let imageSrc, imageAlt, listItems, indicating, error; +const LoadingComponent = (props) => { + const { + imageType, messageList, progressType, title, message, progress, + } = props; + let imageSrc; let imageAlt; let listItems; let indicating; let + error; - if (image_type === "ethereum"){ - imageSrc = ethereum_logo; - imageAlt = "ethereum_logo"; - } - else if (image_type === "ipfs"){ - imageSrc = ipfs_logo; - imageAlt = "ipfs_logo"; - } - else if (image_type === "orbit"){ - imageSrc = orbitdb_logo; - imageAlt = "orbitdb_logo"; - } - else if (image_type === "app"){ - imageSrc = app_logo; - imageAlt = "app_logo"; - } + if (imageType === 'ethereum') { + imageSrc = ethereumLogo; + imageAlt = 'ethereum_logo'; + } else if (imageType === 'ipfs') { + imageSrc = ipfsLogo; + imageAlt = 'ipfs_logo'; + } else if (imageType === 'orbit') { + imageSrc = orbitdbLogo; + imageAlt = 'orbitdb_logo'; + } else if (imageType === 'app') { + imageSrc = appLogo; + imageAlt = 'app_logo'; + } - if(progress_type === "indicating") - indicating = true; - else if(progress_type === "error") - error = true; + if (progressType === 'indicating') indicating = true; + else if (progressType === 'error') error = true; - if(message_list){ - listItems = message_list.map((listItem) => -
  • {listItem}
  • - ); - } + if (messageList) { + listItems = messageList.map((listItem) =>
  • {listItem}
  • ); + } - const list = message_list ?
      {listItems}
    : ''; + const list = messageList ?
      {listItems}
    : ''; - return( -
    - - {imageAlt} -

    {this.props.title}

    -

    {this.props.message}

    - {list} -
    - -
    - ); - } -} + return ( +
    + + {imageAlt} +

    {title}

    +

    {message}

    + {list} +
    + +
    + ); +}; LoadingComponent.propTypes = { - title: PropTypes.string.isRequired, - message: PropTypes.string.isRequired, - message_list: PropTypes.arrayOf(PropTypes.string), - image_type: PropTypes.string.isRequired, - progress: PropTypes.number.isRequired, - progress_type: PropTypes.string.isRequired, + title: PropTypes.string.isRequired, + message: PropTypes.string.isRequired, + messageList: PropTypes.arrayOf(PropTypes.string), + imageType: PropTypes.string.isRequired, + progress: PropTypes.number.isRequired, + progressType: PropTypes.string.isRequired, }; export default LoadingComponent; diff --git a/packages/concordia-app/src/components/LoadingContainer.jsx b/packages/concordia-app/src/components/LoadingContainer.jsx index c8ed6e0..0260132 100644 --- a/packages/concordia-app/src/components/LoadingContainer.jsx +++ b/packages/concordia-app/src/components/LoadingContainer.jsx @@ -1,7 +1,7 @@ import React, { Children, Component } from 'react'; import { connect } from 'react-redux'; -import { breezeConstants } from '@ezerous/breeze' +import { breezeConstants } from '@ezerous/breeze'; import LoadingComponent from './LoadingComponent'; @@ -9,128 +9,159 @@ import LoadingComponent from './LoadingComponent'; import '../assets/css/loading-component.css'; class LoadingContainer extends Component { - render() { - if ((this.props.web3.status === 'initializing' || !this.props.web3.networkId) - && !this.props.web3.networkFailed) { - return - } - - if (this.props.web3.status === 'failed' || this.props.web3.networkFailed) { - return - } - - if (this.props.web3.status === 'initialized' && this.props.web3.accountsFailed) { - return - } - - if (this.props.drizzleStatus.initializing - || (!this.props.drizzleStatus.failed && !this.props.contractInitialized && this.props.contractDeployed )){ - return - } - - if (!this.props.contractDeployed) { - return - } - - if (this.props.ipfsStatus === breezeConstants.STATUS_INITIALIZING) { - return - } - - if (this.props.ipfsStatus === breezeConstants.STATUS_FAILED) { - return - } - - if (this.props.orbitStatus === breezeConstants.STATUS_INITIALIZING) { - const message = process.env.NODE_ENV === 'development' - ? 'If needed, please sign the transaction in MetaMask to create the databases.' - : 'Please sign the transaction in MetaMask to create the databases.'; - return - } - - if (this.props.orbitStatus === breezeConstants.STATUS_FAILED) { - return - } - - if (!this.props.userFetched){ - return - } - - return Children.only(this.props.children); + render() { + const { + web3: { + status, networkId, networkFailed, accountsFailed, + }, + drizzleStatus: { + initializing, + failed, + }, + contractInitialized, contractDeployed, ipfsStatus, orbitStatus, userFetched, children, + } = this.props; + + if ((status === 'initializing' || !networkId) + && !networkFailed) { + return ( + + ); } + + if (status === 'failed' || networkFailed) { + return ( + + ); + } + + if (status === 'initialized' && accountsFailed) { + return ( + + ); + } + + if (initializing + || (!failed && !contractInitialized && contractDeployed)) { + return ( + + ); + } + + if (!contractDeployed) { + return ( + + ); + } + + if (ipfsStatus === breezeConstants.STATUS_INITIALIZING) { + return ( + + ); + } + + if (ipfsStatus === breezeConstants.STATUS_FAILED) { + return ( + + ); + } + + if (orbitStatus === breezeConstants.STATUS_INITIALIZING) { + const message = process.env.NODE_ENV === 'development' + ? 'If needed, please sign the transaction in MetaMask to create the databases.' + : 'Please sign the transaction in MetaMask to create the databases.'; + return ( + + ); + } + + if (orbitStatus === breezeConstants.STATUS_FAILED) { + return ( + + ); + } + + if (!userFetched) { + return ( + + ); + } + + return Children.only(children); + } } const mapStateToProps = (state) => ({ - drizzleStatus: state.drizzleStatus, - breezeStatus: state.breezeStatus, - ipfsStatus: state.ipfs.status, - orbitStatus: state.orbit.status, - web3: state.web3, - accounts: state.accounts, - contractInitialized: state.contracts.Forum.initialized, - contractDeployed: state.contracts.Forum.deployed, - userFetched: state.user.address + drizzleStatus: state.drizzleStatus, + breezeStatus: state.breezeStatus, + ipfsStatus: state.ipfs.status, + orbitStatus: state.orbit.status, + web3: state.web3, + accounts: state.accounts, + contractInitialized: state.contracts.Forum.initialized, + contractDeployed: state.contracts.Forum.deployed, + userFetched: state.user.address, }); export default connect(mapStateToProps)(LoadingContainer); diff --git a/packages/concordia-app/src/components/MenuComponent.jsx b/packages/concordia-app/src/components/MenuComponent.jsx index c71b040..e0c2421 100644 --- a/packages/concordia-app/src/components/MenuComponent.jsx +++ b/packages/concordia-app/src/components/MenuComponent.jsx @@ -1,38 +1,35 @@ -import React, { Component } from 'react'; -import { withRouter } from "react-router"; +import React from 'react'; +import { withRouter } from 'react-router'; import { Menu } from 'semantic-ui-react'; -import AppContext from "./AppContext"; +import AppContext from './AppContext'; -import app_logo from '../assets/images/app_logo.png'; +import appLogo from '../assets/images/app_logo.png'; import SignUpForm from './SignUpForm'; -class MenuComponent extends Component { - render() { - return ( - - {context => { - return( -
    - - { this.props.history.push("/"); }} - > - app_logo - +const MenuComponent = (props) => { + const { history: { push } } = props; - + return ( + + {() => ( +
    + + { push('/'); }} + > + app_logo + - -
    - ) - } - } -
    - ) - } -} + + +
    +
    + )} +
    + ); +}; export default withRouter(MenuComponent); diff --git a/packages/concordia-app/src/components/NotFound.jsx b/packages/concordia-app/src/components/NotFound.jsx index c73a7e5..9b5be95 100644 --- a/packages/concordia-app/src/components/NotFound.jsx +++ b/packages/concordia-app/src/components/NotFound.jsx @@ -3,7 +3,7 @@ import pageNotFound from '../assets/images/PageNotFound.jpg'; const NotFound = () => (
    Page not found! diff --git a/packages/concordia-app/src/components/SignUpForm.jsx b/packages/concordia-app/src/components/SignUpForm.jsx index fad79bc..3c9fed3 100644 --- a/packages/concordia-app/src/components/SignUpForm.jsx +++ b/packages/concordia-app/src/components/SignUpForm.jsx @@ -1,139 +1,144 @@ import React, { Component } from 'react'; -import { Button, Form, Menu, Message, Modal } from 'semantic-ui-react'; +import { + Button, Form, Menu, Message, Modal, +} from 'semantic-ui-react'; -import AppContext from "./AppContext"; import { connect } from 'react-redux'; +import AppContext from './AppContext'; const contractName = 'Forum'; const checkUsernameTakenMethod = 'isUserNameTaken'; const signUpMethod = 'signUp'; class SignUpForm extends Component { - constructor(props, context) { - super(props, context); - - // For quick access - this.contract = this.context.drizzle.contracts[contractName]; - - this.handleInputChange = this.handleInputChange.bind(this); - this.handleSubmit = this.handleSubmit.bind(this); - this.completeAction = this.completeAction.bind(this); - - this.checkedUsernames = []; - - this.state = { - usernameInput: '', - error: false, - errorHeader: '', - errorMessage: '', - signingUp: false, - }; + constructor(props, context) { + super(props, context); + + // For quick access + this.contract = this.context.drizzle.contracts[contractName]; + + this.handleInputChange = this.handleInputChange.bind(this); + this.handleSubmit = this.handleSubmit.bind(this); + this.completeAction = this.completeAction.bind(this); + + this.checkedUsernames = []; + + this.state = { + usernameInput: '', + error: false, + errorHeader: '', + errorMessage: '', + signingUp: false, + }; + } + + componentDidUpdate() { + // TODO + } + + handleSubmit() { + const { usernameInput, error } = this.state; + + if (usernameInput === '') { + this.setState({ + error: true, + errorHeader: 'Data Incomplete', + errorMessage: 'You need to provide a username', + }); + } else if (!error) { + // TODO + // // Makes sure current input username has been checked for availability + // if (this.checkedUsernames.some((e) => e.usernameChecked === usernameInput)) { + // this.completeAction(); + // } + this.completeAction(); } - - handleInputChange(e, { name, value }) { - this.setState({ - [name]: value, - error: false, - }); - if (value !== '') { - if (this.checkedUsernames.length > 0) { - if (this.checkedUsernames.some((e) => e.usernameChecked === value)) { - return; - } - } - - this.contract.methods[checkUsernameTakenMethod].cacheCall( - value, - ); - } - } - - handleSubmit() { - const { usernameInput, error } = this.state; - - if (usernameInput === '') { - this.setState({ - error: true, - errorHeader: 'Data Incomplete', - errorMessage: 'You need to provide a username', - }); - } else if (!error) { - // TODO - // // Makes sure current input username has been checked for availability - // if (this.checkedUsernames.some((e) => e.usernameChecked === usernameInput)) { - // this.completeAction(); - // } - this.completeAction(); + } + + handleInputChange(e, { name, value }) { + this.setState({ + [name]: value, + error: false, + }); + if (value !== '') { + if (this.checkedUsernames.length > 0) { + if (this.checkedUsernames.some((e) => e.usernameChecked === value)) { + return; } - } + } - componentDidUpdate() { - // TODO + this.contract.methods[checkUsernameTakenMethod].cacheCall( + value, + ); } - - completeAction() { - const { usernameInput } = this.state; - const { user, account } = this.props; - - if (user.hasSignedUp) { - console.log('Signing up..') - this.contract.methods['signUp'].cacheSend(usernameInput); - } else { - this.setState({ - signingUp: true, - }); - this.contract.methods[signUpMethod].cacheSend( - ...[usernameInput], { from: account }, - ); - } - this.setState({ - usernameInput: '', - }); + } + + completeAction() { + const { usernameInput } = this.state; + const { user, account } = this.props; + + if (user.hasSignedUp) { + console.log('Signing up..'); + this.contract.methods.signUp.cacheSend(usernameInput); + } else { + this.setState({ + signingUp: true, + }); + this.contract.methods[signUpMethod].cacheSend( + ...[usernameInput], { from: account }, + ); } - - render() { - const { - error, usernameInput, errorHeader, errorMessage, signingUp, - } = this.state; - - return( - this.handleSubmit(e)} trigger={ - - }> - Sign Up - - - - - - - this.handleSubmit(e)} + trigger={( + + )} + > + Sign Up + + + + + -
    diff --git a/packages/concordia-app/src/layouts/RegisterLayout/index.jsx b/packages/concordia-app/src/layouts/RegisterLayout/index.jsx index 2f7199f..c2317d8 100644 --- a/packages/concordia-app/src/layouts/RegisterLayout/index.jsx +++ b/packages/concordia-app/src/layouts/RegisterLayout/index.jsx @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import Particles from 'react-particles-js'; import particlesOptions from '../../assets/particles'; -import '../../assets/css/register-layout.css'; +import './styles.css'; const RegisterLayout = (props) => { const { children } = props; diff --git a/packages/concordia-app/src/assets/css/register-layout.css b/packages/concordia-app/src/layouts/RegisterLayout/styles.css similarity index 100% rename from packages/concordia-app/src/assets/css/register-layout.css rename to packages/concordia-app/src/layouts/RegisterLayout/styles.css diff --git a/packages/concordia-app/src/views/Register/index.jsx b/packages/concordia-app/src/views/Register/index.jsx index e69de29..3785ddf 100644 --- a/packages/concordia-app/src/views/Register/index.jsx +++ b/packages/concordia-app/src/views/Register/index.jsx @@ -0,0 +1,172 @@ +import React, { + useCallback, useContext, useEffect, useMemo, useState, +} from 'react'; +import { + Button, Card, Form, Header, Input, Message, +} from 'semantic-ui-react'; +import throttle from 'lodash/throttle'; +import { useTranslation } from 'react-i18next'; +import { connect } from 'react-redux'; +import { useHistory } from 'react-router'; +import AppContext from '../../components/AppContext'; +import './styles.css'; + +const Register = (props) => { + const { user, account, isUserNameTakenResults } = props; + const { + drizzle: { + contracts: { + Forum: { + methods: { isUserNameTaken, signUp }, + }, + }, + }, + } = useContext(AppContext.Context); + const [usernameInput, setUsernameInput] = useState(''); + const [usernameIsChecked, setUsernameIsChecked] = useState(true); + const [usernameIsTaken, setUsernameIsTaken] = useState(true); + const [error, setError] = useState(false); + const [errorMessage, setErrorMessage] = useState(''); + const [signingUp, setSigningUp] = useState(false); + const history = useHistory(); + const { t } = useTranslation(); + + useEffect(() => { + if (usernameInput.length > 0) { + const checkedUsernames = Object + .values(isUserNameTakenResults) + .map((callCompleted) => ({ + checkedUsername: callCompleted.args[0], + isTaken: callCompleted.value, + })); + const checkedUsername = checkedUsernames + .find((callCompleted) => callCompleted.checkedUsername === usernameInput); + + setUsernameIsChecked(checkedUsername !== undefined); + + if (checkedUsername && checkedUsername.isTaken) { + setUsernameIsTaken(true); + setError(true); + setErrorMessage(t('register.form.error.username.taken.message', { username: usernameInput })); + } else { + setUsernameIsTaken(false); + setError(false); + } + } + }, [isUserNameTakenResults, t, usernameInput]); + + const checkUsernameTaken = useMemo(() => throttle( + (username) => { + isUserNameTaken.cacheCall(username); + }, 200, + ), [isUserNameTaken]); + + const handleInputChange = useCallback((event, { value }) => { + setUsernameInput(value); + + if (value.length > 0) { + checkUsernameTaken(value); + } + }, [checkUsernameTaken]); + + const handleSubmit = useCallback(() => { + if (user.hasSignedUp) { + signUp.cacheSend(usernameInput); + } else { + setSigningUp(true); + signUp.cacheSend( + ...[usernameInput], { from: account }, + ); + } + }, [account, signUp, user.hasSignedUp, usernameInput]); + + const goToHomePage = React.useCallback(() => history.push('/'), [history]); + + return ( +
    + + + Sign Up + +

    + {t('register.p.account.address')} +   + {user.address} +

    + {user.hasSignedUp + ? ( +
    +
    + {t('register.form.header.already.member.message')} +
    +
    + ) + : ( +
    + + + + +
    + )} +
    +
    + {error === true && ( + + + + )} + + {user.hasSignedUp + ? ( +
    + ); +}; + +const mapStateToProps = (state) => ({ + user: state.user, + isUserNameTakenResults: state.contracts.Forum.isUserNameTaken, +}); + +export default connect(mapStateToProps)(Register); diff --git a/packages/concordia-app/src/views/Register/styles.css b/packages/concordia-app/src/views/Register/styles.css new file mode 100644 index 0000000..4732c4a --- /dev/null +++ b/packages/concordia-app/src/views/Register/styles.css @@ -0,0 +1,10 @@ +.centered { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +.form-card-container { + min-width: 15vw; +} From 98a2c6723b7673b95acd3237e4c3814bc3e23bfd Mon Sep 17 00:00:00 2001 From: Apostolof Date: Thu, 5 Nov 2020 00:24:57 +0200 Subject: [PATCH 012/150] Change menu button when user signed up --- .../public/locales/en/translation.json | 1 + .../MainLayout/MainLayoutMenu/index.jsx | 46 +++++++++++++------ 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/packages/concordia-app/public/locales/en/translation.json b/packages/concordia-app/public/locales/en/translation.json index e288c36..78f816d 100644 --- a/packages/concordia-app/public/locales/en/translation.json +++ b/packages/concordia-app/public/locales/en/translation.json @@ -9,5 +9,6 @@ "register.form.username.field.label": "Username", "register.form.username.field.placeholder": "Username", "register.p.account.address": "Account address:", + "topbar.button.profile": "Profile", "topbar.button.register": "Sign Up" } \ No newline at end of file diff --git a/packages/concordia-app/src/layouts/MainLayout/MainLayoutMenu/index.jsx b/packages/concordia-app/src/layouts/MainLayout/MainLayoutMenu/index.jsx index e017c4f..7edbf43 100644 --- a/packages/concordia-app/src/layouts/MainLayout/MainLayoutMenu/index.jsx +++ b/packages/concordia-app/src/layouts/MainLayout/MainLayoutMenu/index.jsx @@ -1,12 +1,14 @@ import React from 'react'; -import { withRouter } from 'react-router'; import { Menu } from 'semantic-ui-react'; import { useTranslation } from 'react-i18next'; +import { useHistory } from 'react-router'; +import { connect } from 'react-redux'; import AppContext from '../../../components/AppContext'; import appLogo from '../../../assets/images/app_logo.png'; const MainLayoutMenu = (props) => { - const { history: { push } } = props; + const { user: { hasSignedUp } } = props; + const history = useHistory(); const { t } = useTranslation(); return ( @@ -18,19 +20,33 @@ const MainLayoutMenu = (props) => { link name="home" key="home" - onClick={() => { push('/'); }} + onClick={() => { history.push('/'); }} > app_logo - { push('/auth/register'); }} - position="right" - > - {t('topbar.button.register')} - + {hasSignedUp + ? ( + { history.push('/profile'); }} + position="right" + > + {t('topbar.button.profile')} + + ) + : ( + { history.push('/auth/register'); }} + position="right" + > + {t('topbar.button.register')} + + )} )} @@ -38,4 +54,8 @@ const MainLayoutMenu = (props) => { ); }; -export default withRouter(MainLayoutMenu); +const mapStateToProps = (state) => ({ + user: state.user, +}); + +export default connect(mapStateToProps)(MainLayoutMenu); From 519541d1d17d76fb10286e123473420d66957571 Mon Sep 17 00:00:00 2001 From: Apostolof Date: Thu, 5 Nov 2020 01:28:31 +0200 Subject: [PATCH 013/150] Add Home view --- .../public/locales/en/translation.json | 4 ++ packages/concordia-app/src/Routes.jsx | 2 +- .../src/components/HomeContainer.jsx | 5 -- .../MainLayout/MainLayoutMenu/index.jsx | 37 ++++++++----- .../src/views/Home/Board/index.jsx | 53 +++++++++++++++++++ .../concordia-app/src/views/Home/index.jsx | 34 ++++++++++++ 6 files changed, 115 insertions(+), 20 deletions(-) delete mode 100644 packages/concordia-app/src/components/HomeContainer.jsx create mode 100644 packages/concordia-app/src/views/Home/Board/index.jsx create mode 100644 packages/concordia-app/src/views/Home/index.jsx diff --git a/packages/concordia-app/public/locales/en/translation.json b/packages/concordia-app/public/locales/en/translation.json index 78f816d..29db84c 100644 --- a/packages/concordia-app/public/locales/en/translation.json +++ b/packages/concordia-app/public/locales/en/translation.json @@ -1,4 +1,7 @@ { + "board.header.no.topics.message": "There are no topics yet!", + "board.sub.header.no.topics.guest": "Sign up and be the first to post.", + "board.sub.header.no.topics.user": "Be the first to post.", "register.card.header": "Sign Up", "register.form.button.back": "Back", "register.form.button.guest": "Continue as guest", @@ -9,6 +12,7 @@ "register.form.username.field.label": "Username", "register.form.username.field.placeholder": "Username", "register.p.account.address": "Account address:", + "topbar.button.create.topic": "Create topic", "topbar.button.profile": "Profile", "topbar.button.register": "Sign Up" } \ No newline at end of file diff --git a/packages/concordia-app/src/Routes.jsx b/packages/concordia-app/src/Routes.jsx index cee10ce..3363d93 100644 --- a/packages/concordia-app/src/Routes.jsx +++ b/packages/concordia-app/src/Routes.jsx @@ -32,7 +32,7 @@ const routesConfig = [ { exact: true, path: '/', - component: lazy(() => import('./components/HomeContainer')), + component: lazy(() => import('./views/Home')), }, { component: () => , diff --git a/packages/concordia-app/src/components/HomeContainer.jsx b/packages/concordia-app/src/components/HomeContainer.jsx deleted file mode 100644 index d11b3f4..0000000 --- a/packages/concordia-app/src/components/HomeContainer.jsx +++ /dev/null @@ -1,5 +0,0 @@ -import React from 'react'; - -const HomeContainer = () => (

    TODO: Home Container

    ); - -export default HomeContainer; diff --git a/packages/concordia-app/src/layouts/MainLayout/MainLayoutMenu/index.jsx b/packages/concordia-app/src/layouts/MainLayout/MainLayoutMenu/index.jsx index 7edbf43..af9d6f4 100644 --- a/packages/concordia-app/src/layouts/MainLayout/MainLayoutMenu/index.jsx +++ b/packages/concordia-app/src/layouts/MainLayout/MainLayoutMenu/index.jsx @@ -14,16 +14,27 @@ const MainLayoutMenu = (props) => { return ( {() => ( -
    - - { history.push('/'); }} - > - app_logo - + + { history.push('/'); }} + > + app_logo + + + {hasSignedUp && history.location.pathname === '/' && ( + { history.push('/topics/new'); }} + position="right" + > + {t('topbar.button.create.topic')} + + )} {hasSignedUp ? ( { name="profile" key="profile" onClick={() => { history.push('/profile'); }} - position="right" > {t('topbar.button.profile')} @@ -42,13 +52,12 @@ const MainLayoutMenu = (props) => { name="register" key="register" onClick={() => { history.push('/auth/register'); }} - position="right" > {t('topbar.button.register')} )} - -
    + + )}
    ); diff --git a/packages/concordia-app/src/views/Home/Board/index.jsx b/packages/concordia-app/src/views/Home/Board/index.jsx new file mode 100644 index 0000000..58652bf --- /dev/null +++ b/packages/concordia-app/src/views/Home/Board/index.jsx @@ -0,0 +1,53 @@ +import React, { useMemo, useState } from 'react'; +import { Header } from 'semantic-ui-react'; +import { connect } from 'react-redux'; +import _ from 'lodash'; +import { useTranslation } from 'react-i18next'; + +const Board = (props) => { + const { numberOfTopics, userHasSignedUp } = props; + const [topicIds, setTopicIds] = useState([]); + const { t } = useTranslation(); + + const boardContents = useMemo(() => { + if (numberOfTopics > 0) { + setTopicIds(_.range(0, numberOfTopics)); + + return (
    TODO
    ); + } if (!userHasSignedUp) { + return ( +
    +
    + {t('board.header.no.topics.message')} +
    +
    + {t('board.sub.header.no.topics.guest')} +
    +
    + ); + } + + return ( +
    +
    + {t('board.header.no.topics.message')} +
    +
    + {t('board.sub.header.no.topics.user')} +
    +
    + ); + }, [numberOfTopics, userHasSignedUp, t]); + + return ( +
    + {boardContents} +
    + ); +}; + +const mapStateToProps = (state) => ({ + userHasSignedUp: state.user.hasSignedUp, +}); + +export default connect(mapStateToProps)(Board); diff --git a/packages/concordia-app/src/views/Home/index.jsx b/packages/concordia-app/src/views/Home/index.jsx new file mode 100644 index 0000000..36f9b71 --- /dev/null +++ b/packages/concordia-app/src/views/Home/index.jsx @@ -0,0 +1,34 @@ +import React, { + useContext, useEffect, useMemo, useState, +} from 'react'; +import { Container } from 'semantic-ui-react'; +import { connect } from 'react-redux'; +import AppContext from '../../components/AppContext'; +import Board from './Board'; + +const Home = (props) => { + const { getNumberOfTopicsResults } = props; + const { drizzle: { contracts: { Forum: { methods: { getNumberOfTopics } } } } } = useContext(AppContext.Context); + const [numberOfTopicsCallHash, setNumberOfTopicsCallHash] = useState(''); + + useEffect(() => { + setNumberOfTopicsCallHash(getNumberOfTopics.cacheCall()); + }, [getNumberOfTopics]); + + const numberOfTopics = useMemo(() => (getNumberOfTopicsResults[numberOfTopicsCallHash] !== undefined + ? parseInt(getNumberOfTopicsResults[numberOfTopicsCallHash].value, 10) + : null), + [getNumberOfTopicsResults, numberOfTopicsCallHash]); + + return ( + + {numberOfTopics !== null && } + + ); +}; + +const mapStateToProps = (state) => ({ + getNumberOfTopicsResults: state.contracts.Forum.getNumberOfTopics, +}); + +export default connect(mapStateToProps)(Home); From 0abe5debe5093d0ac445579a9e75453cd556396c Mon Sep 17 00:00:00 2001 From: Apostolof Date: Thu, 5 Nov 2020 21:23:09 +0200 Subject: [PATCH 014/150] Handle register success and failure --- .../src/views/Register/index.jsx | 37 +++++++++++++------ 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/packages/concordia-app/src/views/Register/index.jsx b/packages/concordia-app/src/views/Register/index.jsx index 3785ddf..fe9ccd5 100644 --- a/packages/concordia-app/src/views/Register/index.jsx +++ b/packages/concordia-app/src/views/Register/index.jsx @@ -6,13 +6,14 @@ import { } from 'semantic-ui-react'; import throttle from 'lodash/throttle'; import { useTranslation } from 'react-i18next'; -import { connect } from 'react-redux'; +import { useSelector } from 'react-redux'; import { useHistory } from 'react-router'; import AppContext from '../../components/AppContext'; import './styles.css'; const Register = (props) => { - const { user, account, isUserNameTakenResults } = props; + const { account } = props; + const { drizzle: { contracts: { @@ -22,12 +23,20 @@ const Register = (props) => { }, }, } = useContext(AppContext.Context); + + const user = useSelector((state) => state.user); + const isUserNameTakenResults = useSelector((state) => state.contracts.Forum.isUserNameTaken); + const transactionStack = useSelector((state) => state.transactionStack); + const transactions = useSelector((state) => state.transactions); + const [usernameInput, setUsernameInput] = useState(''); const [usernameIsChecked, setUsernameIsChecked] = useState(true); const [usernameIsTaken, setUsernameIsTaken] = useState(true); const [error, setError] = useState(false); const [errorMessage, setErrorMessage] = useState(''); const [signingUp, setSigningUp] = useState(false); + const [registerCacheSendStackId, setRegisterCacheSendStackId] = useState(''); + const history = useHistory(); const { t } = useTranslation(); @@ -55,6 +64,18 @@ const Register = (props) => { } }, [isUserNameTakenResults, t, usernameInput]); + useEffect(() => { + if (signingUp && transactionStack && transactionStack[registerCacheSendStackId] + && transactions[transactionStack[registerCacheSendStackId]]) { + if (transactions[transactionStack[registerCacheSendStackId]].status === 'error') { + setSigningUp(false); + } else if (transactions[transactionStack[registerCacheSendStackId]].status === 'success') { + history.push('/'); + // TODO: display a welcome message? + } + } + }, [registerCacheSendStackId, signingUp, transactions, transactionStack, history]); + const checkUsernameTaken = useMemo(() => throttle( (username) => { isUserNameTaken.cacheCall(username); @@ -74,9 +95,7 @@ const Register = (props) => { signUp.cacheSend(usernameInput); } else { setSigningUp(true); - signUp.cacheSend( - ...[usernameInput], { from: account }, - ); + setRegisterCacheSendStackId(signUp.cacheSend(...[usernameInput], { from: account })); } }, [account, signUp, user.hasSignedUp, usernameInput]); @@ -155,6 +174,7 @@ const Register = (props) => { basic content={t('register.form.button.guest')} onClick={goToHomePage} + disabled={signingUp} /> )} @@ -164,9 +184,4 @@ const Register = (props) => { ); }; -const mapStateToProps = (state) => ({ - user: state.user, - isUserNameTakenResults: state.contracts.Forum.isUserNameTaken, -}); - -export default connect(mapStateToProps)(Register); +export default Register; From 3d35f5df5cdafa33a5fc3b07d34e0d4215b1fc6d Mon Sep 17 00:00:00 2001 From: Apostolof Date: Thu, 5 Nov 2020 21:36:35 +0200 Subject: [PATCH 015/150] Replace mapStateToProps with hook --- .../layouts/MainLayout/MainLayoutMenu/index.jsx | 14 +++++--------- .../concordia-app/src/views/Home/Board/index.jsx | 11 ++++------- packages/concordia-app/src/views/Home/index.jsx | 12 ++++-------- 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/packages/concordia-app/src/layouts/MainLayout/MainLayoutMenu/index.jsx b/packages/concordia-app/src/layouts/MainLayout/MainLayoutMenu/index.jsx index af9d6f4..11524eb 100644 --- a/packages/concordia-app/src/layouts/MainLayout/MainLayoutMenu/index.jsx +++ b/packages/concordia-app/src/layouts/MainLayout/MainLayoutMenu/index.jsx @@ -2,12 +2,12 @@ import React from 'react'; import { Menu } from 'semantic-ui-react'; import { useTranslation } from 'react-i18next'; import { useHistory } from 'react-router'; -import { connect } from 'react-redux'; +import { useSelector } from 'react-redux'; import AppContext from '../../../components/AppContext'; import appLogo from '../../../assets/images/app_logo.png'; -const MainLayoutMenu = (props) => { - const { user: { hasSignedUp } } = props; +const MainLayoutMenu = () => { + const hasSignedUp = useSelector((state) => state.user.hasSignedUp); const history = useHistory(); const { t } = useTranslation(); @@ -24,7 +24,7 @@ const MainLayoutMenu = (props) => { app_logo - {hasSignedUp && history.location.pathname === '/' && ( + {hasSignedUp && history.location.pathname === '/home' && ( { ); }; -const mapStateToProps = (state) => ({ - user: state.user, -}); - -export default connect(mapStateToProps)(MainLayoutMenu); +export default MainLayoutMenu; diff --git a/packages/concordia-app/src/views/Home/Board/index.jsx b/packages/concordia-app/src/views/Home/Board/index.jsx index 58652bf..2ef3cc4 100644 --- a/packages/concordia-app/src/views/Home/Board/index.jsx +++ b/packages/concordia-app/src/views/Home/Board/index.jsx @@ -1,11 +1,12 @@ import React, { useMemo, useState } from 'react'; import { Header } from 'semantic-ui-react'; -import { connect } from 'react-redux'; import _ from 'lodash'; import { useTranslation } from 'react-i18next'; +import { useSelector } from 'react-redux'; const Board = (props) => { - const { numberOfTopics, userHasSignedUp } = props; + const { numberOfTopics } = props; + const userHasSignedUp = useSelector((state) => state.user.hasSignedUp); const [topicIds, setTopicIds] = useState([]); const { t } = useTranslation(); @@ -46,8 +47,4 @@ const Board = (props) => { ); }; -const mapStateToProps = (state) => ({ - userHasSignedUp: state.user.hasSignedUp, -}); - -export default connect(mapStateToProps)(Board); +export default Board; diff --git a/packages/concordia-app/src/views/Home/index.jsx b/packages/concordia-app/src/views/Home/index.jsx index 36f9b71..42808b0 100644 --- a/packages/concordia-app/src/views/Home/index.jsx +++ b/packages/concordia-app/src/views/Home/index.jsx @@ -2,12 +2,12 @@ import React, { useContext, useEffect, useMemo, useState, } from 'react'; import { Container } from 'semantic-ui-react'; -import { connect } from 'react-redux'; +import { useSelector } from 'react-redux'; import AppContext from '../../components/AppContext'; import Board from './Board'; -const Home = (props) => { - const { getNumberOfTopicsResults } = props; +const Home = () => { + const getNumberOfTopicsResults = useSelector((state) => state.contracts.Forum.getNumberOfTopics); const { drizzle: { contracts: { Forum: { methods: { getNumberOfTopics } } } } } = useContext(AppContext.Context); const [numberOfTopicsCallHash, setNumberOfTopicsCallHash] = useState(''); @@ -27,8 +27,4 @@ const Home = (props) => { ); }; -const mapStateToProps = (state) => ({ - getNumberOfTopicsResults: state.contracts.Forum.getNumberOfTopics, -}); - -export default connect(mapStateToProps)(Home); +export default Home; From 029eae0ab6219e0c3bec0141955d9db7eadb25b1 Mon Sep 17 00:00:00 2001 From: Apostolof Date: Fri, 6 Nov 2020 00:15:12 +0200 Subject: [PATCH 016/150] Init topic creation and view --- .../public/locales/en/translation.json | 7 +- packages/concordia-app/src/Routes.jsx | 12 +- .../src/views/Topic/TopicCreate/index.jsx | 166 ++++++++++++++++++ .../src/views/Topic/TopicCreate/styles.css | 6 + .../src/views/Topic/TopicView/index.jsx | 18 ++ .../concordia-app/src/views/Topic/index.jsx | 19 ++ 6 files changed, 226 insertions(+), 2 deletions(-) create mode 100644 packages/concordia-app/src/views/Topic/TopicCreate/index.jsx create mode 100644 packages/concordia-app/src/views/Topic/TopicCreate/styles.css create mode 100644 packages/concordia-app/src/views/Topic/TopicView/index.jsx create mode 100644 packages/concordia-app/src/views/Topic/index.jsx diff --git a/packages/concordia-app/public/locales/en/translation.json b/packages/concordia-app/public/locales/en/translation.json index 29db84c..c55754f 100644 --- a/packages/concordia-app/public/locales/en/translation.json +++ b/packages/concordia-app/public/locales/en/translation.json @@ -14,5 +14,10 @@ "register.p.account.address": "Account address:", "topbar.button.create.topic": "Create topic", "topbar.button.profile": "Profile", - "topbar.button.register": "Sign Up" + "topbar.button.register": "Sign Up", + "topic.create.form.subject.field.label": "Topic subject", + "topic.create.form.subject.field.placeholder": "Subject", + "topic.create.form.message.field.label": "First post message", + "topic.create.form.message.field.placeholder": "Message", + "topic.create.form.post.button": "Post" } \ No newline at end of file diff --git a/packages/concordia-app/src/Routes.jsx b/packages/concordia-app/src/Routes.jsx index 3363d93..9931cfa 100644 --- a/packages/concordia-app/src/Routes.jsx +++ b/packages/concordia-app/src/Routes.jsx @@ -5,6 +5,11 @@ import LoadingScreen from './components/LoadingScreen'; import RegisterLayout from './layouts/RegisterLayout'; const routesConfig = [ + { + exact: true, + path: '/', + component: () => , + }, { exact: true, path: '/404', @@ -31,9 +36,14 @@ const routesConfig = [ routes: [ { exact: true, - path: '/', + path: '/home', component: lazy(() => import('./views/Home')), }, + { + exact: true, + path: '/topics/:id(\\bnew\\b|\\d+)', + component: lazy(() => import('./views/Topic')), + }, { component: () => , }, diff --git a/packages/concordia-app/src/views/Topic/TopicCreate/index.jsx b/packages/concordia-app/src/views/Topic/TopicCreate/index.jsx new file mode 100644 index 0000000..70e2c9a --- /dev/null +++ b/packages/concordia-app/src/views/Topic/TopicCreate/index.jsx @@ -0,0 +1,166 @@ +import React, { + useCallback, useContext, useEffect, useState, +} from 'react'; +import { + Button, Container, Form, Icon, Input, TextArea, +} from 'semantic-ui-react'; +import { useTranslation } from 'react-i18next'; +import { useHistory } from 'react-router'; +import { useSelector } from 'react-redux'; +import AppContext from '../../../components/AppContext'; +import './styles.css'; + +const TopicCreate = (props) => { + const { account } = props; + + const { + drizzle: { + contracts: { + Forum: { + methods: { createTopic }, + }, + }, + }, + } = useContext(AppContext.Context); + + const orbit = useSelector((state) => state.orbit); + const transactionStack = useSelector((state) => state.transactionStack); + const transactions = useSelector((state) => state.transactions); + + const [subjectInput, setSubjectInput] = useState(''); + const [messageInput, setMessageInput] = useState(''); + const [topicSubjectInputEmptySubmit, setTopicSubjectInputEmptySubmit] = useState(false); + const [topicMessageInputEmptySubmit, setTopicMessageInputEmptySubmit] = useState(false); + const [createTopicCacheSendStackId, setCreateTopicCacheSendStackId] = useState(''); + const [posting, setPosting] = useState(false); + + const history = useHistory(); + const { t } = useTranslation(); + + const handleSubjectInputChange = useCallback((event) => { + if (posting) { + return; + } + + switch (event.target.name) { + case 'subjectInput': + setSubjectInput(event.target.value); + break; + case 'messageInput': + setMessageInput(event.target.value); + break; + default: + break; + } + }, [posting]); + + useEffect(() => { + if (posting && transactionStack && transactionStack[createTopicCacheSendStackId] + && transactions[transactionStack[createTopicCacheSendStackId]]) { + if (transactions[transactionStack[createTopicCacheSendStackId]].status === 'error') { + setPosting(false); + } else if (transactions[transactionStack[createTopicCacheSendStackId]].status === 'success') { + const { + receipt: { + events: { + TopicCreated: { + returnValues: { + topicID: topicId, + postID: postId, + }, + }, + }, + }, + } = transactions[transactionStack[createTopicCacheSendStackId]]; + + // Promise.all( + // orbit.topicsDB + // .put(topicId, { subject: subjectInput }), + // orbit.postsDB + // .put(postId, { + // subject: subjectInput, + // content: messageInput, + // }), + // ).then((value) => { + // console.log(value); + // history.push('/'); + // }) + // .catch((reason) => console.log(reason)); + } + } + }, [ + transactions, transactionStack, history, posting, createTopicCacheSendStackId, orbit, subjectInput, messageInput, + ]); + + const validateAndPost = useCallback(() => { + if (subjectInput === '') { + setTopicSubjectInputEmptySubmit(true); + return; + } + + if (messageInput === '') { + setTopicMessageInputEmptySubmit(true); + return; + } + + setPosting(true); + setCreateTopicCacheSendStackId(createTopic.cacheSend(...[], { from: account })); + }, [account, createTopic, messageInput, subjectInput]); + + return ( + +
    + + + + + + +