From 9c29d383f7fc284d1cc9ec87b032f183694577ce Mon Sep 17 00:00:00 2001 From: UnchartedBull Date: Thu, 13 Feb 2020 14:38:43 +0100 Subject: [PATCH 01/10] Fix numeric input values --- main.js | 7 +++++++ src/app/settings/settings.component.html | 12 ++++++------ src/app/settings/settings.component.ts | 10 +++++++++- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/main.js b/main.js index 042d1592a..6f1ddb29f 100644 --- a/main.js +++ b/main.js @@ -57,6 +57,7 @@ function createWindow() { setTimeout(sendVersionInfo, 30 * 1000); activateScreenSleepListener(); + activateReloadListener(); window.on('closed', () => { window = null; @@ -73,6 +74,12 @@ function activateScreenSleepListener() { }) } +function activateReloadListener() { + ipcMain.on("reload", () => { + window.reload() + }) +} + function sendVersionInfo() { window.webContents.send("versionInformation", { version: app.getVersion() diff --git a/src/app/settings/settings.component.html b/src/app/settings/settings.component.html index ba3a6f846..f18886d1f 100644 --- a/src/app/settings/settings.component.html +++ b/src/app/settings/settings.component.html @@ -53,13 +53,13 @@ - - @@ -72,14 +72,14 @@ - - @@ -88,14 +88,14 @@ - - diff --git a/src/app/settings/settings.component.ts b/src/app/settings/settings.component.ts index faf124ce6..5edd3b07f 100644 --- a/src/app/settings/settings.component.ts +++ b/src/app/settings/settings.component.ts @@ -23,11 +23,19 @@ export class SettingsComponent implements OnInit { public version: string; private overwriteNoSave = false; private pages = []; + private ipc: any; public constructor(private configService: ConfigService, private notificationService: NotificationService, private service: AppService) { this.config = this.configService.getCurrentConfig(); this.config = this.configService.revertConfigForInput(this.config); this.getVersion(); + if (window.require) { + try { + this.ipc = window.require('electron').ipcRenderer; + } catch (e) { + this.notificationService.setError('Can\'t connect to backend', 'Please open an issue for GitHub as this shouldn\'t happen.'); + } + } } private getVersion() { @@ -82,6 +90,6 @@ export class SettingsComponent implements OnInit { this.overwriteNoSave = true; this.hideSettings(); this.configService.updateConfig(); - window.location.reload(); + this.ipc.send('reload', ''); } } From 5df227715c0362ea4bf9b65c1dfd313c6935b089 Mon Sep 17 00:00:00 2001 From: UnchartedBull Date: Thu, 13 Feb 2020 15:30:17 +0100 Subject: [PATCH 02/10] Replace Sleep Logo --- src/app/app.routing.module.ts | 2 +- src/app/standby/standby.component.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/app.routing.module.ts b/src/app/app.routing.module.ts index dc545d5b8..e471f6f67 100644 --- a/src/app/app.routing.module.ts +++ b/src/app/app.routing.module.ts @@ -15,7 +15,7 @@ import { StandbyComponent } from './standby/standby.component'; const routes: Routes = [ { path: 'main-screen', - component: MainScreenComponent + component: StandbyComponent }, { path: 'main-screen-no-touch', diff --git a/src/app/standby/standby.component.html b/src/app/standby/standby.component.html index e31923a18..afb8dd483 100644 --- a/src/app/standby/standby.component.html +++ b/src/app/standby/standby.component.html @@ -1,5 +1,5 @@
- + Shhh! OctoDash is sleeping. Press on the screen to wake me up again.
From 156419f52ad15dcd0ee8abf0906960f16d5fa3c4 Mon Sep 17 00:00:00 2001 From: UnchartedBull Date: Thu, 13 Feb 2020 15:32:58 +0100 Subject: [PATCH 03/10] delete unused icons --- src/app/settings/settings.component.html | 2 -- src/assets/discard.svg | 1 - src/assets/sleeping.svg | 1 - 3 files changed, 4 deletions(-) delete mode 100644 src/assets/discard.svg delete mode 100644 src/assets/sleeping.svg diff --git a/src/app/settings/settings.component.html b/src/app/settings/settings.component.html index f18886d1f..1af2788e1 100644 --- a/src/app/settings/settings.component.html +++ b/src/app/settings/settings.component.html @@ -329,9 +329,7 @@
  • "Upload" by Nikita Tcherednikov from thenounproject.com
  • "print" by Delta from thenounproject.com
  • "Delete" by Daily icons from thenounproject.com
  • -
  • "discard" by Alice Design from thenounproject.com
  • "Heat" by Adrien Coquet from thenounproject.com
  • -
  • "sleeping" by AomAm from thenounproject.com
  • "cubes" by artworkbean from thenounproject.com
  • Special Thanks diff --git a/src/assets/discard.svg b/src/assets/discard.svg deleted file mode 100644 index 784d8f9e4..000000000 --- a/src/assets/discard.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/sleeping.svg b/src/assets/sleeping.svg deleted file mode 100644 index 100bdaedc..000000000 --- a/src/assets/sleeping.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file From aa51544199e9812f8011f07bdac3b00b90f2de65 Mon Sep 17 00:00:00 2001 From: UnchartedBull Date: Thu, 13 Feb 2020 15:34:46 +0100 Subject: [PATCH 04/10] Cleanup --- src/assets/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/assets/.gitkeep diff --git a/src/assets/.gitkeep b/src/assets/.gitkeep deleted file mode 100644 index e69de29bb..000000000 From 1326a7ad4eb0556ada9126e5d59bcdae14f252bf Mon Sep 17 00:00:00 2001 From: UnchartedBull Date: Thu, 13 Feb 2020 16:10:40 +0100 Subject: [PATCH 05/10] Started integrating new linter --- .editorconfig | 6 + .eslintrc.js | 45 + .prettierrc.js | 11 + package-lock.json | 1016 ++++++++++++++++- package.json | 33 +- src/app/app.component.ts | 67 +- src/app/app.module.ts | 168 +-- src/app/app.routing.module.ts | 94 +- src/app/app.service.ts | 411 ++++--- src/app/bottom-bar/bottom-bar.component.ts | 74 +- src/app/config/config.service.ts | 952 ++++++++------- .../invalid-config.component.ts | 20 +- .../config/no-config/no-config.component.ts | 343 +++--- src/app/control/control.component.ts | 270 ++--- src/app/filament/filament.component.ts | 12 +- src/app/files.service.ts | 347 +++--- src/app/files/files.component.ts | 179 +-- src/app/job-status/job-status.component.ts | 66 +- src/app/job.service.ts | 376 +++--- .../layer-progress.component.ts | 53 +- src/app/main-menu/main-menu.component.ts | 31 +- src/app/main-screen/main-screen.component.ts | 33 +- .../main-screen-no-touch.component.ts | 13 +- .../notification/notification.component.ts | 54 +- src/app/notification/notification.service.ts | 75 +- src/app/octoprint-api/connectionAPI.ts | 6 +- src/app/octoprint.service.ts | 71 +- src/app/plugin-service/enclosure.service.ts | 110 +- .../plugin-service/layer-progress.service.ts | 86 +- src/app/plugin-service/psu-control.service.ts | 70 +- .../print-control/print-control.component.ts | 236 ++-- .../printer-status.component.ts | 84 +- src/app/printer.service.ts | 399 ++++--- src/app/settings/settings.component.ts | 175 +-- src/app/standby/standby.component.ts | 164 +-- src/app/url.pipe.ts | 7 +- src/environments/environment.prod.ts | 4 +- src/environments/environment.ts | 4 +- src/main.ts | 11 +- src/polyfills.ts | 3 +- src/test.ts | 20 - tsconfig.json | 5 +- tslint.json | 92 -- 43 files changed, 3707 insertions(+), 2589 deletions(-) create mode 100644 .eslintrc.js create mode 100644 .prettierrc.js delete mode 100644 src/test.ts delete mode 100644 tslint.json diff --git a/.editorconfig b/.editorconfig index b585a7616..c80d49c1c 100644 --- a/.editorconfig +++ b/.editorconfig @@ -11,3 +11,9 @@ trim_trailing_whitespace = true [*.md] max_line_length = off trim_trailing_whitespace = false + +[{*.ts,*.js,*.json}] +indent_size = 4 + +[package.json] +indent_size = 2 \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 000000000..19b8ae12a --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,45 @@ +module.exports = { + parser: '@typescript-eslint/parser', + extends: [ + 'plugin:@typescript-eslint/recommended', + 'prettier', + 'prettier/@typescript-eslint', + 'plugin:import/errors', + 'plugin:import/warnings', + 'plugin:import/typescript' + ], + parserOptions: { + ecmaVersion: 2018, + sourceType: 'module', + }, + rules: { + '@typescript-eslint/no-parameter-properties': 'off', + '@typescript-eslint/no-use-before-define': 'off', + 'prettier/prettier': 'warn', + 'import/no-unresolved': 'off', + 'camelcase': 'warn', + 'simple-import-sort/sort': 'warn', + 'sort-imports': 'off', + "import/first": "warn", + "import/newline-after-import": "warn", + "import/no-duplicates": "warn", + 'import/no-absolute-path': 'warn', + 'import/no-unused-modules': 'warn', + 'import/no-deprecated': 'warn', + 'import/no-self-import': 'error' + }, + plugins: [ + '@typescript-eslint', + 'prettier', + 'import', + 'simple-import-sort' + ], + overrides: [{ + 'files': '**/*.ts', + 'rules': { + 'import/order': ['off', { + 'newlines-between': 'always' + }], + } + }] +} diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 000000000..54477b3cf --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,11 @@ +module.exports = { + arrowParens: 'avoid', + bracketSpacing: true, + endOfLine: 'lf', + jsxBracketSameLine: true, + printWidth: 120, + semi: true, + singleQuote: true, + tabWidth: 4, + trailingComma: 'all' +}; diff --git a/package-lock.json b/package-lock.json index 70e32e7d3..7cd31022e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1874,6 +1874,12 @@ "integrity": "sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ==", "dev": true }, + "@types/eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", + "dev": true + }, "@types/estree": { "version": "0.0.42", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.42.tgz", @@ -1897,6 +1903,12 @@ "@types/node": "*" } }, + "@types/json-schema": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz", + "integrity": "sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==", + "dev": true + }, "@types/lodash": { "version": "4.14.149", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz", @@ -1946,6 +1958,71 @@ } } }, + "@typescript-eslint/eslint-plugin": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.13.0.tgz", + "integrity": "sha512-WQHCozMnuNADiqMtsNzp96FNox5sOVpU8Xt4meaT4em8lOG1SrOv92/mUbEHQVh90sldKSfcOc/I0FOb/14G1g==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "1.13.0", + "eslint-utils": "^1.3.1", + "functional-red-black-tree": "^1.0.1", + "regexpp": "^2.0.1", + "tsutils": "^3.7.0" + }, + "dependencies": { + "tsutils": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", + "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + } + } + }, + "@typescript-eslint/experimental-utils": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-1.13.0.tgz", + "integrity": "sha512-zmpS6SyqG4ZF64ffaJ6uah6tWWWgZ8m+c54XXgwFtUv0jNz8aJAVx8chMCvnk7yl6xwn8d+d96+tWp7fXzTuDg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/typescript-estree": "1.13.0", + "eslint-scope": "^4.0.0" + } + }, + "@typescript-eslint/parser": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-1.13.0.tgz", + "integrity": "sha512-ITMBs52PCPgLb2nGPoeT4iU3HdQZHcPaZVw+7CsFagRJHUhyeTgorEwHXhFf3e7Evzi8oujKNpHc8TONth8AdQ==", + "dev": true, + "requires": { + "@types/eslint-visitor-keys": "^1.0.0", + "@typescript-eslint/experimental-utils": "1.13.0", + "@typescript-eslint/typescript-estree": "1.13.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "@typescript-eslint/typescript-estree": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.13.0.tgz", + "integrity": "sha512-b5rCmd2e6DCC6tCTN9GSUAuxdYwCM/k/2wdjHGrIRGPSJotWMCe/dGpi66u42bhuh8q3QBzqM4TMA1GUUCJvdw==", + "dev": true, + "requires": { + "lodash.unescape": "4.0.1", + "semver": "5.5.0" + }, + "dependencies": { + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + } + } + }, "@webassemblyjs/ast": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", @@ -2166,6 +2243,12 @@ "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", "dev": true }, + "acorn-jsx": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", + "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", + "dev": true + }, "agent-base": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", @@ -2466,6 +2549,70 @@ "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", "dev": true }, + "array-includes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", + "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "is-string": "^1.0.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", + "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + } + } + }, "array-map": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", @@ -2499,6 +2646,69 @@ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, + "array.prototype.flat": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", + "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", + "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + } + } + }, "asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", @@ -2570,6 +2780,12 @@ "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", "dev": true }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, "async": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", @@ -3997,6 +4213,12 @@ "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", "dev": true }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, "content-disposition": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", @@ -4602,6 +4824,12 @@ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, "default-gateway": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", @@ -4882,6 +5110,15 @@ "buffer-indexof": "^1.0.0" } }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, "dom-serializer": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", @@ -5465,26 +5702,378 @@ "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", "dev": true }, - "es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dev": true, + "requires": { + "es6-promise": "^4.0.3" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", + "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.9.1", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^4.0.3", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^5.0.1", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.2.2", + "js-yaml": "^3.13.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^5.5.1", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0" + }, + "dependencies": { + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "dependencies": { + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + } + } + } + } + }, + "eslint-config-prettier": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-5.1.0.tgz", + "integrity": "sha512-+tpiaLm3wl6fPW5nq0dDyVowQM0FT61lAdWZ+sDWgk6kKzgbOnCDwlcbwI38cyCBhq+Z3ret5Iofp6/gZpO0zw==", + "dev": true, + "requires": { + "get-stdin": "^6.0.0" + } + }, + "eslint-import-resolver-node": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz", + "integrity": "sha512-b8crLDo0M5RSe5YG8Pu2DYBj71tSB6OvXkfzwbJU2w7y8P4/yo0MyF8jU26IEuEuHF2K5/gcAJE3LhQGqBBbVg==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.13.1" + }, + "dependencies": { + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "eslint-module-utils": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.5.2.tgz", + "integrity": "sha512-LGScZ/JSlqGKiT8OC+cYRxseMjyqt6QO54nl281CK93unD89ijSeRV6An8Ci/2nvWVKe8K/Tqdm75RQoIOCr+Q==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "pkg-dir": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + } + } + }, + "eslint-plugin-import": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.20.1.tgz", + "integrity": "sha512-qQHgFOTjguR+LnYRoToeZWT62XM55MBVXObHM6SKFd1VzDcX/vqT1kAz8ssqigh5eMj8qXcRoXXGZpPP6RfdCw==", + "dev": true, + "requires": { + "array-includes": "^3.0.3", + "array.prototype.flat": "^1.2.1", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.2", + "eslint-module-utils": "^2.4.1", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.0", + "read-pkg-up": "^2.0.0", + "resolve": "^1.12.0" + }, + "dependencies": { + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } + } + }, + "eslint-plugin-prettier": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.2.tgz", + "integrity": "sha512-GlolCC9y3XZfv3RQfwGew7NnuFDKsfI4lbvRK+PIIo23SFH+LemGs4cKwzAaRa+Mdb+lQO/STaIayno8T5sJJA==", "dev": true, "requires": { - "es6-promise": "^4.0.3" + "prettier-linter-helpers": "^1.0.0" } }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "eslint-plugin-simple-import-sort": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-4.0.0.tgz", + "integrity": "sha512-QsxOMrXhhqvSiTmZafPc/lvSET9lhblaO2kaaSbFo1FVU/AW9mFQDXadiHJ5OqG6i0N6+Qd+RZ95iQbkg4p+0w==", + "dev": true, + "requires": { + "validate-npm-package-name": "^3.0.0" + } }, "eslint-scope": { "version": "4.0.3", @@ -5496,12 +6085,55 @@ "estraverse": "^4.1.1" } }, + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + }, + "espree": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", + "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", + "dev": true, + "requires": { + "acorn": "^6.0.7", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + }, + "dependencies": { + "acorn": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", + "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==", + "dev": true + } + } + }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, + "esquery": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.1.0.tgz", + "integrity": "sha512-MxYW9xKmROWF672KqjO75sszsA8Mxhw06YFeS5VHlB98KDHbOSurm3ArsjO60Eaf3QmGMCP1yn+0JQkNLo/97Q==", + "dev": true, + "requires": { + "estraverse": "^4.0.0" + } + }, "esrecurse": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", @@ -5788,11 +6420,23 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, "fastparse": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", @@ -5832,6 +6476,15 @@ "escape-string-regexp": "^1.0.5" } }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, "file-loader": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-4.2.0.tgz", @@ -5972,6 +6625,34 @@ "locate-path": "^3.0.0" } }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "flatted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "dev": true + }, "flush-write-stream": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", @@ -6664,6 +7345,12 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, "genfun": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/genfun/-/genfun-5.0.0.tgz", @@ -6676,6 +7363,12 @@ "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", "dev": true }, + "get-stdin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", + "dev": true + }, "get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", @@ -7682,6 +8375,12 @@ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, "is-svg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz", @@ -7846,6 +8545,12 @@ "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-7.0.2.tgz", "integrity": "sha512-40FRIcBSz4y0Ego3gMpbkhtIgebpxKRgW/7i1FfDNL4/xEPQKBM12tKSiCZFNQvad5K4IS3I5Sc8cxza/KSwog==" }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -7991,6 +8696,16 @@ "pify": "^4.0.1" } }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, "license-webpack-plugin": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-2.1.3.tgz", @@ -8001,6 +8716,35 @@ "webpack-sources": "^1.2.0" } }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, "loader-runner": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", @@ -8044,6 +8788,12 @@ "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", "dev": true }, + "lodash.unescape": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz", + "integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=", + "dev": true + }, "lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -8648,6 +9398,12 @@ "to-regex": "^3.0.1" } }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, "negotiator": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", @@ -9246,6 +10002,20 @@ } } }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, "ora": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/ora/-/ora-4.0.2.tgz", @@ -9530,6 +10300,23 @@ "readable-stream": "^2.1.5" } }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + }, + "dependencies": { + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + } + } + }, "parse-asn1": { "version": "5.1.5", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", @@ -10333,12 +11120,33 @@ "integrity": "sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ==", "dev": true }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, "prepend-http": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", "dev": true }, + "prettier": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", + "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", + "dev": true + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", @@ -10357,6 +11165,12 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, "promise": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", @@ -10666,6 +11480,89 @@ "util-promisify": "^2.1.0" } }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + }, + "dependencies": { + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + } + } + }, "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", @@ -10813,6 +11710,12 @@ } } }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, "regexpu-core": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", @@ -11466,6 +12369,17 @@ "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", "dev": true }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, "smart-buffer": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz", @@ -12240,6 +13154,46 @@ "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", "dev": true }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, "tapable": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", @@ -12449,6 +13403,12 @@ } } }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -12678,6 +13638,15 @@ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, "type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", @@ -13642,6 +14611,12 @@ } } }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, "worker-farm": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", @@ -13698,6 +14673,15 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, "write-file-atomic": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.1.tgz", diff --git a/package.json b/package.json index a8cea3266..c915ad40b 100644 --- a/package.json +++ b/package.json @@ -32,16 +32,14 @@ "output": "package" }, "linux": { - "target": [ - { - "target": "deb", - "arch": [ - "armv7l", - "arm64", - "x64" - ] - } - ], + "target": [{ + "target": "deb", + "arch": [ + "armv7l", + "arm64", + "x64" + ] + }], "category": "Utility" } }, @@ -51,8 +49,8 @@ "start:big": "npm-run-all -p ng:serve electron:serve:big", "build": "npm run ng:build && electron .", "test": "", - "lint": "ng lint", - "e2e": "ng e2e", + "lint": "eslint ./src/ -c .eslintrc.js --ext .ts", + "lint:fix": "eslint ./src/ -c .eslintrc.js --ext .ts --fix", "electron": "electron .", "electron:serve": "wait-on http-get://localhost:4200/ && electron . --serve", "electron:serve:big": "wait-on http-get://localhost:4200/ && electron . --serve --big", @@ -94,13 +92,20 @@ "@types/ajv": "^1.0.0", "@types/lodash": "^4.14.149", "@types/node": "^12.11.1", + "@typescript-eslint/eslint-plugin": "^1.13.0", + "@typescript-eslint/parser": "^1.13.0", "codelyzer": "^5.1.2", - "electron": "^8.0.0", "electron-builder": "^22.3.2", "electron-reload": "^1.5.0", + "electron": "^8.0.0", + "eslint-config-prettier": "^5.1.0", + "eslint-plugin-import": "^2.18.2", + "eslint-plugin-prettier": "^3.1.0", + "eslint-plugin-simple-import-sort": "^4.0.0", + "eslint": "^5.16.0", "npm-run-all": "^4.1.5", + "prettier": "^1.18.2", "ts-node": "~8.6.2", - "tslint": "~5.20.1", "typescript": "~3.7.5", "wait-on": "^4.0.0" } diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 96697891d..de2c5d6f4 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,47 +1,46 @@ +import { Component } from '@angular/core'; +import { Router } from '@angular/router'; import _ from 'lodash'; + import { AppService } from './app.service'; -import { Component, } from '@angular/core'; import { ConfigService } from './config/config.service'; -import { Router } from '@angular/router'; @Component({ - selector: 'app-root', - templateUrl: './app.component.html', - styleUrls: ['./app.component.scss'] + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.scss'], }) - export class AppComponent { + public constructor(private configService: ConfigService, private service: AppService, private router: Router) { + this.initialize(); + } - constructor(private configService: ConfigService, private service: AppService, private router: Router) { - this.initialize(); - } - - initialize() { - if (this.configService && this.configService.isInitialized()) { - if (this.configService.isLoaded()) { - if (this.configService.isValid()) { - if (this.configService.isTouchscreen()) { - this.router.navigate(['/main-screen']); - } else { - this.router.navigate(['/main-screen-no-touch']); - } - } else { - if (_.isEqual(this.configService.getErrors(), this.service.getUpdateError())) { - if (this.service.autoFixError()) { - this.initialize(); + private initialize(): void { + if (this.configService && this.configService.isInitialized()) { + if (this.configService.isLoaded()) { + if (this.configService.isValid()) { + if (this.configService.isTouchscreen()) { + this.router.navigate(['/main-screen']); + } else { + this.router.navigate(['/main-screen-no-touch']); + } + } else { + if (_.isEqual(this.configService.getErrors(), this.service.getUpdateError())) { + if (this.service.autoFixError()) { + this.initialize(); + } else { + this.configService.setUpdate(); + this.router.navigate(['/no-config']); + } + } else { + this.router.navigate(['/invalid-config']); + } + } } else { - this.configService.setUpdate(); - this.router.navigate(['/no-config']); + this.router.navigate(['/no-config']); } - } else { - this.router.navigate(['/invalid-config']); - } + } else { + setTimeout(this.initialize.bind(this), 1000); } - } else { - this.router.navigate(['/no-config']); - } - } else { - setTimeout(this.initialize.bind(this), 1000); } - } } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 3be5463ca..8b1882432 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,113 +1,113 @@ -import { BrowserModule, HammerGestureConfig, HAMMER_GESTURE_CONFIG } from '@angular/platform-browser'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { FormsModule } from '@angular/forms'; import { HttpClientModule } from '@angular/common/http'; -import { NgModule, Injectable } from '@angular/core'; +import { Injectable, NgModule } from '@angular/core'; +import { FormsModule } from '@angular/forms'; import { MatRippleModule } from '@angular/material/core'; +import { BrowserModule, HAMMER_GESTURE_CONFIG, HammerGestureConfig } from '@angular/platform-browser'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { FaIconLibrary, FontAwesomeModule } from '@fortawesome/angular-fontawesome'; +import { fas } from '@fortawesome/free-solid-svg-icons'; +import { RoundProgressModule } from 'angular-svg-round-progressbar'; +import * as Hammer from 'hammerjs'; +import { NgxSpinnerModule } from 'ngx-spinner'; import { AppComponent } from './app.component'; import { AppRoutingModule } from './app.routing.module'; +import { AppService } from './app.service'; import { BottomBarComponent } from './bottom-bar/bottom-bar.component'; +import { ConfigService } from './config/config.service'; +import { InvalidConfigComponent } from './config/invalid-config/invalid-config.component'; +import { NoConfigComponent } from './config/no-config/no-config.component'; import { ControlComponent } from './control/control.component'; import { FilamentComponent } from './filament/filament.component'; import { FilesComponent } from './files/files.component'; -import { InvalidConfigComponent } from './config/invalid-config/invalid-config.component'; import { JobStatusComponent } from './job-status/job-status.component'; +import { JobService } from './job.service'; import { LayerProgressComponent } from './layer-progress/layer-progress.component'; import { MainMenuComponent } from './main-menu/main-menu.component'; import { MainScreenComponent } from './main-screen/main-screen.component'; import { MainScreenNoTouchComponent } from './main-screen/no-touch/main-screen-no-touch.component'; -import { NoConfigComponent } from './config/no-config/no-config.component'; import { NotificationComponent } from './notification/notification.component'; +import { NotificationService } from './notification/notification.service'; import { PrintControlComponent } from './print-control/print-control.component'; import { PrinterStatusComponent } from './printer-status/printer-status.component'; +import { PrinterService } from './printer.service'; import { SettingsComponent } from './settings/settings.component'; import { StandbyComponent } from './standby/standby.component'; - -import { AppService } from './app.service'; -import { ConfigService } from './config/config.service'; -import { NotificationService } from './notification/notification.service'; -import { JobService } from './job.service'; -import { PrinterService } from './printer.service'; - import { URLSafePipe } from './url.pipe'; -import { fas } from '@fortawesome/free-solid-svg-icons'; -import { FontAwesomeModule, FaIconLibrary } from '@fortawesome/angular-fontawesome'; -import { NgxSpinnerModule } from 'ngx-spinner'; - -import * as Hammer from 'hammerjs'; -import { RoundProgressModule } from 'angular-svg-round-progressbar'; - @Injectable() export class HammerConfig extends HammerGestureConfig { - overrides = { - pan: { - direction: 6 - }, - pinch: { - enable: false - }, - rotate: { - enable: false - }, - press: { - pointers: 1, time: 501, threshold: 15 - }, - swipe: { - pointers: 1, direction: Hammer.DIRECTION_LEFT, threshold: 20, velocity: 0.4 - } - }; + public overrides = { + pan: { + direction: 6, + }, + pinch: { + enable: false, + }, + rotate: { + enable: false, + }, + press: { + pointers: 1, + time: 501, + threshold: 15, + }, + swipe: { + pointers: 1, + direction: Hammer.DIRECTION_LEFT, + threshold: 20, + velocity: 0.4, + }, + }; } @NgModule({ - declarations: [ - AppComponent, - BottomBarComponent, - PrinterStatusComponent, - JobStatusComponent, - LayerProgressComponent, - InvalidConfigComponent, - NoConfigComponent, - PrintControlComponent, - NotificationComponent, - MainMenuComponent, - ControlComponent, - MainScreenComponent, - MainScreenNoTouchComponent, - FilamentComponent, - FilesComponent, - SettingsComponent, - URLSafePipe, - StandbyComponent - ], - imports: [ - BrowserModule, - HttpClientModule, - AppRoutingModule, - RoundProgressModule, - FormsModule, - FontAwesomeModule, - NgxSpinnerModule, - BrowserAnimationsModule, - MatRippleModule - ], - providers: [ - AppService, - ConfigService, - NotificationService, - PrinterService, - JobService, - { - provide: HAMMER_GESTURE_CONFIG, - useClass: HammerConfig - } - ], - bootstrap: [AppComponent] + declarations: [ + AppComponent, + BottomBarComponent, + PrinterStatusComponent, + JobStatusComponent, + LayerProgressComponent, + InvalidConfigComponent, + NoConfigComponent, + PrintControlComponent, + NotificationComponent, + MainMenuComponent, + ControlComponent, + MainScreenComponent, + MainScreenNoTouchComponent, + FilamentComponent, + FilesComponent, + SettingsComponent, + URLSafePipe, + StandbyComponent, + ], + imports: [ + BrowserModule, + HttpClientModule, + AppRoutingModule, + RoundProgressModule, + FormsModule, + FontAwesomeModule, + NgxSpinnerModule, + BrowserAnimationsModule, + MatRippleModule, + ], + providers: [ + AppService, + ConfigService, + NotificationService, + PrinterService, + JobService, + { + provide: HAMMER_GESTURE_CONFIG, + useClass: HammerConfig, + }, + ], + bootstrap: [AppComponent], }) - export class AppModule { - constructor(library: FaIconLibrary) { - library.addIconPacks(fas); - } + public constructor(library: FaIconLibrary) { + library.addIconPacks(fas); + } } diff --git a/src/app/app.routing.module.ts b/src/app/app.routing.module.ts index e471f6f67..b0e5da8cd 100644 --- a/src/app/app.routing.module.ts +++ b/src/app/app.routing.module.ts @@ -1,65 +1,59 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; -import { ControlComponent } from './control/control.component'; -import { MainScreenComponent } from './main-screen/main-screen.component'; + import { InvalidConfigComponent } from './config/invalid-config/invalid-config.component'; import { NoConfigComponent } from './config/no-config/no-config.component'; -import { MainScreenNoTouchComponent } from './main-screen/no-touch/main-screen-no-touch.component'; +import { ControlComponent } from './control/control.component'; import { FilamentComponent } from './filament/filament.component'; import { FilesComponent } from './files/files.component'; +import { MainScreenComponent } from './main-screen/main-screen.component'; +import { MainScreenNoTouchComponent } from './main-screen/no-touch/main-screen-no-touch.component'; import { SettingsComponent } from './settings/settings.component'; import { StandbyComponent } from './standby/standby.component'; - const routes: Routes = [ - { - path: 'main-screen', - component: StandbyComponent - }, - { - path: 'main-screen-no-touch', - component: MainScreenNoTouchComponent - }, - { - path: 'control', - component: ControlComponent - }, - { - path: 'filament', - component: FilamentComponent - }, - { - path: 'files', - component: FilesComponent - }, - { - path: 'invalid-config', - component: InvalidConfigComponent - }, - { - path: 'no-config', - component: NoConfigComponent - }, - { - path: 'settings', - component: SettingsComponent - }, - { - path: 'standby', - component: StandbyComponent - } + { + path: 'main-screen', + component: MainScreenComponent, + }, + { + path: 'main-screen-no-touch', + component: MainScreenNoTouchComponent, + }, + { + path: 'control', + component: ControlComponent, + }, + { + path: 'filament', + component: FilamentComponent, + }, + { + path: 'files', + component: FilesComponent, + }, + { + path: 'invalid-config', + component: InvalidConfigComponent, + }, + { + path: 'no-config', + component: NoConfigComponent, + }, + { + path: 'settings', + component: SettingsComponent, + }, + { + path: 'standby', + component: StandbyComponent, + }, ]; - @NgModule({ - declarations: [], - imports: [ - CommonModule, - RouterModule.forRoot(routes) - ], - exports: [ - RouterModule - ] + declarations: [], + imports: [CommonModule, RouterModule.forRoot(routes)], + exports: [RouterModule], }) -export class AppRoutingModule { } +export class AppRoutingModule {} diff --git a/src/app/app.service.ts b/src/app/app.service.ts index ceeeabfed..1bfd64521 100644 --- a/src/app/app.service.ts +++ b/src/app/app.service.ts @@ -1,209 +1,248 @@ -import { Injectable } from '@angular/core'; -import { ConfigService, Config } from './config/config.service'; -import { NotificationService } from './notification/notification.service'; import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; + import { ConfigOld } from './config/config.old'; +import { Config, ConfigService } from './config/config.service'; +import { NotificationService } from './notification/notification.service'; @Injectable({ - providedIn: 'root' + providedIn: 'root', }) export class AppService { + private updateError: string[]; + private loadedFile = false; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + private ipc: any; + private version: string; + + public constructor( + private configService: ConfigService, + private notificationService: NotificationService, + private http: HttpClient, + ) { + if (window.require) { + try { + this.ipc = window.require('electron').ipcRenderer; + this.ipc.on('versionInformation', ({}, versionInformation: VersionInformation): void => { + this.version = versionInformation.version; + this.checkUpdate(); + }); + } catch (e) { + this.notificationService.setError( + "Can't retrieve version information", + "Please open an issue for GitHub as this shouldn't happen.", + ); + } + } - private updateError: string[]; - private loadedFile = false; - private ipc: any; - private version: string; - - constructor(private configService: ConfigService, private notificationService: NotificationService, private http: HttpClient) { - if (window.require) { - try { - this.ipc = window.require('electron').ipcRenderer; - this.ipc.on('versionInformation', ({ }, versionInformation: VersionInformation) => { - this.version = versionInformation.version; - this.checkUpdate(); - }); - } catch (e) { - this.notificationService.setError('Can\'t retrieve version information', 'Please open an issue for GitHub as this shouldn\'t happen.'); - } + this.updateError = [ + ".filament should have required property 'feedLength'", + ".filament should have required property 'feedSpeed'", + ". should have required property 'plugins'", + ".octodash.customActions[0] should have required property 'confirm'", + ".octodash.customActions[0] should have required property 'exit'", + ".octodash.customActions[1] should have required property 'confirm'", + ".octodash.customActions[1] should have required property 'exit'", + ".octodash.customActions[2] should have required property 'confirm'", + ".octodash.customActions[2] should have required property 'exit'", + ".octodash.customActions[3] should have required property 'confirm'", + ".octodash.customActions[3] should have required property 'exit'", + ".octodash.customActions[4] should have required property 'confirm'", + ".octodash.customActions[4] should have required property 'exit'", + ".octodash.customActions[5] should have required property 'confirm'", + ".octodash.customActions[5] should have required property 'exit'", + ".octodash should have required property 'fileSorting'", + ".octodash should have required property 'pollingInterval'", + ".octodash should have required property 'turnScreenOffWhileSleeping'", + ]; } - this.updateError = ['.filament should have required property \'feedLength\'', '.filament should have required property \'feedSpeed\'', '. should have required property \'plugins\'', '.octodash.customActions[0] should have required property \'confirm\'', '.octodash.customActions[0] should have required property \'exit\'', '.octodash.customActions[1] should have required property \'confirm\'', '.octodash.customActions[1] should have required property \'exit\'', '.octodash.customActions[2] should have required property \'confirm\'', '.octodash.customActions[2] should have required property \'exit\'', '.octodash.customActions[3] should have required property \'confirm\'', '.octodash.customActions[3] should have required property \'exit\'', '.octodash.customActions[4] should have required property \'confirm\'', '.octodash.customActions[4] should have required property \'exit\'', '.octodash.customActions[5] should have required property \'confirm\'', '.octodash.customActions[5] should have required property \'exit\'', '.octodash should have required property \'fileSorting\'', '.octodash should have required property \'pollingInterval\'', '.octodash should have required property \'turnScreenOffWhileSleeping\'']; - } - - // If the errors can be automatically fixed return true here - public autoFixError(): boolean { - // TODO: remove ConfigOld after release - const configOld = (Object.assign({}, this.configService.getCurrentConfig()) as object) as ConfigOld; - const config: Config = { - octoprint: { - accessToken: configOld.octoprint.accessToken, - url: configOld.octoprint.url - }, - printer: { - name: configOld.printer.name, - xySpeed: configOld.printer.xySpeed, - zSpeed: configOld.printer.zSpeed - }, - filament: { - density: configOld.filament.density, - thickness: configOld.filament.thickness, - feedLength: 470, - feedSpeed: 100 - }, - plugins: { - displayLayerProgress: { - enabled: true - }, - enclosure: { - enabled: true, - ambientSensorID: configOld.octodash.temperatureSensor.ambient, - filament1SensorID: null, - filament2SensorID: null - }, - filamentManager: { - enabled: true - }, - preheatButton: { - enabled: true - }, - printTimeGenius: { - enabled: true - }, - psuControl: { - enabled: false, - turnOnPSUWhenExitingSleep: false - } - }, - octodash: { - customActions: [{ - icon: 'home', - command: 'G28', - color: '#dcdde1', - confirm: false, - exit: false - }, - { - icon: 'ruler-vertical', - command: 'G29', - color: '#44bd32', - confirm: false, - exit: false - }, - { - icon: 'fire-alt', - command: 'M140 S50; M104 S185', - color: '#e1b12c', - confirm: false, - exit: true - }, - { - icon: 'snowflake', - command: 'M140 S0; M104 S0', - color: '#0097e6', - confirm: false, - exit: true - }, - { - icon: 'redo-alt', - command: '[!RELOAD]', - color: '#7f8fa6', - confirm: true, - exit: false - }, - { - icon: 'skull', - command: '[!KILL]', - color: '#e84118', - confirm: true, - exit: false + // If the errors can be automatically fixed return true here + public autoFixError(): boolean { + // TODO: remove ConfigOld after release + const configOld = (Object.assign({}, this.configService.getCurrentConfig()) as object) as ConfigOld; + const config: Config = { + octoprint: { + accessToken: configOld.octoprint.accessToken, + url: configOld.octoprint.url, + }, + printer: { + name: configOld.printer.name, + xySpeed: configOld.printer.xySpeed, + zSpeed: configOld.printer.zSpeed, + }, + filament: { + density: configOld.filament.density, + thickness: configOld.filament.thickness, + feedLength: 470, + feedSpeed: 100, + }, + plugins: { + displayLayerProgress: { + enabled: true, + }, + enclosure: { + enabled: true, + ambientSensorID: configOld.octodash.temperatureSensor.ambient, + filament1SensorID: null, + filament2SensorID: null, + }, + filamentManager: { + enabled: true, + }, + preheatButton: { + enabled: true, + }, + printTimeGenius: { + enabled: true, + }, + psuControl: { + enabled: false, + turnOnPSUWhenExitingSleep: false, + }, + }, + octodash: { + customActions: [ + { + icon: 'home', + command: 'G28', + color: '#dcdde1', + confirm: false, + exit: false, + }, + { + icon: 'ruler-vertical', + command: 'G29', + color: '#44bd32', + confirm: false, + exit: false, + }, + { + icon: 'fire-alt', + command: 'M140 S50; M104 S185', + color: '#e1b12c', + confirm: false, + exit: true, + }, + { + icon: 'snowflake', + command: 'M140 S0; M104 S0', + color: '#0097e6', + confirm: false, + exit: true, + }, + { + icon: 'redo-alt', + command: '[!RELOAD]', + color: '#7f8fa6', + confirm: true, + exit: false, + }, + { + icon: 'skull', + command: '[!KILL]', + color: '#e84118', + confirm: true, + exit: false, + }, + ], + fileSorting: { + attribute: 'name', + order: 'asc', + }, + pollingInterval: configOld.octoprint.apiInterval, + touchscreen: configOld.octodash.touchscreen, + turnScreenOffWhileSleeping: configOld.octodash.turnScreenOffSleep, + }, + }; + this.configService.saveConfig(config); + this.configService.updateConfig(); + return false; + } + + private checkUpdate(): void { + this.http.get('https://api.github.com/repos/UnchartedBull/OctoDash/releases/latest').subscribe( + (data: GitHubRealeaseInformation): void => { + if (this.version !== data.name.replace('v', '')) { + this.notificationService.setUpdate( + "It's time for an update", + `Version ${data.name} is available now, while you're on v${this.version}. Consider updating :)`, + ); + } + }, + (): void => null, + ); + setTimeout(this.checkUpdate.bind(this), 21.6 * 1000000); + } + + public getVersion(): string { + return this.version; + } + + public turnDisplayOff(): void { + if (this.ipc) { + this.ipc.send('screenSleep', ''); } - ], - fileSorting: { - attribute: 'name', - order: 'asc' - }, - pollingInterval: configOld.octoprint.apiInterval, - touchscreen: configOld.octodash.touchscreen, - turnScreenOffWhileSleeping: configOld.octodash.turnScreenOffSleep - } - }; - this.configService.saveConfig(config); - this.configService.updateConfig(); - return false; - } - - private checkUpdate(): void { - this.http.get('https://api.github.com/repos/UnchartedBull/OctoDash/releases/latest').subscribe( - (data: GitHubRealeaseInformation) => { - if (this.version !== data.name.replace('v', '')) { - this.notificationService.setUpdate('It\'s time for an update', - `Version ${data.name} is available now, while you're on v${this.version}. Consider updating :)`); + } + + public turnDisplayOn(): void { + if (this.ipc) { + this.ipc.send('screenWakeup', ''); } - }, - () => null - ); - setTimeout(this.checkUpdate.bind(this), 21.6 * 1000000); - } - - public getVersion(): string { - return this.version; - } - - public turnDisplayOff(): void { - if (this.ipc) { - this.ipc.send('screenSleep', ''); } - } - public turnDisplayOn(): void { - if (this.ipc) { - this.ipc.send('screenWakeup', ''); + public getUpdateError(): string[] { + return this.updateError; + } + + public setLoadedFile(value: boolean): void { + this.loadedFile = value; } - } - - public getUpdateError(): string[] { - return this.updateError; - } - - public setLoadedFile(value: boolean): void { - this.loadedFile = value; - } - - public getLoadedFile(): boolean { - return this.loadedFile; - } - - public convertByteToMegabyte(byte: number): string { - return (byte / 1000000).toFixed(1); - } - - public convertDateToString(date: Date): string { - return `${('0' + date.getDate()).slice(-2)}.${('0' + (date.getMonth() + 1)).slice(-2)}.${date.getFullYear()} ${('0' + date.getHours()).slice(-2)}:${('0' + date.getMinutes()).slice(-2)}:${('0' + date.getSeconds()).slice(-2)}`; - } - - public convertSecondsToHours(input: number): string { - const hours = (input / 60 / 60); - let roundedHours = Math.floor(hours); - const minutes = (hours - roundedHours) * 60; - let roundedMinutes = Math.round(minutes); - if (roundedMinutes === 60) { - roundedMinutes = 0; - roundedHours += 1; + + public getLoadedFile(): boolean { + return this.loadedFile; + } + + public convertByteToMegabyte(byte: number): string { + return (byte / 1000000).toFixed(1); } - return roundedHours + ':' + ('0' + roundedMinutes).slice(-2); - } - public convertFilamentLengthToAmount(filamentLength: number): number { - return Math.round((Math.PI * (this.configService.getFilamentThickness() / 2) * filamentLength) - * this.configService.getFilamentDensity() / 100) / 10; - } + public convertDateToString(date: Date): string { + return `${('0' + date.getDate()).slice(-2)}.${('0' + (date.getMonth() + 1)).slice(-2)}.${date.getFullYear()} ${( + '0' + date.getHours() + ).slice(-2)}:${('0' + date.getMinutes()).slice(-2)}:${('0' + date.getSeconds()).slice(-2)}`; + } + + public convertSecondsToHours(input: number): string { + const hours = input / 60 / 60; + let roundedHours = Math.floor(hours); + const minutes = (hours - roundedHours) * 60; + let roundedMinutes = Math.round(minutes); + if (roundedMinutes === 60) { + roundedMinutes = 0; + roundedHours += 1; + } + return roundedHours + ':' + ('0' + roundedMinutes).slice(-2); + } + + public convertFilamentLengthToAmount(filamentLength: number): number { + return ( + Math.round( + (Math.PI * + (this.configService.getFilamentThickness() / 2) * + filamentLength * + this.configService.getFilamentDensity()) / + 100, + ) / 10 + ); + } } interface VersionInformation { - version: string; + version: string; } interface GitHubRealeaseInformation { - name: string; - [key: string]: any; + name: string; + [key: string]: string; } diff --git a/src/app/bottom-bar/bottom-bar.component.ts b/src/app/bottom-bar/bottom-bar.component.ts index a75809647..06bf2e8cf 100644 --- a/src/app/bottom-bar/bottom-bar.component.ts +++ b/src/app/bottom-bar/bottom-bar.component.ts @@ -1,49 +1,57 @@ -import { Component, OnInit, OnDestroy } from '@angular/core'; -import { ConfigService } from '../config/config.service'; -import { PrinterService, PrinterStatusAPI } from '../printer.service'; +import { Component, OnDestroy, OnInit } from '@angular/core'; import { Subscription } from 'rxjs'; + +import { ConfigService } from '../config/config.service'; import { EnclosureService } from '../plugin-service/enclosure.service'; +import { PrinterService, PrinterStatusAPI } from '../printer.service'; @Component({ - selector: 'app-bottom-bar', - templateUrl: './bottom-bar.component.html', - styleUrls: ['./bottom-bar.component.scss'] + selector: 'app-bottom-bar', + templateUrl: './bottom-bar.component.html', + styleUrls: ['./bottom-bar.component.scss'], }) export class BottomBarComponent implements OnDestroy { + private subscriptions: Subscription = new Subscription(); + public printer: Printer; + public enclosureTemperature: TemperatureReading; - private subscriptions: Subscription = new Subscription(); - public printer: Printer; - public enclosureTemperature: TemperatureReading; - - constructor(private printerService: PrinterService, private configService: ConfigService, private enclosureService: EnclosureService) { - if (this.configService.getAmbientTemperatureSensorName() !== null) { - this.subscriptions.add(this.enclosureService.getObservable().subscribe((temperatureReading: TemperatureReading) => { - this.enclosureTemperature = temperatureReading; - })); - } else { - this.enclosureTemperature = null; + constructor( + private printerService: PrinterService, + private configService: ConfigService, + private enclosureService: EnclosureService, + ) { + if (this.configService.getAmbientTemperatureSensorName() !== null) { + this.subscriptions.add( + this.enclosureService.getObservable().subscribe((temperatureReading: TemperatureReading) => { + this.enclosureTemperature = temperatureReading; + }), + ); + } else { + this.enclosureTemperature = null; + } + this.printer = { + name: this.configService.getPrinterName(), + status: 'connecting ...', + }; + this.subscriptions.add( + this.printerService.getObservable().subscribe((printerStatus: PrinterStatusAPI) => { + this.printer.status = printerStatus.status; + }), + ); } - this.printer = { - name: this.configService.getPrinterName(), - status: 'connecting ...' - }; - this.subscriptions.add(this.printerService.getObservable().subscribe((printerStatus: PrinterStatusAPI) => { - this.printer.status = printerStatus.status; - })); - } - public ngOnDestroy(): void { - this.subscriptions.unsubscribe(); - } + public ngOnDestroy(): void { + this.subscriptions.unsubscribe(); + } } interface Printer { - name: string; - status: string; + name: string; + status: string; } export interface TemperatureReading { - temperature: number; - humidity: number; - unit: string; + temperature: number; + humidity: number; + unit: string; } diff --git a/src/app/config/config.service.ts b/src/app/config/config.service.ts index c0c5402aa..c085e4cee 100644 --- a/src/app/config/config.service.ts +++ b/src/app/config/config.service.ts @@ -1,567 +1,521 @@ -import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; -import { environment } from '../../environments/environment'; +import { Injectable } from '@angular/core'; import Ajv from 'ajv'; import _ from 'lodash'; + +import { environment } from '../../environments/environment'; import { DisplayLayerProgressAPI } from '../plugin-service/layer-progress.service'; declare global { - interface Window { - require: any; - process: any; - } + interface Window { + require: any; + process: any; + } } @Injectable({ - providedIn: 'root' + providedIn: 'root', }) export class ConfigService { - private store: any | undefined; - private validator: Ajv.ValidateFunction; - - private config: Config; - private valid: boolean; - private update = false; - private initialized = false; - - private httpHeaders: object; - - constructor(private http: HttpClient) { - const ajv = new Ajv({ allErrors: true }); - this.validator = ajv.compile(schema); - if (window && window.process && window.process.type) { - const Store = window.require('electron-store'); - this.store = new Store(); - this.initialize(this.store.get('config')); - } else { - console.warn('Detected non-electron environment. Fallback to assets/config.json. Any changes are non-persistent!'); - this.http.get(environment.config).subscribe((config: Config) => { - this.initialize(config); - }); + private store: any | undefined; + private validator: Ajv.ValidateFunction; + + private config: Config; + private valid: boolean; + private update = false; + private initialized = false; + + private httpHeaders: object; + + constructor(private http: HttpClient) { + const ajv = new Ajv({ allErrors: true }); + this.validator = ajv.compile(schema); + if (window && window.process && window.process.type) { + const Store = window.require('electron-store'); + this.store = new Store(); + this.initialize(this.store.get('config')); + } else { + console.warn( + 'Detected non-electron environment. Fallback to assets/config.json. Any changes are non-persistent!', + ); + this.http.get(environment.config).subscribe((config: Config) => { + this.initialize(config); + }); + } } - } - - private initialize(config: Config): void { - this.config = config; - this.valid = this.validate(); - if (this.valid) { - this.httpHeaders = { - headers: new HttpHeaders({ - 'x-api-key': this.config.octoprint.accessToken, - 'Cache-Control': 'no-cache', - Pragma: 'no-cache', - Expires: '0' - }) - }; + + private initialize(config: Config): void { + this.config = config; + this.valid = this.validate(); + if (this.valid) { + this.httpHeaders = { + headers: new HttpHeaders({ + 'x-api-key': this.config.octoprint.accessToken, + 'Cache-Control': 'no-cache', + Pragma: 'no-cache', + Expires: '0', + }), + }; + } + this.initialized = true; } - this.initialized = true; - } - - public getRemoteConfig(): Config { - return this.store.get('config'); - } - - public getCurrentConfig(): Config { - return (_.cloneDeep(this.config)); - } - - public isEqualToCurrentConfig(changedConfig: Config): boolean { - return _.isEqual(this.config, changedConfig); - } - - public validate(): boolean { - return this.validator(this.config) ? true : false; - } - - public validateGiven(config: Config): boolean { - return this.validator(config) ? true : false; - } - - public getErrors(): string[] { - const errors = []; - this.validator.errors.forEach(error => { - if (error.keyword === 'type') { - errors.push(`${error.dataPath} ${error.message}`); - } else { - errors.push(`${error.dataPath === '' ? '.' : error.dataPath} ${error.message}`); - } - }); - return errors; - } - - public saveConfig(config?: Config): string { - if (!config) { - config = this.config; + + public getRemoteConfig(): Config { + return this.store.get('config'); } - if (window && window.process && window.process.type) { - this.store.set('config', config); - const configStored = this.store.get('config'); - if (this.validateGiven(configStored)) { - return null; - } else { - return ('Saved config is invalid!'); - } - } else { - return ('Browser version doesn\'t support saving!'); + + public getCurrentConfig(): Config { + return _.cloneDeep(this.config); } - } - public updateConfig() { - if (window && window.process && window.process.type) { - this.update = false; - this.initialize(this.store.get('config')); + public isEqualToCurrentConfig(changedConfig: Config): boolean { + return _.isEqual(this.config, changedConfig); } - } - public revertConfigForInput(config: Config) { - config.octoprint.urlSplit = { - url: config.octoprint.url.split(':')[1].replace('//', ''), - port: parseInt(config.octoprint.url.split(':')[2].replace('/api/', ''), 10) - }; - if (isNaN(config.octoprint.urlSplit.port)) { - config.octoprint.urlSplit.port = null; + public validate(): boolean { + return this.validator(this.config) ? true : false; + } + + public validateGiven(config: Config): boolean { + return this.validator(config) ? true : false; + } + + public getErrors(): string[] { + const errors = []; + this.validator.errors.forEach(error => { + if (error.keyword === 'type') { + errors.push(`${error.dataPath} ${error.message}`); + } else { + errors.push(`${error.dataPath === '' ? '.' : error.dataPath} ${error.message}`); + } + }); + return errors; + } + + public saveConfig(config?: Config): string { + if (!config) { + config = this.config; + } + if (window && window.process && window.process.type) { + this.store.set('config', config); + const configStored = this.store.get('config'); + if (this.validateGiven(configStored)) { + return null; + } else { + return 'Saved config is invalid!'; + } + } else { + return 'Browser version doesn\'t support saving!'; + } + } + + public updateConfig() { + if (window && window.process && window.process.type) { + this.update = false; + this.initialize(this.store.get('config')); + } + } + + public revertConfigForInput(config: Config) { + config.octoprint.urlSplit = { + url: config.octoprint.url.split(':')[1].replace('//', ''), + port: parseInt(config.octoprint.url.split(':')[2].replace('/api/', ''), 10), + }; + if (isNaN(config.octoprint.urlSplit.port)) { + config.octoprint.urlSplit.port = null; + } + return config; + } + + public createConfigFromInput(config: Config) { + const configOut = _.cloneDeep(config); + configOut.octoprint.url = `http://${configOut.octoprint.urlSplit.url}:${configOut.octoprint.urlSplit.port}/api/`; + delete configOut.octoprint.urlSplit; + return configOut; + } + + public isLoaded(): boolean { + return this.config ? true : false; + } + + public setUpdate(): void { + this.update = true; + } + + public getHTTPHeaders(): object { + return this.httpHeaders; + } + + public getURL(path: string) { + return this.config.octoprint.url + path; + } + + public getAPIPollingInterval(): number { + return this.config.octodash.pollingInterval; + } + + public getPrinterName(): string { + return this.config.printer.name; + } + + public getCustomActions(): CustomAction[] { + return this.config.octodash.customActions; + } + + public getXYSpeed(): number { + return this.config.printer.xySpeed; + } + + public getZSpeed(): number { + return this.config.printer.zSpeed; + } + + public isInitialized(): boolean { + return this.initialized; + } + + public isValid(): boolean { + return this.valid; + } + + public isUpdate(): boolean { + return this.update; + } + + public isTouchscreen(): boolean { + return this.config.octodash.touchscreen; + } + + public getAmbientTemperatureSensorName(): number { + return this.config.plugins.enclosure.ambientSensorID; + } + + public getAutomaticScreenSleep(): boolean { + return this.config.octodash.turnScreenOffWhileSleeping; + } + + public turnOnPSUWhenExitingSleep(): boolean { + return this.config.plugins.psuControl.turnOnPSUWhenExitingSleep; + } + + public getFilamentThickness(): number { + return this.config.filament.thickness; + } + + public getFilamentDensity(): number { + return this.config.filament.density; } - return config; - } - - public createConfigFromInput(config: Config) { - const configOut = _.cloneDeep(config); - configOut.octoprint.url = `http://${configOut.octoprint.urlSplit.url}:${configOut.octoprint.urlSplit.port}/api/`; - delete configOut.octoprint.urlSplit; - return configOut; - } - - public isLoaded(): boolean { - return this.config ? true : false; - } - - public setUpdate(): void { - this.update = true; - } - - public getHTTPHeaders(): object { - return this.httpHeaders; - } - - public getURL(path: string) { - return this.config.octoprint.url + path; - } - - public getAPIPollingInterval(): number { - return this.config.octodash.pollingInterval; - } - - public getPrinterName(): string { - return this.config.printer.name; - } - - public getCustomActions(): Array { - return this.config.octodash.customActions; - } - - public getXYSpeed(): number { - return this.config.printer.xySpeed; - } - - public getZSpeed(): number { - return this.config.printer.zSpeed; - } - - public isInitialized(): boolean { - return this.initialized; - } - - public isValid(): boolean { - return this.valid; - } - - public isUpdate(): boolean { - return this.update; - } - - public isTouchscreen(): boolean { - return this.config.octodash.touchscreen; - } - - public getAmbientTemperatureSensorName(): number { - return this.config.plugins.enclosure.ambientSensorID; - } - - public getAutomaticScreenSleep(): boolean { - return this.config.octodash.turnScreenOffWhileSleeping; - } - - public turnOnPSUWhenExitingSleep(): boolean { - return this.config.plugins.psuControl.turnOnPSUWhenExitingSleep; - } - - public getFilamentThickness(): number { - return this.config.filament.thickness; - } - - public getFilamentDensity(): number { - return this.config.filament.density; - } } export interface Config { - octoprint: Octoprint; - printer: Printer; - filament: Filament; - plugins: Plugins; - octodash: OctoDash; + octoprint: Octoprint; + printer: Printer; + filament: Filament; + plugins: Plugins; + octodash: OctoDash; } interface Octoprint { - url: string; - accessToken: string; - urlSplit?: { url: string; - port: number; - }; + accessToken: string; + urlSplit?: { + url: string; + port: number; + }; } interface Printer { - name: string; - xySpeed: number; - zSpeed: number; + name: string; + xySpeed: number; + zSpeed: number; } interface Filament { - thickness: number; - density: number; - feedLength: number; - feedSpeed: number; + thickness: number; + density: number; + feedLength: number; + feedSpeed: number; } interface Plugins { - displayLayerProgress: Plugin; - enclosure: EnclosurePlugin; - filamentManager: Plugin; - preheatButton: Plugin; - printTimeGenius: Plugin; - psuControl: PSUControlPlugin; + displayLayerProgress: Plugin; + enclosure: EnclosurePlugin; + filamentManager: Plugin; + preheatButton: Plugin; + printTimeGenius: Plugin; + psuControl: PSUControlPlugin; } interface Plugin { - enabled: boolean; + enabled: boolean; } interface EnclosurePlugin extends Plugin { - ambientSensorID: number | null; - filament1SensorID: number | null; - filament2SensorID: number | null; + ambientSensorID: number | null; + filament1SensorID: number | null; + filament2SensorID: number | null; } interface PSUControlPlugin extends Plugin { - turnOnPSUWhenExitingSleep: boolean; + turnOnPSUWhenExitingSleep: boolean; } interface OctoDash { - customActions: CustomAction[]; - fileSorting: FileSorting; - pollingInterval: number; - touchscreen: boolean; - turnScreenOffWhileSleeping: boolean; + customActions: CustomAction[]; + fileSorting: FileSorting; + pollingInterval: number; + touchscreen: boolean; + turnScreenOffWhileSleeping: boolean; } interface CustomAction { - icon: string; - command: string; - color: string; - confirm: boolean; - exit: boolean; + icon: string; + command: string; + color: string; + confirm: boolean; + exit: boolean; } interface FileSorting { - attribute: string; - order: string; + attribute: string; + order: string; } const schema = { - definitions: {}, - $schema: 'http://json-schema.org/draft-07/schema#', - $id: 'http://example.com/root.json', - type: 'object', - required: [ - 'octoprint', - 'printer', - 'filament', - 'plugins', - 'octodash' - ], - properties: { - octoprint: { - $id: '#/properties/octoprint', - type: 'object', - required: [ - 'accessToken', - 'url' - ], - properties: { - accessToken: { - $id: '#/properties/octoprint/properties/accessToken', - type: 'string', - pattern: '^(.*)$' - }, - url: { - $id: '#/properties/octoprint/properties/url', - type: 'string', - pattern: '^(.*)$' - } - } - }, - printer: { - $id: '#/properties/printer', - type: 'object', - required: [ - 'name', - 'xySpeed', - 'zSpeed' - ], - properties: { - name: { - $id: '#/properties/printer/properties/name', - type: 'string', - pattern: '^(.*)$' - }, - xySpeed: { - $id: '#/properties/printer/properties/xySpeed', - type: 'integer' - }, - zSpeed: { - $id: '#/properties/printer/properties/zSpeed', - type: 'integer' - } - } - }, - filament: { - $id: '#/properties/filament', - type: 'object', - required: [ - 'density', - 'thickness', - 'feedLength', - 'feedSpeed' - ], - properties: { - density: { - $id: '#/properties/filament/properties/density', - type: 'number' - }, - thickness: { - $id: '#/properties/filament/properties/thickness', - type: 'number' - }, - feedLength: { - $id: '#/properties/filament/properties/feedLength', - type: 'integer' - }, - feedSpeed: { - $id: '#/properties/filament/properties/feedSpeed', - type: 'integer' - } - } - }, - plugins: { - $id: '#/properties/plugins', - type: 'object', - required: [ - 'displayLayerProgress', - 'enclosure', - 'filamentManager', - 'preheatButton', - 'printTimeGenius', - 'psuControl' - ], - properties: { - displayLayerProgress: { - $id: '#/properties/plugins/properties/displayLayerProgress', - type: 'object', - required: [ - 'enabled' - ], - properties: { - enabled: { - $id: '#/properties/plugins/properties/displayLayerProgress/properties/enabled', - type: 'boolean' - } - } - }, - enclosure: { - $id: '#/properties/plugins/properties/enclosure', - type: 'object', - required: [ - 'enabled', - 'ambientSensorID', - 'filament1SensorID', - 'filament2SensorID' - ], - properties: { - enabled: { - $id: '#/properties/plugins/properties/enclosure/properties/enabled', - type: 'boolean' - }, - ambientSensorID: { - $id: '#/properties/plugins/properties/enclosure/properties/ambientSensorID', - type: ['number', 'null'], - pattern: '^(.*)$' - }, - filament1SensorID: { - $id: '#/properties/plugins/properties/enclosure/properties/filament1SensorID', - type: ['number', 'null'], - pattern: '^(.*)$' + definitions: {}, + $schema: 'http://json-schema.org/draft-07/schema#', + $id: 'http://example.com/root.json', + type: 'object', + required: ['octoprint', 'printer', 'filament', 'plugins', 'octodash'], + properties: { + octoprint: { + $id: '#/properties/octoprint', + type: 'object', + required: ['accessToken', 'url'], + properties: { + accessToken: { + $id: '#/properties/octoprint/properties/accessToken', + type: 'string', + pattern: '^(.*)$', + }, + url: { + $id: '#/properties/octoprint/properties/url', + type: 'string', + pattern: '^(.*)$', + }, }, - filament2SensorID: { - $id: '#/properties/plugins/properties/enclosure/properties/filament2SensorID', - type: ['number', 'null'], - pattern: '^(.*)$' - } - } - }, - filamentManager: { - $id: '#/properties/plugins/properties/filamentManager', - type: 'object', - required: [ - 'enabled' - ], - properties: { - enabled: { - $id: '#/properties/plugins/properties/filamentManager/properties/enabled', - type: 'boolean' - } - } - }, - preheatButton: { - $id: '#/properties/plugins/properties/preheatButton', - type: 'object', - required: [ - 'enabled' - ], - properties: { - enabled: { - $id: '#/properties/plugins/properties/preheatButton/properties/enabled', - type: 'boolean' - } - } }, - printTimeGenius: { - $id: '#/properties/plugins/properties/printTimeGenius', - type: 'object', - required: [ - 'enabled' - ], - properties: { - enabled: { - $id: '#/properties/plugins/properties/printTimeGenius/properties/enabled', - type: 'boolean' - } - } + printer: { + $id: '#/properties/printer', + type: 'object', + required: ['name', 'xySpeed', 'zSpeed'], + properties: { + name: { + $id: '#/properties/printer/properties/name', + type: 'string', + pattern: '^(.*)$', + }, + xySpeed: { + $id: '#/properties/printer/properties/xySpeed', + type: 'integer', + }, + zSpeed: { + $id: '#/properties/printer/properties/zSpeed', + type: 'integer', + }, + }, }, - psuControl: { - $id: '#/properties/plugins/properties/psuControl', - type: 'object', - required: [ - 'enabled', - 'turnOnPSUWhenExitingSleep' - ], - properties: { - enabled: { - $id: '#/properties/plugins/properties/printTimeGenius/properties/enabled', - type: 'boolean' + filament: { + $id: '#/properties/filament', + type: 'object', + required: ['density', 'thickness', 'feedLength', 'feedSpeed'], + properties: { + density: { + $id: '#/properties/filament/properties/density', + type: 'number', + }, + thickness: { + $id: '#/properties/filament/properties/thickness', + type: 'number', + }, + feedLength: { + $id: '#/properties/filament/properties/feedLength', + type: 'integer', + }, + feedSpeed: { + $id: '#/properties/filament/properties/feedSpeed', + type: 'integer', + }, }, - turnOnPSUWhenExitingSleep: { - $id: '#/properties/octodash/properties/turnOnPSUWhenExitingSleep', - type: 'boolean' - } - } - } - } - }, - octodash: { - $id: '#/properties/octodash', - type: 'object', - required: [ - 'customActions', - 'fileSorting', - 'pollingInterval', - 'touchscreen', - 'turnScreenOffWhileSleeping' - ], - properties: { - customActions: { - $id: '#/properties/octodash/properties/customActions', - type: 'array', - items: { - $id: '#/properties/octodash/properties/customActions/items', + }, + plugins: { + $id: '#/properties/plugins', type: 'object', required: [ - 'icon', - 'command', - 'color', - 'confirm', - 'exit' + 'displayLayerProgress', + 'enclosure', + 'filamentManager', + 'preheatButton', + 'printTimeGenius', + 'psuControl', ], properties: { - icon: { - $id: '#/properties/octodash/properties/customActions/items/properties/icon', - type: 'string', - pattern: '^(.*)$' - }, - command: { - $id: '#/properties/octodash/properties/customActions/items/properties/command', - type: 'string', - pattern: '^(.*)$' - }, - color: { - $id: '#/properties/octodash/properties/customActions/items/properties/color', - type: 'string', - pattern: '^(.*)$' - }, - confirm: { - $id: '#/properties/octodash/properties/customActions/items/properties/confirm', - type: 'boolean' - }, - exit: { - $id: '#/properties/octodash/properties/customActions/items/properties/exit', - type: 'boolean' - } - } - } - }, - fileSorting: { - $id: '#/properties/octodash/properties/fileSorting', - type: 'object', - required: [ - 'attribute', - 'order' - ], - properties: { - attribute: { - $id: '#/properties/octodash/properties/fileSorting/properties/attribute', - type: 'string', - pattern: '^(name|date|size)$' + displayLayerProgress: { + $id: '#/properties/plugins/properties/displayLayerProgress', + type: 'object', + required: ['enabled'], + properties: { + enabled: { + $id: '#/properties/plugins/properties/displayLayerProgress/properties/enabled', + type: 'boolean', + }, + }, + }, + enclosure: { + $id: '#/properties/plugins/properties/enclosure', + type: 'object', + required: ['enabled', 'ambientSensorID', 'filament1SensorID', 'filament2SensorID'], + properties: { + enabled: { + $id: '#/properties/plugins/properties/enclosure/properties/enabled', + type: 'boolean', + }, + ambientSensorID: { + $id: '#/properties/plugins/properties/enclosure/properties/ambientSensorID', + type: ['number', 'null'], + pattern: '^(.*)$', + }, + filament1SensorID: { + $id: '#/properties/plugins/properties/enclosure/properties/filament1SensorID', + type: ['number', 'null'], + pattern: '^(.*)$', + }, + filament2SensorID: { + $id: '#/properties/plugins/properties/enclosure/properties/filament2SensorID', + type: ['number', 'null'], + pattern: '^(.*)$', + }, + }, + }, + filamentManager: { + $id: '#/properties/plugins/properties/filamentManager', + type: 'object', + required: ['enabled'], + properties: { + enabled: { + $id: '#/properties/plugins/properties/filamentManager/properties/enabled', + type: 'boolean', + }, + }, + }, + preheatButton: { + $id: '#/properties/plugins/properties/preheatButton', + type: 'object', + required: ['enabled'], + properties: { + enabled: { + $id: '#/properties/plugins/properties/preheatButton/properties/enabled', + type: 'boolean', + }, + }, + }, + printTimeGenius: { + $id: '#/properties/plugins/properties/printTimeGenius', + type: 'object', + required: ['enabled'], + properties: { + enabled: { + $id: '#/properties/plugins/properties/printTimeGenius/properties/enabled', + type: 'boolean', + }, + }, + }, + psuControl: { + $id: '#/properties/plugins/properties/psuControl', + type: 'object', + required: ['enabled', 'turnOnPSUWhenExitingSleep'], + properties: { + enabled: { + $id: '#/properties/plugins/properties/printTimeGenius/properties/enabled', + type: 'boolean', + }, + turnOnPSUWhenExitingSleep: { + $id: '#/properties/octodash/properties/turnOnPSUWhenExitingSleep', + type: 'boolean', + }, + }, + }, }, - order: { - $id: '#/properties/octodash/properties/fileSorting/properties/order', - type: 'string', - pattern: '^(asc|dsc)$' - } - } - }, - pollingInterval: { - $id: '#/properties/octodash/properties/pollingInterval', - type: 'integer' }, - touchscreen: { - $id: '#/properties/octodash/properties/touchscreen', - type: 'boolean' + octodash: { + $id: '#/properties/octodash', + type: 'object', + required: ['customActions', 'fileSorting', 'pollingInterval', 'touchscreen', 'turnScreenOffWhileSleeping'], + properties: { + customActions: { + $id: '#/properties/octodash/properties/customActions', + type: 'array', + items: { + $id: '#/properties/octodash/properties/customActions/items', + type: 'object', + required: ['icon', 'command', 'color', 'confirm', 'exit'], + properties: { + icon: { + $id: '#/properties/octodash/properties/customActions/items/properties/icon', + type: 'string', + pattern: '^(.*)$', + }, + command: { + $id: '#/properties/octodash/properties/customActions/items/properties/command', + type: 'string', + pattern: '^(.*)$', + }, + color: { + $id: '#/properties/octodash/properties/customActions/items/properties/color', + type: 'string', + pattern: '^(.*)$', + }, + confirm: { + $id: '#/properties/octodash/properties/customActions/items/properties/confirm', + type: 'boolean', + }, + exit: { + $id: '#/properties/octodash/properties/customActions/items/properties/exit', + type: 'boolean', + }, + }, + }, + }, + fileSorting: { + $id: '#/properties/octodash/properties/fileSorting', + type: 'object', + required: ['attribute', 'order'], + properties: { + attribute: { + $id: '#/properties/octodash/properties/fileSorting/properties/attribute', + type: 'string', + pattern: '^(name|date|size)$', + }, + order: { + $id: '#/properties/octodash/properties/fileSorting/properties/order', + type: 'string', + pattern: '^(asc|dsc)$', + }, + }, + }, + pollingInterval: { + $id: '#/properties/octodash/properties/pollingInterval', + type: 'integer', + }, + touchscreen: { + $id: '#/properties/octodash/properties/touchscreen', + type: 'boolean', + }, + turnScreenOffWhileSleeping: { + $id: '#/properties/octodash/properties/turnScreenOffWhileSleeping', + type: 'boolean', + }, + }, }, - turnScreenOffWhileSleeping: { - $id: '#/properties/octodash/properties/turnScreenOffWhileSleeping', - type: 'boolean' - } - } - } - } + }, }; diff --git a/src/app/config/invalid-config/invalid-config.component.ts b/src/app/config/invalid-config/invalid-config.component.ts index c90e289f0..93571172a 100644 --- a/src/app/config/invalid-config/invalid-config.component.ts +++ b/src/app/config/invalid-config/invalid-config.component.ts @@ -1,19 +1,17 @@ import { Component, OnInit } from '@angular/core'; + import { ConfigService } from '../config.service'; @Component({ - selector: 'app-invalid-config', - templateUrl: './invalid-config.component.html', - styleUrls: ['./invalid-config.component.scss'] + selector: 'app-invalid-config', + templateUrl: './invalid-config.component.html', + styleUrls: ['./invalid-config.component.scss'], }) - - export class InvalidConfigComponent implements OnInit { - errors: string[]; - constructor(private configService: ConfigService) { - } + errors: string[]; + constructor(private configService: ConfigService) {} - public ngOnInit(): void { - this.errors = this.configService.getErrors(); - } + public ngOnInit(): void { + this.errors = this.configService.getErrors(); + } } diff --git a/src/app/config/no-config/no-config.component.ts b/src/app/config/no-config/no-config.component.ts index 519b22b2b..8dc362010 100644 --- a/src/app/config/no-config/no-config.component.ts +++ b/src/app/config/no-config/no-config.component.ts @@ -1,195 +1,196 @@ +import { HttpClient, HttpErrorResponse, HttpHeaders } from '@angular/common/http'; import { Component, OnInit } from '@angular/core'; -import { Config, ConfigService } from '../config.service'; -import { HttpHeaders, HttpClient, HttpErrorResponse } from '@angular/common/http'; import { Router } from '@angular/router'; +import { Config, ConfigService } from '../config.service'; + @Component({ - selector: 'app-no-config', - templateUrl: './no-config.component.html', - styleUrls: ['./no-config.component.scss'] + selector: 'app-no-config', + templateUrl: './no-config.component.html', + styleUrls: ['./no-config.component.scss'], }) export class NoConfigComponent implements OnInit { - public page = 0; - public totalPages = 5; + public page = 0; + public totalPages = 5; - private configUpdate: boolean; - public config: Config; - public configErrors: string[]; - public configValid: boolean; - public configSaved: string; + private configUpdate: boolean; + public config: Config; + public configErrors: string[]; + public configValid: boolean; + public configSaved: string; - public octoprintConnection: boolean; - public octoprintConnectionError: string; + public octoprintConnection: boolean; + public octoprintConnectionError: string; - public constructor(private configService: ConfigService, private http: HttpClient, private router: Router) { - this.configUpdate = this.configService.isUpdate(); - if (this.configUpdate) { - this.config = configService.getCurrentConfig(); - } else { - this.config = { - octoprint: { - url: 'http://localhost:5000/api/', - accessToken: '', - }, - printer: { - name: '', - xySpeed: 150, - zSpeed: 5 - }, - filament: { - thickness: 1.75, - density: 1.25, - feedLength: 470, - feedSpeed: 100, - }, - plugins: { - displayLayerProgress: { - enabled: true - }, - enclosure: { - enabled: false, - ambientSensorID: null, - filament1SensorID: null, - filament2SensorID: null - }, - filamentManager: { - enabled: true - }, - preheatButton: { - enabled: true - }, - printTimeGenius: { - enabled: true - }, - psuControl: { - enabled: false, - turnOnPSUWhenExitingSleep: false - } - }, - octodash: { - customActions: [ - { - icon: 'home', - command: 'G28', - color: '#dcdde1', - confirm: false, - exit: true - }, - { - icon: 'ruler-vertical', - command: 'G29', - color: '#44bd32', - confirm: false, - exit: true - }, - { - icon: 'fire-alt', - command: 'M140 S50; M104 S185', - color: '#e1b12c', - confirm: false, - exit: true - }, - { - icon: 'snowflake', - command: 'M140 S0; M104 S0', - color: '#0097e6', - confirm: false, - exit: true - }, - { - icon: 'redo-alt', - command: '[!RELOAD]', - color: '#7f8fa6', - confirm: true, - exit: false - }, - { - icon: 'skull', - command: '[!KILL]', - color: '#e84118', - confirm: true, - exit: false - } - ], - fileSorting: { - attribute: 'name', - order: 'asc' - }, - pollingInterval: 2000, - touchscreen: true, - turnScreenOffWhileSleeping: false + public constructor(private configService: ConfigService, private http: HttpClient, private router: Router) { + this.configUpdate = this.configService.isUpdate(); + if (this.configUpdate) { + this.config = configService.getCurrentConfig(); + } else { + this.config = { + octoprint: { + url: 'http://localhost:5000/api/', + accessToken: '', + }, + printer: { + name: '', + xySpeed: 150, + zSpeed: 5, + }, + filament: { + thickness: 1.75, + density: 1.25, + feedLength: 470, + feedSpeed: 100, + }, + plugins: { + displayLayerProgress: { + enabled: true, + }, + enclosure: { + enabled: false, + ambientSensorID: null, + filament1SensorID: null, + filament2SensorID: null, + }, + filamentManager: { + enabled: true, + }, + preheatButton: { + enabled: true, + }, + printTimeGenius: { + enabled: true, + }, + psuControl: { + enabled: false, + turnOnPSUWhenExitingSleep: false, + }, + }, + octodash: { + customActions: [ + { + icon: 'home', + command: 'G28', + color: '#dcdde1', + confirm: false, + exit: true, + }, + { + icon: 'ruler-vertical', + command: 'G29', + color: '#44bd32', + confirm: false, + exit: true, + }, + { + icon: 'fire-alt', + command: 'M140 S50; M104 S185', + color: '#e1b12c', + confirm: false, + exit: true, + }, + { + icon: 'snowflake', + command: 'M140 S0; M104 S0', + color: '#0097e6', + confirm: false, + exit: true, + }, + { + icon: 'redo-alt', + command: '[!RELOAD]', + color: '#7f8fa6', + confirm: true, + exit: false, + }, + { + icon: 'skull', + command: '[!KILL]', + color: '#e84118', + confirm: true, + exit: false, + }, + ], + fileSorting: { + attribute: 'name', + order: 'asc', + }, + pollingInterval: 2000, + touchscreen: true, + turnScreenOffWhileSleeping: false, + }, + }; } - }; + this.config = this.configService.revertConfigForInput(this.config); } - this.config = this.configService.revertConfigForInput(this.config); - } - public ngOnInit(): void { - this.changeProgress(); - } + public ngOnInit(): void { + this.changeProgress(); + } - public testOctoprintAPI(): boolean { - const httpHeaders = { - headers: new HttpHeaders({ - 'x-api-key': this.config.octoprint.accessToken - }) - }; - this.http.get(this.config.octoprint.url + 'version', httpHeaders).subscribe( - () => { - this.octoprintConnection = true; - this.saveConfig(); - }, - (error: HttpErrorResponse) => { - this.octoprintConnection = false; - this.octoprintConnectionError = error.message; - } - ); - return true; - } + public testOctoprintAPI(): boolean { + const httpHeaders = { + headers: new HttpHeaders({ + 'x-api-key': this.config.octoprint.accessToken, + }), + }; + this.http.get(this.config.octoprint.url + 'version', httpHeaders).subscribe( + () => { + this.octoprintConnection = true; + this.saveConfig(); + }, + (error: HttpErrorResponse) => { + this.octoprintConnection = false; + this.octoprintConnectionError = error.message; + }, + ); + return true; + } - public createConfig(): boolean { - this.configErrors = []; - this.octoprintConnectionError = null; - this.config = this.configService.createConfigFromInput(this.config); - this.validateConfig(); - return true; - } + public createConfig(): boolean { + this.configErrors = []; + this.octoprintConnectionError = null; + this.config = this.configService.createConfigFromInput(this.config); + this.validateConfig(); + return true; + } - public validateConfig(): void { - this.configValid = this.configService.validateGiven(this.config); - if (!this.configValid) { - this.configErrors = this.configService.getErrors(); - } else { - this.testOctoprintAPI(); + public validateConfig(): void { + this.configValid = this.configService.validateGiven(this.config); + if (!this.configValid) { + this.configErrors = this.configService.getErrors(); + } else { + this.testOctoprintAPI(); + } } - } - public saveConfig(): void { - this.configSaved = this.configService.saveConfig(this.config); - } + public saveConfig(): void { + this.configSaved = this.configService.saveConfig(this.config); + } - public finishWizard(): void { - this.configService.updateConfig(); - this.router.navigate(['/main-screen']); - } + public finishWizard(): void { + this.configService.updateConfig(); + this.router.navigate(['/main-screen']); + } - public increasePage(): void { - this.page += 1; - if (this.page === this.totalPages) { - this.createConfig(); + public increasePage(): void { + this.page += 1; + if (this.page === this.totalPages) { + this.createConfig(); + } + this.changeProgress(); } - this.changeProgress(); - } - public decreasePage(): void { - if (this.page === 4) { - this.config = this.configService.revertConfigForInput(this.config); + public decreasePage(): void { + if (this.page === 4) { + this.config = this.configService.revertConfigForInput(this.config); + } + this.page -= 1; + this.changeProgress(); } - this.page -= 1; - this.changeProgress(); - } - public changeProgress(): void { - document.getElementById('progressBar').style.width = this.page * (20 / this.totalPages) + 'vw'; - } + public changeProgress(): void { + document.getElementById('progressBar').style.width = this.page * (20 / this.totalPages) + 'vw'; + } } diff --git a/src/app/control/control.component.ts b/src/app/control/control.component.ts index 26cbe0f62..65b831dec 100644 --- a/src/app/control/control.component.ts +++ b/src/app/control/control.component.ts @@ -1,145 +1,161 @@ import { Component, SecurityContext } from '@angular/core'; -import { PrinterService } from '../printer.service'; +import { SafeResourceUrl } from '@angular/platform-browser'; +import { Router } from '@angular/router'; + import { ConfigService } from '../config/config.service'; import { OctoprintService } from '../octoprint.service'; -import { SafeResourceUrl } from '@angular/platform-browser'; import { PsuControlService } from '../plugin-service/psu-control.service'; -import { Router } from '@angular/router'; +import { PrinterService } from '../printer.service'; @Component({ - selector: 'app-control', - templateUrl: './control.component.html', - styleUrls: ['./control.component.scss'] + selector: 'app-control', + templateUrl: './control.component.html', + styleUrls: ['./control.component.scss'], }) export class ControlComponent { - public jogDistance = 10; - public customActions = []; - public showHelp = false; - public iFrameURL: SafeResourceUrl = 'about:blank'; - public actionToConfirm: ActionToConfirm; - - constructor( - private printerService: PrinterService, - private octoprintService: OctoprintService, - private configService: ConfigService, - private psuControlService: PsuControlService, - private router: Router) { - this.customActions = this.configService.getCustomActions(); - } - - public setDistance(distance: number): void { - this.jogDistance = distance; - } - - public moveAxis(axis: string, direction: '+' | '-'): void { - const distance = Number(direction + this.jogDistance); - this.printerService.jog( - axis === 'x' ? distance : 0, - axis === 'y' ? distance : 0, - axis === 'z' ? distance : 0, - ); - } - - public doAction(command: string, exit: boolean, confirm: boolean) { - console.log(command, exit, confirm); - if (confirm) { - this.actionToConfirm = { - command, - exit - }; - } else { - this.executeGCode(command); - if (exit) { - this.router.navigate(['/main-screen']); - } + public jogDistance = 10; + public customActions = []; + public showHelp = false; + public iFrameURL: SafeResourceUrl = 'about:blank'; + public actionToConfirm: ActionToConfirm; + + constructor( + private printerService: PrinterService, + private octoprintService: OctoprintService, + private configService: ConfigService, + private psuControlService: PsuControlService, + private router: Router, + ) { + this.customActions = this.configService.getCustomActions(); + } + + public setDistance(distance: number): void { + this.jogDistance = distance; } - } - public doActionConfirm() { - this.executeGCode(this.actionToConfirm.command); - if (this.actionToConfirm.exit) { - this.router.navigate(['/main-screen']); + public moveAxis(axis: string, direction: '+' | '-'): void { + const distance = Number(direction + this.jogDistance); + this.printerService.jog(axis === 'x' ? distance : 0, axis === 'y' ? distance : 0, axis === 'z' ? distance : 0); } - } - - public doActionNoConfirm() { - this.actionToConfirm = null; - } - - private executeGCode(command: string): void { - switch (command) { - case '[!DISCONNECT]': this.disconnectPrinter(); break; - case '[!STOPDASHBOARD]': this.stopOctoDash(); break; - case '[!RELOAD]': this.reloadOctoPrint(); break; - case '[!REBOOT]': this.rebootPi(); break; - case '[!SHUTDOWN]': this.shutdownPi(); break; - case '[!KILL]': this.kill(); break; - case '[!POWEROFF]': this.psuControlService.changePSUState(false); break; - case '[!POWERON]': this.psuControlService.changePSUState(true); break; - case '[!POWERTOGGLE]': this.psuControlService.togglePSU(); break; - default: { - if (command.includes('[!WEB]')) { - this.openIFrame(command.replace('[!WEB]', '')); + + public doAction(command: string, exit: boolean, confirm: boolean) { + console.log(command, exit, confirm); + if (confirm) { + this.actionToConfirm = { + command, + exit, + }; } else { - this.printerService.executeGCode(command); + this.executeGCode(command); + if (exit) { + this.router.navigate(['/main-screen']); + } + } + } + + public doActionConfirm() { + this.executeGCode(this.actionToConfirm.command); + if (this.actionToConfirm.exit) { + this.router.navigate(['/main-screen']); + } + } + + public doActionNoConfirm() { + this.actionToConfirm = null; + } + + private executeGCode(command: string): void { + switch (command) { + case '[!DISCONNECT]': + this.disconnectPrinter(); + break; + case '[!STOPDASHBOARD]': + this.stopOctoDash(); + break; + case '[!RELOAD]': + this.reloadOctoPrint(); + break; + case '[!REBOOT]': + this.rebootPi(); + break; + case '[!SHUTDOWN]': + this.shutdownPi(); + break; + case '[!KILL]': + this.kill(); + break; + case '[!POWEROFF]': + this.psuControlService.changePSUState(false); + break; + case '[!POWERON]': + this.psuControlService.changePSUState(true); + break; + case '[!POWERTOGGLE]': + this.psuControlService.togglePSU(); + break; + default: { + if (command.includes('[!WEB]')) { + this.openIFrame(command.replace('[!WEB]', '')); + } else { + this.printerService.executeGCode(command); + } + break; + } } - break; - } } - } - - // [!DISCONNECT] - public disconnectPrinter(): void { - this.octoprintService.disconnectPrinter(); - } - - // [!STOPDASHBOARD] - public stopOctoDash(): void { - window.close(); - } - - // [!RELOAD] - public reloadOctoPrint(): void { - this.octoprintService.sendSystemCommand('restart'); - } - - // [!REBOOT] - public rebootPi(): void { - this.octoprintService.sendSystemCommand('reboot'); - } - - // [!SHUTDOWN] - public shutdownPi(): void { - this.octoprintService.sendSystemCommand('shutdown'); - } - - // [!KILL] - public kill(): void { - this.shutdownPi(); - setTimeout(this.stopOctoDash, 500); - } - - // [!WEB] - public openIFrame(url: string): void { - this.iFrameURL = url; - const iFrameDOM = document.getElementById('iFrame'); - iFrameDOM.style.display = 'block'; - setTimeout(() => { - iFrameDOM.style.opacity = '1'; - }, 50); - } - - public hideIFrame(): void { - const iFrameDOM = document.getElementById('iFrame'); - iFrameDOM.style.opacity = '0'; - setTimeout(() => { - iFrameDOM.style.display = 'none'; - this.iFrameURL = 'about:blank'; - }, 500); - } + + // [!DISCONNECT] + public disconnectPrinter(): void { + this.octoprintService.disconnectPrinter(); + } + + // [!STOPDASHBOARD] + public stopOctoDash(): void { + window.close(); + } + + // [!RELOAD] + public reloadOctoPrint(): void { + this.octoprintService.sendSystemCommand('restart'); + } + + // [!REBOOT] + public rebootPi(): void { + this.octoprintService.sendSystemCommand('reboot'); + } + + // [!SHUTDOWN] + public shutdownPi(): void { + this.octoprintService.sendSystemCommand('shutdown'); + } + + // [!KILL] + public kill(): void { + this.shutdownPi(); + setTimeout(this.stopOctoDash, 500); + } + + // [!WEB] + public openIFrame(url: string): void { + this.iFrameURL = url; + const iFrameDOM = document.getElementById('iFrame'); + iFrameDOM.style.display = 'block'; + setTimeout(() => { + iFrameDOM.style.opacity = '1'; + }, 50); + } + + public hideIFrame(): void { + const iFrameDOM = document.getElementById('iFrame'); + iFrameDOM.style.opacity = '0'; + setTimeout(() => { + iFrameDOM.style.display = 'none'; + this.iFrameURL = 'about:blank'; + }, 500); + } } interface ActionToConfirm { - command: string; - exit: boolean; + command: string; + exit: boolean; } diff --git a/src/app/filament/filament.component.ts b/src/app/filament/filament.component.ts index 404afd38d..160459637 100644 --- a/src/app/filament/filament.component.ts +++ b/src/app/filament/filament.component.ts @@ -1,14 +1,12 @@ import { Component, OnInit } from '@angular/core'; @Component({ - selector: 'app-filament', - templateUrl: './filament.component.html', - styleUrls: ['./filament.component.scss'] + selector: 'app-filament', + templateUrl: './filament.component.html', + styleUrls: ['./filament.component.scss'], }) export class FilamentComponent implements OnInit { + constructor() {} - constructor() { } - - public ngOnInit(): void { - } + public ngOnInit(): void {} } diff --git a/src/app/files.service.ts b/src/app/files.service.ts index 3d0ad9cb2..49ecdb517 100644 --- a/src/app/files.service.ts +++ b/src/app/files.service.ts @@ -1,191 +1,210 @@ -import _ from 'lodash'; -import { Injectable } from '@angular/core'; -import { ConfigService } from './config/config.service'; import { HttpClient, HttpErrorResponse } from '@angular/common/http'; -import { NotificationService } from './notification/notification.service'; +import { Injectable } from '@angular/core'; +import _ from 'lodash'; import { Subscription } from 'rxjs'; -import { OctoprintFolderAPI, OctoprintFilesAPI, OctoprintFolderContentAPI } from './octoprint-api/filesAPI'; -import { AppService } from './app.service'; +import { AppService } from './app.service'; +import { ConfigService } from './config/config.service'; +import { NotificationService } from './notification/notification.service'; +import { OctoprintFilesAPI, OctoprintFolderAPI, OctoprintFolderContentAPI } from './octoprint-api/filesAPI'; @Injectable({ - providedIn: 'root' + providedIn: 'root', }) export class FilesService { + private httpGETRequest: Subscription; + private httpPOSTRequest: Subscription; + private httpDELETERequest: Subscription; - httpGETRequest: Subscription; - httpPOSTRequest: Subscription; - httpDELETERequest: Subscription; - - constructor( - private configService: ConfigService, - private http: HttpClient, - private notificationService: NotificationService, - private service: AppService) { } + public constructor( + private configService: ConfigService, + private http: HttpClient, + private notificationService: NotificationService, + private service: AppService, + ) {} - public getFolder(folderPath: string = '/'): Promise> { - return new Promise((resolve, reject): void => { - folderPath = folderPath === '/' ? '' : folderPath; - if (this.httpGETRequest) { - this.httpGETRequest.unsubscribe(); - } - this.httpGETRequest = this.http.get(this.configService.getURL('files/local' + folderPath), - this.configService.getHTTPHeaders()).subscribe( - (data: OctoprintFolderAPI & OctoprintFolderContentAPI) => { - if ('children' in data) { - data.files = data.children; - delete data.children; + public getFolder(folderPath: string = '/'): Promise<(File | Folder)[]> { + return new Promise((resolve, reject): void => { + folderPath = folderPath === '/' ? '' : folderPath; + if (this.httpGETRequest) { + this.httpGETRequest.unsubscribe(); } - const folder: Array = []; - data.files.forEach((fileOrFolder) => { - if (fileOrFolder.type === 'folder') { - folder.push({ - type: 'folder', - path: '/' + fileOrFolder.path, - name: fileOrFolder.name, - // TODO: Think of a way to retrieve number of children - files: fileOrFolder.children ? fileOrFolder.children.length : '-', - } as Folder); - } else if (fileOrFolder.typePath.includes('gcode') && fileOrFolder.origin === 'local') { - if (!fileOrFolder.gcodeAnalysis) { - this.notificationService.setError('Corrupted file found!', `File ${fileOrFolder.name} does not include GCodeAnalysis. Ignoring it for now ...`); - return; - } - let filamentLength = 0; - _.forEach(fileOrFolder.gcodeAnalysis.filament, (tool) => { - filamentLength += tool.length; - }); + this.httpGETRequest = this.http + .get(this.configService.getURL('files/local' + folderPath), this.configService.getHTTPHeaders()) + .subscribe( + (data: OctoprintFolderAPI & OctoprintFolderContentAPI): void => { + if ('children' in data) { + data.files = data.children; + delete data.children; + } + const folder: (File | Folder)[] = []; + data.files.forEach((fileOrFolder): void => { + if (fileOrFolder.type === 'folder') { + folder.push(({ + type: 'folder', + path: '/' + fileOrFolder.path, + name: fileOrFolder.name, + // TODO: Think of a way to retrieve number of children + files: fileOrFolder.children ? fileOrFolder.children.length : '-', + } as unknown) as Folder); + } else if (fileOrFolder.typePath.includes('gcode') && fileOrFolder.origin === 'local') { + if (!fileOrFolder.gcodeAnalysis) { + this.notificationService.setError( + 'Corrupted file found!', + `File ${fileOrFolder.name} does not include GCodeAnalysis. Ignoring it for now ...`, + ); + return; + } + let filamentLength = 0; + _.forEach(fileOrFolder.gcodeAnalysis.filament, (tool): void => { + filamentLength += tool.length; + }); - folder.push({ - type: 'file', - path: '/' + fileOrFolder.path, - name: fileOrFolder.name, - size: this.service.convertByteToMegabyte(fileOrFolder.size), - printTime: this.service.convertSecondsToHours(fileOrFolder.gcodeAnalysis.estimatedPrintTime), - filamentWeight: this.service.convertFilamentLengthToAmount(filamentLength), - } as File); - } - }); - data = null; - folder.sort((a, b) => a.type === b.type ? a.name > b.name ? 1 : -1 : a.type === 'folder' ? -1 : 1); + folder.push(({ + type: 'file', + path: '/' + fileOrFolder.path, + name: fileOrFolder.name, + size: this.service.convertByteToMegabyte(fileOrFolder.size), + printTime: this.service.convertSecondsToHours( + fileOrFolder.gcodeAnalysis.estimatedPrintTime, + ), + filamentWeight: this.service.convertFilamentLengthToAmount(filamentLength), + } as unknown) as File); + } + }); + data = null; + folder.sort((a, b): number => + a.type === b.type ? (a.name > b.name ? 1 : -1) : a.type === 'folder' ? -1 : 1, + ); - resolve(folder); - }, - (error: HttpErrorResponse) => { - if (error.status === 404) { - this.notificationService.setError('Can\'t find specified folder!', error.message); - if (folderPath !== '/') { - this.getFolder(folderPath.substring(0, folderPath.lastIndexOf('/'))); - } else { - reject(); - } - } else { - this.notificationService.setError('Can\'t retrieve folder!', error.message); - reject(); - } - } - ); - }); - } - - public getFile(filePath: string): Promise { + resolve(folder); + }, + (error: HttpErrorResponse): void => { + if (error.status === 404) { + this.notificationService.setError("Can't find specified folder!", error.message); + if (folderPath !== '/') { + this.getFolder(folderPath.substring(0, folderPath.lastIndexOf('/'))); + } else { + reject(); + } + } else { + this.notificationService.setError("Can't retrieve folder!", error.message); + reject(); + } + }, + ); + }); + } - return new Promise((resolve, reject): void => { - if (this.httpGETRequest) { - this.httpGETRequest.unsubscribe(); - } - this.httpGETRequest = this.http.get(this.configService.getURL('files/local' + filePath), - this.configService.getHTTPHeaders()).subscribe( - (data: OctoprintFilesAPI) => { - let filamentLength = 0; - _.forEach(data.gcodeAnalysis.filament, (tool) => { - filamentLength += tool.length; - }); - const file = { - type: 'file', - path: '/' + data.path, - name: data.name, - size: this.service.convertByteToMegabyte(data.size), - printTime: this.service.convertSecondsToHours(data.gcodeAnalysis.estimatedPrintTime), - filamentWeight: this.service.convertFilamentLengthToAmount(filamentLength), - date: this.service.convertDateToString(new Date(data.date * 1000)) - } as File; - resolve(file); - }, - (error: HttpErrorResponse) => { - if (error.status === 404) { - this.notificationService.setError('Can\'t find specified file!', error.message); - reject(); - } else { - this.notificationService.setError('Can\'t retrieve folder!', error.message); - reject(); + public getFile(filePath: string): Promise { + return new Promise((resolve, reject): void => { + if (this.httpGETRequest) { + this.httpGETRequest.unsubscribe(); } - } - ); - }); - } - - public loadFile(filePath: string) { - if (this.httpPOSTRequest) { - this.httpPOSTRequest.unsubscribe(); + this.httpGETRequest = this.http + .get(this.configService.getURL('files/local' + filePath), this.configService.getHTTPHeaders()) + .subscribe( + (data: OctoprintFilesAPI): void => { + let filamentLength = 0; + _.forEach(data.gcodeAnalysis.filament, (tool): void => { + filamentLength += tool.length; + }); + const file = ({ + type: 'file', + path: '/' + data.path, + name: data.name, + size: this.service.convertByteToMegabyte(data.size), + printTime: this.service.convertSecondsToHours(data.gcodeAnalysis.estimatedPrintTime), + filamentWeight: this.service.convertFilamentLengthToAmount(filamentLength), + date: this.service.convertDateToString(new Date(data.date * 1000)), + } as unknown) as File; + resolve(file); + }, + (error: HttpErrorResponse): void => { + if (error.status === 404) { + this.notificationService.setError("Can't find specified file!", error.message); + reject(); + } else { + this.notificationService.setError("Can't retrieve folder!", error.message); + reject(); + } + }, + ); + }); } - const loadFileBody = { - command: 'select', - print: false - }; - this.httpPOSTRequest = this.http.post(this.configService.getURL('files/local' + filePath), - loadFileBody, this.configService.getHTTPHeaders()).subscribe( - () => null, - (error: HttpErrorResponse) => { - this.notificationService.setError('Can\'t load the file!', error.message); - } - ); - } - public printFile(filePath: string) { - if (this.httpPOSTRequest) { - this.httpPOSTRequest.unsubscribe(); - } - const printFileBody = { - command: 'select', - print: true - }; - this.httpPOSTRequest = this.http.post(this.configService.getURL('files/local' + filePath), - printFileBody, this.configService.getHTTPHeaders()).subscribe( - () => null, - (error: HttpErrorResponse) => { - this.notificationService.setError('Can\'t start print!', error.message); + public loadFile(filePath: string): void { + if (this.httpPOSTRequest) { + this.httpPOSTRequest.unsubscribe(); } - ); - } + const loadFileBody = { + command: 'select', + print: false, + }; + this.httpPOSTRequest = this.http + .post( + this.configService.getURL('files/local' + filePath), + loadFileBody, + this.configService.getHTTPHeaders(), + ) + .subscribe( + (): void => null, + (error: HttpErrorResponse): void => { + this.notificationService.setError("Can't load the file!", error.message); + }, + ); + } - public deleteFile(filePath: string) { - if (this.httpDELETERequest) { - this.httpDELETERequest.unsubscribe(); + public printFile(filePath: string): void { + if (this.httpPOSTRequest) { + this.httpPOSTRequest.unsubscribe(); + } + const printFileBody = { + command: 'select', + print: true, + }; + this.httpPOSTRequest = this.http + .post( + this.configService.getURL('files/local' + filePath), + printFileBody, + this.configService.getHTTPHeaders(), + ) + .subscribe( + (): void => null, + (error: HttpErrorResponse): void => { + this.notificationService.setError("Can't start print!", error.message); + }, + ); } - this.httpDELETERequest = this.http.delete(this.configService.getURL('files/local' + filePath), - this.configService.getHTTPHeaders()).subscribe( - () => null, - (error: HttpErrorResponse) => { - this.notificationService.setError('Can\'t delete file!', error.message); + + public deleteFile(filePath: string): void { + if (this.httpDELETERequest) { + this.httpDELETERequest.unsubscribe(); } - ); - } + this.httpDELETERequest = this.http + .delete(this.configService.getURL('files/local' + filePath), this.configService.getHTTPHeaders()) + .subscribe( + (): void => null, + (error: HttpErrorResponse): void => { + this.notificationService.setError("Can't delete file!", error.message); + }, + ); + } } export interface Folder { - type: string; - path: string; - name: string; - files?: number; + type: string; + path: string; + name: string; + files?: number; } export interface File { - type: string; - path: string; - name: string; - size?: string; - printTime?: string; - filamentWeight?: number; - date?: string; + type: string; + path: string; + name: string; + size?: string; + printTime?: string; + filamentWeight?: number; + date?: string; } diff --git a/src/app/files/files.component.ts b/src/app/files/files.component.ts index a8deb8994..a5c4e1668 100644 --- a/src/app/files/files.component.ts +++ b/src/app/files/files.component.ts @@ -1,104 +1,109 @@ import { Component } from '@angular/core'; +import { Router } from '@angular/router'; import { NgxSpinnerService } from 'ngx-spinner'; -import { FilesService, Folder } from '../files.service'; + import { AppService } from '../app.service'; -import { Router } from '@angular/router'; +import { File, FilesService, Folder } from '../files.service'; import { JobService } from '../job.service'; @Component({ - selector: 'app-files', - templateUrl: './files.component.html', - styleUrls: ['./files.component.scss'] + selector: 'app-files', + templateUrl: './files.component.html', + styleUrls: ['./files.component.scss'], }) - export class FilesComponent { + public currentFolder: string; + public folderContent: (File | Folder)[]; + public fileDetail: File; - currentFolder: string; - folderContent: Array; - fileDetail: File; + public constructor( + private filesService: FilesService, + private spinner: NgxSpinnerService, + private service: AppService, + private router: Router, + private jobService: JobService, + ) { + this.showLoader(); + this.folderContent = []; + this.currentFolder = '/'; + this.openFolder(this.currentFolder); + } - constructor( - private filesService: FilesService, - private spinner: NgxSpinnerService, - private service: AppService, - private router: Router, - private jobService: JobService) { - this.showLoader(); - this.folderContent = []; - this.currentFolder = '/'; - this.openFolder(this.currentFolder); - } + public openDetails(filePath: string): void { + this.filesService + .getFile(filePath) + .then((data): void => { + this.fileDetail = data; + }) + .catch((err): void => { + this.fileDetail = ({ name: 'error' } as unknown) as File; + }); + const fileDOMElement = document.getElementById('fileDetailView'); + fileDOMElement.style.display = 'block'; + setTimeout(() => { + fileDOMElement.style.opacity = '1'; + }, 50); + } - public openDetails(filePath: string): void { - this.filesService.getFile(filePath).then((data) => { - this.fileDetail = data; - }).catch((err) => { - this.fileDetail = { name: 'error' } as File; - }); - const fileDOMElement = document.getElementById('fileDetailView'); - fileDOMElement.style.display = 'block'; - setTimeout(() => { - fileDOMElement.style.opacity = '1'; - }, 50); - } + public openFolder(folderPath: string): void { + setTimeout(() => { + this.showLoader(); + this.folderContent = []; + this.filesService + .getFolder(folderPath) + .then(data => { + this.folderContent = data; + this.currentFolder = folderPath; + this.spinner.hide(); + }) + .catch(err => { + this.folderContent = null; + this.currentFolder = folderPath; + this.spinner.hide(); + }); + }, 300); + } - public openFolder(folderPath: string): void { - setTimeout(() => { - this.showLoader(); - this.folderContent = []; - this.filesService.getFolder(folderPath).then( - (data) => { - this.folderContent = data; - this.currentFolder = folderPath; - this.spinner.hide(); - }).catch((err) => { - this.folderContent = null; - this.currentFolder = folderPath; - this.spinner.hide(); - }); - }, 300); - } - - public closeDetails(): void { - const fileDOMElement = document.getElementById('fileDetailView'); - fileDOMElement.style.opacity = '0'; - setTimeout(() => { - fileDOMElement.style.display = 'none'; - this.fileDetail = null; - }, 500); - } + public closeDetails(): void { + const fileDOMElement = document.getElementById('fileDetailView'); + fileDOMElement.style.opacity = '0'; + setTimeout(() => { + fileDOMElement.style.display = 'none'; + this.fileDetail = null; + }, 500); + } - public loadFile(filePath: string): void { - setTimeout(() => { - this.filesService.loadFile(filePath); - this.service.setLoadedFile(true); - this.jobService.deleteJobInformation(); - this.router.navigate(['/main-screen']); - }, 300); - } + public loadFile(filePath: string): void { + setTimeout(() => { + this.filesService.loadFile(filePath); + this.service.setLoadedFile(true); + this.jobService.deleteJobInformation(); + this.router.navigate(['/main-screen']); + }, 300); + } - public printFile(filePath: string): void { - setTimeout(() => { - this.filesService.printFile(filePath); - this.router.navigate(['/main-screen']); - }, 300); - } + public printFile(filePath: string): void { + setTimeout(() => { + this.filesService.printFile(filePath); + this.router.navigate(['/main-screen']); + }, 300); + } - public deleteFile(filePath: string): void { - setTimeout(() => { - this.filesService.deleteFile(filePath); - this.closeDetails(); - this.openFolder(this.currentFolder); - }, 300); - } + public deleteFile(filePath: string): void { + setTimeout(() => { + this.filesService.deleteFile(filePath); + this.closeDetails(); + this.openFolder(this.currentFolder); + }, 300); + } - private showLoader(): void { - this.spinner.show(undefined, { - bdColor: '#353b48', - color: '#f5f6fa', - size: 'medium', - type: 'pacman', - fullScreen: false - }); - } + private showLoader(): void { + this.spinner.show(undefined, { + bdColor: '#353b48', + color: '#f5f6fa', + size: 'medium', + type: 'pacman', + fullScreen: false, + }); + } } diff --git a/src/app/job-status/job-status.component.ts b/src/app/job-status/job-status.component.ts index 955316dc2..6d2b9cf3b 100644 --- a/src/app/job-status/job-status.component.ts +++ b/src/app/job-status/job-status.component.ts @@ -1,49 +1,49 @@ -import { Component, OnInit, OnDestroy } from '@angular/core'; -import { JobService, Job } from '../job.service'; +import { Component, OnDestroy, OnInit } from '@angular/core'; import { Subscription } from 'rxjs'; + import { AppService } from '../app.service'; +import { Job, JobService } from '../job.service'; import { NotificationService } from '../notification/notification.service'; @Component({ - selector: 'app-job-status', - templateUrl: './job-status.component.html', - styleUrls: ['./job-status.component.scss'] + selector: 'app-job-status', + templateUrl: './job-status.component.html', + styleUrls: ['./job-status.component.scss'], }) export class JobStatusComponent implements OnInit, OnDestroy { + private subscriptions: Subscription = new Subscription(); + public job: Job; - private subscriptions: Subscription = new Subscription(); - public job: Job; - - constructor(private jobService: JobService, private service: AppService) { } + constructor(private jobService: JobService, private service: AppService) {} - ngOnInit() { - this.subscriptions.add(this.jobService.getObservable().subscribe((job: Job) => this.job = job)); - } + ngOnInit() { + this.subscriptions.add(this.jobService.getObservable().subscribe((job: Job) => (this.job = job))); + } - ngOnDestroy() { - this.subscriptions.unsubscribe(); - } + ngOnDestroy() { + this.subscriptions.unsubscribe(); + } - public isFileLoaded(): boolean { - return this.service.getLoadedFile(); - } + public isFileLoaded(): boolean { + return this.service.getLoadedFile(); + } - public preheat(): void { - this.jobService.preheat(); - } + public preheat(): void { + this.jobService.preheat(); + } - public cancelLoadedFile(): void { - this.service.setLoadedFile(false); - } + public cancelLoadedFile(): void { + this.service.setLoadedFile(false); + } - public startJob(): void { - this.jobService.startJob(); - setTimeout(() => { - this.service.setLoadedFile(false); - }, 5000); - } + public startJob(): void { + this.jobService.startJob(); + setTimeout(() => { + this.service.setLoadedFile(false); + }, 5000); + } - public isPrinting(): boolean { - return this.jobService.isPrinting(); - } + public isPrinting(): boolean { + return this.jobService.isPrinting(); + } } diff --git a/src/app/job.service.ts b/src/app/job.service.ts index 81b70c297..46f19b59a 100644 --- a/src/app/job.service.ts +++ b/src/app/job.service.ts @@ -1,203 +1,233 @@ -import { Injectable, OnDestroy } from '@angular/core'; -import { Observable, Observer, timer, Subscription } from 'rxjs'; -import { ConfigService } from './config/config.service'; import { HttpClient, HttpErrorResponse } from '@angular/common/http'; -import { shareReplay, publish } from 'rxjs/operators'; -import { OctoprintJobAPI, JobCommand, OctoprintFilament } from './octoprint-api/jobAPI'; -import { NotificationService } from './notification/notification.service'; +import { Injectable } from '@angular/core'; +import { Observable, Observer, Subscription, timer } from 'rxjs'; +import { shareReplay } from 'rxjs/operators'; + import { AppService } from './app.service'; +import { ConfigService } from './config/config.service'; +import { NotificationService } from './notification/notification.service'; +import { JobCommand, OctoprintFilament, OctoprintJobAPI } from './octoprint-api/jobAPI'; @Injectable({ - providedIn: 'root' + providedIn: 'root', }) export class JobService { - httpGETRequest: Subscription; - httpPOSTRequest: Subscription; - observable: Observable; - private observer: Observer; - private printing = false; + private httpGETRequest: Subscription; + private httpPOSTRequest: Subscription; + private observable: Observable; + private observer: Observer; + private printing = false; - constructor( - private configService: ConfigService, - private http: HttpClient, - private notificationService: NotificationService, - private service: AppService) { - this.observable = new Observable((observer: Observer) => { - this.observer = observer; - timer(750, this.configService.getAPIPollingInterval()).subscribe(_ => { - if (this.httpGETRequest) { - this.httpGETRequest.unsubscribe(); - } - this.httpGETRequest = this.http.get(this.configService.getURL('job'), this.configService.getHTTPHeaders()).subscribe( - (data: OctoprintJobAPI) => { - let job: Job = null; - if (data.job && data.job.file.name) { - this.printing = ['Printing', 'Pausing', 'Paused', 'Cancelling'].includes(data.state); - try { - job = { - status: data.state, - filename: data.job.file.display.replace('.gcode', ''), - progress: Math.round((data.progress.filepos / data.job.file.size) * 100), - filamentAmount: this.service.convertFilamentLengthToAmount(this.getTotalAmountOfFilament(data.job.filament)), - timeLeft: { - value: this.service.convertSecondsToHours(data.progress.printTimeLeft), - unit: 'h' - }, - timePrinted: { - value: this.service.convertSecondsToHours(data.progress.printTime), - unit: 'h' - }, - estimatedPrintTime: { - value: this.service.convertSecondsToHours(data.job.estimatedPrintTime), - unit: 'h' - }, - estimatedEndTime: this.calculateEndTime(data.job.estimatedPrintTime), - }; - } catch (error) { - this.notificationService.setError('Can\'t retrieve Job Status', error); - } - } - observer.next(job); - }, (error: HttpErrorResponse) => { - this.printing = false; - this.notificationService.setError('Can\'t retrieve jobs!', error.message); - }); - - }); - }).pipe(shareReplay(1)); - this.observable.subscribe(); - } - - private getTotalAmountOfFilament(filamentAmount: OctoprintFilament): number { - let filamentLength = 0; - for (const property in filamentAmount) { - if (filamentAmount.hasOwnProperty(property) && filamentAmount[property].hasOwnProperty('length')) { - filamentLength += filamentAmount[property].length; - } + public constructor( + private configService: ConfigService, + private http: HttpClient, + private notificationService: NotificationService, + private service: AppService, + ) { + this.observable = new Observable((observer: Observer): void => { + this.observer = observer; + timer(750, this.configService.getAPIPollingInterval()).subscribe((): void => { + if (this.httpGETRequest) { + this.httpGETRequest.unsubscribe(); + } + this.httpGETRequest = this.http + .get(this.configService.getURL('job'), this.configService.getHTTPHeaders()) + .subscribe( + (data: OctoprintJobAPI): void => { + let job: Job = null; + if (data.job && data.job.file.name) { + this.printing = ['Printing', 'Pausing', 'Paused', 'Cancelling'].includes(data.state); + try { + job = { + status: data.state, + filename: data.job.file.display.replace('.gcode', ''), + progress: Math.round((data.progress.filepos / data.job.file.size) * 100), + filamentAmount: this.service.convertFilamentLengthToAmount( + this.getTotalAmountOfFilament(data.job.filament), + ), + timeLeft: { + value: this.service.convertSecondsToHours(data.progress.printTimeLeft), + unit: 'h', + }, + timePrinted: { + value: this.service.convertSecondsToHours(data.progress.printTime), + unit: 'h', + }, + estimatedPrintTime: { + value: this.service.convertSecondsToHours(data.job.estimatedPrintTime), + unit: 'h', + }, + estimatedEndTime: this.calculateEndTime(data.job.estimatedPrintTime), + }; + } catch (error) { + this.notificationService.setError("Can't retrieve Job Status", error); + } + } + observer.next(job); + }, + (error: HttpErrorResponse): void => { + this.printing = false; + this.notificationService.setError("Can't retrieve jobs!", error.message); + }, + ); + }); + }).pipe(shareReplay(1)); + this.observable.subscribe(); } - return filamentLength; - } - - public deleteJobInformation(): void { - this.observer.next(null); - } - public getObservable(): Observable { - return this.observable; - } - - public isPrinting(): boolean { - return this.printing; - } + private getTotalAmountOfFilament(filamentAmount: OctoprintFilament): number { + let filamentLength = 0; + for (const property in filamentAmount) { + if (filamentAmount.hasOwnProperty(property) && filamentAmount[property].hasOwnProperty('length')) { + filamentLength += filamentAmount[property].length; + } + } + return filamentLength; + } - public cancelJob(): void { - if (this.httpPOSTRequest) { - this.httpPOSTRequest.unsubscribe(); + public deleteJobInformation(): void { + this.observer.next(null); } - const cancelPayload: JobCommand = { - command: 'cancel' - }; - this.httpPOSTRequest = this.http.post(this.configService.getURL('job'), cancelPayload, this.configService.getHTTPHeaders()).subscribe( - () => null, (error: HttpErrorResponse) => { - if (error.status === 409) { - this.notificationService.setError('Can\'t cancel Job!', 'There is no running job, that could be cancelled (409)'); - } else { - this.notificationService.setError('Can\'t cancel Job!', error.message); - } - } - ); - } - public pauseJob(): void { - if (this.httpPOSTRequest) { - this.httpPOSTRequest.unsubscribe(); + public getObservable(): Observable { + return this.observable; } - const pausePayload: JobCommand = { - command: 'pause', - action: 'pause' - }; - this.httpPOSTRequest = this.http.post(this.configService.getURL('job'), pausePayload, this.configService.getHTTPHeaders()).subscribe( - () => null, (error: HttpErrorResponse) => { - if (error.status === 409) { - this.notificationService.setError('Can\'t pause Job!', 'There is no running job, that could be paused (409)'); - } else { - this.notificationService.setError('Can\'t pause Job!', error.message); - } - } - ); - } - public resumeJob(): void { - if (this.httpPOSTRequest) { - this.httpPOSTRequest.unsubscribe(); + public isPrinting(): boolean { + return this.printing; } - const pausePayload: JobCommand = { - command: 'pause', - action: 'resume' - }; - this.httpPOSTRequest = this.http.post(this.configService.getURL('job'), pausePayload, this.configService.getHTTPHeaders()).subscribe( - () => null, (error: HttpErrorResponse) => { - if (error.status === 409) { - this.notificationService.setError('Can\'t resume Job!', 'There is no paused job, that could be resumed (409)'); - } else { - this.notificationService.setError('Can\'t resume Job!', error.message); + + public cancelJob(): void { + if (this.httpPOSTRequest) { + this.httpPOSTRequest.unsubscribe(); } - } - ); - } + const cancelPayload: JobCommand = { + command: 'cancel', + }; + this.httpPOSTRequest = this.http + .post(this.configService.getURL('job'), cancelPayload, this.configService.getHTTPHeaders()) + .subscribe( + (): void => null, + (error: HttpErrorResponse): void => { + if (error.status === 409) { + this.notificationService.setError( + "Can't cancel Job!", + 'There is no running job, that could be cancelled (409)', + ); + } else { + this.notificationService.setError("Can't cancel Job!", error.message); + } + }, + ); + } - public startJob(): void { - if (this.httpPOSTRequest) { - this.httpPOSTRequest.unsubscribe(); + public pauseJob(): void { + if (this.httpPOSTRequest) { + this.httpPOSTRequest.unsubscribe(); + } + const pausePayload: JobCommand = { + command: 'pause', + action: 'pause', + }; + this.httpPOSTRequest = this.http + .post(this.configService.getURL('job'), pausePayload, this.configService.getHTTPHeaders()) + .subscribe( + (): void => null, + (error: HttpErrorResponse): void => { + if (error.status === 409) { + this.notificationService.setError( + "Can't pause Job!", + 'There is no running job, that could be paused (409)', + ); + } else { + this.notificationService.setError("Can't pause Job!", error.message); + } + }, + ); } - const pausePayload: JobCommand = { - command: 'start' - }; - this.httpPOSTRequest = this.http.post(this.configService.getURL('job'), pausePayload, this.configService.getHTTPHeaders()).subscribe( - () => null, (error: HttpErrorResponse) => { - if (error.status === 409) { - this.notificationService.setError('Can\'t start Job!', 'There is already a job running (409)'); - } else { - this.notificationService.setError('Can\'t start Job!', error.message); + + public resumeJob(): void { + if (this.httpPOSTRequest) { + this.httpPOSTRequest.unsubscribe(); } - } - ); - } + const pausePayload: JobCommand = { + command: 'pause', + action: 'resume', + }; + this.httpPOSTRequest = this.http + .post(this.configService.getURL('job'), pausePayload, this.configService.getHTTPHeaders()) + .subscribe( + (): void => null, + (error: HttpErrorResponse): void => { + if (error.status === 409) { + this.notificationService.setError( + "Can't resume Job!", + 'There is no paused job, that could be resumed (409)', + ); + } else { + this.notificationService.setError("Can't resume Job!", error.message); + } + }, + ); + } - public preheat(): void { - if (this.httpPOSTRequest) { - this.httpPOSTRequest.unsubscribe(); + public startJob(): void { + if (this.httpPOSTRequest) { + this.httpPOSTRequest.unsubscribe(); + } + const pausePayload: JobCommand = { + command: 'start', + }; + this.httpPOSTRequest = this.http + .post(this.configService.getURL('job'), pausePayload, this.configService.getHTTPHeaders()) + .subscribe( + (): void => null, + (error: HttpErrorResponse): void => { + if (error.status === 409) { + this.notificationService.setError("Can't start Job!", 'There is already a job running (409)'); + } else { + this.notificationService.setError("Can't start Job!", error.message); + } + }, + ); } - const preheatPayload: JobCommand = { - command: 'preheat' - }; - this.httpPOSTRequest = this.http.post(this.configService.getURL('plugin/preheat'), preheatPayload, this.configService.getHTTPHeaders()) - .subscribe( - () => null, (error: HttpErrorResponse) => { - this.notificationService.setError('Can\'t preheat printer!', error.message); + + public preheat(): void { + if (this.httpPOSTRequest) { + this.httpPOSTRequest.unsubscribe(); } - ); - } + const preheatPayload: JobCommand = { + command: 'preheat', + }; + this.httpPOSTRequest = this.http + .post(this.configService.getURL('plugin/preheat'), preheatPayload, this.configService.getHTTPHeaders()) + .subscribe( + (): void => null, + (error: HttpErrorResponse): void => { + this.notificationService.setError("Can't preheat printer!", error.message); + }, + ); + } - private calculateEndTime(duration: number): string { - const date = new Date(); - date.setSeconds(date.getSeconds() + duration); - return `${('0' + date.getHours()).slice(-2)}:${('0' + date.getMinutes()).slice(-2)}`; - } + private calculateEndTime(duration: number): string { + const date = new Date(); + date.setSeconds(date.getSeconds() + duration); + return `${('0' + date.getHours()).slice(-2)}:${('0' + date.getMinutes()).slice(-2)}`; + } } interface Duration { - value: string; - unit: string; + value: string; + unit: string; } export interface Job { - status: string; - filename: string; - progress: number; - filamentAmount: number; - timeLeft: Duration; - timePrinted: Duration; - estimatedPrintTime: Duration; - estimatedEndTime: string; + status: string; + filename: string; + progress: number; + filamentAmount: number; + timeLeft: Duration; + timePrinted: Duration; + estimatedPrintTime: Duration; + estimatedEndTime: string; } diff --git a/src/app/layer-progress/layer-progress.component.ts b/src/app/layer-progress/layer-progress.component.ts index 0108c4970..143771a82 100644 --- a/src/app/layer-progress/layer-progress.component.ts +++ b/src/app/layer-progress/layer-progress.component.ts @@ -1,38 +1,39 @@ -import { Component, OnInit, OnDestroy } from '@angular/core'; -import { LayerProgressService, DisplayLayerProgressAPI } from '../plugin-service/layer-progress.service'; +import { Component, OnDestroy, OnInit } from '@angular/core'; import { Subscription } from 'rxjs'; +import { DisplayLayerProgressAPI, LayerProgressService } from '../plugin-service/layer-progress.service'; + @Component({ - selector: 'app-layer-progress', - templateUrl: './layer-progress.component.html', - styleUrls: ['./layer-progress.component.scss'] + selector: 'app-layer-progress', + templateUrl: './layer-progress.component.html', + styleUrls: ['./layer-progress.component.scss'], }) export class LayerProgressComponent implements OnInit, OnDestroy { + private subscriptions: Subscription = new Subscription(); + public layerProgress: LayerProgress; - private subscriptions: Subscription = new Subscription(); - public layerProgress: LayerProgress; - - constructor(private displayLayerProgressService: LayerProgressService) { - this.layerProgress = { - current: 0, - total: 0 - }; - } - - ngOnInit() { - this.subscriptions.add(this.displayLayerProgressService.getObservable().subscribe((layerProgress: DisplayLayerProgressAPI) => { - this.layerProgress.current = layerProgress.current; - this.layerProgress.total = layerProgress.total; - })); - } + constructor(private displayLayerProgressService: LayerProgressService) { + this.layerProgress = { + current: 0, + total: 0, + }; + } - ngOnDestroy() { - this.subscriptions.unsubscribe(); - } + ngOnInit() { + this.subscriptions.add( + this.displayLayerProgressService.getObservable().subscribe((layerProgress: DisplayLayerProgressAPI) => { + this.layerProgress.current = layerProgress.current; + this.layerProgress.total = layerProgress.total; + }), + ); + } + ngOnDestroy() { + this.subscriptions.unsubscribe(); + } } export interface LayerProgress { - current: number; - total: number; + current: number; + total: number; } diff --git a/src/app/main-menu/main-menu.component.ts b/src/app/main-menu/main-menu.component.ts index b3dd0e55a..48d28f2b9 100644 --- a/src/app/main-menu/main-menu.component.ts +++ b/src/app/main-menu/main-menu.component.ts @@ -1,27 +1,24 @@ import { Component, OnInit } from '@angular/core'; @Component({ - selector: 'app-main-menu', - templateUrl: './main-menu.component.html', - styleUrls: ['./main-menu.component.scss'] + selector: 'app-main-menu', + templateUrl: './main-menu.component.html', + styleUrls: ['./main-menu.component.scss'], }) export class MainMenuComponent implements OnInit { + public settings = false; - public settings = false; + public showSettings() { + this.settings = true; + } - public showSettings() { - this.settings = true; - } + public hideSettings() { + setTimeout(() => { + this.settings = false; + }, 600); + } - public hideSettings() { - setTimeout(() => { - this.settings = false; - }, 600); - } - - constructor() { } - - ngOnInit() { - } + constructor() {} + ngOnInit() {} } diff --git a/src/app/main-screen/main-screen.component.ts b/src/app/main-screen/main-screen.component.ts index 60f7e1cc0..7edca3c70 100644 --- a/src/app/main-screen/main-screen.component.ts +++ b/src/app/main-screen/main-screen.component.ts @@ -1,28 +1,25 @@ -import { Component, OnInit, OnDestroy } from '@angular/core'; +import { Component, OnDestroy, OnInit } from '@angular/core'; import { Subscription } from 'rxjs'; -import { JobService, Job } from '../job.service'; -import { AppService } from '../app.service'; import { connectableObservableDescriptor } from 'rxjs/internal/observable/ConnectableObservable'; +import { AppService } from '../app.service'; +import { Job, JobService } from '../job.service'; + @Component({ - selector: 'app-main-screen', - templateUrl: './main-screen.component.html', - styleUrls: ['./main-screen.component.scss'] + selector: 'app-main-screen', + templateUrl: './main-screen.component.html', + styleUrls: ['./main-screen.component.scss'], }) - export class MainScreenComponent { + public printing = false; - public printing = false; - - - constructor(private jobService: JobService, private service: AppService) { - } + constructor(private jobService: JobService, private service: AppService) {} - public isPrinting() { - return this.jobService.isPrinting(); - } + public isPrinting() { + return this.jobService.isPrinting(); + } - public isFileLoaded(): boolean { - return this.service.getLoadedFile(); - } + public isFileLoaded(): boolean { + return this.service.getLoadedFile(); + } } diff --git a/src/app/main-screen/no-touch/main-screen-no-touch.component.ts b/src/app/main-screen/no-touch/main-screen-no-touch.component.ts index 86a394c7f..f64f16516 100644 --- a/src/app/main-screen/no-touch/main-screen-no-touch.component.ts +++ b/src/app/main-screen/no-touch/main-screen-no-touch.component.ts @@ -1,15 +1,12 @@ import { Component, OnInit } from '@angular/core'; @Component({ - selector: 'app-main-screen-no-touch', - templateUrl: './main-screen-no-touch.component.html', - styleUrls: ['./main-screen-no-touch.component.scss'] + selector: 'app-main-screen-no-touch', + templateUrl: './main-screen-no-touch.component.html', + styleUrls: ['./main-screen-no-touch.component.scss'], }) export class MainScreenNoTouchComponent implements OnInit { + constructor() {} - constructor() { } - - ngOnInit() { - } - + ngOnInit() {} } diff --git a/src/app/notification/notification.component.ts b/src/app/notification/notification.component.ts index 53eda1f12..b3ad246b1 100644 --- a/src/app/notification/notification.component.ts +++ b/src/app/notification/notification.component.ts @@ -1,37 +1,41 @@ import { Component, OnDestroy } from '@angular/core'; import { Subscription } from 'rxjs'; -import { NotificationService, Notification } from './notification.service'; + +import { Notification, NotificationService } from './notification.service'; @Component({ - selector: 'app-notification', - templateUrl: './notification.component.html', - styleUrls: ['./notification.component.scss'] + selector: 'app-notification', + templateUrl: './notification.component.html', + styleUrls: ['./notification.component.scss'], }) export class NotificationComponent implements OnDestroy { + private subscriptions: Subscription = new Subscription(); - private subscriptions: Subscription = new Subscription(); - - public notification: Notification = { - heading: '', - text: '', - type: '' - }; - public show = false; + public notification: Notification = { + heading: '', + text: '', + type: '', + }; + public show = false; - public constructor(private notificationService: NotificationService) { - this.subscriptions.add(this.notificationService.getObservable().subscribe((message: Notification) => this.setNotification(message))); - } + public constructor(private notificationService: NotificationService) { + this.subscriptions.add( + this.notificationService + .getObservable() + .subscribe((message: Notification) => this.setNotification(message)), + ); + } - public hideNotification() { - this.show = false; - } + public hideNotification() { + this.show = false; + } - public setNotification(notification: Notification) { - this.notification = notification; - this.show = true; - } + public setNotification(notification: Notification) { + this.notification = notification; + this.show = true; + } - public ngOnDestroy() { - this.subscriptions.unsubscribe(); - } + public ngOnDestroy() { + this.subscriptions.unsubscribe(); + } } diff --git a/src/app/notification/notification.service.ts b/src/app/notification/notification.service.ts index 484e1116f..b6299cacf 100644 --- a/src/app/notification/notification.service.ts +++ b/src/app/notification/notification.service.ts @@ -3,53 +3,52 @@ import { Observable, Observer } from 'rxjs'; import { shareReplay } from 'rxjs/operators'; @Injectable({ - providedIn: 'root' + providedIn: 'root', }) export class NotificationService { + private observable: Observable; + private observer: Observer; + private hideNotifications = false; + + constructor() { + this.observable = new Observable((observer: Observer) => { + this.observer = observer; + }).pipe(shareReplay(1)); + } + + enableNotifications() { + // console.clear(); + this.hideNotifications = false; + } - private observable: Observable; - private observer: Observer; - private hideNotifications = false; - - constructor() { - this.observable = new Observable((observer: Observer) => { - this.observer = observer; - }).pipe(shareReplay(1)); - } - - enableNotifications() { - // console.clear(); - this.hideNotifications = false; - } - - disableNotifications() { - // console.clear(); - this.hideNotifications = true; - } - - setError(heading: string, text: string) { - if (!this.hideNotifications) { - this.observer.next({ heading, text, type: 'error' }); + disableNotifications() { + // console.clear(); + this.hideNotifications = true; } - } - setWarning(heading: string, text: string) { - if (!this.hideNotifications) { - this.observer.next({ heading, text, type: 'warn' }); + setError(heading: string, text: string) { + if (!this.hideNotifications) { + this.observer.next({ heading, text, type: 'error' }); + } } - } - setUpdate(heading: string, text: string) { - this.observer.next({ heading, text, type: 'update' }); - } + setWarning(heading: string, text: string) { + if (!this.hideNotifications) { + this.observer.next({ heading, text, type: 'warn' }); + } + } - getObservable() { - return this.observable; - } + setUpdate(heading: string, text: string) { + this.observer.next({ heading, text, type: 'update' }); + } + + getObservable() { + return this.observable; + } } export interface Notification { - heading: string; - text: string; - type: string; + heading: string; + text: string; + type: string; } diff --git a/src/app/octoprint-api/connectionAPI.ts b/src/app/octoprint-api/connectionAPI.ts index 2379070bc..29ff90d83 100644 --- a/src/app/octoprint-api/connectionAPI.ts +++ b/src/app/octoprint-api/connectionAPI.ts @@ -11,9 +11,9 @@ interface OctoprintConnectionCurrentAPI { } interface OctoprintConnectionOptionsAPI { - ports: Array; - baudrates: Array; - printerProfiles: Array; + ports: string[]; + baudrates: number[]; + printerProfiles: object[]; portPreference: string; baudratePreference: string; printerProfilePreference: string; diff --git a/src/app/octoprint.service.ts b/src/app/octoprint.service.ts index 3c3e3bc36..e820f4f7d 100644 --- a/src/app/octoprint.service.ts +++ b/src/app/octoprint.service.ts @@ -1,47 +1,58 @@ +import { HttpClient, HttpErrorResponse } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Subscription } from 'rxjs'; -import { HttpClient, HttpErrorResponse } from '@angular/common/http'; + import { ConfigService } from './config/config.service'; import { NotificationService } from './notification/notification.service'; @Injectable({ - providedIn: 'root' + providedIn: 'root', }) export class OctoprintService { - httpPOSTRequest: Subscription; - - constructor(private http: HttpClient, private configService: ConfigService, private notificationService: NotificationService) { } + private httpPOSTRequest: Subscription; + public constructor( + private http: HttpClient, + private configService: ConfigService, + private notificationService: NotificationService, + ) {} - public disconnectPrinter() { - if (this.httpPOSTRequest) { - this.httpPOSTRequest.unsubscribe(); - } - const disconnectPayload: DisconnectCommand = { - command: 'disconnect' - }; - this.httpPOSTRequest = this.http.post(this.configService.getURL('connection'), disconnectPayload, this.configService.getHTTPHeaders()) - .subscribe( - () => null, (error: HttpErrorResponse) => { - this.notificationService.setError('Can\'t disconnect from Printer!', error.message); + public disconnectPrinter(): void { + if (this.httpPOSTRequest) { + this.httpPOSTRequest.unsubscribe(); } - ); - } - - public sendSystemCommand(command: string) { - if (this.httpPOSTRequest) { - this.httpPOSTRequest.unsubscribe(); + const disconnectPayload: DisconnectCommand = { + command: 'disconnect', + }; + this.httpPOSTRequest = this.http + .post(this.configService.getURL('connection'), disconnectPayload, this.configService.getHTTPHeaders()) + .subscribe( + (): void => null, + (error: HttpErrorResponse): void => { + this.notificationService.setError("Can't disconnect from Printer!", error.message); + }, + ); } - this.httpPOSTRequest = this.http.post(this.configService.getURL(`system/commands/core/${command}`), - null, this.configService.getHTTPHeaders()) - .subscribe( - () => null, (error: HttpErrorResponse) => { - this.notificationService.setError(`Can't execute ${command} command!`, error.message); + + public sendSystemCommand(command: string): void { + if (this.httpPOSTRequest) { + this.httpPOSTRequest.unsubscribe(); } - ); - } + this.httpPOSTRequest = this.http + .post( + this.configService.getURL(`system/commands/core/${command}`), + null, + this.configService.getHTTPHeaders(), + ) + .subscribe( + (): void => null, + (error: HttpErrorResponse): void => { + this.notificationService.setError(`Can't execute ${command} command!`, error.message); + }, + ); + } } interface DisconnectCommand { - command: string; + command: string; } diff --git a/src/app/plugin-service/enclosure.service.ts b/src/app/plugin-service/enclosure.service.ts index 4d006190e..4a5b5fa98 100644 --- a/src/app/plugin-service/enclosure.service.ts +++ b/src/app/plugin-service/enclosure.service.ts @@ -1,63 +1,75 @@ -import { Injectable } from '@angular/core'; import { HttpClient, HttpErrorResponse } from '@angular/common/http'; -import { ConfigService } from '../config/config.service'; -import { NotificationService } from '../notification/notification.service'; -import { Observable, Observer, timer, Subscription } from 'rxjs'; +import { Injectable } from '@angular/core'; +import { Observable, Observer, Subscription, timer } from 'rxjs'; import { shareReplay } from 'rxjs/operators'; + import { TemperatureReading } from '../bottom-bar/bottom-bar.component'; +import { ConfigService } from '../config/config.service'; +import { NotificationService } from '../notification/notification.service'; @Injectable({ - providedIn: 'root' + providedIn: 'root', }) export class EnclosureService { + httpGETRequest: Subscription; + observable: Observable; - httpGETRequest: Subscription; - observable: Observable; - - constructor(private http: HttpClient, private configService: ConfigService, private notificationService: NotificationService) { - this.observable = new Observable((observer: Observer) => { - timer(850, 30000).subscribe(_ => { - if (this.httpGETRequest) { - this.httpGETRequest.unsubscribe(); - } - this.httpGETRequest = this.http.get(this.configService.getURL('plugin/enclosure/inputs/' + - this.configService.getAmbientTemperatureSensorName()).replace('/api', ''), this.configService.getHTTPHeaders()).subscribe( - (data: EnclosurePluginAPI) => { - observer.next({ - temperature: data.temp_sensor_temp, - humidity: data.temp_sensor_humidity, - unit: data.use_fahrenheit ? '°F' : '°C' - } as TemperatureReading); - }, (error: HttpErrorResponse) => { - this.notificationService.setError('Can\'t retrieve enclosure temperature!', error.message); + constructor( + private http: HttpClient, + private configService: ConfigService, + private notificationService: NotificationService, + ) { + this.observable = new Observable((observer: Observer) => { + timer(850, 30000).subscribe(_ => { + if (this.httpGETRequest) { + this.httpGETRequest.unsubscribe(); + } + this.httpGETRequest = this.http + .get( + this.configService + .getURL('plugin/enclosure/inputs/' + this.configService.getAmbientTemperatureSensorName()) + .replace('/api', ''), + this.configService.getHTTPHeaders(), + ) + .subscribe( + (data: EnclosurePluginAPI) => { + observer.next({ + temperature: data.temp_sensor_temp, + humidity: data.temp_sensor_humidity, + unit: data.use_fahrenheit ? '°F' : '°C', + } as TemperatureReading); + }, + (error: HttpErrorResponse) => { + this.notificationService.setError("Can't retrieve enclosure temperature!", error.message); + }, + ); }); - }); - }).pipe(shareReplay(1)); - } + }).pipe(shareReplay(1)); + } - public getObservable(): Observable { - return this.observable; - } + public getObservable(): Observable { + return this.observable; + } } interface EnclosurePluginAPI { - controlled_io: any; - temp_sensor_address: string; - temp_sensor_navbar: boolean; - temp_sensor_temp: number; - printer_action: string; - filament_sensor_enabled: boolean; - controlled_io_set_value: number; - temp_sensor_type: string; - temp_sensor_humidity: number; - filament_sensor_timeout: number; - edge: string; - ds18b20_serial: string; - action_type: string; - input_pull_resistor: string; - input_type: string; - label: string; - index_id: number; - use_fahrenheit: boolean; - gpio_pin: string; + controlled_io: any; + temp_sensor_address: string; + temp_sensor_navbar: boolean; + temp_sensor_temp: number; + printer_action: string; + filament_sensor_enabled: boolean; + controlled_io_set_value: number; + temp_sensor_type: string; + temp_sensor_humidity: number; + filament_sensor_timeout: number; + edge: string; + ds18b20_serial: string; + action_type: string; + input_pull_resistor: string; + input_type: string; + label: string; + index_id: number; + use_fahrenheit: boolean; + gpio_pin: string; } diff --git a/src/app/plugin-service/layer-progress.service.ts b/src/app/plugin-service/layer-progress.service.ts index 73e4ed79a..3cec02601 100644 --- a/src/app/plugin-service/layer-progress.service.ts +++ b/src/app/plugin-service/layer-progress.service.ts @@ -1,50 +1,62 @@ +import { HttpClient, HttpErrorResponse } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { Observable, Observer, timer, Subscription } from 'rxjs'; -import { HttpErrorResponse, HttpClient } from '@angular/common/http'; -import { ConfigService } from '../config/config.service'; +import { Observable, Observer, Subscription, timer } from 'rxjs'; import { shareReplay } from 'rxjs/operators'; -import { OctoprintLayerProgressAPI } from '../octoprint-api/layerProgressAPI'; + +import { ConfigService } from '../config/config.service'; import { NotificationService } from '../notification/notification.service'; +import { OctoprintLayerProgressAPI } from '../octoprint-api/layerProgressAPI'; @Injectable({ - providedIn: 'root' + providedIn: 'root', }) export class LayerProgressService { - - httpGETRequest: Subscription; - observable: Observable; - - constructor(private configService: ConfigService, private notificationService: NotificationService, private http: HttpClient) { - this.observable = new Observable((observer: Observer) => { - timer(1000, this.configService.getAPIPollingInterval()).subscribe(_ => { - if (this.httpGETRequest) { - this.httpGETRequest.unsubscribe(); - } - this.httpGETRequest = this.http.get(this.configService.getURL('plugin/DisplayLayerProgress/values').replace('/api', ''), - this.configService.getHTTPHeaders()).subscribe( - (data: OctoprintLayerProgressAPI) => { - observer.next({ - current: data.layer.current === '-' ? 0 : Number(data.layer.current) + 1, - total: data.layer.total === '-' ? 0 : Number(data.layer.total) + 1, - fanSpeed: data.fanSpeed === '-' ? 0 : data.fanSpeed === 'Off' ? 0 : data.fanSpeed.replace('%', '') - }); - }, (error: HttpErrorResponse) => { - this.notificationService.setError('Can\'t retrieve layer progress!', error.message); + httpGETRequest: Subscription; + observable: Observable; + + constructor( + private configService: ConfigService, + private notificationService: NotificationService, + private http: HttpClient, + ) { + this.observable = new Observable((observer: Observer) => { + timer(1000, this.configService.getAPIPollingInterval()).subscribe(_ => { + if (this.httpGETRequest) { + this.httpGETRequest.unsubscribe(); + } + this.httpGETRequest = this.http + .get( + this.configService.getURL('plugin/DisplayLayerProgress/values').replace('/api', ''), + this.configService.getHTTPHeaders(), + ) + .subscribe( + (data: OctoprintLayerProgressAPI) => { + observer.next({ + current: data.layer.current === '-' ? 0 : Number(data.layer.current) + 1, + total: data.layer.total === '-' ? 0 : Number(data.layer.total) + 1, + fanSpeed: + data.fanSpeed === '-' + ? 0 + : data.fanSpeed === 'Off' + ? 0 + : data.fanSpeed.replace('%', ''), + }); + }, + (error: HttpErrorResponse) => { + this.notificationService.setError("Can't retrieve layer progress!", error.message); + }, + ); }); + }).pipe(shareReplay(1)); + } - }); - }).pipe(shareReplay(1)); - } - - - public getObservable(): Observable { - return this.observable; - } - + public getObservable(): Observable { + return this.observable; + } } export interface DisplayLayerProgressAPI { - current: number; - total: number; - fanSpeed: number; + current: number; + total: number; + fanSpeed: number; } diff --git a/src/app/plugin-service/psu-control.service.ts b/src/app/plugin-service/psu-control.service.ts index ed5031750..8bdb63d00 100644 --- a/src/app/plugin-service/psu-control.service.ts +++ b/src/app/plugin-service/psu-control.service.ts @@ -1,46 +1,54 @@ +import { HttpClient, HttpErrorResponse } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Subscription } from 'rxjs'; + import { ConfigService } from '../config/config.service'; import { NotificationService } from '../notification/notification.service'; -import { HttpClient, HttpErrorResponse } from '@angular/common/http'; import { JobCommand } from '../octoprint-api/jobAPI'; @Injectable({ - providedIn: 'root' + providedIn: 'root', }) export class PsuControlService { + httpPOSTRequest: Subscription; - httpPOSTRequest: Subscription; - - constructor(private configService: ConfigService, private notificationService: NotificationService, private http: HttpClient) { } + constructor( + private configService: ConfigService, + private notificationService: NotificationService, + private http: HttpClient, + ) {} - public changePSUState(on: boolean) { - if (this.httpPOSTRequest) { - this.httpPOSTRequest.unsubscribe(); - } - const psuPayload: JobCommand = { - command: on ? 'turnPSUOn' : 'turnPSUOff' - }; - this.httpPOSTRequest = this.http.post(this.configService.getURL('plugin/psucontrol'), psuPayload, this.configService.getHTTPHeaders()) - .subscribe( - () => null, (error: HttpErrorResponse) => { - this.notificationService.setError('Can\'t control PSU!', error.message); + public changePSUState(on: boolean) { + if (this.httpPOSTRequest) { + this.httpPOSTRequest.unsubscribe(); } - ); - } - - public togglePSU() { - if (this.httpPOSTRequest) { - this.httpPOSTRequest.unsubscribe(); + const psuPayload: JobCommand = { + command: on ? 'turnPSUOn' : 'turnPSUOff', + }; + this.httpPOSTRequest = this.http + .post(this.configService.getURL('plugin/psucontrol'), psuPayload, this.configService.getHTTPHeaders()) + .subscribe( + () => null, + (error: HttpErrorResponse) => { + this.notificationService.setError("Can't control PSU!", error.message); + }, + ); } - const psuPayload: JobCommand = { - command: 'togglePSU' - }; - this.httpPOSTRequest = this.http.post(this.configService.getURL('plugin/psucontrol'), psuPayload, this.configService.getHTTPHeaders()) - .subscribe( - () => null, (error: HttpErrorResponse) => { - this.notificationService.setError('Can\'t control PSU!', error.message); + + public togglePSU() { + if (this.httpPOSTRequest) { + this.httpPOSTRequest.unsubscribe(); } - ); - } + const psuPayload: JobCommand = { + command: 'togglePSU', + }; + this.httpPOSTRequest = this.http + .post(this.configService.getURL('plugin/psucontrol'), psuPayload, this.configService.getHTTPHeaders()) + .subscribe( + () => null, + (error: HttpErrorResponse) => { + this.notificationService.setError("Can't control PSU!", error.message); + }, + ); + } } diff --git a/src/app/print-control/print-control.component.ts b/src/app/print-control/print-control.component.ts index 875a2b9a3..8f0ce39d7 100644 --- a/src/app/print-control/print-control.component.ts +++ b/src/app/print-control/print-control.component.ts @@ -1,137 +1,153 @@ import { Component, OnInit } from '@angular/core'; +import { take } from 'rxjs/operators'; + import { JobService } from '../job.service'; import { PrinterService, PrinterStatusAPI } from '../printer.service'; -import { take } from 'rxjs/operators'; @Component({ - selector: 'app-print-control', - templateUrl: './print-control.component.html', - styleUrls: ['./print-control.component.scss'] + selector: 'app-print-control', + templateUrl: './print-control.component.html', + styleUrls: ['./print-control.component.scss'], }) export class PrintControlComponent implements OnInit { + public showControls = false; + public controlView = ControlView; + public view = ControlView.MAIN; - public showControls = false; - public controlView = ControlView; - public view = ControlView.MAIN; + public temperatureHotend; + public temperatureHeatbed; + public feedrate; + public flowrate; - public temperatureHotend; - public temperatureHeatbed; - public feedrate; - public flowrate; + constructor(private jobService: JobService, private printerService: PrinterService) {} - constructor(private jobService: JobService, private printerService: PrinterService) { } + ngOnInit() {} - ngOnInit() { - } + public cancel(event) { + if (this.showControls) { + this.stopPropagation(event); + this.view = ControlView.CANCEL; + } + } - public cancel(event) { - if (this.showControls) { - this.stopPropagation(event); - this.view = ControlView.CANCEL; + public pause(event) { + if (this.showControls) { + this.stopPropagation(event); + this.jobService.pauseJob(); + this.view = ControlView.PAUSE; + } } - } - public pause(event) { - if (this.showControls) { - this.stopPropagation(event); - this.jobService.pauseJob(); - this.view = ControlView.PAUSE; + public adjust(event) { + if (this.showControls) { + this.view = ControlView.ADJUST; + this.stopPropagation(event); + } } - } - public adjust(event) { - if (this.showControls) { - this.view = ControlView.ADJUST; - this.stopPropagation(event); + public stopPropagation(event) { + if (this.showControls) { + event.stopPropagation(); + } } - } - public stopPropagation(event) { - if (this.showControls) { - event.stopPropagation(); + public showControlOverlay(event?) { + this.stopPropagation(event); + this.loadData(); + this.view = ControlView.MAIN; + this.showControls = true; } - } - - public showControlOverlay(event?) { - this.stopPropagation(event); - this.loadData(); - this.view = ControlView.MAIN; - this.showControls = true; - } - - public hideControlOverlay(event) { - this.stopPropagation(event); - this.showControls = false; - } - - public cancelPrint(event) { - if (this.showControls && this.view === ControlView.CANCEL) { - this.jobService.cancelJob(); - this.hideControlOverlay(event); + + public hideControlOverlay(event) { + this.stopPropagation(event); + this.showControls = false; } - } - public resume(event) { - if (this.showControls && this.view === ControlView.PAUSE) { - this.jobService.resumeJob(); - this.hideControlOverlay(event); + public cancelPrint(event) { + if (this.showControls && this.view === ControlView.CANCEL) { + this.jobService.cancelJob(); + this.hideControlOverlay(event); + } } - } - - public backToControlScreen(event) { - this.view = ControlView.MAIN; - this.stopPropagation(event); - } - - private loadData() { - this.temperatureHotend = '?'; - this.temperatureHeatbed = '?'; - this.flowrate = 100; - this.feedrate = 100; - this.printerService.getObservable().pipe(take(1)).subscribe((printerStatus: PrinterStatusAPI) => { - this.temperatureHotend = printerStatus.nozzle.set; - this.temperatureHeatbed = printerStatus.heatbed.set; - }); - } - - public changeTemperatureHotend(value: number) { - this.temperatureHotend += value; - if (this.temperatureHotend < 0) { this.temperatureHotend = 0; } - if (this.temperatureHotend > 999) { this.temperatureHotend = 999; } - } - - public changeTemperatureHeatbed(value: number) { - this.temperatureHeatbed += value; - if (this.temperatureHeatbed < 0) { this.temperatureHeatbed = 0; } - if (this.temperatureHeatbed > 999) { this.temperatureHeatbed = 999; } - } - - public changeFeedrate(value: number) { - this.feedrate += value; - if (this.feedrate < 50) { this.feedrate = 50; } - if (this.feedrate > 200) { this.feedrate = 200; } - } - - public changeFlowrate(value: number) { - this.flowrate += value; - if (this.flowrate < 75) { this.flowrate = 75; } - if (this.flowrate > 125) { this.flowrate = 125; } - } - - public setAdjustParameters(event) { - this.printerService.setTemperatureHotend(this.temperatureHotend); - this.printerService.setTemperatureHeatbed(this.temperatureHeatbed); - this.printerService.setFeedrate(this.feedrate); - this.printerService.setFlowrate(this.flowrate); - this.hideControlOverlay(event); - } -} + public resume(event) { + if (this.showControls && this.view === ControlView.PAUSE) { + this.jobService.resumeJob(); + this.hideControlOverlay(event); + } + } + + public backToControlScreen(event) { + this.view = ControlView.MAIN; + this.stopPropagation(event); + } + + private loadData() { + this.temperatureHotend = '?'; + this.temperatureHeatbed = '?'; + this.flowrate = 100; + this.feedrate = 100; + this.printerService + .getObservable() + .pipe(take(1)) + .subscribe((printerStatus: PrinterStatusAPI) => { + this.temperatureHotend = printerStatus.nozzle.set; + this.temperatureHeatbed = printerStatus.heatbed.set; + }); + } + public changeTemperatureHotend(value: number) { + this.temperatureHotend += value; + if (this.temperatureHotend < 0) { + this.temperatureHotend = 0; + } + if (this.temperatureHotend > 999) { + this.temperatureHotend = 999; + } + } + + public changeTemperatureHeatbed(value: number) { + this.temperatureHeatbed += value; + if (this.temperatureHeatbed < 0) { + this.temperatureHeatbed = 0; + } + if (this.temperatureHeatbed > 999) { + this.temperatureHeatbed = 999; + } + } + + public changeFeedrate(value: number) { + this.feedrate += value; + if (this.feedrate < 50) { + this.feedrate = 50; + } + if (this.feedrate > 200) { + this.feedrate = 200; + } + } + + public changeFlowrate(value: number) { + this.flowrate += value; + if (this.flowrate < 75) { + this.flowrate = 75; + } + if (this.flowrate > 125) { + this.flowrate = 125; + } + } + + public setAdjustParameters(event) { + this.printerService.setTemperatureHotend(this.temperatureHotend); + this.printerService.setTemperatureHeatbed(this.temperatureHeatbed); + this.printerService.setFeedrate(this.feedrate); + this.printerService.setFlowrate(this.flowrate); + this.hideControlOverlay(event); + } +} enum ControlView { - MAIN, - CANCEL, - PAUSE, - ADJUST + MAIN, + CANCEL, + PAUSE, + ADJUST, } diff --git a/src/app/printer-status/printer-status.component.ts b/src/app/printer-status/printer-status.component.ts index c5236f18b..94bc01a0b 100644 --- a/src/app/printer-status/printer-status.component.ts +++ b/src/app/printer-status/printer-status.component.ts @@ -1,53 +1,57 @@ -import { Component, OnInit, OnDestroy } from '@angular/core'; -import { PrinterService, PrinterStatusAPI, PrinterValue } from '../printer.service'; -import { LayerProgressService, DisplayLayerProgressAPI } from '../plugin-service/layer-progress.service'; +import { Component, OnDestroy, OnInit } from '@angular/core'; import { Subscription } from 'rxjs'; +import { DisplayLayerProgressAPI, LayerProgressService } from '../plugin-service/layer-progress.service'; +import { PrinterService, PrinterStatusAPI, PrinterValue } from '../printer.service'; + @Component({ - selector: 'app-printer-status', - templateUrl: './printer-status.component.html', - styleUrls: ['./printer-status.component.scss'] + selector: 'app-printer-status', + templateUrl: './printer-status.component.html', + styleUrls: ['./printer-status.component.scss'], }) export class PrinterStatusComponent implements OnInit, OnDestroy { + private subscriptions: Subscription = new Subscription(); + public printerStatus: PrinterStatus; + public status: string; - private subscriptions: Subscription = new Subscription(); - public printerStatus: PrinterStatus; - public status: string; - - constructor(private printerService: PrinterService, private displayLayerProgressService: LayerProgressService) { - this.printerStatus = { - nozzle: { - current: 0, - set: 0 - }, - heatbed: { - current: 0, - set: 0 - }, - fan: 0 - }; - this.status = 'connecting'; - } + constructor(private printerService: PrinterService, private displayLayerProgressService: LayerProgressService) { + this.printerStatus = { + nozzle: { + current: 0, + set: 0, + }, + heatbed: { + current: 0, + set: 0, + }, + fan: 0, + }; + this.status = 'connecting'; + } - ngOnInit() { - this.subscriptions.add(this.printerService.getObservable().subscribe((printerStatus: PrinterStatusAPI) => { - this.printerStatus.nozzle = printerStatus.nozzle; - this.printerStatus.heatbed = printerStatus.heatbed; - this.status = printerStatus.status; - })); + ngOnInit() { + this.subscriptions.add( + this.printerService.getObservable().subscribe((printerStatus: PrinterStatusAPI) => { + this.printerStatus.nozzle = printerStatus.nozzle; + this.printerStatus.heatbed = printerStatus.heatbed; + this.status = printerStatus.status; + }), + ); - this.subscriptions.add(this.displayLayerProgressService.getObservable().subscribe((layerProgress: DisplayLayerProgressAPI) => { - this.printerStatus.fan = layerProgress.fanSpeed; - })); - } + this.subscriptions.add( + this.displayLayerProgressService.getObservable().subscribe((layerProgress: DisplayLayerProgressAPI) => { + this.printerStatus.fan = layerProgress.fanSpeed; + }), + ); + } - ngOnDestroy() { - this.subscriptions.unsubscribe(); - } + ngOnDestroy() { + this.subscriptions.unsubscribe(); + } } export interface PrinterStatus { - nozzle: PrinterValue; - heatbed: PrinterValue; - fan: number; + nozzle: PrinterValue; + heatbed: PrinterValue; + fan: number; } diff --git a/src/app/printer.service.ts b/src/app/printer.service.ts index 9c4dad79b..49fc78d6f 100644 --- a/src/app/printer.service.ts +++ b/src/app/printer.service.ts @@ -1,224 +1,251 @@ -import { Injectable } from '@angular/core'; import { HttpClient, HttpErrorResponse } from '@angular/common/http'; -import { ConfigService } from './config/config.service'; -import { Observable, Observer, timer, Subscription } from 'rxjs'; +import { Injectable } from '@angular/core'; +import { Router } from '@angular/router'; +import { Observable, Observer, Subscription, timer } from 'rxjs'; import { shareReplay } from 'rxjs/operators'; -import { OctoprintPrinterStatusAPI } from './octoprint-api/printerStatusAPI'; + +import { ConfigService } from './config/config.service'; import { NotificationService } from './notification/notification.service'; import { OctoprintConnectionAPI } from './octoprint-api/connectionAPI'; -import { Router } from '@angular/router'; +import { OctoprintPrinterStatusAPI } from './octoprint-api/printerStatusAPI'; @Injectable({ - providedIn: 'root' + providedIn: 'root', }) export class PrinterService { - - httpGETRequest: Subscription; - httpPOSTRequest: Subscription; - observable: Observable; - - constructor( - private http: HttpClient, - private configService: ConfigService, - private notificationService: NotificationService, - private router: Router) { - this.observable = new Observable((observer: Observer) => { - timer(500, this.configService.getAPIPollingInterval()).subscribe(_ => { - if (this.httpGETRequest) { - this.httpGETRequest.unsubscribe(); - } - this.httpGETRequest = this.http.get(this.configService.getURL('printer'), this.configService.getHTTPHeaders()).subscribe( - (data: OctoprintPrinterStatusAPI) => { - const printerStatus: PrinterStatusAPI = { - status: data.state.text.toLowerCase(), - nozzle: { - current: Math.round(data.temperature.tool0.actual), - set: Math.round(data.temperature.tool0.target) - }, - heatbed: { - current: data.temperature.bed ? Math.round(data.temperature.bed.actual) : 0, - set: data.temperature.bed ? Math.round(data.temperature.bed.target) : 0 - } - }; - observer.next(printerStatus); - }, (error: HttpErrorResponse) => { - if (error.status === 409) { - this.isPrinterOffline().then((printerOffline) => { - if (printerOffline) { - this.router.navigate(['/standby']); - this.notificationService.disableNotifications(); - } else { - this.notificationService.setError('Can\'t retrieve printer status!', error.message); + private httpGETRequest: Subscription; + private httpPOSTRequest: Subscription; + private observable: Observable; + + public constructor( + private http: HttpClient, + private configService: ConfigService, + private notificationService: NotificationService, + private router: Router, + ) { + this.observable = new Observable((observer: Observer): void => { + timer(500, this.configService.getAPIPollingInterval()).subscribe((): void => { + if (this.httpGETRequest) { + this.httpGETRequest.unsubscribe(); } - }); - } else { - const printerStatus: PrinterStatusAPI = { - status: `error (${error.status})`, - nozzle: { - current: 0, - set: 0 + this.httpGETRequest = this.http + .get(this.configService.getURL('printer'), this.configService.getHTTPHeaders()) + .subscribe( + (data: OctoprintPrinterStatusAPI): void => { + const printerStatus: PrinterStatusAPI = { + status: data.state.text.toLowerCase(), + nozzle: { + current: Math.round(data.temperature.tool0.actual), + set: Math.round(data.temperature.tool0.target), + }, + heatbed: { + current: data.temperature.bed ? Math.round(data.temperature.bed.actual) : 0, + set: data.temperature.bed ? Math.round(data.temperature.bed.target) : 0, + }, + }; + observer.next(printerStatus); + }, + (error: HttpErrorResponse): void => { + if (error.status === 409) { + this.isPrinterOffline().then((printerOffline): void => { + if (printerOffline) { + this.router.navigate(['/standby']); + this.notificationService.disableNotifications(); + } else { + this.notificationService.setError( + "Can't retrieve printer status!", + error.message, + ); + } + }); + } else { + const printerStatus: PrinterStatusAPI = { + status: `error (${error.status})`, + nozzle: { + current: 0, + set: 0, + }, + heatbed: { + current: 0, + set: 0, + }, + }; + observer.next(printerStatus); + this.notificationService.setError("Can't retrieve printer status!", error.message); + } + }, + ); + }); + }).pipe(shareReplay(1)); + } + + public getObservable(): Observable { + return this.observable; + } + + public jog(x: number, y: number, z: number): void { + const jogPayload: JogCommand = { + command: 'jog', + x, + y, + z, + speed: z !== 0 ? this.configService.getZSpeed() * 60 : this.configService.getXYSpeed() * 60, + }; + this.httpPOSTRequest = this.http + .post(this.configService.getURL('printer/printhead'), jogPayload, this.configService.getHTTPHeaders()) + .subscribe( + (): void => null, + (error: HttpErrorResponse): void => { + this.notificationService.setError("Can't move Printhead!", error.message); }, - heatbed: { - current: 0, - set: 0 - } - }; - observer.next(printerStatus); - this.notificationService.setError('Can\'t retrieve printer status!', error.message); - } - }); - }); - }).pipe(shareReplay(1)); - } - - public getObservable(): Observable { - return this.observable; - } - - public jog(x: number, y: number, z: number) { - const jogPayload: JogCommand = { - command: 'jog', - x, - y, - z, - speed: z !== 0 ? this.configService.getZSpeed() * 60 : this.configService.getXYSpeed() * 60 - }; - this.httpPOSTRequest = this.http.post(this.configService.getURL('printer/printhead'), jogPayload, this.configService.getHTTPHeaders()) - .subscribe( - () => null, (error: HttpErrorResponse) => { - this.notificationService.setError('Can\'t move Printhead!', error.message); + ); + } + + public executeGCode(gCode: string): void { + if (this.httpPOSTRequest) { + this.httpPOSTRequest.unsubscribe(); } - ); - } + const gCodePayload: GCodeCommand = { + commands: gCode.split('; '), + }; + this.httpPOSTRequest = this.http + .post(this.configService.getURL('printer/command'), gCodePayload, this.configService.getHTTPHeaders()) + .subscribe( + (): void => null, + (error: HttpErrorResponse): void => { + this.notificationService.setError("Can't send GCode!", error.message); + }, + ); + } - public executeGCode(gCode: string) { - if (this.httpPOSTRequest) { - this.httpPOSTRequest.unsubscribe(); + public setTemperatureHotend(temperature: number): void { + const temperatureHotendCommand: TemperatureHotendCommand = { + command: 'target', + targets: { + tool0: temperature, + }, + }; + this.httpPOSTRequest = this.http + .post( + this.configService.getURL('printer/tool'), + temperatureHotendCommand, + this.configService.getHTTPHeaders(), + ) + .subscribe( + (): void => null, + (error: HttpErrorResponse): void => { + this.notificationService.setError("Can't set Hotend Temperature!", error.message); + }, + ); } - const gCodePayload: GCodeCommand = { - commands: gCode.split('; ') - }; - this.httpPOSTRequest = this.http.post(this.configService.getURL('printer/command'), gCodePayload, this.configService.getHTTPHeaders()) - .subscribe( - () => null, (error: HttpErrorResponse) => { - this.notificationService.setError('Can\'t send GCode!', error.message); - } - ); - } - - public setTemperatureHotend(temperature: number) { - const temperatureHotendCommand: TemperatureHotendCommand = { - command: 'target', - targets: { - tool0: temperature - } - }; - this.httpPOSTRequest = this.http.post(this.configService.getURL('printer/tool'), temperatureHotendCommand, - this.configService.getHTTPHeaders()) - .subscribe( - () => null, (error: HttpErrorResponse) => { - this.notificationService.setError('Can\'t set Hotend Temperature!', error.message); - } - ); - } - public setTemperatureHeatbed(temperature: number) { - const temperatureHeatbedCommand: TemperatureHeatbedCommand = { - command: 'target', - target: temperature - }; - this.httpPOSTRequest = this.http.post(this.configService.getURL('printer/bed'), temperatureHeatbedCommand, - this.configService.getHTTPHeaders()) - .subscribe( - () => null, (error: HttpErrorResponse) => { - this.notificationService.setError('Can\'t set Heatbed Temperature!', error.message); - } - ); - } - - public setFeedrate(feedrate: number) { - if (feedrate === 100) { return; } - const feedrateCommand: FeedrateCommand = { - command: 'feedrate', - factor: feedrate - }; - this.httpPOSTRequest = this.http.post(this.configService.getURL('printer/printhead'), feedrateCommand, - this.configService.getHTTPHeaders()) - .subscribe( - () => null, (error: HttpErrorResponse) => { - this.notificationService.setError('Can\'t set Feedrate!', error.message); + public setTemperatureHeatbed(temperature: number): void { + const temperatureHeatbedCommand: TemperatureHeatbedCommand = { + command: 'target', + target: temperature, + }; + this.httpPOSTRequest = this.http + .post( + this.configService.getURL('printer/bed'), + temperatureHeatbedCommand, + this.configService.getHTTPHeaders(), + ) + .subscribe( + (): void => null, + (error: HttpErrorResponse): void => { + this.notificationService.setError("Can't set Heatbed Temperature!", error.message); + }, + ); + } + + public setFeedrate(feedrate: number): void { + if (feedrate === 100) { + return; } - ); - } - - public setFlowrate(flowrate: number) { - if (flowrate === 100) { return; } - const flowrateCommand: FeedrateCommand = { - command: 'flowrate', - factor: flowrate - }; - this.httpPOSTRequest = this.http.post(this.configService.getURL('printer/tool'), flowrateCommand, - this.configService.getHTTPHeaders()) - .subscribe( - () => null, (error: HttpErrorResponse) => { - this.notificationService.setError('Can\'t set Flowrate!', error.message); + const feedrateCommand: FeedrateCommand = { + command: 'feedrate', + factor: feedrate, + }; + this.httpPOSTRequest = this.http + .post(this.configService.getURL('printer/printhead'), feedrateCommand, this.configService.getHTTPHeaders()) + .subscribe( + (): void => null, + (error: HttpErrorResponse): void => { + this.notificationService.setError("Can't set Feedrate!", error.message); + }, + ); + } + + public setFlowrate(flowrate: number): void { + if (flowrate === 100) { + return; } - ); - } - - public isPrinterOffline(): Promise { - return new Promise((resolve) => { - this.http.get(this.configService.getURL('connection'), this.configService.getHTTPHeaders()) - .subscribe( - (data: OctoprintConnectionAPI) => { - resolve(data.current.state === 'Closed' || data.current.state.includes('Error:')); - }, - (error: HttpErrorResponse) => { - this.notificationService.setError('Can\'t retrieve connection state!', error.message); - resolve(false); - } - ); - }); - } + const flowrateCommand: FeedrateCommand = { + command: 'flowrate', + factor: flowrate, + }; + this.httpPOSTRequest = this.http + .post(this.configService.getURL('printer/tool'), flowrateCommand, this.configService.getHTTPHeaders()) + .subscribe( + (): void => null, + (error: HttpErrorResponse): void => { + this.notificationService.setError("Can't set Flowrate!", error.message); + }, + ); + } + + public isPrinterOffline(): Promise { + return new Promise((resolve): void => { + this.http.get(this.configService.getURL('connection'), this.configService.getHTTPHeaders()).subscribe( + (data: OctoprintConnectionAPI): void => { + resolve(data.current.state === 'Closed' || data.current.state.includes('Error:')); + }, + (error: HttpErrorResponse): void => { + this.notificationService.setError("Can't retrieve connection state!", error.message); + resolve(false); + }, + ); + }); + } } export interface PrinterStatusAPI { - status: string; - nozzle: PrinterValue; - heatbed: PrinterValue; + status: string; + nozzle: PrinterValue; + heatbed: PrinterValue; } export interface PrinterValue { - current: number; - set: number; + current: number; + set: number; } interface JogCommand { - command: string; - x: number; - y: number; - z: number; - speed: number; + command: string; + x: number; + y: number; + z: number; + speed: number; } interface GCodeCommand { - commands: string[]; + commands: string[]; } interface FeedrateCommand { - command: string; - factor: number; + command: string; + factor: number; } interface TemperatureHotendCommand { - command: string; - targets: { - tool0: number; - tool1?: number; - }; + command: string; + targets: { + tool0: number; + tool1?: number; + }; } interface TemperatureHeatbedCommand { - command: string; - target: number; + command: string; + target: number; } diff --git a/src/app/settings/settings.component.ts b/src/app/settings/settings.component.ts index 5edd3b07f..ae5afcb25 100644 --- a/src/app/settings/settings.component.ts +++ b/src/app/settings/settings.component.ts @@ -1,95 +1,116 @@ -import { Component, OnInit, Output, EventEmitter, ViewChild, ElementRef } from '@angular/core'; -import { ConfigService, Config } from '../config/config.service'; -import { NotificationService } from '../notification/notification.service'; +import { Component, ElementRef, EventEmitter, OnInit, Output, ViewChild } from '@angular/core'; + import { AppService } from '../app.service'; +import { Config, ConfigService } from '../config/config.service'; +import { NotificationService } from '../notification/notification.service'; @Component({ - selector: 'app-settings', - templateUrl: './settings.component.html', - styleUrls: ['./settings.component.scss'] + selector: 'app-settings', + templateUrl: './settings.component.html', + styleUrls: ['./settings.component.scss'], }) export class SettingsComponent implements OnInit { + @Output() closeFunction = new EventEmitter(); + @ViewChild('settingsMain') settingsMain: ElementRef; + @ViewChild('settingsGeneral') settingsGeneral: ElementRef; + @ViewChild('settingsOctoDash') settingsOctoDash: ElementRef; + @ViewChild('settingsPlugins') settingsPlugins: ElementRef; + @ViewChild('settingsCredits') settingsCredits: ElementRef; - @Output() closeFunction = new EventEmitter(); - @ViewChild('settingsMain') settingsMain: ElementRef; - @ViewChild('settingsGeneral') settingsGeneral: ElementRef; - @ViewChild('settingsOctoDash') settingsOctoDash: ElementRef; - @ViewChild('settingsPlugins') settingsPlugins: ElementRef; - @ViewChild('settingsCredits') settingsCredits: ElementRef; + public fadeOutAnimation = false; + public config: Config; + public customActionsPosition = [ + 'Top Left', + 'Top Right', + 'Middle Left', + 'Middle Right', + 'Bottom Left', + 'Bottom Right', + ]; + public version: string; + private overwriteNoSave = false; + private pages = []; + private ipc: any; - public fadeOutAnimation = false; - public config: Config; - public customActionsPosition = ['Top Left', 'Top Right', 'Middle Left', 'Middle Right', 'Bottom Left', 'Bottom Right']; - public version: string; - private overwriteNoSave = false; - private pages = []; - private ipc: any; - - public constructor(private configService: ConfigService, private notificationService: NotificationService, private service: AppService) { - this.config = this.configService.getCurrentConfig(); - this.config = this.configService.revertConfigForInput(this.config); - this.getVersion(); - if (window.require) { - try { - this.ipc = window.require('electron').ipcRenderer; - } catch (e) { - this.notificationService.setError('Can\'t connect to backend', 'Please open an issue for GitHub as this shouldn\'t happen.'); - } + public constructor( + private configService: ConfigService, + private notificationService: NotificationService, + private service: AppService, + ) { + this.config = this.configService.getCurrentConfig(); + this.config = this.configService.revertConfigForInput(this.config); + this.getVersion(); + if (window.require) { + try { + this.ipc = window.require('electron').ipcRenderer; + } catch (e) { + this.notificationService.setError( + "Can't connect to backend", + "Please open an issue for GitHub as this shouldn't happen.", + ); + } + } } - } - private getVersion() { - this.version = this.service.getVersion(); - if (this.version === undefined) { - setTimeout(this.getVersion.bind(this), 3500); + private getVersion() { + this.version = this.service.getVersion(); + if (this.version === undefined) { + setTimeout(this.getVersion.bind(this), 3500); + } } - } - public ngOnInit(): void { - setTimeout(() => { - this.pages = [ - this.settingsMain.nativeElement, - this.settingsGeneral.nativeElement, - this.settingsOctoDash.nativeElement, - this.settingsPlugins.nativeElement, - this.settingsCredits.nativeElement]; - }, 400); - } + public ngOnInit(): void { + setTimeout(() => { + this.pages = [ + this.settingsMain.nativeElement, + this.settingsGeneral.nativeElement, + this.settingsOctoDash.nativeElement, + this.settingsPlugins.nativeElement, + this.settingsCredits.nativeElement, + ]; + }, 400); + } - public hideSettings(): void { - if (this.configService.isEqualToCurrentConfig(this.configService.createConfigFromInput(this.config)) || this.overwriteNoSave) { - this.fadeOutAnimation = true; - this.closeFunction.emit(); - setTimeout(() => { - this.fadeOutAnimation = false; - }, 800); - } else { - this.notificationService.setWarning('Configuration not saved!', 'You haven\'t saved your config yet, so your changes will not be applied. Click close again if you want to discard your changes!'); - this.overwriteNoSave = true; + public hideSettings(): void { + if ( + this.configService.isEqualToCurrentConfig(this.configService.createConfigFromInput(this.config)) || + this.overwriteNoSave + ) { + this.fadeOutAnimation = true; + this.closeFunction.emit(); + setTimeout(() => { + this.fadeOutAnimation = false; + }, 800); + } else { + this.notificationService.setWarning( + 'Configuration not saved!', + "You haven't saved your config yet, so your changes will not be applied. Click close again if you want to discard your changes!", + ); + this.overwriteNoSave = true; + } } - } - public changePage(page: number, current: number, direction: 'forward' | 'backward'): void { - this.pages[current].classList.add('settings__content-slideout-' + direction); - this.pages[page].classList.remove('settings__content-inactive'); - this.pages[page].classList.add('settings__content-slidein-' + direction); + public changePage(page: number, current: number, direction: 'forward' | 'backward'): void { + this.pages[current].classList.add('settings__content-slideout-' + direction); + this.pages[page].classList.remove('settings__content-inactive'); + this.pages[page].classList.add('settings__content-slidein-' + direction); - setTimeout(() => { - this.pages[current].classList.add('settings__content-inactive'); - this.pages[current].classList.remove('settings__content-slideout-' + direction); - this.pages[page].classList.remove('settings__content-slidein-' + direction); - }, 470); - } + setTimeout(() => { + this.pages[current].classList.add('settings__content-inactive'); + this.pages[current].classList.remove('settings__content-slideout-' + direction); + this.pages[page].classList.remove('settings__content-slidein-' + direction); + }, 470); + } - public updateConfig(): void { - const config = this.configService.createConfigFromInput(this.config); - if (!this.configService.validateGiven(config)) { - this.notificationService.setError('Config is invalid!', this.configService.getErrors().toString()); + public updateConfig(): void { + const config = this.configService.createConfigFromInput(this.config); + if (!this.configService.validateGiven(config)) { + this.notificationService.setError('Config is invalid!', this.configService.getErrors().toString()); + } + this.configService.saveConfig(config); + this.overwriteNoSave = true; + this.hideSettings(); + this.configService.updateConfig(); + this.ipc.send('reload', ''); } - this.configService.saveConfig(config); - this.overwriteNoSave = true; - this.hideSettings(); - this.configService.updateConfig(); - this.ipc.send('reload', ''); - } } diff --git a/src/app/standby/standby.component.ts b/src/app/standby/standby.component.ts index 373e734ca..be0929dfb 100644 --- a/src/app/standby/standby.component.ts +++ b/src/app/standby/standby.component.ts @@ -1,104 +1,112 @@ -import { Component, OnInit } from '@angular/core'; -import { ConfigService } from '../config/config.service'; import { HttpClient, HttpErrorResponse } from '@angular/common/http'; +import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; + import { AppService } from '../app.service'; +import { ConfigService } from '../config/config.service'; import { NotificationService } from '../notification/notification.service'; import { OctoprintConnectionAPI } from '../octoprint-api/connectionAPI'; import { PsuControlService } from '../plugin-service/psu-control.service'; @Component({ - selector: 'app-standby', - templateUrl: './standby.component.html', - styleUrls: ['./standby.component.scss'] + selector: 'app-standby', + templateUrl: './standby.component.html', + styleUrls: ['./standby.component.scss'], }) export class StandbyComponent implements OnInit { + public connecting = false; + public error = ''; + private connectionRetries = 3; - public connecting = false; - public error = ''; - private connectionRetries = 3; - - constructor( - private configService: ConfigService, - private http: HttpClient, - private router: Router, - private service: AppService, - private notificationService: NotificationService, - private psuControlService: PsuControlService) { } + constructor( + private configService: ConfigService, + private http: HttpClient, + private router: Router, + private service: AppService, + private notificationService: NotificationService, + private psuControlService: PsuControlService, + ) {} - ngOnInit() { - if (this.configService.getAutomaticScreenSleep()) { - setTimeout(this.service.turnDisplayOff.bind(this.service), 300000); + ngOnInit() { + if (this.configService.getAutomaticScreenSleep()) { + setTimeout(this.service.turnDisplayOff.bind(this.service), 300000); + } } - } - public reconnect() { - this.connecting = true; - if (this.configService.turnOnPSUWhenExitingSleep()) { - this.psuControlService.changePSUState(true); - setTimeout(this.checkConnection.bind(this), 5000); - } else { - this.checkConnection(); + public reconnect() { + this.connecting = true; + if (this.configService.turnOnPSUWhenExitingSleep()) { + this.psuControlService.changePSUState(true); + setTimeout(this.checkConnection.bind(this), 5000); + } else { + this.checkConnection(); + } } - } - private connectToPrinter() { - this.http.post(this.configService.getURL('connection'), connectPayload, this.configService.getHTTPHeaders()) - .subscribe( - () => { setTimeout(this.checkConnection.bind(this), 3000); }, - () => { this.setConnectionError(); }); - } + private connectToPrinter() { + this.http + .post(this.configService.getURL('connection'), connectPayload, this.configService.getHTTPHeaders()) + .subscribe( + () => { + setTimeout(this.checkConnection.bind(this), 3000); + }, + () => { + this.setConnectionError(); + }, + ); + } - private checkConnection() { - this.http.get(this.configService.getURL('connection'), this.configService.getHTTPHeaders()) - .subscribe( - (data: OctoprintConnectionAPI) => { - if (data.current.state !== 'Operational') { - if (this.connectionRetries === 0) { - this.connectionRetries = 3; - this.setConnectionError(); - } else { - this.connectionRetries--; - setTimeout(this.connectToPrinter.bind(this), 500); - } - } else { - this.disableStandby(); - } - }, - (error: HttpErrorResponse) => { - this.connecting = false; - this.error = 'There is something really wrong, OctoDash can\'t get a response from OctoPrint. Please check your setup!'; - }); - } + private checkConnection() { + this.http.get(this.configService.getURL('connection'), this.configService.getHTTPHeaders()).subscribe( + (data: OctoprintConnectionAPI) => { + if (data.current.state !== 'Operational') { + if (this.connectionRetries === 0) { + this.connectionRetries = 3; + this.setConnectionError(); + } else { + this.connectionRetries--; + setTimeout(this.connectToPrinter.bind(this), 500); + } + } else { + this.disableStandby(); + } + }, + (error: HttpErrorResponse) => { + this.connecting = false; + this.error = + "There is something really wrong, OctoDash can't get a response from OctoPrint. Please check your setup!"; + }, + ); + } - private setConnectionError() { - this.connecting = false; - this.error = - 'OctoPrint can\'t connect to your printer. Please make sure that the connection works, then come back and try again.'; - } + private setConnectionError() { + this.connecting = false; + this.error = + "OctoPrint can't connect to your printer. Please make sure that the connection works, then come back and try again."; + } - private disableStandby() { - setTimeout(() => { - this.connecting = false; - if (this.configService.getAutomaticScreenSleep()) { - this.service.turnDisplayOn(); - } - this.notificationService.enableNotifications(); - this.router.navigate(['/main-screen']); - }, 1000); - } + private disableStandby() { + setTimeout(() => { + this.connecting = false; + if (this.configService.getAutomaticScreenSleep()) { + this.service.turnDisplayOn(); + } + this.notificationService.enableNotifications(); + this.router.navigate(['/main-screen']); + }, 1000); + } } const connectPayload: ConnectCommand = { - command: 'connect', - save: false + command: 'connect', + save: false, }; interface ConnectCommand { - command: string; - port?: string; - baudrate?: number; - printerProfile?: string; - save?: boolean; - autoconnect?: boolean; + command: string; + port?: string; + baudrate?: number; + printerProfile?: string; + save?: boolean; + autoconnect?: boolean; } diff --git a/src/app/url.pipe.ts b/src/app/url.pipe.ts index f017c74a9..9c9bf004d 100644 --- a/src/app/url.pipe.ts +++ b/src/app/url.pipe.ts @@ -1,10 +1,11 @@ import { Pipe, PipeTransform } from '@angular/core'; -import { DomSanitizer } from '@angular/platform-browser'; +import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; @Pipe({ name: 'url' }) export class URLSafePipe implements PipeTransform { - constructor(private sanitizer: DomSanitizer) { } - transform(url) { + public constructor(private sanitizer: DomSanitizer) {} + + public transform(url): SafeResourceUrl { return this.sanitizer.bypassSecurityTrustResourceUrl(url); } } diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts index 35734d1d1..99ea51f2e 100644 --- a/src/environments/environment.prod.ts +++ b/src/environments/environment.prod.ts @@ -1,4 +1,4 @@ export const environment = { - production: true, - config: 'assets/config.json' + production: true, + config: 'assets/config.json', }; diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 1b79cbb2b..7aa6e6e8a 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -3,8 +3,8 @@ // The list of file replacements can be found in `angular.json`. export const environment = { - production: false, - config: 'assets/config.testing.json' + production: false, + config: 'assets/config.testing.json', }; /* diff --git a/src/main.ts b/src/main.ts index 5f262778d..b90ebbf39 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,14 +1,15 @@ +import 'hammerjs'; + import { enableProdMode } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; import { environment } from './environments/environment'; -import 'hammerjs'; - if (environment.production) { - enableProdMode(); + enableProdMode(); } -platformBrowserDynamic().bootstrapModule(AppModule) - .catch(err => console.error(err)); +platformBrowserDynamic() + .bootstrapModule(AppModule) + .catch((err): void => console.error(err)); diff --git a/src/polyfills.ts b/src/polyfills.ts index aa665d6b8..2f258e56c 100644 --- a/src/polyfills.ts +++ b/src/polyfills.ts @@ -55,8 +55,7 @@ /*************************************************************************************************** * Zone JS is required by default for Angular itself. */ -import 'zone.js/dist/zone'; // Included with Angular CLI. - +import 'zone.js/dist/zone'; // Included with Angular CLI. /*************************************************************************************************** * APPLICATION IMPORTS diff --git a/src/test.ts b/src/test.ts deleted file mode 100644 index 16317897b..000000000 --- a/src/test.ts +++ /dev/null @@ -1,20 +0,0 @@ -// This file is required by karma.conf.js and loads recursively all the .spec and framework files - -import 'zone.js/dist/zone-testing'; -import { getTestBed } from '@angular/core/testing'; -import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting -} from '@angular/platform-browser-dynamic/testing'; - -declare const require: any; - -// First, initialize the Angular testing environment. -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting() -); -// Then we find all the tests. -const context = require.context('./', true, /\.spec\.ts$/); -// And load the modules. -context.keys().map(context); diff --git a/tsconfig.json b/tsconfig.json index 81acc719a..ae257c4d3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,5 +17,8 @@ "types": [], "lib": ["es2018", "dom"], "esModuleInterop": true - } + }, + "exclude": [ + "**/node_modules/**" + ] } diff --git a/tslint.json b/tslint.json deleted file mode 100644 index fcb585ef7..000000000 --- a/tslint.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "extends": "tslint:recommended", - "rules": { - "array-type": false, - "arrow-parens": false, - "deprecation": { - "severity": "warn" - }, - "component-class-suffix": true, - "contextual-lifecycle": true, - "directive-class-suffix": true, - "directive-selector": [ - true, - "attribute", - "app", - "camelCase" - ], - "component-selector": [ - true, - "element", - "app", - "kebab-case" - ], - "import-blacklist": [ - true, - "rxjs/Rx" - ], - "interface-name": false, - "max-classes-per-file": false, - "max-line-length": [ - true, - 140 - ], - "member-access": false, - "member-ordering": [ - true, - { - "order": [ - "static-field", - "instance-field", - "static-method", - "instance-method" - ] - } - ], - "no-consecutive-blank-lines": false, - "no-console": [ - true, - "debug", - "info", - "time", - "timeEnd", - "trace" - ], - "no-empty": false, - "no-inferrable-types": [ - true, - "ignore-params" - ], - "no-non-null-assertion": true, - "no-redundant-jsdoc": true, - "no-switch-case-fall-through": true, - "no-use-before-declare": false, - "no-var-requires": false, - "object-literal-key-quotes": [ - true, - "as-needed" - ], - "object-literal-sort-keys": false, - "ordered-imports": false, - "quotemark": [ - true, - "single" - ], - "trailing-comma": false, - "no-conflicting-lifecycle": true, - "no-host-metadata-property": true, - "no-input-rename": true, - "no-inputs-metadata-property": true, - "no-output-native": true, - "no-output-on-prefix": true, - "no-output-rename": true, - "no-outputs-metadata-property": true, - "template-banana-in-box": true, - "template-no-negated-async": true, - "use-lifecycle-interface": true, - "use-pipe-transform-interface": true - }, - "rulesDirectory": [ - "codelyzer" - ] -} From b2c47e0716b54a4b8aa2e267c305ae88ce0b749d Mon Sep 17 00:00:00 2001 From: UnchartedBull Date: Thu, 13 Feb 2020 16:21:43 +0100 Subject: [PATCH 06/10] Continued Clean-Up --- src/app/plugin-service/enclosure.service.ts | 21 +++++----- .../plugin-service/layer-progress.service.ts | 16 ++++---- src/app/plugin-service/psu-control.service.ts | 16 ++++---- .../print-control/print-control.component.ts | 40 +++++++++---------- .../printer-status.component.ts | 21 ++++++---- src/app/settings/settings.component.ts | 21 +++++----- src/app/standby/standby.component.ts | 26 ++++++------ 7 files changed, 83 insertions(+), 78 deletions(-) diff --git a/src/app/plugin-service/enclosure.service.ts b/src/app/plugin-service/enclosure.service.ts index 4a5b5fa98..3b09801a7 100644 --- a/src/app/plugin-service/enclosure.service.ts +++ b/src/app/plugin-service/enclosure.service.ts @@ -11,16 +11,16 @@ import { NotificationService } from '../notification/notification.service'; providedIn: 'root', }) export class EnclosureService { - httpGETRequest: Subscription; - observable: Observable; + private httpGETRequest: Subscription; + private observable: Observable; - constructor( + public constructor( private http: HttpClient, private configService: ConfigService, private notificationService: NotificationService, ) { - this.observable = new Observable((observer: Observer) => { - timer(850, 30000).subscribe(_ => { + this.observable = new Observable((observer: Observer): void => { + timer(850, 30000).subscribe((): void => { if (this.httpGETRequest) { this.httpGETRequest.unsubscribe(); } @@ -32,14 +32,14 @@ export class EnclosureService { this.configService.getHTTPHeaders(), ) .subscribe( - (data: EnclosurePluginAPI) => { - observer.next({ + (data: EnclosurePluginAPI): void => { + observer.next(({ temperature: data.temp_sensor_temp, humidity: data.temp_sensor_humidity, unit: data.use_fahrenheit ? '°F' : '°C', - } as TemperatureReading); + } as unknown) as TemperatureReading); }, - (error: HttpErrorResponse) => { + (error: HttpErrorResponse): void => { this.notificationService.setError("Can't retrieve enclosure temperature!", error.message); }, ); @@ -53,7 +53,8 @@ export class EnclosureService { } interface EnclosurePluginAPI { - controlled_io: any; + /* eslint-disable camelcase */ + controlled_io: string; temp_sensor_address: string; temp_sensor_navbar: boolean; temp_sensor_temp: number; diff --git a/src/app/plugin-service/layer-progress.service.ts b/src/app/plugin-service/layer-progress.service.ts index 3cec02601..014f5e256 100644 --- a/src/app/plugin-service/layer-progress.service.ts +++ b/src/app/plugin-service/layer-progress.service.ts @@ -11,16 +11,16 @@ import { OctoprintLayerProgressAPI } from '../octoprint-api/layerProgressAPI'; providedIn: 'root', }) export class LayerProgressService { - httpGETRequest: Subscription; - observable: Observable; + private httpGETRequest: Subscription; + private observable: Observable; - constructor( + public constructor( private configService: ConfigService, private notificationService: NotificationService, private http: HttpClient, ) { - this.observable = new Observable((observer: Observer) => { - timer(1000, this.configService.getAPIPollingInterval()).subscribe(_ => { + this.observable = new Observable((observer: Observer): void => { + timer(1000, this.configService.getAPIPollingInterval()).subscribe((): void => { if (this.httpGETRequest) { this.httpGETRequest.unsubscribe(); } @@ -30,7 +30,7 @@ export class LayerProgressService { this.configService.getHTTPHeaders(), ) .subscribe( - (data: OctoprintLayerProgressAPI) => { + (data: OctoprintLayerProgressAPI): void => { observer.next({ current: data.layer.current === '-' ? 0 : Number(data.layer.current) + 1, total: data.layer.total === '-' ? 0 : Number(data.layer.total) + 1, @@ -42,7 +42,7 @@ export class LayerProgressService { : data.fanSpeed.replace('%', ''), }); }, - (error: HttpErrorResponse) => { + (error: HttpErrorResponse): void => { this.notificationService.setError("Can't retrieve layer progress!", error.message); }, ); @@ -58,5 +58,5 @@ export class LayerProgressService { export interface DisplayLayerProgressAPI { current: number; total: number; - fanSpeed: number; + fanSpeed: number | string; } diff --git a/src/app/plugin-service/psu-control.service.ts b/src/app/plugin-service/psu-control.service.ts index 8bdb63d00..b7d1eeea8 100644 --- a/src/app/plugin-service/psu-control.service.ts +++ b/src/app/plugin-service/psu-control.service.ts @@ -10,15 +10,15 @@ import { JobCommand } from '../octoprint-api/jobAPI'; providedIn: 'root', }) export class PsuControlService { - httpPOSTRequest: Subscription; + private httpPOSTRequest: Subscription; - constructor( + public constructor( private configService: ConfigService, private notificationService: NotificationService, private http: HttpClient, ) {} - public changePSUState(on: boolean) { + public changePSUState(on: boolean): void { if (this.httpPOSTRequest) { this.httpPOSTRequest.unsubscribe(); } @@ -28,14 +28,14 @@ export class PsuControlService { this.httpPOSTRequest = this.http .post(this.configService.getURL('plugin/psucontrol'), psuPayload, this.configService.getHTTPHeaders()) .subscribe( - () => null, - (error: HttpErrorResponse) => { + (): void => null, + (error: HttpErrorResponse): void => { this.notificationService.setError("Can't control PSU!", error.message); }, ); } - public togglePSU() { + public togglePSU(): void { if (this.httpPOSTRequest) { this.httpPOSTRequest.unsubscribe(); } @@ -45,8 +45,8 @@ export class PsuControlService { this.httpPOSTRequest = this.http .post(this.configService.getURL('plugin/psucontrol'), psuPayload, this.configService.getHTTPHeaders()) .subscribe( - () => null, - (error: HttpErrorResponse) => { + (): void => null, + (error: HttpErrorResponse): void => { this.notificationService.setError("Can't control PSU!", error.message); }, ); diff --git a/src/app/print-control/print-control.component.ts b/src/app/print-control/print-control.component.ts index 8f0ce39d7..72d77005b 100644 --- a/src/app/print-control/print-control.component.ts +++ b/src/app/print-control/print-control.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { take } from 'rxjs/operators'; import { JobService } from '../job.service'; @@ -9,7 +9,7 @@ import { PrinterService, PrinterStatusAPI } from '../printer.service'; templateUrl: './print-control.component.html', styleUrls: ['./print-control.component.scss'], }) -export class PrintControlComponent implements OnInit { +export class PrintControlComponent { public showControls = false; public controlView = ControlView; public view = ControlView.MAIN; @@ -19,18 +19,16 @@ export class PrintControlComponent implements OnInit { public feedrate; public flowrate; - constructor(private jobService: JobService, private printerService: PrinterService) {} + public constructor(private jobService: JobService, private printerService: PrinterService) {} - ngOnInit() {} - - public cancel(event) { + public cancel(event): void { if (this.showControls) { this.stopPropagation(event); this.view = ControlView.CANCEL; } } - public pause(event) { + public pause(event): void { if (this.showControls) { this.stopPropagation(event); this.jobService.pauseJob(); @@ -38,51 +36,51 @@ export class PrintControlComponent implements OnInit { } } - public adjust(event) { + public adjust(event): void { if (this.showControls) { this.view = ControlView.ADJUST; this.stopPropagation(event); } } - public stopPropagation(event) { + public stopPropagation(event): void { if (this.showControls) { event.stopPropagation(); } } - public showControlOverlay(event?) { + public showControlOverlay(event?): void { this.stopPropagation(event); this.loadData(); this.view = ControlView.MAIN; this.showControls = true; } - public hideControlOverlay(event) { + public hideControlOverlay(event): void { this.stopPropagation(event); this.showControls = false; } - public cancelPrint(event) { + public cancelPrint(event): void { if (this.showControls && this.view === ControlView.CANCEL) { this.jobService.cancelJob(); this.hideControlOverlay(event); } } - public resume(event) { + public resume(event): void { if (this.showControls && this.view === ControlView.PAUSE) { this.jobService.resumeJob(); this.hideControlOverlay(event); } } - public backToControlScreen(event) { + public backToControlScreen(event): void { this.view = ControlView.MAIN; this.stopPropagation(event); } - private loadData() { + private loadData(): void { this.temperatureHotend = '?'; this.temperatureHeatbed = '?'; this.flowrate = 100; @@ -90,13 +88,13 @@ export class PrintControlComponent implements OnInit { this.printerService .getObservable() .pipe(take(1)) - .subscribe((printerStatus: PrinterStatusAPI) => { + .subscribe((printerStatus: PrinterStatusAPI): void => { this.temperatureHotend = printerStatus.nozzle.set; this.temperatureHeatbed = printerStatus.heatbed.set; }); } - public changeTemperatureHotend(value: number) { + public changeTemperatureHotend(value: number): void { this.temperatureHotend += value; if (this.temperatureHotend < 0) { this.temperatureHotend = 0; @@ -106,7 +104,7 @@ export class PrintControlComponent implements OnInit { } } - public changeTemperatureHeatbed(value: number) { + public changeTemperatureHeatbed(value: number): void { this.temperatureHeatbed += value; if (this.temperatureHeatbed < 0) { this.temperatureHeatbed = 0; @@ -116,7 +114,7 @@ export class PrintControlComponent implements OnInit { } } - public changeFeedrate(value: number) { + public changeFeedrate(value: number): void { this.feedrate += value; if (this.feedrate < 50) { this.feedrate = 50; @@ -126,7 +124,7 @@ export class PrintControlComponent implements OnInit { } } - public changeFlowrate(value: number) { + public changeFlowrate(value: number): void { this.flowrate += value; if (this.flowrate < 75) { this.flowrate = 75; @@ -136,7 +134,7 @@ export class PrintControlComponent implements OnInit { } } - public setAdjustParameters(event) { + public setAdjustParameters(event): void { this.printerService.setTemperatureHotend(this.temperatureHotend); this.printerService.setTemperatureHeatbed(this.temperatureHeatbed); this.printerService.setFeedrate(this.feedrate); diff --git a/src/app/printer-status/printer-status.component.ts b/src/app/printer-status/printer-status.component.ts index 94bc01a0b..4ebba2e98 100644 --- a/src/app/printer-status/printer-status.component.ts +++ b/src/app/printer-status/printer-status.component.ts @@ -14,7 +14,10 @@ export class PrinterStatusComponent implements OnInit, OnDestroy { public printerStatus: PrinterStatus; public status: string; - constructor(private printerService: PrinterService, private displayLayerProgressService: LayerProgressService) { + public constructor( + private printerService: PrinterService, + private displayLayerProgressService: LayerProgressService, + ) { this.printerStatus = { nozzle: { current: 0, @@ -29,9 +32,9 @@ export class PrinterStatusComponent implements OnInit, OnDestroy { this.status = 'connecting'; } - ngOnInit() { + public ngOnInit(): void { this.subscriptions.add( - this.printerService.getObservable().subscribe((printerStatus: PrinterStatusAPI) => { + this.printerService.getObservable().subscribe((printerStatus: PrinterStatusAPI): void => { this.printerStatus.nozzle = printerStatus.nozzle; this.printerStatus.heatbed = printerStatus.heatbed; this.status = printerStatus.status; @@ -39,13 +42,15 @@ export class PrinterStatusComponent implements OnInit, OnDestroy { ); this.subscriptions.add( - this.displayLayerProgressService.getObservable().subscribe((layerProgress: DisplayLayerProgressAPI) => { - this.printerStatus.fan = layerProgress.fanSpeed; - }), + this.displayLayerProgressService + .getObservable() + .subscribe((layerProgress: DisplayLayerProgressAPI): void => { + this.printerStatus.fan = layerProgress.fanSpeed; + }), ); } - ngOnDestroy() { + public ngOnDestroy(): void { this.subscriptions.unsubscribe(); } } @@ -53,5 +58,5 @@ export class PrinterStatusComponent implements OnInit, OnDestroy { export interface PrinterStatus { nozzle: PrinterValue; heatbed: PrinterValue; - fan: number; + fan: number | string; } diff --git a/src/app/settings/settings.component.ts b/src/app/settings/settings.component.ts index ae5afcb25..a1c76d1dc 100644 --- a/src/app/settings/settings.component.ts +++ b/src/app/settings/settings.component.ts @@ -10,12 +10,12 @@ import { NotificationService } from '../notification/notification.service'; styleUrls: ['./settings.component.scss'], }) export class SettingsComponent implements OnInit { - @Output() closeFunction = new EventEmitter(); - @ViewChild('settingsMain') settingsMain: ElementRef; - @ViewChild('settingsGeneral') settingsGeneral: ElementRef; - @ViewChild('settingsOctoDash') settingsOctoDash: ElementRef; - @ViewChild('settingsPlugins') settingsPlugins: ElementRef; - @ViewChild('settingsCredits') settingsCredits: ElementRef; + @Output() private closeFunction = new EventEmitter(); + @ViewChild('settingsMain') private settingsMain: ElementRef; + @ViewChild('settingsGeneral') private settingsGeneral: ElementRef; + @ViewChild('settingsOctoDash') private settingsOctoDash: ElementRef; + @ViewChild('settingsPlugins') private settingsPlugins: ElementRef; + @ViewChild('settingsCredits') private settingsCredits: ElementRef; public fadeOutAnimation = false; public config: Config; @@ -30,6 +30,7 @@ export class SettingsComponent implements OnInit { public version: string; private overwriteNoSave = false; private pages = []; + // eslint-disable-next-line @typescript-eslint/no-explicit-any private ipc: any; public constructor( @@ -52,7 +53,7 @@ export class SettingsComponent implements OnInit { } } - private getVersion() { + private getVersion(): void { this.version = this.service.getVersion(); if (this.version === undefined) { setTimeout(this.getVersion.bind(this), 3500); @@ -60,7 +61,7 @@ export class SettingsComponent implements OnInit { } public ngOnInit(): void { - setTimeout(() => { + setTimeout((): void => { this.pages = [ this.settingsMain.nativeElement, this.settingsGeneral.nativeElement, @@ -78,7 +79,7 @@ export class SettingsComponent implements OnInit { ) { this.fadeOutAnimation = true; this.closeFunction.emit(); - setTimeout(() => { + setTimeout((): void => { this.fadeOutAnimation = false; }, 800); } else { @@ -95,7 +96,7 @@ export class SettingsComponent implements OnInit { this.pages[page].classList.remove('settings__content-inactive'); this.pages[page].classList.add('settings__content-slidein-' + direction); - setTimeout(() => { + setTimeout((): void => { this.pages[current].classList.add('settings__content-inactive'); this.pages[current].classList.remove('settings__content-slideout-' + direction); this.pages[page].classList.remove('settings__content-slidein-' + direction); diff --git a/src/app/standby/standby.component.ts b/src/app/standby/standby.component.ts index be0929dfb..ddcfb2eef 100644 --- a/src/app/standby/standby.component.ts +++ b/src/app/standby/standby.component.ts @@ -1,4 +1,4 @@ -import { HttpClient, HttpErrorResponse } from '@angular/common/http'; +import { HttpClient } from '@angular/common/http'; import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; @@ -18,7 +18,7 @@ export class StandbyComponent implements OnInit { public error = ''; private connectionRetries = 3; - constructor( + public constructor( private configService: ConfigService, private http: HttpClient, private router: Router, @@ -27,13 +27,13 @@ export class StandbyComponent implements OnInit { private psuControlService: PsuControlService, ) {} - ngOnInit() { + public ngOnInit(): void { if (this.configService.getAutomaticScreenSleep()) { setTimeout(this.service.turnDisplayOff.bind(this.service), 300000); } } - public reconnect() { + public reconnect(): void { this.connecting = true; if (this.configService.turnOnPSUWhenExitingSleep()) { this.psuControlService.changePSUState(true); @@ -43,22 +43,22 @@ export class StandbyComponent implements OnInit { } } - private connectToPrinter() { + private connectToPrinter(): void { this.http .post(this.configService.getURL('connection'), connectPayload, this.configService.getHTTPHeaders()) .subscribe( - () => { + (): void => { setTimeout(this.checkConnection.bind(this), 3000); }, - () => { + (): void => { this.setConnectionError(); }, ); } - private checkConnection() { + private checkConnection(): void { this.http.get(this.configService.getURL('connection'), this.configService.getHTTPHeaders()).subscribe( - (data: OctoprintConnectionAPI) => { + (data: OctoprintConnectionAPI): void => { if (data.current.state !== 'Operational') { if (this.connectionRetries === 0) { this.connectionRetries = 3; @@ -71,7 +71,7 @@ export class StandbyComponent implements OnInit { this.disableStandby(); } }, - (error: HttpErrorResponse) => { + (): void => { this.connecting = false; this.error = "There is something really wrong, OctoDash can't get a response from OctoPrint. Please check your setup!"; @@ -79,14 +79,14 @@ export class StandbyComponent implements OnInit { ); } - private setConnectionError() { + private setConnectionError(): void { this.connecting = false; this.error = "OctoPrint can't connect to your printer. Please make sure that the connection works, then come back and try again."; } - private disableStandby() { - setTimeout(() => { + private disableStandby(): void { + setTimeout((): void => { this.connecting = false; if (this.configService.getAutomaticScreenSleep()) { this.service.turnDisplayOn(); From fa3d04a1854cdf018d1650606a9b4b3f061cdfcf Mon Sep 17 00:00:00 2001 From: UnchartedBull Date: Thu, 13 Feb 2020 17:00:35 +0100 Subject: [PATCH 07/10] Fixed linter issues --- src/app/bottom-bar/bottom-bar.component.ts | 8 ++++---- src/app/config/config.service.ts | 18 ++++++++++-------- .../invalid-config/invalid-config.component.ts | 5 +++-- .../config/no-config/no-config.component.ts | 4 ++-- src/app/control/control.component.ts | 14 +++++++------- src/app/filament/filament.component.ts | 8 +++----- src/app/files/files.component.ts | 18 +++++++++--------- src/app/job-status/job-status.component.ts | 11 +++++------ .../layer-progress/layer-progress.component.ts | 16 +++++++++------- src/app/main-menu/main-menu.component.ts | 16 +++++++--------- src/app/main-screen/main-screen.component.ts | 10 ++++------ .../no-touch/main-screen-no-touch.component.ts | 8 +++----- src/app/notification/notification.component.ts | 8 ++++---- src/app/notification/notification.service.ts | 16 ++++++++-------- src/app/octoprint-api/filesAPI.ts | 2 +- src/app/octoprint-api/jobAPI.ts | 2 +- src/app/octoprint-api/printerStatusAPI.ts | 2 +- 17 files changed, 81 insertions(+), 85 deletions(-) diff --git a/src/app/bottom-bar/bottom-bar.component.ts b/src/app/bottom-bar/bottom-bar.component.ts index 06bf2e8cf..75fa6570c 100644 --- a/src/app/bottom-bar/bottom-bar.component.ts +++ b/src/app/bottom-bar/bottom-bar.component.ts @@ -1,4 +1,4 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Component, OnDestroy } from '@angular/core'; import { Subscription } from 'rxjs'; import { ConfigService } from '../config/config.service'; @@ -15,14 +15,14 @@ export class BottomBarComponent implements OnDestroy { public printer: Printer; public enclosureTemperature: TemperatureReading; - constructor( + public constructor( private printerService: PrinterService, private configService: ConfigService, private enclosureService: EnclosureService, ) { if (this.configService.getAmbientTemperatureSensorName() !== null) { this.subscriptions.add( - this.enclosureService.getObservable().subscribe((temperatureReading: TemperatureReading) => { + this.enclosureService.getObservable().subscribe((temperatureReading: TemperatureReading): void => { this.enclosureTemperature = temperatureReading; }), ); @@ -34,7 +34,7 @@ export class BottomBarComponent implements OnDestroy { status: 'connecting ...', }; this.subscriptions.add( - this.printerService.getObservable().subscribe((printerStatus: PrinterStatusAPI) => { + this.printerService.getObservable().subscribe((printerStatus: PrinterStatusAPI): void => { this.printer.status = printerStatus.status; }), ); diff --git a/src/app/config/config.service.ts b/src/app/config/config.service.ts index c085e4cee..ff3cd71fa 100644 --- a/src/app/config/config.service.ts +++ b/src/app/config/config.service.ts @@ -4,11 +4,12 @@ import Ajv from 'ajv'; import _ from 'lodash'; import { environment } from '../../environments/environment'; -import { DisplayLayerProgressAPI } from '../plugin-service/layer-progress.service'; declare global { interface Window { + // eslint-disable-next-line @typescript-eslint/no-explicit-any require: any; + // eslint-disable-next-line @typescript-eslint/no-explicit-any process: any; } } @@ -17,6 +18,7 @@ declare global { providedIn: 'root', }) export class ConfigService { + // eslint-disable-next-line @typescript-eslint/no-explicit-any private store: any | undefined; private validator: Ajv.ValidateFunction; @@ -27,7 +29,7 @@ export class ConfigService { private httpHeaders: object; - constructor(private http: HttpClient) { + public constructor(private http: HttpClient) { const ajv = new Ajv({ allErrors: true }); this.validator = ajv.compile(schema); if (window && window.process && window.process.type) { @@ -38,7 +40,7 @@ export class ConfigService { console.warn( 'Detected non-electron environment. Fallback to assets/config.json. Any changes are non-persistent!', ); - this.http.get(environment.config).subscribe((config: Config) => { + this.http.get(environment.config).subscribe((config: Config): void => { this.initialize(config); }); } @@ -82,7 +84,7 @@ export class ConfigService { public getErrors(): string[] { const errors = []; - this.validator.errors.forEach(error => { + this.validator.errors.forEach((error): void => { if (error.keyword === 'type') { errors.push(`${error.dataPath} ${error.message}`); } else { @@ -109,14 +111,14 @@ export class ConfigService { } } - public updateConfig() { + public updateConfig(): void { if (window && window.process && window.process.type) { this.update = false; this.initialize(this.store.get('config')); } } - public revertConfigForInput(config: Config) { + public revertConfigForInput(config: Config): Config { config.octoprint.urlSplit = { url: config.octoprint.url.split(':')[1].replace('//', ''), port: parseInt(config.octoprint.url.split(':')[2].replace('/api/', ''), 10), @@ -127,7 +129,7 @@ export class ConfigService { return config; } - public createConfigFromInput(config: Config) { + public createConfigFromInput(config: Config): Config { const configOut = _.cloneDeep(config); configOut.octoprint.url = `http://${configOut.octoprint.urlSplit.url}:${configOut.octoprint.urlSplit.port}/api/`; delete configOut.octoprint.urlSplit; @@ -146,7 +148,7 @@ export class ConfigService { return this.httpHeaders; } - public getURL(path: string) { + public getURL(path: string): string { return this.config.octoprint.url + path; } diff --git a/src/app/config/invalid-config/invalid-config.component.ts b/src/app/config/invalid-config/invalid-config.component.ts index 93571172a..95d8f9620 100644 --- a/src/app/config/invalid-config/invalid-config.component.ts +++ b/src/app/config/invalid-config/invalid-config.component.ts @@ -8,8 +8,9 @@ import { ConfigService } from '../config.service'; styleUrls: ['./invalid-config.component.scss'], }) export class InvalidConfigComponent implements OnInit { - errors: string[]; - constructor(private configService: ConfigService) {} + public errors: string[]; + + public constructor(private configService: ConfigService) {} public ngOnInit(): void { this.errors = this.configService.getErrors(); diff --git a/src/app/config/no-config/no-config.component.ts b/src/app/config/no-config/no-config.component.ts index 8dc362010..74831ad19 100644 --- a/src/app/config/no-config/no-config.component.ts +++ b/src/app/config/no-config/no-config.component.ts @@ -136,11 +136,11 @@ export class NoConfigComponent implements OnInit { }), }; this.http.get(this.config.octoprint.url + 'version', httpHeaders).subscribe( - () => { + (): void => { this.octoprintConnection = true; this.saveConfig(); }, - (error: HttpErrorResponse) => { + (error: HttpErrorResponse): void => { this.octoprintConnection = false; this.octoprintConnectionError = error.message; }, diff --git a/src/app/control/control.component.ts b/src/app/control/control.component.ts index 65b831dec..cd32b18b1 100644 --- a/src/app/control/control.component.ts +++ b/src/app/control/control.component.ts @@ -1,4 +1,4 @@ -import { Component, SecurityContext } from '@angular/core'; +import { Component } from '@angular/core'; import { SafeResourceUrl } from '@angular/platform-browser'; import { Router } from '@angular/router'; @@ -19,7 +19,7 @@ export class ControlComponent { public iFrameURL: SafeResourceUrl = 'about:blank'; public actionToConfirm: ActionToConfirm; - constructor( + public constructor( private printerService: PrinterService, private octoprintService: OctoprintService, private configService: ConfigService, @@ -38,7 +38,7 @@ export class ControlComponent { this.printerService.jog(axis === 'x' ? distance : 0, axis === 'y' ? distance : 0, axis === 'z' ? distance : 0); } - public doAction(command: string, exit: boolean, confirm: boolean) { + public doAction(command: string, exit: boolean, confirm: boolean): void { console.log(command, exit, confirm); if (confirm) { this.actionToConfirm = { @@ -53,14 +53,14 @@ export class ControlComponent { } } - public doActionConfirm() { + public doActionConfirm(): void { this.executeGCode(this.actionToConfirm.command); if (this.actionToConfirm.exit) { this.router.navigate(['/main-screen']); } } - public doActionNoConfirm() { + public doActionNoConfirm(): void { this.actionToConfirm = null; } @@ -140,7 +140,7 @@ export class ControlComponent { this.iFrameURL = url; const iFrameDOM = document.getElementById('iFrame'); iFrameDOM.style.display = 'block'; - setTimeout(() => { + setTimeout((): void => { iFrameDOM.style.opacity = '1'; }, 50); } @@ -148,7 +148,7 @@ export class ControlComponent { public hideIFrame(): void { const iFrameDOM = document.getElementById('iFrame'); iFrameDOM.style.opacity = '0'; - setTimeout(() => { + setTimeout((): void => { iFrameDOM.style.display = 'none'; this.iFrameURL = 'about:blank'; }, 500); diff --git a/src/app/filament/filament.component.ts b/src/app/filament/filament.component.ts index 160459637..48d61208c 100644 --- a/src/app/filament/filament.component.ts +++ b/src/app/filament/filament.component.ts @@ -1,12 +1,10 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; @Component({ selector: 'app-filament', templateUrl: './filament.component.html', styleUrls: ['./filament.component.scss'], }) -export class FilamentComponent implements OnInit { - constructor() {} - - public ngOnInit(): void {} +export class FilamentComponent { + public constructor() {} } diff --git a/src/app/files/files.component.ts b/src/app/files/files.component.ts index a5c4e1668..1b19c3f5a 100644 --- a/src/app/files/files.component.ts +++ b/src/app/files/files.component.ts @@ -35,28 +35,28 @@ export class FilesComponent { .then((data): void => { this.fileDetail = data; }) - .catch((err): void => { + .catch(({}): void => { this.fileDetail = ({ name: 'error' } as unknown) as File; }); const fileDOMElement = document.getElementById('fileDetailView'); fileDOMElement.style.display = 'block'; - setTimeout(() => { + setTimeout((): void => { fileDOMElement.style.opacity = '1'; }, 50); } public openFolder(folderPath: string): void { - setTimeout(() => { + setTimeout((): void => { this.showLoader(); this.folderContent = []; this.filesService .getFolder(folderPath) - .then(data => { + .then((data): void => { this.folderContent = data; this.currentFolder = folderPath; this.spinner.hide(); }) - .catch(err => { + .catch(({}): void => { this.folderContent = null; this.currentFolder = folderPath; this.spinner.hide(); @@ -67,14 +67,14 @@ export class FilesComponent { public closeDetails(): void { const fileDOMElement = document.getElementById('fileDetailView'); fileDOMElement.style.opacity = '0'; - setTimeout(() => { + setTimeout((): void => { fileDOMElement.style.display = 'none'; this.fileDetail = null; }, 500); } public loadFile(filePath: string): void { - setTimeout(() => { + setTimeout((): void => { this.filesService.loadFile(filePath); this.service.setLoadedFile(true); this.jobService.deleteJobInformation(); @@ -83,14 +83,14 @@ export class FilesComponent { } public printFile(filePath: string): void { - setTimeout(() => { + setTimeout((): void => { this.filesService.printFile(filePath); this.router.navigate(['/main-screen']); }, 300); } public deleteFile(filePath: string): void { - setTimeout(() => { + setTimeout((): void => { this.filesService.deleteFile(filePath); this.closeDetails(); this.openFolder(this.currentFolder); diff --git a/src/app/job-status/job-status.component.ts b/src/app/job-status/job-status.component.ts index 6d2b9cf3b..4049e630a 100644 --- a/src/app/job-status/job-status.component.ts +++ b/src/app/job-status/job-status.component.ts @@ -3,7 +3,6 @@ import { Subscription } from 'rxjs'; import { AppService } from '../app.service'; import { Job, JobService } from '../job.service'; -import { NotificationService } from '../notification/notification.service'; @Component({ selector: 'app-job-status', @@ -14,13 +13,13 @@ export class JobStatusComponent implements OnInit, OnDestroy { private subscriptions: Subscription = new Subscription(); public job: Job; - constructor(private jobService: JobService, private service: AppService) {} + public constructor(private jobService: JobService, private service: AppService) {} - ngOnInit() { - this.subscriptions.add(this.jobService.getObservable().subscribe((job: Job) => (this.job = job))); + public ngOnInit(): void { + this.subscriptions.add(this.jobService.getObservable().subscribe((job: Job): Job => (this.job = job))); } - ngOnDestroy() { + public ngOnDestroy(): void { this.subscriptions.unsubscribe(); } @@ -38,7 +37,7 @@ export class JobStatusComponent implements OnInit, OnDestroy { public startJob(): void { this.jobService.startJob(); - setTimeout(() => { + setTimeout((): void => { this.service.setLoadedFile(false); }, 5000); } diff --git a/src/app/layer-progress/layer-progress.component.ts b/src/app/layer-progress/layer-progress.component.ts index 143771a82..7c0e2f779 100644 --- a/src/app/layer-progress/layer-progress.component.ts +++ b/src/app/layer-progress/layer-progress.component.ts @@ -12,23 +12,25 @@ export class LayerProgressComponent implements OnInit, OnDestroy { private subscriptions: Subscription = new Subscription(); public layerProgress: LayerProgress; - constructor(private displayLayerProgressService: LayerProgressService) { + public constructor(private displayLayerProgressService: LayerProgressService) { this.layerProgress = { current: 0, total: 0, }; } - ngOnInit() { + public ngOnInit(): void { this.subscriptions.add( - this.displayLayerProgressService.getObservable().subscribe((layerProgress: DisplayLayerProgressAPI) => { - this.layerProgress.current = layerProgress.current; - this.layerProgress.total = layerProgress.total; - }), + this.displayLayerProgressService + .getObservable() + .subscribe((layerProgress: DisplayLayerProgressAPI): void => { + this.layerProgress.current = layerProgress.current; + this.layerProgress.total = layerProgress.total; + }), ); } - ngOnDestroy() { + public ngOnDestroy(): void { this.subscriptions.unsubscribe(); } } diff --git a/src/app/main-menu/main-menu.component.ts b/src/app/main-menu/main-menu.component.ts index 48d28f2b9..1155a7936 100644 --- a/src/app/main-menu/main-menu.component.ts +++ b/src/app/main-menu/main-menu.component.ts @@ -1,24 +1,22 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; @Component({ selector: 'app-main-menu', templateUrl: './main-menu.component.html', styleUrls: ['./main-menu.component.scss'], }) -export class MainMenuComponent implements OnInit { +export class MainMenuComponent { public settings = false; - public showSettings() { + public constructor() {} + + public showSettings(): void { this.settings = true; } - public hideSettings() { - setTimeout(() => { + public hideSettings(): void { + setTimeout((): void => { this.settings = false; }, 600); } - - constructor() {} - - ngOnInit() {} } diff --git a/src/app/main-screen/main-screen.component.ts b/src/app/main-screen/main-screen.component.ts index 7edca3c70..e9b196ead 100644 --- a/src/app/main-screen/main-screen.component.ts +++ b/src/app/main-screen/main-screen.component.ts @@ -1,9 +1,7 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; -import { Subscription } from 'rxjs'; -import { connectableObservableDescriptor } from 'rxjs/internal/observable/ConnectableObservable'; +import { Component } from '@angular/core'; import { AppService } from '../app.service'; -import { Job, JobService } from '../job.service'; +import { JobService } from '../job.service'; @Component({ selector: 'app-main-screen', @@ -13,9 +11,9 @@ import { Job, JobService } from '../job.service'; export class MainScreenComponent { public printing = false; - constructor(private jobService: JobService, private service: AppService) {} + public constructor(private jobService: JobService, private service: AppService) {} - public isPrinting() { + public isPrinting(): boolean { return this.jobService.isPrinting(); } diff --git a/src/app/main-screen/no-touch/main-screen-no-touch.component.ts b/src/app/main-screen/no-touch/main-screen-no-touch.component.ts index f64f16516..50a3ded45 100644 --- a/src/app/main-screen/no-touch/main-screen-no-touch.component.ts +++ b/src/app/main-screen/no-touch/main-screen-no-touch.component.ts @@ -1,12 +1,10 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; @Component({ selector: 'app-main-screen-no-touch', templateUrl: './main-screen-no-touch.component.html', styleUrls: ['./main-screen-no-touch.component.scss'], }) -export class MainScreenNoTouchComponent implements OnInit { - constructor() {} - - ngOnInit() {} +export class MainScreenNoTouchComponent { + public constructor() {} } diff --git a/src/app/notification/notification.component.ts b/src/app/notification/notification.component.ts index b3ad246b1..25f8506fa 100644 --- a/src/app/notification/notification.component.ts +++ b/src/app/notification/notification.component.ts @@ -22,20 +22,20 @@ export class NotificationComponent implements OnDestroy { this.subscriptions.add( this.notificationService .getObservable() - .subscribe((message: Notification) => this.setNotification(message)), + .subscribe((message: Notification): void => this.setNotification(message)), ); } - public hideNotification() { + public hideNotification(): void { this.show = false; } - public setNotification(notification: Notification) { + public setNotification(notification: Notification): void { this.notification = notification; this.show = true; } - public ngOnDestroy() { + public ngOnDestroy(): void { this.subscriptions.unsubscribe(); } } diff --git a/src/app/notification/notification.service.ts b/src/app/notification/notification.service.ts index b6299cacf..f6a8134d8 100644 --- a/src/app/notification/notification.service.ts +++ b/src/app/notification/notification.service.ts @@ -10,39 +10,39 @@ export class NotificationService { private observer: Observer; private hideNotifications = false; - constructor() { - this.observable = new Observable((observer: Observer) => { + public constructor() { + this.observable = new Observable((observer: Observer): void => { this.observer = observer; }).pipe(shareReplay(1)); } - enableNotifications() { + public enableNotifications(): void { // console.clear(); this.hideNotifications = false; } - disableNotifications() { + public disableNotifications(): void { // console.clear(); this.hideNotifications = true; } - setError(heading: string, text: string) { + public setError(heading: string, text: string): void { if (!this.hideNotifications) { this.observer.next({ heading, text, type: 'error' }); } } - setWarning(heading: string, text: string) { + public setWarning(heading: string, text: string): void { if (!this.hideNotifications) { this.observer.next({ heading, text, type: 'warn' }); } } - setUpdate(heading: string, text: string) { + public setUpdate(heading: string, text: string): void { this.observer.next({ heading, text, type: 'update' }); } - getObservable() { + public getObservable(): Observable { return this.observable; } } diff --git a/src/app/octoprint-api/filesAPI.ts b/src/app/octoprint-api/filesAPI.ts index e899264f1..264e82fe5 100644 --- a/src/app/octoprint-api/filesAPI.ts +++ b/src/app/octoprint-api/filesAPI.ts @@ -10,7 +10,7 @@ export interface OctoprintFilesAPI { prints: OctoprintPrints; refs: OctoprintRefs; size: number; - statistics?: any; + statistics?: object; type: string; typePath: [string]; } diff --git a/src/app/octoprint-api/jobAPI.ts b/src/app/octoprint-api/jobAPI.ts index 9f47cb4f6..633b643ee 100644 --- a/src/app/octoprint-api/jobAPI.ts +++ b/src/app/octoprint-api/jobAPI.ts @@ -28,7 +28,7 @@ export interface OctoprintFilament { tool3?: OctoprintFilamentValues; tool4?: OctoprintFilamentValues; tool5?: OctoprintFilamentValues; - [key: string]: any; + [key: string]: OctoprintFilamentValues; } interface OctoprintFilamentValues { diff --git a/src/app/octoprint-api/printerStatusAPI.ts b/src/app/octoprint-api/printerStatusAPI.ts index f0d60d047..10501e331 100644 --- a/src/app/octoprint-api/printerStatusAPI.ts +++ b/src/app/octoprint-api/printerStatusAPI.ts @@ -12,7 +12,7 @@ interface OctoprintTemperature { tool4?: OctoprintTemperatureData; tool5?: OctoprintTemperatureData; bed?: OctoprintTemperatureData; - [key: string]: any; + [key: string]: OctoprintTemperatureData; } interface OctoprintTemperatureData { From 8af64799fa9399d577c07caa71d2c6376baa4447 Mon Sep 17 00:00:00 2001 From: UnchartedBull Date: Thu, 13 Feb 2020 17:09:34 +0100 Subject: [PATCH 08/10] Fix null for port value --- src/app/config/config.service.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/app/config/config.service.ts b/src/app/config/config.service.ts index ff3cd71fa..bf33e5b70 100644 --- a/src/app/config/config.service.ts +++ b/src/app/config/config.service.ts @@ -131,7 +131,11 @@ export class ConfigService { public createConfigFromInput(config: Config): Config { const configOut = _.cloneDeep(config); - configOut.octoprint.url = `http://${configOut.octoprint.urlSplit.url}:${configOut.octoprint.urlSplit.port}/api/`; + if (config.octoprint.urlSplit.port !== null || !isNaN(config.octoprint.urlSplit.port)) { + configOut.octoprint.url = `http://${config.octoprint.urlSplit.url}:${config.octoprint.urlSplit.port}/api/`; + } else { + configOut.octoprint.url = `http://${config.octoprint.urlSplit.url}/api/`; + } delete configOut.octoprint.urlSplit; return configOut; } From eab5e852c12aa31aff0c75471258aca12d7b15f1 Mon Sep 17 00:00:00 2001 From: UnchartedBull Date: Mon, 17 Feb 2020 15:38:54 +0100 Subject: [PATCH 09/10] Fix saving issue --- main.js | 96 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 50 insertions(+), 46 deletions(-) diff --git a/main.js b/main.js index 6f1ddb29f..35971f774 100644 --- a/main.js +++ b/main.js @@ -1,58 +1,56 @@ -const { - app, - BrowserWindow -} = require("electron"); -const url = require('url') -const path = require('path') +/* eslint-disable @typescript-eslint/no-var-requires */ +const { app, BrowserWindow } = require('electron'); +const url = require('url'); +const path = require('path'); const Store = require('electron-store'); + const store = new Store(); const exec = require('child_process').exec; -const { - ipcMain -} = require('electron') +const { ipcMain } = require('electron'); const args = process.argv.slice(1); const dev = args.some(val => val === '--serve'); -const big = args.some(val => val === '--big') +const big = args.some(val => val === '--big'); app.commandLine.appendSwitch('touch-events', 'enabled'); let window; function createWindow() { - config = store.get("config"); - store.onDidChange("config", (newValue) => { - config = newValue - }) - - const { - screen - } = require('electron') + config = store.get('config'); + store.onDidChange('config', newValue => { + config = newValue; + }); + + const { screen } = require('electron'); const mainScreen = screen.getPrimaryDisplay(); window = new BrowserWindow({ - width: dev ? big ? 1400 : 1080 : mainScreen.size.width, - height: dev ? big ? 502 : 342 : mainScreen.size.height, + width: dev ? (big ? 1400 : 1080) : mainScreen.size.width, + height: dev ? (big ? 502 : 342) : mainScreen.size.height, frame: dev ? true : false, backgroundColor: '#353b48', webPreferences: { - nodeIntegration: true + nodeIntegration: true, + webSecurity: false, }, - icon: path.join(__dirname, 'src/assets/icon.png') - }) + icon: path.join(__dirname, 'src/assets/icon.png'), + }); if (dev) { require('electron-reload')(__dirname, { - electron: require(`${__dirname}/node_modules/electron`) + electron: require(`${__dirname}/node_modules/electron`), }); window.loadURL('http://localhost:4200'); window.webContents.openDevTools(); } else { - window.loadURL(url.format({ - pathname: path.join(__dirname, 'dist/index.html'), - protocol: 'file:', - slashes: true - })); - window.setFullScreen(true) + window.loadURL( + url.format({ + pathname: path.join(__dirname, 'dist/index.html'), + protocol: 'file:', + slashes: true, + }), + ); + window.setFullScreen(true); } setTimeout(sendVersionInfo, 30 * 1000); @@ -65,34 +63,40 @@ function createWindow() { } function activateScreenSleepListener() { - ipcMain.on("screenSleep", () => { - exec('xset dpms force standby') - }) + ipcMain.on('screenSleep', () => { + exec('xset dpms force standby'); + }); - ipcMain.on("screenWakeup", () => { - exec('xset -dpms') - }) + ipcMain.on('screenWakeup', () => { + exec('xset -dpms'); + }); } function activateReloadListener() { - ipcMain.on("reload", () => { - window.reload() - }) + ipcMain.on('reload', () => { + window.loadURL( + url.format({ + pathname: path.join(__dirname, 'dist/index.html'), + protocol: 'file:', + slashes: true, + }), + ); + }); } function sendVersionInfo() { - window.webContents.send("versionInformation", { - version: app.getVersion() - }) + window.webContents.send('versionInformation', { + version: app.getVersion(), + }); } -app.on('ready', createWindow) +app.on('ready', createWindow); -app.on("window-all-closed", () => { - app.quit() +app.on('window-all-closed', () => { + app.quit(); }); -app.on("activate", () => { +app.on('activate', () => { if (window === null) { createWindow(); } From f4ce07176f6a79ef23a2c2e38fe19ffdaf8e8f9d Mon Sep 17 00:00:00 2001 From: UnchartedBull Date: Tue, 18 Feb 2020 10:09:52 +0100 Subject: [PATCH 10/10] Fix CI pipeline --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4fd778a0c..54e8bc31f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,7 @@ jobs: - stage: lint if: branch = master name: "Linting Application ..." - script: ng lint + script: npm run lint - stage: build if: type = push AND branch != master OR type = pull_request name: "Building Application ..."