summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.eslintignore3
-rw-r--r--.eslintrc163
-rw-r--r--package-lock.json439
-rw-r--r--package.json11
-rw-r--r--packages/forms/src/button/index.tsx29
-rw-r--r--packages/forms/src/error/index.tsx13
-rw-r--r--packages/forms/src/input/index.tsx63
-rw-r--r--packages/forms/src/input/scorePassword.ts6
-rw-r--r--packages/forms/src/label/index.tsx13
-rw-r--r--packages/forms/src/select/index.tsx119
-rw-r--r--packages/forms/src/textarea/index.tsx22
-rw-r--r--packages/forms/src/toggle/index.tsx2
-rw-r--r--packages/forms/src/wrapper/index.tsx9
-rw-r--r--packages/forms/tslint.json3
-rw-r--r--packages/theme/src/index.ts12
-rw-r--r--packages/theme/src/themes/IStyleTypes.ts1
-rw-r--r--packages/theme/src/themes/dark/index.ts30
-rw-r--r--packages/theme/src/themes/default/index.ts14
-rw-r--r--packages/theme/tslint.json3
-rw-r--r--packages/typings/types/react-loader.d.ts2
-rw-r--r--packages/ui/src/badge/ProBadge.tsx11
-rw-r--r--packages/ui/src/badge/index.tsx9
-rw-r--r--packages/ui/src/headline/index.tsx15
-rw-r--r--packages/ui/src/icon/index.tsx7
-rw-r--r--packages/ui/src/infobox/index.tsx49
-rw-r--r--packages/ui/src/loader/index.tsx10
-rw-r--r--packages/ui/tslint.json3
-rw-r--r--src/actions/lib/actions.js4
-rw-r--r--src/api/server/LocalApi.js20
-rw-r--r--src/api/server/ServerApi.js288
-rw-r--r--src/app.js8
-rw-r--r--src/components/auth/AuthLayout.js28
-rw-r--r--src/components/auth/ChangeServer.js4
-rw-r--r--src/components/auth/Locked.js2
-rw-r--r--src/components/auth/Login.js2
-rw-r--r--src/components/auth/Password.js2
-rw-r--r--src/components/auth/SetupAssistant.js10
-rw-r--r--src/components/auth/Signup.js2
-rw-r--r--src/components/auth/Welcome.js2
-rw-r--r--src/components/layout/AppLayout.js4
-rw-r--r--src/components/services/content/ConnectionLostBanner.js2
-rw-r--r--src/components/services/content/ErrorHandlers/styles.js2
-rw-r--r--src/components/services/content/Services.js2
-rw-r--r--src/components/services/content/WebviewCrashHandler.js2
-rw-r--r--src/components/services/tabs/Tabbar.js10
-rw-r--r--src/components/settings/services/EditServiceForm.js2
-rw-r--r--src/components/settings/services/ServicesDashboard.js4
-rw-r--r--src/components/settings/settings/EditSettingsForm.js23
-rw-r--r--src/components/settings/supportFerdi/SupportFerdiDashboard.js18
-rw-r--r--src/components/settings/user/EditUserForm.js2
-rw-r--r--src/components/ui/AppLoader/index.js2
-rw-r--r--src/components/ui/FeatureItem.js2
-rw-r--r--src/components/ui/FeatureList.js2
-rw-r--r--src/components/ui/Link.js2
-rw-r--r--src/components/ui/Modal/styles.js2
-rw-r--r--src/components/ui/Radio.js2
-rw-r--r--src/components/ui/SearchInput.js2
-rw-r--r--src/components/ui/Select.js4
-rw-r--r--src/components/ui/ServiceIcon.js2
-rw-r--r--src/components/ui/Slider.js2
-rw-r--r--src/components/ui/Tabs/TabItem.js8
-rw-r--r--src/components/ui/Tabs/Tabs.js2
-rw-r--r--src/components/ui/Toggle.js2
-rw-r--r--src/components/ui/ToggleRaw.js2
-rw-r--r--src/components/ui/WebviewLoader/styles.js2
-rw-r--r--src/components/util/ErrorBoundary/styles.js2
-rw-r--r--src/containers/auth/SetupAssistantScreen.js2
-rw-r--r--src/containers/auth/SignupScreen.js2
-rw-r--r--src/containers/layout/AppLayoutContainer.js4
-rw-r--r--src/containers/settings/AccountScreen.js5
-rw-r--r--src/containers/settings/EditServiceScreen.js4
-rw-r--r--src/containers/settings/EditSettingsScreen.js2
-rw-r--r--src/containers/settings/EditUserScreen.js2
-rw-r--r--src/containers/settings/RecipesScreen.js10
-rw-r--r--src/features/announcements/components/AnnouncementScreen.js2
-rw-r--r--src/features/communityRecipes/store.js2
-rw-r--r--src/features/publishDebugInfo/Component.js6
-rw-r--r--src/features/quickSwitch/Component.js4
-rw-r--r--src/features/shareFranz/Component.js2
-rw-r--r--src/features/todos/containers/TodosScreen.js4
-rw-r--r--src/features/utils/ActionBinding.js4
-rw-r--r--src/features/utils/FeatureStore.js8
-rw-r--r--src/features/webControls/components/WebControls.js4
-rw-r--r--src/features/webControls/containers/WebControlsScreen.js2
-rw-r--r--src/features/workspaces/api.js2
-rw-r--r--src/features/workspaces/components/WorkspaceDrawer.js2
-rw-r--r--src/features/workspaces/components/WorkspaceDrawerItem.js2
-rw-r--r--src/features/workspaces/components/WorkspaceItem.js2
-rw-r--r--src/features/workspaces/components/WorkspaceServiceListItem.js2
-rw-r--r--src/features/workspaces/components/WorkspaceSwitchingIndicator.js2
-rw-r--r--src/features/workspaces/components/WorkspacesDashboard.js4
-rw-r--r--src/features/workspaces/containers/WorkspacesScreen.js4
-rw-r--r--src/features/workspaces/models/Workspace.js4
-rw-r--r--src/helpers/array-helpers.js6
-rw-r--r--src/helpers/async-helpers.js2
-rw-r--r--src/helpers/service-helpers.js2
-rw-r--r--src/helpers/validation-helpers.js2
-rw-r--r--src/models/Recipe.js2
-rw-r--r--src/models/Service.js2
-rw-r--r--src/models/UserAgent.js4
-rw-r--r--src/stores/AppStore.js105
-rw-r--r--src/stores/NewsStore.js2
-rw-r--r--src/stores/RecipePreviewsStore.js2
-rw-r--r--src/stores/RecipesStore.js8
-rw-r--r--src/stores/ServicesStore.js44
-rw-r--r--src/stores/UIStore.js2
-rw-r--r--src/stores/UserStore.js4
-rw-r--r--src/stores/lib/CachedRequest.js4
-rw-r--r--src/stores/lib/Reaction.js4
-rw-r--r--src/stores/lib/Request.js2
-rw-r--r--src/stores/lib/Store.js6
-rw-r--r--src/webview/contextMenuBuilder.js4
-rw-r--r--src/webview/lib/RecipeWebview.js2
-rw-r--r--src/webview/notifications.js2
-rw-r--r--src/webview/spellchecker.js2
-rw-r--r--tsconfig.settings.json3
-rw-r--r--tslint.json12
-rw-r--r--uidev/src/app.tsx2
-rw-r--r--uidev/src/stores/stories.ts2
-rw-r--r--uidev/src/stories/button.stories.tsx72
-rw-r--r--uidev/src/stories/headline.stories.tsx3
-rw-r--r--uidev/src/stories/infobox.stories.tsx10
-rw-r--r--uidev/src/stories/input.stories.tsx4
-rw-r--r--uidev/src/stories/loader.stories.tsx3
-rw-r--r--uidev/src/stories/select.stories.tsx2
-rw-r--r--uidev/src/stories/textarea.stories.tsx2
-rw-r--r--uidev/src/stories/toggle.stories.tsx19
-rw-r--r--uidev/src/withTheme/index.tsx16
-rw-r--r--uidev/tslint.json3
129 files changed, 964 insertions, 1039 deletions
diff --git a/.eslintignore b/.eslintignore
index 52fde4c3e..5385bbb5f 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -1,5 +1,6 @@
1build/ 1build/
2out/ 2out/
3packages/*/lib 3packages/*/lib
4packages/**/*.test.*
4src/internal-server 5src/internal-server
5recipes/ \ No newline at end of file 6recipes/
diff --git a/.eslintrc b/.eslintrc
index 668f688ae..5e8d4cebf 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -3,71 +3,124 @@
3 "parser": "@babel/eslint-parser", 3 "parser": "@babel/eslint-parser",
4 "extends": "eslint-config-airbnb", 4 "extends": "eslint-config-airbnb",
5 "plugins": ["jest"], 5 "plugins": ["jest"],
6 "rules": { 6 "overrides": [
7 "arrow-parens": 0, 7 {
8 "consistent-return": 0, 8 "files": ["**/*.ts", "**/*.tsx"],
9 "no-param-reassign": 0, 9 "env": { "browser": true, "es6": true, "node": true },
10 "import/extensions": 0, 10 "extends": ["airbnb-typescript"],
11 "import/no-extraneous-dependencies": 0, 11 "parser": "@typescript-eslint/parser",
12 "import/no-unresolved": [ 12 "parserOptions": {
13 2, 13 "ecmaFeatures": { "jsx": true },
14 { 14 "ecmaVersion": 2018,
15 "ignore": ["electron"] 15 "sourceType": "module",
16 } 16 "project": "./tsconfig.json"
17 ], 17 },
18 "import/prefer-default-export": 0, 18 "plugins": ["@typescript-eslint"],
19 "linebreak-style": 0, 19 "rules": {
20 "react/static-property-placement": 0, 20 // eslint
21 "react/state-in-constructor": 0, 21 "arrow-parens": 0,
22 "react/jsx-props-no-spreading": 0, 22 "array-callback-return": 1,
23 "react/prefer-stateless-function": 0, 23 "class-methods-use-this": 0,
24 "react/jsx-filename-extension": [ 24 "consistent-return": 0,
25 1, 25 "implicit-arrow-linebreak": 0,
26 { 26 "linebreak-style": 0,
27 "extensions": [".js", ".jsx"] 27 "max-len": 0,
28 } 28 "no-confusing-arrow": 0,
29 ], 29 "no-console": 0,
30 "react/forbid-prop-types": 0, 30 "no-param-reassign": 0,
31 "react/destructuring-assignment": 0, 31 "no-return-assign": 1,
32 "prefer-destructuring": 1, 32 "no-underscore-dangle": 0,
33 "no-underscore-dangle": 0, 33 "no-use-before-define": 0,
34 "max-len": 0, 34 "prefer-destructuring": 1,
35 "class-methods-use-this": 0, 35 "object-curly-newline": 0,
36 "no-console": 0, 36 "operator-linebreak": 0,
37 "react/jsx-no-bind": 0, 37 // @typescript-eslint
38 "react/sort-comp": 0, 38 "@typescript-eslint/indent": 0,
39 "jsx-a11y/no-static-element-interactions": 0, 39 "@typescript-eslint/no-shadow": 0,
40 "react/jsx-no-target-blank": 0, 40 "@typescript-eslint/no-unused-expressions": 0,
41 "no-restricted-syntax": [0, "ForInStatement"], 41 // eslint-plugin-import
42 "jsx-a11y/no-noninteractive-element-interactions": 1, 42 "import/extensions": 0,
43 "jsx-a11y/label-has-for": [ 43 "import/no-cycle": 1,
44 2, 44 "import/no-extraneous-dependencies": 0,
45 { 45 "import/no-unresolved": 0,
46 "components": ["Label"], 46 "import/prefer-default-export": 0,
47 "required": { 47 // eslint-plugin-react
48 "every": ["id"] 48 "react/destructuring-assignment": 0,
49 }, 49 "react/button-has-type": 0,
50 "allowChildren": false 50 "react/forbid-prop-types": 0,
51 "react/jsx-curly-newline": 0,
52 "react/jsx-no-bind": 0,
53 "react/jsx-no-target-blank": 0,
54 "react/jsx-props-no-spreading": 0,
55 "react/no-deprecated": 1,
56 "react/no-array-index-key": 0,
57 "react/prefer-stateless-function": 0,
58 "react/sort-comp": 0,
59 "react/state-in-constructor": 0,
60 "react/static-property-placement": 0,
61 // eslint-plugin-jsx-a11y
62 "jsx-a11y/click-events-have-key-events": 1,
63 "jsx-a11y/mouse-events-have-key-events": 1,
64 "jsx-a11y/label-has-for": [
65 2,
66 {
67 "components": ["Label"],
68 "required": {
69 "every": ["id"]
70 },
71 "allowChildren": false
72 }
73 ],
74 "jsx-a11y/no-static-element-interactions": 0,
75 "jsx-a11y/no-noninteractive-element-interactions": 1
51 } 76 }
52 ], 77 }
53 "jsx-a11y/click-events-have-key-events": 1 78 ],
79 "settings": {
80 "react": {
81 "pragma": "React", // Pragma to use, default to "React"
82 "version": "detect" // React version. "detect" automatically picks the version you have installed.
83 }
54 }, 84 },
55 "globals": { 85 "globals": {
56 "window": true, 86 "window": true,
57 "document": true, 87 "document": true,
58 "ENV": true,
59 "FormData": true, 88 "FormData": true,
60 "localStorage": true, 89 "localStorage": true,
61 "navigator": true, 90 "navigator": true,
62 "Worker": true, 91 "Element": true
63 "atob": true,
64 "btoa": true,
65 "ga": true,
66 "mocha": true,
67 "Element": true,
68 "electron": true
69 }, 92 },
70 "env": { 93 "env": {
71 "jest/globals": true 94 "jest/globals": true
95 },
96 "rules": {
97 // eslint
98 "prefer-destructuring": 1,
99 "class-methods-use-this": 1,
100 "consistent-return": 1,
101 "max-len": 0,
102 "no-param-reassign": 1,
103 "no-restricted-syntax": 0,
104 "no-underscore-dangle": 0,
105 "operator-linebreak": 0,
106 // eslint-plugin-import
107 "import/extensions": 1,
108 "import/prefer-default-export": 0,
109 "import/no-extraneous-dependencies": 1,
110 "import/no-unresolved": 1,
111 // eslint-plugin-react
112 "react/forbid-prop-types": 1,
113 "react/destructuring-assignment": 0,
114 "react/jsx-filename-extension": 1,
115 "react/jsx-no-bind": 1,
116 "react/jsx-props-no-spreading": 0,
117 "react/prefer-stateless-function": 1,
118 "react/static-property-placement": 0,
119 "react/state-in-constructor": 1,
120 "react/sort-comp": 0,
121 // eslint-plugin-jsx-a11y
122 "jsx-a11y/click-events-have-key-events": 1,
123 "jsx-a11y/no-static-element-interactions": 1,
124 "jsx-a11y/no-noninteractive-element-interactions": 1
72 } 125 }
73} 126}
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 @@
3526 } 3526 }
3527 } 3527 }
3528 }, 3528 },
3529 "@fimbul/bifrost": {
3530 "version": "0.21.0",
3531 "resolved": "https://registry.npmjs.org/@fimbul/bifrost/-/bifrost-0.21.0.tgz",
3532 "integrity": "sha512-ou8VU+nTmOW1jeg+FT+sn+an/M0Xb9G16RucrfhjXGWv1Q97kCoM5CG9Qj7GYOSdu7km72k7nY83Eyr53Bkakg==",
3533 "dev": true,
3534 "requires": {
3535 "@fimbul/ymir": "^0.21.0",
3536 "get-caller-file": "^2.0.0",
3537 "tslib": "^1.8.1",
3538 "tsutils": "^3.5.0"
3539 },
3540 "dependencies": {
3541 "get-caller-file": {
3542 "version": "2.0.5",
3543 "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
3544 "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
3545 "dev": true
3546 },
3547 "tsutils": {
3548 "version": "3.17.1",
3549 "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz",
3550 "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==",
3551 "dev": true,
3552 "requires": {
3553 "tslib": "^1.8.1"
3554 }
3555 }
3556 }
3557 },
3558 "@fimbul/ymir": {
3559 "version": "0.21.0",
3560 "resolved": "https://registry.npmjs.org/@fimbul/ymir/-/ymir-0.21.0.tgz",
3561 "integrity": "sha512-T/y7WqPsm4n3zhT08EpB5sfdm2Kvw3gurAxr2Lr5dQeLi8ZsMlNT/Jby+ZmuuAAd1PnXYzKp+2SXgIkQIIMCUg==",
3562 "dev": true,
3563 "requires": {
3564 "inversify": "^5.0.0",
3565 "reflect-metadata": "^0.1.12",
3566 "tslib": "^1.8.1"
3567 }
3568 },
3569 "@hapi/address": { 3529 "@hapi/address": {
3570 "version": "2.1.4", 3530 "version": "2.1.4",
3571 "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz", 3531 "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz",
@@ -8175,22 +8135,6 @@
8175 "@types/ms": "*" 8135 "@types/ms": "*"
8176 } 8136 }
8177 }, 8137 },
8178 "@types/eslint": {
8179 "version": "7.2.13",
8180 "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.13.tgz",
8181 "integrity": "sha512-LKmQCWAlnVHvvXq4oasNUMTJJb2GwSyTY8+1C7OH5ILR8mPLaljv1jxL1bXW3xB3jFbQxTKxJAvI8PyjB09aBg==",
8182 "dev": true,
8183 "requires": {
8184 "@types/estree": "*",
8185 "@types/json-schema": "*"
8186 }
8187 },
8188 "@types/estree": {
8189 "version": "0.0.48",
8190 "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.48.tgz",
8191 "integrity": "sha512-LfZwXoGUDo0C3me81HXgkBg5CTQYb6xzEl+fNmbO4JdRiSKQ8A0GD1OBBvKAIsbCUgoyAty7m99GqqMQe784ew==",
8192 "dev": true
8193 },
8194 "@types/events": { 8138 "@types/events": {
8195 "version": "3.0.0", 8139 "version": "3.0.0",
8196 "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", 8140 "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",
@@ -8484,6 +8428,38 @@
8484 "integrity": "sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==", 8428 "integrity": "sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg==",
8485 "dev": true 8429 "dev": true
8486 }, 8430 },
8431 "@typescript-eslint/eslint-plugin": {
8432 "version": "4.28.5",
8433 "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.5.tgz",
8434 "integrity": "sha512-m31cPEnbuCqXtEZQJOXAHsHvtoDi9OVaeL5wZnO2KZTnkvELk+u6J6jHg+NzvWQxk+87Zjbc4lJS4NHmgImz6Q==",
8435 "dev": true,
8436 "requires": {
8437 "@typescript-eslint/experimental-utils": "4.28.5",
8438 "@typescript-eslint/scope-manager": "4.28.5",
8439 "debug": "^4.3.1",
8440 "functional-red-black-tree": "^1.0.1",
8441 "regexpp": "^3.1.0",
8442 "semver": "^7.3.5",
8443 "tsutils": "^3.21.0"
8444 },
8445 "dependencies": {
8446 "debug": {
8447 "version": "4.3.2",
8448 "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
8449 "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
8450 "dev": true,
8451 "requires": {
8452 "ms": "2.1.2"
8453 }
8454 },
8455 "ms": {
8456 "version": "2.1.2",
8457 "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
8458 "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
8459 "dev": true
8460 }
8461 }
8462 },
8487 "@typescript-eslint/experimental-utils": { 8463 "@typescript-eslint/experimental-utils": {
8488 "version": "4.28.5", 8464 "version": "4.28.5",
8489 "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.5.tgz", 8465 "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.5.tgz",
@@ -8536,6 +8512,35 @@
8536 } 8512 }
8537 } 8513 }
8538 }, 8514 },
8515 "@typescript-eslint/parser": {
8516 "version": "4.28.5",
8517 "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.5.tgz",
8518 "integrity": "sha512-NPCOGhTnkXGMqTznqgVbA5LqVsnw+i3+XA1UKLnAb+MG1Y1rP4ZSK9GX0kJBmAZTMIktf+dTwXToT6kFwyimbw==",
8519 "dev": true,
8520 "requires": {
8521 "@typescript-eslint/scope-manager": "4.28.5",
8522 "@typescript-eslint/types": "4.28.5",
8523 "@typescript-eslint/typescript-estree": "4.28.5",
8524 "debug": "^4.3.1"
8525 },
8526 "dependencies": {
8527 "debug": {
8528 "version": "4.3.2",
8529 "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
8530 "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
8531 "dev": true,
8532 "requires": {
8533 "ms": "2.1.2"
8534 }
8535 },
8536 "ms": {
8537 "version": "2.1.2",
8538 "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
8539 "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
8540 "dev": true
8541 }
8542 }
8543 },
8539 "@typescript-eslint/scope-manager": { 8544 "@typescript-eslint/scope-manager": {
8540 "version": "4.28.5", 8545 "version": "4.28.5",
8541 "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.5.tgz", 8546 "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.5.tgz",
@@ -11698,12 +11703,6 @@
11698 } 11703 }
11699 } 11704 }
11700 }, 11705 },
11701 "builtin-modules": {
11702 "version": "1.1.1",
11703 "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
11704 "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
11705 "dev": true
11706 },
11707 "builtin-status-codes": { 11706 "builtin-status-codes": {
11708 "version": "3.0.0", 11707 "version": "3.0.0",
11709 "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", 11708 "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
@@ -16965,6 +16964,23 @@
16965 } 16964 }
16966 } 16965 }
16967 }, 16966 },
16967 "eslint-config-airbnb-typescript": {
16968 "version": "12.3.1",
16969 "resolved": "https://registry.npmjs.org/eslint-config-airbnb-typescript/-/eslint-config-airbnb-typescript-12.3.1.tgz",
16970 "integrity": "sha512-ql/Pe6/hppYuRp4m3iPaHJqkBB7dgeEmGPQ6X0UNmrQOfTF+dXw29/ZjU2kQ6RDoLxaxOA+Xqv07Vbef6oVTWw==",
16971 "dev": true,
16972 "requires": {
16973 "@typescript-eslint/parser": "^4.4.1",
16974 "eslint-config-airbnb": "^18.2.0",
16975 "eslint-config-airbnb-base": "^14.2.0"
16976 }
16977 },
16978 "eslint-config-prettier": {
16979 "version": "8.3.0",
16980 "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz",
16981 "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==",
16982 "dev": true
16983 },
16968 "eslint-import-resolver-node": { 16984 "eslint-import-resolver-node": {
16969 "version": "0.3.4", 16985 "version": "0.3.4",
16970 "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", 16986 "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz",
@@ -17237,6 +17253,15 @@
17237 } 17253 }
17238 } 17254 }
17239 }, 17255 },
17256 "eslint-plugin-prettier": {
17257 "version": "3.4.0",
17258 "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.0.tgz",
17259 "integrity": "sha512-UDK6rJT6INSfcOo545jiaOwB701uAIt2/dR7WnFQoGCVl1/EMqdANBmwUaqqQ45aXprsTGzSa39LI1PyuRBxxw==",
17260 "dev": true,
17261 "requires": {
17262 "prettier-linter-helpers": "^1.0.0"
17263 }
17264 },
17240 "eslint-plugin-react": { 17265 "eslint-plugin-react": {
17241 "version": "7.24.0", 17266 "version": "7.24.0",
17242 "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.24.0.tgz", 17267 "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.24.0.tgz",
@@ -17289,6 +17314,12 @@
17289 } 17314 }
17290 } 17315 }
17291 }, 17316 },
17317 "eslint-plugin-react-hooks": {
17318 "version": "4.2.0",
17319 "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz",
17320 "integrity": "sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ==",
17321 "dev": true
17322 },
17292 "eslint-scope": { 17323 "eslint-scope": {
17293 "version": "4.0.3", 17324 "version": "4.0.3",
17294 "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", 17325 "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz",
@@ -17322,120 +17353,6 @@
17322 "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", 17353 "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
17323 "dev": true 17354 "dev": true
17324 }, 17355 },
17325 "eslint-webpack-plugin": {
17326 "version": "2.5.4",
17327 "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-2.5.4.tgz",
17328 "integrity": "sha512-7rYh0m76KyKSDE+B+2PUQrlNS4HJ51t3WKpkJg6vo2jFMbEPTG99cBV0Dm7LXSHucN4WGCG65wQcRiTFrj7iWw==",
17329 "dev": true,
17330 "requires": {
17331 "@types/eslint": "^7.2.6",
17332 "arrify": "^2.0.1",
17333 "jest-worker": "^26.6.2",
17334 "micromatch": "^4.0.2",
17335 "normalize-path": "^3.0.0",
17336 "schema-utils": "^3.0.0"
17337 },
17338 "dependencies": {
17339 "arrify": {
17340 "version": "2.0.1",
17341 "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
17342 "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==",
17343 "dev": true
17344 },
17345 "braces": {
17346 "version": "3.0.2",
17347 "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
17348 "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
17349 "dev": true,
17350 "requires": {
17351 "fill-range": "^7.0.1"
17352 }
17353 },
17354 "fill-range": {
17355 "version": "7.0.1",
17356 "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
17357 "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
17358 "dev": true,
17359 "requires": {
17360 "to-regex-range": "^5.0.1"
17361 }
17362 },
17363 "has-flag": {
17364 "version": "4.0.0",
17365 "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
17366 "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
17367 "dev": true
17368 },
17369 "is-number": {
17370 "version": "7.0.0",
17371 "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
17372 "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
17373 "dev": true
17374 },
17375 "jest-worker": {
17376 "version": "26.6.2",
17377 "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz",
17378 "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==",
17379 "dev": true,
17380 "requires": {
17381 "@types/node": "*",
17382 "merge-stream": "^2.0.0",
17383 "supports-color": "^7.0.0"
17384 }
17385 },
17386 "micromatch": {
17387 "version": "4.0.4",
17388 "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
17389 "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==",
17390 "dev": true,
17391 "requires": {
17392 "braces": "^3.0.1",
17393 "picomatch": "^2.2.3"
17394 }
17395 },
17396 "normalize-path": {
17397 "version": "3.0.0",
17398 "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
17399 "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
17400 "dev": true
17401 },
17402 "picomatch": {
17403 "version": "2.3.0",
17404 "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
17405 "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==",
17406 "dev": true
17407 },
17408 "schema-utils": {
17409 "version": "3.0.0",
17410 "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz",
17411 "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==",
17412 "dev": true,
17413 "requires": {
17414 "@types/json-schema": "^7.0.6",
17415 "ajv": "^6.12.5",
17416 "ajv-keywords": "^3.5.2"
17417 }
17418 },
17419 "supports-color": {
17420 "version": "7.2.0",
17421 "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
17422 "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
17423 "dev": true,
17424 "requires": {
17425 "has-flag": "^4.0.0"
17426 }
17427 },
17428 "to-regex-range": {
17429 "version": "5.0.1",
17430 "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
17431 "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
17432 "dev": true,
17433 "requires": {
17434 "is-number": "^7.0.0"
17435 }
17436 }
17437 }
17438 },
17439 "espree": { 17356 "espree": {
17440 "version": "7.3.1", 17357 "version": "7.3.1",
17441 "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", 17358 "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz",
@@ -17927,6 +17844,12 @@
17927 "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 17844 "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
17928 "dev": true 17845 "dev": true
17929 }, 17846 },
17847 "fast-diff": {
17848 "version": "1.2.0",
17849 "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
17850 "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
17851 "dev": true
17852 },
17930 "fast-glob": { 17853 "fast-glob": {
17931 "version": "3.2.5", 17854 "version": "3.2.5",
17932 "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", 17855 "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz",
@@ -22075,12 +21998,6 @@
22075 "loose-envify": "^1.0.0" 21998 "loose-envify": "^1.0.0"
22076 } 21999 }
22077 }, 22000 },
22078 "inversify": {
22079 "version": "5.0.1",
22080 "resolved": "https://registry.npmjs.org/inversify/-/inversify-5.0.1.tgz",
22081 "integrity": "sha512-Ieh06s48WnEYGcqHepdsJUIJUXpwH5o5vodAX+DK2JA/gjy4EbEcQZxw+uFfzysmKjiLXGYwNG3qDZsKVMcINQ==",
22082 "dev": true
22083 },
22084 "invert-kv": { 22001 "invert-kv": {
22085 "version": "2.0.0", 22002 "version": "2.0.0",
22086 "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", 22003 "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
@@ -30130,6 +30047,15 @@
30130 "integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==", 30047 "integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==",
30131 "dev": true 30048 "dev": true
30132 }, 30049 },
30050 "prettier-linter-helpers": {
30051 "version": "1.0.0",
30052 "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
30053 "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
30054 "dev": true,
30055 "requires": {
30056 "fast-diff": "^1.1.2"
30057 }
30058 },
30133 "pretty-bytes": { 30059 "pretty-bytes": {
30134 "version": "5.6.0", 30060 "version": "5.6.0",
30135 "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", 30061 "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz",
@@ -31734,12 +31660,6 @@
31734 } 31660 }
31735 } 31661 }
31736 }, 31662 },
31737 "reflect-metadata": {
31738 "version": "0.1.13",
31739 "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
31740 "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==",
31741 "dev": true
31742 },
31743 "regenerate": { 31663 "regenerate": {
31744 "version": "1.4.2", 31664 "version": "1.4.2",
31745 "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", 31665 "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
@@ -34842,152 +34762,15 @@
34842 "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", 34762 "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
34843 "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" 34763 "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
34844 }, 34764 },
34845 "tslint": {
34846 "version": "5.20.1",
34847 "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz",
34848 "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==",
34849 "dev": true,
34850 "requires": {
34851 "@babel/code-frame": "^7.0.0",
34852 "builtin-modules": "^1.1.1",
34853 "chalk": "^2.3.0",
34854 "commander": "^2.12.1",
34855 "diff": "^4.0.1",
34856 "glob": "^7.1.1",
34857 "js-yaml": "^3.13.1",
34858 "minimatch": "^3.0.4",
34859 "mkdirp": "^0.5.1",
34860 "resolve": "^1.3.2",
34861 "semver": "^5.3.0",
34862 "tslib": "^1.8.0",
34863 "tsutils": "^2.29.0"
34864 },
34865 "dependencies": {
34866 "diff": {
34867 "version": "4.0.1",
34868 "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz",
34869 "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==",
34870 "dev": true
34871 },
34872 "js-yaml": {
34873 "version": "3.14.0",
34874 "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz",
34875 "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==",
34876 "dev": true,
34877 "requires": {
34878 "argparse": "^1.0.7",
34879 "esprima": "^4.0.0"
34880 }
34881 },
34882 "semver": {
34883 "version": "5.7.1",
34884 "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
34885 "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
34886 "dev": true
34887 }
34888 }
34889 },
34890 "tslint-config-airbnb": {
34891 "version": "5.11.2",
34892 "resolved": "https://registry.npmjs.org/tslint-config-airbnb/-/tslint-config-airbnb-5.11.2.tgz",
34893 "integrity": "sha512-mUpHPTeeCFx8XARGG/kzYP4dPSOgoCqNiYbGHh09qTH8q+Y1ghsOgaeZKYYQT7IyxMos523z/QBaiv2zKNBcow==",
34894 "dev": true,
34895 "requires": {
34896 "tslint-consistent-codestyle": "^1.14.1",
34897 "tslint-eslint-rules": "^5.4.0",
34898 "tslint-microsoft-contrib": "~5.2.1"
34899 }
34900 },
34901 "tslint-consistent-codestyle": {
34902 "version": "1.16.0",
34903 "resolved": "https://registry.npmjs.org/tslint-consistent-codestyle/-/tslint-consistent-codestyle-1.16.0.tgz",
34904 "integrity": "sha512-ebR/xHyMEuU36hGNOgCfjGBNYxBPixf0yU1Yoo6s3BrpBRFccjPOmIVaVvQsWAUAMdmfzHOCihVkcaMfimqvHw==",
34905 "dev": true,
34906 "requires": {
34907 "@fimbul/bifrost": "^0.21.0",
34908 "tslib": "^1.7.1",
34909 "tsutils": "^2.29.0"
34910 }
34911 },
34912 "tslint-eslint-rules": {
34913 "version": "5.4.0",
34914 "resolved": "https://registry.npmjs.org/tslint-eslint-rules/-/tslint-eslint-rules-5.4.0.tgz",
34915 "integrity": "sha512-WlSXE+J2vY/VPgIcqQuijMQiel+UtmXS+4nvK4ZzlDiqBfXse8FAvkNnTcYhnQyOTW5KFM+uRRGXxYhFpuBc6w==",
34916 "dev": true,
34917 "requires": {
34918 "doctrine": "0.7.2",
34919 "tslib": "1.9.0",
34920 "tsutils": "^3.0.0"
34921 },
34922 "dependencies": {
34923 "doctrine": {
34924 "version": "0.7.2",
34925 "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-0.7.2.tgz",
34926 "integrity": "sha1-fLhgNZujvpDgQLJrcpzkv6ZUxSM=",
34927 "dev": true,
34928 "requires": {
34929 "esutils": "^1.1.6",
34930 "isarray": "0.0.1"
34931 }
34932 },
34933 "esutils": {
34934 "version": "1.1.6",
34935 "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz",
34936 "integrity": "sha1-wBzKqa5LiXxtDD4hCuUvPHqEQ3U=",
34937 "dev": true
34938 },
34939 "isarray": {
34940 "version": "0.0.1",
34941 "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
34942 "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
34943 "dev": true
34944 },
34945 "tslib": {
34946 "version": "1.9.0",
34947 "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz",
34948 "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==",
34949 "dev": true
34950 },
34951 "tsutils": {
34952 "version": "3.17.1",
34953 "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz",
34954 "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==",
34955 "dev": true,
34956 "requires": {
34957 "tslib": "^1.8.1"
34958 }
34959 }
34960 }
34961 },
34962 "tslint-microsoft-contrib": {
34963 "version": "5.2.1",
34964 "resolved": "https://registry.npmjs.org/tslint-microsoft-contrib/-/tslint-microsoft-contrib-5.2.1.tgz",
34965 "integrity": "sha512-PDYjvpo0gN9IfMULwKk0KpVOPMhU6cNoT9VwCOLeDl/QS8v8W2yspRpFFuUS7/c5EIH/n8ApMi8TxJAz1tfFUA==",
34966 "dev": true,
34967 "requires": {
34968 "tsutils": "^2.27.2 <2.29.0"
34969 },
34970 "dependencies": {
34971 "tsutils": {
34972 "version": "2.28.0",
34973 "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.28.0.tgz",
34974 "integrity": "sha512-bh5nAtW0tuhvOJnx1GLRn5ScraRLICGyJV5wJhtRWOLsxW70Kk5tZtpK3O/hW6LDnqKS9mlUMPZj9fEMJ0gxqA==",
34975 "dev": true,
34976 "requires": {
34977 "tslib": "^1.8.1"
34978 }
34979 }
34980 }
34981 },
34982 "tsscmp": { 34765 "tsscmp": {
34983 "version": "1.0.6", 34766 "version": "1.0.6",
34984 "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", 34767 "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz",
34985 "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==" 34768 "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA=="
34986 }, 34769 },
34987 "tsutils": { 34770 "tsutils": {
34988 "version": "2.29.0", 34771 "version": "3.21.0",
34989 "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", 34772 "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
34990 "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", 34773 "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
34991 "dev": true, 34774 "dev": true,
34992 "requires": { 34775 "requires": {
34993 "tslib": "^1.8.1" 34776 "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 @@
25 "dev": "cross-env NODE_ENV=development gulp dev", 25 "dev": "cross-env NODE_ENV=development gulp dev",
26 "test": "jest", 26 "test": "jest",
27 "test:watch": "jest --watch", 27 "test:watch": "jest --watch",
28 "lint": "eslint --quiet --fix src", 28 "lint": "eslint \"{src,packages,uidev}/**/*.{js,jsx,ts,tsx}\" --quiet --fix",
29 "manage-translations": "node ./src/i18n/manage-translations.js", 29 "manage-translations": "node ./src/i18n/manage-translations.js",
30 "prebuild": "preval-build-info-cli && gulp build", 30 "prebuild": "preval-build-info-cli && gulp build",
31 "build": "electron-builder", 31 "build": "electron-builder",
@@ -156,6 +156,8 @@
156 "@types/react": "16.14.6", 156 "@types/react": "16.14.6",
157 "@types/react-dom": "16.9.13", 157 "@types/react-dom": "16.9.13",
158 "@types/uuid": "3.4.9", 158 "@types/uuid": "3.4.9",
159 "@typescript-eslint/eslint-plugin": "4.28.5",
160 "@typescript-eslint/parser": "4.28.5",
159 "all-contributors-cli": "6.20.0", 161 "all-contributors-cli": "6.20.0",
160 "babel-loader": "8.2.2", 162 "babel-loader": "8.2.2",
161 "babel-plugin-react-intl": "3.5.1", 163 "babel-plugin-react-intl": "3.5.1",
@@ -169,11 +171,14 @@
169 "electron-rebuild": "2.3.5", 171 "electron-rebuild": "2.3.5",
170 "eslint": "7.31.0", 172 "eslint": "7.31.0",
171 "eslint-config-airbnb": "18.2.1", 173 "eslint-config-airbnb": "18.2.1",
174 "eslint-config-airbnb-typescript": "12.3.1",
175 "eslint-config-prettier": "8.3.0",
172 "eslint-plugin-import": "2.23.4", 176 "eslint-plugin-import": "2.23.4",
173 "eslint-plugin-jest": "24.4.0", 177 "eslint-plugin-jest": "24.4.0",
174 "eslint-plugin-jsx-a11y": "6.4.1", 178 "eslint-plugin-jsx-a11y": "6.4.1",
179 "eslint-plugin-prettier": "3.4.0",
175 "eslint-plugin-react": "7.24.0", 180 "eslint-plugin-react": "7.24.0",
176 "eslint-webpack-plugin": "2.5.4", 181 "eslint-plugin-react-hooks": "4.2.0",
177 "expect.js": "0.3.1", 182 "expect.js": "0.3.1",
178 "gulp": "4.0.0", 183 "gulp": "4.0.0",
179 "gulp-babel": "8.0.0", 184 "gulp-babel": "8.0.0",
@@ -196,8 +201,6 @@
196 "sass": "1.36.0", 201 "sass": "1.36.0",
197 "terser-webpack-plugin": "1.4.5", 202 "terser-webpack-plugin": "1.4.5",
198 "ts-loader": "5.4.5", 203 "ts-loader": "5.4.5",
199 "tslint": "5.20.1",
200 "tslint-config-airbnb": "5.11.2",
201 "typescript": "3.9.10", 204 "typescript": "3.9.10",
202 "webpack": "4.46.0", 205 "webpack": "4.46.0",
203 "webpack-cli": "3.3.12", 206 "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';
8import { IFormField, IWithStyle } from '../typings/generic'; 8import { IFormField, IWithStyle } from '../typings/generic';
9import { Theme } from '../../../theme'; 9import { Theme } from '../../../theme';
10 10
11type ButtonType = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'inverted'; 11type ButtonType =
12 | 'primary'
13 | 'secondary'
14 | 'success'
15 | 'danger'
16 | 'warning'
17 | 'inverted';
12 18
13interface IProps extends IFormField, IWithStyle { 19interface IProps extends IFormField, IWithStyle {
14 className?: string; 20 className?: string;
15 disabled?: boolean; 21 disabled?: boolean;
16 id?: string; 22 id?: string;
17 type?: 'button' | 'reset' | 'submit' | undefined; 23 type?: 'button' | 'reset' | 'submit' | undefined;
18 onClick: (event: React.MouseEvent<HTMLButtonElement> | React.MouseEvent<HTMLAnchorElement>) => void; 24 onClick: (
25 event:
26 | React.MouseEvent<HTMLButtonElement>
27 | React.MouseEvent<HTMLAnchorElement>,
28 ) => void;
19 buttonType?: ButtonType; 29 buttonType?: ButtonType;
20 stretch?: boolean; 30 stretch?: boolean;
21 loaded?: boolean; 31 loaded?: boolean;
@@ -25,10 +35,6 @@ interface IProps extends IFormField, IWithStyle {
25 target?: string; 35 target?: string;
26} 36}
27 37
28interface IState {
29 busy: boolean;
30}
31
32const styles = (theme: Theme) => ({ 38const styles = (theme: Theme) => ({
33 button: { 39 button: {
34 borderRadius: theme.borderRadiusSmall, 40 borderRadius: theme.borderRadiusSmall,
@@ -40,7 +46,8 @@ const styles = (theme: Theme) => ({
40 outline: 'none', 46 outline: 'none',
41 alignItems: 'center', 47 alignItems: 'center',
42 padding: 0, 48 padding: 0,
43 width: (props: IProps) => (props.stretch ? '100%' : 'auto') as Property.Width<string>, 49 width: (props: IProps) =>
50 (props.stretch ? '100%' : 'auto') as Property.Width<string>,
44 fontSize: theme.uiFontSize, 51 fontSize: theme.uiFontSize,
45 textDecoration: 'none', 52 textDecoration: 'none',
46 // height: theme.buttonHeight, 53 // height: theme.buttonHeight,
@@ -125,7 +132,8 @@ const styles = (theme: Theme) => ({
125 transition: 'all 0.3s', 132 transition: 'all 0.3s',
126 marginLeft: (props: IProps): number => (!props.busy ? 10 : 20), 133 marginLeft: (props: IProps): number => (!props.busy ? 10 : 20),
127 marginRight: (props: IProps): number => (!props.busy ? -10 : -20), 134 marginRight: (props: IProps): number => (!props.busy ? -10 : -20),
128 position: (props: IProps): Property.Position => props.stretch ? 'absolute' : 'inherit', 135 position: (props: IProps): Property.Position =>
136 props.stretch ? 'absolute' : 'inherit',
129 }, 137 },
130 icon: { 138 icon: {
131 margin: [1, 10, 0, -5], 139 margin: [1, 10, 0, -5],
@@ -175,7 +183,6 @@ class ButtonComponent extends Component<IProps> {
175 buttonType, 183 buttonType,
176 loaded, 184 loaded,
177 icon, 185 icon,
178 busy: busyProp,
179 href, 186 href,
180 target, 187 target,
181 } = this.props; 188 } = this.props;
@@ -185,7 +192,9 @@ class ButtonComponent extends Component<IProps> {
185 let showLoader = false; 192 let showLoader = false;
186 if (loaded) { 193 if (loaded) {
187 showLoader = !loaded; 194 showLoader = !loaded;
188 console.warn('Ferdi Button prop `loaded` will be deprecated in the future. Please use `busy` instead'); 195 console.warn(
196 'Ferdi Button prop `loaded` will be deprecated in the future. Please use `busy` instead',
197 );
189 } 198 }
190 if (busy) { 199 if (busy) {
191 showLoader = busy; 200 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 {
11 11
12class ErrorComponent extends Component<IProps> { 12class ErrorComponent extends Component<IProps> {
13 render() { 13 render() {
14 const { 14 const { classes, message } = this.props;
15 classes,
16 message,
17 } = this.props;
18 15
19 return ( 16 return <p className={classes.message}>{message}</p>;
20 <p
21 className={classes.message}
22 >
23 {message}
24 </p>
25 );
26 } 17 }
27} 18}
28 19
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 {
17 [index: string]: string; 17 [index: string]: string;
18} 18}
19 19
20interface IProps extends React.InputHTMLAttributes<HTMLInputElement>, IFormField, IWithStyle { 20interface IProps
21 extends React.InputHTMLAttributes<HTMLInputElement>,
22 IFormField,
23 IWithStyle {
21 focus?: boolean; 24 focus?: boolean;
22 prefix?: string; 25 prefix?: string;
23 suffix?: string; 26 suffix?: string;
@@ -62,23 +65,24 @@ class InputComponent extends Component<IProps, IState> {
62 } 65 }
63 66
64 if (data) { 67 if (data) {
65 Object.keys(data).map(key => this.inputRef.current!.dataset[key] = data[key]); 68 Object.keys(data).map(
69 key => (this.inputRef.current!.dataset[key] = data[key]),
70 );
66 } 71 }
67 } 72 }
68 } 73 }
69 74
70 onChange(e: React.ChangeEvent<HTMLInputElement>) { 75 onChange(e: React.ChangeEvent<HTMLInputElement>) {
71 const { 76 const { scorePassword, onChange } = this.props;
72 scorePassword,
73 onChange,
74 } = this.props;
75 77
76 if (onChange) { 78 if (onChange) {
77 onChange(e); 79 onChange(e);
78 } 80 }
79 81
80 if (this.inputRef && this.inputRef.current && scorePassword) { 82 if (this.inputRef && this.inputRef.current && scorePassword) {
81 this.setState({ passwordScore: scorePasswordFunc(this.inputRef.current.value) }); 83 this.setState({
84 passwordScore: scorePasswordFunc(this.inputRef.current.value),
85 });
82 } 86 }
83 } 87 }
84 88
@@ -117,10 +121,7 @@ class InputComponent extends Component<IProps, IState> {
117 noMargin, 121 noMargin,
118 } = this.props; 122 } = this.props;
119 123
120 const { 124 const { showPassword, passwordScore } = this.state;
121 showPassword,
122 passwordScore,
123 } = this.state;
124 125
125 const inputType = type === 'password' && showPassword ? 'text' : type; 126 const inputType = type === 'password' && showPassword ? 'text' : type;
126 127
@@ -144,12 +145,9 @@ class InputComponent extends Component<IProps, IState> {
144 [`${classes.wrapper}`]: true, 145 [`${classes.wrapper}`]: true,
145 [`${classes.disabled}`]: disabled, 146 [`${classes.disabled}`]: disabled,
146 [`${classes.hasError}`]: error, 147 [`${classes.hasError}`]: error,
147 })}> 148 })}
148 {prefix && ( 149 >
149 <span className={classes.prefix}> 150 {prefix && <span className={classes.prefix}>{prefix}</span>}
150 {prefix}
151 </span>
152 )}
153 <input 151 <input
154 id={id} 152 id={id}
155 type={inputType} 153 type={inputType}
@@ -168,30 +166,29 @@ class InputComponent extends Component<IProps, IState> {
168 max={max} 166 max={max}
169 step={step} 167 step={step}
170 /> 168 />
171 {suffix && ( 169 {suffix && <span className={classes.suffix}>{suffix}</span>}
172 <span className={classes.suffix}>
173 {suffix}
174 </span>
175 )}
176 {showPasswordToggle && ( 170 {showPasswordToggle && (
177 <button 171 <button
178 type="button" 172 type="button"
179 className={classes.formModifier} 173 className={classes.formModifier}
180 onClick={() => this.setState(prevState => ({ showPassword: !prevState.showPassword }))} 174 onClick={() =>
175 this.setState(prevState => ({
176 showPassword: !prevState.showPassword,
177 }))
178 }
181 tabIndex={-1} 179 tabIndex={-1}
182 > 180 >
183 <Icon 181 <Icon path={!showPassword ? mdiEye : mdiEyeOff} size={1} />
184 path={!showPassword ? mdiEye : mdiEyeOff}
185 size={1}
186 />
187 </button> 182 </button>
188 )} 183 )}
189 </div> 184 </div>
190 {scorePassword && ( 185 {scorePassword && (
191 <div className={classnames({ 186 <div
192 [`${classes.passwordScore}`]: true, 187 className={classnames({
193 [`${classes.hasError}`]: error, 188 [`${classes.passwordScore}`]: true,
194 })}> 189 [`${classes.hasError}`]: error,
190 })}
191 >
195 <meter 192 <meter
196 value={passwordScore < 5 ? 5 : passwordScore} 193 value={passwordScore < 5 ? 5 : passwordScore}
197 low={30} 194 low={30}
@@ -202,9 +199,7 @@ class InputComponent extends Component<IProps, IState> {
202 </div> 199 </div>
203 )} 200 )}
204 </Label> 201 </Label>
205 {error && ( 202 {error && <Error message={error} />}
206 <Error message={error} />
207 )}
208 </Wrapper> 203 </Wrapper>
209 ); 204 );
210 } 205 }
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 {
11} 11}
12 12
13export function scorePasswordFunc(password: string): number { 13export function scorePasswordFunc(password: string): number {
14 let score: number = 0; 14 let score = 0;
15 if (!password) { 15 if (!password) {
16 return score; 16 return score;
17 } 17 }
@@ -32,8 +32,8 @@ export function scorePasswordFunc(password: string): number {
32 }; 32 };
33 33
34 let variationCount = 0; 34 let variationCount = 0;
35 Object.keys(variations).forEach((key) => { 35 Object.keys(variations).forEach(key => {
36 variationCount += (variations[key] === true) ? 1 : 0; 36 variationCount += variations[key] === true ? 1 : 0;
37 }); 37 });
38 38
39 score += (variationCount - 1) * 10; 39 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';
7 7
8import styles from './styles'; 8import styles from './styles';
9 9
10interface ILabel extends IFormField, React.LabelHTMLAttributes<HTMLLabelElement> { 10interface ILabel
11 extends IFormField,
12 React.LabelHTMLAttributes<HTMLLabelElement> {
11 classes: Classes; 13 classes: Classes;
12 isRequired: boolean; 14 isRequired: boolean;
13} 15}
@@ -38,11 +40,12 @@ class LabelComponent extends Component<ILabel> {
38 htmlFor={htmlFor} 40 htmlFor={htmlFor}
39 > 41 >
40 {showLabel && ( 42 {showLabel && (
41 <span className={classes.label}>{title}{isRequired && ' *'}</span> 43 <span className={classes.label}>
44 {title}
45 {isRequired && ' *'}
46 </span>
42 )} 47 )}
43 <div className={classes.content}> 48 <div className={classes.content}>{children}</div>
44 {children}
45 </div>
46 </label> 49 </label>
47 ); 50 );
48 } 51 }
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 @@
1import { mdiArrowRightDropCircleOutline, mdiCloseCircle, mdiMagnify } from '@mdi/js'; 1import {
2 mdiArrowRightDropCircleOutline,
3 mdiCloseCircle,
4 mdiMagnify,
5} from '@mdi/js';
2import Icon from '@mdi/react'; 6import Icon from '@mdi/react';
3import classnames from 'classnames'; 7import classnames from 'classnames';
4import React, { Component, createRef } from 'react'; 8import React, { Component, createRef } from 'react';
@@ -58,7 +62,7 @@ const styles = (theme: Theme) => ({
58 label: { 62 label: {
59 '& > div': { 63 '& > div': {
60 marginTop: 5, 64 marginTop: 5,
61 } 65 },
62 }, 66 },
63 popup: { 67 popup: {
64 opacity: 0, 68 opacity: 0,
@@ -153,9 +157,13 @@ class SelectComponent extends Component<IProps> {
153 }; 157 };
154 158
155 private componentRef = createRef<HTMLDivElement>(); 159 private componentRef = createRef<HTMLDivElement>();
160
156 private inputRef = createRef<HTMLInputElement>(); 161 private inputRef = createRef<HTMLInputElement>();
162
157 private searchInputRef = createRef<HTMLInputElement>(); 163 private searchInputRef = createRef<HTMLInputElement>();
164
158 private scrollContainerRef = createRef<HTMLDivElement>(); 165 private scrollContainerRef = createRef<HTMLDivElement>();
166
159 private activeOptionRef = createRef<HTMLDivElement>(); 167 private activeOptionRef = createRef<HTMLDivElement>();
160 168
161 private keyListener: any; 169 private keyListener: any;
@@ -168,7 +176,7 @@ class SelectComponent extends Component<IProps> {
168 } 176 }
169 } 177 }
170 178
171 componentDidUpdate(prevProps: IProps, prevState: IState) { 179 componentDidUpdate() {
172 const { open } = this.state; 180 const { open } = this.state;
173 181
174 if (this.searchInputRef && this.searchInputRef.current) { 182 if (this.searchInputRef && this.searchInputRef.current) {
@@ -183,7 +191,9 @@ class SelectComponent extends Component<IProps> {
183 const { data } = this.props; 191 const { data } = this.props;
184 192
185 if (data) { 193 if (data) {
186 Object.keys(data).map(key => this.inputRef.current!.dataset[key] = data[key]); 194 Object.keys(data).map(
195 key => (this.inputRef.current!.dataset[key] = data[key]),
196 );
187 } 197 }
188 } 198 }
189 199
@@ -194,7 +204,10 @@ class SelectComponent extends Component<IProps> {
194 const { value } = this.props; 204 const { value } = this.props;
195 205
196 if (this.componentRef && this.componentRef.current) { 206 if (this.componentRef && this.componentRef.current) {
197 this.componentRef.current.removeEventListener('keydown', this.keyListener); 207 this.componentRef.current.removeEventListener(
208 'keydown',
209 this.keyListener,
210 );
198 } 211 }
199 212
200 if (value) { 213 if (value) {
@@ -210,13 +223,18 @@ class SelectComponent extends Component<IProps> {
210 window.removeEventListener('keydown', this.arrowKeysHandler.bind(this)); 223 window.removeEventListener('keydown', this.arrowKeysHandler.bind(this));
211 } 224 }
212 225
213 setFilter(needle: string = '') { 226 setFilter(needle = '') {
214 const { options } = this.props; 227 const { options } = this.props;
215 228
216 let filteredOptions = {}; 229 let filteredOptions = {};
217 if (needle) { 230 if (needle) {
218 Object.keys(options).map((key) => { 231 Object.keys(options).map(key => {
219 if (key.toLocaleLowerCase().startsWith(needle.toLocaleLowerCase()) || options[key].toLocaleLowerCase().startsWith(needle.toLocaleLowerCase())) { 232 if (
233 key.toLocaleLowerCase().startsWith(needle.toLocaleLowerCase()) ||
234 options[key]
235 .toLocaleLowerCase()
236 .startsWith(needle.toLocaleLowerCase())
237 ) {
220 Object.assign(filteredOptions, { 238 Object.assign(filteredOptions, {
221 [`${key}`]: options[key], 239 [`${key}`]: options[key],
222 }); 240 });
@@ -234,7 +252,7 @@ class SelectComponent extends Component<IProps> {
234 } 252 }
235 253
236 select(key: string) { 254 select(key: string) {
237 this.setState((state: IState) => ({ 255 this.setState(() => ({
238 value: key, 256 value: key,
239 open: false, 257 open: false,
240 })); 258 }));
@@ -247,11 +265,7 @@ class SelectComponent extends Component<IProps> {
247 } 265 }
248 266
249 arrowKeysHandler(e: KeyboardEvent) { 267 arrowKeysHandler(e: KeyboardEvent) {
250 const { 268 const { selected, open, options } = this.state;
251 selected,
252 open,
253 options,
254 } = this.state;
255 269
256 if (!open) return; 270 if (!open) return;
257 271
@@ -264,7 +278,10 @@ class SelectComponent extends Component<IProps> {
264 this.setState((state: IState) => ({ 278 this.setState((state: IState) => ({
265 selected: state.selected - 1, 279 selected: state.selected - 1,
266 })); 280 }));
267 } else if (e.keyCode === 40 && selected < Object.keys(options!).length - 1) { 281 } else if (
282 e.keyCode === 40 &&
283 selected < Object.keys(options!).length - 1
284 ) {
268 this.setState((state: IState) => ({ 285 this.setState((state: IState) => ({
269 selected: state.selected + 1, 286 selected: state.selected + 1,
270 })); 287 }));
@@ -272,7 +289,12 @@ class SelectComponent extends Component<IProps> {
272 this.select(Object.keys(options!)[selected]); 289 this.select(Object.keys(options!)[selected]);
273 } 290 }
274 291
275 if (this.activeOptionRef && this.activeOptionRef.current && this.scrollContainerRef && this.scrollContainerRef.current) { 292 if (
293 this.activeOptionRef &&
294 this.activeOptionRef.current &&
295 this.scrollContainerRef &&
296 this.scrollContainerRef.current
297 ) {
276 const containerTopOffset = this.scrollContainerRef.current.offsetTop; 298 const containerTopOffset = this.scrollContainerRef.current.offsetTop;
277 const optionTopOffset = this.activeOptionRef.current.offsetTop; 299 const optionTopOffset = this.activeOptionRef.current.offsetTop;
278 300
@@ -282,10 +304,15 @@ class SelectComponent extends Component<IProps> {
282 } 304 }
283 } 305 }
284 306
285 switch (e.keyCode){ 307 switch (e.keyCode) {
286 case 37: case 39: case 38: case 40: // Arrow keys 308 case 37:
287 case 32: break; // Space 309 case 39:
288 default: break; // do not block other keys 310 case 38:
311 case 40: // Arrow keys
312 case 32:
313 break; // Space
314 default:
315 break; // do not block other keys
289 } 316 }
290 } 317 }
291 318
@@ -307,13 +334,7 @@ class SelectComponent extends Component<IProps> {
307 required, 334 required,
308 } = this.props; 335 } = this.props;
309 336
310 const { 337 const { open, needle, value, selected, options } = this.state;
311 open,
312 needle,
313 value,
314 selected,
315 options,
316 } = this.state;
317 338
318 let selection = ''; 339 let selection = '';
319 if (!value && defaultValue && options![defaultValue]) { 340 if (!value && defaultValue && options![defaultValue]) {
@@ -325,10 +346,7 @@ class SelectComponent extends Component<IProps> {
325 } 346 }
326 347
327 return ( 348 return (
328 <Wrapper 349 <Wrapper className={className} identifier="franz-select">
329 className={className}
330 identifier="franz-select"
331 >
332 <Label 350 <Label
333 title={label} 351 title={label}
334 showLabel={showLabel} 352 showLabel={showLabel}
@@ -345,14 +363,19 @@ class SelectComponent extends Component<IProps> {
345 > 363 >
346 <button 364 <button
347 type="button" 365 type="button"
348 className={classnames({ 366 className={classnames({
349 [`${inputClassName}`]: inputClassName, 367 [`${inputClassName}`]: inputClassName,
350 [`${classes.select}`]: true, 368 [`${classes.select}`]: true,
351 [`${classes.hasError}`]: error, 369 [`${classes.hasError}`]: error,
352 })} 370 })}
353 onClick= {!disabled ? () => this.setState((state: IState) => ({ 371 onClick={
354 open: !state.open, 372 !disabled
355 })) : () => {}} 373 ? () =>
374 this.setState((state: IState) => ({
375 open: !state.open,
376 }))
377 : () => {}
378 }
356 > 379 >
357 {selection} 380 {selection}
358 <Icon 381 <Icon
@@ -366,10 +389,7 @@ class SelectComponent extends Component<IProps> {
366 </button> 389 </button>
367 {showSearch && open && ( 390 {showSearch && open && (
368 <div className={classes.searchContainer}> 391 <div className={classes.searchContainer}>
369 <Icon 392 <Icon path={mdiMagnify} size={0.8} />
370 path={mdiMagnify}
371 size={0.8}
372 />
373 <input 393 <input
374 type="text" 394 type="text"
375 value={needle} 395 value={needle}
@@ -384,10 +404,7 @@ class SelectComponent extends Component<IProps> {
384 className={classes.clearNeedle} 404 className={classes.clearNeedle}
385 onClick={() => this.setFilter()} 405 onClick={() => this.setFilter()}
386 > 406 >
387 <Icon 407 <Icon path={mdiCloseCircle} size={0.7} />
388 path={mdiCloseCircle}
389 size={0.7}
390 />
391 </button> 408 </button>
392 )} 409 )}
393 </div> 410 </div>
@@ -399,7 +416,7 @@ class SelectComponent extends Component<IProps> {
399 })} 416 })}
400 ref={this.scrollContainerRef} 417 ref={this.scrollContainerRef}
401 > 418 >
402 {Object.keys(options!).map(((key, i) => ( 419 {Object.keys(options!).map((key, i) => (
403 <div 420 <div
404 key={key} 421 key={key}
405 onClick={() => this.select(key)} 422 onClick={() => this.select(key)}
@@ -413,7 +430,7 @@ class SelectComponent extends Component<IProps> {
413 > 430 >
414 {options![key]} 431 {options![key]}
415 </div> 432 </div>
416 )))} 433 ))}
417 </div> 434 </div>
418 </div> 435 </div>
419 <input 436 <input
@@ -427,9 +444,7 @@ class SelectComponent extends Component<IProps> {
427 ref={this.inputRef} 444 ref={this.inputRef}
428 /> 445 />
429 </Label> 446 </Label>
430 {error && ( 447 {error && <Error message={error} />}
431 <Error message={error} />
432 )}
433 </Wrapper> 448 </Wrapper>
434 ); 449 );
435 } 450 }
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 {
14 [index: string]: string; 14 [index: string]: string;
15} 15}
16 16
17interface IProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement>, IFormField, IWithStyle { 17interface IProps
18 extends React.TextareaHTMLAttributes<HTMLTextAreaElement>,
19 IFormField,
20 IWithStyle {
18 focus?: boolean; 21 focus?: boolean;
19 data: IData; 22 data: IData;
20 textareaClassName?: string; 23 textareaClassName?: string;
@@ -37,14 +40,14 @@ class TextareaComponent extends Component<IProps> {
37 const { data } = this.props; 40 const { data } = this.props;
38 41
39 if (this.textareaRef && this.textareaRef.current && data) { 42 if (this.textareaRef && this.textareaRef.current && data) {
40 Object.keys(data).map(key => this.textareaRef.current!.dataset[key] = data[key]); 43 Object.keys(data).map(
44 key => (this.textareaRef.current!.dataset[key] = data[key]),
45 );
41 } 46 }
42 } 47 }
43 48
44 onChange(e: React.ChangeEvent<HTMLTextAreaElement>) { 49 onChange(e: React.ChangeEvent<HTMLTextAreaElement>) {
45 const { 50 const { onChange } = this.props;
46 onChange,
47 } = this.props;
48 51
49 if (onChange) { 52 if (onChange) {
50 onChange(e); 53 onChange(e);
@@ -57,7 +60,6 @@ class TextareaComponent extends Component<IProps> {
57 className, 60 className,
58 disabled, 61 disabled,
59 error, 62 error,
60 focus,
61 id, 63 id,
62 textareaClassName, 64 textareaClassName,
63 label, 65 label,
@@ -94,9 +96,9 @@ class TextareaComponent extends Component<IProps> {
94 [`${classes.wrapper}`]: true, 96 [`${classes.wrapper}`]: true,
95 [`${classes.disabled}`]: disabled, 97 [`${classes.disabled}`]: disabled,
96 [`${classes.hasError}`]: error, 98 [`${classes.hasError}`]: error,
97 })}> 99 })}
100 >
98 <textarea 101 <textarea
99 autoFocus={focus}
100 id={id} 102 id={id}
101 name={name} 103 name={name}
102 placeholder={placeholder} 104 placeholder={placeholder}
@@ -115,9 +117,7 @@ class TextareaComponent extends Component<IProps> {
115 </textarea> 117 </textarea>
116 </div> 118 </div>
117 </Label> 119 </Label>
118 {error && ( 120 {error && <Error message={error} />}
119 <Error message={error} />
120 )}
121 </Wrapper> 121 </Wrapper>
122 ); 122 );
123 } 123 }
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';
3import React, { Component } from 'react'; 3import React, { Component } from 'react';
4import injectStyle from 'react-jss'; 4import injectStyle from 'react-jss';
5 5
6import { IFormField, IWithStyle, Omit } from '../typings/generic'; 6import { IFormField, IWithStyle } from '../typings/generic';
7import { Theme } from '../../../theme'; 7import { Theme } from '../../../theme';
8 8
9import { Error } from '../error'; 9import { 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 {
12 12
13const styles = { 13const styles = {
14 container: { 14 container: {
15 marginBottom: (props: IProps) => props.noMargin ? 0 : 20, 15 marginBottom: (props: IProps) => (props.noMargin ? 0 : 20),
16 }, 16 },
17}; 17};
18 18
19class WrapperComponent extends Component<IProps> { 19class WrapperComponent extends Component<IProps> {
20 render() { 20 render() {
21 const { 21 const { children, classes, className, identifier } = this.props;
22 children,
23 classes,
24 className,
25 identifier,
26 } = this.props;
27 22
28 return ( 23 return (
29 <div 24 <div
diff --git a/packages/forms/tslint.json b/packages/forms/tslint.json
deleted file mode 100644
index 0946f2096..000000000
--- a/packages/forms/tslint.json
+++ /dev/null
@@ -1,3 +0,0 @@
1{
2 "extends": "../../tslint.json"
3}
diff --git a/packages/theme/src/index.ts b/packages/theme/src/index.ts
index 94df5afd1..5ba225e51 100644
--- a/packages/theme/src/index.ts
+++ b/packages/theme/src/index.ts
@@ -9,11 +9,13 @@ export enum ThemeType {
9 9
10export const DEFAULT_ACCENT_COLOR = themeBrandPrimary; 10export const DEFAULT_ACCENT_COLOR = themeBrandPrimary;
11 11
12export function theme(themeId: ThemeType, 12export function theme(
13 brandColor: string = DEFAULT_ACCENT_COLOR) { 13 themeId: ThemeType,
14 return themeId === ThemeType.dark ? 14 brandColor: string = DEFAULT_ACCENT_COLOR,
15 makeDarkThemeConfig(brandColor) : 15) {
16 makeDefaultThemeConfig(brandColor); 16 return themeId === ThemeType.dark
17 ? makeDarkThemeConfig(brandColor)
18 : makeDefaultThemeConfig(brandColor);
17} 19}
18 20
19const defaultThemeConfigWithDefaultAccentColor = 21const defaultThemeConfigWithDefaultAccentColor =
diff --git a/packages/theme/src/themes/IStyleTypes.ts b/packages/theme/src/themes/IStyleTypes.ts
index df5b51c1d..cf8bdea33 100644
--- a/packages/theme/src/themes/IStyleTypes.ts
+++ b/packages/theme/src/themes/IStyleTypes.ts
@@ -1,4 +1,3 @@
1
2export default interface IStyleTypes { 1export default interface IStyleTypes {
3 [index: string]: { 2 [index: string]: {
4 accent: string; 3 accent: string;
diff --git a/packages/theme/src/themes/dark/index.ts b/packages/theme/src/themes/dark/index.ts
index c8ad78829..7d7bab399 100644
--- a/packages/theme/src/themes/dark/index.ts
+++ b/packages/theme/src/themes/dark/index.ts
@@ -18,7 +18,9 @@ export default (brandPrimary: string) => {
18 const inputColor = legacyStyles.darkThemeGrayLightest; 18 const inputColor = legacyStyles.darkThemeGrayLightest;
19 const inputBackground = legacyStyles.themeGrayDark; 19 const inputBackground = legacyStyles.themeGrayDark;
20 const inputBorder = `1px solid ${legacyStyles.darkThemeGrayLight}`; 20 const inputBorder = `1px solid ${legacyStyles.darkThemeGrayLight}`;
21 const inputPrefixColor = color(legacyStyles.darkThemeGrayLighter).lighten(0.3).hex(); 21 const inputPrefixColor = color(legacyStyles.darkThemeGrayLighter)
22 .lighten(0.3)
23 .hex();
22 const buttonSecondaryTextColor = legacyStyles.darkThemeTextColor; 24 const buttonSecondaryTextColor = legacyStyles.darkThemeTextColor;
23 const selectColor = inputColor; 25 const selectColor = inputColor;
24 const drawerBg = color(colorBackground).lighten(0.3).hex(); 26 const drawerBg = color(colorBackground).lighten(0.3).hex();
@@ -47,7 +49,10 @@ export default (brandPrimary: string) => {
47 49
48 // Loader 50 // Loader
49 colorFullscreenLoaderSpinner: '#FFF', 51 colorFullscreenLoaderSpinner: '#FFF',
50 colorWebviewLoaderBackground: color(legacyStyles.darkThemeGrayDarkest).alpha(0.5).rgb().string(), 52 colorWebviewLoaderBackground: color(legacyStyles.darkThemeGrayDarkest)
53 .alpha(0.5)
54 .rgb()
55 .string(),
51 56
52 // Input 57 // Input
53 labelColor: legacyStyles.darkThemeTextColor, 58 labelColor: legacyStyles.darkThemeTextColor,
@@ -58,8 +63,12 @@ export default (brandPrimary: string) => {
58 inputPrefixBackground: legacyStyles.darkThemeGray, 63 inputPrefixBackground: legacyStyles.darkThemeGray,
59 inputDisabledOpacity: 0.5, 64 inputDisabledOpacity: 0.5,
60 inputScorePasswordBackground: legacyStyles.darkThemeGrayDark, 65 inputScorePasswordBackground: legacyStyles.darkThemeGrayDark,
61 inputModifierColor: color(legacyStyles.darkThemeGrayLighter).lighten(0.3).hex(), 66 inputModifierColor: color(legacyStyles.darkThemeGrayLighter)
62 inputPlaceholderColor: color(legacyStyles.darkThemeGrayLighter).darken(0.1).hex(), 67 .lighten(0.3)
68 .hex(),
69 inputPlaceholderColor: color(legacyStyles.darkThemeGrayLighter)
70 .darken(0.1)
71 .hex(),
63 72
64 // Toggle 73 // Toggle
65 toggleBackground: legacyStyles.darkThemeGray, 74 toggleBackground: legacyStyles.darkThemeGray,
@@ -91,13 +100,20 @@ export default (brandPrimary: string) => {
91 selectToggleColor: inputPrefixColor, 100 selectToggleColor: inputPrefixColor,
92 selectPopupBackground: legacyStyles.darkThemeGrayLight, 101 selectPopupBackground: legacyStyles.darkThemeGrayLight,
93 selectOptionColor: '#FFF', 102 selectOptionColor: '#FFF',
94 selectOptionBorder: `1px solid ${color(legacyStyles.darkThemeGrayLight).darken(0.2).hex()}`, 103 selectOptionBorder: `1px solid ${color(legacyStyles.darkThemeGrayLight)
95 selectOptionItemHover: color(legacyStyles.darkThemeGrayLight).darken(0.2).hex(), 104 .darken(0.2)
105 .hex()}`,
106 selectOptionItemHover: color(legacyStyles.darkThemeGrayLight)
107 .darken(0.2)
108 .hex(),
96 selectOptionItemHoverColor: selectColor, 109 selectOptionItemHoverColor: selectColor,
97 selectSearchColor: inputBackground, 110 selectSearchColor: inputBackground,
98 111
99 // Modal 112 // Modal
100 colorModalOverlayBackground: color(legacyStyles.darkThemeBlack).alpha(0.9).rgb().string(), 113 colorModalOverlayBackground: color(legacyStyles.darkThemeBlack)
114 .alpha(0.9)
115 .rgb()
116 .string(),
101 colorModalBackground: legacyStyles.darkThemeGrayDark, 117 colorModalBackground: legacyStyles.darkThemeGrayDark,
102 118
103 // Services 119 // 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) => {
82 82
83 colorText, 83 colorText,
84 84
85 defaultContentBorder: color(legacyStyles.themeGrayLighter).darken(0.1).rgb().string(), 85 defaultContentBorder: color(legacyStyles.themeGrayLighter)
86 .darken(0.1)
87 .rgb()
88 .string(),
86 89
87 // Subscription Container Component 90 // Subscription Container Component
88 colorSubscriptionContainerBackground: 'none', 91 colorSubscriptionContainerBackground: 'none',
@@ -94,7 +97,10 @@ export default (brandPrimary: string) => {
94 // Loader 97 // Loader
95 colorAppLoaderSpinner: '#FFF', 98 colorAppLoaderSpinner: '#FFF',
96 colorFullscreenLoaderSpinner: legacyStyles.themeGrayDark, 99 colorFullscreenLoaderSpinner: legacyStyles.themeGrayDark,
97 colorWebviewLoaderBackground: color(legacyStyles.themeGrayLighter).alpha(0.8).rgb().string(), 100 colorWebviewLoaderBackground: color(legacyStyles.themeGrayLighter)
101 .alpha(0.8)
102 .rgb()
103 .string(),
98 104
99 // Input 105 // Input
100 labelColor: legacyStyles.themeGrayLight, 106 labelColor: legacyStyles.themeGrayLight,
@@ -103,7 +109,9 @@ export default (brandPrimary: string) => {
103 inputBackground, 109 inputBackground,
104 inputBorder, 110 inputBorder,
105 inputModifierColor: legacyStyles.themeGrayLight, 111 inputModifierColor: legacyStyles.themeGrayLight,
106 inputPlaceholderColor: color(legacyStyles.themeGrayLight).lighten(0.3).hex(), 112 inputPlaceholderColor: color(legacyStyles.themeGrayLight)
113 .lighten(0.3)
114 .hex(),
107 inputPrefixColor, 115 inputPrefixColor,
108 inputPrefixBackground: legacyStyles.themeGrayLighter, 116 inputPrefixBackground: legacyStyles.themeGrayLighter,
109 inputDisabledOpacity, 117 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 @@
1{
2 "extends": "../../tslint.json"
3}
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 {
36 className?: string; 36 className?: string;
37} 37}
38 38
39declare class ReactLoader extends Component<LoaderProps> { 39declare class ReactLoader extends Component<LoaderProps> {
40} 40}
41 41
42declare namespace ReactLoader { 42declare 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';
3import React, { Component } from 'react'; 3import React, { Component } from 'react';
4import injectStyle from 'react-jss'; 4import injectStyle from 'react-jss';
5 5
6import { Badge, Icon } from '../'; 6import { Badge, Icon } from '..';
7import { Theme } from '../../../theme'; 7import { Theme } from '../../../theme';
8import { IWithStyle } from '../typings/generic'; 8import { IWithStyle } from '../typings/generic';
9 9
@@ -34,13 +34,8 @@ const styles = (theme: Theme) => ({
34 34
35class ProBadgeComponent extends Component<IProps> { 35class ProBadgeComponent extends Component<IProps> {
36 render() { 36 render() {
37 const { 37 const { classes, badgeClasses, iconClasses, inverted, className } =
38 classes, 38 this.props;
39 badgeClasses,
40 iconClasses,
41 inverted,
42 className,
43 } = this.props;
44 39
45 return ( 40 return (
46 <Badge 41 <Badge
diff --git a/packages/ui/src/badge/index.tsx b/packages/ui/src/badge/index.tsx
index 0ba383673..5dd735879 100644
--- a/packages/ui/src/badge/index.tsx
+++ b/packages/ui/src/badge/index.tsx
@@ -13,7 +13,7 @@ interface IProps extends IWithStyle {
13 13
14const badgeStyles = (theme: Theme) => { 14const badgeStyles = (theme: Theme) => {
15 const styles = {}; 15 const styles = {};
16 Object.keys(theme.styleTypes).map((style) => { 16 Object.keys(theme.styleTypes).map(style => {
17 Object.assign(styles, { 17 Object.assign(styles, {
18 [style]: { 18 [style]: {
19 background: theme.styleTypes[style].accent, 19 background: theme.styleTypes[style].accent,
@@ -51,12 +51,7 @@ class BadgeComponent extends Component<IProps> {
51 }; 51 };
52 52
53 render() { 53 render() {
54 const { 54 const { classes, children, type, className } = this.props;
55 classes,
56 children,
57 type,
58 className,
59 } = this.props;
60 55
61 return ( 56 return (
62 <div 57 <div
diff --git a/packages/ui/src/headline/index.tsx b/packages/ui/src/headline/index.tsx
index 11b6125cd..bf3d4418c 100644
--- a/packages/ui/src/headline/index.tsx
+++ b/packages/ui/src/headline/index.tsx
@@ -37,13 +37,7 @@ const styles = (theme: Theme) => ({
37 37
38class HeadlineComponent extends Component<IProps> { 38class HeadlineComponent extends Component<IProps> {
39 render() { 39 render() {
40 const { 40 const { classes, level, className, children, id } = this.props;
41 classes,
42 level,
43 className,
44 children,
45 id,
46 } = this.props;
47 41
48 return React.createElement( 42 return React.createElement(
49 `h${level}`, 43 `h${level}`,
@@ -63,7 +57,12 @@ class HeadlineComponent extends Component<IProps> {
63 57
64const Headline = injectStyle(styles)(HeadlineComponent); 58const Headline = injectStyle(styles)(HeadlineComponent);
65 59
66const createH = (level: number) => (props: Omit<IProps, 'classes' | 'theme'>) => <Headline level={level} {...props}>{props.children}</Headline>; 60const createH = (level: number) => (props: Omit<IProps, 'classes' | 'theme'>) =>
61 (
62 <Headline level={level} {...props}>
63 {props.children}
64 </Headline>
65 );
67 66
68export const H1 = createH(1); 67export const H1 = createH(1);
69export const H2 = createH(2); 68export 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<IProps> {
24 }; 24 };
25 25
26 render() { 26 render() {
27 const { 27 const { classes, icon, size, className } = this.props;
28 classes,
29 icon,
30 size,
31 className,
32 } = this.props;
33 28
34 if (!icon) { 29 if (!icon) {
35 console.warn('No Icon specified'); 30 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';
3import React, { Component } from 'react'; 3import React, { Component } from 'react';
4import injectStyle from 'react-jss'; 4import injectStyle from 'react-jss';
5 5
6import { Icon } from '..';
6import { Theme } from '../../../theme'; 7import { Theme } from '../../../theme';
7import { Icon } from '../';
8import { IWithStyle } from '../typings/generic'; 8import { IWithStyle } from '../typings/generic';
9 9
10interface IProps extends IWithStyle { 10interface IProps extends IWithStyle {
@@ -27,7 +27,7 @@ interface IState {
27 27
28const buttonStyles = (theme: Theme) => { 28const buttonStyles = (theme: Theme) => {
29 const styles = {}; 29 const styles = {};
30 Object.keys(theme.styleTypes).map((style) => { 30 Object.keys(theme.styleTypes).map(style => {
31 Object.assign(styles, { 31 Object.assign(styles, {
32 [style]: { 32 [style]: {
33 background: theme.styleTypes[style].accent, 33 background: theme.styleTypes[style].accent,
@@ -73,18 +73,21 @@ const styles = (theme: Theme) => ({
73 marginRight: 10, 73 marginRight: 10,
74 }, 74 },
75 close: { 75 close: {
76 color: (props: IProps) => theme.styleTypes[props.type ? props.type : 'primary'].contrast, 76 color: (props: IProps) =>
77 theme.styleTypes[props.type ? props.type : 'primary'].contrast,
77 marginRight: -5, 78 marginRight: -5,
78 border: 0, 79 border: 0,
79 background: 'none', 80 background: 'none',
80 }, 81 },
81 cta: { 82 cta: {
82 borderColor: (props: IProps) => theme.styleTypes[props.type ? props.type : 'primary'].contrast, 83 borderColor: (props: IProps) =>
84 theme.styleTypes[props.type ? props.type : 'primary'].contrast,
83 borderRadius: theme.borderRadiusSmall, 85 borderRadius: theme.borderRadiusSmall,
84 borderStyle: 'solid', 86 borderStyle: 'solid',
85 borderWidth: 1, 87 borderWidth: 1,
86 background: 'none', 88 background: 'none',
87 color: (props: IProps) => theme.styleTypes[props.type ? props.type : 'primary'].contrast, 89 color: (props: IProps) =>
90 theme.styleTypes[props.type ? props.type : 'primary'].contrast,
88 marginLeft: 15, 91 marginLeft: 15,
89 padding: [4, 10], 92 padding: [4, 10],
90 fontSize: theme.uiFontSize, 93 fontSize: theme.uiFontSize,
@@ -113,9 +116,7 @@ class InfoboxComponent extends Component<IProps, IState> {
113 }; 116 };
114 117
115 dismiss() { 118 dismiss() {
116 const { 119 const { onDismiss } = this.props;
117 onDismiss,
118 } = this.props;
119 120
120 this.setState({ 121 this.setState({
121 isDismissing: true, 122 isDismissing: true,
@@ -129,7 +130,7 @@ class InfoboxComponent extends Component<IProps, IState> {
129 this.setState({ 130 this.setState({
130 dismissed: true, 131 dismissed: true,
131 }); 132 });
132 }, 3000); 133 }, 3000);
133 } 134 }
134 135
135 componentWillUnmount(): void { 136 componentWillUnmount(): void {
@@ -144,26 +145,24 @@ class InfoboxComponent extends Component<IProps, IState> {
144 icon, 145 icon,
145 type, 146 type,
146 ctaLabel, 147 ctaLabel,
147 ctaLoading,
148 ctaOnClick, 148 ctaOnClick,
149 dismissable, 149 dismissable,
150 className, 150 className,
151 } = this.props; 151 } = this.props;
152 152
153 const { 153 const { isDismissing, dismissed } = this.state;
154 isDismissing,
155 dismissed,
156 } = this.state;
157 154
158 if (dismissed) { 155 if (dismissed) {
159 return null; 156 return null;
160 } 157 }
161 158
162 return ( 159 return (
163 <div className={classnames({ 160 <div
164 [classes.wrapper]: true, 161 className={classnames({
165 [`${className}`]: className, 162 [classes.wrapper]: true,
166 })}> 163 [`${className}`]: className,
164 })}
165 >
167 <div 166 <div
168 className={classnames({ 167 className={classnames({
169 [classes.infobox]: true, 168 [classes.infobox]: true,
@@ -172,18 +171,10 @@ class InfoboxComponent extends Component<IProps, IState> {
172 })} 171 })}
173 data-type="franz-infobox" 172 data-type="franz-infobox"
174 > 173 >
175 {icon && ( 174 {icon && <Icon icon={icon} className={classes.icon} />}
176 <Icon icon={icon} className={classes.icon} /> 175 <div className={classes.content}>{children}</div>
177 )}
178 <div className={classes.content}>
179 {children}
180 </div>
181 {ctaLabel && ( 176 {ctaLabel && (
182 <button 177 <button className={classes.cta} onClick={ctaOnClick} type="button">
183 className={classes.cta}
184 onClick={ctaOnClick}
185 type="button"
186 >
187 {ctaLabel} 178 {ctaLabel}
188 </button> 179 </button>
189 )} 180 )}
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';
3import injectStyle, { withTheme } from 'react-jss'; 3import injectStyle, { withTheme } from 'react-jss';
4import ReactLoader from 'react-loader'; 4import ReactLoader from 'react-loader';
5 5
6import { Theme } from '../../../theme';
7import { IWithStyle } from '../typings/generic'; 6import { IWithStyle } from '../typings/generic';
8 7
9interface IProps extends IWithStyle { 8interface IProps extends IWithStyle {
@@ -11,7 +10,7 @@ interface IProps extends IWithStyle {
11 color?: string; 10 color?: string;
12} 11}
13 12
14const styles = (theme: Theme) => ({ 13const styles = () => ({
15 container: { 14 container: {
16 position: 'relative', 15 position: 'relative',
17 height: 60, 16 height: 60,
@@ -20,12 +19,7 @@ const styles = (theme: Theme) => ({
20 19
21class LoaderComponent extends Component<IProps> { 20class LoaderComponent extends Component<IProps> {
22 render() { 21 render() {
23 const { 22 const { classes, className, color, theme } = this.props;
24 classes,
25 className,
26 color,
27 theme,
28 } = this.props;
29 23
30 return ( 24 return (
31 <div 25 <div
diff --git a/packages/ui/tslint.json b/packages/ui/tslint.json
deleted file mode 100644
index 0946f2096..000000000
--- a/packages/ui/tslint.json
+++ /dev/null
@@ -1,3 +0,0 @@
1{
2 "extends": "../../tslint.json"
3}
diff --git a/src/actions/lib/actions.js b/src/actions/lib/actions.js
index b38db9946..7be40f1cf 100644
--- a/src/actions/lib/actions.js
+++ b/src/actions/lib/actions.js
@@ -8,12 +8,12 @@ export const createActionsFromDefinitions = (actionDefinitions, validate) => {
8 }; 8 };
9 actions[actionName] = action; 9 actions[actionName] = action;
10 action.listeners = []; 10 action.listeners = [];
11 action.listen = listener => action.listeners.push(listener); 11 action.listen = (listener) => action.listeners.push(listener);
12 action.off = (listener) => { 12 action.off = (listener) => {
13 const { listeners } = action; 13 const { listeners } = action;
14 listeners.splice(listeners.indexOf(listener), 1); 14 listeners.splice(listeners.indexOf(listener), 1);
15 }; 15 };
16 action.notify = params => action.listeners.forEach(listener => listener(params)); 16 action.notify = (params) => action.listeners.forEach((listener) => listener(params));
17 }); 17 });
18 return actions; 18 return actions;
19}; 19};
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';
2import { session } from '@electron/remote'; 2import { session } from '@electron/remote';
3import du from 'du'; 3import du from 'du';
4 4
5import { getServicePartitionsDirectory } from '../../helpers/service-helpers.js'; 5import { getServicePartitionsDirectory } from '../../helpers/service-helpers';
6 6
7const debug = require('debug')('Ferdi:LocalApi'); 7const debug = require('debug')('Ferdi:LocalApi');
8 8
@@ -41,11 +41,23 @@ export default class LocalApi {
41 } 41 }
42 42
43 async clearCache(serviceId = null) { 43 async clearCache(serviceId = null) {
44 const s = serviceId ? session.fromPartition(`persist:service-${serviceId}`) : session.defaultSession; 44 const s = serviceId
45 ? session.fromPartition(`persist:service-${serviceId}`)
46 : session.defaultSession;
45 47
46 debug('LocalApi::clearCache resolves', (serviceId || 'clearAppCache')); 48 debug('LocalApi::clearCache resolves', serviceId || 'clearAppCache');
47 await s.clearStorageData({ 49 await s.clearStorageData({
48 storages: ['appcache', 'cookies', 'filesystem', 'indexdb', 'localstorage', 'shadercache', 'websql', 'serviceworkers', 'cachestorage'], 50 storages: [
51 'appcache',
52 'cookies',
53 'filesystem',
54 'indexdb',
55 'localstorage',
56 'shadercache',
57 'websql',
58 'serviceworkers',
59 'cachestorage',
60 ],
49 quotas: ['temporary', 'persistent', 'syncable'], 61 quotas: ['temporary', 'persistent', 'syncable'],
50 }); 62 });
51 return s.clearCache(); 63 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 {
23 loadRecipeConfig, 23 loadRecipeConfig,
24} from '../../helpers/recipe-helpers'; 24} from '../../helpers/recipe-helpers';
25 25
26import { 26import { removeServicePartitionDirectory } from '../../helpers/service-helpers';
27 removeServicePartitionDirectory,
28} from '../../helpers/service-helpers.js';
29 27
30const debug = require('debug')('Ferdi:ServerApi'); 28const debug = require('debug')('Ferdi:ServerApi');
31 29
32module.paths.unshift( 30module.paths.unshift(getDevRecipeDirectory(), getRecipeDirectory());
33 getDevRecipeDirectory(),
34 getRecipeDirectory(),
35);
36 31
37const { default: fetch } = remoteRequire('electron-fetch'); 32const { default: fetch } = remoteRequire('electron-fetch');
38 33
@@ -43,12 +38,16 @@ export default class ServerApi {
43 38
44 // User 39 // User
45 async login(email, passwordHash) { 40 async login(email, passwordHash) {
46 const request = await sendAuthRequest(`${apiBase()}/auth/login`, { 41 const request = await sendAuthRequest(
47 method: 'POST', 42 `${apiBase()}/auth/login`,
48 headers: { 43 {
49 Authorization: `Basic ${window.btoa(`${email}:${passwordHash}`)}`, 44 method: 'POST',
45 headers: {
46 Authorization: `Basic ${window.btoa(`${email}:${passwordHash}`)}`,
47 },
50 }, 48 },
51 }, false); 49 false,
50 );
52 if (!request.ok) { 51 if (!request.ok) {
53 throw request; 52 throw request;
54 } 53 }
@@ -59,10 +58,14 @@ export default class ServerApi {
59 } 58 }
60 59
61 async signup(data) { 60 async signup(data) {
62 const request = await sendAuthRequest(`${apiBase()}/auth/signup`, { 61 const request = await sendAuthRequest(
63 method: 'POST', 62 `${apiBase()}/auth/signup`,
64 body: JSON.stringify(data), 63 {
65 }, false); 64 method: 'POST',
65 body: JSON.stringify(data),
66 },
67 false,
68 );
66 if (!request.ok) { 69 if (!request.ok) {
67 throw request; 70 throw request;
68 } 71 }
@@ -86,12 +89,16 @@ export default class ServerApi {
86 } 89 }
87 90
88 async retrievePassword(email) { 91 async retrievePassword(email) {
89 const request = await sendAuthRequest(`${apiBase()}/auth/password`, { 92 const request = await sendAuthRequest(
90 method: 'POST', 93 `${apiBase()}/auth/password`,
91 body: JSON.stringify({ 94 {
92 email, 95 method: 'POST',
93 }), 96 body: JSON.stringify({
94 }, false); 97 email,
98 }),
99 },
100 false,
101 );
95 if (!request.ok) { 102 if (!request.ok) {
96 throw request; 103 throw request;
97 } 104 }
@@ -128,7 +135,9 @@ export default class ServerApi {
128 } 135 }
129 const updatedData = await request.json(); 136 const updatedData = await request.json();
130 137
131 const user = Object.assign(updatedData, { data: new UserModel(updatedData.data) }); 138 const user = Object.assign(updatedData, {
139 data: new UserModel(updatedData.data),
140 });
132 debug('ServerApi::updateUserInfo resolves', user); 141 debug('ServerApi::updateUserInfo resolves', user);
133 return user; 142 return user;
134 } 143 }
@@ -159,7 +168,7 @@ export default class ServerApi {
159 const data = await request.json(); 168 const data = await request.json();
160 169
161 let services = await this._mapServiceModels(data); 170 let services = await this._mapServiceModels(data);
162 services = services.filter(service => service !== null); 171 services = services.filter((service) => service !== null);
163 debug('ServerApi::getServices resolves', services); 172 debug('ServerApi::getServices resolves', services);
164 return services; 173 return services;
165 } 174 }
@@ -175,12 +184,17 @@ export default class ServerApi {
175 const serviceData = await request.json(); 184 const serviceData = await request.json();
176 185
177 if (data.iconFile) { 186 if (data.iconFile) {
178 const iconData = await this.uploadServiceIcon(serviceData.data.id, data.iconFile); 187 const iconData = await this.uploadServiceIcon(
188 serviceData.data.id,
189 data.iconFile,
190 );
179 191
180 serviceData.data = iconData; 192 serviceData.data = iconData;
181 } 193 }
182 194
183 const service = Object.assign(serviceData, { data: await this._prepareServiceModel(serviceData.data) }); 195 const service = Object.assign(serviceData, {
196 data: await this._prepareServiceModel(serviceData.data),
197 });
184 198
185 debug('ServerApi::createService resolves', service); 199 debug('ServerApi::createService resolves', service);
186 return service; 200 return service;
@@ -204,7 +218,9 @@ export default class ServerApi {
204 218
205 const serviceData = await request.json(); 219 const serviceData = await request.json();
206 220
207 const service = Object.assign(serviceData, { data: await this._prepareServiceModel(serviceData.data) }); 221 const service = Object.assign(serviceData, {
222 data: await this._prepareServiceModel(serviceData.data),
223 });
208 224
209 debug('ServerApi::updateService resolves', service); 225 debug('ServerApi::updateService resolves', service);
210 return service; 226 return service;
@@ -221,7 +237,10 @@ export default class ServerApi {
221 237
222 delete requestData.headers['Content-Type']; 238 delete requestData.headers['Content-Type'];
223 239
224 const request = await window.fetch(`${apiBase()}/service/${serviceId}`, requestData); 240 const request = await window.fetch(
241 `${apiBase()}/service/${serviceId}`,
242 requestData,
243 );
225 244
226 if (!request.ok) { 245 if (!request.ok) {
227 throw request; 246 throw request;
@@ -292,18 +311,21 @@ export default class ServerApi {
292 // Recipes 311 // Recipes
293 async getInstalledRecipes() { 312 async getInstalledRecipes() {
294 const recipesDirectory = getRecipeDirectory(); 313 const recipesDirectory = getRecipeDirectory();
295 const paths = fs.readdirSync(recipesDirectory) 314 const paths = fs
296 .filter(file => ( 315 .readdirSync(recipesDirectory)
297 fs.statSync(path.join(recipesDirectory, file)).isDirectory() 316 .filter(
298 && file !== 'temp' 317 (file) => fs.statSync(path.join(recipesDirectory, file)).isDirectory()
299 && file !== 'dev' 318 && file !== 'temp'
300 )); 319 && file !== 'dev',
301 320 );
302 this.recipes = paths.map((id) => { 321
303 // eslint-disable-next-line 322 this.recipes = paths
304 const Recipe = require(id)(RecipeModel); 323 .map((id) => {
305 return new Recipe(loadRecipeConfig(id)); 324 // eslint-disable-next-line
306 }).filter(recipe => recipe.id); 325 const Recipe = require(id)(RecipeModel);
326 return new Recipe(loadRecipeConfig(id));
327 })
328 .filter((recipe) => recipe.id);
307 329
308 this.recipes = this.recipes.concat(this._getDevRecipes()); 330 this.recipes = this.recipes.concat(this._getDevRecipes());
309 331
@@ -373,7 +395,9 @@ export default class ServerApi {
373 console.log('[ServerApi::getRecipePackage] Using internal recipe file'); 395 console.log('[ServerApi::getRecipePackage] Using internal recipe file');
374 archivePath = internalRecipeFile; 396 archivePath = internalRecipeFile;
375 } else { 397 } else {
376 console.log('[ServerApi::getRecipePackage] Downloading recipe from server'); 398 console.log(
399 '[ServerApi::getRecipePackage] Downloading recipe from server',
400 );
377 archivePath = tempArchivePath; 401 archivePath = tempArchivePath;
378 402
379 const packageUrl = `${apiBase()}/recipes/download/${recipeId}`; 403 const packageUrl = `${apiBase()}/recipes/download/${recipeId}`;
@@ -393,12 +417,14 @@ export default class ServerApi {
393 preservePaths: true, 417 preservePaths: true,
394 unlink: true, 418 unlink: true,
395 preserveOwner: false, 419 preserveOwner: false,
396 onwarn: x => console.log('warn', recipeId, x), 420 onwarn: (x) => console.log('warn', recipeId, x),
397 }); 421 });
398 422
399 await sleep(10); 423 await sleep(10);
400 424
401 const { id } = fs.readJsonSync(path.join(recipeTempDirectory, 'package.json')); 425 const { id } = fs.readJsonSync(
426 path.join(recipeTempDirectory, 'package.json'),
427 );
402 const recipeDirectory = path.join(recipesDirectory, id); 428 const recipeDirectory = path.join(recipesDirectory, id);
403 fs.copySync(recipeTempDirectory, recipeDirectory); 429 fs.copySync(recipeTempDirectory, recipeDirectory);
404 fs.remove(recipeTempDirectory); 430 fs.remove(recipeTempDirectory);
@@ -414,7 +440,9 @@ export default class ServerApi {
414 440
415 // News 441 // News
416 async getLatestNews() { 442 async getLatestNews() {
417 const url = `${apiBase(true)}/news?platform=${osPlatform}&arch=${osArch}&version=${app.getVersion()}`; 443 const url = `${apiBase(
444 true,
445 )}/news?platform=${osPlatform}&arch=${osArch}&version=${app.getVersion()}`;
418 const request = await sendAuthRequest(url); 446 const request = await sendAuthRequest(url);
419 if (!request.ok) throw request; 447 if (!request.ok) throw request;
420 const data = await request.json(); 448 const data = await request.json();
@@ -435,9 +463,13 @@ export default class ServerApi {
435 throw new Error('Server not loaded'); 463 throw new Error('Server not loaded');
436 } 464 }
437 465
438 const request = await sendAuthRequest(`${apiBase(false)}/health`, { 466 const request = await sendAuthRequest(
439 method: 'GET', 467 `${apiBase(false)}/health`,
440 }, false); 468 {
469 method: 'GET',
470 },
471 false,
472 );
441 if (!request.ok) { 473 if (!request.ok) {
442 throw request; 474 throw request;
443 } 475 }
@@ -445,23 +477,31 @@ export default class ServerApi {
445 } 477 }
446 478
447 async getLegacyServices() { 479 async getLegacyServices() {
448 const file = path.join(app.getPath('userData'), 'settings', 'services.json'); 480 const file = path.join(
481 app.getPath('userData'),
482 'settings',
483 'services.json',
484 );
449 485
450 try { 486 try {
451 const config = fs.readJsonSync(file); 487 const config = fs.readJsonSync(file);
452 488
453 if (Object.prototype.hasOwnProperty.call(config, 'services')) { 489 if (Object.prototype.hasOwnProperty.call(config, 'services')) {
454 const services = await Promise.all(config.services.map(async (s) => { 490 const services = await Promise.all(
455 const service = s; 491 config.services.map(async (s) => {
456 const request = await sendAuthRequest(`${apiBase()}/recipes/${s.service}`); 492 const service = s;
457 493 const request = await sendAuthRequest(
458 if (request.status === 200) { 494 `${apiBase()}/recipes/${s.service}`,
459 const data = await request.json(); 495 );
460 service.recipe = new RecipePreviewModel(data); 496
461 } 497 if (request.status === 200) {
462 498 const data = await request.json();
463 return service; 499 service.recipe = new RecipePreviewModel(data);
464 })); 500 }
501
502 return service;
503 }),
504 );
465 505
466 debug('ServerApi::getLegacyServices resolves', services); 506 debug('ServerApi::getLegacyServices resolves', services);
467 return services; 507 return services;
@@ -475,17 +515,19 @@ export default class ServerApi {
475 515
476 // Helper 516 // Helper
477 async _mapServiceModels(services) { 517 async _mapServiceModels(services) {
478 const recipes = services.map(s => s.recipeId); 518 const recipes = services.map((s) => s.recipeId);
479 await this._bulkRecipeCheck(recipes); 519 await this._bulkRecipeCheck(recipes);
480 /* eslint-disable no-return-await */ 520 /* eslint-disable no-return-await */
481 return Promise.all(services.map(async service => await this._prepareServiceModel(service))); 521 return Promise.all(
522 services.map(async (service) => await this._prepareServiceModel(service)),
523 );
482 /* eslint-enable no-return-await */ 524 /* eslint-enable no-return-await */
483 } 525 }
484 526
485 async _prepareServiceModel(service) { 527 async _prepareServiceModel(service) {
486 let recipe; 528 let recipe;
487 try { 529 try {
488 recipe = this.recipes.find(r => r.id === service.recipeId); 530 recipe = this.recipes.find((r) => r.id === service.recipeId);
489 531
490 if (!recipe) { 532 if (!recipe) {
491 console.warn(`Recipe ${service.recipeId} not loaded`); 533 console.warn(`Recipe ${service.recipeId} not loaded`);
@@ -501,21 +543,25 @@ export default class ServerApi {
501 543
502 async _bulkRecipeCheck(unfilteredRecipes) { 544 async _bulkRecipeCheck(unfilteredRecipes) {
503 // Filter recipe duplicates as we don't need to download 3 Slack recipes 545 // Filter recipe duplicates as we don't need to download 3 Slack recipes
504 const recipes = unfilteredRecipes.filter((elem, pos, arr) => arr.indexOf(elem) === pos); 546 const recipes = unfilteredRecipes.filter(
547 (elem, pos, arr) => arr.indexOf(elem) === pos,
548 );
505 549
506 return Promise.all(recipes 550 return Promise.all(
507 .map(async (recipeId) => { 551 recipes.map(async (recipeId) => {
508 let recipe = this.recipes.find(r => r.id === recipeId); 552 let recipe = this.recipes.find((r) => r.id === recipeId);
509 553
510 if (!recipe) { 554 if (!recipe) {
511 console.warn(`Recipe '${recipeId}' not installed, trying to fetch from server`); 555 console.warn(
556 `Recipe '${recipeId}' not installed, trying to fetch from server`,
557 );
512 558
513 await this.getRecipePackage(recipeId); 559 await this.getRecipePackage(recipeId);
514 560
515 debug('Rerun ServerAPI::getInstalledRecipes'); 561 debug('Rerun ServerAPI::getInstalledRecipes');
516 await this.getInstalledRecipes(); 562 await this.getInstalledRecipes();
517 563
518 recipe = this.recipes.find(r => r.id === recipeId); 564 recipe = this.recipes.find((r) => r.id === recipeId);
519 565
520 if (!recipe) { 566 if (!recipe) {
521 console.warn(`Could not load recipe ${recipeId}`); 567 console.warn(`Could not load recipe ${recipeId}`);
@@ -524,69 +570,83 @@ export default class ServerApi {
524 } 570 }
525 571
526 return recipe; 572 return recipe;
527 })).catch(err => console.error('Can\'t load recipe', err)); 573 }),
574 ).catch((err) => console.error("Can't load recipe", err));
528 } 575 }
529 576
530 _mapRecipePreviewModel(recipes) { 577 _mapRecipePreviewModel(recipes) {
531 return recipes.map((recipe) => { 578 return recipes
532 try { 579 .map((recipe) => {
533 return new RecipePreviewModel(recipe); 580 try {
534 } catch (e) { 581 return new RecipePreviewModel(recipe);
535 console.error(e); 582 } catch (e) {
536 return null; 583 console.error(e);
537 } 584 return null;
538 }).filter(recipe => recipe !== null); 585 }
586 })
587 .filter((recipe) => recipe !== null);
539 } 588 }
540 589
541 _mapNewsModels(news) { 590 _mapNewsModels(news) {
542 return news.map((newsItem) => { 591 return news
543 try { 592 .map((newsItem) => {
544 return new NewsModel(newsItem); 593 try {
545 } catch (e) { 594 return new NewsModel(newsItem);
546 console.error(e); 595 } catch (e) {
547 return null; 596 console.error(e);
548 } 597 return null;
549 }).filter(newsItem => newsItem !== null); 598 }
599 })
600 .filter((newsItem) => newsItem !== null);
550 } 601 }
551 602
552 _mapOrderModels(orders) { 603 _mapOrderModels(orders) {
553 return orders.map((orderItem) => { 604 return orders
554 try { 605 .map((orderItem) => {
555 return new OrderModel(orderItem); 606 try {
556 } catch (e) { 607 return new OrderModel(orderItem);
557 console.error(e); 608 } catch (e) {
558 return null; 609 console.error(e);
559 } 610 return null;
560 }).filter(orderItem => orderItem !== null); 611 }
612 })
613 .filter((orderItem) => orderItem !== null);
561 } 614 }
562 615
563 _getDevRecipes() { 616 _getDevRecipes() {
564 const recipesDirectory = getDevRecipeDirectory(); 617 const recipesDirectory = getDevRecipeDirectory();
565 try { 618 try {
566 const paths = fs.readdirSync(recipesDirectory) 619 const paths = fs
567 .filter(file => fs.statSync(path.join(recipesDirectory, file)).isDirectory() && file !== 'temp'); 620 .readdirSync(recipesDirectory)
568 621 .filter(
569 const recipes = paths.map((id) => { 622 (file) => fs.statSync(path.join(recipesDirectory, file)).isDirectory()
570 let Recipe; 623 && file !== 'temp',
571 try { 624 );
572 // eslint-disable-next-line 625
573 Recipe = require(id)(RecipeModel); 626 const recipes = paths
574 return new Recipe(loadRecipeConfig(id)); 627 .map((id) => {
575 } catch (err) { 628 let Recipe;
576 console.error(err); 629 try {
577 } 630 // eslint-disable-next-line
631 Recipe = require(id)(RecipeModel);
632 return new Recipe(loadRecipeConfig(id));
633 } catch (err) {
634 console.error(err);
635 }
578 636
579 return false; 637 return false;
580 }).filter(recipe => recipe.id).map((data) => { 638 })
581 const recipe = data; 639 .filter((recipe) => recipe.id)
640 .map((data) => {
641 const recipe = data;
582 642
583 recipe.icons = { 643 recipe.icons = {
584 svg: `${recipe.path}/icon.svg`, 644 svg: `${recipe.path}/icon.svg`,
585 }; 645 };
586 recipe.local = true; 646 recipe.local = true;
587 647
588 return data; 648 return data;
589 }); 649 });
590 650
591 return recipes; 651 return recipes;
592 } catch (err) { 652 } 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', () => {
59}); 59});
60 60
61// Prevent drag and drop into window from redirecting 61// Prevent drag and drop into window from redirecting
62window.addEventListener('dragover', event => event.preventDefault()); 62window.addEventListener('dragover', (event) => event.preventDefault());
63window.addEventListener('drop', event => event.preventDefault()); 63window.addEventListener('drop', (event) => event.preventDefault());
64window.addEventListener('dragover', event => event.stopPropagation()); 64window.addEventListener('dragover', (event) => event.stopPropagation());
65window.addEventListener('drop', event => event.stopPropagation()); 65window.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';
7import Link from '../ui/Link'; 7import Link from '../ui/Link';
8import InfoBar from '../ui/InfoBar'; 8import InfoBar from '../ui/InfoBar';
9 9
10import { oneOrManyChildElements, globalError as globalErrorPropType } from '../../prop-types'; 10import {
11 oneOrManyChildElements,
12 globalError as globalErrorPropType,
13} from '../../prop-types';
11import globalMessages from '../../i18n/globalMessages'; 14import globalMessages from '../../i18n/globalMessages';
12 15
13import { isWindows } from '../../environment'; 16import { isWindows } from '../../environment';
14import AppUpdateInfoBar from '../AppUpdateInfoBar'; 17import AppUpdateInfoBar from '../AppUpdateInfoBar';
15import { GITHUB_FERDI_URL } from '../../config'; 18import { GITHUB_FERDI_URL } from '../../config';
16 19
17export default @observer class AuthLayout extends Component { 20export default
21@observer
22class AuthLayout extends Component {
18 static propTypes = { 23 static propTypes = {
19 children: oneOrManyChildElements.isRequired, 24 children: oneOrManyChildElements.isRequired,
20 error: globalErrorPropType.isRequired, 25 error: globalErrorPropType.isRequired,
@@ -30,7 +35,7 @@ export default @observer class AuthLayout extends Component {
30 35
31 state = { 36 state = {
32 shouldShowAppUpdateInfoBar: true, 37 shouldShowAppUpdateInfoBar: true,
33 } 38 };
34 39
35 static defaultProps = { 40 static defaultProps = {
36 nextAppReleaseVersion: null, 41 nextAppReleaseVersion: null,
@@ -57,12 +62,15 @@ export default @observer class AuthLayout extends Component {
57 62
58 return ( 63 return (
59 <> 64 <>
60 {isWindows && !isFullScreen && <TitleBar menu={window.ferdi.menu.template} icon="assets/images/logo.svg" />} 65 {isWindows && !isFullScreen && (
66 <TitleBar
67 menu={window.ferdi.menu.template}
68 icon="assets/images/logo.svg"
69 />
70 )}
61 <div className="auth"> 71 <div className="auth">
62 {!isOnline && ( 72 {!isOnline && (
63 <InfoBar 73 <InfoBar type="warning">
64 type="warning"
65 >
66 <span className="mdi mdi-flash" /> 74 <span className="mdi mdi-flash" />
67 {intl.formatMessage(globalMessages.notConnectedToTheInternet)} 75 {intl.formatMessage(globalMessages.notConnectedToTheInternet)}
68 </InfoBar> 76 </InfoBar>
@@ -95,7 +103,11 @@ export default @observer class AuthLayout extends Component {
95 })} 103 })}
96 </div> 104 </div>
97 {/* </div> */} 105 {/* </div> */}
98 <Link to={`${GITHUB_FERDI_URL}/ferdi`} className="auth__adlk" target="_blank"> 106 <Link
107 to={`${GITHUB_FERDI_URL}/ferdi`}
108 className="auth__adlk"
109 target="_blank"
110 >
99 <img src="./assets/images/adlk.svg" alt="" /> 111 <img src="./assets/images/adlk.svg" alt="" />
100 </Link> 112 </Link>
101 </div> 113 </div>
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 {
100 const { intl } = this.context; 100 const { intl } = this.context;
101 return ( 101 return (
102 <div className="auth__container"> 102 <div className="auth__container">
103 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> 103 <form className="franz-form auth__form" onSubmit={(e) => this.submit(e)}>
104 <h1>{intl.formatMessage(messages.headline)}</h1> 104 <h1>{intl.formatMessage(messages.headline)}</h1>
105 {form.$('server').value === this.franzServer 105 {form.$('server').value === this.franzServer
106 && ( 106 && (
@@ -113,7 +113,7 @@ export default @observer class ChangeServer extends Component {
113 && ( 113 && (
114 <Input 114 <Input
115 placeholder="Custom Server" 115 placeholder="Custom Server"
116 onChange={e => this.submit(e)} 116 onChange={(e) => this.submit(e)}
117 field={form.$('customServer')} 117 field={form.$('customServer')}
118 /> 118 />
119 )} 119 )}
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 {
102 102
103 return ( 103 return (
104 <div className="auth__container"> 104 <div className="auth__container">
105 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> 105 <form className="franz-form auth__form" onSubmit={(e) => this.submit(e)}>
106 <img 106 <img
107 src="./assets/images/logo.svg" 107 src="./assets/images/logo.svg"
108 className="auth__logo" 108 className="auth__logo"
diff --git a/src/components/auth/Login.js b/src/components/auth/Login.js
index 52b09eab6..9e6a8d046 100644
--- a/src/components/auth/Login.js
+++ b/src/components/auth/Login.js
@@ -135,7 +135,7 @@ export default @inject('actions') @observer class Login extends Component {
135 135
136 return ( 136 return (
137 <div className="auth__container"> 137 <div className="auth__container">
138 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> 138 <form className="franz-form auth__form" onSubmit={(e) => this.submit(e)}>
139 <img 139 <img
140 src="./assets/images/logo.svg" 140 src="./assets/images/logo.svg"
141 className="auth__logo" 141 className="auth__logo"
diff --git a/src/components/auth/Password.js b/src/components/auth/Password.js
index ad34e39af..eafc48502 100644
--- a/src/components/auth/Password.js
+++ b/src/components/auth/Password.js
@@ -86,7 +86,7 @@ export default @observer class Password extends Component {
86 86
87 return ( 87 return (
88 <div className="auth__container"> 88 <div className="auth__container">
89 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> 89 <form className="franz-form auth__form" onSubmit={(e) => this.submit(e)}>
90 <img 90 <img
91 src="./assets/images/logo.svg" 91 src="./assets/images/logo.svg"
92 className="auth__logo" 92 className="auth__logo"
diff --git a/src/components/auth/SetupAssistant.js b/src/components/auth/SetupAssistant.js
index e03cf9101..bd9069eb7 100644
--- a/src/components/auth/SetupAssistant.js
+++ b/src/components/auth/SetupAssistant.js
@@ -34,7 +34,7 @@ const messages = defineMessages({
34 }, 34 },
35}); 35});
36 36
37const styles = theme => ({ 37const styles = (theme) => ({
38 root: { 38 root: {
39 width: '500px !important', 39 width: '500px !important',
40 textAlign: 'center', 40 textAlign: 'center',
@@ -161,7 +161,7 @@ class SetupAssistant extends Component {
161 const sanitizedWorkspace = slackWorkspace.trim().replace(/^https?:\/\//, ''); 161 const sanitizedWorkspace = slackWorkspace.trim().replace(/^https?:\/\//, '');
162 162
163 if (sanitizedWorkspace) { 163 if (sanitizedWorkspace) {
164 const index = services.findIndex(s => s.id === SLACK_ID); 164 const index = services.findIndex((s) => s.id === SLACK_ID);
165 165
166 if (index === -1) { 166 if (index === -1) {
167 const newServices = services; 167 const newServices = services;
@@ -215,11 +215,11 @@ class SetupAssistant extends Component {
215 <button 215 <button
216 className={classnames({ 216 className={classnames({
217 [classes.serviceContainer]: true, 217 [classes.serviceContainer]: true,
218 [classes.selected]: this.state.services.findIndex(s => s.id === id) !== -1, 218 [classes.selected]: this.state.services.findIndex((s) => s.id === id) !== -1,
219 })} 219 })}
220 key={id} 220 key={id}
221 onClick={() => { 221 onClick={() => {
222 const index = this.state.services.findIndex(s => s.id === id); 222 const index = this.state.services.findIndex((s) => s.id === id);
223 if (index === -1) { 223 if (index === -1) {
224 if (id === SLACK_ID) { 224 if (id === SLACK_ID) {
225 this.setState({ isSlackModalOpen: true }); 225 this.setState({ isSlackModalOpen: true });
@@ -283,7 +283,7 @@ class SetupAssistant extends Component {
283 <Input 283 <Input
284 suffix=".slack.com" 284 suffix=".slack.com"
285 placeholder="workspace-url" 285 placeholder="workspace-url"
286 onChange={e => this.setState({ slackWorkspace: e.target.value })} 286 onChange={(e) => this.setState({ slackWorkspace: e.target.value })}
287 value={slackWorkspace} 287 value={slackWorkspace}
288 /> 288 />
289 <div className={classes.modalActionContainer}> 289 <div className={classes.modalActionContainer}>
diff --git a/src/components/auth/Signup.js b/src/components/auth/Signup.js
index 140867ea1..411b6697b 100644
--- a/src/components/auth/Signup.js
+++ b/src/components/auth/Signup.js
@@ -138,7 +138,7 @@ export default @inject('actions') @observer class Signup extends Component {
138 return ( 138 return (
139 <div className="auth__scroll-container"> 139 <div className="auth__scroll-container">
140 <div className="auth__container auth__container--signup"> 140 <div className="auth__container auth__container--signup">
141 <form className="franz-form auth__form" onSubmit={e => this.submit(e)}> 141 <form className="franz-form auth__form" onSubmit={(e) => this.submit(e)}>
142 <img 142 <img
143 src="./assets/images/logo.svg" 143 src="./assets/images/logo.svg"
144 className="auth__logo" 144 className="auth__logo"
diff --git a/src/components/auth/Welcome.js b/src/components/auth/Welcome.js
index 5f2fac64b..cb522e26e 100644
--- a/src/components/auth/Welcome.js
+++ b/src/components/auth/Welcome.js
@@ -84,7 +84,7 @@ export default @inject('actions') @observer class Login extends Component {
84 </Link> 84 </Link>
85 </div> 85 </div>
86 <div className="welcome__featured-services"> 86 <div className="welcome__featured-services">
87 {recipes.map(recipe => ( 87 {recipes.map((recipe) => (
88 <div 88 <div
89 key={recipe.id} 89 key={recipe.id}
90 className="welcome__featured-service" 90 className="welcome__featured-service"
diff --git a/src/components/layout/AppLayout.js b/src/components/layout/AppLayout.js
index 7e4d0e53e..6e1d7c9a0 100644
--- a/src/components/layout/AppLayout.js
+++ b/src/components/layout/AppLayout.js
@@ -44,7 +44,7 @@ const messages = defineMessages({
44 }, 44 },
45}); 45});
46 46
47const styles = theme => ({ 47const styles = (theme) => ({
48 appContent: { 48 appContent: {
49 // width: `calc(100% + ${theme.workspaces.drawer.width}px)`, 49 // width: `calc(100% + ${theme.workspaces.drawer.width}px)`,
50 width: '100%', 50 width: '100%',
@@ -124,7 +124,7 @@ class AppLayout extends Component {
124 {sidebar} 124 {sidebar}
125 <div className="app__service"> 125 <div className="app__service">
126 <WorkspaceSwitchingIndicator /> 126 <WorkspaceSwitchingIndicator />
127 {news.length > 0 && news.map(item => ( 127 {news.length > 0 && news.map((item) => (
128 <InfoBar 128 <InfoBar
129 key={item.id} 129 key={item.id}
130 position="top" 130 position="top"
diff --git a/src/components/services/content/ConnectionLostBanner.js b/src/components/services/content/ConnectionLostBanner.js
index e54a88faa..0b9d3122c 100644
--- a/src/components/services/content/ConnectionLostBanner.js
+++ b/src/components/services/content/ConnectionLostBanner.js
@@ -26,7 +26,7 @@ const messages = defineMessages({
26 }, 26 },
27}); 27});
28 28
29const styles = theme => ({ 29const styles = (theme) => ({
30 root: { 30 root: {
31 background: theme.colorBackground, 31 background: theme.colorBackground,
32 borderRadius: theme.borderRadius, 32 borderRadius: theme.borderRadius,
diff --git a/src/components/services/content/ErrorHandlers/styles.js b/src/components/services/content/ErrorHandlers/styles.js
index 9e2509ee5..72d62f5e3 100644
--- a/src/components/services/content/ErrorHandlers/styles.js
+++ b/src/components/services/content/ErrorHandlers/styles.js
@@ -1,4 +1,4 @@
1export default theme => ({ 1export default (theme) => ({
2 component: { 2 component: {
3 left: 0, 3 left: 0,
4 position: 'absolute', 4 position: 'absolute',
diff --git a/src/components/services/content/Services.js b/src/components/services/content/Services.js
index 6e46a60d2..fbf884f0a 100644
--- a/src/components/services/content/Services.js
+++ b/src/components/services/content/Services.js
@@ -167,7 +167,7 @@ export default @injectSheet(styles) @inject('actions') @observer class Services
167 </div> 167 </div>
168 </Appear> 168 </Appear>
169 )} 169 )}
170 {services.filter(service => !service.isTodosService).map(service => ( 170 {services.filter((service) => !service.isTodosService).map((service) => (
171 <ServiceView 171 <ServiceView
172 key={service.id} 172 key={service.id}
173 service={service} 173 service={service}
diff --git a/src/components/services/content/WebviewCrashHandler.js b/src/components/services/content/WebviewCrashHandler.js
index b62940c06..10ff0bbbb 100644
--- a/src/components/services/content/WebviewCrashHandler.js
+++ b/src/components/services/content/WebviewCrashHandler.js
@@ -47,7 +47,7 @@ export default @observer class WebviewCrashHandler extends Component {
47 const { reload } = this.props; 47 const { reload } = this.props;
48 48
49 this.countdownInterval = setInterval(() => { 49 this.countdownInterval = setInterval(() => {
50 this.setState(prevState => ({ 50 this.setState((prevState) => ({
51 countdown: prevState.countdown - this.countdownIntervalTimeout, 51 countdown: prevState.countdown - this.countdownIntervalTimeout,
52 })); 52 }));
53 53
diff --git a/src/components/services/tabs/Tabbar.js b/src/components/services/tabs/Tabbar.js
index db7a69bfc..0f608c415 100644
--- a/src/components/services/tabs/Tabbar.js
+++ b/src/components/services/tabs/Tabbar.js
@@ -33,7 +33,7 @@ export default @observer class TabBar extends Component {
33 reorder({ oldIndex, newIndex }); 33 reorder({ oldIndex, newIndex });
34 }; 34 };
35 35
36 shouldPreventSorting = event => event.target.tagName !== 'LI'; 36 shouldPreventSorting = (event) => event.target.tagName !== 'LI';
37 37
38 toggleService = ({ serviceId, isEnabled }) => { 38 toggleService = ({ serviceId, isEnabled }) => {
39 const { updateService } = this.props; 39 const { updateService } = this.props;
@@ -95,10 +95,10 @@ export default @observer class TabBar extends Component {
95 toggleNotifications={toggleNotifications} 95 toggleNotifications={toggleNotifications}
96 toggleAudio={toggleAudio} 96 toggleAudio={toggleAudio}
97 deleteService={deleteService} 97 deleteService={deleteService}
98 disableService={args => this.disableService(args)} 98 disableService={(args) => this.disableService(args)}
99 enableService={args => this.enableService(args)} 99 enableService={(args) => this.enableService(args)}
100 hibernateService={args => this.hibernateService(args)} 100 hibernateService={(args) => this.hibernateService(args)}
101 wakeUpService={args => this.wakeUpService(args)} 101 wakeUpService={(args) => this.wakeUpService(args)}
102 openSettings={openSettings} 102 openSettings={openSettings}
103 distance={20} 103 distance={20}
104 axis="y" 104 axis="y"
diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js
index 56e5f9c94..5e424fdd5 100644
--- a/src/components/settings/services/EditServiceForm.js
+++ b/src/components/settings/services/EditServiceForm.js
@@ -266,7 +266,7 @@ export default @observer class EditServiceForm extends Component {
266 </span> 266 </span>
267 </div> 267 </div>
268 <div className="settings__body"> 268 <div className="settings__body">
269 <form onSubmit={e => this.submit(e)} id="form"> 269 <form onSubmit={(e) => this.submit(e)} id="form">
270 <div className="service-name"> 270 <div className="service-name">
271 <Input field={form.$('name')} focus /> 271 <Input field={form.$('name')} focus />
272 </div> 272 </div>
diff --git a/src/components/settings/services/ServicesDashboard.js b/src/components/settings/services/ServicesDashboard.js
index a05af5da0..11d3eaa79 100644
--- a/src/components/settings/services/ServicesDashboard.js
+++ b/src/components/settings/services/ServicesDashboard.js
@@ -96,7 +96,7 @@ export default @observer class ServicesDashboard extends Component {
96 {(services.length !== 0 || searchNeedle) && !isLoading && ( 96 {(services.length !== 0 || searchNeedle) && !isLoading && (
97 <SearchInput 97 <SearchInput
98 placeholder={intl.formatMessage(messages.searchService)} 98 placeholder={intl.formatMessage(messages.searchService)}
99 onChange={needle => filterServices({ needle })} 99 onChange={(needle) => filterServices({ needle })}
100 onReset={() => resetFilter()} 100 onReset={() => resetFilter()}
101 autoFocus 101 autoFocus
102 /> 102 />
@@ -163,7 +163,7 @@ export default @observer class ServicesDashboard extends Component {
163 ) : ( 163 ) : (
164 <table className="service-table"> 164 <table className="service-table">
165 <tbody> 165 <tbody>
166 {services.map(service => ( 166 {services.map((service) => (
167 <ServiceItem 167 <ServiceItem
168 key={service.id} 168 key={service.id}
169 service={service} 169 service={service}
diff --git a/src/components/settings/settings/EditSettingsForm.js b/src/components/settings/settings/EditSettingsForm.js
index 7ac644446..339e2dff6 100644
--- a/src/components/settings/settings/EditSettingsForm.js
+++ b/src/components/settings/settings/EditSettingsForm.js
@@ -266,8 +266,8 @@ export default @observer class EditSettingsForm extends Component {
266 </div> 266 </div>
267 <div className="settings__body"> 267 <div className="settings__body">
268 <form 268 <form
269 onSubmit={e => this.submit(e)} 269 onSubmit={(e) => this.submit(e)}
270 onChange={e => this.submit(e)} 270 onChange={(e) => this.submit(e)}
271 id="form" 271 id="form"
272 > 272 >
273 {/* Titles */} 273 {/* Titles */}
@@ -367,7 +367,7 @@ export default @observer class EditSettingsForm extends Component {
367 <div> 367 <div>
368 <Input 368 <Input
369 placeholder="Todo Server" 369 placeholder="Todo Server"
370 onChange={e => this.submit(e)} 370 onChange={(e) => this.submit(e)}
371 field={form.$('customTodoServer')} 371 field={form.$('customTodoServer')}
372 /> 372 />
373 <p 373 <p
@@ -401,7 +401,7 @@ export default @observer class EditSettingsForm extends Component {
401 > 401 >
402 <Input 402 <Input
403 placeholder="17:00" 403 placeholder="17:00"
404 onChange={e => this.submit(e)} 404 onChange={(e) => this.submit(e)}
405 field={form.$('scheduledDNDStart')} 405 field={form.$('scheduledDNDStart')}
406 type="time" 406 type="time"
407 /> 407 />
@@ -413,7 +413,7 @@ export default @observer class EditSettingsForm extends Component {
413 > 413 >
414 <Input 414 <Input
415 placeholder="09:00" 415 placeholder="09:00"
416 onChange={e => this.submit(e)} 416 onChange={(e) => this.submit(e)}
417 field={form.$('scheduledDNDEnd')} 417 field={form.$('scheduledDNDEnd')}
418 type="time" 418 type="time"
419 /> 419 />
@@ -480,7 +480,7 @@ export default @observer class EditSettingsForm extends Component {
480 480
481 <Input 481 <Input
482 placeholder="Accent Color" 482 placeholder="Accent Color"
483 onChange={e => this.submit(e)} 483 onChange={(e) => this.submit(e)}
484 field={form.$('accentColor')} 484 field={form.$('accentColor')}
485 /> 485 />
486 <p> 486 <p>
@@ -515,7 +515,7 @@ export default @observer class EditSettingsForm extends Component {
515 515
516 <Input 516 <Input
517 placeholder={intl.formatMessage(messages.lockedPassword)} 517 placeholder={intl.formatMessage(messages.lockedPassword)}
518 onChange={e => this.submit(e)} 518 onChange={(e) => this.submit(e)}
519 field={form.$('lockedPassword')} 519 field={form.$('lockedPassword')}
520 type="password" 520 type="password"
521 scorePassword 521 scorePassword
@@ -527,7 +527,7 @@ export default @observer class EditSettingsForm extends Component {
527 527
528 <Input 528 <Input
529 placeholder="Lock after inactivity" 529 placeholder="Lock after inactivity"
530 onChange={e => this.submit(e)} 530 onChange={(e) => this.submit(e)}
531 field={form.$('inactivityLock')} 531 field={form.$('inactivityLock')}
532 autoFocus 532 autoFocus
533 /> 533 />
@@ -570,6 +570,7 @@ export default @observer class EditSettingsForm extends Component {
570 href={FRANZ_TRANSLATION} 570 href={FRANZ_TRANSLATION}
571 target="_blank" 571 target="_blank"
572 className="link" 572 className="link"
573 rel="noreferrer"
573 > 574 >
574 {intl.formatMessage(messages.translationHelp)} 575 {intl.formatMessage(messages.translationHelp)}
575 {' '} 576 {' '}
@@ -588,7 +589,7 @@ export default @observer class EditSettingsForm extends Component {
588 589
589 <Input 590 <Input
590 placeholder="User Agent" 591 placeholder="User Agent"
591 onChange={e => this.submit(e)} 592 onChange={(e) => this.submit(e)}
592 field={form.$('userAgentPref')} 593 field={form.$('userAgentPref')}
593 /> 594 />
594 <p className="settings__help">{intl.formatMessage(globalMessages.userAgentHelp)}</p> 595 <p className="settings__help">{intl.formatMessage(globalMessages.userAgentHelp)}</p>
@@ -674,12 +675,12 @@ export default @observer class EditSettingsForm extends Component {
674 675
675 Ferdi is based on 676 Ferdi is based on
676 {' '} 677 {' '}
677 <a href={`${GITHUB_FRANZ_URL}/franz`} target="_blank">Franz</a> 678 <a href={`${GITHUB_FRANZ_URL}/franz`} target="_blank" rel="noreferrer">Franz</a>
678 679
679 , a project published 680 , a project published
680 under the 681 under the
681 {' '} 682 {' '}
682 <a href={`${GITHUB_FRANZ_URL}/franz/blob/master/LICENSE`} target="_blank">Apache-2.0 License</a> 683 <a href={`${GITHUB_FRANZ_URL}/franz/blob/master/LICENSE`} target="_blank" rel="noreferrer">Apache-2.0 License</a>
683 </span> 684 </span>
684 <br /> 685 <br />
685 <span className="mdi mdi-information" /> 686 <span className="mdi mdi-information" />
diff --git a/src/components/settings/supportFerdi/SupportFerdiDashboard.js b/src/components/settings/supportFerdi/SupportFerdiDashboard.js
index 36c126565..b84e06739 100644
--- a/src/components/settings/supportFerdi/SupportFerdiDashboard.js
+++ b/src/components/settings/supportFerdi/SupportFerdiDashboard.js
@@ -94,10 +94,10 @@ class SupportFerdiDashboard extends Component {
94 <h1>{intl.formatMessage(messages.title)}</h1> 94 <h1>{intl.formatMessage(messages.title)}</h1>
95 <div> 95 <div>
96 <p className="settings__support-badges"> 96 <p className="settings__support-badges">
97 <a href="https://github.com/getferdi/ferdi" target="_blank"><img alt="GitHub Stars" src="https://img.shields.io/github/stars/getferdi/ferdi?style=social" /></a> 97 <a href="https://github.com/getferdi/ferdi" target="_blank" rel="noreferrer"><img alt="GitHub Stars" src="https://img.shields.io/github/stars/getferdi/ferdi?style=social" /></a>
98 <a href="https://twitter.com/getferdi/" target="_blank"><img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/getferdi?label=Follow&style=social" /></a> 98 <a href="https://twitter.com/getferdi/" target="_blank" rel="noreferrer"><img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/getferdi?label=Follow&style=social" /></a>
99 <a href="https://opencollective.com/getferdi#section-contributors" target="_blank"><img alt="Open Collective backers" src="https://img.shields.io/opencollective/backers/getferdi?logo=open-collective" /></a> 99 <a href="https://opencollective.com/getferdi#section-contributors" target="_blank" rel="noreferrer"><img alt="Open Collective backers" src="https://img.shields.io/opencollective/backers/getferdi?logo=open-collective" /></a>
100 <a href="https://opencollective.com/getferdi#section-contributors" target="_blank"><img alt="Open Collective sponsors" src="https://img.shields.io/opencollective/sponsors/getferdi?logo=open-collective" /></a> 100 <a href="https://opencollective.com/getferdi#section-contributors" target="_blank" rel="noreferrer"><img alt="Open Collective sponsors" src="https://img.shields.io/opencollective/sponsors/getferdi?logo=open-collective" /></a>
101 </p> 101 </p>
102 <FormattedHTMLMessage {...messages.aboutIntro} /> 102 <FormattedHTMLMessage {...messages.aboutIntro} />
103 <br /> 103 <br />
@@ -109,7 +109,7 @@ class SupportFerdiDashboard extends Component {
109 </p> 109 </p>
110 <p> 110 <p>
111 {intl.formatMessage(messages.textListContributors)} 111 {intl.formatMessage(messages.textListContributors)}
112 <a href="https://github.com/getferdi/ferdi#contributors-" target="_blank" className="link"> 112 <a href="https://github.com/getferdi/ferdi#contributors-" target="_blank" className="link" rel="noreferrer">
113 {' '} 113 {' '}
114 {intl.formatMessage(messages.textListContributorsHere)} 114 {intl.formatMessage(messages.textListContributorsHere)}
115 <i className="mdi mdi-open-in-new" /> 115 <i className="mdi mdi-open-in-new" />
@@ -122,7 +122,7 @@ class SupportFerdiDashboard extends Component {
122 </p> 122 </p>
123 <p> 123 <p>
124 {intl.formatMessage(messages.textSupportWelcome)} 124 {intl.formatMessage(messages.textSupportWelcome)}
125 <a href="https://help.getferdi.com/general/support" target="_blank" className="link"> 125 <a href="https://help.getferdi.com/general/support" target="_blank" className="link" rel="noreferrer">
126 {' '} 126 {' '}
127 {intl.formatMessage(messages.textSupportWelcomeHere)} 127 {intl.formatMessage(messages.textSupportWelcomeHere)}
128 <i className="mdi mdi-open-in-new" /> 128 <i className="mdi mdi-open-in-new" />
@@ -130,7 +130,7 @@ class SupportFerdiDashboard extends Component {
130 </p> 130 </p>
131 <p> 131 <p>
132 {intl.formatMessage(messages.textExpenses)} 132 {intl.formatMessage(messages.textExpenses)}
133 <a href="https://opencollective.com/getferdi#section-budget" target="_blank" className="link"> 133 <a href="https://opencollective.com/getferdi#section-budget" target="_blank" className="link" rel="noreferrer">
134 {' '} 134 {' '}
135 {intl.formatMessage(messages.textOpenCollective)} 135 {intl.formatMessage(messages.textOpenCollective)}
136 <i className="mdi mdi-open-in-new" /> 136 <i className="mdi mdi-open-in-new" />
@@ -138,14 +138,14 @@ class SupportFerdiDashboard extends Component {
138 </p> 138 </p>
139 <p> 139 <p>
140 {intl.formatMessage(messages.textDonation)} 140 {intl.formatMessage(messages.textDonation)}
141 <a href="https://opencollective.com/getferdi#section-contribute" target="_blank" className="link"> 141 <a href="https://opencollective.com/getferdi#section-contribute" target="_blank" className="link" rel="noreferrer">
142 {' '} 142 {' '}
143 {intl.formatMessage(messages.textOpenCollective)} 143 {intl.formatMessage(messages.textOpenCollective)}
144 <i className="mdi mdi-open-in-new" /> 144 <i className="mdi mdi-open-in-new" />
145 </a> 145 </a>
146 {' '} 146 {' '}
147 {intl.formatMessage(messages.textDonationAnd)} 147 {intl.formatMessage(messages.textDonationAnd)}
148 <a href="https://github.com/sponsors/getferdi" target="_blank" className="link"> 148 <a href="https://github.com/sponsors/getferdi" target="_blank" className="link" rel="noreferrer">
149 {' '} 149 {' '}
150 {intl.formatMessage(messages.textGitHubSponsors)} 150 {intl.formatMessage(messages.textGitHubSponsors)}
151 <i className="mdi mdi-open-in-new" /> 151 <i className="mdi mdi-open-in-new" />
diff --git a/src/components/settings/user/EditUserForm.js b/src/components/settings/user/EditUserForm.js
index a1a353e57..db78acb69 100644
--- a/src/components/settings/user/EditUserForm.js
+++ b/src/components/settings/user/EditUserForm.js
@@ -84,7 +84,7 @@ export default @observer class EditUserForm extends Component {
84 </span> 84 </span>
85 </div> 85 </div>
86 <div className="settings__body"> 86 <div className="settings__body">
87 <form onSubmit={e => this.submit(e)} id="form"> 87 <form onSubmit={(e) => this.submit(e)} id="form">
88 {status.length > 0 && status.includes('data-updated') && ( 88 {status.length > 0 && status.includes('data-updated') && (
89 <Infobox 89 <Infobox
90 type="success" 90 type="success"
diff --git a/src/components/ui/AppLoader/index.js b/src/components/ui/AppLoader/index.js
index a7f6f4545..31d7ca249 100644
--- a/src/components/ui/AppLoader/index.js
+++ b/src/components/ui/AppLoader/index.js
@@ -37,7 +37,7 @@ export default @injectSheet(styles) @withTheme class AppLoader extends Component
37 37
38 componentDidMount() { 38 componentDidMount() {
39 this.interval = setInterval(() => { 39 this.interval = setInterval(() => {
40 this.setState(prevState => ({ 40 this.setState((prevState) => ({
41 step: prevState.step === textList.length - 1 ? 0 : prevState.step + 1, 41 step: prevState.step === textList.length - 1 ? 0 : prevState.step + 1,
42 })); 42 }));
43 }, 2500); 43 }, 2500);
diff --git a/src/components/ui/FeatureItem.js b/src/components/ui/FeatureItem.js
index 4926df470..646cf56ca 100644
--- a/src/components/ui/FeatureItem.js
+++ b/src/components/ui/FeatureItem.js
@@ -4,7 +4,7 @@ import { Icon } from '@meetfranz/ui';
4import classnames from 'classnames'; 4import classnames from 'classnames';
5import { mdiCheckCircle } from '@mdi/js'; 5import { mdiCheckCircle } from '@mdi/js';
6 6
7const styles = theme => ({ 7const styles = (theme) => ({
8 featureItem: { 8 featureItem: {
9 borderBottom: [1, 'solid', theme.defaultContentBorder], 9 borderBottom: [1, 'solid', theme.defaultContentBorder],
10 padding: [8, 0], 10 padding: [8, 0],
diff --git a/src/components/ui/FeatureList.js b/src/components/ui/FeatureList.js
index ada15244b..cf2664830 100644
--- a/src/components/ui/FeatureList.js
+++ b/src/components/ui/FeatureList.js
@@ -92,7 +92,7 @@ export class FeatureList extends Component {
92 92
93 return ( 93 return (
94 <ul className={className}> 94 <ul className={className}>
95 {features.map(feature => <FeatureItem name={intl.formatMessage(feature)} className={featureClassName} />)} 95 {features.map((feature) => <FeatureItem name={intl.formatMessage(feature)} className={featureClassName} />)}
96 </ul> 96 </ul>
97 ); 97 );
98 } 98 }
diff --git a/src/components/ui/Link.js b/src/components/ui/Link.js
index 7930d98b4..fd14b7018 100644
--- a/src/components/ui/Link.js
+++ b/src/components/ui/Link.js
@@ -48,7 +48,7 @@ export default @inject('stores') @observer class Link extends Component {
48 href={router.history.createHref(to)} 48 href={router.history.createHref(to)}
49 className={linkClasses} 49 className={linkClasses}
50 style={style} 50 style={style}
51 onClick={e => this.onClick(e)} 51 onClick={(e) => this.onClick(e)}
52 > 52 >
53 {children} 53 {children}
54 </a> 54 </a>
diff --git a/src/components/ui/Modal/styles.js b/src/components/ui/Modal/styles.js
index c2bebf9bb..f32c075ce 100644
--- a/src/components/ui/Modal/styles.js
+++ b/src/components/ui/Modal/styles.js
@@ -1,4 +1,4 @@
1export default theme => ({ 1export default (theme) => ({
2 component: { 2 component: {
3 zIndex: 500, 3 zIndex: 500,
4 position: 'absolute', 4 position: 'absolute',
diff --git a/src/components/ui/Radio.js b/src/components/ui/Radio.js
index ba13aca63..e77714eb7 100644
--- a/src/components/ui/Radio.js
+++ b/src/components/ui/Radio.js
@@ -54,7 +54,7 @@ export default @observer class Radio extends Component {
54 </label> 54 </label>
55 )} 55 )}
56 <div className="franz-form__radio-wrapper"> 56 <div className="franz-form__radio-wrapper">
57 {field.options.map(type => ( 57 {field.options.map((type) => (
58 <label 58 <label
59 key={type.value} 59 key={type.value}
60 htmlFor={`${field.id}-${type.value}`} 60 htmlFor={`${field.id}-${type.value}`}
diff --git a/src/components/ui/SearchInput.js b/src/components/ui/SearchInput.js
index 78d6aae8b..0b25734dd 100644
--- a/src/components/ui/SearchInput.js
+++ b/src/components/ui/SearchInput.js
@@ -96,7 +96,7 @@ export default @observer class SearchInput extends Component {
96 type="text" 96 type="text"
97 placeholder={placeholder} 97 placeholder={placeholder}
98 value={value} 98 value={value}
99 onChange={e => this.onChange(e)} 99 onChange={(e) => this.onChange(e)}
100 ref={(ref) => { this.input = ref; }} 100 ref={(ref) => { this.input = ref; }}
101 /> 101 />
102 </label> 102 </label>
diff --git a/src/components/ui/Select.js b/src/components/ui/Select.js
index b4511433c..e7a5eafa8 100644
--- a/src/components/ui/Select.js
+++ b/src/components/ui/Select.js
@@ -82,7 +82,7 @@ export default @observer class Select extends Component {
82 </label> 82 </label>
83 )} 83 )}
84 <select 84 <select
85 onChange={multiple ? e => this.multipleChange(e) : field.onChange} 85 onChange={multiple ? (e) => this.multipleChange(e) : field.onChange}
86 id={field.id} 86 id={field.id}
87 defaultValue={selected} 87 defaultValue={selected}
88 className="franz-form__select" 88 className="franz-form__select"
@@ -90,7 +90,7 @@ export default @observer class Select extends Component {
90 multiple={multiple} 90 multiple={multiple}
91 ref={this.element} 91 ref={this.element}
92 > 92 >
93 {field.options.map(type => ( 93 {field.options.map((type) => (
94 <option 94 <option
95 key={type.value} 95 key={type.value}
96 value={type.value} 96 value={type.value}
diff --git a/src/components/ui/ServiceIcon.js b/src/components/ui/ServiceIcon.js
index 0b9155a4e..b2dadeac3 100644
--- a/src/components/ui/ServiceIcon.js
+++ b/src/components/ui/ServiceIcon.js
@@ -6,7 +6,7 @@ import classnames from 'classnames';
6 6
7import ServiceModel from '../../models/Service'; 7import ServiceModel from '../../models/Service';
8 8
9const styles = theme => ({ 9const styles = (theme) => ({
10 root: { 10 root: {
11 height: 'auto', 11 height: 'auto',
12 }, 12 },
diff --git a/src/components/ui/Slider.js b/src/components/ui/Slider.js
index b00a6a3f8..f344449a0 100644
--- a/src/components/ui/Slider.js
+++ b/src/components/ui/Slider.js
@@ -53,7 +53,7 @@ export default @observer class Slider extends Component {
53 value={field.value} 53 value={field.value}
54 min="1" 54 min="1"
55 max="100" 55 max="100"
56 onChange={e => (!disabled ? this.onChange(e) : null)} 56 onChange={(e) => (!disabled ? this.onChange(e) : null)}
57 /> 57 />
58 </div> 58 </div>
59 59
diff --git a/src/components/ui/Tabs/TabItem.js b/src/components/ui/Tabs/TabItem.js
index 546b05a4e..d0ef4e798 100644
--- a/src/components/ui/Tabs/TabItem.js
+++ b/src/components/ui/Tabs/TabItem.js
@@ -1,17 +1,15 @@
1import React, { Component, Fragment } from 'react'; 1import React, { Component } from 'react';
2 2
3import { oneOrManyChildElements } from '../../../prop-types'; 3import { oneOrManyChildElements } from '../../../prop-types';
4 4
5export default class TabItem extends Component { 5export default class TabItem extends Component {
6 static propTypes = { 6 static propTypes = {
7 children: oneOrManyChildElements.isRequired, 7 children: oneOrManyChildElements.isRequired,
8 } 8 };
9 9
10 render() { 10 render() {
11 const { children } = this.props; 11 const { children } = this.props;
12 12
13 return ( 13 return <>{children}</>;
14 <>{children}</>
15 );
16 } 14 }
17} 15}
diff --git a/src/components/ui/Tabs/Tabs.js b/src/components/ui/Tabs/Tabs.js
index e68dc3a1d..56c76f215 100644
--- a/src/components/ui/Tabs/Tabs.js
+++ b/src/components/ui/Tabs/Tabs.js
@@ -28,7 +28,7 @@ class Tab extends Component {
28 28
29 render() { 29 render() {
30 const { children: childElements } = this.props; 30 const { children: childElements } = this.props;
31 const children = childElements.filter(c => !!c); 31 const children = childElements.filter((c) => !!c);
32 32
33 if (children.length === 1) { 33 if (children.length === 1) {
34 return <div>{children}</div>; 34 return <div>{children}</div>;
diff --git a/src/components/ui/Toggle.js b/src/components/ui/Toggle.js
index 78fb77cbe..14330e5c7 100644
--- a/src/components/ui/Toggle.js
+++ b/src/components/ui/Toggle.js
@@ -59,7 +59,7 @@ export default @observer class Toggle extends Component {
59 name={field.name} 59 name={field.name}
60 value={field.name} 60 value={field.name}
61 checked={field.value} 61 checked={field.value}
62 onChange={e => (!disabled ? this.onChange(e) : null)} 62 onChange={(e) => (!disabled ? this.onChange(e) : null)}
63 /> 63 />
64 </label> 64 </label>
65 {field.error && <div className={field.error}>{field.error}</div>} 65 {field.error && <div className={field.error}>{field.error}</div>}
diff --git a/src/components/ui/ToggleRaw.js b/src/components/ui/ToggleRaw.js
index dcaf664e1..4700127d4 100644
--- a/src/components/ui/ToggleRaw.js
+++ b/src/components/ui/ToggleRaw.js
@@ -64,7 +64,7 @@ export default @observer class ToggleRaw extends Component {
64 name={field.name} 64 name={field.name}
65 value={field.name} 65 value={field.name}
66 checked={field.value} 66 checked={field.value}
67 onChange={e => (!disabled ? this.onChange(e) : null)} 67 onChange={(e) => (!disabled ? this.onChange(e) : null)}
68 /> 68 />
69 </label> 69 </label>
70 {field.error && <div className={field.error}>{field.error}</div>} 70 {field.error && <div className={field.error}>{field.error}</div>}
diff --git a/src/components/ui/WebviewLoader/styles.js b/src/components/ui/WebviewLoader/styles.js
index dbd75db8a..5d58011fe 100644
--- a/src/components/ui/WebviewLoader/styles.js
+++ b/src/components/ui/WebviewLoader/styles.js
@@ -1,4 +1,4 @@
1export default theme => ({ 1export default (theme) => ({
2 component: { 2 component: {
3 background: theme.colorWebviewLoaderBackground, 3 background: theme.colorWebviewLoaderBackground,
4 padding: 20, 4 padding: 20,
diff --git a/src/components/util/ErrorBoundary/styles.js b/src/components/util/ErrorBoundary/styles.js
index 0960546ff..51b36fdf3 100644
--- a/src/components/util/ErrorBoundary/styles.js
+++ b/src/components/util/ErrorBoundary/styles.js
@@ -1,4 +1,4 @@
1export default theme => ({ 1export default (theme) => ({
2 component: { 2 component: {
3 display: 'flex', 3 display: 'flex',
4 width: '100%', 4 width: '100%',
diff --git a/src/containers/auth/SetupAssistantScreen.js b/src/containers/auth/SetupAssistantScreen.js
index eaf3fda8a..d14085f63 100644
--- a/src/containers/auth/SetupAssistantScreen.js
+++ b/src/containers/auth/SetupAssistantScreen.js
@@ -102,7 +102,7 @@ export default @inject('stores', 'actions') @observer class SetupAssistantScreen
102 render() { 102 render() {
103 return ( 103 return (
104 <SetupAssistant 104 <SetupAssistant
105 onSubmit={config => this.setupServices(config)} 105 onSubmit={(config) => this.setupServices(config)}
106 services={this.services} 106 services={this.services}
107 embed={false} 107 embed={false}
108 isSettingUpServices={this.state.isSettingUpServices} 108 isSettingUpServices={this.state.isSettingUpServices}
diff --git a/src/containers/auth/SignupScreen.js b/src/containers/auth/SignupScreen.js
index eeab63a0c..38c5dfb43 100644
--- a/src/containers/auth/SignupScreen.js
+++ b/src/containers/auth/SignupScreen.js
@@ -24,7 +24,7 @@ export default @inject('stores', 'actions') @observer class SignupScreen extends
24 24
25 return ( 25 return (
26 <Signup 26 <Signup
27 onSubmit={values => this.onSignup(values)} 27 onSubmit={(values) => this.onSignup(values)}
28 isSubmitting={stores.user.signupRequest.isExecuting} 28 isSubmitting={stores.user.signupRequest.isExecuting}
29 loginRoute={stores.user.loginRoute} 29 loginRoute={stores.user.loginRoute}
30 changeServerRoute={stores.user.changeServerRoute} 30 changeServerRoute={stores.user.changeServerRoute}
diff --git a/src/containers/layout/AppLayoutContainer.js b/src/containers/layout/AppLayoutContainer.js
index 21be9d9d1..fff628946 100644
--- a/src/containers/layout/AppLayoutContainer.js
+++ b/src/containers/layout/AppLayoutContainer.js
@@ -92,8 +92,8 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e
92 92
93 const workspacesDrawer = ( 93 const workspacesDrawer = (
94 <WorkspaceDrawer 94 <WorkspaceDrawer
95 getServicesForWorkspace={workspace => ( 95 getServicesForWorkspace={(workspace) => (
96 workspace ? workspaceStore.getWorkspaceServices(workspace).map(s => s.name) : services.all.map(s => s.name) 96 workspace ? workspaceStore.getWorkspaceServices(workspace).map((s) => s.name) : services.all.map((s) => s.name)
97 )} 97 )}
98 /> 98 />
99 ); 99 );
diff --git a/src/containers/settings/AccountScreen.js b/src/containers/settings/AccountScreen.js
index 4ee932895..8d92b01be 100644
--- a/src/containers/settings/AccountScreen.js
+++ b/src/containers/settings/AccountScreen.js
@@ -46,10 +46,7 @@ class AccountScreen extends Component {
46 } 46 }
47 47
48 render() { 48 render() {
49 const { 49 const { user, settings } = this.props.stores;
50 user,
51 settings,
52 } = this.props.stores;
53 const { user: userActions } = this.props.actions; 50 const { user: userActions } = this.props.actions;
54 51
55 const isLoadingUserInfo = user.getUserInfoRequest.isExecuting; 52 const isLoadingUserInfo = user.getUserInfoRequest.isExecuting;
diff --git a/src/containers/settings/EditServiceScreen.js b/src/containers/settings/EditServiceScreen.js
index 0fe84792f..c880e97ae 100644
--- a/src/containers/settings/EditServiceScreen.js
+++ b/src/containers/settings/EditServiceScreen.js
@@ -394,9 +394,9 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
394 status={services.actionStatus} 394 status={services.actionStatus}
395 isSaving={services.updateServiceRequest.isExecuting || services.createServiceRequest.isExecuting} 395 isSaving={services.updateServiceRequest.isExecuting || services.createServiceRequest.isExecuting}
396 isDeleting={services.deleteServiceRequest.isExecuting} 396 isDeleting={services.deleteServiceRequest.isExecuting}
397 onSubmit={d => this.onSubmit(d)} 397 onSubmit={(d) => this.onSubmit(d)}
398 onDelete={() => this.deleteService()} 398 onDelete={() => this.deleteService()}
399 openRecipeFile={file => this.openRecipeFile(file)} 399 openRecipeFile={(file) => this.openRecipeFile(file)}
400 isProxyFeatureEnabled={proxyFeature.isEnabled} 400 isProxyFeatureEnabled={proxyFeature.isEnabled}
401 /> 401 />
402 </ErrorBoundary> 402 </ErrorBoundary>
diff --git a/src/containers/settings/EditSettingsScreen.js b/src/containers/settings/EditSettingsScreen.js
index 764078cb8..e0a648095 100644
--- a/src/containers/settings/EditSettingsScreen.js
+++ b/src/containers/settings/EditSettingsScreen.js
@@ -652,7 +652,7 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
652 isUpdateAvailable={updateStatus === updateStatusTypes.AVAILABLE} 652 isUpdateAvailable={updateStatus === updateStatusTypes.AVAILABLE}
653 noUpdateAvailable={updateStatus === updateStatusTypes.NOT_AVAILABLE} 653 noUpdateAvailable={updateStatus === updateStatusTypes.NOT_AVAILABLE}
654 updateIsReadyToInstall={updateStatus === updateStatusTypes.DOWNLOADED} 654 updateIsReadyToInstall={updateStatus === updateStatusTypes.DOWNLOADED}
655 onSubmit={d => this.onSubmit(d)} 655 onSubmit={(d) => this.onSubmit(d)}
656 getCacheSize={() => app.cacheSize} 656 getCacheSize={() => app.cacheSize}
657 isClearingAllCache={isClearingAllCache} 657 isClearingAllCache={isClearingAllCache}
658 onClearAllCache={clearAllCache} 658 onClearAllCache={clearAllCache}
diff --git a/src/containers/settings/EditUserScreen.js b/src/containers/settings/EditUserScreen.js
index 8e93164de..820b5e4d3 100644
--- a/src/containers/settings/EditUserScreen.js
+++ b/src/containers/settings/EditUserScreen.js
@@ -141,7 +141,7 @@ export default @inject('stores', 'actions') @observer class EditUserScreen exten
141 status={user.actionStatus} 141 status={user.actionStatus}
142 form={form} 142 form={form}
143 isSaving={user.updateUserInfoRequest.isExecuting} 143 isSaving={user.updateUserInfoRequest.isExecuting}
144 onSubmit={d => this.onSubmit(d)} 144 onSubmit={(d) => this.onSubmit(d)}
145 /> 145 />
146 </ErrorBoundary> 146 </ErrorBoundary>
147 ); 147 );
diff --git a/src/containers/settings/RecipesScreen.js b/src/containers/settings/RecipesScreen.js
index 9a16fd064..0d6506705 100644
--- a/src/containers/settings/RecipesScreen.js
+++ b/src/containers/settings/RecipesScreen.js
@@ -82,7 +82,7 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend
82 return recipes 82 return recipes
83 // Filter out duplicate recipes 83 // Filter out duplicate recipes
84 .filter((recipe, index, self) => { 84 .filter((recipe, index, self) => {
85 const ids = self.map(rec => rec.id); 85 const ids = self.map((rec) => rec.id);
86 return ids.indexOf(recipe.id) === index; 86 return ids.indexOf(recipe.id) === index;
87 87
88 // Sort alphabetically 88 // Sort alphabetically
@@ -95,7 +95,7 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend
95 95
96 // Create an array of RecipePreviews from an array of recipe objects 96 // Create an array of RecipePreviews from an array of recipe objects
97 createPreviews(recipes) { 97 createPreviews(recipes) {
98 return recipes.map(recipe => new RecipePreview(recipe)); 98 return recipes.map((recipe) => new RecipePreview(recipe));
99 } 99 }
100 100
101 resetSearch() { 101 resetSearch() {
@@ -134,11 +134,11 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend
134 // All search recipes from local recipes 134 // All search recipes from local recipes
135 ...this.createPreviews( 135 ...this.createPreviews(
136 this.customRecipes 136 this.customRecipes
137 .filter(service => service.name.toLowerCase().includes(this.state.needle.toLowerCase())), 137 .filter((service) => service.name.toLowerCase().includes(this.state.needle.toLowerCase())),
138 ), 138 ),
139 ]) : recipeFilter; 139 ]) : recipeFilter;
140 140
141 const customWebsiteRecipe = recipePreviews.all.find(service => service.id === CUSTOM_WEBSITE_RECIPE_ID); 141 const customWebsiteRecipe = recipePreviews.all.find((service) => service.id === CUSTOM_WEBSITE_RECIPE_ID);
142 142
143 const isLoading = recipePreviews.featuredRecipePreviewsRequest.isExecuting 143 const isLoading = recipePreviews.featuredRecipePreviewsRequest.isExecuting
144 || recipePreviews.allRecipePreviewsRequest.isExecuting 144 || recipePreviews.allRecipePreviewsRequest.isExecuting
@@ -156,7 +156,7 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend
156 addedServiceCount={services.all.length} 156 addedServiceCount={services.all.length}
157 hasLoadedRecipes={recipePreviews.featuredRecipePreviewsRequest.wasExecuted} 157 hasLoadedRecipes={recipePreviews.featuredRecipePreviewsRequest.wasExecuted}
158 showAddServiceInterface={serviceActions.showAddServiceInterface} 158 showAddServiceInterface={serviceActions.showAddServiceInterface}
159 searchRecipes={e => this.searchRecipes(e)} 159 searchRecipes={(e) => this.searchRecipes(e)}
160 resetSearch={() => this.resetSearch()} 160 resetSearch={() => this.resetSearch()}
161 searchNeedle={this.state.needle} 161 searchNeedle={this.state.needle}
162 serviceStatus={services.actionStatus} 162 serviceStatus={services.actionStatus}
diff --git a/src/features/announcements/components/AnnouncementScreen.js b/src/features/announcements/components/AnnouncementScreen.js
index 21964b108..315843db3 100644
--- a/src/features/announcements/components/AnnouncementScreen.js
+++ b/src/features/announcements/components/AnnouncementScreen.js
@@ -25,7 +25,7 @@ const messages = defineMessages({
25 25
26const smallScreen = '1000px'; 26const smallScreen = '1000px';
27 27
28const styles = theme => ({ 28const styles = (theme) => ({
29 container: { 29 container: {
30 background: theme.colorBackground, 30 background: theme.colorBackground,
31 position: 'relative', 31 position: 'relative',
diff --git a/src/features/communityRecipes/store.js b/src/features/communityRecipes/store.js
index acc1e52f6..b115a53e1 100644
--- a/src/features/communityRecipes/store.js
+++ b/src/features/communityRecipes/store.js
@@ -19,7 +19,7 @@ export class CommunityRecipesStore extends FeatureStore {
19 if (!this.stores) return []; 19 if (!this.stores) return [];
20 20
21 return this.stores.recipePreviews.dev.map((r) => { 21 return this.stores.recipePreviews.dev.map((r) => {
22 r.isDevRecipe = !!r.author.find(a => a.email === this.stores.user.data.email); 22 r.isDevRecipe = !!r.author.find((a) => a.email === this.stores.user.data.email);
23 23
24 return r; 24 return r;
25 }); 25 });
diff --git a/src/features/publishDebugInfo/Component.js b/src/features/publishDebugInfo/Component.js
index f97a7c750..5387bd358 100644
--- a/src/features/publishDebugInfo/Component.js
+++ b/src/features/publishDebugInfo/Component.js
@@ -46,7 +46,7 @@ const messages = defineMessages({
46 }, 46 },
47}); 47});
48 48
49const styles = theme => ({ 49const styles = (theme) => ({
50 container: { 50 container: {
51 minWidth: '70vw', 51 minWidth: '70vw',
52 }, 52 },
@@ -186,10 +186,10 @@ export default @injectSheet(styles) @inject('stores', 'actions') @observer class
186 <> 186 <>
187 <p className={classes.info}>{intl.formatMessage(messages.info)}</p> 187 <p className={classes.info}>{intl.formatMessage(messages.info)}</p>
188 188
189 <a href={`${DEBUG_API}/privacy.html`} target="_blank" className={classes.link}> 189 <a href={`${DEBUG_API}/privacy.html`} target="_blank" className={classes.link} rel="noreferrer">
190 {intl.formatMessage(messages.privacy)} 190 {intl.formatMessage(messages.privacy)}
191 </a> 191 </a>
192 <a href={`${DEBUG_API}/terms.html`} target="_blank" className={classes.link}> 192 <a href={`${DEBUG_API}/terms.html`} target="_blank" className={classes.link} rel="noreferrer">
193 {intl.formatMessage(messages.terms)} 193 {intl.formatMessage(messages.terms)}
194 </a> 194 </a>
195 195
diff --git a/src/features/quickSwitch/Component.js b/src/features/quickSwitch/Component.js
index 04822db71..812f2c04b 100644
--- a/src/features/quickSwitch/Component.js
+++ b/src/features/quickSwitch/Component.js
@@ -28,7 +28,7 @@ const messages = defineMessages({
28 }, 28 },
29}); 29});
30 30
31const styles = theme => ({ 31const styles = (theme) => ({
32 modal: { 32 modal: {
33 width: '80%', 33 width: '80%',
34 maxWidth: 600, 34 maxWidth: 600,
@@ -139,7 +139,7 @@ export default @injectSheet(styles) @inject('stores', 'actions') @observer class
139 if (this.state.search && compact(invoke(this.state.search, 'match', /^[a-z0-9]/i)).length > 0) { 139 if (this.state.search && compact(invoke(this.state.search, 'match', /^[a-z0-9]/i)).length > 0) {
140 // Apply simple search algorythm to list of all services 140 // Apply simple search algorythm to list of all services
141 services = this.props.stores.services.allDisplayed; 141 services = this.props.stores.services.allDisplayed;
142 services = services.filter(service => service.name.toLowerCase().search(this.state.search.toLowerCase()) !== -1); 142 services = services.filter((service) => service.name.toLowerCase().search(this.state.search.toLowerCase()) !== -1);
143 } else { 143 } else {
144 // Add the currently active service first 144 // Add the currently active service first
145 const currentService = this.props.stores.services.active; 145 const currentService = this.props.stores.services.active;
diff --git a/src/features/shareFranz/Component.js b/src/features/shareFranz/Component.js
index b66375453..cc2e81b70 100644
--- a/src/features/shareFranz/Component.js
+++ b/src/features/shareFranz/Component.js
@@ -44,7 +44,7 @@ const messages = defineMessages({
44 }, 44 },
45}); 45});
46 46
47const styles = theme => ({ 47const styles = (theme) => ({
48 modal: { 48 modal: {
49 width: '80%', 49 width: '80%',
50 maxWidth: 600, 50 maxWidth: 600,
diff --git a/src/features/todos/containers/TodosScreen.js b/src/features/todos/containers/TodosScreen.js
index 6425746e6..d05e24e56 100644
--- a/src/features/todos/containers/TodosScreen.js
+++ b/src/features/todos/containers/TodosScreen.js
@@ -24,10 +24,10 @@ class TodosScreen extends Component {
24 isVisible={todosStore.isTodosPanelVisible} 24 isVisible={todosStore.isTodosPanelVisible}
25 togglePanel={todoActions.toggleTodosPanel} 25 togglePanel={todoActions.toggleTodosPanel}
26 handleClientMessage={todoActions.handleClientMessage} 26 handleClientMessage={todoActions.handleClientMessage}
27 setTodosWebview={webview => todoActions.setTodosWebview({ webview })} 27 setTodosWebview={(webview) => todoActions.setTodosWebview({ webview })}
28 width={todosStore.width} 28 width={todosStore.width}
29 minWidth={TODOS_MIN_WIDTH} 29 minWidth={TODOS_MIN_WIDTH}
30 resize={width => todoActions.resize({ width })} 30 resize={(width) => todoActions.resize({ width })}
31 userAgent={todosStore.userAgent} 31 userAgent={todosStore.userAgent}
32 todoUrl={todosStore.todoUrl} 32 todoUrl={todosStore.todoUrl}
33 isTodoUrlValid={todosStore.isTodoUrlValid} 33 isTodoUrlValid={todosStore.isTodoUrlValid}
diff --git a/src/features/utils/ActionBinding.js b/src/features/utils/ActionBinding.js
index 497aa071b..787166d44 100644
--- a/src/features/utils/ActionBinding.js
+++ b/src/features/utils/ActionBinding.js
@@ -24,6 +24,6 @@ export default class ActionBinding {
24 } 24 }
25} 25}
26 26
27export const createActionBindings = actions => ( 27export const createActionBindings = (actions) => (
28 actions.map(a => new ActionBinding(a)) 28 actions.map((a) => new ActionBinding(a))
29); 29);
diff --git a/src/features/utils/FeatureStore.js b/src/features/utils/FeatureStore.js
index 0bc10e176..4d4e217a9 100644
--- a/src/features/utils/FeatureStore.js
+++ b/src/features/utils/FeatureStore.js
@@ -16,11 +16,11 @@ export class FeatureStore {
16 } 16 }
17 17
18 _startActions(actions = this._actions) { 18 _startActions(actions = this._actions) {
19 actions.forEach(a => a.start()); 19 actions.forEach((a) => a.start());
20 } 20 }
21 21
22 _stopActions(actions = this._actions) { 22 _stopActions(actions = this._actions) {
23 actions.forEach(a => a.stop()); 23 actions.forEach((a) => a.stop());
24 } 24 }
25 25
26 // REACTIONS 26 // REACTIONS
@@ -31,10 +31,10 @@ export class FeatureStore {
31 } 31 }
32 32
33 _startReactions(reactions = this._reactions) { 33 _startReactions(reactions = this._reactions) {
34 reactions.forEach(r => r.start()); 34 reactions.forEach((r) => r.start());
35 } 35 }
36 36
37 _stopReactions(reactions = this._reactions) { 37 _stopReactions(reactions = this._reactions) {
38 reactions.forEach(r => r.stop()); 38 reactions.forEach((r) => r.stop());
39 } 39 }
40} 40}
diff --git a/src/features/webControls/components/WebControls.js b/src/features/webControls/components/WebControls.js
index b9403bd0d..1cdd14e55 100644
--- a/src/features/webControls/components/WebControls.js
+++ b/src/features/webControls/components/WebControls.js
@@ -32,7 +32,7 @@ const messages = defineMessages({
32 }, 32 },
33}); 33});
34 34
35const styles = theme => ({ 35const styles = (theme) => ({
36 root: { 36 root: {
37 background: theme.colorBackground, 37 background: theme.colorBackground,
38 position: 'relative', 38 position: 'relative',
@@ -197,7 +197,7 @@ class WebControls extends Component {
197 <input 197 <input
198 value={editUrl ? inputUrl : url} 198 value={editUrl ? inputUrl : url}
199 className={classes.input} 199 className={classes.input}
200 onChange={event => this.setState({ 200 onChange={(event) => this.setState({
201 inputUrl: event.target.value, 201 inputUrl: event.target.value,
202 })} 202 })}
203 onFocus={(event) => { 203 onFocus={(event) => {
diff --git a/src/features/webControls/containers/WebControlsScreen.js b/src/features/webControls/containers/WebControlsScreen.js
index d638b831c..e1e1b9991 100644
--- a/src/features/webControls/containers/WebControlsScreen.js
+++ b/src/features/webControls/containers/WebControlsScreen.js
@@ -114,7 +114,7 @@ class WebControlsScreen extends Component {
114 goBack={() => this.goBack()} 114 goBack={() => this.goBack()}
115 canGoForward={this.canGoForward} 115 canGoForward={this.canGoForward}
116 goForward={() => this.goForward()} 116 goForward={() => this.goForward()}
117 navigate={url => this.navigate(url)} 117 navigate={(url) => this.navigate(url)}
118 url={this.url} 118 url={this.url}
119 /> 119 />
120 ); 120 );
diff --git a/src/features/workspaces/api.js b/src/features/workspaces/api.js
index 30fbd84be..322695ed2 100644
--- a/src/features/workspaces/api.js
+++ b/src/features/workspaces/api.js
@@ -14,7 +14,7 @@ export const workspaceApi = {
14 debug('getUserWorkspaces RESULT', result); 14 debug('getUserWorkspaces RESULT', result);
15 if (!result.ok) throw result; 15 if (!result.ok) throw result;
16 const workspaces = await result.json(); 16 const workspaces = await result.json();
17 return workspaces.map(data => new Workspace(data)); 17 return workspaces.map((data) => new Workspace(data));
18 }, 18 },
19 19
20 createWorkspace: async (name) => { 20 createWorkspace: async (name) => {
diff --git a/src/features/workspaces/components/WorkspaceDrawer.js b/src/features/workspaces/components/WorkspaceDrawer.js
index 3ddc9cf16..1138f23d7 100644
--- a/src/features/workspaces/components/WorkspaceDrawer.js
+++ b/src/features/workspaces/components/WorkspaceDrawer.js
@@ -34,7 +34,7 @@ const messages = defineMessages({
34 }, 34 },
35}); 35});
36 36
37const styles = theme => ({ 37const styles = (theme) => ({
38 drawer: { 38 drawer: {
39 background: theme.workspaces.drawer.background, 39 background: theme.workspaces.drawer.background,
40 width: `${theme.workspaces.drawer.width}px`, 40 width: `${theme.workspaces.drawer.width}px`,
diff --git a/src/features/workspaces/components/WorkspaceDrawerItem.js b/src/features/workspaces/components/WorkspaceDrawerItem.js
index 2e58b70d6..a3fdf4f47 100644
--- a/src/features/workspaces/components/WorkspaceDrawerItem.js
+++ b/src/features/workspaces/components/WorkspaceDrawerItem.js
@@ -18,7 +18,7 @@ const messages = defineMessages({
18 }, 18 },
19}); 19});
20 20
21const styles = theme => ({ 21const styles = (theme) => ({
22 item: { 22 item: {
23 height: '67px', 23 height: '67px',
24 padding: `15px ${theme.workspaces.drawer.padding}px`, 24 padding: `15px ${theme.workspaces.drawer.padding}px`,
diff --git a/src/features/workspaces/components/WorkspaceItem.js b/src/features/workspaces/components/WorkspaceItem.js
index cc4b1a3ba..85fc02d51 100644
--- a/src/features/workspaces/components/WorkspaceItem.js
+++ b/src/features/workspaces/components/WorkspaceItem.js
@@ -6,7 +6,7 @@ import injectSheet from 'react-jss';
6 6
7import Workspace from '../models/Workspace'; 7import Workspace from '../models/Workspace';
8 8
9const styles = theme => ({ 9const styles = (theme) => ({
10 row: { 10 row: {
11 height: theme.workspaces.settings.listItems.height, 11 height: theme.workspaces.settings.listItems.height,
12 borderBottom: `1px solid ${theme.workspaces.settings.listItems.borderColor}`, 12 borderBottom: `1px solid ${theme.workspaces.settings.listItems.borderColor}`,
diff --git a/src/features/workspaces/components/WorkspaceServiceListItem.js b/src/features/workspaces/components/WorkspaceServiceListItem.js
index e05b21440..f6e2a2786 100644
--- a/src/features/workspaces/components/WorkspaceServiceListItem.js
+++ b/src/features/workspaces/components/WorkspaceServiceListItem.js
@@ -8,7 +8,7 @@ import { Toggle } from '@meetfranz/forms';
8import Service from '../../../models/Service'; 8import Service from '../../../models/Service';
9import ServiceIcon from '../../../components/ui/ServiceIcon'; 9import ServiceIcon from '../../../components/ui/ServiceIcon';
10 10
11const styles = theme => ({ 11const styles = (theme) => ({
12 listItem: { 12 listItem: {
13 height: theme.workspaces.settings.listItems.height, 13 height: theme.workspaces.settings.listItems.height,
14 borderBottom: `1px solid ${theme.workspaces.settings.listItems.borderColor}`, 14 borderBottom: `1px solid ${theme.workspaces.settings.listItems.borderColor}`,
diff --git a/src/features/workspaces/components/WorkspaceSwitchingIndicator.js b/src/features/workspaces/components/WorkspaceSwitchingIndicator.js
index a70d1d66f..b46959e91 100644
--- a/src/features/workspaces/components/WorkspaceSwitchingIndicator.js
+++ b/src/features/workspaces/components/WorkspaceSwitchingIndicator.js
@@ -15,7 +15,7 @@ const messages = defineMessages({
15 }, 15 },
16}); 16});
17 17
18const styles = theme => ({ 18const styles = (theme) => ({
19 wrapper: { 19 wrapper: {
20 display: 'flex', 20 display: 'flex',
21 alignItems: 'flex-start', 21 alignItems: 'flex-start',
diff --git a/src/features/workspaces/components/WorkspacesDashboard.js b/src/features/workspaces/components/WorkspacesDashboard.js
index 0c2588c42..8319d3bc6 100644
--- a/src/features/workspaces/components/WorkspacesDashboard.js
+++ b/src/features/workspaces/components/WorkspacesDashboard.js
@@ -175,11 +175,11 @@ class WorkspacesDashboard extends Component {
175 <table className={classes.table}> 175 <table className={classes.table}>
176 {/* ===== Workspaces list ===== */} 176 {/* ===== Workspaces list ===== */}
177 <tbody> 177 <tbody>
178 {workspaces.map(workspace => ( 178 {workspaces.map((workspace) => (
179 <WorkspaceItem 179 <WorkspaceItem
180 key={workspace.id} 180 key={workspace.id}
181 workspace={workspace} 181 workspace={workspace}
182 onItemClick={w => onWorkspaceClick(w)} 182 onItemClick={(w) => onWorkspaceClick(w)}
183 /> 183 />
184 ))} 184 ))}
185 </tbody> 185 </tbody>
diff --git a/src/features/workspaces/containers/WorkspacesScreen.js b/src/features/workspaces/containers/WorkspacesScreen.js
index c241cd622..4828658f9 100644
--- a/src/features/workspaces/containers/WorkspacesScreen.js
+++ b/src/features/workspaces/containers/WorkspacesScreen.js
@@ -30,8 +30,8 @@ class WorkspacesScreen extends Component {
30 createWorkspaceRequest={createWorkspaceRequest} 30 createWorkspaceRequest={createWorkspaceRequest}
31 deleteWorkspaceRequest={deleteWorkspaceRequest} 31 deleteWorkspaceRequest={deleteWorkspaceRequest}
32 updateWorkspaceRequest={updateWorkspaceRequest} 32 updateWorkspaceRequest={updateWorkspaceRequest}
33 onCreateWorkspaceSubmit={data => actions.workspaces.create(data)} 33 onCreateWorkspaceSubmit={(data) => actions.workspaces.create(data)}
34 onWorkspaceClick={w => actions.workspaces.edit({ workspace: w })} 34 onWorkspaceClick={(w) => actions.workspaces.edit({ workspace: w })}
35 /> 35 />
36 </ErrorBoundary> 36 </ErrorBoundary>
37 ); 37 );
diff --git a/src/features/workspaces/models/Workspace.js b/src/features/workspaces/models/Workspace.js
index 77c4e05f4..11ee377cd 100644
--- a/src/features/workspaces/models/Workspace.js
+++ b/src/features/workspaces/models/Workspace.js
@@ -22,13 +22,13 @@ export default class Workspace {
22 this.name = data.name; 22 this.name = data.name;
23 this.order = data.order; 23 this.order = data.order;
24 24
25 let services = data.services; 25 let { services } = data;
26 if (data.saving && data.keepLoaded) { 26 if (data.saving && data.keepLoaded) {
27 // Keep workspaces loaded 27 // Keep workspaces loaded
28 services.push(KEEP_WS_LOADED_USID); 28 services.push(KEEP_WS_LOADED_USID);
29 } else if (data.saving && data.services.includes(KEEP_WS_LOADED_USID)) { 29 } else if (data.saving && data.services.includes(KEEP_WS_LOADED_USID)) {
30 // Don't keep loaded 30 // Don't keep loaded
31 services = services.filter(e => e !== KEEP_WS_LOADED_USID); 31 services = services.filter((e) => e !== KEEP_WS_LOADED_USID);
32 } 32 }
33 this.services.replace(services); 33 this.services.replace(services);
34 34
diff --git a/src/helpers/array-helpers.js b/src/helpers/array-helpers.js
index ffb3b63dc..5e592b7f7 100644
--- a/src/helpers/array-helpers.js
+++ b/src/helpers/array-helpers.js
@@ -1,4 +1,4 @@
1export const shuffleArray = arr => arr 1export const shuffleArray = (arr) => arr
2 .map(a => [Math.random(), a]) 2 .map((a) => [Math.random(), a])
3 .sort((a, b) => a[0] - b[0]) 3 .sort((a, b) => a[0] - b[0])
4 .map(a => a[1]); 4 .map((a) => a[1]);
diff --git a/src/helpers/async-helpers.js b/src/helpers/async-helpers.js
index 2ef01ee09..c6c57e28e 100644
--- a/src/helpers/async-helpers.js
+++ b/src/helpers/async-helpers.js
@@ -1,5 +1,5 @@
1/* eslint-disable import/prefer-default-export */ 1/* eslint-disable import/prefer-default-export */
2 2
3export function sleep(ms = 0) { 3export function sleep(ms = 0) {
4 return new Promise(r => setTimeout(r, ms)); 4 return new Promise((r) => setTimeout(r, ms));
5} 5}
diff --git a/src/helpers/service-helpers.js b/src/helpers/service-helpers.js
index f6363aca8..28d483182 100644
--- a/src/helpers/service-helpers.js
+++ b/src/helpers/service-helpers.js
@@ -14,5 +14,5 @@ export function removeServicePartitionDirectory(id = '', addServicePrefix = fals
14 14
15export async function getServiceIdsFromPartitions() { 15export async function getServiceIdsFromPartitions() {
16 const files = await fs.readdir(getServicePartitionsDirectory()); 16 const files = await fs.readdir(getServicePartitionsDirectory());
17 return files.filter(n => n !== '__chrome_extension'); 17 return files.filter((n) => n !== '__chrome_extension');
18} 18}
diff --git a/src/helpers/validation-helpers.js b/src/helpers/validation-helpers.js
index f489ec65e..116f19905 100644
--- a/src/helpers/validation-helpers.js
+++ b/src/helpers/validation-helpers.js
@@ -61,7 +61,7 @@ export function minLength(length) {
61 61
62export function oneRequired(targets) { 62export function oneRequired(targets) {
63 return ({ field, form }) => { 63 return ({ field, form }) => {
64 const invalidFields = targets.filter(target => form.$(target).value === ''); 64 const invalidFields = targets.filter((target) => form.$(target).value === '');
65 return [targets.length !== invalidFields.length, window.ferdi.intl.formatMessage(messages.required, { field: field.label })]; 65 return [targets.length !== invalidFields.length, window.ferdi.intl.formatMessage(messages.required, { field: field.label })];
66 }; 66 };
67} 67}
diff --git a/src/models/Recipe.js b/src/models/Recipe.js
index 4db056f26..106b4a56a 100644
--- a/src/models/Recipe.js
+++ b/src/models/Recipe.js
@@ -89,7 +89,7 @@ export default class Recipe {
89 get author() { 89 get author() {
90 try { 90 try {
91 const addresses = emailParser.parse(this.rawAuthor); 91 const addresses = emailParser.parse(this.rawAuthor);
92 return addresses.map(a => ({ email: a.address, name: a.phrase })); 92 return addresses.map((a) => ({ email: a.address, name: a.phrase }));
93 } catch (err) { 93 } catch (err) {
94 console.warn(`Not a valid author for ${this.name}`); 94 console.warn(`Not a valid author for ${this.name}`);
95 } 95 }
diff --git a/src/models/Service.js b/src/models/Service.js
index 36b310da1..79181186a 100644
--- a/src/models/Service.js
+++ b/src/models/Service.js
@@ -277,7 +277,7 @@ export default class Service {
277 277
278 this.webview.addEventListener('ipc-message', async (e) => { 278 this.webview.addEventListener('ipc-message', async (e) => {
279 if (e.channel === 'inject-js-unsafe') { 279 if (e.channel === 'inject-js-unsafe') {
280 await Promise.all(e.args.map(script => this.webview.executeJavaScript(`"use strict"; (() => { ${script} })();`))); 280 await Promise.all(e.args.map((script) => this.webview.executeJavaScript(`"use strict"; (() => { ${script} })();`)));
281 } else { 281 } else {
282 handleIPCMessage({ 282 handleIPCMessage({
283 serviceId: this.id, 283 serviceId: this.id,
diff --git a/src/models/UserAgent.js b/src/models/UserAgent.js
index 6f91d4ed0..930ae19ef 100644
--- a/src/models/UserAgent.js
+++ b/src/models/UserAgent.js
@@ -95,10 +95,10 @@ export default class UserAgent {
95 _addWebviewEvents(webview) { 95 _addWebviewEvents(webview) {
96 debug('Adding event handlers'); 96 debug('Adding event handlers');
97 97
98 this._willNavigateListener = event => this._handleNavigate(event.url, true); 98 this._willNavigateListener = (event) => this._handleNavigate(event.url, true);
99 webview.addEventListener('will-navigate', this._willNavigateListener); 99 webview.addEventListener('will-navigate', this._willNavigateListener);
100 100
101 this._didNavigateListener = event => this._handleNavigate(event.url); 101 this._didNavigateListener = (event) => this._handleNavigate(event.url);
102 webview.addEventListener('did-navigate', this._didNavigateListener); 102 webview.addEventListener('did-navigate', this._didNavigateListener);
103 } 103 }
104 104
diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js
index bbb5e6305..6b5ca7c9a 100644
--- a/src/stores/AppStore.js
+++ b/src/stores/AppStore.js
@@ -1,6 +1,11 @@
1import { ipcRenderer, shell } from 'electron'; 1import { ipcRenderer, shell } from 'electron';
2import { 2import {
3 app, screen, powerMonitor, nativeTheme, getCurrentWindow, process as remoteProcess, 3 app,
4 screen,
5 powerMonitor,
6 nativeTheme,
7 getCurrentWindow,
8 process as remoteProcess,
4} from '@electron/remote'; 9} from '@electron/remote';
5import { action, computed, observable } from 'mobx'; 10import { action, computed, observable } from 'mobx';
6import moment from 'moment'; 11import moment from 'moment';
@@ -14,13 +19,20 @@ import Store from './lib/Store';
14import Request from './lib/Request'; 19import Request from './lib/Request';
15import { CHECK_INTERVAL } from '../config'; 20import { CHECK_INTERVAL } from '../config';
16import { 21import {
17 DEFAULT_APP_SETTINGS, isMac, ferdiVersion, electronVersion, osRelease, 22 DEFAULT_APP_SETTINGS,
23 isMac,
24 ferdiVersion,
25 electronVersion,
26 osRelease,
18} from '../environment'; 27} from '../environment';
19import locales from '../i18n/translations'; 28import locales from '../i18n/translations';
20import { onVisibilityChange } from '../helpers/visibility-helper'; 29import { onVisibilityChange } from '../helpers/visibility-helper';
21import { getLocale } from '../helpers/i18n-helpers'; 30import { getLocale } from '../helpers/i18n-helpers';
22 31
23import { getServiceIdsFromPartitions, removeServicePartitionDirectory } from '../helpers/service-helpers.js'; 32import {
33 getServiceIdsFromPartitions,
34 removeServicePartitionDirectory,
35} from '../helpers/service-helpers';
24import { isValidExternalURL } from '../helpers/url-helpers'; 36import { isValidExternalURL } from '../helpers/url-helpers';
25import { sleep } from '../helpers/async-helpers'; 37import { sleep } from '../helpers/async-helpers';
26 38
@@ -49,7 +61,10 @@ export default class AppStore extends Store {
49 61
50 @observable healthCheckRequest = new Request(this.api.app, 'health'); 62 @observable healthCheckRequest = new Request(this.api.app, 'health');
51 63
52 @observable getAppCacheSizeRequest = new Request(this.api.local, 'getAppCacheSize'); 64 @observable getAppCacheSizeRequest = new Request(
65 this.api.local,
66 'getAppCacheSize',
67 );
53 68
54 @observable clearAppCacheRequest = new Request(this.api.local, 'clearCache'); 69 @observable clearAppCacheRequest = new Request(this.api.local, 'clearCache');
55 70
@@ -93,7 +108,9 @@ export default class AppStore extends Store {
93 this.actions.app.openExternalUrl.listen(this._openExternalUrl.bind(this)); 108 this.actions.app.openExternalUrl.listen(this._openExternalUrl.bind(this));
94 this.actions.app.checkForUpdates.listen(this._checkForUpdates.bind(this)); 109 this.actions.app.checkForUpdates.listen(this._checkForUpdates.bind(this));
95 this.actions.app.installUpdate.listen(this._installUpdate.bind(this)); 110 this.actions.app.installUpdate.listen(this._installUpdate.bind(this));
96 this.actions.app.resetUpdateStatus.listen(this._resetUpdateStatus.bind(this)); 111 this.actions.app.resetUpdateStatus.listen(
112 this._resetUpdateStatus.bind(this),
113 );
97 this.actions.app.healthCheck.listen(this._healthCheck.bind(this)); 114 this.actions.app.healthCheck.listen(this._healthCheck.bind(this));
98 this.actions.app.muteApp.listen(this._muteApp.bind(this)); 115 this.actions.app.muteApp.listen(this._muteApp.bind(this));
99 this.actions.app.toggleMuteApp.listen(this._toggleMuteApp.bind(this)); 116 this.actions.app.toggleMuteApp.listen(this._toggleMuteApp.bind(this));
@@ -183,9 +200,7 @@ export default class AppStore extends Store {
183 // Handle deep linking (ferdi://) 200 // Handle deep linking (ferdi://)
184 ipcRenderer.on('navigateFromDeepLink', (event, data) => { 201 ipcRenderer.on('navigateFromDeepLink', (event, data) => {
185 debug('Navigate from deep link', data); 202 debug('Navigate from deep link', data);
186 let { 203 let { url } = data;
187 url,
188 } = data;
189 if (!url) return; 204 if (!url) return;
190 205
191 url = url.replace(/\/$/, ''); 206 url = url.replace(/\/$/, '');
@@ -221,7 +236,10 @@ export default class AppStore extends Store {
221 debug('System resumed, last suspended on', this.timeSuspensionStart); 236 debug('System resumed, last suspended on', this.timeSuspensionStart);
222 this.actions.service.resetLastPollTimer(); 237 this.actions.service.resetLastPollTimer();
223 238
224 if (this.timeSuspensionStart.add(10, 'm').isBefore(moment()) && this.stores.settings.app.get('reloadAfterResume')) { 239 if (
240 this.timeSuspensionStart.add(10, 'm').isBefore(moment())
241 && this.stores.settings.app.get('reloadAfterResume')
242 ) {
225 debug('Reloading services, user info and features'); 243 debug('Reloading services, user info and features');
226 244
227 setInterval(() => { 245 setInterval(() => {
@@ -266,15 +284,15 @@ export default class AppStore extends Store {
266 ferdi: { 284 ferdi: {
267 version: ferdiVersion, 285 version: ferdiVersion,
268 electron: electronVersion, 286 electron: electronVersion,
269 installedRecipes: this.stores.recipes.all.map(recipe => ({ 287 installedRecipes: this.stores.recipes.all.map((recipe) => ({
270 id: recipe.id, 288 id: recipe.id,
271 version: recipe.version, 289 version: recipe.version,
272 })), 290 })),
273 devRecipes: this.stores.recipePreviews.dev.map(recipe => ({ 291 devRecipes: this.stores.recipePreviews.dev.map((recipe) => ({
274 id: recipe.id, 292 id: recipe.id,
275 version: recipe.version, 293 version: recipe.version,
276 })), 294 })),
277 services: this.stores.services.all.map(service => ({ 295 services: this.stores.services.all.map((service) => ({
278 id: service.id, 296 id: service.id,
279 recipe: service.recipe.id, 297 recipe: service.recipe.id,
280 isAttached: service.isAttached, 298 isAttached: service.isAttached,
@@ -285,11 +303,13 @@ export default class AppStore extends Store {
285 isDarkModeEnabled: service.isDarkModeEnabled, 303 isDarkModeEnabled: service.isDarkModeEnabled,
286 })), 304 })),
287 messages: this.stores.globalError.messages, 305 messages: this.stores.globalError.messages,
288 workspaces: this.stores.workspaces.workspaces.map(workspace => ({ 306 workspaces: this.stores.workspaces.workspaces.map((workspace) => ({
289 id: workspace.id, 307 id: workspace.id,
290 services: workspace.services, 308 services: workspace.services,
291 })), 309 })),
292 windowSettings: readJsonSync(path.join(app.getPath('userData'), 'window-state.json')), 310 windowSettings: readJsonSync(
311 path.join(app.getPath('userData'), 'window-state.json'),
312 ),
293 settings, 313 settings,
294 features: this.stores.features.features, 314 features: this.stores.features.features,
295 user: this.stores.user.data.id, 315 user: this.stores.user.data.id,
@@ -299,10 +319,7 @@ export default class AppStore extends Store {
299 319
300 // Actions 320 // Actions
301 @action _notify({ 321 @action _notify({
302 title, 322 title, options, notificationId, serviceId = null,
303 options,
304 notificationId,
305 serviceId = null,
306 }) { 323 }) {
307 if (this.stores.settings.all.app.isAppMuted) return; 324 if (this.stores.settings.all.app.isAppMuted) return;
308 325
@@ -339,15 +356,15 @@ export default class AppStore extends Store {
339 }; 356 };
340 } 357 }
341 358
342 @action _setBadge({ 359 @action _setBadge({ unreadDirectMessageCount, unreadIndirectMessageCount }) {
343 unreadDirectMessageCount,
344 unreadIndirectMessageCount,
345 }) {
346 let indicator = unreadDirectMessageCount; 360 let indicator = unreadDirectMessageCount;
347 361
348 if (indicator === 0 && unreadIndirectMessageCount !== 0) { 362 if (indicator === 0 && unreadIndirectMessageCount !== 0) {
349 indicator = '•'; 363 indicator = '•';
350 } else if (unreadDirectMessageCount === 0 && unreadIndirectMessageCount === 0) { 364 } else if (
365 unreadDirectMessageCount === 0
366 && unreadIndirectMessageCount === 0
367 ) {
351 indicator = 0; 368 indicator = 0;
352 } else { 369 } else {
353 indicator = parseInt(indicator, 10); 370 indicator = parseInt(indicator, 10);
@@ -358,9 +375,7 @@ export default class AppStore extends Store {
358 }); 375 });
359 } 376 }
360 377
361 @action _launchOnStartup({ 378 @action _launchOnStartup({ enable }) {
362 enable,
363 }) {
364 this.autoLaunchOnStart = enable; 379 this.autoLaunchOnStart = enable;
365 380
366 try { 381 try {
@@ -376,9 +391,7 @@ export default class AppStore extends Store {
376 } 391 }
377 } 392 }
378 393
379 @action _openExternalUrl({ 394 @action _openExternalUrl({ url }) {
380 url,
381 }) {
382 const parsedUrl = new URL(url); 395 const parsedUrl = new URL(url);
383 debug('open external url', parsedUrl); 396 debug('open external url', parsedUrl);
384 397
@@ -414,10 +427,7 @@ export default class AppStore extends Store {
414 this.healthCheckRequest.execute(); 427 this.healthCheckRequest.execute();
415 } 428 }
416 429
417 @action _muteApp({ 430 @action _muteApp({ isMuted, overrideSystemMute = true }) {
418 isMuted,
419 overrideSystemMute = true,
420 }) {
421 this.isSystemMuteOverridden = overrideSystemMute; 431 this.isSystemMuteOverridden = overrideSystemMute;
422 this.actions.settings.update({ 432 this.actions.settings.update({
423 type: 'app', 433 type: 'app',
@@ -437,16 +447,24 @@ export default class AppStore extends Store {
437 this.isClearingAllCache = true; 447 this.isClearingAllCache = true;
438 const clearAppCache = this.clearAppCacheRequest.execute(); 448 const clearAppCache = this.clearAppCacheRequest.execute();
439 const allServiceIds = await getServiceIdsFromPartitions(); 449 const allServiceIds = await getServiceIdsFromPartitions();
440 const allOrphanedServiceIds = allServiceIds.filter(id => !this.stores.services.all.find(s => id.replace('service-', '') === s.id)); 450 const allOrphanedServiceIds = allServiceIds.filter(
451 (id) => !this.stores.services.all.find(
452 (s) => id.replace('service-', '') === s.id,
453 ),
454 );
441 455
442 try { 456 try {
443 await Promise.all(allOrphanedServiceIds.map(id => removeServicePartitionDirectory(id))); 457 await Promise.all(
458 allOrphanedServiceIds.map((id) => removeServicePartitionDirectory(id)),
459 );
444 } catch (ex) { 460 } catch (ex) {
445 console.log('Error while deleting service partition directory - ', ex); 461 console.log('Error while deleting service partition directory - ', ex);
446 } 462 }
447 await Promise.all(this.stores.services.all.map(s => this.actions.service.clearCache({ 463 await Promise.all(
448 serviceId: s.id, 464 this.stores.services.all.map((s) => this.actions.service.clearCache({
449 }))); 465 serviceId: s.id,
466 })),
467 );
450 468
451 await clearAppCache._promise; 469 await clearAppCache._promise;
452 470
@@ -476,7 +494,11 @@ export default class AppStore extends Store {
476 locale = this.stores.user.data.locale; 494 locale = this.stores.user.data.locale;
477 } 495 }
478 496
479 if (locale && Object.prototype.hasOwnProperty.call(locales, locale) && locale !== this.locale) { 497 if (
498 locale
499 && Object.prototype.hasOwnProperty.call(locales, locale)
500 && locale !== this.locale
501 ) {
480 this.locale = locale; 502 this.locale = locale;
481 } else if (!locale) { 503 } else if (!locale) {
482 this.locale = this._getDefaultLocale(); 504 this.locale = this._getDefaultLocale();
@@ -553,7 +575,10 @@ export default class AppStore extends Store {
553 const dnd = await ipcRenderer.invoke('get-dnd'); 575 const dnd = await ipcRenderer.invoke('get-dnd');
554 debug('Do not disturb mode is', dnd); 576 debug('Do not disturb mode is', dnd);
555 // ipcRenderer.on('autoUpdate', (event, data) => { 577 // ipcRenderer.on('autoUpdate', (event, data) => {
556 if (dnd !== this.stores.settings.all.app.isAppMuted && !this.isSystemMuteOverridden) { 578 if (
579 dnd !== this.stores.settings.all.app.isAppMuted
580 && !this.isSystemMuteOverridden
581 ) {
557 this.actions.app.muteApp({ 582 this.actions.app.muteApp({
558 isMuted: dnd, 583 isMuted: dnd,
559 overrideSystemMute: false, 584 overrideSystemMute: false,
diff --git a/src/stores/NewsStore.js b/src/stores/NewsStore.js
index 86e092592..66a17cb29 100644
--- a/src/stores/NewsStore.js
+++ b/src/stores/NewsStore.js
@@ -38,7 +38,7 @@ export default class NewsStore extends Store {
38 38
39 this.latestNewsRequest.invalidate().patch((result) => { 39 this.latestNewsRequest.invalidate().patch((result) => {
40 // TODO: check if we can use mobx.array remove 40 // TODO: check if we can use mobx.array remove
41 remove(result, n => n.id === newsId); 41 remove(result, (n) => n.id === newsId);
42 }); 42 });
43 } 43 }
44 44
diff --git a/src/stores/RecipePreviewsStore.js b/src/stores/RecipePreviewsStore.js
index 989e1124a..10c170e81 100644
--- a/src/stores/RecipePreviewsStore.js
+++ b/src/stores/RecipePreviewsStore.js
@@ -31,7 +31,7 @@ export default class RecipePreviewsStore extends Store {
31 } 31 }
32 32
33 @computed get dev() { 33 @computed get dev() {
34 return this.stores.recipes.all.filter(r => r.local); 34 return this.stores.recipes.all.filter((r) => r.local);
35 } 35 }
36 36
37 // Actions 37 // Actions
diff --git a/src/stores/RecipesStore.js b/src/stores/RecipesStore.js
index b49fb72d9..c7c4c1deb 100644
--- a/src/stores/RecipesStore.js
+++ b/src/stores/RecipesStore.js
@@ -54,11 +54,11 @@ export default class RecipesStore extends Store {
54 } 54 }
55 55
56 @computed get recipeIdForServices() { 56 @computed get recipeIdForServices() {
57 return this.stores.services.all.map(s => s.recipe.id); 57 return this.stores.services.all.map((s) => s.recipe.id);
58 } 58 }
59 59
60 one(id) { 60 one(id) {
61 return this.all.find(recipe => recipe.id === id); 61 return this.all.find((recipe) => recipe.id === id);
62 } 62 }
63 63
64 isInstalled(id) { 64 isInstalled(id) {
@@ -78,7 +78,7 @@ export default class RecipesStore extends Store {
78 const recipes = {}; 78 const recipes = {};
79 79
80 // Hackfix, reference this.all to fetch services 80 // Hackfix, reference this.all to fetch services
81 debug(`Check Recipe updates for ${this.all.map(recipe => recipe.id)}`); 81 debug(`Check Recipe updates for ${this.all.map((recipe) => recipe.id)}`);
82 82
83 recipeIds.forEach((r) => { 83 recipeIds.forEach((r) => {
84 const recipe = this.one(r); 84 const recipe = this.one(r);
@@ -98,7 +98,7 @@ export default class RecipesStore extends Store {
98 const version = recipes[recipe]; 98 const version = recipes[recipe];
99 99
100 // Find recipe in local recipe repository 100 // Find recipe in local recipe repository
101 const localRecipe = allJson.find(r => r.id === recipe); 101 const localRecipe = allJson.find((r) => r.id === recipe);
102 102
103 if (localRecipe && semver.lt(version, localRecipe.version)) { 103 if (localRecipe && semver.lt(version, localRecipe.version)) {
104 localUpdates.push(recipe); 104 localUpdates.push(recipe);
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js
index fa31dc292..fefcb5080 100644
--- a/src/stores/ServicesStore.js
+++ b/src/stores/ServicesStore.js
@@ -216,7 +216,7 @@ export default class ServicesStore extends Store {
216 } 216 }
217 217
218 @computed get enabled() { 218 @computed get enabled() {
219 return this.all.filter(service => service.isEnabled); 219 return this.all.filter((service) => service.isEnabled);
220 } 220 }
221 221
222 @computed get allDisplayed() { 222 @computed get allDisplayed() {
@@ -229,7 +229,7 @@ export default class ServicesStore extends Store {
229 const { showDisabledServices } = this.stores.settings.all.app; 229 const { showDisabledServices } = this.stores.settings.all.app;
230 const { keepAllWorkspacesLoaded } = this.stores.workspaces.settings; 230 const { keepAllWorkspacesLoaded } = this.stores.workspaces.settings;
231 const services = this.allServicesRequest.execute().result || []; 231 const services = this.allServicesRequest.execute().result || [];
232 const filteredServices = showDisabledServices ? services : services.filter(service => service.isEnabled); 232 const filteredServices = showDisabledServices ? services : services.filter((service) => service.isEnabled);
233 233
234 let displayedServices; 234 let displayedServices;
235 if (keepAllWorkspacesLoaded) { 235 if (keepAllWorkspacesLoaded) {
@@ -244,8 +244,8 @@ export default class ServicesStore extends Store {
244 // Check if workspace needs to be kept loaded 244 // Check if workspace needs to be kept loaded
245 if (workspace.services.includes(KEEP_WS_LOADED_USID)) { 245 if (workspace.services.includes(KEEP_WS_LOADED_USID)) {
246 // Get services for workspace 246 // Get services for workspace
247 const serviceIDs = workspace.services.filter(i => i !== KEEP_WS_LOADED_USID); 247 const serviceIDs = workspace.services.filter((i) => i !== KEEP_WS_LOADED_USID);
248 const wsServices = filteredServices.filter(service => serviceIDs.includes(service.id)); 248 const wsServices = filteredServices.filter((service) => serviceIDs.includes(service.id));
249 249
250 displayedServices = [ 250 displayedServices = [
251 ...displayedServices, 251 ...displayedServices,
@@ -262,11 +262,11 @@ export default class ServicesStore extends Store {
262 } 262 }
263 263
264 @computed get filtered() { 264 @computed get filtered() {
265 return this.all.filter(service => service.name.toLowerCase().includes(this.filterNeedle.toLowerCase())); 265 return this.all.filter((service) => service.name.toLowerCase().includes(this.filterNeedle.toLowerCase()));
266 } 266 }
267 267
268 @computed get active() { 268 @computed get active() {
269 return this.all.find(service => service.isActive); 269 return this.all.find((service) => service.isActive);
270 } 270 }
271 271
272 @computed get activeSettings() { 272 @computed get activeSettings() {
@@ -284,7 +284,7 @@ export default class ServicesStore extends Store {
284 } 284 }
285 285
286 @computed get isTodosServiceAdded() { 286 @computed get isTodosServiceAdded() {
287 return this.allDisplayed.find(service => service.isTodosService && service.isEnabled) || false; 287 return this.allDisplayed.find((service) => service.isTodosService && service.isEnabled) || false;
288 } 288 }
289 289
290 @computed get isTodosServiceActive() { 290 @computed get isTodosServiceActive() {
@@ -292,7 +292,7 @@ export default class ServicesStore extends Store {
292 } 292 }
293 293
294 one(id) { 294 one(id) {
295 return this.all.find(service => service.id === id); 295 return this.all.find((service) => service.id === id);
296 } 296 }
297 297
298 async _showAddServiceInterface({ recipeId }) { 298 async _showAddServiceInterface({ recipeId }) {
@@ -400,7 +400,7 @@ export default class ServicesStore extends Store {
400 newData.iconUrl = data.customIconUrl; 400 newData.iconUrl = data.customIconUrl;
401 } 401 }
402 402
403 Object.assign(result.find(c => c.id === serviceId), newData); 403 Object.assign(result.find((c) => c.id === serviceId), newData);
404 }); 404 });
405 405
406 await request._promise; 406 await request._promise;
@@ -434,7 +434,7 @@ export default class ServicesStore extends Store {
434 } 434 }
435 435
436 this.allServicesRequest.patch((result) => { 436 this.allServicesRequest.patch((result) => {
437 remove(result, c => c.id === serviceId); 437 remove(result, (c) => c.id === serviceId);
438 }); 438 });
439 439
440 await request._promise; 440 await request._promise;
@@ -493,7 +493,7 @@ export default class ServicesStore extends Store {
493 } 493 }
494 494
495 // Update list of last used services 495 // Update list of last used services
496 this.lastUsedServices = this.lastUsedServices.filter(id => id !== serviceId); 496 this.lastUsedServices = this.lastUsedServices.filter((id) => id !== serviceId);
497 this.lastUsedServices.unshift(serviceId); 497 this.lastUsedServices.unshift(serviceId);
498 498
499 this._focusActiveService(); 499 this._focusActiveService();
@@ -505,7 +505,7 @@ export default class ServicesStore extends Store {
505 } 505 }
506 506
507 @action _setActiveNext() { 507 @action _setActiveNext() {
508 const nextIndex = this._wrapIndex(this.allDisplayed.findIndex(service => service.isActive), 1, this.allDisplayed.length); 508 const nextIndex = this._wrapIndex(this.allDisplayed.findIndex((service) => service.isActive), 1, this.allDisplayed.length);
509 509
510 // TODO: simplify this; 510 // TODO: simplify this;
511 this.all.forEach((s, index) => { 511 this.all.forEach((s, index) => {
@@ -515,7 +515,7 @@ export default class ServicesStore extends Store {
515 } 515 }
516 516
517 @action _setActivePrev() { 517 @action _setActivePrev() {
518 const prevIndex = this._wrapIndex(this.allDisplayed.findIndex(service => service.isActive), -1, this.allDisplayed.length); 518 const prevIndex = this._wrapIndex(this.allDisplayed.findIndex((service) => service.isActive), -1, this.allDisplayed.length);
519 519
520 // TODO: simplify this; 520 // TODO: simplify this;
521 this.all.forEach((s, index) => { 521 this.all.forEach((s, index) => {
@@ -689,7 +689,7 @@ export default class ServicesStore extends Store {
689 } 689 }
690 690
691 @action _sendIPCMessageToAllServices({ channel, args }) { 691 @action _sendIPCMessageToAllServices({ channel, args }) {
692 this.all.forEach(s => this.actions.service.sendIPCMessage({ 692 this.all.forEach((s) => this.actions.service.sendIPCMessage({
693 serviceId: s.id, 693 serviceId: s.id,
694 channel, 694 channel,
695 args, 695 args,
@@ -740,7 +740,7 @@ export default class ServicesStore extends Store {
740 } 740 }
741 741
742 @action _reloadAll() { 742 @action _reloadAll() {
743 this.enabled.forEach(s => this._reload({ 743 this.enabled.forEach((s) => this._reload({
744 serviceId: s.id, 744 serviceId: s.id,
745 })); 745 }));
746 } 746 }
@@ -859,7 +859,7 @@ export default class ServicesStore extends Store {
859 }; 859 };
860 860
861 if (!serviceId) { 861 if (!serviceId) {
862 this.allDisplayed.forEach(service => resetTimer(service)); 862 this.allDisplayed.forEach((service) => resetTimer(service));
863 } else { 863 } else {
864 const service = this.one(serviceId); 864 const service = this.one(serviceId);
865 if (service) { 865 if (service) {
@@ -893,7 +893,7 @@ export default class ServicesStore extends Store {
893 _mapActiveServiceToServiceModelReaction() { 893 _mapActiveServiceToServiceModelReaction() {
894 const { activeService } = this.stores.settings.all.service; 894 const { activeService } = this.stores.settings.all.service;
895 if (this.allDisplayed.length) { 895 if (this.allDisplayed.length) {
896 this.allDisplayed.map(service => Object.assign(service, { 896 this.allDisplayed.map((service) => Object.assign(service, {
897 isActive: activeService ? activeService === service.id : this.allDisplayed[0].id === service.id, 897 isActive: activeService ? activeService === service.id : this.allDisplayed[0].id === service.id,
898 })); 898 }));
899 } 899 }
@@ -904,13 +904,13 @@ export default class ServicesStore extends Store {
904 const { showMessageBadgesEvenWhenMuted } = this.stores.ui; 904 const { showMessageBadgesEvenWhenMuted } = this.stores.ui;
905 905
906 const unreadDirectMessageCount = this.allDisplayed 906 const unreadDirectMessageCount = this.allDisplayed
907 .filter(s => (showMessageBadgeWhenMuted || s.isNotificationEnabled) && showMessageBadgesEvenWhenMuted && s.isBadgeEnabled) 907 .filter((s) => (showMessageBadgeWhenMuted || s.isNotificationEnabled) && showMessageBadgesEvenWhenMuted && s.isBadgeEnabled)
908 .map(s => s.unreadDirectMessageCount) 908 .map((s) => s.unreadDirectMessageCount)
909 .reduce((a, b) => a + b, 0); 909 .reduce((a, b) => a + b, 0);
910 910
911 const unreadIndirectMessageCount = this.allDisplayed 911 const unreadIndirectMessageCount = this.allDisplayed
912 .filter(s => (showMessageBadgeWhenMuted && showMessageBadgesEvenWhenMuted) && (s.isBadgeEnabled && s.isIndirectMessageBadgeEnabled)) 912 .filter((s) => (showMessageBadgeWhenMuted && showMessageBadgesEvenWhenMuted) && (s.isBadgeEnabled && s.isIndirectMessageBadgeEnabled))
913 .map(s => s.unreadIndirectMessageCount) 913 .map((s) => s.unreadIndirectMessageCount)
914 .reduce((a, b) => a + b, 0); 914 .reduce((a, b) => a + b, 0);
915 915
916 // We can't just block this earlier, otherwise the mobx reaction won't be aware of the vars to watch in some cases 916 // We can't just block this earlier, otherwise the mobx reaction won't be aware of the vars to watch in some cases
@@ -975,7 +975,7 @@ export default class ServicesStore extends Store {
975 return; 975 return;
976 } 976 }
977 977
978 if (this.allDisplayed.findIndex(service => service.isActive) === -1 && this.allDisplayed.length !== 0) { 978 if (this.allDisplayed.findIndex((service) => service.isActive) === -1 && this.allDisplayed.length !== 0) {
979 debug('No active service found, setting active service to index 0'); 979 debug('No active service found, setting active service to index 0');
980 980
981 this._setActive({ serviceId: this.allDisplayed[0].id }); 981 this._setActive({ serviceId: this.allDisplayed[0].id });
diff --git a/src/stores/UIStore.js b/src/stores/UIStore.js
index 0ca61046a..adcd776c1 100644
--- a/src/stores/UIStore.js
+++ b/src/stores/UIStore.js
@@ -71,7 +71,7 @@ export default class UIStore extends Store {
71 71
72 @computed get theme() { 72 @computed get theme() {
73 const themeId = (this.isDarkThemeActive || this.stores.settings.app.darkMode) ? 'dark' : 'default'; 73 const themeId = (this.isDarkThemeActive || this.stores.settings.app.darkMode) ? 'dark' : 'default';
74 const accentColor = this.stores.settings.app.accentColor; 74 const { accentColor } = this.stores.settings.app;
75 return theme(themeId, accentColor); 75 return theme(themeId, accentColor);
76 } 76 }
77 77
diff --git a/src/stores/UserStore.js b/src/stores/UserStore.js
index 8a525c2ef..2e009893a 100644
--- a/src/stores/UserStore.js
+++ b/src/stores/UserStore.js
@@ -205,7 +205,7 @@ export default class UserStore extends Store {
205 } 205 }
206 206
207 @action async _invite({ invites }) { 207 @action async _invite({ invites }) {
208 const data = invites.filter(invite => invite.email !== ''); 208 const data = invites.filter((invite) => invite.email !== '');
209 209
210 const response = await this.inviteRequest.execute(data)._promise; 210 const response = await this.inviteRequest.execute(data)._promise;
211 211
@@ -250,7 +250,7 @@ export default class UserStore extends Store {
250 this.isImportLegacyServicesExecuting = true; 250 this.isImportLegacyServicesExecuting = true;
251 251
252 // Reduces recipe duplicates 252 // Reduces recipe duplicates
253 const recipes = services.filter((obj, pos, arr) => arr.map(mapObj => mapObj.recipe.id).indexOf(obj.recipe.id) === pos).map(s => s.recipe.id); 253 const recipes = services.filter((obj, pos, arr) => arr.map((mapObj) => mapObj.recipe.id).indexOf(obj.recipe.id) === pos).map((s) => s.recipe.id);
254 254
255 // Install recipes 255 // Install recipes
256 for (const recipe of recipes) { // eslint-disable-line no-unused-vars 256 for (const recipe of recipes) { // eslint-disable-line no-unused-vars
diff --git a/src/stores/lib/CachedRequest.js b/src/stores/lib/CachedRequest.js
index 31c7ce241..94f615144 100644
--- a/src/stores/lib/CachedRequest.js
+++ b/src/stores/lib/CachedRequest.js
@@ -92,7 +92,7 @@ export default class CachedRequest extends Request {
92 } 92 }
93 93
94 removeCacheForCallWith(...args) { 94 removeCacheForCallWith(...args) {
95 remove(this._apiCalls, c => isEqual(c.args, args)); 95 remove(this._apiCalls, (c) => isEqual(c.args, args));
96 } 96 }
97 97
98 _addApiCall(args) { 98 _addApiCall(args) {
@@ -102,6 +102,6 @@ export default class CachedRequest extends Request {
102 } 102 }
103 103
104 _findApiCall(args) { 104 _findApiCall(args) {
105 return this._apiCalls.find(c => isEqual(c.args, args)); 105 return this._apiCalls.find((c) => isEqual(c.args, args));
106 } 106 }
107} 107}
diff --git a/src/stores/lib/Reaction.js b/src/stores/lib/Reaction.js
index f8009b7f6..7e1bc685e 100644
--- a/src/stores/lib/Reaction.js
+++ b/src/stores/lib/Reaction.js
@@ -26,6 +26,6 @@ export default class Reaction {
26 } 26 }
27} 27}
28 28
29export const createReactions = reactions => ( 29export const createReactions = (reactions) => (
30 reactions.map(r => new Reaction(r)) 30 reactions.map((r) => new Reaction(r))
31); 31);
diff --git a/src/stores/lib/Request.js b/src/stores/lib/Request.js
index cfc857c2e..32ffe4367 100644
--- a/src/stores/lib/Request.js
+++ b/src/stores/lib/Request.js
@@ -107,7 +107,7 @@ export default class Request {
107 } 107 }
108 108
109 _triggerHooks() { 109 _triggerHooks() {
110 Request._hooks.forEach(hook => hook(this)); 110 Request._hooks.forEach((hook) => hook(this));
111 } 111 }
112 112
113 reset = () => { 113 reset = () => {
diff --git a/src/stores/lib/Store.js b/src/stores/lib/Store.js
index 8d2fb4066..b03a7e725 100644
--- a/src/stores/lib/Store.js
+++ b/src/stores/lib/Store.js
@@ -28,18 +28,18 @@ export default class Store {
28 } 28 }
29 29
30 registerReactions(reactions) { 30 registerReactions(reactions) {
31 reactions.forEach(reaction => this._reactions.push(new Reaction(reaction))); 31 reactions.forEach((reaction) => this._reactions.push(new Reaction(reaction)));
32 } 32 }
33 33
34 setup() {} 34 setup() {}
35 35
36 initialize() { 36 initialize() {
37 this.setup(); 37 this.setup();
38 this._reactions.forEach(reaction => reaction.start()); 38 this._reactions.forEach((reaction) => reaction.start());
39 } 39 }
40 40
41 teardown() { 41 teardown() {
42 this._reactions.forEach(reaction => reaction.stop()); 42 this._reactions.forEach((reaction) => reaction.stop());
43 } 43 }
44 44
45 resetStatus() { 45 resetStatus() {
diff --git a/src/webview/contextMenuBuilder.js b/src/webview/contextMenuBuilder.js
index 63eed2ebe..2598dbf03 100644
--- a/src/webview/contextMenuBuilder.js
+++ b/src/webview/contextMenuBuilder.js
@@ -61,7 +61,7 @@ module.exports = class ContextMenuBuilder {
61 * @param {function} processMenu If passed, this method will be passed the menu to change 61 * @param {function} processMenu If passed, this method will be passed the menu to change
62 * it prior to display. Signature: (menu, info) => menu 62 * it prior to display. Signature: (menu, info) => menu
63 */ 63 */
64 constructor(webContents, debugMode = false, processMenu = m => m) { 64 constructor(webContents, debugMode = false, processMenu = (m) => m) {
65 this.debugMode = debugMode; 65 this.debugMode = debugMode;
66 this.processMenu = processMenu; 66 this.processMenu = processMenu;
67 this.menu = null; 67 this.menu = null;
@@ -320,7 +320,7 @@ module.exports = class ContextMenuBuilder {
320 label: this.stringTable.copyImage(), 320 label: this.stringTable.copyImage(),
321 click: () => { 321 click: () => {
322 const result = this.convertImageToBase64(menuInfo.srcURL, 322 const result = this.convertImageToBase64(menuInfo.srcURL,
323 dataURL => clipboard.writeImage(nativeImage.createFromDataURL(dataURL))); 323 (dataURL) => clipboard.writeImage(nativeImage.createFromDataURL(dataURL)));
324 324
325 this._sendNotificationOnClipboardEvent(menuInfo.clipboardNotifications, () => `Image copied from URL: ${menuInfo.srcURL}`); 325 this._sendNotificationOnClipboardEvent(menuInfo.clipboardNotifications, () => `Image copied from URL: ${menuInfo.srcURL}`);
326 return result; 326 return result;
diff --git a/src/webview/lib/RecipeWebview.js b/src/webview/lib/RecipeWebview.js
index 3bb9352f6..305e79882 100644
--- a/src/webview/lib/RecipeWebview.js
+++ b/src/webview/lib/RecipeWebview.js
@@ -75,7 +75,7 @@ class RecipeWebview {
75 debug('Script not found', file); 75 debug('Script not found', file);
76 return null; 76 return null;
77 })).then(async (scripts) => { 77 })).then(async (scripts) => {
78 const scriptsFound = scripts.filter(script => script !== null); 78 const scriptsFound = scripts.filter((script) => script !== null);
79 if (scriptsFound.length > 0) { 79 if (scriptsFound.length > 0) {
80 debug('Inject scripts to main world', scriptsFound); 80 debug('Inject scripts to main world', scriptsFound);
81 ipcRenderer.sendToHost('inject-js-unsafe', ...scriptsFound); 81 ipcRenderer.sendToHost('inject-js-unsafe', ...scriptsFound);
diff --git a/src/webview/notifications.js b/src/webview/notifications.js
index 39a515143..205a3220c 100644
--- a/src/webview/notifications.js
+++ b/src/webview/notifications.js
@@ -4,7 +4,7 @@ import uuidV1 from 'uuid/v1';
4const debug = require('debug')('Ferdi:Notifications'); 4const debug = require('debug')('Ferdi:Notifications');
5 5
6export class NotificationsHandler { 6export class NotificationsHandler {
7 onNotify = data => data; 7 onNotify = (data) => data;
8 8
9 displayNotification(title, options) { 9 displayNotification(title, options) {
10 return new Promise((resolve) => { 10 return new Promise((resolve) => {
diff --git a/src/webview/spellchecker.js b/src/webview/spellchecker.js
index 58a04b728..b59319495 100644
--- a/src/webview/spellchecker.js
+++ b/src/webview/spellchecker.js
@@ -9,7 +9,7 @@ const [defaultLocale] = webContents.session.getSpellCheckerLanguages();
9debug('Spellchecker default locale is', defaultLocale); 9debug('Spellchecker default locale is', defaultLocale);
10 10
11export function getSpellcheckerLocaleByFuzzyIdentifier(identifier) { 11export function getSpellcheckerLocaleByFuzzyIdentifier(identifier) {
12 const locales = Object.keys(SPELLCHECKER_LOCALES).filter(key => key.toLocaleLowerCase() === identifier.toLowerCase() || key.split('-')[0] === identifier.toLowerCase()); 12 const locales = Object.keys(SPELLCHECKER_LOCALES).filter((key) => key.toLocaleLowerCase() === identifier.toLowerCase() || key.split('-')[0] === identifier.toLowerCase());
13 13
14 if (locales.length >= 1) { 14 if (locales.length >= 1) {
15 return locales[0]; 15 return locales[0];
diff --git a/tsconfig.settings.json b/tsconfig.settings.json
index 35f2cd80e..8fb9ab041 100644
--- a/tsconfig.settings.json
+++ b/tsconfig.settings.json
@@ -12,6 +12,9 @@
12 "experimentalDecorators": true, 12 "experimentalDecorators": true,
13 "composite": true, 13 "composite": true,
14 "esModuleInterop": true, 14 "esModuleInterop": true,
15 "forceConsistentCasingInFileNames": true,
16 "importHelpers": true,
17 "removeComments": true,
15 "typeRoots": ["packages/typings/types", "node_modules/@types"], 18 "typeRoots": ["packages/typings/types", "node_modules/@types"],
16 "paths": { 19 "paths": {
17 "@types/*": ["packages/typings/types/*.d.ts"], 20 "@types/*": ["packages/typings/types/*.d.ts"],
diff --git a/tslint.json b/tslint.json
deleted file mode 100644
index 975089ab0..000000000
--- a/tslint.json
+++ /dev/null
@@ -1,12 +0,0 @@
1{
2 "extends": ["tslint-config-airbnb"],
3 "rules": {
4 "import-name": false,
5 "variable-name": false,
6 "class-name": false,
7 "prefer-array-literal": false,
8 "semicolon": [true, "always"],
9 "max-line-length": false,
10 "ordered-imports": true
11 }
12}
diff --git a/uidev/src/app.tsx b/uidev/src/app.tsx
index 41930e805..ecc7020c1 100644
--- a/uidev/src/app.tsx
+++ b/uidev/src/app.tsx
@@ -5,6 +5,7 @@ import DevTools from 'mobx-react-devtools';
5import React from 'react'; 5import React from 'react';
6import injectSheet from 'react-jss'; 6import injectSheet from 'react-jss';
7 7
8import { theme, ThemeType } from '@meetfranz/theme';
8import { WithTheme } from './withTheme'; 9import { WithTheme } from './withTheme';
9 10
10import './stories/badge.stories'; 11import './stories/badge.stories';
@@ -20,7 +21,6 @@ import './stories/toggle.stories';
20 21
21import { store } from './stores'; 22import { store } from './stores';
22 23
23import { theme, ThemeType } from '@meetfranz/theme';
24const defaultTheme = theme(ThemeType.default); 24const defaultTheme = theme(ThemeType.default);
25 25
26const styles = { 26const styles = {
diff --git a/uidev/src/stores/stories.ts b/uidev/src/stores/stories.ts
index 6a98c9fd3..12bacdd59 100644
--- a/uidev/src/stores/stories.ts
+++ b/uidev/src/stores/stories.ts
@@ -1,5 +1,3 @@
1import { store } from './index';
2
3export type StorySectionName = string; 1export type StorySectionName = string;
4export type StoryName = string; 2export type StoryName = string;
5export type StoryComponent = () => JSX.Element; 3export type StoryComponent = () => JSX.Element;
diff --git a/uidev/src/stories/button.stories.tsx b/uidev/src/stories/button.stories.tsx
index 5c1c9246d..5ca657238 100644
--- a/uidev/src/stories/button.stories.tsx
+++ b/uidev/src/stories/button.stories.tsx
@@ -27,20 +27,18 @@ const styles = {
27 }, 27 },
28}; 28};
29 29
30const createStore = (args?: any) => { 30const createStore = (args?: any) => observable({ ...defaultProps, ...args });
31 return observable(Object.assign({}, defaultProps, args));
32};
33 31
34const WithStoreButton = observer(({ store }: { store: any }) => ( 32const WithStoreButton = observer(({ store }: { store: any }) => (
35 <> 33 <>
36 <Button 34 <Button
37 {...Object.assign({}, defaultProps, store)} 35 {...({ ...defaultProps, ...store })}
38 onClick={!store.onClick ? () => { 36 onClick={!store.onClick ? () => {
39 store.busy = !store.busy; 37 store.busy = !store.busy;
40 38
41 window.setTimeout(() => { 39 window.setTimeout(() => {
42 store.busy = !store.busy; 40 store.busy = !store.busy;
43 }, 1000); 41 }, 1000);
44 } : store.onClick} 42 } : store.onClick}
45 /> 43 />
46 </> 44 </>
@@ -53,58 +51,69 @@ storiesOf('Button')
53 .add('Secondary', () => ( 51 .add('Secondary', () => (
54 <WithStoreButton store={createStore({ 52 <WithStoreButton store={createStore({
55 buttonType: 'secondary', 53 buttonType: 'secondary',
56 })} /> 54 })}
55 />
57 )) 56 ))
58 .add('Success', () => ( 57 .add('Success', () => (
59 <WithStoreButton store={createStore({ 58 <WithStoreButton store={createStore({
60 buttonType: 'success', 59 buttonType: 'success',
61 })} /> 60 })}
61 />
62 )) 62 ))
63 .add('Warning', () => ( 63 .add('Warning', () => (
64 <WithStoreButton store={createStore({ 64 <WithStoreButton store={createStore({
65 buttonType: 'warning', 65 buttonType: 'warning',
66 })} /> 66 })}
67 />
67 )) 68 ))
68 .add('Danger', () => ( 69 .add('Danger', () => (
69 <WithStoreButton store={createStore({ 70 <WithStoreButton store={createStore({
70 buttonType: 'danger', 71 buttonType: 'danger',
71 })} /> 72 })}
73 />
72 )) 74 ))
73 .add('Inverted', () => ( 75 .add('Inverted', () => (
74 <WithStoreButton store={createStore({ 76 <WithStoreButton store={createStore({
75 buttonType: 'inverted', 77 buttonType: 'inverted',
76 })} /> 78 })}
79 />
77 )) 80 ))
78 .add('Full width', () => ( 81 .add('Full width', () => (
79 <WithStoreButton store={createStore({ 82 <WithStoreButton store={createStore({
80 stretch: true, 83 stretch: true,
81 })} /> 84 })}
85 />
82 )) 86 ))
83 .add('Disabled', () => ( 87 .add('Disabled', () => (
84 <WithStoreButton store={createStore({ 88 <WithStoreButton store={createStore({
85 disabled: true, 89 disabled: true,
86 })} /> 90 })}
91 />
87 )) 92 ))
88 .add('With loader', () => ( 93 .add('With loader', () => (
89 <WithStoreButton store={createStore({ 94 <WithStoreButton store={createStore({
90 busy: true, 95 busy: true,
91 })} /> 96 })}
97 />
92 )) 98 ))
93 .add('With icon', () => ( 99 .add('With icon', () => (
94 <WithStoreButton store={createStore({ 100 <WithStoreButton store={createStore({
95 icon: mdiInformation, 101 icon: mdiInformation,
96 })} /> 102 })}
103 />
97 )) 104 ))
98 .add('As link', () => ( 105 .add('As link', () => (
99 <WithStoreButton store={createStore({ 106 <WithStoreButton store={createStore({
100 href: 'https://meetfranz.com', 107 href: 'https://meetfranz.com',
101 })} /> 108 })}
109 />
102 )) 110 ))
103 .add('As link (target=_blank)', () => ( 111 .add('As link (target=_blank)', () => (
104 <WithStoreButton store={createStore({ 112 <WithStoreButton store={createStore({
105 href: 'https://meetfranz.com', 113 href: 'https://meetfranz.com',
106 target: '_blank', 114 target: '_blank',
107 })} /> 115 })}
116 />
108 )) 117 ))
109 .add('As link (with onClick)', () => ( 118 .add('As link (with onClick)', () => (
110 <WithStoreButton store={createStore({ 119 <WithStoreButton store={createStore({
@@ -113,26 +122,27 @@ storiesOf('Button')
113 e.preventDefault(); 122 e.preventDefault();
114 alert('Click event'); 123 alert('Click event');
115 }, 124 },
116 })}/> 125 })}
126 />
117 )) 127 ))
118 .add('Long multi-line button', () => ( 128 .add('Long multi-line button', () => (
119 <WithStoreButton store={createStore({ 129 <WithStoreButton store={createStore({
120 label: 'But there is something that I must say to my people, who stand on the warm threshold which leads into the palace of justice: In the process of gaining our rightful place, we must not be guilty of wrongful deeds. Let us not seek to satisfy our thirst for freedom by drinking from the cup of bitterness and hatred. We must forever conduct our struggle on the high plane of dignity and discipline. We must not allow our creative protest to degenerate into physical violence. Again and again, we must rise to the majestic heights of meeting physical force with soul force.', 130 label: 'But there is something that I must say to my people, who stand on the warm threshold which leads into the palace of justice: In the process of gaining our rightful place, we must not be guilty of wrongful deeds. Let us not seek to satisfy our thirst for freedom by drinking from the cup of bitterness and hatred. We must forever conduct our struggle on the high plane of dignity and discipline. We must not allow our creative protest to degenerate into physical violence. Again and again, we must rise to the majestic heights of meeting physical force with soul force.',
121 })} /> 131 })}
132 />
122 )) 133 ))
123 .add('Button with Input', injectSheet(styles)(observer(({ classes }: { classes: Classes }) => ( 134 .add('Button with Input', injectSheet(styles)(observer(({ classes }: { classes: Classes }) => (
124 <div className={classes.combinedElements}> 135 <div className={classes.combinedElements}>
125 <Input showLabel={false} className={classes.input} noMargin /> 136 <Input showLabel={false} className={classes.input} noMargin />
126 <WithStoreButton store={createStore({})} /> 137 <WithStoreButton store={createStore({})} />
127 </div> 138 </div>
128 )), 139 ))))
129 ))
130 .add('Icon Button with Input', injectSheet(styles)(observer(({ classes }: { classes: Classes }) => ( 140 .add('Icon Button with Input', injectSheet(styles)(observer(({ classes }: { classes: Classes }) => (
131 <div className={classes.combinedElements}> 141 <div className={classes.combinedElements}>
132 <Input showLabel={false} className={classes.input} noMargin /> 142 <Input showLabel={false} className={classes.input} noMargin />
133 <WithStoreButton store={createStore({ 143 <WithStoreButton store={createStore({
134 icon: mdiInformation, 144 icon: mdiInformation,
135 })} /> 145 })}
136 </div> 146 />
137 )), 147 </div>
138 )); 148 ))));
diff --git a/uidev/src/stories/headline.stories.tsx b/uidev/src/stories/headline.stories.tsx
index f42771cae..320ac832f 100644
--- a/uidev/src/stories/headline.stories.tsx
+++ b/uidev/src/stories/headline.stories.tsx
@@ -1,7 +1,4 @@
1import { observable } from 'mobx';
2import { observer } from 'mobx-react';
3import React from 'react'; 1import React from 'react';
4import uuid from 'uuid/v4';
5 2
6import { H1, H2, H3, H4 } from '@meetfranz/ui'; 3import { H1, H2, H3, H4 } from '@meetfranz/ui';
7import { storiesOf } from '../stores/stories'; 4import { storiesOf } from '../stores/stories';
diff --git a/uidev/src/stories/infobox.stories.tsx b/uidev/src/stories/infobox.stories.tsx
index b0416b844..fe4aaab06 100644
--- a/uidev/src/stories/infobox.stories.tsx
+++ b/uidev/src/stories/infobox.stories.tsx
@@ -14,14 +14,11 @@ interface IStoreArgs {
14 className?: string; 14 className?: string;
15} 15}
16 16
17const createStore = (args?: IStoreArgs) => { 17const createStore = (args?: IStoreArgs) => observable({ type: 'primary',
18 return observable(Object.assign({
19 type: 'primary',
20 ctaOnClick: () => { 18 ctaOnClick: () => {
21 alert('on click handler'); 19 alert('on click handler');
22 }, 20 },
23 }, args)); 21...args });
24};
25 22
26const WithStoreInfobox = observer(({ store, children }: { store: any, children: string | React.ReactNode }) => ( 23const WithStoreInfobox = observer(({ store, children }: { store: any, children: string | React.ReactNode }) => (
27 <> 24 <>
@@ -130,7 +127,8 @@ storiesOf('Infobox')
130 .add('With className', () => ( 127 .add('With className', () => (
131 <WithStoreInfobox store={createStore({ 128 <WithStoreInfobox store={createStore({
132 className: 'franz-is-awesome', 129 className: 'franz-is-awesome',
133 })}> 130 })}
131 >
134 Welcome to the world of tomorrow 132 Welcome to the world of tomorrow
135 </WithStoreInfobox> 133 </WithStoreInfobox>
136 )); 134 ));
diff --git a/uidev/src/stories/input.stories.tsx b/uidev/src/stories/input.stories.tsx
index af5e791d0..889539266 100644
--- a/uidev/src/stories/input.stories.tsx
+++ b/uidev/src/stories/input.stories.tsx
@@ -10,7 +10,7 @@ const defaultProps = () => {
10 label: 'Label', 10 label: 'Label',
11 id: `test-${id}`, 11 id: `test-${id}`,
12 name: `test-${id}`, 12 name: `test-${id}`,
13 onChange: (e: React.ChangeEvent<HTMLInputElement>) => console.log('changed event', e), 13 onChange: (e: React.ChangeEvent<HTMLInputElement>) => console.log('changed event', e),
14 }; 14 };
15}; 15};
16 16
@@ -21,7 +21,7 @@ const defaultPasswordProps = () => {
21 id: `test-${id}`, 21 id: `test-${id}`,
22 name: `test-${id}`, 22 name: `test-${id}`,
23 type: 'password', 23 type: 'password',
24 onChange: (e: React.ChangeEvent<HTMLInputElement>) => console.log('changed event', e), 24 onChange: (e: React.ChangeEvent<HTMLInputElement>) => console.log('changed event', e),
25 }; 25 };
26}; 26};
27 27
diff --git a/uidev/src/stories/loader.stories.tsx b/uidev/src/stories/loader.stories.tsx
index 84e813c04..50eb7b9e1 100644
--- a/uidev/src/stories/loader.stories.tsx
+++ b/uidev/src/stories/loader.stories.tsx
@@ -1,7 +1,4 @@
1import { observable } from 'mobx';
2import { observer } from 'mobx-react';
3import React from 'react'; 1import React from 'react';
4import uuid from 'uuid/v4';
5 2
6import { Loader } from '@meetfranz/ui'; 3import { Loader } from '@meetfranz/ui';
7import { storiesOf } from '../stores/stories'; 4import { storiesOf } from '../stores/stories';
diff --git a/uidev/src/stories/select.stories.tsx b/uidev/src/stories/select.stories.tsx
index 81f7f08a6..51ec6ed88 100644
--- a/uidev/src/stories/select.stories.tsx
+++ b/uidev/src/stories/select.stories.tsx
@@ -282,7 +282,7 @@ const defaultProps = () => {
282 }, 282 },
283 actionText: 'Select country', 283 actionText: 'Select country',
284 // defaultValue: 'AT', 284 // defaultValue: 'AT',
285 onChange: (e: React.ChangeEvent<HTMLInputElement>) => console.log('changed event', e), 285 onChange: (e: React.ChangeEvent<HTMLInputElement>) => console.log('changed event', e),
286 }; 286 };
287}; 287};
288 288
diff --git a/uidev/src/stories/textarea.stories.tsx b/uidev/src/stories/textarea.stories.tsx
index c2dd74e24..1ab21820b 100644
--- a/uidev/src/stories/textarea.stories.tsx
+++ b/uidev/src/stories/textarea.stories.tsx
@@ -11,7 +11,7 @@ const defaultProps = () => {
11 id: `test-${id}`, 11 id: `test-${id}`,
12 name: `test-${id}`, 12 name: `test-${id}`,
13 rows: 5, 13 rows: 5,
14 onChange: (e: React.ChangeEvent<HTMLInputElement>) => console.log('changed event', e), 14 onChange: (e: React.ChangeEvent<HTMLInputElement>) => console.log('changed event', e),
15 }; 15 };
16}; 16};
17 17
diff --git a/uidev/src/stories/toggle.stories.tsx b/uidev/src/stories/toggle.stories.tsx
index 091342496..af6b282bc 100644
--- a/uidev/src/stories/toggle.stories.tsx
+++ b/uidev/src/stories/toggle.stories.tsx
@@ -16,17 +16,14 @@ interface IStoreArgs {
16 error?: string; 16 error?: string;
17} 17}
18 18
19const createStore = (args?: IStoreArgs) => { 19const createStore = (args?: IStoreArgs) => observable({ id: `element-${uuid()}`,
20 return observable(Object.assign({
21 id: `element-${uuid()}`,
22 name: 'toggle', 20 name: 'toggle',
23 label: 'Label', 21 label: 'Label',
24 value: true, 22 value: true,
25 checked: false, 23 checked: false,
26 disabled: false, 24 disabled: false,
27 error: '', 25 error: '',
28 }, args)); 26...args });
29};
30 27
31const WithStoreToggle = observer(({ store }: { store: any }) => ( 28const WithStoreToggle = observer(({ store }: { store: any }) => (
32 <> 29 <>
@@ -50,21 +47,25 @@ storiesOf('Toggle')
50 .add('Checked', () => ( 47 .add('Checked', () => (
51 <WithStoreToggle store={createStore({ 48 <WithStoreToggle store={createStore({
52 checked: true, 49 checked: true,
53 })} /> 50 })}
51 />
54 )) 52 ))
55 .add('Disabled', () => ( 53 .add('Disabled', () => (
56 <WithStoreToggle store={createStore({ 54 <WithStoreToggle store={createStore({
57 checked: true, 55 checked: true,
58 disabled: true, 56 disabled: true,
59 })} /> 57 })}
58 />
60 )) 59 ))
61 .add('Long label', () => ( 60 .add('Long label', () => (
62 <WithStoreToggle store={createStore({ 61 <WithStoreToggle store={createStore({
63 label: 'Hello world, this is an insanely long label for this toggle. We need to make sure that it will be displayed correctly.', 62 label: 'Hello world, this is an insanely long label for this toggle. We need to make sure that it will be displayed correctly.',
64 })} /> 63 })}
64 />
65 )) 65 ))
66 .add('With error', () => ( 66 .add('With error', () => (
67 <WithStoreToggle store={createStore({ 67 <WithStoreToggle store={createStore({
68 error: 'Something went wrong', 68 error: 'Something went wrong',
69 })} /> 69 })}
70 />
70 )); 71 ));
diff --git a/uidev/src/withTheme/index.tsx b/uidev/src/withTheme/index.tsx
index 17a1074d3..4ef649367 100644
--- a/uidev/src/withTheme/index.tsx
+++ b/uidev/src/withTheme/index.tsx
@@ -37,14 +37,12 @@ const Container = injectSheet(styles)(({ name, classes, story }: { name: string,
37 </article> 37 </article>
38)); 38));
39 39
40export const WithTheme = ({ children }: {children: React.ReactChild}) => { 40export const WithTheme = ({ children }: { children: React.ReactChild }) => (
41 return ( 41 <>
42 <> 42 {themes.map((theme, key) => (
43 {themes.map((theme, key) => ( 43 <ThemeProvider key={key} theme={theme.variables}>
44 <ThemeProvider key={key} theme={theme.variables}> 44 <Container story={children} name={theme.name} />
45 <Container story={children} name={theme.name} /> 45 </ThemeProvider>
46 </ThemeProvider>
47 ))} 46 ))}
48 </> 47 </>
49 ); 48 );
50};
diff --git a/uidev/tslint.json b/uidev/tslint.json
deleted file mode 100644
index ec365f164..000000000
--- a/uidev/tslint.json
+++ /dev/null
@@ -1,3 +0,0 @@
1{
2 "extends": "../tslint.json"
3}