From f4b4416ea52d564bc2dbe543a82084ed98843ccc Mon Sep 17 00:00:00 2001 From: Markus Hatvan Date: Fri, 30 Jul 2021 10:54:54 +0200 Subject: chore: migrate from tslint to @typescript-eslint (#1706) - update .eslintrc to work for .js and .ts - update devDependencies - lint properly both root /src and nested /packages - update webhint recommended setting for tsconfig.json to shrink output - Manage all eslint rules from the repo root - escape single quotes in scripts to please windows build Co-authored-by: Vijay A --- .eslintignore | 3 +- .eslintrc | 163 +++++--- package-lock.json | 439 ++++++--------------- package.json | 11 +- packages/forms/src/button/index.tsx | 29 +- packages/forms/src/error/index.tsx | 13 +- packages/forms/src/input/index.tsx | 63 ++- packages/forms/src/input/scorePassword.ts | 6 +- packages/forms/src/label/index.tsx | 13 +- packages/forms/src/select/index.tsx | 119 +++--- packages/forms/src/textarea/index.tsx | 22 +- packages/forms/src/toggle/index.tsx | 2 +- packages/forms/src/wrapper/index.tsx | 9 +- packages/forms/tslint.json | 3 - packages/theme/src/index.ts | 12 +- packages/theme/src/themes/IStyleTypes.ts | 1 - packages/theme/src/themes/dark/index.ts | 30 +- packages/theme/src/themes/default/index.ts | 14 +- packages/theme/tslint.json | 3 - packages/typings/types/react-loader.d.ts | 2 +- packages/ui/src/badge/ProBadge.tsx | 11 +- packages/ui/src/badge/index.tsx | 9 +- packages/ui/src/headline/index.tsx | 15 +- packages/ui/src/icon/index.tsx | 7 +- packages/ui/src/infobox/index.tsx | 49 +-- packages/ui/src/loader/index.tsx | 10 +- packages/ui/tslint.json | 3 - src/actions/lib/actions.js | 4 +- src/api/server/LocalApi.js | 20 +- src/api/server/ServerApi.js | 288 ++++++++------ src/app.js | 8 +- src/components/auth/AuthLayout.js | 28 +- src/components/auth/ChangeServer.js | 4 +- src/components/auth/Locked.js | 2 +- src/components/auth/Login.js | 2 +- src/components/auth/Password.js | 2 +- src/components/auth/SetupAssistant.js | 10 +- src/components/auth/Signup.js | 2 +- src/components/auth/Welcome.js | 2 +- src/components/layout/AppLayout.js | 4 +- .../services/content/ConnectionLostBanner.js | 2 +- .../services/content/ErrorHandlers/styles.js | 2 +- src/components/services/content/Services.js | 2 +- .../services/content/WebviewCrashHandler.js | 2 +- src/components/services/tabs/Tabbar.js | 10 +- .../settings/services/EditServiceForm.js | 2 +- .../settings/services/ServicesDashboard.js | 4 +- .../settings/settings/EditSettingsForm.js | 23 +- .../settings/supportFerdi/SupportFerdiDashboard.js | 18 +- src/components/settings/user/EditUserForm.js | 2 +- src/components/ui/AppLoader/index.js | 2 +- src/components/ui/FeatureItem.js | 2 +- src/components/ui/FeatureList.js | 2 +- src/components/ui/Link.js | 2 +- src/components/ui/Modal/styles.js | 2 +- src/components/ui/Radio.js | 2 +- src/components/ui/SearchInput.js | 2 +- src/components/ui/Select.js | 4 +- src/components/ui/ServiceIcon.js | 2 +- src/components/ui/Slider.js | 2 +- src/components/ui/Tabs/TabItem.js | 8 +- src/components/ui/Tabs/Tabs.js | 2 +- src/components/ui/Toggle.js | 2 +- src/components/ui/ToggleRaw.js | 2 +- src/components/ui/WebviewLoader/styles.js | 2 +- src/components/util/ErrorBoundary/styles.js | 2 +- src/containers/auth/SetupAssistantScreen.js | 2 +- src/containers/auth/SignupScreen.js | 2 +- src/containers/layout/AppLayoutContainer.js | 4 +- src/containers/settings/AccountScreen.js | 5 +- src/containers/settings/EditServiceScreen.js | 4 +- src/containers/settings/EditSettingsScreen.js | 2 +- src/containers/settings/EditUserScreen.js | 2 +- src/containers/settings/RecipesScreen.js | 10 +- .../announcements/components/AnnouncementScreen.js | 2 +- src/features/communityRecipes/store.js | 2 +- src/features/publishDebugInfo/Component.js | 6 +- src/features/quickSwitch/Component.js | 4 +- src/features/shareFranz/Component.js | 2 +- src/features/todos/containers/TodosScreen.js | 4 +- src/features/utils/ActionBinding.js | 4 +- src/features/utils/FeatureStore.js | 8 +- src/features/webControls/components/WebControls.js | 4 +- .../webControls/containers/WebControlsScreen.js | 2 +- src/features/workspaces/api.js | 2 +- .../workspaces/components/WorkspaceDrawer.js | 2 +- .../workspaces/components/WorkspaceDrawerItem.js | 2 +- .../workspaces/components/WorkspaceItem.js | 2 +- .../components/WorkspaceServiceListItem.js | 2 +- .../components/WorkspaceSwitchingIndicator.js | 2 +- .../workspaces/components/WorkspacesDashboard.js | 4 +- .../workspaces/containers/WorkspacesScreen.js | 4 +- src/features/workspaces/models/Workspace.js | 4 +- src/helpers/array-helpers.js | 6 +- src/helpers/async-helpers.js | 2 +- src/helpers/service-helpers.js | 2 +- src/helpers/validation-helpers.js | 2 +- src/models/Recipe.js | 2 +- src/models/Service.js | 2 +- src/models/UserAgent.js | 4 +- src/stores/AppStore.js | 105 +++-- src/stores/NewsStore.js | 2 +- src/stores/RecipePreviewsStore.js | 2 +- src/stores/RecipesStore.js | 8 +- src/stores/ServicesStore.js | 44 +-- src/stores/UIStore.js | 2 +- src/stores/UserStore.js | 4 +- src/stores/lib/CachedRequest.js | 4 +- src/stores/lib/Reaction.js | 4 +- src/stores/lib/Request.js | 2 +- src/stores/lib/Store.js | 6 +- src/webview/contextMenuBuilder.js | 4 +- src/webview/lib/RecipeWebview.js | 2 +- src/webview/notifications.js | 2 +- src/webview/spellchecker.js | 2 +- tsconfig.settings.json | 3 + tslint.json | 12 - uidev/src/app.tsx | 2 +- uidev/src/stores/stories.ts | 2 - uidev/src/stories/button.stories.tsx | 72 ++-- uidev/src/stories/headline.stories.tsx | 3 - uidev/src/stories/infobox.stories.tsx | 10 +- uidev/src/stories/input.stories.tsx | 4 +- uidev/src/stories/loader.stories.tsx | 3 - uidev/src/stories/select.stories.tsx | 2 +- uidev/src/stories/textarea.stories.tsx | 2 +- uidev/src/stories/toggle.stories.tsx | 19 +- uidev/src/withTheme/index.tsx | 16 +- uidev/tslint.json | 3 - 129 files changed, 964 insertions(+), 1039 deletions(-) delete mode 100644 packages/forms/tslint.json delete mode 100644 packages/theme/tslint.json delete mode 100644 packages/ui/tslint.json delete mode 100644 tslint.json delete mode 100644 uidev/tslint.json diff --git a/.eslintignore b/.eslintignore index 52fde4c3e..5385bbb5f 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,5 +1,6 @@ build/ out/ packages/*/lib +packages/**/*.test.* src/internal-server -recipes/ \ No newline at end of file +recipes/ diff --git a/.eslintrc b/.eslintrc index 668f688ae..5e8d4cebf 100644 --- a/.eslintrc +++ b/.eslintrc @@ -3,71 +3,124 @@ "parser": "@babel/eslint-parser", "extends": "eslint-config-airbnb", "plugins": ["jest"], - "rules": { - "arrow-parens": 0, - "consistent-return": 0, - "no-param-reassign": 0, - "import/extensions": 0, - "import/no-extraneous-dependencies": 0, - "import/no-unresolved": [ - 2, - { - "ignore": ["electron"] - } - ], - "import/prefer-default-export": 0, - "linebreak-style": 0, - "react/static-property-placement": 0, - "react/state-in-constructor": 0, - "react/jsx-props-no-spreading": 0, - "react/prefer-stateless-function": 0, - "react/jsx-filename-extension": [ - 1, - { - "extensions": [".js", ".jsx"] - } - ], - "react/forbid-prop-types": 0, - "react/destructuring-assignment": 0, - "prefer-destructuring": 1, - "no-underscore-dangle": 0, - "max-len": 0, - "class-methods-use-this": 0, - "no-console": 0, - "react/jsx-no-bind": 0, - "react/sort-comp": 0, - "jsx-a11y/no-static-element-interactions": 0, - "react/jsx-no-target-blank": 0, - "no-restricted-syntax": [0, "ForInStatement"], - "jsx-a11y/no-noninteractive-element-interactions": 1, - "jsx-a11y/label-has-for": [ - 2, - { - "components": ["Label"], - "required": { - "every": ["id"] - }, - "allowChildren": false + "overrides": [ + { + "files": ["**/*.ts", "**/*.tsx"], + "env": { "browser": true, "es6": true, "node": true }, + "extends": ["airbnb-typescript"], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaFeatures": { "jsx": true }, + "ecmaVersion": 2018, + "sourceType": "module", + "project": "./tsconfig.json" + }, + "plugins": ["@typescript-eslint"], + "rules": { + // eslint + "arrow-parens": 0, + "array-callback-return": 1, + "class-methods-use-this": 0, + "consistent-return": 0, + "implicit-arrow-linebreak": 0, + "linebreak-style": 0, + "max-len": 0, + "no-confusing-arrow": 0, + "no-console": 0, + "no-param-reassign": 0, + "no-return-assign": 1, + "no-underscore-dangle": 0, + "no-use-before-define": 0, + "prefer-destructuring": 1, + "object-curly-newline": 0, + "operator-linebreak": 0, + // @typescript-eslint + "@typescript-eslint/indent": 0, + "@typescript-eslint/no-shadow": 0, + "@typescript-eslint/no-unused-expressions": 0, + // eslint-plugin-import + "import/extensions": 0, + "import/no-cycle": 1, + "import/no-extraneous-dependencies": 0, + "import/no-unresolved": 0, + "import/prefer-default-export": 0, + // eslint-plugin-react + "react/destructuring-assignment": 0, + "react/button-has-type": 0, + "react/forbid-prop-types": 0, + "react/jsx-curly-newline": 0, + "react/jsx-no-bind": 0, + "react/jsx-no-target-blank": 0, + "react/jsx-props-no-spreading": 0, + "react/no-deprecated": 1, + "react/no-array-index-key": 0, + "react/prefer-stateless-function": 0, + "react/sort-comp": 0, + "react/state-in-constructor": 0, + "react/static-property-placement": 0, + // eslint-plugin-jsx-a11y + "jsx-a11y/click-events-have-key-events": 1, + "jsx-a11y/mouse-events-have-key-events": 1, + "jsx-a11y/label-has-for": [ + 2, + { + "components": ["Label"], + "required": { + "every": ["id"] + }, + "allowChildren": false + } + ], + "jsx-a11y/no-static-element-interactions": 0, + "jsx-a11y/no-noninteractive-element-interactions": 1 } - ], - "jsx-a11y/click-events-have-key-events": 1 + } + ], + "settings": { + "react": { + "pragma": "React", // Pragma to use, default to "React" + "version": "detect" // React version. "detect" automatically picks the version you have installed. + } }, "globals": { "window": true, "document": true, - "ENV": true, "FormData": true, "localStorage": true, "navigator": true, - "Worker": true, - "atob": true, - "btoa": true, - "ga": true, - "mocha": true, - "Element": true, - "electron": true + "Element": true }, "env": { "jest/globals": true + }, + "rules": { + // eslint + "prefer-destructuring": 1, + "class-methods-use-this": 1, + "consistent-return": 1, + "max-len": 0, + "no-param-reassign": 1, + "no-restricted-syntax": 0, + "no-underscore-dangle": 0, + "operator-linebreak": 0, + // eslint-plugin-import + "import/extensions": 1, + "import/prefer-default-export": 0, + "import/no-extraneous-dependencies": 1, + "import/no-unresolved": 1, + // eslint-plugin-react + "react/forbid-prop-types": 1, + "react/destructuring-assignment": 0, + "react/jsx-filename-extension": 1, + "react/jsx-no-bind": 1, + "react/jsx-props-no-spreading": 0, + "react/prefer-stateless-function": 1, + "react/static-property-placement": 0, + "react/state-in-constructor": 1, + "react/sort-comp": 0, + // eslint-plugin-jsx-a11y + "jsx-a11y/click-events-have-key-events": 1, + "jsx-a11y/no-static-element-interactions": 1, + "jsx-a11y/no-noninteractive-element-interactions": 1 } } diff --git a/package-lock.json b/package-lock.json index 45c38f01b..cb80ba47a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3526,46 +3526,6 @@ } } }, - "@fimbul/bifrost": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/@fimbul/bifrost/-/bifrost-0.21.0.tgz", - "integrity": "sha512-ou8VU+nTmOW1jeg+FT+sn+an/M0Xb9G16RucrfhjXGWv1Q97kCoM5CG9Qj7GYOSdu7km72k7nY83Eyr53Bkakg==", - "dev": true, - "requires": { - "@fimbul/ymir": "^0.21.0", - "get-caller-file": "^2.0.0", - "tslib": "^1.8.1", - "tsutils": "^3.5.0" - }, - "dependencies": { - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "tsutils": { - "version": "3.17.1", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", - "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - } - } - }, - "@fimbul/ymir": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/@fimbul/ymir/-/ymir-0.21.0.tgz", - "integrity": "sha512-T/y7WqPsm4n3zhT08EpB5sfdm2Kvw3gurAxr2Lr5dQeLi8ZsMlNT/Jby+ZmuuAAd1PnXYzKp+2SXgIkQIIMCUg==", - "dev": true, - "requires": { - "inversify": "^5.0.0", - "reflect-metadata": "^0.1.12", - "tslib": "^1.8.1" - } - }, "@hapi/address": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz", @@ -8175,22 +8135,6 @@ "@types/ms": "*" } }, - "@types/eslint": { - "version": "7.2.13", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.13.tgz", - "integrity": "sha512-LKmQCWAlnVHvvXq4oasNUMTJJb2GwSyTY8+1C7OH5ILR8mPLaljv1jxL1bXW3xB3jFbQxTKxJAvI8PyjB09aBg==", - "dev": true, - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/estree": { - "version": "0.0.48", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.48.tgz", - "integrity": "sha512-LfZwXoGUDo0C3me81HXgkBg5CTQYb6xzEl+fNmbO4JdRiSKQ8A0GD1OBBvKAIsbCUgoyAty7m99GqqMQe784ew==", - "dev": true - }, "@types/events": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", @@ -8484,6 +8428,38 @@ "integrity": "sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==", "dev": true }, + "@typescript-eslint/eslint-plugin": { + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.5.tgz", + "integrity": "sha512-m31cPEnbuCqXtEZQJOXAHsHvtoDi9OVaeL5wZnO2KZTnkvELk+u6J6jHg+NzvWQxk+87Zjbc4lJS4NHmgImz6Q==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "4.28.5", + "@typescript-eslint/scope-manager": "4.28.5", + "debug": "^4.3.1", + "functional-red-black-tree": "^1.0.1", + "regexpp": "^3.1.0", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, "@typescript-eslint/experimental-utils": { "version": "4.28.5", "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.5.tgz", @@ -8536,6 +8512,35 @@ } } }, + "@typescript-eslint/parser": { + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.5.tgz", + "integrity": "sha512-NPCOGhTnkXGMqTznqgVbA5LqVsnw+i3+XA1UKLnAb+MG1Y1rP4ZSK9GX0kJBmAZTMIktf+dTwXToT6kFwyimbw==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "4.28.5", + "@typescript-eslint/types": "4.28.5", + "@typescript-eslint/typescript-estree": "4.28.5", + "debug": "^4.3.1" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, "@typescript-eslint/scope-manager": { "version": "4.28.5", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.5.tgz", @@ -11698,12 +11703,6 @@ } } }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, "builtin-status-codes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", @@ -16965,6 +16964,23 @@ } } }, + "eslint-config-airbnb-typescript": { + "version": "12.3.1", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-typescript/-/eslint-config-airbnb-typescript-12.3.1.tgz", + "integrity": "sha512-ql/Pe6/hppYuRp4m3iPaHJqkBB7dgeEmGPQ6X0UNmrQOfTF+dXw29/ZjU2kQ6RDoLxaxOA+Xqv07Vbef6oVTWw==", + "dev": true, + "requires": { + "@typescript-eslint/parser": "^4.4.1", + "eslint-config-airbnb": "^18.2.0", + "eslint-config-airbnb-base": "^14.2.0" + } + }, + "eslint-config-prettier": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", + "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", + "dev": true + }, "eslint-import-resolver-node": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", @@ -17237,6 +17253,15 @@ } } }, + "eslint-plugin-prettier": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.0.tgz", + "integrity": "sha512-UDK6rJT6INSfcOo545jiaOwB701uAIt2/dR7WnFQoGCVl1/EMqdANBmwUaqqQ45aXprsTGzSa39LI1PyuRBxxw==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, "eslint-plugin-react": { "version": "7.24.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.24.0.tgz", @@ -17289,6 +17314,12 @@ } } }, + "eslint-plugin-react-hooks": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz", + "integrity": "sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ==", + "dev": true + }, "eslint-scope": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", @@ -17322,120 +17353,6 @@ "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", "dev": true }, - "eslint-webpack-plugin": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-2.5.4.tgz", - "integrity": "sha512-7rYh0m76KyKSDE+B+2PUQrlNS4HJ51t3WKpkJg6vo2jFMbEPTG99cBV0Dm7LXSHucN4WGCG65wQcRiTFrj7iWw==", - "dev": true, - "requires": { - "@types/eslint": "^7.2.6", - "arrify": "^2.0.1", - "jest-worker": "^26.6.2", - "micromatch": "^4.0.2", - "normalize-path": "^3.0.0", - "schema-utils": "^3.0.0" - }, - "dependencies": { - "arrify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", - "dev": true - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "jest-worker": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", - "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" - } - }, - "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", - "dev": true - }, - "schema-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", - "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.6", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - } - } - }, "espree": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", @@ -17927,6 +17844,12 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, "fast-glob": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", @@ -22075,12 +21998,6 @@ "loose-envify": "^1.0.0" } }, - "inversify": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/inversify/-/inversify-5.0.1.tgz", - "integrity": "sha512-Ieh06s48WnEYGcqHepdsJUIJUXpwH5o5vodAX+DK2JA/gjy4EbEcQZxw+uFfzysmKjiLXGYwNG3qDZsKVMcINQ==", - "dev": true - }, "invert-kv": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", @@ -30130,6 +30047,15 @@ "integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==", "dev": true }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, "pretty-bytes": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", @@ -31734,12 +31660,6 @@ } } }, - "reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", - "dev": true - }, "regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -34842,152 +34762,15 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" }, - "tslint": { - "version": "5.20.1", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", - "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.8.0", - "tsutils": "^2.29.0" - }, - "dependencies": { - "diff": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz", - "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==", - "dev": true - }, - "js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "tslint-config-airbnb": { - "version": "5.11.2", - "resolved": "https://registry.npmjs.org/tslint-config-airbnb/-/tslint-config-airbnb-5.11.2.tgz", - "integrity": "sha512-mUpHPTeeCFx8XARGG/kzYP4dPSOgoCqNiYbGHh09qTH8q+Y1ghsOgaeZKYYQT7IyxMos523z/QBaiv2zKNBcow==", - "dev": true, - "requires": { - "tslint-consistent-codestyle": "^1.14.1", - "tslint-eslint-rules": "^5.4.0", - "tslint-microsoft-contrib": "~5.2.1" - } - }, - "tslint-consistent-codestyle": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/tslint-consistent-codestyle/-/tslint-consistent-codestyle-1.16.0.tgz", - "integrity": "sha512-ebR/xHyMEuU36hGNOgCfjGBNYxBPixf0yU1Yoo6s3BrpBRFccjPOmIVaVvQsWAUAMdmfzHOCihVkcaMfimqvHw==", - "dev": true, - "requires": { - "@fimbul/bifrost": "^0.21.0", - "tslib": "^1.7.1", - "tsutils": "^2.29.0" - } - }, - "tslint-eslint-rules": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/tslint-eslint-rules/-/tslint-eslint-rules-5.4.0.tgz", - "integrity": "sha512-WlSXE+J2vY/VPgIcqQuijMQiel+UtmXS+4nvK4ZzlDiqBfXse8FAvkNnTcYhnQyOTW5KFM+uRRGXxYhFpuBc6w==", - "dev": true, - "requires": { - "doctrine": "0.7.2", - "tslib": "1.9.0", - "tsutils": "^3.0.0" - }, - "dependencies": { - "doctrine": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-0.7.2.tgz", - "integrity": "sha1-fLhgNZujvpDgQLJrcpzkv6ZUxSM=", - "dev": true, - "requires": { - "esutils": "^1.1.6", - "isarray": "0.0.1" - } - }, - "esutils": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz", - "integrity": "sha1-wBzKqa5LiXxtDD4hCuUvPHqEQ3U=", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "tslib": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz", - "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==", - "dev": true - }, - "tsutils": { - "version": "3.17.1", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", - "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - } - } - }, - "tslint-microsoft-contrib": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/tslint-microsoft-contrib/-/tslint-microsoft-contrib-5.2.1.tgz", - "integrity": "sha512-PDYjvpo0gN9IfMULwKk0KpVOPMhU6cNoT9VwCOLeDl/QS8v8W2yspRpFFuUS7/c5EIH/n8ApMi8TxJAz1tfFUA==", - "dev": true, - "requires": { - "tsutils": "^2.27.2 <2.29.0" - }, - "dependencies": { - "tsutils": { - "version": "2.28.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.28.0.tgz", - "integrity": "sha512-bh5nAtW0tuhvOJnx1GLRn5ScraRLICGyJV5wJhtRWOLsxW70Kk5tZtpK3O/hW6LDnqKS9mlUMPZj9fEMJ0gxqA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - } - } - }, "tsscmp": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==" }, "tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, "requires": { "tslib": "^1.8.1" diff --git a/package.json b/package.json index 524a445f1..6bc86ea6d 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "dev": "cross-env NODE_ENV=development gulp dev", "test": "jest", "test:watch": "jest --watch", - "lint": "eslint --quiet --fix src", + "lint": "eslint \"{src,packages,uidev}/**/*.{js,jsx,ts,tsx}\" --quiet --fix", "manage-translations": "node ./src/i18n/manage-translations.js", "prebuild": "preval-build-info-cli && gulp build", "build": "electron-builder", @@ -156,6 +156,8 @@ "@types/react": "16.14.6", "@types/react-dom": "16.9.13", "@types/uuid": "3.4.9", + "@typescript-eslint/eslint-plugin": "4.28.5", + "@typescript-eslint/parser": "4.28.5", "all-contributors-cli": "6.20.0", "babel-loader": "8.2.2", "babel-plugin-react-intl": "3.5.1", @@ -169,11 +171,14 @@ "electron-rebuild": "2.3.5", "eslint": "7.31.0", "eslint-config-airbnb": "18.2.1", + "eslint-config-airbnb-typescript": "12.3.1", + "eslint-config-prettier": "8.3.0", "eslint-plugin-import": "2.23.4", "eslint-plugin-jest": "24.4.0", "eslint-plugin-jsx-a11y": "6.4.1", + "eslint-plugin-prettier": "3.4.0", "eslint-plugin-react": "7.24.0", - "eslint-webpack-plugin": "2.5.4", + "eslint-plugin-react-hooks": "4.2.0", "expect.js": "0.3.1", "gulp": "4.0.0", "gulp-babel": "8.0.0", @@ -196,8 +201,6 @@ "sass": "1.36.0", "terser-webpack-plugin": "1.4.5", "ts-loader": "5.4.5", - "tslint": "5.20.1", - "tslint-config-airbnb": "5.11.2", "typescript": "3.9.10", "webpack": "4.46.0", "webpack-cli": "3.3.12", diff --git a/packages/forms/src/button/index.tsx b/packages/forms/src/button/index.tsx index ecb2876ca..c08c4e97d 100644 --- a/packages/forms/src/button/index.tsx +++ b/packages/forms/src/button/index.tsx @@ -8,14 +8,24 @@ import Loader from 'react-loader'; import { IFormField, IWithStyle } from '../typings/generic'; import { Theme } from '../../../theme'; -type ButtonType = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'inverted'; +type ButtonType = + | 'primary' + | 'secondary' + | 'success' + | 'danger' + | 'warning' + | 'inverted'; interface IProps extends IFormField, IWithStyle { className?: string; disabled?: boolean; id?: string; type?: 'button' | 'reset' | 'submit' | undefined; - onClick: (event: React.MouseEvent | React.MouseEvent) => void; + onClick: ( + event: + | React.MouseEvent + | React.MouseEvent, + ) => void; buttonType?: ButtonType; stretch?: boolean; loaded?: boolean; @@ -25,10 +35,6 @@ interface IProps extends IFormField, IWithStyle { target?: string; } -interface IState { - busy: boolean; -} - const styles = (theme: Theme) => ({ button: { borderRadius: theme.borderRadiusSmall, @@ -40,7 +46,8 @@ const styles = (theme: Theme) => ({ outline: 'none', alignItems: 'center', padding: 0, - width: (props: IProps) => (props.stretch ? '100%' : 'auto') as Property.Width, + width: (props: IProps) => + (props.stretch ? '100%' : 'auto') as Property.Width, fontSize: theme.uiFontSize, textDecoration: 'none', // height: theme.buttonHeight, @@ -125,7 +132,8 @@ const styles = (theme: Theme) => ({ transition: 'all 0.3s', marginLeft: (props: IProps): number => (!props.busy ? 10 : 20), marginRight: (props: IProps): number => (!props.busy ? -10 : -20), - position: (props: IProps): Property.Position => props.stretch ? 'absolute' : 'inherit', + position: (props: IProps): Property.Position => + props.stretch ? 'absolute' : 'inherit', }, icon: { margin: [1, 10, 0, -5], @@ -175,7 +183,6 @@ class ButtonComponent extends Component { buttonType, loaded, icon, - busy: busyProp, href, target, } = this.props; @@ -185,7 +192,9 @@ class ButtonComponent extends Component { let showLoader = false; if (loaded) { showLoader = !loaded; - console.warn('Ferdi Button prop `loaded` will be deprecated in the future. Please use `busy` instead'); + console.warn( + 'Ferdi Button prop `loaded` will be deprecated in the future. Please use `busy` instead', + ); } if (busy) { showLoader = busy; diff --git a/packages/forms/src/error/index.tsx b/packages/forms/src/error/index.tsx index a487bb281..243321d97 100644 --- a/packages/forms/src/error/index.tsx +++ b/packages/forms/src/error/index.tsx @@ -11,18 +11,9 @@ interface IProps { class ErrorComponent extends Component { render() { - const { - classes, - message, - } = this.props; + const { classes, message } = this.props; - return ( -

- {message} -

- ); + return

{message}

; } } diff --git a/packages/forms/src/input/index.tsx b/packages/forms/src/input/index.tsx index b96dbc12d..41751710a 100644 --- a/packages/forms/src/input/index.tsx +++ b/packages/forms/src/input/index.tsx @@ -17,7 +17,10 @@ interface IData { [index: string]: string; } -interface IProps extends React.InputHTMLAttributes, IFormField, IWithStyle { +interface IProps + extends React.InputHTMLAttributes, + IFormField, + IWithStyle { focus?: boolean; prefix?: string; suffix?: string; @@ -62,23 +65,24 @@ class InputComponent extends Component { } if (data) { - Object.keys(data).map(key => this.inputRef.current!.dataset[key] = data[key]); + Object.keys(data).map( + key => (this.inputRef.current!.dataset[key] = data[key]), + ); } } } onChange(e: React.ChangeEvent) { - const { - scorePassword, - onChange, - } = this.props; + const { scorePassword, onChange } = this.props; if (onChange) { onChange(e); } if (this.inputRef && this.inputRef.current && scorePassword) { - this.setState({ passwordScore: scorePasswordFunc(this.inputRef.current.value) }); + this.setState({ + passwordScore: scorePasswordFunc(this.inputRef.current.value), + }); } } @@ -117,10 +121,7 @@ class InputComponent extends Component { noMargin, } = this.props; - const { - showPassword, - passwordScore, - } = this.state; + const { showPassword, passwordScore } = this.state; const inputType = type === 'password' && showPassword ? 'text' : type; @@ -144,12 +145,9 @@ class InputComponent extends Component { [`${classes.wrapper}`]: true, [`${classes.disabled}`]: disabled, [`${classes.hasError}`]: error, - })}> - {prefix && ( - - {prefix} - - )} + })} + > + {prefix && {prefix}} { max={max} step={step} /> - {suffix && ( - - {suffix} - - )} + {suffix && {suffix}} {showPasswordToggle && ( )} {scorePassword && ( -
+
{
)} - {error && ( - - )} + {error && } ); } diff --git a/packages/forms/src/input/scorePassword.ts b/packages/forms/src/input/scorePassword.ts index 0b7719ec1..bc30de4b8 100644 --- a/packages/forms/src/input/scorePassword.ts +++ b/packages/forms/src/input/scorePassword.ts @@ -11,7 +11,7 @@ interface IVariations { } export function scorePasswordFunc(password: string): number { - let score: number = 0; + let score = 0; if (!password) { return score; } @@ -32,8 +32,8 @@ export function scorePasswordFunc(password: string): number { }; let variationCount = 0; - Object.keys(variations).forEach((key) => { - variationCount += (variations[key] === true) ? 1 : 0; + Object.keys(variations).forEach(key => { + variationCount += variations[key] === true ? 1 : 0; }); score += (variationCount - 1) * 10; diff --git a/packages/forms/src/label/index.tsx b/packages/forms/src/label/index.tsx index 1b33ba22c..ad503b785 100644 --- a/packages/forms/src/label/index.tsx +++ b/packages/forms/src/label/index.tsx @@ -7,7 +7,9 @@ import { IFormField } from '../typings/generic'; import styles from './styles'; -interface ILabel extends IFormField, React.LabelHTMLAttributes { +interface ILabel + extends IFormField, + React.LabelHTMLAttributes { classes: Classes; isRequired: boolean; } @@ -38,11 +40,12 @@ class LabelComponent extends Component { htmlFor={htmlFor} > {showLabel && ( - {title}{isRequired && ' *'} + + {title} + {isRequired && ' *'} + )} -
- {children} -
+
{children}
); } diff --git a/packages/forms/src/select/index.tsx b/packages/forms/src/select/index.tsx index e5b59cb19..4a5775579 100644 --- a/packages/forms/src/select/index.tsx +++ b/packages/forms/src/select/index.tsx @@ -1,4 +1,8 @@ -import { mdiArrowRightDropCircleOutline, mdiCloseCircle, mdiMagnify } from '@mdi/js'; +import { + mdiArrowRightDropCircleOutline, + mdiCloseCircle, + mdiMagnify, +} from '@mdi/js'; import Icon from '@mdi/react'; import classnames from 'classnames'; import React, { Component, createRef } from 'react'; @@ -58,7 +62,7 @@ const styles = (theme: Theme) => ({ label: { '& > div': { marginTop: 5, - } + }, }, popup: { opacity: 0, @@ -153,9 +157,13 @@ class SelectComponent extends Component { }; private componentRef = createRef(); + private inputRef = createRef(); + private searchInputRef = createRef(); + private scrollContainerRef = createRef(); + private activeOptionRef = createRef(); private keyListener: any; @@ -168,7 +176,7 @@ class SelectComponent extends Component { } } - componentDidUpdate(prevProps: IProps, prevState: IState) { + componentDidUpdate() { const { open } = this.state; if (this.searchInputRef && this.searchInputRef.current) { @@ -183,7 +191,9 @@ class SelectComponent extends Component { const { data } = this.props; if (data) { - Object.keys(data).map(key => this.inputRef.current!.dataset[key] = data[key]); + Object.keys(data).map( + key => (this.inputRef.current!.dataset[key] = data[key]), + ); } } @@ -194,7 +204,10 @@ class SelectComponent extends Component { const { value } = this.props; if (this.componentRef && this.componentRef.current) { - this.componentRef.current.removeEventListener('keydown', this.keyListener); + this.componentRef.current.removeEventListener( + 'keydown', + this.keyListener, + ); } if (value) { @@ -210,13 +223,18 @@ class SelectComponent extends Component { window.removeEventListener('keydown', this.arrowKeysHandler.bind(this)); } - setFilter(needle: string = '') { + setFilter(needle = '') { const { options } = this.props; let filteredOptions = {}; if (needle) { - Object.keys(options).map((key) => { - if (key.toLocaleLowerCase().startsWith(needle.toLocaleLowerCase()) || options[key].toLocaleLowerCase().startsWith(needle.toLocaleLowerCase())) { + Object.keys(options).map(key => { + if ( + key.toLocaleLowerCase().startsWith(needle.toLocaleLowerCase()) || + options[key] + .toLocaleLowerCase() + .startsWith(needle.toLocaleLowerCase()) + ) { Object.assign(filteredOptions, { [`${key}`]: options[key], }); @@ -234,7 +252,7 @@ class SelectComponent extends Component { } select(key: string) { - this.setState((state: IState) => ({ + this.setState(() => ({ value: key, open: false, })); @@ -247,11 +265,7 @@ class SelectComponent extends Component { } arrowKeysHandler(e: KeyboardEvent) { - const { - selected, - open, - options, - } = this.state; + const { selected, open, options } = this.state; if (!open) return; @@ -264,7 +278,10 @@ class SelectComponent extends Component { this.setState((state: IState) => ({ selected: state.selected - 1, })); - } else if (e.keyCode === 40 && selected < Object.keys(options!).length - 1) { + } else if ( + e.keyCode === 40 && + selected < Object.keys(options!).length - 1 + ) { this.setState((state: IState) => ({ selected: state.selected + 1, })); @@ -272,7 +289,12 @@ class SelectComponent extends Component { this.select(Object.keys(options!)[selected]); } - if (this.activeOptionRef && this.activeOptionRef.current && this.scrollContainerRef && this.scrollContainerRef.current) { + if ( + this.activeOptionRef && + this.activeOptionRef.current && + this.scrollContainerRef && + this.scrollContainerRef.current + ) { const containerTopOffset = this.scrollContainerRef.current.offsetTop; const optionTopOffset = this.activeOptionRef.current.offsetTop; @@ -282,10 +304,15 @@ class SelectComponent extends Component { } } - switch (e.keyCode){ - case 37: case 39: case 38: case 40: // Arrow keys - case 32: break; // Space - default: break; // do not block other keys + switch (e.keyCode) { + case 37: + case 39: + case 38: + case 40: // Arrow keys + case 32: + break; // Space + default: + break; // do not block other keys } } @@ -307,13 +334,7 @@ class SelectComponent extends Component { required, } = this.props; - const { - open, - needle, - value, - selected, - options, - } = this.state; + const { open, needle, value, selected, options } = this.state; let selection = ''; if (!value && defaultValue && options![defaultValue]) { @@ -325,10 +346,7 @@ class SelectComponent extends Component { } return ( - +
{ ref={this.inputRef} /> - {error && ( - - )} + {error && } ); } diff --git a/packages/forms/src/textarea/index.tsx b/packages/forms/src/textarea/index.tsx index 31c572d1c..2d89d1c9f 100644 --- a/packages/forms/src/textarea/index.tsx +++ b/packages/forms/src/textarea/index.tsx @@ -14,7 +14,10 @@ interface IData { [index: string]: string; } -interface IProps extends React.TextareaHTMLAttributes, IFormField, IWithStyle { +interface IProps + extends React.TextareaHTMLAttributes, + IFormField, + IWithStyle { focus?: boolean; data: IData; textareaClassName?: string; @@ -37,14 +40,14 @@ class TextareaComponent extends Component { const { data } = this.props; if (this.textareaRef && this.textareaRef.current && data) { - Object.keys(data).map(key => this.textareaRef.current!.dataset[key] = data[key]); + Object.keys(data).map( + key => (this.textareaRef.current!.dataset[key] = data[key]), + ); } } onChange(e: React.ChangeEvent) { - const { - onChange, - } = this.props; + const { onChange } = this.props; if (onChange) { onChange(e); @@ -57,7 +60,6 @@ class TextareaComponent extends Component { className, disabled, error, - focus, id, textareaClassName, label, @@ -94,9 +96,9 @@ class TextareaComponent extends Component { [`${classes.wrapper}`]: true, [`${classes.disabled}`]: disabled, [`${classes.hasError}`]: error, - })}> + })} + > - {error && ( - - )} + {error && } ); } diff --git a/packages/forms/src/toggle/index.tsx b/packages/forms/src/toggle/index.tsx index b146236df..a9970c8f1 100644 --- a/packages/forms/src/toggle/index.tsx +++ b/packages/forms/src/toggle/index.tsx @@ -3,7 +3,7 @@ import { Property } from 'csstype'; import React, { Component } from 'react'; import injectStyle from 'react-jss'; -import { IFormField, IWithStyle, Omit } from '../typings/generic'; +import { IFormField, IWithStyle } from '../typings/generic'; import { Theme } from '../../../theme'; import { Error } from '../error'; diff --git a/packages/forms/src/wrapper/index.tsx b/packages/forms/src/wrapper/index.tsx index cf179bc5e..3ae551e2c 100644 --- a/packages/forms/src/wrapper/index.tsx +++ b/packages/forms/src/wrapper/index.tsx @@ -12,18 +12,13 @@ interface IProps extends IWithStyle { const styles = { container: { - marginBottom: (props: IProps) => props.noMargin ? 0 : 20, + marginBottom: (props: IProps) => (props.noMargin ? 0 : 20), }, }; class WrapperComponent extends Component { render() { - const { - children, - classes, - className, - identifier, - } = this.props; + const { children, classes, className, identifier } = this.props; return (
{ const inputColor = legacyStyles.darkThemeGrayLightest; const inputBackground = legacyStyles.themeGrayDark; const inputBorder = `1px solid ${legacyStyles.darkThemeGrayLight}`; - const inputPrefixColor = color(legacyStyles.darkThemeGrayLighter).lighten(0.3).hex(); + const inputPrefixColor = color(legacyStyles.darkThemeGrayLighter) + .lighten(0.3) + .hex(); const buttonSecondaryTextColor = legacyStyles.darkThemeTextColor; const selectColor = inputColor; const drawerBg = color(colorBackground).lighten(0.3).hex(); @@ -47,7 +49,10 @@ export default (brandPrimary: string) => { // Loader colorFullscreenLoaderSpinner: '#FFF', - colorWebviewLoaderBackground: color(legacyStyles.darkThemeGrayDarkest).alpha(0.5).rgb().string(), + colorWebviewLoaderBackground: color(legacyStyles.darkThemeGrayDarkest) + .alpha(0.5) + .rgb() + .string(), // Input labelColor: legacyStyles.darkThemeTextColor, @@ -58,8 +63,12 @@ export default (brandPrimary: string) => { inputPrefixBackground: legacyStyles.darkThemeGray, inputDisabledOpacity: 0.5, inputScorePasswordBackground: legacyStyles.darkThemeGrayDark, - inputModifierColor: color(legacyStyles.darkThemeGrayLighter).lighten(0.3).hex(), - inputPlaceholderColor: color(legacyStyles.darkThemeGrayLighter).darken(0.1).hex(), + inputModifierColor: color(legacyStyles.darkThemeGrayLighter) + .lighten(0.3) + .hex(), + inputPlaceholderColor: color(legacyStyles.darkThemeGrayLighter) + .darken(0.1) + .hex(), // Toggle toggleBackground: legacyStyles.darkThemeGray, @@ -91,13 +100,20 @@ export default (brandPrimary: string) => { selectToggleColor: inputPrefixColor, selectPopupBackground: legacyStyles.darkThemeGrayLight, selectOptionColor: '#FFF', - selectOptionBorder: `1px solid ${color(legacyStyles.darkThemeGrayLight).darken(0.2).hex()}`, - selectOptionItemHover: color(legacyStyles.darkThemeGrayLight).darken(0.2).hex(), + selectOptionBorder: `1px solid ${color(legacyStyles.darkThemeGrayLight) + .darken(0.2) + .hex()}`, + selectOptionItemHover: color(legacyStyles.darkThemeGrayLight) + .darken(0.2) + .hex(), selectOptionItemHoverColor: selectColor, selectSearchColor: inputBackground, // Modal - colorModalOverlayBackground: color(legacyStyles.darkThemeBlack).alpha(0.9).rgb().string(), + colorModalOverlayBackground: color(legacyStyles.darkThemeBlack) + .alpha(0.9) + .rgb() + .string(), colorModalBackground: legacyStyles.darkThemeGrayDark, // Services diff --git a/packages/theme/src/themes/default/index.ts b/packages/theme/src/themes/default/index.ts index b8f3e3201..21017bbe0 100644 --- a/packages/theme/src/themes/default/index.ts +++ b/packages/theme/src/themes/default/index.ts @@ -82,7 +82,10 @@ export default (brandPrimary: string) => { colorText, - defaultContentBorder: color(legacyStyles.themeGrayLighter).darken(0.1).rgb().string(), + defaultContentBorder: color(legacyStyles.themeGrayLighter) + .darken(0.1) + .rgb() + .string(), // Subscription Container Component colorSubscriptionContainerBackground: 'none', @@ -94,7 +97,10 @@ export default (brandPrimary: string) => { // Loader colorAppLoaderSpinner: '#FFF', colorFullscreenLoaderSpinner: legacyStyles.themeGrayDark, - colorWebviewLoaderBackground: color(legacyStyles.themeGrayLighter).alpha(0.8).rgb().string(), + colorWebviewLoaderBackground: color(legacyStyles.themeGrayLighter) + .alpha(0.8) + .rgb() + .string(), // Input labelColor: legacyStyles.themeGrayLight, @@ -103,7 +109,9 @@ export default (brandPrimary: string) => { inputBackground, inputBorder, inputModifierColor: legacyStyles.themeGrayLight, - inputPlaceholderColor: color(legacyStyles.themeGrayLight).lighten(0.3).hex(), + inputPlaceholderColor: color(legacyStyles.themeGrayLight) + .lighten(0.3) + .hex(), inputPrefixColor, inputPrefixBackground: legacyStyles.themeGrayLighter, inputDisabledOpacity, diff --git a/packages/theme/tslint.json b/packages/theme/tslint.json deleted file mode 100644 index 0946f2096..000000000 --- a/packages/theme/tslint.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "../../tslint.json" -} diff --git a/packages/typings/types/react-loader.d.ts b/packages/typings/types/react-loader.d.ts index 8dc36b71f..728e3dfa0 100644 --- a/packages/typings/types/react-loader.d.ts +++ b/packages/typings/types/react-loader.d.ts @@ -36,7 +36,7 @@ interface LoaderProps extends LoaderOptions { className?: string; } -declare class ReactLoader extends Component { +declare class ReactLoader extends Component { } declare namespace ReactLoader { diff --git a/packages/ui/src/badge/ProBadge.tsx b/packages/ui/src/badge/ProBadge.tsx index 73db47068..63d5d673a 100644 --- a/packages/ui/src/badge/ProBadge.tsx +++ b/packages/ui/src/badge/ProBadge.tsx @@ -3,7 +3,7 @@ import classnames from 'classnames'; import React, { Component } from 'react'; import injectStyle from 'react-jss'; -import { Badge, Icon } from '../'; +import { Badge, Icon } from '..'; import { Theme } from '../../../theme'; import { IWithStyle } from '../typings/generic'; @@ -34,13 +34,8 @@ const styles = (theme: Theme) => ({ class ProBadgeComponent extends Component { render() { - const { - classes, - badgeClasses, - iconClasses, - inverted, - className, - } = this.props; + const { classes, badgeClasses, iconClasses, inverted, className } = + this.props; return ( { const styles = {}; - Object.keys(theme.styleTypes).map((style) => { + Object.keys(theme.styleTypes).map(style => { Object.assign(styles, { [style]: { background: theme.styleTypes[style].accent, @@ -51,12 +51,7 @@ class BadgeComponent extends Component { }; render() { - const { - classes, - children, - type, - className, - } = this.props; + const { classes, children, type, className } = this.props; return (
({ class HeadlineComponent extends Component { render() { - const { - classes, - level, - className, - children, - id, - } = this.props; + const { classes, level, className, children, id } = this.props; return React.createElement( `h${level}`, @@ -63,7 +57,12 @@ class HeadlineComponent extends Component { const Headline = injectStyle(styles)(HeadlineComponent); -const createH = (level: number) => (props: Omit) => {props.children}; +const createH = (level: number) => (props: Omit) => + ( + + {props.children} + + ); export const H1 = createH(1); export const H2 = createH(2); diff --git a/packages/ui/src/icon/index.tsx b/packages/ui/src/icon/index.tsx index ed55eccfe..b644a9234 100644 --- a/packages/ui/src/icon/index.tsx +++ b/packages/ui/src/icon/index.tsx @@ -24,12 +24,7 @@ class IconComponent extends Component { }; render() { - const { - classes, - icon, - size, - className, - } = this.props; + const { classes, icon, size, className } = this.props; if (!icon) { console.warn('No Icon specified'); diff --git a/packages/ui/src/infobox/index.tsx b/packages/ui/src/infobox/index.tsx index bd62fc4ea..961262001 100644 --- a/packages/ui/src/infobox/index.tsx +++ b/packages/ui/src/infobox/index.tsx @@ -3,8 +3,8 @@ import classnames from 'classnames'; import React, { Component } from 'react'; import injectStyle from 'react-jss'; +import { Icon } from '..'; import { Theme } from '../../../theme'; -import { Icon } from '../'; import { IWithStyle } from '../typings/generic'; interface IProps extends IWithStyle { @@ -27,7 +27,7 @@ interface IState { const buttonStyles = (theme: Theme) => { const styles = {}; - Object.keys(theme.styleTypes).map((style) => { + Object.keys(theme.styleTypes).map(style => { Object.assign(styles, { [style]: { background: theme.styleTypes[style].accent, @@ -73,18 +73,21 @@ const styles = (theme: Theme) => ({ marginRight: 10, }, close: { - color: (props: IProps) => theme.styleTypes[props.type ? props.type : 'primary'].contrast, + color: (props: IProps) => + theme.styleTypes[props.type ? props.type : 'primary'].contrast, marginRight: -5, border: 0, background: 'none', }, cta: { - borderColor: (props: IProps) => theme.styleTypes[props.type ? props.type : 'primary'].contrast, + borderColor: (props: IProps) => + theme.styleTypes[props.type ? props.type : 'primary'].contrast, borderRadius: theme.borderRadiusSmall, borderStyle: 'solid', borderWidth: 1, background: 'none', - color: (props: IProps) => theme.styleTypes[props.type ? props.type : 'primary'].contrast, + color: (props: IProps) => + theme.styleTypes[props.type ? props.type : 'primary'].contrast, marginLeft: 15, padding: [4, 10], fontSize: theme.uiFontSize, @@ -113,9 +116,7 @@ class InfoboxComponent extends Component { }; dismiss() { - const { - onDismiss, - } = this.props; + const { onDismiss } = this.props; this.setState({ isDismissing: true, @@ -129,7 +130,7 @@ class InfoboxComponent extends Component { this.setState({ dismissed: true, }); - }, 3000); + }, 3000); } componentWillUnmount(): void { @@ -144,26 +145,24 @@ class InfoboxComponent extends Component { icon, type, ctaLabel, - ctaLoading, ctaOnClick, dismissable, className, } = this.props; - const { - isDismissing, - dismissed, - } = this.state; + const { isDismissing, dismissed } = this.state; if (dismissed) { return null; } return ( -
+
{ })} data-type="franz-infobox" > - {icon && ( - - )} -
- {children} -
+ {icon && } +
{children}
{ctaLabel && ( - )} diff --git a/packages/ui/src/loader/index.tsx b/packages/ui/src/loader/index.tsx index e2701a8e9..244aa9dc9 100644 --- a/packages/ui/src/loader/index.tsx +++ b/packages/ui/src/loader/index.tsx @@ -3,7 +3,6 @@ import React, { Component } from 'react'; import injectStyle, { withTheme } from 'react-jss'; import ReactLoader from 'react-loader'; -import { Theme } from '../../../theme'; import { IWithStyle } from '../typings/generic'; interface IProps extends IWithStyle { @@ -11,7 +10,7 @@ interface IProps extends IWithStyle { color?: string; } -const styles = (theme: Theme) => ({ +const styles = () => ({ container: { position: 'relative', height: 60, @@ -20,12 +19,7 @@ const styles = (theme: Theme) => ({ class LoaderComponent extends Component { render() { - const { - classes, - className, - color, - theme, - } = this.props; + const { classes, className, color, theme } = this.props; return (
{ }; actions[actionName] = action; action.listeners = []; - action.listen = listener => action.listeners.push(listener); + action.listen = (listener) => action.listeners.push(listener); action.off = (listener) => { const { listeners } = action; listeners.splice(listeners.indexOf(listener), 1); }; - action.notify = params => action.listeners.forEach(listener => listener(params)); + action.notify = (params) => action.listeners.forEach((listener) => listener(params)); }); return actions; }; diff --git a/src/api/server/LocalApi.js b/src/api/server/LocalApi.js index 4b1f03f22..2d5bd8b80 100644 --- a/src/api/server/LocalApi.js +++ b/src/api/server/LocalApi.js @@ -2,7 +2,7 @@ import { ipcRenderer } from 'electron'; import { session } from '@electron/remote'; import du from 'du'; -import { getServicePartitionsDirectory } from '../../helpers/service-helpers.js'; +import { getServicePartitionsDirectory } from '../../helpers/service-helpers'; const debug = require('debug')('Ferdi:LocalApi'); @@ -41,11 +41,23 @@ export default class LocalApi { } async clearCache(serviceId = null) { - const s = serviceId ? session.fromPartition(`persist:service-${serviceId}`) : session.defaultSession; + const s = serviceId + ? session.fromPartition(`persist:service-${serviceId}`) + : session.defaultSession; - debug('LocalApi::clearCache resolves', (serviceId || 'clearAppCache')); + debug('LocalApi::clearCache resolves', serviceId || 'clearAppCache'); await s.clearStorageData({ - storages: ['appcache', 'cookies', 'filesystem', 'indexdb', 'localstorage', 'shadercache', 'websql', 'serviceworkers', 'cachestorage'], + storages: [ + 'appcache', + 'cookies', + 'filesystem', + 'indexdb', + 'localstorage', + 'shadercache', + 'websql', + 'serviceworkers', + 'cachestorage', + ], quotas: ['temporary', 'persistent', 'syncable'], }); return s.clearCache(); diff --git a/src/api/server/ServerApi.js b/src/api/server/ServerApi.js index 78a98e544..bc1d665b1 100644 --- a/src/api/server/ServerApi.js +++ b/src/api/server/ServerApi.js @@ -23,16 +23,11 @@ import { loadRecipeConfig, } from '../../helpers/recipe-helpers'; -import { - removeServicePartitionDirectory, -} from '../../helpers/service-helpers.js'; +import { removeServicePartitionDirectory } from '../../helpers/service-helpers'; const debug = require('debug')('Ferdi:ServerApi'); -module.paths.unshift( - getDevRecipeDirectory(), - getRecipeDirectory(), -); +module.paths.unshift(getDevRecipeDirectory(), getRecipeDirectory()); const { default: fetch } = remoteRequire('electron-fetch'); @@ -43,12 +38,16 @@ export default class ServerApi { // User async login(email, passwordHash) { - const request = await sendAuthRequest(`${apiBase()}/auth/login`, { - method: 'POST', - headers: { - Authorization: `Basic ${window.btoa(`${email}:${passwordHash}`)}`, + const request = await sendAuthRequest( + `${apiBase()}/auth/login`, + { + method: 'POST', + headers: { + Authorization: `Basic ${window.btoa(`${email}:${passwordHash}`)}`, + }, }, - }, false); + false, + ); if (!request.ok) { throw request; } @@ -59,10 +58,14 @@ export default class ServerApi { } async signup(data) { - const request = await sendAuthRequest(`${apiBase()}/auth/signup`, { - method: 'POST', - body: JSON.stringify(data), - }, false); + const request = await sendAuthRequest( + `${apiBase()}/auth/signup`, + { + method: 'POST', + body: JSON.stringify(data), + }, + false, + ); if (!request.ok) { throw request; } @@ -86,12 +89,16 @@ export default class ServerApi { } async retrievePassword(email) { - const request = await sendAuthRequest(`${apiBase()}/auth/password`, { - method: 'POST', - body: JSON.stringify({ - email, - }), - }, false); + const request = await sendAuthRequest( + `${apiBase()}/auth/password`, + { + method: 'POST', + body: JSON.stringify({ + email, + }), + }, + false, + ); if (!request.ok) { throw request; } @@ -128,7 +135,9 @@ export default class ServerApi { } const updatedData = await request.json(); - const user = Object.assign(updatedData, { data: new UserModel(updatedData.data) }); + const user = Object.assign(updatedData, { + data: new UserModel(updatedData.data), + }); debug('ServerApi::updateUserInfo resolves', user); return user; } @@ -159,7 +168,7 @@ export default class ServerApi { const data = await request.json(); let services = await this._mapServiceModels(data); - services = services.filter(service => service !== null); + services = services.filter((service) => service !== null); debug('ServerApi::getServices resolves', services); return services; } @@ -175,12 +184,17 @@ export default class ServerApi { const serviceData = await request.json(); if (data.iconFile) { - const iconData = await this.uploadServiceIcon(serviceData.data.id, data.iconFile); + const iconData = await this.uploadServiceIcon( + serviceData.data.id, + data.iconFile, + ); serviceData.data = iconData; } - const service = Object.assign(serviceData, { data: await this._prepareServiceModel(serviceData.data) }); + const service = Object.assign(serviceData, { + data: await this._prepareServiceModel(serviceData.data), + }); debug('ServerApi::createService resolves', service); return service; @@ -204,7 +218,9 @@ export default class ServerApi { const serviceData = await request.json(); - const service = Object.assign(serviceData, { data: await this._prepareServiceModel(serviceData.data) }); + const service = Object.assign(serviceData, { + data: await this._prepareServiceModel(serviceData.data), + }); debug('ServerApi::updateService resolves', service); return service; @@ -221,7 +237,10 @@ export default class ServerApi { delete requestData.headers['Content-Type']; - const request = await window.fetch(`${apiBase()}/service/${serviceId}`, requestData); + const request = await window.fetch( + `${apiBase()}/service/${serviceId}`, + requestData, + ); if (!request.ok) { throw request; @@ -292,18 +311,21 @@ export default class ServerApi { // Recipes async getInstalledRecipes() { const recipesDirectory = getRecipeDirectory(); - const paths = fs.readdirSync(recipesDirectory) - .filter(file => ( - fs.statSync(path.join(recipesDirectory, file)).isDirectory() - && file !== 'temp' - && file !== 'dev' - )); - - this.recipes = paths.map((id) => { - // eslint-disable-next-line - const Recipe = require(id)(RecipeModel); - return new Recipe(loadRecipeConfig(id)); - }).filter(recipe => recipe.id); + const paths = fs + .readdirSync(recipesDirectory) + .filter( + (file) => fs.statSync(path.join(recipesDirectory, file)).isDirectory() + && file !== 'temp' + && file !== 'dev', + ); + + this.recipes = paths + .map((id) => { + // eslint-disable-next-line + const Recipe = require(id)(RecipeModel); + return new Recipe(loadRecipeConfig(id)); + }) + .filter((recipe) => recipe.id); this.recipes = this.recipes.concat(this._getDevRecipes()); @@ -373,7 +395,9 @@ export default class ServerApi { console.log('[ServerApi::getRecipePackage] Using internal recipe file'); archivePath = internalRecipeFile; } else { - console.log('[ServerApi::getRecipePackage] Downloading recipe from server'); + console.log( + '[ServerApi::getRecipePackage] Downloading recipe from server', + ); archivePath = tempArchivePath; const packageUrl = `${apiBase()}/recipes/download/${recipeId}`; @@ -393,12 +417,14 @@ export default class ServerApi { preservePaths: true, unlink: true, preserveOwner: false, - onwarn: x => console.log('warn', recipeId, x), + onwarn: (x) => console.log('warn', recipeId, x), }); await sleep(10); - const { id } = fs.readJsonSync(path.join(recipeTempDirectory, 'package.json')); + const { id } = fs.readJsonSync( + path.join(recipeTempDirectory, 'package.json'), + ); const recipeDirectory = path.join(recipesDirectory, id); fs.copySync(recipeTempDirectory, recipeDirectory); fs.remove(recipeTempDirectory); @@ -414,7 +440,9 @@ export default class ServerApi { // News async getLatestNews() { - const url = `${apiBase(true)}/news?platform=${osPlatform}&arch=${osArch}&version=${app.getVersion()}`; + const url = `${apiBase( + true, + )}/news?platform=${osPlatform}&arch=${osArch}&version=${app.getVersion()}`; const request = await sendAuthRequest(url); if (!request.ok) throw request; const data = await request.json(); @@ -435,9 +463,13 @@ export default class ServerApi { throw new Error('Server not loaded'); } - const request = await sendAuthRequest(`${apiBase(false)}/health`, { - method: 'GET', - }, false); + const request = await sendAuthRequest( + `${apiBase(false)}/health`, + { + method: 'GET', + }, + false, + ); if (!request.ok) { throw request; } @@ -445,23 +477,31 @@ export default class ServerApi { } async getLegacyServices() { - const file = path.join(app.getPath('userData'), 'settings', 'services.json'); + const file = path.join( + app.getPath('userData'), + 'settings', + 'services.json', + ); try { const config = fs.readJsonSync(file); if (Object.prototype.hasOwnProperty.call(config, 'services')) { - const services = await Promise.all(config.services.map(async (s) => { - const service = s; - const request = await sendAuthRequest(`${apiBase()}/recipes/${s.service}`); - - if (request.status === 200) { - const data = await request.json(); - service.recipe = new RecipePreviewModel(data); - } - - return service; - })); + const services = await Promise.all( + config.services.map(async (s) => { + const service = s; + const request = await sendAuthRequest( + `${apiBase()}/recipes/${s.service}`, + ); + + if (request.status === 200) { + const data = await request.json(); + service.recipe = new RecipePreviewModel(data); + } + + return service; + }), + ); debug('ServerApi::getLegacyServices resolves', services); return services; @@ -475,17 +515,19 @@ export default class ServerApi { // Helper async _mapServiceModels(services) { - const recipes = services.map(s => s.recipeId); + const recipes = services.map((s) => s.recipeId); await this._bulkRecipeCheck(recipes); /* eslint-disable no-return-await */ - return Promise.all(services.map(async service => await this._prepareServiceModel(service))); + return Promise.all( + services.map(async (service) => await this._prepareServiceModel(service)), + ); /* eslint-enable no-return-await */ } async _prepareServiceModel(service) { let recipe; try { - recipe = this.recipes.find(r => r.id === service.recipeId); + recipe = this.recipes.find((r) => r.id === service.recipeId); if (!recipe) { console.warn(`Recipe ${service.recipeId} not loaded`); @@ -501,21 +543,25 @@ export default class ServerApi { async _bulkRecipeCheck(unfilteredRecipes) { // Filter recipe duplicates as we don't need to download 3 Slack recipes - const recipes = unfilteredRecipes.filter((elem, pos, arr) => arr.indexOf(elem) === pos); + const recipes = unfilteredRecipes.filter( + (elem, pos, arr) => arr.indexOf(elem) === pos, + ); - return Promise.all(recipes - .map(async (recipeId) => { - let recipe = this.recipes.find(r => r.id === recipeId); + return Promise.all( + recipes.map(async (recipeId) => { + let recipe = this.recipes.find((r) => r.id === recipeId); if (!recipe) { - console.warn(`Recipe '${recipeId}' not installed, trying to fetch from server`); + console.warn( + `Recipe '${recipeId}' not installed, trying to fetch from server`, + ); await this.getRecipePackage(recipeId); debug('Rerun ServerAPI::getInstalledRecipes'); await this.getInstalledRecipes(); - recipe = this.recipes.find(r => r.id === recipeId); + recipe = this.recipes.find((r) => r.id === recipeId); if (!recipe) { console.warn(`Could not load recipe ${recipeId}`); @@ -524,69 +570,83 @@ export default class ServerApi { } return recipe; - })).catch(err => console.error('Can\'t load recipe', err)); + }), + ).catch((err) => console.error("Can't load recipe", err)); } _mapRecipePreviewModel(recipes) { - return recipes.map((recipe) => { - try { - return new RecipePreviewModel(recipe); - } catch (e) { - console.error(e); - return null; - } - }).filter(recipe => recipe !== null); + return recipes + .map((recipe) => { + try { + return new RecipePreviewModel(recipe); + } catch (e) { + console.error(e); + return null; + } + }) + .filter((recipe) => recipe !== null); } _mapNewsModels(news) { - return news.map((newsItem) => { - try { - return new NewsModel(newsItem); - } catch (e) { - console.error(e); - return null; - } - }).filter(newsItem => newsItem !== null); + return news + .map((newsItem) => { + try { + return new NewsModel(newsItem); + } catch (e) { + console.error(e); + return null; + } + }) + .filter((newsItem) => newsItem !== null); } _mapOrderModels(orders) { - return orders.map((orderItem) => { - try { - return new OrderModel(orderItem); - } catch (e) { - console.error(e); - return null; - } - }).filter(orderItem => orderItem !== null); + return orders + .map((orderItem) => { + try { + return new OrderModel(orderItem); + } catch (e) { + console.error(e); + return null; + } + }) + .filter((orderItem) => orderItem !== null); } _getDevRecipes() { const recipesDirectory = getDevRecipeDirectory(); try { - const paths = fs.readdirSync(recipesDirectory) - .filter(file => fs.statSync(path.join(recipesDirectory, file)).isDirectory() && file !== 'temp'); - - const recipes = paths.map((id) => { - let Recipe; - try { - // eslint-disable-next-line - Recipe = require(id)(RecipeModel); - return new Recipe(loadRecipeConfig(id)); - } catch (err) { - console.error(err); - } + const paths = fs + .readdirSync(recipesDirectory) + .filter( + (file) => fs.statSync(path.join(recipesDirectory, file)).isDirectory() + && file !== 'temp', + ); + + const recipes = paths + .map((id) => { + let Recipe; + try { + // eslint-disable-next-line + Recipe = require(id)(RecipeModel); + return new Recipe(loadRecipeConfig(id)); + } catch (err) { + console.error(err); + } - return false; - }).filter(recipe => recipe.id).map((data) => { - const recipe = data; + return false; + }) + .filter((recipe) => recipe.id) + .map((data) => { + const recipe = data; - recipe.icons = { - svg: `${recipe.path}/icon.svg`, - }; - recipe.local = true; + recipe.icons = { + svg: `${recipe.path}/icon.svg`, + }; + recipe.local = true; - return data; - }); + return data; + }); return recipes; } catch (err) { diff --git a/src/app.js b/src/app.js index aab1729d7..a2d60dbe4 100644 --- a/src/app.js +++ b/src/app.js @@ -59,7 +59,7 @@ window.addEventListener('load', () => { }); // Prevent drag and drop into window from redirecting -window.addEventListener('dragover', event => event.preventDefault()); -window.addEventListener('drop', event => event.preventDefault()); -window.addEventListener('dragover', event => event.stopPropagation()); -window.addEventListener('drop', event => event.stopPropagation()); +window.addEventListener('dragover', (event) => event.preventDefault()); +window.addEventListener('drop', (event) => event.preventDefault()); +window.addEventListener('dragover', (event) => event.stopPropagation()); +window.addEventListener('drop', (event) => event.stopPropagation()); diff --git a/src/components/auth/AuthLayout.js b/src/components/auth/AuthLayout.js index 6fa3adf92..c0e6b982b 100644 --- a/src/components/auth/AuthLayout.js +++ b/src/components/auth/AuthLayout.js @@ -7,14 +7,19 @@ import { TitleBar } from 'electron-react-titlebar'; import Link from '../ui/Link'; import InfoBar from '../ui/InfoBar'; -import { oneOrManyChildElements, globalError as globalErrorPropType } from '../../prop-types'; +import { + oneOrManyChildElements, + globalError as globalErrorPropType, +} from '../../prop-types'; import globalMessages from '../../i18n/globalMessages'; import { isWindows } from '../../environment'; import AppUpdateInfoBar from '../AppUpdateInfoBar'; import { GITHUB_FERDI_URL } from '../../config'; -export default @observer class AuthLayout extends Component { +export default +@observer +class AuthLayout extends Component { static propTypes = { children: oneOrManyChildElements.isRequired, error: globalErrorPropType.isRequired, @@ -30,7 +35,7 @@ export default @observer class AuthLayout extends Component { state = { shouldShowAppUpdateInfoBar: true, - } + }; static defaultProps = { nextAppReleaseVersion: null, @@ -57,12 +62,15 @@ export default @observer class AuthLayout extends Component { return ( <> - {isWindows && !isFullScreen && } + {isWindows && !isFullScreen && ( + + )}
{!isOnline && ( - + {intl.formatMessage(globalMessages.notConnectedToTheInternet)} @@ -95,7 +103,11 @@ export default @observer class AuthLayout extends Component { })}
{/*
*/} - +
diff --git a/src/components/auth/ChangeServer.js b/src/components/auth/ChangeServer.js index 0dedd825a..7bab80280 100644 --- a/src/components/auth/ChangeServer.js +++ b/src/components/auth/ChangeServer.js @@ -100,7 +100,7 @@ export default @observer class ChangeServer extends Component { const { intl } = this.context; return (
-
this.submit(e)}> + this.submit(e)}>

{intl.formatMessage(messages.headline)}

{form.$('server').value === this.franzServer && ( @@ -113,7 +113,7 @@ export default @observer class ChangeServer extends Component { && ( this.submit(e)} + onChange={(e) => this.submit(e)} field={form.$('customServer')} /> )} diff --git a/src/components/auth/Locked.js b/src/components/auth/Locked.js index 1fdbea595..2ad8a2409 100644 --- a/src/components/auth/Locked.js +++ b/src/components/auth/Locked.js @@ -102,7 +102,7 @@ export default @observer class Locked extends Component { return (
- this.submit(e)}> + this.submit(e)}> - this.submit(e)}> + this.submit(e)}> - this.submit(e)}> + this.submit(e)}> ({ +const styles = (theme) => ({ root: { width: '500px !important', textAlign: 'center', @@ -161,7 +161,7 @@ class SetupAssistant extends Component { const sanitizedWorkspace = slackWorkspace.trim().replace(/^https?:\/\//, ''); if (sanitizedWorkspace) { - const index = services.findIndex(s => s.id === SLACK_ID); + const index = services.findIndex((s) => s.id === SLACK_ID); if (index === -1) { const newServices = services; @@ -215,11 +215,11 @@ class SetupAssistant extends Component {