diff --git a/.editorconfig b/.editorconfig index b585a761..4e5c9337 100644 --- a/.editorconfig +++ b/.editorconfig @@ -11,3 +11,7 @@ trim_trailing_whitespace = true [*.md] max_line_length = off trim_trailing_whitespace = false + +[*.yaml] +indent_size = 2 + diff --git a/.eslintrc.json b/.eslintrc.json index 4151e9e9..ac803e7b 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,61 +1,46 @@ { - "root": true, - "ignorePatterns": [ - "projects/**/*" - ], - "overrides": [ - { - "files": [ - "*.ts" - ], - "parserOptions": { - "project": [ - "tsconfig.json", - "e2e/tsconfig.json" - ], - "createDefaultProgram": true - }, - "extends": [ - "plugin:@angular-eslint/recommended", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/component-selector": [ - "error", - { - "prefix": "app", - "style": "kebab-case", - "type": "element" - } - ], - "@angular-eslint/directive-selector": [ - "error", - { - "prefix": "app", - "style": "camelCase", - "type": "attribute" - } - ], - "@angular-eslint/component-class-suffix": [ - "error", - { - "suffixes": [ - "Page", - "Component", - "Dialog" - ] - } - ] - } - }, - { - "files": [ - "*.html" - ], - "extends": [ - "plugin:@angular-eslint/template/recommended" - ], - "rules": { } - } - ] + "root": true, + "ignorePatterns": ["projects/**/*"], + "overrides": [ + { + "files": ["*.ts"], + "parserOptions": { + "project": ["tsconfig.json", "e2e/tsconfig.json"], + "createDefaultProgram": true + }, + "extends": [ + "plugin:@angular-eslint/recommended", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "rules": { + "@angular-eslint/component-selector": [ + "error", + { + "prefix": "app", + "style": "kebab-case", + "type": "element" + } + ], + "@angular-eslint/directive-selector": [ + "error", + { + "prefix": "app", + "style": "camelCase", + "type": "attribute" + } + ], + "@angular-eslint/component-class-suffix": [ + "error", + { + "suffixes": ["Page", "Component", "Dialog"] + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@angular-eslint/template/recommended"], + "rules": {} + } + ] } diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index 5a51f7a6..7bfc08fe 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -53,7 +53,7 @@ jobs: - name: Clean up old images uses: actions/delete-package-versions@v5 with: - package-name: 'leaphy-webbased/leaphy-webbased' - package-type: 'container' + package-name: "leaphy-webbased/leaphy-webbased" + package-type: "container" min-versions-to-keep: 5 - delete-only-untagged-versions: 'true' + delete-only-untagged-versions: "true" diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 780c68c0..48c8ec87 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -1,29 +1,33 @@ name: Playwright Tests on: - pull_request: - branches: [ main, master ] + pull_request: + branches: [main, master] jobs: - test: - timeout-minutes: 60 - runs-on: ubuntu-latest - container: - image: mcr.microsoft.com/playwright:v1.42.1-jammy - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: '20.x' - registry-url: 'https://registry.npmjs.org' - cache: yarn - - name: Install node modules - run: yarn --frozen-lockfile --prefer-offline - - name: Run linter - run: yarn lint - - name: Run Playwright tests - run: yarn playwright test - - uses: actions/upload-artifact@v4 - if: always() - with: - name: playwright-report - path: playwright-report/ - retention-days: 30 + test: + timeout-minutes: 60 + runs-on: ubuntu-latest + container: + image: mcr.microsoft.com/playwright:v1.42.1-jammy + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "20.x" + registry-url: "https://registry.npmjs.org" + cache: yarn + - name: Install node modules + run: yarn --frozen-lockfile --prefer-offline + - name: Run linter + run: yarn lint + - name: Run ESLint + run: npx eslint . + - name: Run prettier + run: npx prettier -c ./src + - name: Run Playwright tests + run: yarn playwright test + - uses: actions/upload-artifact@v4 + if: always() + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 diff --git a/README.md b/README.md index c7a6c38d..ac798fe9 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,26 @@ # Leaphy Easybloqs ## Introduction + Leaphy Easybloqs is software to program [Leaphy Robots](https://www.leaphy.nl) and Arduino microcontrollers using a block-based programming language and a user-friendly interface. It also support programming RP2040 controllers that are able to run MicroPython. ## Contributing -We welcome PRs from anyone that wants to contribute! + +We welcome PRs from anyone that wants to contribute! ### Prerequisites The following should be installed: -- NodeJS (Version 20.X) +- NodeJS (Version 20.X) On Windows: Be sure to install the build tools by checking the box during the NodeJS installation process -- Yarn v1 +- Yarn v1 ### Running locally -First install the dependencies by running `yarn intall`. This will take a while the first time. -Then run `yarn start` to start the application. - +First install the dependencies by running `yarn intall`. This will take a while the first time. +Then run `yarn start` to start the application. ### Pull Requests @@ -30,4 +31,3 @@ Once merged, it will show up on https://testleaphyeasybloqs.com for integration All issues that involve webbased should be reported on the [Leaphy Easybloqs Webbased GitHub](https://github.com/leaphy-robotics/leaphy-webbased/issues) page. Issues that involve the blocks should be reported on the [Leaphy Blocks GitHub](https://github.com/leaphy-robotics/leaphy-blocks/issues) page. - diff --git a/angular.json b/angular.json index e1390572..046c1768 100644 --- a/angular.json +++ b/angular.json @@ -143,7 +143,7 @@ "serve": { "builder": "@angular-devkit/build-angular:dev-server", "options": { - "headers": { + "headers": { "Cross-Origin-Embedder-Policy": "require-corp", "Cross-Origin-Opener-Policy": "same-origin" }, @@ -151,17 +151,17 @@ }, "configurations": { "production": { - "buildTarget": "leaphy-client:build:production" + "buildTarget": "leaphy-client:build:production" }, "dev": { - "buildTarget": "leaphy-client:build:dev" + "buildTarget": "leaphy-client:build:dev" } } }, "extract-i18n": { "builder": "@angular-devkit/build-angular:extract-i18n", "options": { - "buildTarget": "leaphy-client:build" + "buildTarget": "leaphy-client:build" } }, "test": { @@ -170,10 +170,7 @@ "main": "src/test.ts", "tsConfig": "tsconfig.spec.json", "karmaConfig": "karma.conf.js", - "assets": [ - "src/favicon.ico", - "src/assets" - ], + "assets": ["src/favicon.ico", "src/assets"], "styles": [ "src/styles.scss", "src/theme.scss", @@ -185,10 +182,7 @@ "lint": { "builder": "@angular-eslint/builder:lint", "options": { - "lintFilePatterns": [ - "src/**/*.ts", - "src/**/*.html" - ] + "lintFilePatterns": ["src/**/*.ts", "src/**/*.html"] } }, "e2e": { @@ -210,9 +204,7 @@ } }, "cli": { - "analytics": "6d8c3839-2848-4328-b7fb-a10f9273fdfc", - "schematicCollections": [ - "@angular-eslint/schematics" - ] + "analytics": "6d8c3839-2848-4328-b7fb-a10f9273fdfc", + "schematicCollections": ["@angular-eslint/schematics"] } } diff --git a/package.json b/package.json index 83549be8..ddf24c0e 100644 --- a/package.json +++ b/package.json @@ -1,103 +1,104 @@ { - "name": "leaphy_webbased", - "productName": "Leaphy Webbased", - "author": "Leaphy Robotics", - "description": "Build Leaphy Arduino programs", - "version": "3.0.0", - "license": "GPLv3", - "main": "src/main.ts", - "scripts": { - "ng": "ng", - "start": "ng serve --open --configuration dev", - "build": "ng build --configuration production --base-href ./", - "buildLocal": "ng build --configuration local --base-href ./", - "buildstart": "ng build --base-href ./ && yarn run start", - "test": "ng test", - "lint": "ng lint", - "e2e": "ng e2e", - "dev": "lite-server --baseDir=\"dist\"" - }, - "private": true, - "dependencies": { - "@angular/animations": "17.3.4", - "@angular/cdk": "^17.3.4", - "@angular/common": "~17.3.4", - "@angular/compiler": "~17.3.4", - "@angular/core": "~17.3.4", - "@angular/flex-layout": "^15.0.0-beta.42", - "@angular/forms": "~17.3.4", - "@angular/material": "^17.3.4", - "@angular/platform-browser": "~17.3.4", - "@angular/platform-browser-dynamic": "~17.3.4", - "@angular/router": "17.3.4", - "@blockly/field-bitmap": "^4.0.13", - "@blockly/workspace-backpack": "^5.3.3", - "@fortawesome/fontawesome-free": "^6.1.1", - "@leaphy-robotics/avrdude-webassembly": "^1.4.0", - "@leaphy-robotics/dfu-util-wasm": "1.0.2", - "@leaphy-robotics/leaphy-blocks": "2.0.2", - "@leaphy-robotics/picotool-wasm": "1.0.2", - "@ngx-translate/core": "^14.0.0", - "@ngx-translate/http-loader": "^7.0.0", - "@serialport/parser-readline": "^10.3.0", - "@types/w3c-web-serial": "^1.0.3", - "base64-js": "^1.5.1", - "blockly": "^10.1.3", - "bootstrap": "^5.1.3", - "buffer": "^6.0.3", - "chart.js": "^3.8.0", - "chartjs-adapter-moment": "^1.0.0", - "jquery": "^3.5.1", - "jszip": "^3.10.1", - "moment": "^2.30.1", - "monaco-editor": "^0.47.0", - "ng-terminal": "~6.1.0", - "ng2-charts": "3.0.11", - "ngx-matomo-client": "^6.1.3", - "ngx-monaco-editor-v2": "^17.0.1", - "papaparse": "^5.4.1", - "rxjs": "~7.5.5", - "showdown": "^2.1.0", - "tslib": "^2.4.0", - "web-serial-polyfill": "^1.0.15", - "zone.js": "~0.14.3" - }, - "devDependencies": { - "@angular-devkit/build-angular": "^17.3.4", - "@angular-eslint/builder": "17.3.0", - "@angular-eslint/eslint-plugin": "17.3.0", - "@angular-eslint/eslint-plugin-template": "17.3.0", - "@angular-eslint/schematics": "17.3.0", - "@angular-eslint/template-parser": "17.3.0", - "@angular/cli": "^17.3.4", - "@angular/compiler-cli": "~17.3.4", - "@angular/language-service": "~17.3.4", - "@playwright/test": "^1.42.1", - "@types/jasmine": "~4.0.3", - "@types/jasminewd2": "~2.0.3", - "@types/node": "^20.4.8", - "@types/w3c-web-usb": "^1.0.10", - "@typescript-eslint/eslint-plugin": "^7.2.0", - "@typescript-eslint/parser": "^7.2.0", - "eslint": "^8.57.0", - "jasmine-core": "~4.1.1", - "jasmine-spec-reporter": "~7.0.0", - "karma": "~6.3.20", - "karma-chrome-launcher": "~3.1.1", - "karma-coverage-istanbul-reporter": "~3.0.2", - "karma-jasmine": "~5.0.1", - "karma-jasmine-html-reporter": "^2.0.0", - "protractor": "~7.0.0", - "ts-node": "~10.8.0", - "typescript": "5.4.5" - }, - "config": { - "forge": "./forge.config.js" - }, - "browser": { - "crypto": false, - "constants": false, - "fs": false, - "path": false - } + "name": "leaphy_webbased", + "productName": "Leaphy Webbased", + "author": "Leaphy Robotics", + "description": "Build Leaphy Arduino programs", + "version": "3.0.0", + "license": "GPLv3", + "main": "src/main.ts", + "scripts": { + "ng": "ng", + "start": "ng serve --open --configuration dev", + "build": "ng build --configuration production --base-href ./", + "buildLocal": "ng build --configuration local --base-href ./", + "buildstart": "ng build --base-href ./ && yarn run start", + "test": "ng test", + "lint": "ng lint", + "e2e": "ng e2e", + "dev": "lite-server --baseDir=\"dist\"" + }, + "private": true, + "dependencies": { + "@angular/animations": "17.3.4", + "@angular/cdk": "^17.3.4", + "@angular/common": "~17.3.4", + "@angular/compiler": "~17.3.4", + "@angular/core": "~17.3.4", + "@angular/flex-layout": "^15.0.0-beta.42", + "@angular/forms": "~17.3.4", + "@angular/material": "^17.3.4", + "@angular/platform-browser": "~17.3.4", + "@angular/platform-browser-dynamic": "~17.3.4", + "@angular/router": "17.3.4", + "@blockly/field-bitmap": "^4.0.13", + "@blockly/workspace-backpack": "^5.3.3", + "@fortawesome/fontawesome-free": "^6.1.1", + "@leaphy-robotics/avrdude-webassembly": "^1.4.0", + "@leaphy-robotics/dfu-util-wasm": "1.0.2", + "@leaphy-robotics/leaphy-blocks": "2.0.2", + "@leaphy-robotics/picotool-wasm": "1.0.2", + "@ngx-translate/core": "^14.0.0", + "@ngx-translate/http-loader": "^7.0.0", + "@serialport/parser-readline": "^10.3.0", + "@types/w3c-web-serial": "^1.0.3", + "base64-js": "^1.5.1", + "blockly": "^10.1.3", + "bootstrap": "^5.1.3", + "buffer": "^6.0.3", + "chart.js": "^3.8.0", + "chartjs-adapter-moment": "^1.0.0", + "jquery": "^3.5.1", + "jszip": "^3.10.1", + "moment": "^2.30.1", + "monaco-editor": "^0.47.0", + "ng-terminal": "~6.1.0", + "ng2-charts": "3.0.11", + "ngx-matomo-client": "^6.1.3", + "ngx-monaco-editor-v2": "^17.0.1", + "papaparse": "^5.4.1", + "rxjs": "~7.5.5", + "showdown": "^2.1.0", + "tslib": "^2.4.0", + "web-serial-polyfill": "^1.0.15", + "zone.js": "~0.14.3" + }, + "devDependencies": { + "@angular-devkit/build-angular": "^17.3.4", + "@angular-eslint/builder": "17.3.0", + "@angular-eslint/eslint-plugin": "17.3.0", + "@angular-eslint/eslint-plugin-template": "17.3.0", + "@angular-eslint/schematics": "17.3.0", + "@angular-eslint/template-parser": "17.3.0", + "@angular/cli": "^17.3.4", + "@angular/compiler-cli": "~17.3.4", + "@angular/language-service": "~17.3.4", + "@playwright/test": "^1.42.1", + "@types/jasmine": "~4.0.3", + "@types/jasminewd2": "~2.0.3", + "@types/node": "^20.4.8", + "@types/w3c-web-usb": "^1.0.10", + "@typescript-eslint/eslint-plugin": "^7.2.0", + "@typescript-eslint/parser": "^7.2.0", + "eslint": "^8.57.0", + "jasmine-core": "~4.1.1", + "jasmine-spec-reporter": "~7.0.0", + "karma": "~6.3.20", + "karma-chrome-launcher": "~3.1.1", + "karma-coverage-istanbul-reporter": "~3.0.2", + "karma-jasmine": "~5.0.1", + "karma-jasmine-html-reporter": "^2.0.0", + "prettier": "^3.2.5", + "protractor": "~7.0.0", + "ts-node": "~10.8.0", + "typescript": "5.4.5" + }, + "config": { + "forge": "./forge.config.js" + }, + "browser": { + "crypto": false, + "constants": false, + "fs": false, + "path": false + } } diff --git a/playwright.config.ts b/playwright.config.ts index 4ee1c22c..64fc0dcb 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -1,4 +1,4 @@ -import { defineConfig, devices } from '@playwright/test'; +import { defineConfig, devices } from "@playwright/test"; /** * Read environment variables from file. @@ -10,58 +10,58 @@ import { defineConfig, devices } from '@playwright/test'; * See https://playwright.dev/docs/test-configuration. */ export default defineConfig({ - testDir: './tests', - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: process.env.CI ? 2 : 0, - /* Opt out of parallel tests on CI. */ - workers: process.env.CI ? 1 : undefined, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'html', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: 'http://localhost:4200/', + testDir: "./tests", + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: "html", + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: "http://localhost:4200/", - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { ...devices['Desktop Chrome'] }, + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: "on-first-retry", }, - /* These browers are not supported because of their lack of webserial support, so we don't need to test them */ - // { - // name: 'firefox', - // use: { ...devices['Desktop Firefox'] }, - // }, - // { - // name: 'webkit', - // use: { ...devices['Desktop Safari'] }, - // }, + /* Configure projects for major browsers */ + projects: [ + { + name: "chromium", + use: { ...devices["Desktop Chrome"] }, + }, + + /* These browers are not supported because of their lack of webserial support, so we don't need to test them */ + // { + // name: 'firefox', + // use: { ...devices['Desktop Firefox'] }, + // }, + // { + // name: 'webkit', + // use: { ...devices['Desktop Safari'] }, + // }, - /* Test against branded browsers. */ - // { - // name: 'Microsoft Edge', - // use: { ...devices['Desktop Edge'], channel: 'msedge' }, - // }, - // { - // name: 'Google Chrome', - // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, - // }, - ], + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { ...devices['Desktop Edge'], channel: 'msedge' }, + // }, + // { + // name: 'Google Chrome', + // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, + // }, + ], - /* Run your local dev server before starting the tests */ - webServer: { - command: 'yarn start', - url: 'http://localhost:4200/', - reuseExistingServer: !process.env.CI, - }, + /* Run your local dev server before starting the tests */ + webServer: { + command: "yarn start", + url: "http://localhost:4200/", + reuseExistingServer: !process.env.CI, + }, }); diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 72153a0e..ac362e06 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -1,38 +1,62 @@ -import { NgModule } from '@angular/core'; -import { Routes, RouterModule } from '@angular/router'; -import {CodeEditorPythonPage} from "./modules/code-editor-python/code-editor-python.page"; -import {DriverIssuesEnglishPage} from "./modules/driver-issues-english/driver-issues.page"; -import {DriverIssuesDutchPage} from "./modules/driver-issues-dutch/driver-issues.page"; -import {BlocklyEditorPage} from "./modules/blockly-editor/blockly-editor.page"; -import {CodeEditorCppPage} from "./modules/code-editor-cpp/code-editor-cpp.page"; -import {MonacoEditorModule} from "ngx-monaco-editor-v2"; - +import { NgModule } from "@angular/core"; +import { Routes, RouterModule } from "@angular/router"; +import { CodeEditorPythonPage } from "./modules/code-editor-python/code-editor-python.page"; +import { DriverIssuesEnglishPage } from "./modules/driver-issues-english/driver-issues.page"; +import { DriverIssuesDutchPage } from "./modules/driver-issues-dutch/driver-issues.page"; +import { BlocklyEditorPage } from "./modules/blockly-editor/blockly-editor.page"; +import { CodeEditorCppPage } from "./modules/code-editor-cpp/code-editor-cpp.page"; +import { MonacoEditorModule } from "ngx-monaco-editor-v2"; const routes: Routes = [ - { path: 'blocks', children: [{ - path: '', - component: BlocklyEditorPage - }]}, - { path: 'cppEditor', children: [{ - path: '', - component: CodeEditorCppPage - }]}, - { path: 'pythonEditor', children: [{ - path: '', - component: CodeEditorPythonPage - }]}, - { path: 'en', children: [{ - path: 'driverissues', - component: DriverIssuesEnglishPage - }]}, - { path: 'nl', children: [{ - path: 'driverissues', - component: DriverIssuesDutchPage - }]} + { + path: "blocks", + children: [ + { + path: "", + component: BlocklyEditorPage, + }, + ], + }, + { + path: "cppEditor", + children: [ + { + path: "", + component: CodeEditorCppPage, + }, + ], + }, + { + path: "pythonEditor", + children: [ + { + path: "", + component: CodeEditorPythonPage, + }, + ], + }, + { + path: "en", + children: [ + { + path: "driverissues", + component: DriverIssuesEnglishPage, + }, + ], + }, + { + path: "nl", + children: [ + { + path: "driverissues", + component: DriverIssuesDutchPage, + }, + ], + }, ]; @NgModule({ imports: [RouterModule.forRoot(routes)], - exports: [RouterModule] + exports: [RouterModule], }) -export class AppRoutingModule { } +export class AppRoutingModule {} diff --git a/src/app/app.component.html b/src/app/app.component.html index 4af68343..3cb52de5 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,6 +1,6 @@ @if (appState.selectedRobotType$ | async) { - + } @else { - + } diff --git a/src/app/app.component.scss b/src/app/app.component.scss index 7d570afb..1d5cca77 100644 --- a/src/app/app.component.scss +++ b/src/app/app.component.scss @@ -1,13 +1,13 @@ .imgcenter { - position:absolute; - top: 50%; - left:50%; - -webkit-transform: translate(-50%, -50%); - -ms-transform: translate(-50%, -50%); - transform: translate(-50%, -50%); + position: absolute; + top: 50%; + left: 50%; + -webkit-transform: translate(-50%, -50%); + -ms-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); } .main_logo { - width: 0.001%; - height:auto; + width: 0.001%; + height: auto; } diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts index dc2ea919..c6e9c4f9 100644 --- a/src/app/app.component.spec.ts +++ b/src/app/app.component.spec.ts @@ -1,35 +1,33 @@ -import { TestBed, waitForAsync } from '@angular/core/testing'; -import { RouterTestingModule } from '@angular/router/testing'; -import { AppComponent } from './app.component'; +import { TestBed, waitForAsync } from "@angular/core/testing"; +import { RouterTestingModule } from "@angular/router/testing"; +import { AppComponent } from "./app.component"; -describe('AppComponent', () => { - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - imports: [ - RouterTestingModule - ], - declarations: [ - AppComponent - ], - }).compileComponents(); - })); +describe("AppComponent", () => { + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [RouterTestingModule], + declarations: [AppComponent], + }).compileComponents(); + })); - it('should create the app', () => { - const fixture = TestBed.createComponent(AppComponent); - const app = fixture.debugElement.componentInstance; - expect(app).toBeTruthy(); - }); + it("should create the app", () => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.debugElement.componentInstance; + expect(app).toBeTruthy(); + }); - it(`should have as title 'leaphy-client'`, () => { - const fixture = TestBed.createComponent(AppComponent); - const app = fixture.debugElement.componentInstance; - expect(app.title).toEqual('leaphy-client'); - }); + it(`should have as title 'leaphy-client'`, () => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.debugElement.componentInstance; + expect(app.title).toEqual("leaphy-client"); + }); - it('should render title', () => { - const fixture = TestBed.createComponent(AppComponent); - fixture.detectChanges(); - const compiled = fixture.debugElement.nativeElement; - expect(compiled.querySelector('.content span').textContent).toContain('leaphy-client app is running!'); - }); + it("should render title", () => { + const fixture = TestBed.createComponent(AppComponent); + fixture.detectChanges(); + const compiled = fixture.debugElement.nativeElement; + expect(compiled.querySelector(".content span").textContent).toContain( + "leaphy-client app is running!", + ); + }); }); diff --git a/src/app/app.component.ts b/src/app/app.component.ts index e3335766..f01bc4ce 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,23 +1,25 @@ -import { Component } from '@angular/core'; -import { AppState } from './state/app.state'; +import { Component } from "@angular/core"; +import { AppState } from "./state/app.state"; import { MatIconRegistry } from "@angular/material/icon"; import { DomSanitizer } from "@angular/platform-browser"; @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 { - title = 'Leaphy Easybloqs'; + title = "Leaphy Easybloqs"; constructor( public appState: AppState, private matIconRegistry: MatIconRegistry, - private domSanitizer: DomSanitizer + private domSanitizer: DomSanitizer, ) { this.matIconRegistry.addSvgIcon( "block", - this.domSanitizer.bypassSecurityTrustResourceUrl("./assets/block.svg") + this.domSanitizer.bypassSecurityTrustResourceUrl( + "./assets/block.svg", + ), ); } } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 68d47432..917eff3b 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,35 +1,31 @@ -import { BrowserModule } from '@angular/platform-browser'; -import { NgModule, APP_INITIALIZER } from '@angular/core'; +import { BrowserModule } from "@angular/platform-browser"; +import { NgModule, APP_INITIALIZER } from "@angular/core"; -import { HttpClientModule, HttpClient } from '@angular/common/http'; +import { HttpClientModule, HttpClient } from "@angular/common/http"; -import { AppRoutingModule } from './app-routing.module'; -import { AppComponent } from './app.component'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { AppRoutingModule } from "./app-routing.module"; +import { AppComponent } from "./app.component"; +import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; -import { TranslateModule, TranslateLoader } from '@ngx-translate/core'; -import { TranslateHttpLoader } from '@ngx-translate/http-loader'; +import { TranslateModule, TranslateLoader } from "@ngx-translate/core"; +import { TranslateHttpLoader } from "@ngx-translate/http-loader"; -import { BlocklyEditorEffects } from './effects/blockly-editor.effects'; -import { DialogEffects } from './effects/dialog.effects'; -import { AppEffects } from './effects/app.effects'; -import { RobotWiredEffects } from './effects/robot.wired.effects'; -import { CoreModule } from './modules/core/core.module'; +import { BlocklyEditorEffects } from "./effects/blockly-editor.effects"; +import { DialogEffects } from "./effects/dialog.effects"; +import { AppEffects } from "./effects/app.effects"; +import { RobotWiredEffects } from "./effects/robot.wired.effects"; +import { CoreModule } from "./modules/core/core.module"; -import { MatomoModule } from 'ngx-matomo-client'; -import {CodeEditorEffects} from "./effects/code-editor.effects"; -import {MonacoEditorModule} from "ngx-monaco-editor-v2"; +import { MatomoModule } from "ngx-matomo-client"; +import { CodeEditorEffects } from "./effects/code-editor.effects"; +import { MonacoEditorModule } from "ngx-monaco-editor-v2"; export function createTranslateLoader(http: HttpClient) { - return new TranslateHttpLoader(http, './assets/i18n/', '.json'); + return new TranslateHttpLoader(http, "./assets/i18n/", ".json"); } - - @NgModule({ - declarations: [ - AppComponent, - ], + declarations: [AppComponent], imports: [ BrowserModule, AppRoutingModule, @@ -39,35 +35,37 @@ export function createTranslateLoader(http: HttpClient) { loader: { provide: TranslateLoader, useFactory: createTranslateLoader, - deps: [HttpClient] - } + deps: [HttpClient], + }, }), MatomoModule.forRoot({ - scriptUrl: 'https://leaphyeasybloqs.com/matomo/matomo.js', + scriptUrl: "https://leaphyeasybloqs.com/matomo/matomo.js", trackers: [ { - trackerUrl: 'https://leaphyeasybloqs.com/matomo/matomo.php', - siteId: 1 - } + trackerUrl: "https://leaphyeasybloqs.com/matomo/matomo.php", + siteId: 1, + }, ], }), CoreModule, - MonacoEditorModule.forRoot() + MonacoEditorModule.forRoot(), ], providers: [ // Initialize the Effects on startup { - provide: APP_INITIALIZER, deps: - [ - AppEffects, - BlocklyEditorEffects, - DialogEffects, - CodeEditorEffects, - RobotWiredEffects - ], useFactory: () => () => null, multi: true - } + provide: APP_INITIALIZER, + deps: [ + AppEffects, + BlocklyEditorEffects, + DialogEffects, + CodeEditorEffects, + RobotWiredEffects, + ], + useFactory: () => () => null, + multi: true, + }, ], exports: [], - bootstrap: [AppComponent] + bootstrap: [AppComponent], }) -export class AppModule { } +export class AppModule {} diff --git a/src/app/domain/language.ts b/src/app/domain/language.ts index 504b8db1..6fbc5b10 100644 --- a/src/app/domain/language.ts +++ b/src/app/domain/language.ts @@ -1,3 +1,6 @@ export class Language { - constructor(public code: string, public name: string) {} + constructor( + public code: string, + public name: string, + ) {} } diff --git a/src/app/domain/python-file.type.ts b/src/app/domain/python-file.type.ts index 8d076705..fc79e31c 100644 --- a/src/app/domain/python-file.type.ts +++ b/src/app/domain/python-file.type.ts @@ -1,8 +1,7 @@ export class PythonFile { - path: string; + path: string; - constructor(path: string) { - this.path = path; - } + constructor(path: string) { + this.path = path; + } } - diff --git a/src/app/domain/robot.type.ts b/src/app/domain/robot.type.ts index b984f2bd..31314b8e 100644 --- a/src/app/domain/robot.type.ts +++ b/src/app/domain/robot.type.ts @@ -16,7 +16,7 @@ const DEFAULTS: Features = { showLeaphyOperators: true, showLeaphySensors: false, showLeaphyLists: false, - showCodeOnStart: false + showCodeOnStart: false, }; interface ProtocolInformation { @@ -38,22 +38,21 @@ export class RobotType { public libs: string[], features?: Partial, ) { - this.features = Object.assign({}, DEFAULTS, features||{}); + this.features = Object.assign({}, DEFAULTS, features || {}); } } export interface RobotEntry { - name: string, - icon: string, - robot: RobotType + name: string; + icon: string; + robot: RobotType; } export interface RobotSelector { - intercept: RobotType, - choices: RobotEntry[][], + intercept: RobotType; + choices: RobotEntry[][]; } - export class BaseUno extends RobotType { constructor( id: string, @@ -63,7 +62,17 @@ export class BaseUno extends RobotType { libs: string[], features?: Partial, ) { - super(id, {protocol: Avrdude, microcontroller: 'atmega328p'}, name, svgname, background, "arduino:avr:uno", "arduino:avr", libs, features); + super( + id, + { protocol: Avrdude, microcontroller: "atmega328p" }, + name, + svgname, + background, + "arduino:avr:uno", + "arduino:avr", + libs, + features, + ); } } @@ -76,7 +85,17 @@ export class BaseNano extends RobotType { libs: string[], features?: Partial, ) { - super(id, {protocol: Avrdude, microcontroller: 'atmega328p'}, name, svgname, background, "arduino:avr:nano", "arduino:avr", libs, features); + super( + id, + { protocol: Avrdude, microcontroller: "atmega328p" }, + name, + svgname, + background, + "arduino:avr:nano", + "arduino:avr", + libs, + features, + ); } } @@ -89,7 +108,17 @@ export class BaseNanoESP32 extends RobotType { libs: string[], features?: Partial, ) { - super(id, {protocol: DFU}, name, svgname, background, "arduino:esp32:nano_nora", "arduino:esp32", libs, features); + super( + id, + { protocol: DFU }, + name, + svgname, + background, + "arduino:esp32:nano_nora", + "arduino:esp32", + libs, + features, + ); } } @@ -102,7 +131,16 @@ export class BaseNanoRP2040 extends RobotType { libs: string[], features?: Partial, ) { - super(id, {protocol: Pico}, name, svgname, background, "arduino:mbed_nano:nanorp2040connect", "arduino:mbed_nano", libs, features); + super( + id, + { protocol: Pico }, + name, + svgname, + background, + "arduino:mbed_nano:nanorp2040connect", + "arduino:mbed_nano", + libs, + features, + ); } } - diff --git a/src/app/domain/robots.ts b/src/app/domain/robots.ts index 76d20730..d438b741 100644 --- a/src/app/domain/robots.ts +++ b/src/app/domain/robots.ts @@ -1,17 +1,34 @@ import Avrdude from "../services/arduino-uploader/protocols/avrdude"; -import {BaseNano, BaseNanoESP32, BaseNanoRP2040, BaseUno, RobotType} from "./robot.type"; +import { + BaseNano, + BaseNanoESP32, + BaseNanoRP2040, + BaseUno, + RobotType, +} from "./robot.type"; const defaultLibraries = [ - 'Leaphy Original Extension', 'Leaphy Extra Extension', 'Servo', 'Adafruit GFX Library', 'Adafruit SSD1306', 'Adafruit LSM9DS1 Library', - 'Adafruit Unified Sensor', 'List', 'Adafruit SGP30 Sensor', 'Adafruit_VL53L0X', 'Adafruit BMP280 Library', 'TM1637', 'LedControl' -] + "Leaphy Original Extension", + "Leaphy Extra Extension", + "Servo", + "Adafruit GFX Library", + "Adafruit SSD1306", + "Adafruit LSM9DS1 Library", + "Adafruit Unified Sensor", + "List", + "Adafruit SGP30 Sensor", + "Adafruit_VL53L0X", + "Adafruit BMP280 Library", + "TM1637", + "LedControl", +]; export const leaphyOriginalRobotType = new BaseUno( - 'l_original_uno', - 'Leaphy Original', - 'orig.svg', - 'orig_uno.svg', - defaultLibraries.concat(['QMC5883LCompass', 'Arduino_APDS9960']), + "l_original_uno", + "Leaphy Original", + "orig.svg", + "orig_uno.svg", + defaultLibraries.concat(["QMC5883LCompass", "Arduino_APDS9960"]), { showLeaphyActuators: true, showLeaphyOperators: false, @@ -19,13 +36,12 @@ export const leaphyOriginalRobotType = new BaseUno( }, ); - export const leaphyOriginalNanoRobotType = new BaseNano( - 'l_original_nano', - 'Original Nano', - 'orig.svg', - 'orig_nano.svg', - defaultLibraries.concat(['QMC5883LCompass', 'Arduino_APDS9960']), + "l_original_nano", + "Original Nano", + "orig.svg", + "orig_nano.svg", + defaultLibraries.concat(["QMC5883LCompass", "Arduino_APDS9960"]), { showLeaphyActuators: true, showLeaphyOperators: true, @@ -34,36 +50,36 @@ export const leaphyOriginalNanoRobotType = new BaseNano( ); export const leaphyOriginalNanoESP32RobotType = new BaseNanoESP32( - 'l_original_nano_esp32', - 'Original Nano ESP32', - 'orig.svg', - 'orig_nano_esp32.svg', - defaultLibraries.concat(['QMC5883LCompass', 'Arduino_APDS9960']), + "l_original_nano_esp32", + "Original Nano ESP32", + "orig.svg", + "orig_nano_esp32.svg", + defaultLibraries.concat(["QMC5883LCompass", "Arduino_APDS9960"]), { showLeaphyActuators: true, showLeaphyOperators: true, showLeaphySensors: true, }, -) +); export const leaphyOriginalNanoRP2040RobotType = new BaseNanoRP2040( - 'l_original_nano_rp2040', - 'Original Nano RP2040', - 'orig.svg', - 'orig_nano_rp2040.svg', - defaultLibraries.concat(['QMC5883LCompass', 'Arduino_APDS9960']), + "l_original_nano_rp2040", + "Original Nano RP2040", + "orig.svg", + "orig_nano_rp2040.svg", + defaultLibraries.concat(["QMC5883LCompass", "Arduino_APDS9960"]), { showLeaphyActuators: true, showLeaphyOperators: true, showLeaphySensors: true, }, -) +); export const leaphyFlitzRobotType = new BaseUno( - 'l_flitz_uno', - 'Leaphy Flitz', - 'flitz.svg', - 'flitz_uno.svg', + "l_flitz_uno", + "Leaphy Flitz", + "flitz.svg", + "flitz_uno.svg", defaultLibraries, { showLeaphyActuators: false, @@ -72,10 +88,10 @@ export const leaphyFlitzRobotType = new BaseUno( ); export const leaphyFlitzNanoRobotType = new BaseNano( - 'l_flitz_nano', - 'Flitz Nano', - 'flitz.svg', - 'flitz_nano.svg', + "l_flitz_nano", + "Flitz Nano", + "flitz.svg", + "flitz_nano.svg", defaultLibraries, { showLeaphyActuators: false, @@ -84,9 +100,9 @@ export const leaphyFlitzNanoRobotType = new BaseNano( ); export const leaphyClickRobotType = new BaseUno( - 'l_click', - 'Leaphy Click', - 'click.svg', + "l_click", + "Leaphy Click", + "click.svg", null, defaultLibraries, { @@ -95,11 +111,11 @@ export const leaphyClickRobotType = new BaseUno( ); export const arduinoUnoRobotType = new BaseUno( - 'l_uno', - 'Arduino Uno', - 'uno.svg', + "l_uno", + "Arduino Uno", + "uno.svg", null, - defaultLibraries.concat(['QMC5883LCompass', 'Arduino_APDS9960']), + defaultLibraries.concat(["QMC5883LCompass", "Arduino_APDS9960"]), { showLeaphyLists: true, showLeaphySensors: true, @@ -107,20 +123,20 @@ export const arduinoUnoRobotType = new BaseUno( ); export const genericRobotType = new BaseUno( - 'l_code', - 'Leaphy C++', + "l_code", + "Leaphy C++", "c++.svg", null, - defaultLibraries.concat(['QMC5883LCompass', 'Arduino_APDS9960']), + defaultLibraries.concat(["QMC5883LCompass", "Arduino_APDS9960"]), {}, ); export const arduinoNanoRobotType = new BaseNano( - 'l_nano', - 'Arduino Nano', - 'nano.svg', + "l_nano", + "Arduino Nano", + "nano.svg", null, - defaultLibraries.concat(['QMC5883LCompass', 'Arduino_APDS9960']), + defaultLibraries.concat(["QMC5883LCompass", "Arduino_APDS9960"]), { showLeaphyLists: true, showLeaphySensors: true, @@ -128,54 +144,55 @@ export const arduinoNanoRobotType = new BaseNano( ); export const arduinoNanoESP32RobotType = new BaseNanoESP32( - 'l_nano_esp32', - 'Arduino Nano ESP32', - 'nano.svg', + "l_nano_esp32", + "Arduino Nano ESP32", + "nano.svg", null, - defaultLibraries.concat(['QMC5883LCompass', 'Arduino_APDS9960']), + defaultLibraries.concat(["QMC5883LCompass", "Arduino_APDS9960"]), { showLeaphyLists: true, showLeaphySensors: true, - } + }, ); export const arduinoNanoRP2040RobotType = new BaseNanoRP2040( - 'l_nano_rp2040', - 'Arduino Nano RP2040', - 'nano.svg', + "l_nano_rp2040", + "Arduino Nano RP2040", + "nano.svg", null, - defaultLibraries.concat(['QMC5883LCompass', 'Arduino_APDS9960']), + defaultLibraries.concat(["QMC5883LCompass", "Arduino_APDS9960"]), { showLeaphyLists: true, showLeaphySensors: true, - } + }, ); export const microPythonRobotType = new RobotType( - 'l_micropython', - {protocol: Avrdude}, - 'MicroPython', - 'micropython.svg', + "l_micropython", + { protocol: Avrdude }, + "MicroPython", + "micropython.svg", null, - '', - '', + "", + "", [], { showLeaphyActuators: false, showLeaphyOperators: false, - }); + }, +); export const arduinoMegaRobotType = new RobotType( - 'l_mega', - {protocol: Avrdude, microcontroller: 'atmega2560'}, - 'Arduino Mega', - 'mega.svg', + "l_mega", + { protocol: Avrdude, microcontroller: "atmega2560" }, + "Arduino Mega", + "mega.svg", null, - 'arduino:avr:mega', - 'arduino:avr', - defaultLibraries.concat(['QMC5883LCompass', 'Arduino_APDS9960']), + "arduino:avr:mega", + "arduino:avr", + defaultLibraries.concat(["QMC5883LCompass", "Arduino_APDS9960"]), { showLeaphyLists: true, showLeaphySensors: true, }, -) +); diff --git a/src/app/domain/snackbar.message.ts b/src/app/domain/snackbar.message.ts index 6c4aebe1..e34612b4 100644 --- a/src/app/domain/snackbar.message.ts +++ b/src/app/domain/snackbar.message.ts @@ -1,3 +1,8 @@ export class SnackbarMessage { - constructor(public event: string, public message: string, public payload: any, public displayTimeout: number) { } + constructor( + public event: string, + public message: string, + public payload: any, + public displayTimeout: number, + ) {} } diff --git a/src/app/effects/app.effects.ts b/src/app/effects/app.effects.ts index 046ce670..ef23b66c 100644 --- a/src/app/effects/app.effects.ts +++ b/src/app/effects/app.effects.ts @@ -1,39 +1,38 @@ -import { Injectable } from '@angular/core'; -import { AppState } from '../state/app.state'; -import { TranslateService } from '@ngx-translate/core'; -import { filter, withLatestFrom } from 'rxjs/operators'; -import { Router } from '@angular/router'; -import { CodeEditorType } from '../domain/code-editor.type'; -import {LocalStorageService} from "../services/localstorage.service"; -import {MatDialog} from "@angular/material/dialog"; -import {ChangeLogDialog} from "../modules/core/dialogs/change-log/change-log.dialog"; +import { Injectable } from "@angular/core"; +import { AppState } from "../state/app.state"; +import { TranslateService } from "@ngx-translate/core"; +import { filter, withLatestFrom } from "rxjs/operators"; +import { Router } from "@angular/router"; +import { CodeEditorType } from "../domain/code-editor.type"; +import { LocalStorageService } from "../services/localstorage.service"; +import { MatDialog } from "@angular/material/dialog"; +import { ChangeLogDialog } from "../modules/core/dialogs/change-log/change-log.dialog"; import showdown from "showdown"; -import {WorkspaceService} from "../services/workspace.service"; +import { WorkspaceService } from "../services/workspace.service"; @Injectable({ - providedIn: 'root', + providedIn: "root", }) - export class AppEffects { - constructor( private appState: AppState, private translate: TranslateService, private router: Router, private localStorage: LocalStorageService, private dialog: MatDialog, - private workspaceService: WorkspaceService + private workspaceService: WorkspaceService, ) { - // Use the current language to translate the angular strings this.appState.currentLanguage$ - .pipe(filter(language => !!language)) - .subscribe(language => this.translate.use(language.code)); - + .pipe(filter((language) => !!language)) + .subscribe((language) => this.translate.use(language.code)); // When the editor change has been confirmed, toggle the code-editor this.appState.isCodeEditorToggleConfirmed$ - .pipe(filter(isToggled => !!isToggled), withLatestFrom(this.appState.codeEditor$)) + .pipe( + filter((isToggled) => !!isToggled), + withLatestFrom(this.appState.codeEditor$), + ) .subscribe(([, codeEditorType]) => { if (codeEditorType == CodeEditorType.Beginner) { this.appState.selectedCodeEditor = CodeEditorType.CPP; @@ -44,17 +43,23 @@ export class AppEffects { // When the code editor changes, route to the correct screen this.appState.codeEditor$ - .pipe(filter(codeEditor => !!codeEditor)) - .subscribe(async codeEditor => { + .pipe(filter((codeEditor) => !!codeEditor)) + .subscribe(async (codeEditor) => { switch (codeEditor) { case CodeEditorType.Beginner: - await this.router.navigate(['/blocks'], { skipLocationChange: true }); + await this.router.navigate(["/blocks"], { + skipLocationChange: true, + }); break; case CodeEditorType.CPP: - await this.router.navigate(['/cppEditor'], { skipLocationChange: true }); + await this.router.navigate(["/cppEditor"], { + skipLocationChange: true, + }); break; case CodeEditorType.Python: - await this.router.navigate(['/pythonEditor'], { skipLocationChange: true }); + await this.router.navigate(["/pythonEditor"], { + skipLocationChange: true, + }); break; default: break; @@ -62,23 +67,23 @@ export class AppEffects { this.appState.isCodeEditorToggleConfirmed = false; }); - - this.appState.releaseInfo$ - .pipe(filter(releaseInfo => !!releaseInfo)) - .subscribe(releaseInfo => { + .pipe(filter((releaseInfo) => !!releaseInfo)) + .subscribe((releaseInfo) => { const releaseVersion = this.appState.releaseVersion; if (!releaseVersion) { return; } try { - this.localStorage.fetch('releaseVersion'); + this.localStorage.fetch("releaseVersion"); } catch (e) { - this.localStorage.store('releaseVersion', ''); + this.localStorage.store("releaseVersion", ""); } - if (releaseVersion != this.localStorage.fetch('releaseVersion')) { - let releaseNotes = releaseInfo["body"] + if ( + releaseVersion != this.localStorage.fetch("releaseVersion") + ) { + let releaseNotes = releaseInfo["body"]; // convert all the urls to links // first find the urls let urls = releaseNotes.match(/(https?:\/\/[\S]+)/g); @@ -86,10 +91,21 @@ export class AppEffects { if (urls) { // to prevent infinite loops we want to know the index of the last url we replaced let lastUrlIndex = 0; - urls.forEach(url => { + urls.forEach((url) => { const link = `${url}`; - releaseNotes = releaseNotes.substring(0, releaseNotes.indexOf(url, lastUrlIndex)) + link + releaseNotes.substring(releaseNotes.indexOf(url, lastUrlIndex) + url.length); - lastUrlIndex = releaseNotes.indexOf(link, lastUrlIndex) + link.length; + releaseNotes = + releaseNotes.substring( + 0, + releaseNotes.indexOf(url, lastUrlIndex), + ) + + link + + releaseNotes.substring( + releaseNotes.indexOf(url, lastUrlIndex) + + url.length, + ); + lastUrlIndex = + releaseNotes.indexOf(link, lastUrlIndex) + + link.length; }); } // turn the @mentions into links @@ -97,9 +113,12 @@ export class AppEffects { let mentions = releaseNotes.match(/@(\w+)/g); // then replace them with links if (mentions) { - mentions.forEach(mention => { + mentions.forEach((mention) => { const username = mention.substring(1); - releaseNotes = releaseNotes.replaceAll(mention, `${mention}`); + releaseNotes = releaseNotes.replaceAll( + mention, + `${mention}`, + ); }); } @@ -111,22 +130,20 @@ export class AppEffects { data: { title: releaseVersion, message: releaseNotes, - type: 'info' - } + type: "info", + }, }); - } - this.localStorage.store('releaseVersion', releaseVersion); + this.localStorage.store("releaseVersion", releaseVersion); - const robotId = this.localStorage.fetch('changedLanguage'); + const robotId = this.localStorage.fetch("changedLanguage"); console.log(robotId); if (robotId) { - this.localStorage.store('changedLanguage', ''); - this.workspaceService.forceRestoreWorkspaceTemp().then(() => {}); + this.localStorage.store("changedLanguage", ""); + this.workspaceService + .forceRestoreWorkspaceTemp() + .then(() => {}); } - }) - + }); } - - } diff --git a/src/app/effects/blockly-editor.effects.ts b/src/app/effects/blockly-editor.effects.ts index 241f7421..8799de5b 100644 --- a/src/app/effects/blockly-editor.effects.ts +++ b/src/app/effects/blockly-editor.effects.ts @@ -1,149 +1,242 @@ -import {Injectable} from '@angular/core'; -import {BlocklyEditorState} from '../state/blockly-editor.state'; -import {filter, pairwise, withLatestFrom} from 'rxjs/operators'; -import {HttpClient, HttpHeaders} from '@angular/common/http'; -import {combineLatest, Observable} from 'rxjs'; -import {AppState} from '../state/app.state'; -import {CodeEditorType} from '../domain/code-editor.type'; -import * as Blockly from 'blockly'; -import '@blockly/field-bitmap' - -import {CATEGORIES, THEME, EXTENSIONS, translations, arduino, getBlocks} from "@leaphy-robotics/leaphy-blocks" -import {LeaphyCategory} from "../services/toolbox/category"; -import {LeaphyToolbox} from "../services/toolbox/toolbox"; -import {CodeEditorState} from "../state/code-editor.state"; -import {genericRobotType, microPythonRobotType} from "../domain/robots"; -import {RobotType} from "../domain/robot.type"; -import {WorkspaceService} from "../services/workspace.service"; -import {LocalStorageService} from "../services/localstorage.service"; +import { Injectable } from "@angular/core"; +import { BlocklyEditorState } from "../state/blockly-editor.state"; +import { filter, pairwise, withLatestFrom } from "rxjs/operators"; +import { HttpClient, HttpHeaders } from "@angular/common/http"; +import { combineLatest, Observable } from "rxjs"; +import { AppState } from "../state/app.state"; +import { CodeEditorType } from "../domain/code-editor.type"; +import * as Blockly from "blockly"; +import "@blockly/field-bitmap"; + +import { + CATEGORIES, + THEME, + EXTENSIONS, + translations, + arduino, + getBlocks, +} from "@leaphy-robotics/leaphy-blocks"; +import { LeaphyCategory } from "../services/toolbox/category"; +import { LeaphyToolbox } from "../services/toolbox/toolbox"; +import { CodeEditorState } from "../state/code-editor.state"; +import { genericRobotType, microPythonRobotType } from "../domain/robots"; +import { RobotType } from "../domain/robot.type"; +import { WorkspaceService } from "../services/workspace.service"; +import { LocalStorageService } from "../services/localstorage.service"; @Injectable({ - providedIn: 'root', + providedIn: "root", }) // Defines the effects on the Blockly Editor that different state changes have export class BlocklyEditorEffects { - constructor( private blocklyState: BlocklyEditorState, private appState: AppState, private codeEditorState: CodeEditorState, private http: HttpClient, private workspaceService: WorkspaceService, - private localStorage: LocalStorageService + private localStorage: LocalStorageService, ) { Blockly.registry.register( Blockly.registry.Type.TOOLBOX_ITEM, Blockly.ToolboxCategory.registrationName, - LeaphyCategory, true); - Blockly.registry.register(Blockly.registry.Type.TOOLBOX, Blockly.CollapsibleToolboxCategory.registrationName, LeaphyToolbox); - Blockly.registry.register(Blockly.registry.Type.SERIALIZER, "lists", new CATEGORIES.ListSerializer()) + LeaphyCategory, + true, + ); + Blockly.registry.register( + Blockly.registry.Type.TOOLBOX, + Blockly.CollapsibleToolboxCategory.registrationName, + LeaphyToolbox, + ); + Blockly.registry.register( + Blockly.registry.Type.SERIALIZER, + "lists", + new CATEGORIES.ListSerializer(), + ); - Blockly.Extensions.register('appendStatementInputStack', EXTENSIONS.APPEND_STATEMENT_INPUT_STACK) - Blockly.Extensions.register('list_select_extension', EXTENSIONS.LIST_SELECT_EXTENSION); + Blockly.Extensions.register( + "appendStatementInputStack", + EXTENSIONS.APPEND_STATEMENT_INPUT_STACK, + ); + Blockly.Extensions.register( + "list_select_extension", + EXTENSIONS.LIST_SELECT_EXTENSION, + ); Blockly.Extensions.registerMutator( - 'l_controls_if_mutator', + "l_controls_if_mutator", EXTENSIONS.CONTROLS_IF_MUTATOR_MIXIN, null as unknown as undefined, // TODO(#6920) - ['controls_if_elseif', 'controls_if_else'], + ["controls_if_elseif", "controls_if_else"], ); // When the current language is set: Find and set the blockly translations this.appState.currentLanguage$ - .pipe(filter(language => !!language)) - .subscribe(async language => { + .pipe(filter((language) => !!language)) + .subscribe(async (language) => { Blockly.setLocale(translations[language.code]); }); // When the language is changed, save the workspace temporarily this.appState.changedLanguage$ - .pipe(filter(language => !!language)) - .pipe(withLatestFrom(this.blocklyState.workspaceJSON$, this.appState.selectedRobotType$)) + .pipe(filter((language) => !!language)) + .pipe( + withLatestFrom( + this.blocklyState.workspaceJSON$, + this.appState.selectedRobotType$, + ), + ) .subscribe(([, workspaceXml]) => { - this.workspaceService.saveWorkspaceTemp(workspaceXml).then(() => {}); - this.localStorage.store("changedLanguage", this.appState.selectedRobotType.id); + this.workspaceService + .saveWorkspaceTemp(workspaceXml) + .then(() => {}); + this.localStorage.store( + "changedLanguage", + this.appState.selectedRobotType.id, + ); }); // When all prerequisites are there, Create a new workspace and open the codeview if needed - combineLatest([this.blocklyState.blocklyElement$, this.blocklyState.blocklyConfig$]) + combineLatest([ + this.blocklyState.blocklyElement$, + this.blocklyState.blocklyConfig$, + ]) .pipe(withLatestFrom(this.appState.selectedRobotType$)) - .pipe(filter(([[element, config], robotType]) => !!element && !!config && !!robotType && (robotType !== genericRobotType && robotType !== microPythonRobotType))) - .pipe(withLatestFrom( - this.getXmlContent('./assets/blockly/base-toolbox.xml'), - this.getXmlContent('./assets/blockly/leaphy-toolbox.xml'), - this.getXmlContent('./assets/blockly/leaphy-start.xml') - )) - .subscribe(([[[element, config], robotType], baseToolboxXml, leaphyToolboxXml, startWorkspaceXml]) => { - const leaphyBlocks = getBlocks(this.appState.selectedRobotType.id); - Blockly.defineBlocksWithJsonArray(leaphyBlocks.block) - config.theme = Blockly.Theme.defineTheme('leaphy', { - 'blockStyles': THEME.defaultBlockStyles, - 'categoryStyles': THEME.categoryStyles, - 'componentStyles': THEME.componentStyles, - name: 'leaphy', - }); - const toolboxXmlString = this.loadToolBox(baseToolboxXml, leaphyToolboxXml, robotType); - config.toolbox = toolboxXmlString; - // @ts-ignore - const workspace = Blockly.inject(element, config); - const toolbox = workspace.getToolbox(); - workspace.registerToolboxCategoryCallback('LISTS', CATEGORIES.LISTS); - toolbox.getFlyout().autoClose = false; - const xml = Blockly.utils.xml.textToDom(startWorkspaceXml); - Blockly.Xml.domToWorkspace(xml, workspace); - this.blocklyState.workspace = workspace; - this.blocklyState.toolboxXml = toolboxXmlString; - if (this.appState.currentEditor == CodeEditorType.Beginner) { - this.workspaceService.restoreWorkspaceTemp().then(() => {}); - } - toolbox.selectItemByPosition(0); - toolbox.refreshTheme(); - - setTimeout(() => this.blocklyState.isSideNavOpen = robotType.features.showCodeOnStart, 200); - }); + .pipe( + filter( + ([[element, config], robotType]) => + !!element && + !!config && + !!robotType && + robotType !== genericRobotType && + robotType !== microPythonRobotType, + ), + ) + .pipe( + withLatestFrom( + this.getXmlContent("./assets/blockly/base-toolbox.xml"), + this.getXmlContent("./assets/blockly/leaphy-toolbox.xml"), + this.getXmlContent("./assets/blockly/leaphy-start.xml"), + ), + ) + .subscribe( + ([ + [[element, config], robotType], + baseToolboxXml, + leaphyToolboxXml, + startWorkspaceXml, + ]) => { + const leaphyBlocks = getBlocks( + this.appState.selectedRobotType.id, + ); + Blockly.defineBlocksWithJsonArray(leaphyBlocks.block); + config.theme = Blockly.Theme.defineTheme("leaphy", { + blockStyles: THEME.defaultBlockStyles, + categoryStyles: THEME.categoryStyles, + componentStyles: THEME.componentStyles, + name: "leaphy", + }); + const toolboxXmlString = this.loadToolBox( + baseToolboxXml, + leaphyToolboxXml, + robotType, + ); + config.toolbox = toolboxXmlString; + // @ts-ignore + const workspace = Blockly.inject(element, config); + const toolbox = workspace.getToolbox(); + workspace.registerToolboxCategoryCallback( + "LISTS", + CATEGORIES.LISTS, + ); + toolbox.getFlyout().autoClose = false; + const xml = Blockly.utils.xml.textToDom(startWorkspaceXml); + Blockly.Xml.domToWorkspace(xml, workspace); + this.blocklyState.workspace = workspace; + this.blocklyState.toolboxXml = toolboxXmlString; + if ( + this.appState.currentEditor == CodeEditorType.Beginner + ) { + this.workspaceService + .restoreWorkspaceTemp() + .then(() => {}); + } + toolbox.selectItemByPosition(0); + toolbox.refreshTheme(); + + setTimeout( + () => + (this.blocklyState.isSideNavOpen = + robotType.features.showCodeOnStart), + 200, + ); + }, + ); // When a new project is started, reset the blockly code this.appState.selectedRobotType$ - .pipe(filter(robotType => !robotType)) - .subscribe(() => this.codeEditorState.code = '') + .pipe(filter((robotType) => !robotType)) + .subscribe(() => (this.codeEditorState.code = "")); // When the robot selection changes, set the toolbox and initialWorkspace this.appState.selectedRobotType$ .pipe(withLatestFrom(this.blocklyState.workspace$)) - .pipe(filter(([robotType, workspace]) => !!robotType && !!workspace)) - .pipe(withLatestFrom( - this.getXmlContent('./assets/blockly/base-toolbox.xml'), - this.getXmlContent('./assets/blockly/leaphy-toolbox.xml'), - this.getXmlContent('./assets/blockly/leaphy-start.xml'), - )) - .subscribe(([[robotType, workspace], baseToolboxXml, leaphyToolboxXml, startWorkspaceXml]) => { - const toolboxXmlString = this.loadToolBox(baseToolboxXml, leaphyToolboxXml, robotType); - this.blocklyState.toolboxXml = toolboxXmlString; - - workspace.clear(); - const xml = Blockly.utils.xml.textToDom(startWorkspaceXml); - Blockly.Xml.domToWorkspace(xml, workspace); - }); + .pipe( + filter(([robotType, workspace]) => !!robotType && !!workspace), + ) + .pipe( + withLatestFrom( + this.getXmlContent("./assets/blockly/base-toolbox.xml"), + this.getXmlContent("./assets/blockly/leaphy-toolbox.xml"), + this.getXmlContent("./assets/blockly/leaphy-start.xml"), + ), + ) + .subscribe( + ([ + [robotType, workspace], + baseToolboxXml, + leaphyToolboxXml, + startWorkspaceXml, + ]) => { + const toolboxXmlString = this.loadToolBox( + baseToolboxXml, + leaphyToolboxXml, + robotType, + ); + this.blocklyState.toolboxXml = toolboxXmlString; + + workspace.clear(); + const xml = Blockly.utils.xml.textToDom(startWorkspaceXml); + Blockly.Xml.domToWorkspace(xml, workspace); + }, + ); // Update the toolbox when it changes this.blocklyState.toolboxXml$ .pipe(withLatestFrom(this.blocklyState.workspace$)) .pipe(filter(([toolbox, workspace]) => !!toolbox && !!workspace)) - .subscribe(([toolbox, workspace]) => workspace.updateToolbox(toolbox)) + .subscribe(([toolbox, workspace]) => + workspace.updateToolbox(toolbox), + ); // Subscribe to changes when the workspace is set this.blocklyState.workspace$ - .pipe(filter(workspace => !!workspace)) - .subscribe(workspace => { + .pipe(filter((workspace) => !!workspace)) + .subscribe((workspace) => { workspace.clearUndo(); workspace.addChangeListener(Blockly.Events.disableOrphans); workspace.addChangeListener(async () => { - if (this.appState.currentEditor !== CodeEditorType.Beginner) return; - this.codeEditorState.code = arduino.workspaceToCode(workspace, this.appState.selectedRobotType.id); - this.blocklyState.workspaceJSON = JSON.stringify(Blockly.serialization.workspaces.save(workspace)); + if (this.appState.currentEditor !== CodeEditorType.Beginner) + return; + this.codeEditorState.code = arduino.workspaceToCode( + workspace, + this.appState.selectedRobotType.id, + ); + this.blocklyState.workspaceJSON = JSON.stringify( + Blockly.serialization.workspaces.save(workspace), + ); }); - }); // When the user presses undo or redo, trigger undo or redo on the workspace @@ -152,12 +245,16 @@ export class BlocklyEditorEffects { .pipe(filter(([, workspace]) => !!workspace)) .subscribe(([redo, workspace]) => workspace.undo(redo)); - // When Advanced CodeEditor is Selected, hide the sideNav this.appState.codeEditor$ .pipe( pairwise(), - filter(([previous, current]) => (current === CodeEditorType.CPP || current === CodeEditorType.Python ) && current !== previous) + filter( + ([previous, current]) => + (current === CodeEditorType.CPP || + current === CodeEditorType.Python) && + current !== previous, + ), ) .subscribe(() => { this.blocklyState.isSideNavOpen = false; @@ -165,7 +262,10 @@ export class BlocklyEditorEffects { // Toggle the isSoundOn state this.blocklyState.isSoundToggled$ - .pipe(filter(isToggled => !!isToggled), withLatestFrom(this.blocklyState.isSoundOn$)) + .pipe( + filter((isToggled) => !!isToggled), + withLatestFrom(this.blocklyState.isSoundOn$), + ) .subscribe(([, isSoundOn]) => { this.blocklyState.isSoundOn = !isSoundOn; }); @@ -178,7 +278,10 @@ export class BlocklyEditorEffects { basePlay = Blockly.WorkspaceAudio.prototype.play; this.blocklyState.playSoundFunction = basePlay; } - Blockly.WorkspaceAudio.prototype.play = function (name, opt_volume) { + Blockly.WorkspaceAudio.prototype.play = function ( + name, + opt_volume, + ) { if (isSoundOn) { basePlay.call(this, name, opt_volume); } @@ -186,67 +289,107 @@ export class BlocklyEditorEffects { }); // When the code editor is changed, clear the projectFilePath - this.appState.codeEditor$ - .subscribe(() => this.blocklyState.projectFileHandle = null); + this.appState.codeEditor$.subscribe( + () => (this.blocklyState.projectFileHandle = null), + ); } - private parseCategory(root: Document, category: HTMLElement, robotType: RobotType,) : HTMLElement { + private parseCategory( + root: Document, + category: HTMLElement, + robotType: RobotType, + ): HTMLElement { // Remove blocks that aren't in robots list - Array.from(category.querySelectorAll('block')) - .filter(block => { - const robots = block.querySelector('robots'); + Array.from(category.querySelectorAll("block")) + .filter((block) => { + const robots = block.querySelector("robots"); if (!robots) return false; block.removeChild(robots); return !robots.querySelector(robotType.id); }) - .forEach(block => block.remove()); + .forEach((block) => block.remove()); // Add separator between groups - Array.from(category.querySelectorAll('group')) - .forEach(group => { - const items = Array.from(group.querySelectorAll('block')) - .map((block, index, array) => { - if (index === array.length - 1) return block - - const separator = root.createElement('sep') - separator.setAttribute('gap', '8') - return [block, separator] - }) - .flat() - - group.before(...items) - group.remove() - }) - - return category + Array.from(category.querySelectorAll("group")).forEach((group) => { + const items = Array.from(group.querySelectorAll("block")) + .map((block, index, array) => { + if (index === array.length - 1) return block; + + const separator = root.createElement("sep"); + separator.setAttribute("gap", "8"); + return [block, separator]; + }) + .flat(); + + group.before(...items); + group.remove(); + }); + + return category; } - private loadToolBox(baseToolboxXml: string, leaphyToolboxXml: string, robotType: RobotType) : string { + private loadToolBox( + baseToolboxXml: string, + leaphyToolboxXml: string, + robotType: RobotType, + ): string { const parser = new DOMParser(); - const toolboxXmlDoc = parser.parseFromString(baseToolboxXml, 'text/xml'); - const toolboxElement = toolboxXmlDoc.getElementById('easyBloqsToolbox'); - const leaphyCategories = parser.parseFromString(leaphyToolboxXml, 'text/xml'); - const leaphyRobotCategory = leaphyCategories.getElementById(robotType.id); + const toolboxXmlDoc = parser.parseFromString( + baseToolboxXml, + "text/xml", + ); + const toolboxElement = toolboxXmlDoc.getElementById("easyBloqsToolbox"); + const leaphyCategories = parser.parseFromString( + leaphyToolboxXml, + "text/xml", + ); + const leaphyRobotCategory = leaphyCategories.getElementById( + robotType.id, + ); if (robotType.features.showLeaphyOperators) { - toolboxElement.removeChild(toolboxXmlDoc.getElementById("l_numbers")) + toolboxElement.removeChild( + toolboxXmlDoc.getElementById("l_numbers"), + ); } else { - toolboxElement.removeChild(toolboxXmlDoc.getElementById("l_operators")) + toolboxElement.removeChild( + toolboxXmlDoc.getElementById("l_operators"), + ); } if (robotType.features.showLeaphyActuators) { - const leaphyExtraCategory = leaphyCategories.getElementById("l_actuators"); - leaphyExtraCategory.setAttribute("toolboxitemid", `${robotType.id}_actuators`) - - toolboxElement.prepend(this.parseCategory(leaphyCategories, leaphyExtraCategory, robotType)); + const leaphyExtraCategory = + leaphyCategories.getElementById("l_actuators"); + leaphyExtraCategory.setAttribute( + "toolboxitemid", + `${robotType.id}_actuators`, + ); + + toolboxElement.prepend( + this.parseCategory( + leaphyCategories, + leaphyExtraCategory, + robotType, + ), + ); } if (robotType.features.showLeaphySensors) { - const leaphySensorCategory = leaphyCategories.getElementById("l_sensors"); - leaphySensorCategory.setAttribute("toolboxitemid", `${robotType.id}_sensors`); - - toolboxElement.prepend(this.parseCategory(leaphyCategories, leaphySensorCategory, robotType)); + const leaphySensorCategory = + leaphyCategories.getElementById("l_sensors"); + leaphySensorCategory.setAttribute( + "toolboxitemid", + `${robotType.id}_sensors`, + ); + + toolboxElement.prepend( + this.parseCategory( + leaphyCategories, + leaphySensorCategory, + robotType, + ), + ); } if (!robotType.features.showLeaphyLists) { - toolboxElement.removeChild(toolboxXmlDoc.getElementById("l_lists")) + toolboxElement.removeChild(toolboxXmlDoc.getElementById("l_lists")); } if (leaphyRobotCategory) { toolboxElement.prepend(leaphyRobotCategory); @@ -256,15 +399,16 @@ export class BlocklyEditorEffects { } private getXmlContent(path: string): Observable { - return this.http - .get(path, { - headers: new HttpHeaders() - .set('Content-Type', 'text/xml') - .append('Access-Control-Allow-Methods', 'GET') - .append('Access-Control-Allow-Origin', '*') - .append('Access-Control-Allow-Headers', - 'Access-Control-Allow-Headers, Access-Control-Allow-Origin, Access-Control-Request-Method'), - responseType: 'text' - }) + return this.http.get(path, { + headers: new HttpHeaders() + .set("Content-Type", "text/xml") + .append("Access-Control-Allow-Methods", "GET") + .append("Access-Control-Allow-Origin", "*") + .append( + "Access-Control-Allow-Headers", + "Access-Control-Allow-Headers, Access-Control-Allow-Origin, Access-Control-Request-Method", + ), + responseType: "text", + }); } } diff --git a/src/app/effects/code-editor.effects.ts b/src/app/effects/code-editor.effects.ts index 41300c82..38503211 100644 --- a/src/app/effects/code-editor.effects.ts +++ b/src/app/effects/code-editor.effects.ts @@ -1,35 +1,34 @@ -import {Injectable} from "@angular/core"; -import {CodeEditorState} from "../state/code-editor.state"; -import {AppState} from "../state/app.state"; -import {CodeEditorType} from "../domain/code-editor.type"; -import {genericRobotType} from "../domain/robots"; -import {WorkspaceService} from "../services/workspace.service"; - +import { Injectable } from "@angular/core"; +import { CodeEditorState } from "../state/code-editor.state"; +import { AppState } from "../state/app.state"; +import { CodeEditorType } from "../domain/code-editor.type"; +import { genericRobotType } from "../domain/robots"; +import { WorkspaceService } from "../services/workspace.service"; @Injectable({ - providedIn: 'root', + providedIn: "root", }) // Defines the effects on the Editor that different state changes have export class CodeEditorEffects { - constructor( private codeEditorState: CodeEditorState, private appState: AppState, private workspaceService: WorkspaceService, ) { - this.appState.codeEditor$ - .subscribe(codeEditor => { - console.log('codeEditor', codeEditor); - if (codeEditor == CodeEditorType.Python) { - this.codeEditorState.code = `from leaphymicropython.utils.pins import set_pwm`; - this.workspaceService.restoreWorkspaceTemp().then(() => {}); - } else if (codeEditor == CodeEditorType.CPP && this.appState.selectedRobotType == genericRobotType) { - this.codeEditorState.code = this.codeEditorState.code = `void leaphyProgram() {\n\n}\n\nvoid setup() {\n leaphyProgram();\n}\n\nvoid loop() {\n\n}`; - this.workspaceService.restoreWorkspaceTemp().then(() => {}); - } - }); + this.appState.codeEditor$.subscribe((codeEditor) => { + console.log("codeEditor", codeEditor); + if (codeEditor == CodeEditorType.Python) { + this.codeEditorState.code = `from leaphymicropython.utils.pins import set_pwm`; + this.workspaceService.restoreWorkspaceTemp().then(() => {}); + } else if ( + codeEditor == CodeEditorType.CPP && + this.appState.selectedRobotType == genericRobotType + ) { + this.codeEditorState.code = + this.codeEditorState.code = `void leaphyProgram() {\n\n}\n\nvoid setup() {\n leaphyProgram();\n}\n\nvoid loop() {\n\n}`; + this.workspaceService.restoreWorkspaceTemp().then(() => {}); + } + }); } - - } diff --git a/src/app/effects/dialog.effects.ts b/src/app/effects/dialog.effects.ts index 903b52b9..6c99ff2b 100644 --- a/src/app/effects/dialog.effects.ts +++ b/src/app/effects/dialog.effects.ts @@ -1,40 +1,39 @@ -import { Injectable } from '@angular/core'; -import { MatDialog } from '@angular/material/dialog'; -import { filter } from 'rxjs/operators'; -import { DialogState } from '../state/dialog.state'; -import { CreditsDialog } from '../modules/core/dialogs/credits/credits.dialog'; -import { InfoDialog } from '../modules/core/dialogs/info/info.dialog'; -import { ConfirmEditorDialog } from '../modules/core/dialogs/confirm-editor/confirm-editor.dialog'; -import { LanguageSelectDialog } from '../modules/core/dialogs/language-select/language-select.dialog'; -import {SerialOutputComponent} from "../modules/shared/components/serial-output/serial-output.component"; -import {AppState} from "../state/app.state"; -import {LibraryManagerComponent} from "../modules/shared/components/library-manager/library-manager.component"; -import {ExamplesDialog} from "../modules/core/dialogs/examples/examples-dialog.component"; +import { Injectable } from "@angular/core"; +import { MatDialog } from "@angular/material/dialog"; +import { filter } from "rxjs/operators"; +import { DialogState } from "../state/dialog.state"; +import { CreditsDialog } from "../modules/core/dialogs/credits/credits.dialog"; +import { InfoDialog } from "../modules/core/dialogs/info/info.dialog"; +import { ConfirmEditorDialog } from "../modules/core/dialogs/confirm-editor/confirm-editor.dialog"; +import { LanguageSelectDialog } from "../modules/core/dialogs/language-select/language-select.dialog"; +import { SerialOutputComponent } from "../modules/shared/components/serial-output/serial-output.component"; +import { AppState } from "../state/app.state"; +import { LibraryManagerComponent } from "../modules/shared/components/library-manager/library-manager.component"; +import { ExamplesDialog } from "../modules/core/dialogs/examples/examples-dialog.component"; @Injectable({ - providedIn: 'root', + providedIn: "root", }) // Defines the effects on the Dialog that different state changes have export class DialogEffects { - constructor( private appState: AppState, private dialogState: DialogState, private dialog: MatDialog, ) { this.dialogState.isExamplesDialogVisible$ - .pipe(filter(isVisible => !!isVisible)) + .pipe(filter((isVisible) => !!isVisible)) .subscribe(() => { this.dialog.open(ExamplesDialog, { width: "800px", disableClose: true, - }) - }) + }); + }); // When the info dialog visibility is set to true, open the dialog this.dialogState.isInfoDialogVisible$ - .pipe(filter(isVisible => !!isVisible)) + .pipe(filter((isVisible) => !!isVisible)) .subscribe(() => { this.dialog.open(InfoDialog, { width: "800px", @@ -43,54 +42,69 @@ export class DialogEffects { }); // If the isSerialOutputWindowOpen is set to true open the dialog - this.dialogState.isSerialOutputWindowOpen$ - .subscribe(() => { - if (this.dialogState.isSerialOutputWindowOpen !== true) - return; - this.dialog.open(SerialOutputComponent, { + this.dialogState.isSerialOutputWindowOpen$.subscribe(() => { + if (this.dialogState.isSerialOutputWindowOpen !== true) return; + this.dialog + .open(SerialOutputComponent, { width: "800px", disableClose: true, hasBackdrop: false, - }).afterClosed().subscribe(() => { + }) + .afterClosed() + .subscribe(() => { this.dialogState.isSerialOutputWindowOpen = false; }); - }); - + }); // If the isLibraryManagerWindowOpen is set to true open the dialog - this.dialogState.isLibraryManagerWindowOpen$ - .subscribe(() => { - if (this.dialogState.isLibraryManagerWindowOpen !== true) - return; - this.dialog.open(LibraryManagerComponent, { + this.dialogState.isLibraryManagerWindowOpen$.subscribe(() => { + if (this.dialogState.isLibraryManagerWindowOpen !== true) return; + this.dialog + .open(LibraryManagerComponent, { disableClose: true, - }).afterClosed().subscribe(() => { + }) + .afterClosed() + .subscribe(() => { this.dialogState.isLibraryManagerWindowOpen = false; }); - }); + }); - const language = localStorage.getItem('currentLanguage'); + const language = localStorage.getItem("currentLanguage"); if (!language) { const languageDialogRef = this.dialog.open(LanguageSelectDialog, { - width: '450px', + width: "450px", disableClose: true, }); languageDialogRef.afterClosed().subscribe(() => { - this.dialog.open(CreditsDialog, { - width: '800px', - disableClose: true, - }).afterClosed().subscribe(() => { - (async () => { - if (localStorage.getItem("showReleaseNotes") === "0") return - this.appState.releaseInfoSubject$.next(await fetch("https://api.github.com/repos/leaphy-robotics/leaphy-webbased/releases/latest").then(response => response.json())); - })(); - }); + this.dialog + .open(CreditsDialog, { + width: "800px", + disableClose: true, + }) + .afterClosed() + .subscribe(() => { + (async () => { + if ( + localStorage.getItem("showReleaseNotes") === "0" + ) + return; + this.appState.releaseInfoSubject$.next( + await fetch( + "https://api.github.com/repos/leaphy-robotics/leaphy-webbased/releases/latest", + ).then((response) => response.json()), + ); + })(); + }); }); } else { (async () => { - if (localStorage.getItem("showReleaseNotes") === "0") return - this.appState.releaseInfoSubject$.next(await fetch("https://api.github.com/repos/leaphy-robotics/leaphy-webbased/releases/latest").then(response => response.json())); + if (localStorage.getItem("showReleaseNotes") === "0") return; + this.appState.releaseInfoSubject$.next( + await fetch( + "https://api.github.com/repos/leaphy-robotics/leaphy-webbased/releases/latest", + ).then((response) => response.json()), + ); })(); } } diff --git a/src/app/effects/robot.wired.effects.ts b/src/app/effects/robot.wired.effects.ts index 9ea48705..ba0a74f6 100644 --- a/src/app/effects/robot.wired.effects.ts +++ b/src/app/effects/robot.wired.effects.ts @@ -1,15 +1,14 @@ -import { Injectable } from '@angular/core'; -import { filter } from 'rxjs/operators'; -import { RobotWiredState } from '../state/robot.wired.state'; -import {DialogState} from "../state/dialog.state"; +import { Injectable } from "@angular/core"; +import { filter } from "rxjs/operators"; +import { RobotWiredState } from "../state/robot.wired.state"; +import { DialogState } from "../state/dialog.state"; import ArduinoUploader from "../services/arduino-uploader/ArduinoUploader"; -import {AppState} from "../state/app.state"; -import {UploadState} from "../state/upload.state"; +import { AppState } from "../state/app.state"; +import { UploadState } from "../state/upload.state"; @Injectable({ - providedIn: 'root', + providedIn: "root", }) - export class RobotWiredEffects { private webserial: ArduinoUploader; private logBuffer: string = ""; @@ -20,13 +19,16 @@ export class RobotWiredEffects { private uploadState: UploadState, private dialogState: DialogState, ) { - this.webserial = new ArduinoUploader(this.robotWiredState, this.appState, this.uploadState); + this.webserial = new ArduinoUploader( + this.robotWiredState, + this.appState, + this.uploadState, + ); this.dialogState.isSerialOutputListening$ - .pipe(filter(isListening => !!isListening)) + .pipe(filter((isListening) => !!isListening)) .subscribe(async () => { - if (this.robotWiredState.pythonDeviceConnected) - return; + if (this.robotWiredState.pythonDeviceConnected) return; const robotWiredState = this.robotWiredState; const outputStream = new WritableStream({ @@ -34,18 +36,23 @@ export class RobotWiredEffects { this.logBuffer = ""; }, write: async (chunk) => { - this.logBuffer += new TextDecoder("utf-8").decode(chunk); + this.logBuffer += new TextDecoder("utf-8").decode( + chunk, + ); const date = new Date(); - function makeString (chunkedStr: string) { - robotWiredState.incomingSerialData = { time: date, data: chunkedStr }; + function makeString(chunkedStr: string) { + robotWiredState.incomingSerialData = { + time: date, + data: chunkedStr, + }; } let i = this.logBuffer.indexOf("\n"); await new Promise((resolve) => { // Give the browser time to render/update the dialog - setTimeout(resolve, 1) - }) + setTimeout(resolve, 1); + }); while (i != -1) { let part = this.logBuffer.slice(0, i); this.logBuffer = this.logBuffer.slice(i + 1); @@ -65,6 +72,4 @@ export class RobotWiredEffects { this.webserial.serialMonitor(outputStream).then(() => {}); }); } - - } diff --git a/src/app/modules/blockly-editor/blockly-editor.module.ts b/src/app/modules/blockly-editor/blockly-editor.module.ts index 7d54b254..f9cefe90 100644 --- a/src/app/modules/blockly-editor/blockly-editor.module.ts +++ b/src/app/modules/blockly-editor/blockly-editor.module.ts @@ -1,18 +1,14 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; +import { NgModule } from "@angular/core"; +import { CommonModule } from "@angular/common"; -import { LeaphyBlocklyComponent } from './components/leaphy-blockly/leaphy-blockly.component'; -import { CodeViewComponent } from './components/code-view/code-view.component'; -import { SharedModule } from '../shared/shared.module'; -import {MonacoEditorModule} from "ngx-monaco-editor-v2"; +import { LeaphyBlocklyComponent } from "./components/leaphy-blockly/leaphy-blockly.component"; +import { CodeViewComponent } from "./components/code-view/code-view.component"; +import { SharedModule } from "../shared/shared.module"; +import { MonacoEditorModule } from "ngx-monaco-editor-v2"; @NgModule({ declarations: [LeaphyBlocklyComponent, CodeViewComponent], - imports: [ - CommonModule, - SharedModule, - MonacoEditorModule - ], + imports: [CommonModule, SharedModule, MonacoEditorModule], exports: [LeaphyBlocklyComponent, CodeViewComponent], }) -export class BlocklyEditorModule { } +export class BlocklyEditorModule {} diff --git a/src/app/modules/blockly-editor/blockly-editor.page.html b/src/app/modules/blockly-editor/blockly-editor.page.html index 57818636..8b57ae70 100644 --- a/src/app/modules/blockly-editor/blockly-editor.page.html +++ b/src/app/modules/blockly-editor/blockly-editor.page.html @@ -3,9 +3,16 @@ - + - + diff --git a/src/app/modules/blockly-editor/blockly-editor.page.scss b/src/app/modules/blockly-editor/blockly-editor.page.scss index 805701c9..9d34ef94 100644 --- a/src/app/modules/blockly-editor/blockly-editor.page.scss +++ b/src/app/modules/blockly-editor/blockly-editor.page.scss @@ -1,32 +1,32 @@ #container { - display: flex; - flex-direction: row; - align-items: stretch; - height: calc(100% - 64px); - width: 100%; - overflow: hidden; + display: flex; + flex-direction: row; + align-items: stretch; + height: calc(100% - 64px); + width: 100%; + overflow: hidden; } .sidenav-container { - flex: 1 1 auto; - background: #eee; + flex: 1 1 auto; + background: #eee; } #sidenav { - height: 100%; - width: 20%; + height: 100%; + width: 20%; } app-code-view { - display: block; - height: 100%; + display: block; + height: 100%; } app-button-bar { - pointer-events: none; - position: absolute; - right: 0; - top: 0; - z-index: 2; - transition: right ease-out 0.25s; + pointer-events: none; + position: absolute; + right: 0; + top: 0; + z-index: 2; + transition: right ease-out 0.25s; } diff --git a/src/app/modules/blockly-editor/blockly-editor.page.spec.ts b/src/app/modules/blockly-editor/blockly-editor.page.spec.ts index 2c98e2f5..44ea5644 100644 --- a/src/app/modules/blockly-editor/blockly-editor.page.spec.ts +++ b/src/app/modules/blockly-editor/blockly-editor.page.spec.ts @@ -1,25 +1,24 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; -import { BlocklyEditorPage } from './blockly-editor.page'; +import { BlocklyEditorPage } from "./blockly-editor.page"; -describe('BlocklyEditorPage', () => { - let component: BlocklyEditorPage; - let fixture: ComponentFixture; +describe("BlocklyEditorPage", () => { + let component: BlocklyEditorPage; + let fixture: ComponentFixture; - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ BlocklyEditorPage ] - }) - .compileComponents(); - })); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [BlocklyEditorPage], + }).compileComponents(); + })); - beforeEach(() => { - fixture = TestBed.createComponent(BlocklyEditorPage); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(BlocklyEditorPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it("should create", () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/modules/blockly-editor/blockly-editor.page.ts b/src/app/modules/blockly-editor/blockly-editor.page.ts index c44767f3..d2fda5f0 100644 --- a/src/app/modules/blockly-editor/blockly-editor.page.ts +++ b/src/app/modules/blockly-editor/blockly-editor.page.ts @@ -1,30 +1,27 @@ -import {Component} from '@angular/core'; -import {BlocklyEditorState} from 'src/app/state/blockly-editor.state'; -import {CommonModule} from "@angular/common"; -import {SharedModule} from "../shared/shared.module"; -import {BlocklyEditorModule} from "./blockly-editor.module"; -import {WorkspaceService} from "../../services/workspace.service"; +import { Component } from "@angular/core"; +import { BlocklyEditorState } from "src/app/state/blockly-editor.state"; +import { CommonModule } from "@angular/common"; +import { SharedModule } from "../shared/shared.module"; +import { BlocklyEditorModule } from "./blockly-editor.module"; +import { WorkspaceService } from "../../services/workspace.service"; @Component({ standalone: true, - selector: 'app-blockly-editor', - templateUrl: './blockly-editor.page.html', - styleUrls: ['./blockly-editor.page.scss'], - imports: [ - CommonModule, - SharedModule, - BlocklyEditorModule - ], + selector: "app-blockly-editor", + templateUrl: "./blockly-editor.page.html", + styleUrls: ["./blockly-editor.page.scss"], + imports: [CommonModule, SharedModule, BlocklyEditorModule], }) - export class BlocklyEditorPage { constructor( public blocklyState: BlocklyEditorState, private blocklyEditorState: BlocklyEditorState, - private workspaceService: WorkspaceService + private workspaceService: WorkspaceService, ) { window.addEventListener("beforeunload", async (event) => { - this.workspaceService.saveWorkspaceTemp(this.blocklyEditorState.workspaceJSON); + this.workspaceService.saveWorkspaceTemp( + this.blocklyEditorState.workspaceJSON, + ); }); } } diff --git a/src/app/modules/blockly-editor/components/code-view/code-view.component.scss b/src/app/modules/blockly-editor/components/code-view/code-view.component.scss index c69eb81f..2b52e80d 100644 --- a/src/app/modules/blockly-editor/components/code-view/code-view.component.scss +++ b/src/app/modules/blockly-editor/components/code-view/code-view.component.scss @@ -1,6 +1,6 @@ .code-view { - width: 100%; - height: 100%; - margin: 0; - overflow-x: scroll; + width: 100%; + height: 100%; + margin: 0; + overflow-x: scroll; } diff --git a/src/app/modules/blockly-editor/components/code-view/code-view.component.spec.ts b/src/app/modules/blockly-editor/components/code-view/code-view.component.spec.ts index edfe7e3b..73adac73 100644 --- a/src/app/modules/blockly-editor/components/code-view/code-view.component.spec.ts +++ b/src/app/modules/blockly-editor/components/code-view/code-view.component.spec.ts @@ -1,25 +1,24 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; -import { CodeViewComponent } from './code-view.component'; +import { CodeViewComponent } from "./code-view.component"; -describe('CodeViewComponent', () => { - let component: CodeViewComponent; - let fixture: ComponentFixture; +describe("CodeViewComponent", () => { + let component: CodeViewComponent; + let fixture: ComponentFixture; - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ CodeViewComponent ] - }) - .compileComponents(); - })); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [CodeViewComponent], + }).compileComponents(); + })); - beforeEach(() => { - fixture = TestBed.createComponent(CodeViewComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(CodeViewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it("should create", () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/modules/blockly-editor/components/code-view/code-view.component.ts b/src/app/modules/blockly-editor/components/code-view/code-view.component.ts index d568a89a..4fac14fc 100644 --- a/src/app/modules/blockly-editor/components/code-view/code-view.component.ts +++ b/src/app/modules/blockly-editor/components/code-view/code-view.component.ts @@ -1,18 +1,17 @@ -import {Component} from '@angular/core'; -import {CodeEditorState} from "../../../../state/code-editor.state"; +import { Component } from "@angular/core"; +import { CodeEditorState } from "../../../../state/code-editor.state"; @Component({ - selector: 'app-code-view', - templateUrl: './code-view.component.html', - styleUrls: ['./code-view.component.scss'] + selector: "app-code-view", + templateUrl: "./code-view.component.html", + styleUrls: ["./code-view.component.scss"], }) export class CodeViewComponent { editorOptions = { - language: 'cpp', + language: "cpp", readOnly: true, - automaticLayout: true - } + automaticLayout: true, + }; - constructor(public codeEditor: CodeEditorState) { - } + constructor(public codeEditor: CodeEditorState) {} } diff --git a/src/app/modules/blockly-editor/components/leaphy-blockly/backpack.plugin.ts b/src/app/modules/blockly-editor/components/leaphy-blockly/backpack.plugin.ts index 968bbb57..dc94ae38 100644 --- a/src/app/modules/blockly-editor/components/leaphy-blockly/backpack.plugin.ts +++ b/src/app/modules/blockly-editor/components/leaphy-blockly/backpack.plugin.ts @@ -1,4 +1,4 @@ -import { Backpack as BaseBackpack } from '@blockly/workspace-backpack'; +import { Backpack as BaseBackpack } from "@blockly/workspace-backpack"; import Blockly from "blockly/core"; export class Backpack extends BaseBackpack { @@ -16,11 +16,12 @@ export class Backpack extends BaseBackpack { rtl: this.workspace_.RTL, oneBasedIndex: this.workspace_.options.oneBasedIndex, renderer: this.workspace_.options.renderer, - rendererOverrides: this.workspace_.options.rendererOverrides || undefined, + rendererOverrides: + this.workspace_.options.rendererOverrides || undefined, move: { scrollbars: true, }, - toolboxPosition: 'left' + toolboxPosition: "left", }); // Create flyout. @@ -37,7 +38,7 @@ export class Backpack extends BaseBackpack { this.flyout_.init(this.workspace_); } override addBlock(block: Blockly.Block) { - if (block.type === 'leaphy_start') { + if (block.type === "leaphy_start") { this.addBlocks(block.getChildren(false)); block.getChildren(false).forEach((child) => { setTimeout(() => child.dispose(undefined), 0); @@ -51,12 +52,17 @@ export class Backpack extends BaseBackpack { setTimeout(() => block.dispose(undefined), 0); } - override position(metrics: Blockly.MetricsManager.UiMetrics, savedPositions: Blockly.utils.Rect[]) { + override position( + metrics: Blockly.MetricsManager.UiMetrics, + savedPositions: Blockly.utils.Rect[], + ) { const toolbox = this.workspace_.getToolbox(); this.left_ = metrics.absoluteMetrics.left + - (!toolbox.getFlyout().isVisible() ? -toolbox.getFlyout().getWidth() : 0) + + (!toolbox.getFlyout().isVisible() + ? -toolbox.getFlyout().getWidth() + : 0) + this.MARGIN_HORIZONTAL_; this.top_ = @@ -68,10 +74,9 @@ export class Backpack extends BaseBackpack { if (this.svgGroup_) { this.svgGroup_.setAttribute( - 'transform', + "transform", `translate(${this.left_},${this.top_})`, ); } } } - diff --git a/src/app/modules/blockly-editor/components/leaphy-blockly/leaphy-blockly.component.html b/src/app/modules/blockly-editor/components/leaphy-blockly/leaphy-blockly.component.html index a200bfaa..b7a8799c 100644 --- a/src/app/modules/blockly-editor/components/leaphy-blockly/leaphy-blockly.component.html +++ b/src/app/modules/blockly-editor/components/leaphy-blockly/leaphy-blockly.component.html @@ -1,6 +1,11 @@
-
- @if (background) { - - } +
+ @if (background) { + + }
diff --git a/src/app/modules/blockly-editor/components/leaphy-blockly/leaphy-blockly.component.scss b/src/app/modules/blockly-editor/components/leaphy-blockly/leaphy-blockly.component.scss index 991ebdf6..b472857e 100644 --- a/src/app/modules/blockly-editor/components/leaphy-blockly/leaphy-blockly.component.scss +++ b/src/app/modules/blockly-editor/components/leaphy-blockly/leaphy-blockly.component.scss @@ -1,4 +1,5 @@ -.workspace-container, #blockly-container { +.workspace-container, +#blockly-container { top: 0px; width: 100%; height: 100%; diff --git a/src/app/modules/blockly-editor/components/leaphy-blockly/leaphy-blockly.component.spec.ts b/src/app/modules/blockly-editor/components/leaphy-blockly/leaphy-blockly.component.spec.ts index 87dbcf5f..18db7c58 100644 --- a/src/app/modules/blockly-editor/components/leaphy-blockly/leaphy-blockly.component.spec.ts +++ b/src/app/modules/blockly-editor/components/leaphy-blockly/leaphy-blockly.component.spec.ts @@ -1,25 +1,24 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; -import { LeaphyBlocklyComponent } from './leaphy-blockly.component'; +import { LeaphyBlocklyComponent } from "./leaphy-blockly.component"; -describe('LeaphyBlocklyComponent', () => { - let component: LeaphyBlocklyComponent; - let fixture: ComponentFixture; +describe("LeaphyBlocklyComponent", () => { + let component: LeaphyBlocklyComponent; + let fixture: ComponentFixture; - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ LeaphyBlocklyComponent ] - }) - .compileComponents(); - })); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [LeaphyBlocklyComponent], + }).compileComponents(); + })); - beforeEach(() => { - fixture = TestBed.createComponent(LeaphyBlocklyComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(LeaphyBlocklyComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it("should create", () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/modules/blockly-editor/components/leaphy-blockly/leaphy-blockly.component.ts b/src/app/modules/blockly-editor/components/leaphy-blockly/leaphy-blockly.component.ts index 21217887..986e962a 100644 --- a/src/app/modules/blockly-editor/components/leaphy-blockly/leaphy-blockly.component.ts +++ b/src/app/modules/blockly-editor/components/leaphy-blockly/leaphy-blockly.component.ts @@ -1,87 +1,92 @@ -import { - Component, - ViewChild, - ElementRef, - AfterViewInit, -} from '@angular/core'; -import { BlocklyEditorState } from 'src/app/state/blockly-editor.state'; -import {Backpack} from "./backpack.plugin"; -import Blockly from 'blockly/core'; -import {BackpackChange} from "@blockly/workspace-backpack/dist"; -import {AppState} from "src/app/state/app.state"; -import {WorkspaceSvg} from "blockly"; +import { Component, ViewChild, ElementRef, AfterViewInit } from "@angular/core"; +import { BlocklyEditorState } from "src/app/state/blockly-editor.state"; +import { Backpack } from "./backpack.plugin"; +import Blockly from "blockly/core"; +import { BackpackChange } from "@blockly/workspace-backpack/dist"; +import { AppState } from "src/app/state/app.state"; +import { WorkspaceSvg } from "blockly"; type Background = { - src: string, - x: string, -} + src: string; + x: string; +}; @Component({ - selector: 'app-leaphy-blockly', - templateUrl: './leaphy-blockly.component.html', - styleUrls: ['./leaphy-blockly.component.scss'] + selector: "app-leaphy-blockly", + templateUrl: "./leaphy-blockly.component.html", + styleUrls: ["./leaphy-blockly.component.scss"], }) export class LeaphyBlocklyComponent implements AfterViewInit { + @ViewChild("blockContent") blockContent: ElementRef; - @ViewChild('blockContent') blockContent: ElementRef; - - public background: Background - private workspace: WorkspaceSvg + public background: Background; + private workspace: WorkspaceSvg; constructor( public appState: AppState, public blocklyState: BlocklyEditorState, ) { - appState.selectedRobotType$.subscribe(robot => { - if (!robot?.background) return this.background = null + appState.selectedRobotType$.subscribe((robot) => { + if (!robot?.background) return (this.background = null); if (this.background) { - this.background.src = robot.background + this.background.src = robot.background; } else { this.background = { src: robot.background, - x: '50%' - } + x: "50%", + }; } - }) + }); - window.addEventListener('resize', this.updateSizing.bind(this)) + window.addEventListener("resize", this.updateSizing.bind(this)); } updateSizing() { - if (!this.background || !this.workspace) return + if (!this.background || !this.workspace) return; const toolbox = this.workspace.getToolbox(); - this.background.x = `${window.innerWidth / 2 + (toolbox.getFlyout().isVisible() ? toolbox.getFlyout().getWidth() : 0)/2 + 40}px` + this.background.x = `${window.innerWidth / 2 + (toolbox.getFlyout().isVisible() ? toolbox.getFlyout().getWidth() : 0) / 2 + 40}px`; } ngAfterViewInit() { this.blocklyState.blocklyElement = this.blockContent.nativeElement; - this.blocklyState.workspace$.subscribe(workspace => { - this.workspace = workspace + this.blocklyState.workspace$.subscribe((workspace) => { + this.workspace = workspace; workspace.addChangeListener((event: any) => { // @ts-ignore - if (!(event.type === "toolbox_item_select")) {return} + if (!(event.type === "toolbox_item_select")) { + return; + } workspace.resize(); - }) + }); - workspace.addChangeListener(this.updateSizing.bind(this)) + workspace.addChangeListener(this.updateSizing.bind(this)); if (!workspace.backpack) { const backpack = new Backpack(workspace); workspace.backpack = backpack; - Blockly.registry.unregister(Blockly.registry.Type.SERIALIZER, "backpack") - - - backpack.setContents(JSON.parse(localStorage.getItem('backpack')) || []); - workspace.addChangeListener((event: Blockly.Events.Abstract) => { - if (!(event instanceof BackpackChange)) return; - - localStorage.setItem('backpack', JSON.stringify(backpack.getContents())); - }); + Blockly.registry.unregister( + Blockly.registry.Type.SERIALIZER, + "backpack", + ); + + backpack.setContents( + JSON.parse(localStorage.getItem("backpack")) || [], + ); + workspace.addChangeListener( + (event: Blockly.Events.Abstract) => { + if (!(event instanceof BackpackChange)) return; + + localStorage.setItem( + "backpack", + JSON.stringify(backpack.getContents()), + ); + }, + ); backpack.init(); } - }) + }); } } diff --git a/src/app/modules/code-editor-cpp/code-editor-cpp.page.scss b/src/app/modules/code-editor-cpp/code-editor-cpp.page.scss index e06ddb52..d6ab890e 100644 --- a/src/app/modules/code-editor-cpp/code-editor-cpp.page.scss +++ b/src/app/modules/code-editor-cpp/code-editor-cpp.page.scss @@ -4,27 +4,27 @@ } #container { - display: flex; - flex-direction: row; - align-items: stretch; - height: calc(100% - 64px); - width: 100%; - overflow: hidden; + display: flex; + flex-direction: row; + align-items: stretch; + height: calc(100% - 64px); + width: 100%; + overflow: hidden; } .sidenav-container { - flex: 1 1 auto; - background: #eee; + flex: 1 1 auto; + background: #eee; } #sidenav { - min-width: 20%; + min-width: 20%; } app-button-bar { - pointer-events: none; - position: absolute; - right: 0; - top: 0; - z-index: 5; + pointer-events: none; + position: absolute; + right: 0; + top: 0; + z-index: 5; } diff --git a/src/app/modules/code-editor-cpp/code-editor-cpp.page.spec.ts b/src/app/modules/code-editor-cpp/code-editor-cpp.page.spec.ts index 6204a897..8a16ad8c 100644 --- a/src/app/modules/code-editor-cpp/code-editor-cpp.page.spec.ts +++ b/src/app/modules/code-editor-cpp/code-editor-cpp.page.spec.ts @@ -1,25 +1,24 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ComponentFixture, TestBed } from "@angular/core/testing"; -import { CodeEditorCppPage } from './code-editor-cpp.page'; +import { CodeEditorCppPage } from "./code-editor-cpp.page"; -describe('CodeEditorPage', () => { - let component: CodeEditorCppPage; - let fixture: ComponentFixture; +describe("CodeEditorPage", () => { + let component: CodeEditorCppPage; + let fixture: ComponentFixture; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ CodeEditorCppPage ] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [CodeEditorCppPage], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(CodeEditorCppPage); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(CodeEditorCppPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it("should create", () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/modules/code-editor-cpp/code-editor-cpp.page.ts b/src/app/modules/code-editor-cpp/code-editor-cpp.page.ts index 82f4e0ce..8702b8dd 100644 --- a/src/app/modules/code-editor-cpp/code-editor-cpp.page.ts +++ b/src/app/modules/code-editor-cpp/code-editor-cpp.page.ts @@ -1,38 +1,34 @@ -import {AfterViewInit, Component, ElementRef, ViewChild} from '@angular/core'; -import {CodeEditorState} from 'src/app/state/code-editor.state'; -import {CommonModule} from "@angular/common"; -import {SharedModule} from "../shared/shared.module"; -import {CoreModule} from "../core/core.module"; -import {WorkspaceService} from "../../services/workspace.service"; -import {MonacoEditorModule} from "ngx-monaco-editor-v2"; - +import { AfterViewInit, Component, ElementRef, ViewChild } from "@angular/core"; +import { CodeEditorState } from "src/app/state/code-editor.state"; +import { CommonModule } from "@angular/common"; +import { SharedModule } from "../shared/shared.module"; +import { CoreModule } from "../core/core.module"; +import { WorkspaceService } from "../../services/workspace.service"; +import { MonacoEditorModule } from "ngx-monaco-editor-v2"; @Component({ standalone: true, - selector: 'app-code-editor-cpp', - templateUrl: './code-editor-cpp.page.html', - styleUrls: ['./code-editor-cpp.page.scss'], - imports: [ - CommonModule, - SharedModule, - CoreModule, - MonacoEditorModule - ] + selector: "app-code-editor-cpp", + templateUrl: "./code-editor-cpp.page.html", + styleUrls: ["./code-editor-cpp.page.scss"], + imports: [CommonModule, SharedModule, CoreModule, MonacoEditorModule], }) export class CodeEditorCppPage implements AfterViewInit { editorOptions = { - language: 'cpp', - automaticLayout: true - } + language: "cpp", + automaticLayout: true, + }; constructor( public codeEditorState: CodeEditorState, - private workspaceService: WorkspaceService + private workspaceService: WorkspaceService, ) {} ngAfterViewInit(): void { window.addEventListener("beforeunload", async () => { - await this.workspaceService.saveWorkspaceTemp(this.codeEditorState.code); + await this.workspaceService.saveWorkspaceTemp( + this.codeEditorState.code, + ); }); } } diff --git a/src/app/modules/code-editor-python/code-editor-python.page.scss b/src/app/modules/code-editor-python/code-editor-python.page.scss index f77a4adb..ee901bd8 100644 --- a/src/app/modules/code-editor-python/code-editor-python.page.scss +++ b/src/app/modules/code-editor-python/code-editor-python.page.scss @@ -1,6 +1,6 @@ .monaco-editor { width: 100%; - height: 80% + height: 80%; } #container { diff --git a/src/app/modules/code-editor-python/code-editor-python.page.spec.ts b/src/app/modules/code-editor-python/code-editor-python.page.spec.ts index 927af20a..d72f0e01 100644 --- a/src/app/modules/code-editor-python/code-editor-python.page.spec.ts +++ b/src/app/modules/code-editor-python/code-editor-python.page.spec.ts @@ -1,25 +1,24 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ComponentFixture, TestBed } from "@angular/core/testing"; -import { CodeEditorPythonPage } from './code-editor-python.page'; +import { CodeEditorPythonPage } from "./code-editor-python.page"; -describe('CodeEditorPythonPage', () => { - let component: CodeEditorPythonPage; - let fixture: ComponentFixture; +describe("CodeEditorPythonPage", () => { + let component: CodeEditorPythonPage; + let fixture: ComponentFixture; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ CodeEditorPythonPage ] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [CodeEditorPythonPage], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(CodeEditorPythonPage); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(CodeEditorPythonPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it("should create", () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/modules/code-editor-python/code-editor-python.page.ts b/src/app/modules/code-editor-python/code-editor-python.page.ts index f0b8e847..45a2fd92 100644 --- a/src/app/modules/code-editor-python/code-editor-python.page.ts +++ b/src/app/modules/code-editor-python/code-editor-python.page.ts @@ -1,38 +1,34 @@ -import {AfterViewInit, Component, ElementRef, ViewChild} from '@angular/core'; -import {CodeEditorState} from 'src/app/state/code-editor.state'; -import {CommonModule} from "@angular/common"; -import {SharedModule} from "../shared/shared.module"; -import {CoreModule} from "../core/core.module"; -import {WorkspaceService} from "../../services/workspace.service"; -import {MonacoEditorModule} from "ngx-monaco-editor-v2"; - +import { AfterViewInit, Component, ElementRef, ViewChild } from "@angular/core"; +import { CodeEditorState } from "src/app/state/code-editor.state"; +import { CommonModule } from "@angular/common"; +import { SharedModule } from "../shared/shared.module"; +import { CoreModule } from "../core/core.module"; +import { WorkspaceService } from "../../services/workspace.service"; +import { MonacoEditorModule } from "ngx-monaco-editor-v2"; @Component({ - selector: 'app-code-editor-python', + selector: "app-code-editor-python", standalone: true, - templateUrl: './code-editor-python.page.html', - styleUrls: ['./code-editor-python.page.scss'], - imports: [ - CommonModule, - SharedModule, - CoreModule, - MonacoEditorModule - ] + templateUrl: "./code-editor-python.page.html", + styleUrls: ["./code-editor-python.page.scss"], + imports: [CommonModule, SharedModule, CoreModule, MonacoEditorModule], }) export class CodeEditorPythonPage implements AfterViewInit { editorOptions = { - language: 'python', - automaticLayout: true - } + language: "python", + automaticLayout: true, + }; constructor( public codeEditorState: CodeEditorState, - private workspaceService: WorkspaceService + private workspaceService: WorkspaceService, ) {} ngAfterViewInit(): void { window.addEventListener("beforeunload", async () => { - await this.workspaceService.saveWorkspaceTemp(this.codeEditorState.code); - }) + await this.workspaceService.saveWorkspaceTemp( + this.codeEditorState.code, + ); + }); } } diff --git a/src/app/modules/components/header/header.component.html b/src/app/modules/components/header/header.component.html index d4a6cc8b..49eef160 100644 --- a/src/app/modules/components/header/header.component.html +++ b/src/app/modules/components/header/header.component.html @@ -1,9 +1,16 @@ - +
- @if (isDriverIssuesUrl() && this.appState.selectedRobotType$ | async) { + @if ( + isDriverIssuesUrl() && this.appState.selectedRobotType$ | async + ) { @@ -13,24 +20,43 @@ - @if ((this.appState.selectedRobotType$ | async) !== microPythonRobotType) { + @if ( + (this.appState.selectedRobotType$ | async) !== + microPythonRobotType + ) { } } @if (!isDriverIssuesUrl()) { - + }
- @if (isDriverIssuesUrl() && this.appState.selectedRobotType$ | async) { - - } @@ -38,35 +64,78 @@
- @if (isDriverIssuesUrl() && this.appState.selectedRobotType$ | async) { + @if ( + isDriverIssuesUrl() && this.appState.selectedRobotType$ | async + ) { @if ((appState.codeEditor$ | async) === 1) { - } @if ((appState.codeEditor$ | async) === 2) { - } @if (this.appState.selectedRobotType$ | async) { - @if ((appState.selectedRobotType$ | async) !== microPythonRobotType) { - } - @if ((appState.selectedRobotType$ | async) === microPythonRobotType) { - } - @if ((robotWiredState.isPythonDeviceConnected$ | async) === true) { - } @@ -75,43 +144,71 @@
@if ((this.appState.selectedRobotType$ | async) === null) { -
{{ (appState.releaseVersion) }}
+
{{ appState.releaseVersion }}
}
- - - - - - - - @@ -127,13 +224,13 @@ {{ "LANGUAGE" | translate }} - @@ -153,12 +254,17 @@ @for (language of AppState.availableLanguages; track language) { - } - - - diff --git a/src/app/modules/components/header/header.component.scss b/src/app/modules/components/header/header.component.scss index 970144fb..f4735927 100644 --- a/src/app/modules/components/header/header.component.scss +++ b/src/app/modules/components/header/header.component.scss @@ -62,7 +62,10 @@ mat-button-toggle { font-weight: normal; } -::ng-deep .mat-button-toggle-group-appearance-standard .mat-button-toggle + .mat-button-toggle { +::ng-deep + .mat-button-toggle-group-appearance-standard + .mat-button-toggle + + .mat-button-toggle { border-color: var(--leaphy-color-secundary) !important; } @@ -72,7 +75,9 @@ mat-button-toggle { font-weight: bold; } -::ng-deep .mat-button-toggle-appearance-standard .mat-button-toggle-label-content { +::ng-deep + .mat-button-toggle-appearance-standard + .mat-button-toggle-label-content { line-height: 10px; } diff --git a/src/app/modules/components/header/header.component.spec.ts b/src/app/modules/components/header/header.component.spec.ts index 48d26266..0d4caadd 100644 --- a/src/app/modules/components/header/header.component.spec.ts +++ b/src/app/modules/components/header/header.component.spec.ts @@ -1,25 +1,24 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; -import { HeaderComponent } from './header.component'; +import { HeaderComponent } from "./header.component"; -describe('HeaderComponent', () => { - let component: HeaderComponent; - let fixture: ComponentFixture; +describe("HeaderComponent", () => { + let component: HeaderComponent; + let fixture: ComponentFixture; - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ HeaderComponent ] - }) - .compileComponents(); - })); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [HeaderComponent], + }).compileComponents(); + })); - beforeEach(() => { - fixture = TestBed.createComponent(HeaderComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(HeaderComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it("should create", () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/modules/components/header/header.component.ts b/src/app/modules/components/header/header.component.ts index 41e4b6ee..3228030d 100644 --- a/src/app/modules/components/header/header.component.ts +++ b/src/app/modules/components/header/header.component.ts @@ -1,30 +1,29 @@ -import {Component, HostListener} from '@angular/core'; -import {AppState} from 'src/app/state/app.state'; -import {BlocklyEditorState} from 'src/app/state/blockly-editor.state'; -import {DialogState} from 'src/app/state/dialog.state'; -import {Language} from 'src/app/domain/language'; -import {Router} from "@angular/router"; -import {CodeEditorType} from "../../../domain/code-editor.type"; -import {RobotWiredState} from "../../../state/robot.wired.state"; -import {MatSnackBar} from "@angular/material/snack-bar"; -import JSZip from 'jszip'; -import {microPythonRobotType} from "../../../domain/robots"; -import {DebugInformationDialog} from "../../core/dialogs/debug-information/debug-information.dialog"; -import {MatDialog} from "@angular/material/dialog"; -import {UploadDialog} from "../../core/dialogs/upload/upload.dialog"; -import {CodeEditorState} from "../../../state/code-editor.state"; -import {PythonUploaderService} from "../../../services/python-uploader/PythonUploader.service"; -import {ConnectPythonDialog} from "../../core/dialogs/connect-python/connect-python.dialog"; -import {StatusMessageDialog} from "../../core/dialogs/status-message/status-message.dialog"; -import {WorkspaceService} from "../../../services/workspace.service"; +import { Component, HostListener } from "@angular/core"; +import { AppState } from "src/app/state/app.state"; +import { BlocklyEditorState } from "src/app/state/blockly-editor.state"; +import { DialogState } from "src/app/state/dialog.state"; +import { Language } from "src/app/domain/language"; +import { Router } from "@angular/router"; +import { CodeEditorType } from "../../../domain/code-editor.type"; +import { RobotWiredState } from "../../../state/robot.wired.state"; +import { MatSnackBar } from "@angular/material/snack-bar"; +import JSZip from "jszip"; +import { microPythonRobotType } from "../../../domain/robots"; +import { DebugInformationDialog } from "../../core/dialogs/debug-information/debug-information.dialog"; +import { MatDialog } from "@angular/material/dialog"; +import { UploadDialog } from "../../core/dialogs/upload/upload.dialog"; +import { CodeEditorState } from "../../../state/code-editor.state"; +import { PythonUploaderService } from "../../../services/python-uploader/PythonUploader.service"; +import { ConnectPythonDialog } from "../../core/dialogs/connect-python/connect-python.dialog"; +import { StatusMessageDialog } from "../../core/dialogs/status-message/status-message.dialog"; +import { WorkspaceService } from "../../../services/workspace.service"; @Component({ - selector: 'app-header', - templateUrl: './header.component.html', - styleUrls: ['./header.component.scss'], + selector: "app-header", + templateUrl: "./header.component.html", + styleUrls: ["./header.component.scss"], }) export class HeaderComponent { - constructor( public appState: AppState, public blocklyState: BlocklyEditorState, @@ -35,10 +34,8 @@ export class HeaderComponent { private dialog: MatDialog, private codeEditorState: CodeEditorState, private uploaderService: PythonUploaderService, - private workspaceService: WorkspaceService - ) { - - } + private workspaceService: WorkspaceService, + ) {} public onNewProjectClicked() { this.appState.setSelectedRobotType(null); @@ -52,7 +49,8 @@ export class HeaderComponent { // check the GitHub api for what files we need to download with url: https://api.github.com/repos/leaphy-robotics/leaphy-firmware/ // then download the files with the url: https://raw.githubusercontent.com/leaphy-robotics/leaphy-firmware/master/drivers/ // then zip the files into one file and download them all - const url = 'https://api.github.com/repos/leaphy-robotics/leaphy-firmware/contents/drivers'; + const url = + "https://api.github.com/repos/leaphy-robotics/leaphy-firmware/contents/drivers"; const response = await fetch(url); const data = await response.json(); const files = []; @@ -62,34 +60,38 @@ export class HeaderComponent { const zip = new JSZip(); const promises = []; for (const file of files) { - promises.push(fetch(file).then(response => response.blob()).then(blob => { - zip.file(file.split('/').pop(), blob); - })); + promises.push( + fetch(file) + .then((response) => response.blob()) + .then((blob) => { + zip.file(file.split("/").pop(), blob); + }), + ); } await Promise.all(promises); - const content = await zip.generateAsync({type: 'blob'}); - const a = document.createElement('a'); + const content = await zip.generateAsync({ type: "blob" }); + const a = document.createElement("a"); const url2 = URL.createObjectURL(content); a.href = url2; - a.download = 'leaphy-drivers.zip'; + a.download = "leaphy-drivers.zip"; a.click(); URL.revokeObjectURL(url2); } public async onChooseRobot() { - const port = await this.robotWiredState.requestSerialPort(true) + const port = await this.robotWiredState.requestSerialPort(true); if (port !== this.robotWiredState.serialPort) { - await port.open({baudRate: 115200}); + await port.open({ baudRate: 115200 }); this.robotWiredState.serialPort = port; this.dialogState.isSerialOutputListening = true; } this.snackBar.openFromComponent(StatusMessageDialog, { duration: 2000, - horizontalPosition: 'center', - verticalPosition: 'bottom', - data: { message: "CONNECTED" } - }) + horizontalPosition: "center", + verticalPosition: "bottom", + data: { message: "CONNECTED" }, + }); } public onSaveWorkspaceClicked() { @@ -97,9 +99,9 @@ export class HeaderComponent { } // To capture the keyboard shortcut for Saving a project - @HostListener('window:keydown', ['$event']) + @HostListener("window:keydown", ["$event"]) onCtrlS(event: KeyboardEvent) { - if ((event.metaKey || event.ctrlKey) && event.key === 's') { + if ((event.metaKey || event.ctrlKey) && event.key === "s") { this.onSaveWorkspaceClicked(); event.preventDefault(); } @@ -110,47 +112,71 @@ export class HeaderComponent { } public onSaveWorkspaceAsClicked() { - this.workspaceService.saveWorkspaceAs(this.appState.selectedRobotType.id).then(() => {}); + this.workspaceService + .saveWorkspaceAs(this.appState.selectedRobotType.id) + .then(() => {}); } public onConnectClicked() { - this.dialog.open(ConnectPythonDialog, { - width: '600px', disableClose: true, - }).afterClosed().subscribe((result) => { - if (result) { - if (result == "HELP_ENVIRONMENT") { - const langcode = this.appState.currentLanguageCode; - this.router.navigateByUrl('/' + langcode + '/driverissues', {skipLocationChange: true}).then(() => {}); + this.dialog + .open(ConnectPythonDialog, { + width: "600px", + disableClose: true, + }) + .afterClosed() + .subscribe((result) => { + if (result) { + if (result == "HELP_ENVIRONMENT") { + const langcode = this.appState.currentLanguageCode; + this.router + .navigateByUrl("/" + langcode + "/driverissues", { + skipLocationChange: true, + }) + .then(() => {}); + } } - } - }); + }); } public async onRunClicked() { const robotType = this.appState.selectedRobotType; const code = this.codeEditorState.code; const libraries = [...robotType.libs]; - libraries.push(...this.codeEditorState.installedLibraries.map(lib => `${lib.name}@${lib.version}`)); + libraries.push( + ...this.codeEditorState.installedLibraries.map( + (lib) => `${lib.name}@${lib.version}`, + ), + ); try { if (this.appState.currentEditor == CodeEditorType.Python) { - await this.uploaderService.runCode(code) + await this.uploaderService.runCode(code); } else { - this.dialog.open(UploadDialog, { - width: '450px', disableClose: true, - data: {source_code: code, libraries: libraries, board: robotType.fqbn} - }).afterClosed().subscribe((result) => { - if (result) { - if (result == "HELP_ENVIRONMENT") { - const langcode = this.appState.currentLanguageCode; - this.router.navigateByUrl('/' + langcode + '/driverissues', {skipLocationChange: true}); + this.dialog + .open(UploadDialog, { + width: "450px", + disableClose: true, + data: { + source_code: code, + libraries: libraries, + board: robotType.fqbn, + }, + }) + .afterClosed() + .subscribe((result) => { + if (result) { + if (result == "HELP_ENVIRONMENT") { + const langcode = + this.appState.currentLanguageCode; + this.router.navigateByUrl( + "/" + langcode + "/driverissues", + { skipLocationChange: true }, + ); + } } - } - }); + }); } - - } catch (error) { - console.log('Error:', error.message); + console.log("Error:", error.message); } } @@ -163,19 +189,21 @@ export class HeaderComponent { } public onHelpClicked() { - window.open("https://discord.com/invite/Yeg7Kkrq5W", '_blank').focus() + window.open("https://discord.com/invite/Yeg7Kkrq5W", "_blank").focus(); } public onEmailClicked() { // copy email to clipboard - navigator.clipboard.writeText('helpdesk@leaphy.org').then(function() {}); - this.snackBar.open('Email copied to clipboard', 'Close', { + navigator.clipboard + .writeText("helpdesk@leaphy.org") + .then(function () {}); + this.snackBar.open("Email copied to clipboard", "Close", { duration: 2000, }); } isDriverIssuesUrl(): boolean { - return !(this.router.url.endsWith('driverissues')); + return !this.router.url.endsWith("driverissues"); } public onShowInfoClicked() { @@ -199,19 +227,23 @@ export class HeaderComponent { public onBackToBlocks() { if (this.appState.currentEditor == CodeEditorType.Beginner) - this.router.navigate(['/blocks'], {skipLocationChange: true}).then(() => {}); + this.router + .navigate(["/blocks"], { skipLocationChange: true }) + .then(() => {}); else if (this.appState.currentEditor == CodeEditorType.CPP) - this.router.navigate(['/cppEditor'], { skipLocationChange: true }).then(() => {}); + this.router + .navigate(["/cppEditor"], { skipLocationChange: true }) + .then(() => {}); else if (this.appState.currentEditor == CodeEditorType.Python) - this.router.navigate(['/pythonEditor'], { skipLocationChange: true }).then(() => {}); + this.router + .navigate(["/pythonEditor"], { skipLocationChange: true }) + .then(() => {}); } public onExamplesClicked() { - this.dialogState.isExamplesDialogVisible = true + this.dialogState.isExamplesDialogVisible = true; } protected readonly AppState = AppState; protected readonly microPythonRobotType = microPythonRobotType; } - - diff --git a/src/app/modules/components/robot-selection/robot-selection.component.html b/src/app/modules/components/robot-selection/robot-selection.component.html index f0ab0ea1..3271fcce 100644 --- a/src/app/modules/components/robot-selection/robot-selection.component.html +++ b/src/app/modules/components/robot-selection/robot-selection.component.html @@ -1,17 +1,23 @@
@for (row of robots; track row) { -
+
@for (robot of row; track robot) { -
- - -

{{robot.name}}

-
+
+ +

{{ robot.name }}

+
}
} diff --git a/src/app/modules/components/robot-selection/robot-selection.component.scss b/src/app/modules/components/robot-selection/robot-selection.component.scss index ab5ceeb9..0fa0bb13 100644 --- a/src/app/modules/components/robot-selection/robot-selection.component.scss +++ b/src/app/modules/components/robot-selection/robot-selection.component.scss @@ -1,5 +1,3 @@ - - .robot-name { margin-top: 10px; } @@ -54,14 +52,14 @@ } h1 { - font-family: 'Inter', sans-serif; + font-family: "Inter", sans-serif; font-size: 24px; line-height: 35px; font-weight: 700; } h3 { - font-family: 'Inter', sans-serif; + font-family: "Inter", sans-serif; font-size: 17px; line-height: 28px; font-weight: 400; diff --git a/src/app/modules/components/robot-selection/robot-selection.component.spec.ts b/src/app/modules/components/robot-selection/robot-selection.component.spec.ts index 2e83838a..f13aceef 100644 --- a/src/app/modules/components/robot-selection/robot-selection.component.spec.ts +++ b/src/app/modules/components/robot-selection/robot-selection.component.spec.ts @@ -1,25 +1,24 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; -import { RobotSelectionComponent } from './robot-selection.component'; +import { RobotSelectionComponent } from "./robot-selection.component"; -describe('RobotSelectionComponent', () => { - let component: RobotSelectionComponent; - let fixture: ComponentFixture; +describe("RobotSelectionComponent", () => { + let component: RobotSelectionComponent; + let fixture: ComponentFixture; - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ RobotSelectionComponent ] - }) - .compileComponents(); - })); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [RobotSelectionComponent], + }).compileComponents(); + })); - beforeEach(() => { - fixture = TestBed.createComponent(RobotSelectionComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(RobotSelectionComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it("should create", () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/modules/components/robot-selection/robot-selection.component.ts b/src/app/modules/components/robot-selection/robot-selection.component.ts index 12cac8b7..2697b2e5 100644 --- a/src/app/modules/components/robot-selection/robot-selection.component.ts +++ b/src/app/modules/components/robot-selection/robot-selection.component.ts @@ -1,57 +1,72 @@ -import {Component, Input} from '@angular/core'; -import {AppState} from 'src/app/state/app.state'; -import {RobotEntry, RobotType} from 'src/app/domain/robot.type'; -import {CodeEditorType} from "../../../domain/code-editor.type"; -import {animate, state, style, transition, trigger} from "@angular/animations"; +import { Component, Input } from "@angular/core"; +import { AppState } from "src/app/state/app.state"; +import { RobotEntry, RobotType } from "src/app/domain/robot.type"; +import { CodeEditorType } from "../../../domain/code-editor.type"; +import { + animate, + state, + style, + transition, + trigger, +} from "@angular/animations"; @Component({ - selector: 'app-robot-selection', - templateUrl: './robot-selection.component.html', - styleUrls: ['./robot-selection.component.scss'], + selector: "app-robot-selection", + templateUrl: "./robot-selection.component.html", + styleUrls: ["./robot-selection.component.scss"], animations: [ - trigger('swipe', [ - state('center', style({ - translate: '-50%', - background: '#ffffff00' - })), - state('left', style({ - translate: '-100%', - background: '#ffffff00' - })), - state('right', style({ - translate: '0', - background: '#fff' - })), - transition('center => left', [ - animate('.3s ease-out') + trigger("swipe", [ + state( + "center", + style({ + translate: "-50%", + background: "#ffffff00", + }), + ), + state( + "left", + style({ + translate: "-100%", + background: "#ffffff00", + }), + ), + state( + "right", + style({ + translate: "0", + background: "#fff", + }), + ), + transition("center => left", [animate(".3s ease-out")]), + transition("void => right", [ + style({ translate: "50vw", background: "#ffffff00" }), + animate(".3s ease-out"), ]), - transition('void => right', [ - style({ translate: '50vw', background: '#ffffff00' }), - animate('.3s ease-out') - ]) - ]) - ] + ]), + ], }) export class RobotSelectionComponent { - @Input() secondary = false - @Input() state = 'center' - @Input() robots: (any)[][] - @Input() selected: RobotType = null + @Input() secondary = false; + @Input() state = "center"; + @Input() robots: any[][]; + @Input() selected: RobotType = null; - constructor(public appState: AppState) { } - public onRobotSelected(robotInstance: RobotType|RobotEntry) { - const robot = robotInstance instanceof RobotType ? robotInstance : robotInstance.robot + constructor(public appState: AppState) {} + public onRobotSelected(robotInstance: RobotType | RobotEntry) { + const robot = + robotInstance instanceof RobotType + ? robotInstance + : robotInstance.robot; // checked this.appState.setSelectedRobotType(robot, this.secondary); - if (robot.id === 'l_code') { - this.appState.selectedCodeEditor = CodeEditorType.CPP - } else if (robot.id === 'l_micropython') { - this.appState.selectedCodeEditor = CodeEditorType.Python + if (robot.id === "l_code") { + this.appState.selectedCodeEditor = CodeEditorType.CPP; + } else if (robot.id === "l_micropython") { + this.appState.selectedCodeEditor = CodeEditorType.Python; } else { - this.appState.selectedCodeEditor = CodeEditorType.Beginner + this.appState.selectedCodeEditor = CodeEditorType.Beginner; } - } protected readonly AppState = AppState; diff --git a/src/app/modules/components/start/start.component.html b/src/app/modules/components/start/start.component.html index 42945dfd..695a7724 100644 --- a/src/app/modules/components/start/start.component.html +++ b/src/app/modules/components/start/start.component.html @@ -1,10 +1,14 @@
- - @if (selector) { - - } + + @if (selector) { + + }
diff --git a/src/app/modules/components/start/start.component.spec.ts b/src/app/modules/components/start/start.component.spec.ts index 500fa09e..9f1191d6 100644 --- a/src/app/modules/components/start/start.component.spec.ts +++ b/src/app/modules/components/start/start.component.spec.ts @@ -1,25 +1,24 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; -import { StartComponent } from './start.component'; +import { StartComponent } from "./start.component"; -describe('StartComponent', () => { - let component: StartComponent; - let fixture: ComponentFixture; +describe("StartComponent", () => { + let component: StartComponent; + let fixture: ComponentFixture; - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ StartComponent ] - }) - .compileComponents(); - })); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [StartComponent], + }).compileComponents(); + })); - beforeEach(() => { - fixture = TestBed.createComponent(StartComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(StartComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it("should create", () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/modules/components/start/start.component.ts b/src/app/modules/components/start/start.component.ts index 47d6d7d3..7c43cfa8 100644 --- a/src/app/modules/components/start/start.component.ts +++ b/src/app/modules/components/start/start.component.ts @@ -1,6 +1,6 @@ -import {Component} from "@angular/core"; -import {AppState} from "src/app/state/app.state"; -import {RobotSelector} from "../../../domain/robot.type"; +import { Component } from "@angular/core"; +import { AppState } from "src/app/state/app.state"; +import { RobotSelector } from "../../../domain/robot.type"; @Component({ selector: "app-start", @@ -8,11 +8,11 @@ import {RobotSelector} from "../../../domain/robot.type"; styleUrls: ["./start.component.scss"], }) export class StartComponent { - public selector: RobotSelector|null = null + public selector: RobotSelector | null = null; constructor(public appState: AppState) { - appState.robotChoice$.subscribe(selector => { - this.selector = selector - }) + appState.robotChoice$.subscribe((selector) => { + this.selector = selector; + }); } } diff --git a/src/app/modules/core/core.module.ts b/src/app/modules/core/core.module.ts index abe7a016..a4ff99d8 100644 --- a/src/app/modules/core/core.module.ts +++ b/src/app/modules/core/core.module.ts @@ -1,27 +1,27 @@ -import { NgModule } from '@angular/core'; -import {CommonModule, NgOptimizedImage} from '@angular/common'; -import { SharedModule } from '../shared/shared.module'; +import { NgModule } from "@angular/core"; +import { CommonModule, NgOptimizedImage } from "@angular/common"; +import { SharedModule } from "../shared/shared.module"; -import { HeaderComponent } from '../components/header/header.component'; -import { RobotSelectionComponent } from '../components/robot-selection/robot-selection.component'; -import { StartComponent } from '../components/start/start.component'; +import { HeaderComponent } from "../components/header/header.component"; +import { RobotSelectionComponent } from "../components/robot-selection/robot-selection.component"; +import { StartComponent } from "../components/start/start.component"; -import { StatusMessageDialog } from './dialogs/status-message/status-message.dialog'; -import { CreditsDialog } from './dialogs/credits/credits.dialog'; -import { InfoDialog } from './dialogs/info/info.dialog'; -import { ConfirmEditorDialog } from './dialogs/confirm-editor/confirm-editor.dialog'; -import { LanguageSelectDialog } from './dialogs/language-select/language-select.dialog'; -import {NameFileDialog} from "./dialogs/name-file/name-file.dialog"; -import {VariableDialog} from "./dialogs/variable/variable.dialog"; -import {UploadDialog} from "./dialogs/upload/upload.dialog"; -import {DebugInformationDialog} from "./dialogs/debug-information/debug-information.dialog"; -import {DragDropModule} from "@angular/cdk/drag-drop"; -import { SelectRobotTypeDialog } from './dialogs/robot-select/robot-select.dialog'; -import {ConnectPythonDialog} from "./dialogs/connect-python/connect-python.dialog"; -import {FileExplorerDialog} from "./dialogs/file-explorer/file-explorer.dialog"; -import {ChangeLogDialog} from "./dialogs/change-log/change-log.dialog"; -import {LocationSelectDialog} from "./dialogs/location-select/location-select.dialog"; -import {ExamplesDialog} from "./dialogs/examples/examples-dialog.component"; +import { StatusMessageDialog } from "./dialogs/status-message/status-message.dialog"; +import { CreditsDialog } from "./dialogs/credits/credits.dialog"; +import { InfoDialog } from "./dialogs/info/info.dialog"; +import { ConfirmEditorDialog } from "./dialogs/confirm-editor/confirm-editor.dialog"; +import { LanguageSelectDialog } from "./dialogs/language-select/language-select.dialog"; +import { NameFileDialog } from "./dialogs/name-file/name-file.dialog"; +import { VariableDialog } from "./dialogs/variable/variable.dialog"; +import { UploadDialog } from "./dialogs/upload/upload.dialog"; +import { DebugInformationDialog } from "./dialogs/debug-information/debug-information.dialog"; +import { DragDropModule } from "@angular/cdk/drag-drop"; +import { SelectRobotTypeDialog } from "./dialogs/robot-select/robot-select.dialog"; +import { ConnectPythonDialog } from "./dialogs/connect-python/connect-python.dialog"; +import { FileExplorerDialog } from "./dialogs/file-explorer/file-explorer.dialog"; +import { ChangeLogDialog } from "./dialogs/change-log/change-log.dialog"; +import { LocationSelectDialog } from "./dialogs/location-select/location-select.dialog"; +import { ExamplesDialog } from "./dialogs/examples/examples-dialog.component"; @NgModule({ declarations: [ @@ -42,14 +42,9 @@ import {ExamplesDialog} from "./dialogs/examples/examples-dialog.component"; DebugInformationDialog, ChangeLogDialog, InfoDialog, - ExamplesDialog - ], - imports: [ - CommonModule, - SharedModule, - NgOptimizedImage, - DragDropModule, + ExamplesDialog, ], + imports: [CommonModule, SharedModule, NgOptimizedImage, DragDropModule], exports: [ HeaderComponent, StartComponent, @@ -59,7 +54,7 @@ import {ExamplesDialog} from "./dialogs/examples/examples-dialog.component"; StatusMessageDialog, CreditsDialog, LanguageSelectDialog, - InfoDialog - ] + InfoDialog, + ], }) -export class CoreModule { } +export class CoreModule {} diff --git a/src/app/modules/core/dialogs/change-log/change-log.dialog.html b/src/app/modules/core/dialogs/change-log/change-log.dialog.html index 9dc9eb56..307a9cca 100644 --- a/src/app/modules/core/dialogs/change-log/change-log.dialog.html +++ b/src/app/modules/core/dialogs/change-log/change-log.dialog.html @@ -1,11 +1,15 @@

- -
-
+ +
- +
diff --git a/src/app/modules/core/dialogs/change-log/change-log.dialog.scss b/src/app/modules/core/dialogs/change-log/change-log.dialog.scss index 42a74cea..510827ff 100644 --- a/src/app/modules/core/dialogs/change-log/change-log.dialog.scss +++ b/src/app/modules/core/dialogs/change-log/change-log.dialog.scss @@ -20,7 +20,9 @@ form { border: none; border-radius: 4px; cursor: pointer; - transition: background-color 0.3s, color 0.3s; + transition: + background-color 0.3s, + color 0.3s; margin-top: 10px; align-self: center; diff --git a/src/app/modules/core/dialogs/change-log/change-log.dialog.spec.ts b/src/app/modules/core/dialogs/change-log/change-log.dialog.spec.ts index 30f8ff23..fe505b8c 100644 --- a/src/app/modules/core/dialogs/change-log/change-log.dialog.spec.ts +++ b/src/app/modules/core/dialogs/change-log/change-log.dialog.spec.ts @@ -1,25 +1,24 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; -import { ChangeLogDialog } from './change-log.dialog'; +import { ChangeLogDialog } from "./change-log.dialog"; -describe('ChangeLogDialog Component', () => { - let component: ChangeLogDialog; - let fixture: ComponentFixture; +describe("ChangeLogDialog Component", () => { + let component: ChangeLogDialog; + let fixture: ComponentFixture; - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ ChangeLogDialog ] - }) - .compileComponents(); - })); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [ChangeLogDialog], + }).compileComponents(); + })); - beforeEach(() => { - fixture = TestBed.createComponent(ChangeLogDialog); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(ChangeLogDialog); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it("should create", () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/modules/core/dialogs/change-log/change-log.dialog.ts b/src/app/modules/core/dialogs/change-log/change-log.dialog.ts index 39866f52..c44cd9e1 100644 --- a/src/app/modules/core/dialogs/change-log/change-log.dialog.ts +++ b/src/app/modules/core/dialogs/change-log/change-log.dialog.ts @@ -1,20 +1,19 @@ -import {AfterViewInit, Component, Inject} from '@angular/core'; -import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import { AfterViewInit, Component, Inject } from "@angular/core"; +import { MAT_DIALOG_DATA, MatDialogRef } from "@angular/material/dialog"; @Component({ - selector: 'app-change-log', - templateUrl: './change-log.dialog.html', - styleUrls: ['./change-log.dialog.scss'] + selector: "app-change-log", + templateUrl: "./change-log.dialog.html", + styleUrls: ["./change-log.dialog.scss"], }) export class ChangeLogDialog implements AfterViewInit { - constructor( @Inject(MAT_DIALOG_DATA) public data: any, - public dialogRef: MatDialogRef + public dialogRef: MatDialogRef, ) {} public onConfirm(dontRepeat = false) { - localStorage.setItem("showReleaseNotes", dontRepeat ? "0" : "1") + localStorage.setItem("showReleaseNotes", dontRepeat ? "0" : "1"); this.dialogRef.close(); } diff --git a/src/app/modules/core/dialogs/confirm-editor/confirm-editor.dialog.html b/src/app/modules/core/dialogs/confirm-editor/confirm-editor.dialog.html index 43f9f700..8b42dd44 100644 --- a/src/app/modules/core/dialogs/confirm-editor/confirm-editor.dialog.html +++ b/src/app/modules/core/dialogs/confirm-editor/confirm-editor.dialog.html @@ -1,6 +1,4 @@ -

- {{ "CONFIRMEDITORCHANGE_TITLE" | translate }} -

+

{{ "CONFIRMEDITORCHANGE_TITLE" | translate }}

{{ "EDITORCHANGEINSTRUCTIONS"|translate }}

diff --git a/src/app/modules/core/dialogs/confirm-editor/confirm-editor.dialog.spec.ts b/src/app/modules/core/dialogs/confirm-editor/confirm-editor.dialog.spec.ts index 9d898e59..5eed460f 100644 --- a/src/app/modules/core/dialogs/confirm-editor/confirm-editor.dialog.spec.ts +++ b/src/app/modules/core/dialogs/confirm-editor/confirm-editor.dialog.spec.ts @@ -1,25 +1,24 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; -import { ConfirmEditorDialog } from './confirm-editor.dialog'; +import { ConfirmEditorDialog } from "./confirm-editor.dialog"; -describe('ConfirmEditorDialog', () => { - let component: ConfirmEditorDialog; - let fixture: ComponentFixture; +describe("ConfirmEditorDialog", () => { + let component: ConfirmEditorDialog; + let fixture: ComponentFixture; - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ ConfirmEditorDialog ] - }) - .compileComponents(); - })); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [ConfirmEditorDialog], + }).compileComponents(); + })); - beforeEach(() => { - fixture = TestBed.createComponent(ConfirmEditorDialog); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(ConfirmEditorDialog); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it("should create", () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/modules/core/dialogs/confirm-editor/confirm-editor.dialog.ts b/src/app/modules/core/dialogs/confirm-editor/confirm-editor.dialog.ts index 50268f44..453b8d7d 100644 --- a/src/app/modules/core/dialogs/confirm-editor/confirm-editor.dialog.ts +++ b/src/app/modules/core/dialogs/confirm-editor/confirm-editor.dialog.ts @@ -1,19 +1,19 @@ -import {Component, Inject} from '@angular/core'; -import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; -import {AppState} from 'src/app/state/app.state'; +import { Component, Inject } from "@angular/core"; +import { MAT_DIALOG_DATA, MatDialogRef } from "@angular/material/dialog"; +import { AppState } from "src/app/state/app.state"; @Component({ - selector: 'app-confirm-editor', - templateUrl: './confirm-editor.dialog.html', - styleUrls: ['../dialog-styles.scss', './confirm-editor.dialog.scss'] + selector: "app-confirm-editor", + templateUrl: "./confirm-editor.dialog.html", + styleUrls: ["../dialog-styles.scss", "./confirm-editor.dialog.scss"], }) export class ConfirmEditorDialog { constructor( public dialogRef: MatDialogRef, public appState: AppState, - ) { } + ) {} public close(confirm: boolean) { - this.dialogRef.close(confirm) + this.dialogRef.close(confirm); } } diff --git a/src/app/modules/core/dialogs/connect-python/connect-python.dialog.html b/src/app/modules/core/dialogs/connect-python/connect-python.dialog.html index 49904363..928badeb 100644 --- a/src/app/modules/core/dialogs/connect-python/connect-python.dialog.html +++ b/src/app/modules/core/dialogs/connect-python/connect-python.dialog.html @@ -1,29 +1,48 @@
- @if ((didUpload | async) === true && (uploadFailed | async) === false) { + @if ((didUpload | async) === true && (uploadFailed | async) === false) {

{{ statusMessage }}

- } - @if ((didUpload | async) === true && (uploadFailed | async) === true) { + } @if ((didUpload | async) === true && (uploadFailed | async) === true) {
{{ statusMessage }}
- } - @if ((uploading | async) && (uploadFailed | async) === false) { + } @if ((uploading | async) && (uploadFailed | async) === false) {

{{ statusMessage }}

- - } - @if ((firmwareWriting | async) && (uploadFailed | async) === false && (didUpload | async) === false) { + + } @if ((firmwareWriting | async) && (uploadFailed | async) === false && + (didUpload | async) === false) {

{{ statusMessage }}

- - } - @if ((didUpload | async) === false && (uploading | async) === false && (firmwareWriting | async) === false) { + + } @if ((didUpload | async) === false && (uploading | async) === false && + (firmwareWriting | async) === false) { - - {{ "FLASH_FIRMWARE" | translate }} - } - @if (didUpload | async) { + + {{ "FLASH_FIRMWARE" | translate }} + } @if (didUpload | async) {
- - @if (uploadFailed | async) { - - } + + @if (uploadFailed | async) { + + }
- } + }
diff --git a/src/app/modules/core/dialogs/connect-python/connect-python.dialog.scss b/src/app/modules/core/dialogs/connect-python/connect-python.dialog.scss index 5658287a..097423f4 100644 --- a/src/app/modules/core/dialogs/connect-python/connect-python.dialog.scss +++ b/src/app/modules/core/dialogs/connect-python/connect-python.dialog.scss @@ -25,7 +25,9 @@ border: none; border-radius: 4px; cursor: pointer; - transition: background-color 0.3s, color 0.3s; + transition: + background-color 0.3s, + color 0.3s; margin-top: 10px; align-self: center; @@ -44,7 +46,9 @@ border: none; border-radius: 4px; cursor: pointer; - transition: background-color 0.3s, color 0.3s; + transition: + background-color 0.3s, + color 0.3s; margin-top: 10px; align-self: center; @@ -75,7 +79,9 @@ border: none; border-radius: 4px; cursor: pointer; - transition: background-color 0.3s, color 0.3s; + transition: + background-color 0.3s, + color 0.3s; margin-top: 10px; align-self: center; diff --git a/src/app/modules/core/dialogs/connect-python/connect-python.dialog.spec.ts b/src/app/modules/core/dialogs/connect-python/connect-python.dialog.spec.ts index 25725e7a..1ced16fc 100644 --- a/src/app/modules/core/dialogs/connect-python/connect-python.dialog.spec.ts +++ b/src/app/modules/core/dialogs/connect-python/connect-python.dialog.spec.ts @@ -1,25 +1,24 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; -import { ConnectPythonDialog } from './connect-python.dialog'; +import { ConnectPythonDialog } from "./connect-python.dialog"; -describe('NameFileComponent', () => { - let component: ConnectPythonDialog; - let fixture: ComponentFixture; +describe("NameFileComponent", () => { + let component: ConnectPythonDialog; + let fixture: ComponentFixture; - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ ConnectPythonDialog ] - }) - .compileComponents(); - })); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [ConnectPythonDialog], + }).compileComponents(); + })); - beforeEach(() => { - fixture = TestBed.createComponent(ConnectPythonDialog); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(ConnectPythonDialog); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it("should create", () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/modules/core/dialogs/connect-python/connect-python.dialog.ts b/src/app/modules/core/dialogs/connect-python/connect-python.dialog.ts index 2b576e9b..cd7e3325 100644 --- a/src/app/modules/core/dialogs/connect-python/connect-python.dialog.ts +++ b/src/app/modules/core/dialogs/connect-python/connect-python.dialog.ts @@ -1,25 +1,31 @@ -import {Component} from '@angular/core'; -import {MatDialogRef} from '@angular/material/dialog'; -import {TranslateService} from "@ngx-translate/core"; -import {DialogState} from "../../../../state/dialog.state"; -import {RobotWiredState} from "../../../../state/robot.wired.state"; -import {BehaviorSubject} from "rxjs"; -import {CodeEditorType} from "../../../../domain/code-editor.type"; -import {PythonUploaderService} from "../../../../services/python-uploader/PythonUploader.service"; +import { Component } from "@angular/core"; +import { MatDialogRef } from "@angular/material/dialog"; +import { TranslateService } from "@ngx-translate/core"; +import { DialogState } from "../../../../state/dialog.state"; +import { RobotWiredState } from "../../../../state/robot.wired.state"; +import { BehaviorSubject } from "rxjs"; +import { CodeEditorType } from "../../../../domain/code-editor.type"; +import { PythonUploaderService } from "../../../../services/python-uploader/PythonUploader.service"; @Component({ - selector: 'app-connect-python', - templateUrl: './connect-python.dialog.html', - styleUrls: ['./connect-python.dialog.scss'] + selector: "app-connect-python", + templateUrl: "./connect-python.dialog.html", + styleUrls: ["./connect-python.dialog.scss"], }) export class ConnectPythonDialog { - statusMessage: string = ''; + statusMessage: string = ""; progressBarWidth: number = 0; protected readonly document = document; - public uploading: BehaviorSubject = new BehaviorSubject(false); - public firmwareWriting: BehaviorSubject = new BehaviorSubject(false); - public uploadFailed: BehaviorSubject = new BehaviorSubject(false); - public didUpload: BehaviorSubject = new BehaviorSubject(false); + public uploading: BehaviorSubject = new BehaviorSubject( + false, + ); + public firmwareWriting: BehaviorSubject = + new BehaviorSubject(false); + public uploadFailed: BehaviorSubject = + new BehaviorSubject(false); + public didUpload: BehaviorSubject = new BehaviorSubject( + false, + ); constructor( public dialogRef: MatDialogRef, @@ -32,69 +38,69 @@ export class ConnectPythonDialog { public async makePythonRobotConnection() { this.dialogState.isSerialOutputListening = false; this.uploading.next(true); - this.onUpdate('CONNECTING'); + this.onUpdate("CONNECTING"); this.progressBarWidth += 25; - if ('serial' in navigator && 'showDirectoryPicker' in window) { + if ("serial" in navigator && "showDirectoryPicker" in window) { try { await this.upload.connect(); } catch (error) { - if (error.message === 'No device selected') { - this.onUpdate('NO_DEVICE_SELECTED'); - this.onError('No device selected') - } else if (error.message === 'Signature mismatch') { + if (error.message === "No device selected") { + this.onUpdate("NO_DEVICE_SELECTED"); + this.onError("No device selected"); + } else if (error.message === "Signature mismatch") { this.onUpdate("SIGNATURE_MISMATCH"); - this.onError('Signature mismatch') + this.onError("Signature mismatch"); } else { console.log(error); } setTimeout(() => { - this.showReturnOptions() + this.showReturnOptions(); }, 1); - return + return; } this.progressBarWidth += 25; await this.upload.installStandardLibraries(); this.progressBarWidth += 25; } else { - this.onUpdate('NO_SERIAL_SUPPORT') + this.onUpdate("NO_SERIAL_SUPPORT"); this.showReturnOptions(); } - this.onUpdate('CONNECTED'); + this.onUpdate("CONNECTED"); this.showReturnOptions(); this.robotWiredState.pythonDeviceConnected = true; } public async startFlash() { this.progressBarWidth += 50; - this.onUpdate('FLASHING'); + this.onUpdate("FLASHING"); try { await this.upload.connectInBootMode(); - } catch (error) { - if (error.message === 'No device selected') { - this.onUpdate('NO_DEVICE_SELECTED'); - this.onError('No device selected') + } catch (error) { + if (error.message === "No device selected") { + this.onUpdate("NO_DEVICE_SELECTED"); + this.onError("No device selected"); } // wait to give angular time to update the UI setTimeout(() => { - this.showReturnOptions() + this.showReturnOptions(); }, 1); - return + return; } try { this.progressBarWidth += 50; await this.upload.flash(); } catch (error) { this.onUpdate("SIGNATURE_MISMATCH"); - this.onError('Signature mismatch') + this.onError("Signature mismatch"); setTimeout(() => { - this.showReturnOptions() + this.showReturnOptions(); }, 1); - return + return; } this.progressBarWidth += 50; - this.onUpdate('FLASHED'); + this.onUpdate("FLASHED"); this.showReturnOptions(); } @@ -103,7 +109,8 @@ export class ConnectPythonDialog { this.progressBarWidth += parseInt(message.replace("%", "")); } else { const translation = this.translate.instant(message); - this.statusMessage = translation !== null ? translation : message.replace(/_/g, " "); + this.statusMessage = + translation !== null ? translation : message.replace(/_/g, " "); } } diff --git a/src/app/modules/core/dialogs/credits/credits.dialog.html b/src/app/modules/core/dialogs/credits/credits.dialog.html index e17b9321..8fc73ce2 100644 --- a/src/app/modules/core/dialogs/credits/credits.dialog.html +++ b/src/app/modules/core/dialogs/credits/credits.dialog.html @@ -1,13 +1,17 @@
-

{{"CREDITS_INTRODUCTION"|translate}}

- +

{{"CREDITS_INTRODUCTION"|translate}}

+ - + - -
- -
+
+ +
diff --git a/src/app/modules/core/dialogs/credits/credits.dialog.scss b/src/app/modules/core/dialogs/credits/credits.dialog.scss index 42875270..758a414a 100644 --- a/src/app/modules/core/dialogs/credits/credits.dialog.scss +++ b/src/app/modules/core/dialogs/credits/credits.dialog.scss @@ -1,50 +1,49 @@ .container { - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; } .title { - font-size: 16px; + font-size: 16px; } - .credits { - color: grey; - margin-top: 20px; - padding: 20px; - text-align: center; - - img { - width: 100%; - max-width: 180px; - height: auto; - display: block; - margin: 1em auto; - } - - .leaphyLogo { - color: green; - } + color: grey; + margin-top: 20px; + padding: 20px; + text-align: center; + + img { + width: 100%; + max-width: 180px; + height: auto; + display: block; + margin: 1em auto; + } + + .leaphyLogo { + color: green; + } } .buttons { - margin-top: 2em; - flex: 0 1 auto; + margin-top: 2em; + flex: 0 1 auto; } .start { - color: var(--leaphy-color-light) !important; - background-color: var(--leaphy-color-secundary); - font-size: 12px; - font-weight: bold; - border-radius: 20px; - text-transform: uppercase; - font-size: 16px; - outline: none; - - [mat-flat-button]:active { - color: var(--leaphy-color-light); - } + color: var(--leaphy-color-light) !important; + background-color: var(--leaphy-color-secundary); + font-size: 12px; + font-weight: bold; + border-radius: 20px; + text-transform: uppercase; + font-size: 16px; + outline: none; + + [mat-flat-button]:active { + color: var(--leaphy-color-light); + } } diff --git a/src/app/modules/core/dialogs/credits/credits.dialog.spec.ts b/src/app/modules/core/dialogs/credits/credits.dialog.spec.ts index 399b6309..4cd33e78 100644 --- a/src/app/modules/core/dialogs/credits/credits.dialog.spec.ts +++ b/src/app/modules/core/dialogs/credits/credits.dialog.spec.ts @@ -1,25 +1,24 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; -import { CreditsDialog } from './credits.dialog'; +import { CreditsDialog } from "./credits.dialog"; -describe('CreditsComponent', () => { - let component: CreditsDialog; - let fixture: ComponentFixture; +describe("CreditsComponent", () => { + let component: CreditsDialog; + let fixture: ComponentFixture; - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ CreditsDialog ] - }) - .compileComponents(); - })); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [CreditsDialog], + }).compileComponents(); + })); - beforeEach(() => { - fixture = TestBed.createComponent(CreditsDialog); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(CreditsDialog); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it("should create", () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/modules/core/dialogs/credits/credits.dialog.ts b/src/app/modules/core/dialogs/credits/credits.dialog.ts index a9720f82..5a0b3f35 100644 --- a/src/app/modules/core/dialogs/credits/credits.dialog.ts +++ b/src/app/modules/core/dialogs/credits/credits.dialog.ts @@ -1,17 +1,15 @@ -import { Component } from '@angular/core'; -import { MatDialogRef } from '@angular/material/dialog'; +import { Component } from "@angular/core"; +import { MatDialogRef } from "@angular/material/dialog"; @Component({ - selector: 'app-credits', - templateUrl: './credits.dialog.html', - styleUrls: ['./credits.dialog.scss'] + selector: "app-credits", + templateUrl: "./credits.dialog.html", + styleUrls: ["./credits.dialog.scss"], }) -export class CreditsDialog { - constructor( - public dialogRef: MatDialogRef - ) { } +export class CreditsDialog { + constructor(public dialogRef: MatDialogRef) {} - public onDialogClosed() { - this.dialogRef.close(); - } + public onDialogClosed() { + this.dialogRef.close(); + } } diff --git a/src/app/modules/core/dialogs/debug-information/debug-information.dialog.html b/src/app/modules/core/dialogs/debug-information/debug-information.dialog.html index 7a2e3d45..7ba101b2 100644 --- a/src/app/modules/core/dialogs/debug-information/debug-information.dialog.html +++ b/src/app/modules/core/dialogs/debug-information/debug-information.dialog.html @@ -1,30 +1,43 @@
+ +
+ @for (item of (robotWiredState.uploadLog$ | async); track item) { +
+
{{item}}
+
+ } +
- -
- @for (item of (robotWiredState.uploadLog$ | async); track item) { -
-
{{item}}
-
- } -
- -
- {{ "DEVICE_INFORMATION" | translate}} -
-
-
Platform: {{os}}
-
Browser: {{browser}}
-
Version {{browserVersion}}
- @if (serialPort) { -
Serial Port; Device ID: {{serialPort?.getInfo().usbProductId}}; USB Vendor ID: {{serialPort?.getInfo().usbVendorId}}
- } -
Supported Vendor IDs: {{RobotWiredState.SUPPORTED_VENDORS.join(", ")}}
-
Web Serial Supported: {{webSerialSupported}}
-
+
{{ "DEVICE_INFORMATION" | translate}}
+
+
+ Platform: {{os}} +
+
Browser: {{browser}}
+
+ Version {{browserVersion}} +
+ @if (serialPort) { +
+ Serial Port; Device ID: {{serialPort?.getInfo().usbProductId}}; USB + Vendor ID: {{serialPort?.getInfo().usbVendorId}} +
+ } +
+ Supported Vendor IDs: {{RobotWiredState.SUPPORTED_VENDORS.join(", + ")}} +
+
+ Web Serial Supported: {{webSerialSupported}} +
+
diff --git a/src/app/modules/core/dialogs/debug-information/debug-information.dialog.scss b/src/app/modules/core/dialogs/debug-information/debug-information.dialog.scss index a2cc965e..3b84e5d0 100644 --- a/src/app/modules/core/dialogs/debug-information/debug-information.dialog.scss +++ b/src/app/modules/core/dialogs/debug-information/debug-information.dialog.scss @@ -1,68 +1,68 @@ .container { - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - height: 70vh; - width: 50vh; + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + height: 70vh; + width: 50vh; } .upload-log-item { - display: flex; - flex-direction: row; - justify-content: right; - align-items: center; - width: 50vh; - height: fit-content; - border-bottom: 1px solid black; + display: flex; + flex-direction: row; + justify-content: right; + align-items: center; + width: 50vh; + height: fit-content; + border-bottom: 1px solid black; } .upload-log-data { - max-width: 99%; - flex: 1 0 auto; - padding-left: 5px; - color: black; - word-break: break-all; + max-width: 99%; + flex: 1 0 auto; + padding-left: 5px; + color: black; + word-break: break-all; } .upload-log { - width: 50vh; - height: 50vh; - margin: 0; - overflow-y: scroll; - background-color: lightgray; + width: 50vh; + height: 50vh; + margin: 0; + overflow-y: scroll; + background-color: lightgray; } .device-information { - width: 50vh; - height: fit-content; - margin: 0; - background-color: lightgray; + width: 50vh; + height: fit-content; + margin: 0; + background-color: lightgray; } #header:hover { - cursor: grab; + cursor: grab; } #header { - background-color: var(--leaphy-color-primary); - color: var(--leaphy-color-light); - display: flex; - justify-content: space-between; - align-items: center; - padding-left: 10px; - width: 50vh; + background-color: var(--leaphy-color-primary); + color: var(--leaphy-color-light); + display: flex; + justify-content: space-between; + align-items: center; + padding-left: 10px; + width: 50vh; } #device-information { - background-color: var(--leaphy-color-primary); - color: var(--leaphy-color-light); - display: flex; - justify-content: space-between; - align-items: center; - padding-left: 10px; - width: 50vh; + background-color: var(--leaphy-color-primary); + color: var(--leaphy-color-light); + display: flex; + justify-content: space-between; + align-items: center; + padding-left: 10px; + width: 50vh; } .device-specification { - margin-left: 10px; + margin-left: 10px; } diff --git a/src/app/modules/core/dialogs/debug-information/debug-information.dialog.spec.ts b/src/app/modules/core/dialogs/debug-information/debug-information.dialog.spec.ts index 92820f90..3abeff5b 100644 --- a/src/app/modules/core/dialogs/debug-information/debug-information.dialog.spec.ts +++ b/src/app/modules/core/dialogs/debug-information/debug-information.dialog.spec.ts @@ -1,25 +1,24 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; -import { DebugInformationDialog } from './debug-information.dialog'; +import { DebugInformationDialog } from "./debug-information.dialog"; -describe('NameFileComponent', () => { - let component: DebugInformationDialog; - let fixture: ComponentFixture; +describe("NameFileComponent", () => { + let component: DebugInformationDialog; + let fixture: ComponentFixture; - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ DebugInformationDialog ] - }) - .compileComponents(); - })); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [DebugInformationDialog], + }).compileComponents(); + })); - beforeEach(() => { - fixture = TestBed.createComponent(DebugInformationDialog); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(DebugInformationDialog); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it("should create", () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/modules/core/dialogs/debug-information/debug-information.dialog.ts b/src/app/modules/core/dialogs/debug-information/debug-information.dialog.ts index 220e99fd..f051d2cb 100644 --- a/src/app/modules/core/dialogs/debug-information/debug-information.dialog.ts +++ b/src/app/modules/core/dialogs/debug-information/debug-information.dialog.ts @@ -1,46 +1,54 @@ -import {Component} from '@angular/core'; -import {MatDialogRef} from '@angular/material/dialog'; -import {LeaphyPort, RobotWiredState} from "../../../../state/robot.wired.state"; -import {TranslateService} from "@ngx-translate/core"; +import { Component } from "@angular/core"; +import { MatDialogRef } from "@angular/material/dialog"; +import { + LeaphyPort, + RobotWiredState, +} from "../../../../state/robot.wired.state"; +import { TranslateService } from "@ngx-translate/core"; @Component({ - selector: 'app-debug-information', - templateUrl: './debug-information.dialog.html', - styleUrls: ['./debug-information.dialog.scss'] + selector: "app-debug-information", + templateUrl: "./debug-information.dialog.html", + styleUrls: ["./debug-information.dialog.scss"], }) export class DebugInformationDialog { + public os: string = ""; + public browser: string = ""; + public browserVersion: string = ""; + public serialPort?: LeaphyPort; + public webSerialSupported: string = "Supported"; - public os: string = ''; - public browser: string = ''; - public browserVersion: string = ''; - public serialPort?: LeaphyPort; - public webSerialSupported: string = 'Supported'; - - - constructor( - public dialogRef: MatDialogRef, - public robotWiredState: RobotWiredState, - private translate: TranslateService, - ) { - // @ts-ignore - this.os = navigator.userAgentData?.platform ?? translate.instant("UNKNOWN"); - // @ts-ignore - this.browser = navigator.userAgentData?.brands[1].brand ?? translate.instant("UNKNOWN"); - // @ts-ignore - this.browserVersion = navigator.userAgentData?.brands[1].version ?? translate.instant("UNKNOWN"); - this.serialPort = this.robotWiredState.serialPort; - if (!('serial' in navigator)) { - this.webSerialSupported = translate.instant("WEB_SERIAL_NOT_SUPPORTED"); - } else { - this.webSerialSupported = translate.instant("WEB_SERIAL_SUPPORTED"); + constructor( + public dialogRef: MatDialogRef, + public robotWiredState: RobotWiredState, + private translate: TranslateService, + ) { + // @ts-ignore + this.os = + navigator["userAgentData"]?.platform ?? + translate.instant("UNKNOWN"); + // @ts-ignore + this.browser = + navigator["userAgentData"]?.brands[0].brand ?? + translate.instant("UNKNOWN"); + // @ts-ignore + this.browserVersion = + navigator["userAgentData"]?.brands[0].version ?? + translate.instant("UNKNOWN"); + this.serialPort = this.robotWiredState.serialPort; + if (!("serial" in navigator)) { + this.webSerialSupported = translate.instant( + "WEB_SERIAL_NOT_SUPPORTED", + ); + } else { + this.webSerialSupported = translate.instant("WEB_SERIAL_SUPPORTED"); + } } - } - - public onCloseClicked() { - this.dialogRef.close(); - } + public onCloseClicked() { + this.dialogRef.close(); + } - protected readonly document = document; + protected readonly document = document; protected readonly RobotWiredState = RobotWiredState; } diff --git a/src/app/modules/core/dialogs/dialog-styles.scss b/src/app/modules/core/dialogs/dialog-styles.scss index 513400d5..14b5aab2 100644 --- a/src/app/modules/core/dialogs/dialog-styles.scss +++ b/src/app/modules/core/dialogs/dialog-styles.scss @@ -7,7 +7,7 @@ border-radius: 20px; outline: none; } - + [mat-dialog-title] { text-transform: uppercase; text-align: center; @@ -15,4 +15,4 @@ [mat-dialog-actions] { margin-bottom: 10px; -} \ No newline at end of file +} diff --git a/src/app/modules/core/dialogs/examples/examples-dialog.component.html b/src/app/modules/core/dialogs/examples/examples-dialog.component.html index c22ab114..0dfbe480 100644 --- a/src/app/modules/core/dialogs/examples/examples-dialog.component.html +++ b/src/app/modules/core/dialogs/examples/examples-dialog.component.html @@ -1,24 +1,46 @@ -
-
- +
+
+ -
- @for (example of filtered; track example) { -
- -
{{ example.name }}
+
+ @for (example of filtered; track example) { +
+ +
{{ example.name }}
+
+ }
- }
-
diff --git a/src/app/modules/core/dialogs/examples/examples-dialog.component.scss b/src/app/modules/core/dialogs/examples/examples-dialog.component.scss index f4134e38..a7965567 100644 --- a/src/app/modules/core/dialogs/examples/examples-dialog.component.scss +++ b/src/app/modules/core/dialogs/examples/examples-dialog.component.scss @@ -1,4 +1,3 @@ - input { background: none; color: var(--leaphy-color-light); @@ -58,7 +57,7 @@ input::placeholder { border: 3px solid #fff; border-radius: 10px; background: #fff; - transition: .3s ease; + transition: 0.3s ease; display: flex; flex-direction: column; diff --git a/src/app/modules/core/dialogs/examples/examples-dialog.component.ts b/src/app/modules/core/dialogs/examples/examples-dialog.component.ts index d4008969..09f7019a 100644 --- a/src/app/modules/core/dialogs/examples/examples-dialog.component.ts +++ b/src/app/modules/core/dialogs/examples/examples-dialog.component.ts @@ -1,8 +1,13 @@ -import {MatDialogRef} from "@angular/material/dialog"; -import {Component} from "@angular/core"; -import examples, {Board, BoardNames, BoardNamesArray, Example} from "src/examples"; -import {AppState} from "../../../../state/app.state"; -import {WorkspaceService} from "../../../../services/workspace.service"; +import { MatDialogRef } from "@angular/material/dialog"; +import { Component } from "@angular/core"; +import examples, { + Board, + BoardNames, + BoardNamesArray, + Example, +} from "src/examples"; +import { AppState } from "../../../../state/app.state"; +import { WorkspaceService } from "../../../../services/workspace.service"; @Component({ selector: "app-examples", @@ -10,69 +15,128 @@ import {WorkspaceService} from "../../../../services/workspace.service"; styleUrls: ["./examples-dialog.component.scss"], }) export class ExamplesDialog { - public examples: Example[] - public filtered: Example[] + public examples: Example[]; + public filtered: Example[]; constructor( public appState: AppState, private dialog: MatDialogRef, - private workspaceService: WorkspaceService + private workspaceService: WorkspaceService, ) { - this.examples = this.getExamplesForRobot(this.appState.selectedRobotType.id) - this.filtered = this.examples + this.examples = this.getExamplesForRobot( + this.appState.selectedRobotType.id, + ); + this.filtered = this.examples; } private getExamplesForRobot(id: string): Example[] { - - return examples.filter(example => { + return examples.filter((example) => { let allowed = false; - if (example.boards.includes(Board.ALL)) allowed = true - if (example.boards.includes(Board.L_ORIGINAL_ALL) && id.startsWith('l_original')) allowed = true - if (example.boards.includes(Board.L_ORIGINAL_NANO_ALL) && id.startsWith('l_original_nano')) allowed = true - if (example.boards.includes(Board.L_FLITZ_ALL) && id.startsWith('l_flitz')) allowed = true - if (example.boards.includes(Board.L_NANO_ALL) && id.startsWith('l_nano')) allowed = true - if (example.boards.includes(Board.L_ARDUINO) && ['l_nano', 'l_nano_esp32', 'l_nano_rp2040', 'l_uno', 'l_mega'].includes(id)) allowed = true + if (example.boards.includes(Board.ALL)) allowed = true; + if ( + example.boards.includes(Board.L_ORIGINAL_ALL) && + id.startsWith("l_original") + ) + allowed = true; + if ( + example.boards.includes(Board.L_ORIGINAL_NANO_ALL) && + id.startsWith("l_original_nano") + ) + allowed = true; + if ( + example.boards.includes(Board.L_FLITZ_ALL) && + id.startsWith("l_flitz") + ) + allowed = true; + if ( + example.boards.includes(Board.L_NANO_ALL) && + id.startsWith("l_nano") + ) + allowed = true; + if ( + example.boards.includes(Board.L_ARDUINO) && + [ + "l_nano", + "l_nano_esp32", + "l_nano_rp2040", + "l_uno", + "l_mega", + ].includes(id) + ) + allowed = true; // check if there is a negative number in the list // @ts-ignore if (allowed == true) { - let negative = [...example.boards].filter(board => board < 0) + let negative = [...example.boards].filter((board) => board < 0); if (negative.length > 0) { // @ts-ignore if (negative.includes(-BoardNames[id])) { - return false + return false; } else { - if (example.boards.includes(-Board.ALL)) return false - if (example.boards.includes(-Board.L_ORIGINAL_ALL) && id.startsWith('l_original')) return false - if (example.boards.includes(-Board.L_ORIGINAL_NANO_ALL) && id.startsWith('l_original_nano')) return false - if (example.boards.includes(-Board.L_FLITZ_ALL) && id.startsWith('l_flitz')) return false - if (example.boards.includes(-Board.L_NANO_ALL) && id.startsWith('l_nano')) return false - return !(example.boards.includes(-Board.L_ARDUINO) && ['l_nano', 'l_nano_esp32', 'l_nano_rp2040', 'l_uno', 'l_mega'].includes(id)); - - + if (example.boards.includes(-Board.ALL)) return false; + if ( + example.boards.includes(-Board.L_ORIGINAL_ALL) && + id.startsWith("l_original") + ) + return false; + if ( + example.boards.includes( + -Board.L_ORIGINAL_NANO_ALL, + ) && + id.startsWith("l_original_nano") + ) + return false; + if ( + example.boards.includes(-Board.L_FLITZ_ALL) && + id.startsWith("l_flitz") + ) + return false; + if ( + example.boards.includes(-Board.L_NANO_ALL) && + id.startsWith("l_nano") + ) + return false; + return !( + example.boards.includes(-Board.L_ARDUINO) && + [ + "l_nano", + "l_nano_esp32", + "l_nano_rp2040", + "l_uno", + "l_mega", + ].includes(id) + ); } } else { - return true + return true; } } - return example.boards.includes(BoardNames[id]) - }) + return example.boards.includes(BoardNames[id]); + }); } public filter(filter = "") { - this.filtered = this.examples.filter(({ name }) => name.toUpperCase().includes(filter.toUpperCase())) + this.filtered = this.examples.filter(({ name }) => + name.toUpperCase().includes(filter.toUpperCase()), + ); } public async open(example: Example) { - const sketch = await fetch(`examples/${example.sketch}`) - .then(res => res.text()) + const sketch = await fetch(`examples/${example.sketch}`).then((res) => + res.text(), + ); this.workspaceService.restoreWorkspaceFromMessage({ - payload: { data: sketch, type: 'beginner', extension: this.appState.selectedRobotType.id }, - displayTimeout: 2000 - }) - this.close() + payload: { + data: sketch, + type: "beginner", + extension: this.appState.selectedRobotType.id, + }, + displayTimeout: 2000, + }); + this.close(); } public close() { diff --git a/src/app/modules/core/dialogs/file-explorer/file-explorer.dialog.html b/src/app/modules/core/dialogs/file-explorer/file-explorer.dialog.html index 0fb04a80..89598a4d 100644 --- a/src/app/modules/core/dialogs/file-explorer/file-explorer.dialog.html +++ b/src/app/modules/core/dialogs/file-explorer/file-explorer.dialog.html @@ -1,23 +1,33 @@
-
- -
-
- @for (items of dirContent; track items) { -
- @if (items.isDir) { -
- - {{ items.name }} -
+
+ +
+
+ @for (items of dirContent; track items) { +
+ @if (items.isDir) { +
+ + {{ items.name }} +
+ } @if (!items.isDir) { +
+ + {{ items.name }} +
+ } +
} - @if (!items.isDir) { -
- - {{ items.name }} -
- } -
- } -
+
diff --git a/src/app/modules/core/dialogs/file-explorer/file-explorer.dialog.spec.ts b/src/app/modules/core/dialogs/file-explorer/file-explorer.dialog.spec.ts index 7805fc69..4b50208b 100644 --- a/src/app/modules/core/dialogs/file-explorer/file-explorer.dialog.spec.ts +++ b/src/app/modules/core/dialogs/file-explorer/file-explorer.dialog.spec.ts @@ -1,25 +1,24 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; -import { FileExplorerDialog } from './file-explorer.dialog'; +import { FileExplorerDialog } from "./file-explorer.dialog"; -describe('NameFileComponent', () => { - let component: FileExplorerDialog; - let fixture: ComponentFixture; +describe("NameFileComponent", () => { + let component: FileExplorerDialog; + let fixture: ComponentFixture; - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ FileExplorerDialog ] - }) - .compileComponents(); - })); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [FileExplorerDialog], + }).compileComponents(); + })); - beforeEach(() => { - fixture = TestBed.createComponent(FileExplorerDialog); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(FileExplorerDialog); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it("should create", () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/modules/core/dialogs/file-explorer/file-explorer.dialog.ts b/src/app/modules/core/dialogs/file-explorer/file-explorer.dialog.ts index 5176fa1a..1e8cf11a 100644 --- a/src/app/modules/core/dialogs/file-explorer/file-explorer.dialog.ts +++ b/src/app/modules/core/dialogs/file-explorer/file-explorer.dialog.ts @@ -1,31 +1,33 @@ -import { Component } from '@angular/core'; -import { MatDialogRef } from '@angular/material/dialog'; -import { AppState } from 'src/app/state/app.state'; -import {PythonUploaderService} from "../../../../services/python-uploader/PythonUploader.service"; -import {RobotWiredState} from "../../../../state/robot.wired.state"; +import { Component } from "@angular/core"; +import { MatDialogRef } from "@angular/material/dialog"; +import { AppState } from "src/app/state/app.state"; +import { PythonUploaderService } from "../../../../services/python-uploader/PythonUploader.service"; +import { RobotWiredState } from "../../../../state/robot.wired.state"; @Component({ - selector: 'app-file-explorer', - templateUrl: './file-explorer.dialog.html', - styleUrls: ['./file-explorer.dialog.scss'] + selector: "app-file-explorer", + templateUrl: "./file-explorer.dialog.html", + styleUrls: ["./file-explorer.dialog.scss"], }) export class FileExplorerDialog { - public currentPath: string = '/'; + public currentPath: string = "/"; protected readonly document = document; - public dirContent: { name: string, isDir: boolean }[] = []; + public dirContent: { name: string; isDir: boolean }[] = []; constructor( private upload: PythonUploaderService, public dialogRef: MatDialogRef, public appState: AppState, - private robotWiredState: RobotWiredState + private robotWiredState: RobotWiredState, ) { this.upload.connect().then(() => { - this.robotWiredState.serialPort = this.upload.port - this.upload.runFileSystemCommand('ls', this.currentPath).then((files) => { - this.dirContent = files; - }); + this.robotWiredState.serialPort = this.upload.port; + this.upload + .runFileSystemCommand("ls", this.currentPath) + .then((files) => { + this.dirContent = files; + }); }); } @@ -34,25 +36,27 @@ export class FileExplorerDialog { } public openDir(path: string) { - if (path[-1] != '/') - path += '/'; + if (path[-1] != "/") path += "/"; this.currentPath += path; - this.upload.runFileSystemCommand('ls', this.currentPath).then((files) => { - this.dirContent = files; - }); + this.upload + .runFileSystemCommand("ls", this.currentPath) + .then((files) => { + this.dirContent = files; + }); } public openDirRaw(path: string) { this.currentPath = path; - this.upload.runFileSystemCommand('ls', this.currentPath).then((files) => { - this.dirContent = files; - }); + this.upload + .runFileSystemCommand("ls", this.currentPath) + .then((files) => { + this.dirContent = files; + }); } public async openFile(filename: string) { - - if (filename[-1] == '/') { - filename = this.currentPath + '/' + filename; + if (filename[-1] == "/") { + filename = this.currentPath + "/" + filename; } else { filename = this.currentPath + filename; } diff --git a/src/app/modules/core/dialogs/info/info.dialog.html b/src/app/modules/core/dialogs/info/info.dialog.html index 3a0d853b..ab78c76b 100644 --- a/src/app/modules/core/dialogs/info/info.dialog.html +++ b/src/app/modules/core/dialogs/info/info.dialog.html @@ -1,28 +1,22 @@
- -

- {{"INFO_INTRO"|translate}} - {{"INFO_GITHUB"|translate}}
-

-

- {{"INFO_OPEN_SOURCE"|translate}} -

-

- {{"INFO_THANKS"|translate}} -

-

- {{"INFO_TEAM"|translate}} -

- -
- -
- -
+

- {{(appState.releaseVersion)}} + {{"INFO_INTRO"|translate}} + {{"INFO_GITHUB"|translate}}

-
+

{{"INFO_OPEN_SOURCE"|translate}}

+

{{"INFO_THANKS"|translate}}

+

{{"INFO_TEAM"|translate}}

+ +
+ +
+ +
+

{{(appState.releaseVersion)}}

+
diff --git a/src/app/modules/core/dialogs/info/info.dialog.scss b/src/app/modules/core/dialogs/info/info.dialog.scss index 3213f852..1f820248 100644 --- a/src/app/modules/core/dialogs/info/info.dialog.scss +++ b/src/app/modules/core/dialogs/info/info.dialog.scss @@ -1,40 +1,40 @@ .info { - text-align: center; + text-align: center; } .version { - text-align: end; - p { - margin-bottom: 0px; - font-size: small; - color: var(--leaphy-color-secundary); - } + text-align: end; + p { + margin-bottom: 0px; + font-size: small; + color: var(--leaphy-color-secundary); + } } img { - width: 100%; - max-width: 180px; - height: auto; - display: block; - margin: 1em auto; + width: 100%; + max-width: 180px; + height: auto; + display: block; + margin: 1em auto; } .buttons { - margin-top: 2em; - flex: 0 1 auto; + margin-top: 2em; + flex: 0 1 auto; } [mat-flat-button] { - color: var(--leaphy-color-light); - background-color: var(--leaphy-color-secundary); - font-size: 12px; - font-weight: bold; - border-radius: 20px; - text-transform: uppercase; - font-size: 16px; - outline: none; - - [mat-flat-button]:active { color: var(--leaphy-color-light); - } -} \ No newline at end of file + background-color: var(--leaphy-color-secundary); + font-size: 12px; + font-weight: bold; + border-radius: 20px; + text-transform: uppercase; + font-size: 16px; + outline: none; + + [mat-flat-button]:active { + color: var(--leaphy-color-light); + } +} diff --git a/src/app/modules/core/dialogs/info/info.dialog.spec.ts b/src/app/modules/core/dialogs/info/info.dialog.spec.ts index ca4b4fcd..e5774eee 100644 --- a/src/app/modules/core/dialogs/info/info.dialog.spec.ts +++ b/src/app/modules/core/dialogs/info/info.dialog.spec.ts @@ -1,25 +1,24 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; -import { InfoDialog } from './info.dialog'; +import { InfoDialog } from "./info.dialog"; -describe('InfoDialog Component', () => { - let component: InfoDialog; - let fixture: ComponentFixture; +describe("InfoDialog Component", () => { + let component: InfoDialog; + let fixture: ComponentFixture; - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ InfoDialog ] - }) - .compileComponents(); - })); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [InfoDialog], + }).compileComponents(); + })); - beforeEach(() => { - fixture = TestBed.createComponent(InfoDialog); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(InfoDialog); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it("should create", () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/modules/core/dialogs/info/info.dialog.ts b/src/app/modules/core/dialogs/info/info.dialog.ts index 8b4b452e..2aff511c 100644 --- a/src/app/modules/core/dialogs/info/info.dialog.ts +++ b/src/app/modules/core/dialogs/info/info.dialog.ts @@ -1,19 +1,19 @@ -import { Component } from '@angular/core'; -import { MatDialogRef } from '@angular/material/dialog'; -import { AppState } from 'src/app/state/app.state'; +import { Component } from "@angular/core"; +import { MatDialogRef } from "@angular/material/dialog"; +import { AppState } from "src/app/state/app.state"; @Component({ - selector: 'app-info-dialog', - templateUrl: './info.dialog.html', - styleUrls: ['./info.dialog.scss'] + selector: "app-info-dialog", + templateUrl: "./info.dialog.html", + styleUrls: ["./info.dialog.scss"], }) -export class InfoDialog { - constructor( - public appState: AppState, - public dialogRef: MatDialogRef - ) { } +export class InfoDialog { + constructor( + public appState: AppState, + public dialogRef: MatDialogRef, + ) {} - public onDialogClosed() { - this.dialogRef.close(); - } + public onDialogClosed() { + this.dialogRef.close(); + } } diff --git a/src/app/modules/core/dialogs/language-select/language-select.dialog.html b/src/app/modules/core/dialogs/language-select/language-select.dialog.html index ba74a9be..a7c51410 100644 --- a/src/app/modules/core/dialogs/language-select/language-select.dialog.html +++ b/src/app/modules/core/dialogs/language-select/language-select.dialog.html @@ -1,13 +1,15 @@
- -
- @for (language of AppState.availableLanguages; track language) { - - } -
+ +
+ @for (language of AppState.availableLanguages; track language) { + + } +
diff --git a/src/app/modules/core/dialogs/language-select/language-select.dialog.scss b/src/app/modules/core/dialogs/language-select/language-select.dialog.scss index 9bb84cee..31426aee 100644 --- a/src/app/modules/core/dialogs/language-select/language-select.dialog.scss +++ b/src/app/modules/core/dialogs/language-select/language-select.dialog.scss @@ -16,7 +16,7 @@ padding-bottom: 10px; } - .languages{ + .languages { display: flex; flex-direction: column; width: 300px; @@ -36,9 +36,9 @@ border-color: #2c9194; border-width: 1px; - .language-name{ + .language-name { align-content: center; - flex: 1 + flex: 1; } } } @@ -50,5 +50,4 @@ font-size: 16px; font-weight: normal; border-radius: 20px; - } diff --git a/src/app/modules/core/dialogs/language-select/language-select.dialog.spec.ts b/src/app/modules/core/dialogs/language-select/language-select.dialog.spec.ts index e64a4cd1..852541e2 100644 --- a/src/app/modules/core/dialogs/language-select/language-select.dialog.spec.ts +++ b/src/app/modules/core/dialogs/language-select/language-select.dialog.spec.ts @@ -1,25 +1,24 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; -import { LanguageSelectDialog } from './language-select.dialog'; +import { LanguageSelectDialog } from "./language-select.dialog"; -describe('LanguageSelectComponent', () => { - let component: LanguageSelectDialog; - let fixture: ComponentFixture; +describe("LanguageSelectComponent", () => { + let component: LanguageSelectDialog; + let fixture: ComponentFixture; - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ LanguageSelectDialog ] - }) - .compileComponents(); - })); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [LanguageSelectDialog], + }).compileComponents(); + })); - beforeEach(() => { - fixture = TestBed.createComponent(LanguageSelectDialog); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(LanguageSelectDialog); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it("should create", () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/modules/core/dialogs/language-select/language-select.dialog.ts b/src/app/modules/core/dialogs/language-select/language-select.dialog.ts index 85ba7c58..8566153c 100644 --- a/src/app/modules/core/dialogs/language-select/language-select.dialog.ts +++ b/src/app/modules/core/dialogs/language-select/language-select.dialog.ts @@ -1,23 +1,23 @@ -import { Component } from '@angular/core'; -import { MatDialogRef } from '@angular/material/dialog'; -import { Language } from 'src/app/domain/language'; -import { AppState } from 'src/app/state/app.state'; +import { Component } from "@angular/core"; +import { MatDialogRef } from "@angular/material/dialog"; +import { Language } from "src/app/domain/language"; +import { AppState } from "src/app/state/app.state"; @Component({ - selector: 'app-language-select', - templateUrl: './language-select.dialog.html', - styleUrls: ['./language-select.dialog.scss'] + selector: "app-language-select", + templateUrl: "./language-select.dialog.html", + styleUrls: ["./language-select.dialog.scss"], }) -export class LanguageSelectDialog { - constructor( - public dialogRef: MatDialogRef, - public appState: AppState - ) { } +export class LanguageSelectDialog { + constructor( + public dialogRef: MatDialogRef, + public appState: AppState, + ) {} - public onLanguageSelected(language: Language) { - this.appState.currentLanguage = language; - this.dialogRef.close(); - } + public onLanguageSelected(language: Language) { + this.appState.currentLanguage = language; + this.dialogRef.close(); + } protected readonly AppState = AppState; } diff --git a/src/app/modules/core/dialogs/location-select/location-select.dialog.html b/src/app/modules/core/dialogs/location-select/location-select.dialog.html index 54c1d601..a9fd86f8 100644 --- a/src/app/modules/core/dialogs/location-select/location-select.dialog.html +++ b/src/app/modules/core/dialogs/location-select/location-select.dialog.html @@ -1,14 +1,12 @@
- -
- @for (option of data.options; track option; let i = $index) { - - } -
+ +
+ @for (option of data.options; track option; let i = $index) { + + } +
diff --git a/src/app/modules/core/dialogs/location-select/location-select.dialog.scss b/src/app/modules/core/dialogs/location-select/location-select.dialog.scss index a601b909..9edd85fa 100644 --- a/src/app/modules/core/dialogs/location-select/location-select.dialog.scss +++ b/src/app/modules/core/dialogs/location-select/location-select.dialog.scss @@ -1,49 +1,48 @@ .container { - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - - .leaphyLogo { - width: 100%; - max-width: 180px; - height: auto; - display: block; - margin: 1em auto; - padding-bottom: 10px; - } - - .options{ display: flex; + align-items: center; + justify-content: center; flex-direction: column; - width: 200px; - height: fit-content; - button { - margin-bottom: 15px; + .leaphyLogo { + width: 100%; + max-width: 180px; + height: auto; + display: block; + margin: 1em auto; + padding-bottom: 10px; } - } - .option { - //display: flex; - align-items: center; - margin-top: 10px; - margin-bottom: 10px; - height: fit-content; - .option-name{ - width: 100%; - align-content: center; - flex: 1 + .options { + display: flex; + flex-direction: column; + width: 200px; + height: fit-content; + + button { + margin-bottom: 15px; + } + } + .option { + //display: flex; + align-items: center; + margin-top: 10px; + margin-bottom: 10px; + height: fit-content; + + .option-name { + width: 100%; + align-content: center; + flex: 1; + } } - } } [mat-stroked-button], [mat-flat-button] { - color: var(--leaphy-color-primary); - border-color: var(--leaphy-color-secundary); - font-size: 16px; - font-weight: normal; - border-radius: 20px; - + color: var(--leaphy-color-primary); + border-color: var(--leaphy-color-secundary); + font-size: 16px; + font-weight: normal; + border-radius: 20px; } diff --git a/src/app/modules/core/dialogs/location-select/location-select.dialog.spec.ts b/src/app/modules/core/dialogs/location-select/location-select.dialog.spec.ts index 3f2dbd8b..749ab9e1 100644 --- a/src/app/modules/core/dialogs/location-select/location-select.dialog.spec.ts +++ b/src/app/modules/core/dialogs/location-select/location-select.dialog.spec.ts @@ -1,25 +1,24 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; -import {LocationSelectDialog} from './location-select.dialog'; +import { LocationSelectDialog } from "./location-select.dialog"; -describe('LocationSelectComponent', () => { - let component: LocationSelectDialog; - let fixture: ComponentFixture; +describe("LocationSelectComponent", () => { + let component: LocationSelectDialog; + let fixture: ComponentFixture; - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ LocationSelectDialog ] - }) - .compileComponents(); - })); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [LocationSelectDialog], + }).compileComponents(); + })); - beforeEach(() => { - fixture = TestBed.createComponent(LocationSelectDialog); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(LocationSelectDialog); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it("should create", () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/modules/core/dialogs/location-select/location-select.dialog.ts b/src/app/modules/core/dialogs/location-select/location-select.dialog.ts index 71684ea0..7dd990ae 100644 --- a/src/app/modules/core/dialogs/location-select/location-select.dialog.ts +++ b/src/app/modules/core/dialogs/location-select/location-select.dialog.ts @@ -1,20 +1,20 @@ -import { Component, Inject } from '@angular/core'; -import { MatDialogRef } from '@angular/material/dialog'; -import { AppState } from 'src/app/state/app.state'; -import {MAT_DIALOG_DATA} from '@angular/material/dialog'; -import {TranslateService} from "@ngx-translate/core"; +import { Component, Inject } from "@angular/core"; +import { MatDialogRef } from "@angular/material/dialog"; +import { AppState } from "src/app/state/app.state"; +import { MAT_DIALOG_DATA } from "@angular/material/dialog"; +import { TranslateService } from "@ngx-translate/core"; @Component({ - selector: 'app-location-select', - templateUrl: './location-select.dialog.html', - styleUrls: ['./location-select.dialog.scss'] + selector: "app-location-select", + templateUrl: "./location-select.dialog.html", + styleUrls: ["./location-select.dialog.scss"], }) export class LocationSelectDialog { constructor( @Inject(MAT_DIALOG_DATA) public data: any, public dialogRef: MatDialogRef, public appState: AppState, - private translate: TranslateService + private translate: TranslateService, ) { // loop through the list in the options key and translate and replace the value let newOptions = []; diff --git a/src/app/modules/core/dialogs/name-file/name-file.dialog.html b/src/app/modules/core/dialogs/name-file/name-file.dialog.html index 3955988c..229b83cc 100644 --- a/src/app/modules/core/dialogs/name-file/name-file.dialog.html +++ b/src/app/modules/core/dialogs/name-file/name-file.dialog.html @@ -1,10 +1,25 @@
-
- + +
- - + +
diff --git a/src/app/modules/core/dialogs/name-file/name-file.dialog.scss b/src/app/modules/core/dialogs/name-file/name-file.dialog.scss index c560785f..5f4987b2 100644 --- a/src/app/modules/core/dialogs/name-file/name-file.dialog.scss +++ b/src/app/modules/core/dialogs/name-file/name-file.dialog.scss @@ -1,46 +1,45 @@ .container { - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - - .leaphyLogo { - width: 100%; - max-width: 180px; - height: auto; - display: block; - margin: 1em auto; - padding-bottom: 10px; - } - - .languages{ display: flex; + align-items: center; + justify-content: center; flex-direction: column; - width: 200px; - button { - margin-bottom: 15px; + .leaphyLogo { + width: 100%; + max-width: 180px; + height: auto; + display: block; + margin: 1em auto; + padding-bottom: 10px; } - } - .language { - display: flex; - align-items: center; - margin-top: 10px; - margin-bottom: 10px; - .language-name{ - align-content: center; - flex: 1 + .languages { + display: flex; + flex-direction: column; + width: 200px; + + button { + margin-bottom: 15px; + } + } + .language { + display: flex; + align-items: center; + margin-top: 10px; + margin-bottom: 10px; + + .language-name { + align-content: center; + flex: 1; + } } - } } [mat-stroked-button], [mat-flat-button] { - color: var(--leaphy-color-primary); - border-color: var(--leaphy-color-secundary); - font-size: 16px; - font-weight: normal; - border-radius: 20px; - + color: var(--leaphy-color-primary); + border-color: var(--leaphy-color-secundary); + font-size: 16px; + font-weight: normal; + border-radius: 20px; } diff --git a/src/app/modules/core/dialogs/name-file/name-file.dialog.spec.ts b/src/app/modules/core/dialogs/name-file/name-file.dialog.spec.ts index cbc2f807..c10aac55 100644 --- a/src/app/modules/core/dialogs/name-file/name-file.dialog.spec.ts +++ b/src/app/modules/core/dialogs/name-file/name-file.dialog.spec.ts @@ -1,25 +1,24 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; -import { NameFileDialog } from './name-file.dialog'; +import { NameFileDialog } from "./name-file.dialog"; -describe('NameFileComponent', () => { - let component: NameFileDialog; - let fixture: ComponentFixture; +describe("NameFileComponent", () => { + let component: NameFileDialog; + let fixture: ComponentFixture; - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ NameFileDialog ] - }) - .compileComponents(); - })); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [NameFileDialog], + }).compileComponents(); + })); - beforeEach(() => { - fixture = TestBed.createComponent(NameFileDialog); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(NameFileDialog); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it("should create", () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/modules/core/dialogs/name-file/name-file.dialog.ts b/src/app/modules/core/dialogs/name-file/name-file.dialog.ts index ead7650c..ddbed891 100644 --- a/src/app/modules/core/dialogs/name-file/name-file.dialog.ts +++ b/src/app/modules/core/dialogs/name-file/name-file.dialog.ts @@ -1,25 +1,25 @@ -import { Component } from '@angular/core'; -import { MatDialogRef } from '@angular/material/dialog'; -import { AppState } from 'src/app/state/app.state'; +import { Component } from "@angular/core"; +import { MatDialogRef } from "@angular/material/dialog"; +import { AppState } from "src/app/state/app.state"; @Component({ - selector: 'app-language-select', - templateUrl: './name-file.dialog.html', - styleUrls: ['./name-file.dialog.scss'] + selector: "app-language-select", + templateUrl: "./name-file.dialog.html", + styleUrls: ["./name-file.dialog.scss"], }) export class NameFileDialog { - constructor( - public dialogRef: MatDialogRef, - public appState: AppState - ) { } + constructor( + public dialogRef: MatDialogRef, + public appState: AppState, + ) {} - public onNameSelected(name: string) { - this.dialogRef.close(name); - } + public onNameSelected(name: string) { + this.dialogRef.close(name); + } - public onClose() { - this.dialogRef.close(null); - } + public onClose() { + this.dialogRef.close(null); + } - protected readonly document = document; + protected readonly document = document; } diff --git a/src/app/modules/core/dialogs/robot-select/robot-select.dialog.html b/src/app/modules/core/dialogs/robot-select/robot-select.dialog.html index f5d2aa43..f6d48947 100644 --- a/src/app/modules/core/dialogs/robot-select/robot-select.dialog.html +++ b/src/app/modules/core/dialogs/robot-select/robot-select.dialog.html @@ -1,15 +1,17 @@
- -
- @for (robot of data.boardTypes; track robot; let i = $index) { - - } -
+ +
+ @for (robot of data.boardTypes; track robot; let i = $index) { + + } +
diff --git a/src/app/modules/core/dialogs/robot-select/robot-select.dialog.scss b/src/app/modules/core/dialogs/robot-select/robot-select.dialog.scss index 0bc6b6db..8bc6f2f3 100644 --- a/src/app/modules/core/dialogs/robot-select/robot-select.dialog.scss +++ b/src/app/modules/core/dialogs/robot-select/robot-select.dialog.scss @@ -14,8 +14,7 @@ padding-bottom: 10px; } - .robots{ - + .robots { display: flex; flex-direction: column; width: 200px; @@ -33,10 +32,10 @@ margin-bottom: 10px; height: 10vh; - .robot-name{ + .robot-name { width: 100%; align-content: center; - flex: 1 + flex: 1; } } } @@ -48,5 +47,4 @@ font-size: 16px; font-weight: normal; border-radius: 20px; - } diff --git a/src/app/modules/core/dialogs/robot-select/robot-select.dialog.spec.ts b/src/app/modules/core/dialogs/robot-select/robot-select.dialog.spec.ts index fe6fad0c..04f721a8 100644 --- a/src/app/modules/core/dialogs/robot-select/robot-select.dialog.spec.ts +++ b/src/app/modules/core/dialogs/robot-select/robot-select.dialog.spec.ts @@ -1,25 +1,24 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; -import { SelectRobotTypeDialog } from './robot-select.dialog'; +import { SelectRobotTypeDialog } from "./robot-select.dialog"; -describe('RobotSelectComponent', () => { - let component: SelectRobotTypeDialog; - let fixture: ComponentFixture; +describe("RobotSelectComponent", () => { + let component: SelectRobotTypeDialog; + let fixture: ComponentFixture; - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ SelectRobotTypeDialog ] - }) - .compileComponents(); - })); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [SelectRobotTypeDialog], + }).compileComponents(); + })); - beforeEach(() => { - fixture = TestBed.createComponent(SelectRobotTypeDialog); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(SelectRobotTypeDialog); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it("should create", () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/modules/core/dialogs/robot-select/robot-select.dialog.ts b/src/app/modules/core/dialogs/robot-select/robot-select.dialog.ts index ba672815..b7478917 100644 --- a/src/app/modules/core/dialogs/robot-select/robot-select.dialog.ts +++ b/src/app/modules/core/dialogs/robot-select/robot-select.dialog.ts @@ -1,20 +1,19 @@ -import { Component, Inject } from '@angular/core'; -import { MatDialogRef } from '@angular/material/dialog'; -import { AppState } from 'src/app/state/app.state'; -import {MAT_DIALOG_DATA} from '@angular/material/dialog'; +import { Component, Inject } from "@angular/core"; +import { MatDialogRef } from "@angular/material/dialog"; +import { AppState } from "src/app/state/app.state"; +import { MAT_DIALOG_DATA } from "@angular/material/dialog"; @Component({ - selector: 'app-robot-select', - templateUrl: './robot-select.dialog.html', - styleUrls: ['./robot-select.dialog.scss'] + selector: "app-robot-select", + templateUrl: "./robot-select.dialog.html", + styleUrls: ["./robot-select.dialog.scss"], }) export class SelectRobotTypeDialog { constructor( @Inject(MAT_DIALOG_DATA) public data: any, public dialogRef: MatDialogRef, public appState: AppState, - - ) { } + ) {} public onRobotSelected(robotType: String) { this.dialogRef.close(robotType); diff --git a/src/app/modules/core/dialogs/status-message/status-message.dialog.html b/src/app/modules/core/dialogs/status-message/status-message.dialog.html index a1687a74..9cd33fdf 100644 --- a/src/app/modules/core/dialogs/status-message/status-message.dialog.html +++ b/src/app/modules/core/dialogs/status-message/status-message.dialog.html @@ -1 +1,3 @@ -

{{ message.message | translate:{'data': message.payload} }}

\ No newline at end of file +

+ {{ message.message | translate:{'data': message.payload} }} +

diff --git a/src/app/modules/core/dialogs/status-message/status-message.dialog.scss b/src/app/modules/core/dialogs/status-message/status-message.dialog.scss index ded25114..e8cff59b 100644 --- a/src/app/modules/core/dialogs/status-message/status-message.dialog.scss +++ b/src/app/modules/core/dialogs/status-message/status-message.dialog.scss @@ -1,4 +1,4 @@ .status-message { margin: 0; text-align: center; -} \ No newline at end of file +} diff --git a/src/app/modules/core/dialogs/status-message/status-message.dialog.spec.ts b/src/app/modules/core/dialogs/status-message/status-message.dialog.spec.ts index 106c3c96..e895f972 100644 --- a/src/app/modules/core/dialogs/status-message/status-message.dialog.spec.ts +++ b/src/app/modules/core/dialogs/status-message/status-message.dialog.spec.ts @@ -1,25 +1,24 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; -import { StatusMessageDialog } from './status-message.dialog'; +import { StatusMessageDialog } from "./status-message.dialog"; -describe('StatusMessageComponent', () => { - let component: StatusMessageDialog; - let fixture: ComponentFixture; +describe("StatusMessageComponent", () => { + let component: StatusMessageDialog; + let fixture: ComponentFixture; - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ StatusMessageDialog ] - }) - .compileComponents(); - })); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [StatusMessageDialog], + }).compileComponents(); + })); - beforeEach(() => { - fixture = TestBed.createComponent(StatusMessageDialog); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(StatusMessageDialog); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it("should create", () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/modules/core/dialogs/status-message/status-message.dialog.ts b/src/app/modules/core/dialogs/status-message/status-message.dialog.ts index 2d9a739d..7f65c89c 100644 --- a/src/app/modules/core/dialogs/status-message/status-message.dialog.ts +++ b/src/app/modules/core/dialogs/status-message/status-message.dialog.ts @@ -1,12 +1,12 @@ -import { Component, Inject } from '@angular/core'; -import { MAT_SNACK_BAR_DATA } from '@angular/material/snack-bar'; -import { SnackbarMessage } from 'src/app/domain/snackbar.message'; +import { Component, Inject } from "@angular/core"; +import { MAT_SNACK_BAR_DATA } from "@angular/material/snack-bar"; +import { SnackbarMessage } from "src/app/domain/snackbar.message"; @Component({ - selector: 'app-status-message', - templateUrl: './status-message.dialog.html', - styleUrls: ['./status-message.dialog.scss'] + selector: "app-status-message", + templateUrl: "./status-message.dialog.html", + styleUrls: ["./status-message.dialog.scss"], }) export class StatusMessageDialog { - constructor(@Inject(MAT_SNACK_BAR_DATA) public message: SnackbarMessage) { } + constructor(@Inject(MAT_SNACK_BAR_DATA) public message: SnackbarMessage) {} } diff --git a/src/app/modules/core/dialogs/upload/upload.dialog.html b/src/app/modules/core/dialogs/upload/upload.dialog.html index e7baee18..6d71efbc 100644 --- a/src/app/modules/core/dialogs/upload/upload.dialog.html +++ b/src/app/modules/core/dialogs/upload/upload.dialog.html @@ -1,34 +1,44 @@
- @if ((uploadState.USBConnecting$ | async) === false) { + @if ((uploadState.USBConnecting$ | async) === false) {
-

{{ uploadState.stateMessage$ | async }}

- @if ((uploadState.done$ | async) === false) { - - } +

+ {{ uploadState.stateMessage$ | async }} +

+ @if ((uploadState.done$ | async) === false) { + + }
- } - - @if (uploadState.USBConnecting$ | async) { + } @if (uploadState.USBConnecting$ | async) {
-

{{ "RECONNECT_INFO" | translate }}

- +

{{ "RECONNECT_INFO" | translate }}

+
- } - - @if (uploadState.error$ | async) { + } @if (uploadState.error$ | async) {
{{ uploadState.error$ | async }}
- } - @if (uploadState.done$ | async) { + } @if (uploadState.done$ | async) {
- - @if (uploadState.failed$ | async) { - + @if (uploadState.failed$ | async) { + - } + }
- } + }
diff --git a/src/app/modules/core/dialogs/upload/upload.dialog.scss b/src/app/modules/core/dialogs/upload/upload.dialog.scss index a741f2c1..ab75972e 100644 --- a/src/app/modules/core/dialogs/upload/upload.dialog.scss +++ b/src/app/modules/core/dialogs/upload/upload.dialog.scss @@ -17,7 +17,9 @@ border: none; border-radius: 4px; cursor: pointer; - transition: background-color 0.3s, color 0.3s; + transition: + background-color 0.3s, + color 0.3s; margin-top: 10px; align-self: center; @@ -36,7 +38,9 @@ border: none; border-radius: 4px; cursor: pointer; - transition: background-color 0.3s, color 0.3s; + transition: + background-color 0.3s, + color 0.3s; margin-top: 10px; align-self: center; diff --git a/src/app/modules/core/dialogs/upload/upload.dialog.spec.ts b/src/app/modules/core/dialogs/upload/upload.dialog.spec.ts index 2dfa142e..c3eda614 100644 --- a/src/app/modules/core/dialogs/upload/upload.dialog.spec.ts +++ b/src/app/modules/core/dialogs/upload/upload.dialog.spec.ts @@ -1,25 +1,24 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; -import { UploadDialog } from './upload.dialog'; +import { UploadDialog } from "./upload.dialog"; -describe('NameFileComponent', () => { - let component: UploadDialog; - let fixture: ComponentFixture; +describe("NameFileComponent", () => { + let component: UploadDialog; + let fixture: ComponentFixture; - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ UploadDialog ] - }) - .compileComponents(); - })); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [UploadDialog], + }).compileComponents(); + })); - beforeEach(() => { - fixture = TestBed.createComponent(UploadDialog); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(UploadDialog); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it("should create", () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/modules/core/dialogs/upload/upload.dialog.ts b/src/app/modules/core/dialogs/upload/upload.dialog.ts index cbbd50c4..04aaa261 100644 --- a/src/app/modules/core/dialogs/upload/upload.dialog.ts +++ b/src/app/modules/core/dialogs/upload/upload.dialog.ts @@ -1,19 +1,23 @@ -import {Component, Inject} from '@angular/core'; -import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import { Component, Inject } from "@angular/core"; +import { MAT_DIALOG_DATA, MatDialogRef } from "@angular/material/dialog"; import ArduinoUploader from "../../../../services/arduino-uploader/ArduinoUploader"; -import {DialogState} from "../../../../state/dialog.state"; -import {RobotWiredState} from "../../../../state/robot.wired.state"; -import {environment} from "src/environments/environment"; -import {AppState} from "../../../../state/app.state"; -import {UploadState} from "../../../../state/upload.state"; +import { DialogState } from "../../../../state/dialog.state"; +import { RobotWiredState } from "../../../../state/robot.wired.state"; +import { environment } from "src/environments/environment"; +import { AppState } from "../../../../state/app.state"; +import { UploadState } from "../../../../state/upload.state"; @Component({ - selector: 'app-upload', - templateUrl: './upload.dialog.html', - styleUrls: ['./upload.dialog.scss'] + selector: "app-upload", + templateUrl: "./upload.dialog.html", + styleUrls: ["./upload.dialog.scss"], }) export class UploadDialog { - private upload = new ArduinoUploader(this.robotWiredState, this.appState, this.uploadState); + private upload = new ArduinoUploader( + this.robotWiredState, + this.appState, + this.uploadState, + ); constructor( public dialogRef: MatDialogRef, @@ -21,63 +25,69 @@ export class UploadDialog { private robotWiredState: RobotWiredState, private appState: AppState, public uploadState: UploadState, - @Inject(MAT_DIALOG_DATA) public data: any + @Inject(MAT_DIALOG_DATA) public data: any, ) { // get all the vars for upload from the data passed in const source_code = data.source_code; const board = data.board; const libraries = data.libraries; - this.uploadState.reset() - this.startUpload(source_code, board, libraries).then() + this.uploadState.reset(); + this.startUpload(source_code, board, libraries).then(); } async compile(source_code: string, board: string, libraries: string) { const res = await fetch(`${environment.backend}/compile/cpp`, { - method: 'POST', + method: "POST", headers: { - 'Content-Type': 'application/json' + "Content-Type": "application/json", }, body: JSON.stringify({ - source_code, board, libraries - }) - }) + source_code, + board, + libraries, + }), + }); if (!res.ok) { - let message: string = await res.text() + let message: string = await res.text(); try { - message = JSON.parse(message).detail + message = JSON.parse(message).detail; } catch {} - throw new Error(message) + throw new Error(message); } - return await res.json() as Record + return (await res.json()) as Record; } - public async startUpload(source_code: string, board: string, libraries: string) { + public async startUpload( + source_code: string, + board: string, + libraries: string, + ) { this.dialogState.isSerialOutputListening = false; if (!navigator.serial && !navigator.usb) { - this.uploadState.statusMessage = 'NO_SERIAL_SUPPORT' - this.uploadState.failed = true - this.uploadState.done = true - return + this.uploadState.statusMessage = "NO_SERIAL_SUPPORT"; + this.uploadState.failed = true; + this.uploadState.done = true; + return; } if (this.robotWiredState.serialPort === null) { try { - await this.upload.connect() + await this.upload.connect(); this.robotWiredState.serialPort = this.upload.port; } catch (error) { - if (error.toString() === 'Error: No device selected') { - this.uploadState.failed = true - this.uploadState.statusMessage = 'NO_DEVICE_SELECTED' + if (error.toString() === "Error: No device selected") { + this.uploadState.failed = true; + this.uploadState.statusMessage = "NO_DEVICE_SELECTED"; console.error(error); } else { - this.uploadState.statusMessage = "UPDATE_FAILED" - this.uploadState.error = error.toString() + this.uploadState.statusMessage = "UPDATE_FAILED"; + this.uploadState.error = error.toString(); console.error(error); } - return + return; } } @@ -85,33 +95,35 @@ export class UploadDialog { this.upload.setPort(this.robotWiredState.serialPort); this.uploadState.addProgress(25); - this.uploadState.statusMessage = 'COMPILATION_STARTED'; - const response = await this.compile(source_code, board, libraries).catch(error => { - this.uploadState.statusMessage = 'COMPILATION_FAILED'; + this.uploadState.statusMessage = "COMPILATION_STARTED"; + const response = await this.compile( + source_code, + board, + libraries, + ).catch((error) => { + this.uploadState.statusMessage = "COMPILATION_FAILED"; // make the printed red text - console.log('%c' + error.toString(), 'color: red'); + console.log("%c" + error.toString(), "color: red"); // remove the last 4 lines of the error message const errorLines = error.toString().split("\n"); errorLines.splice(errorLines.length - 5, 5); - this.uploadState.error = errorLines.join("\n") - }) - if (!response) return + this.uploadState.error = errorLines.join("\n"); + }); + if (!response) return; this.uploadState.addProgress(25); - this.uploadState.statusMessage = 'UPDATE_STARTED' + this.uploadState.statusMessage = "UPDATE_STARTED"; try { await this.upload.upload(response); } catch (error) { - this.uploadState.error = error.toString() + this.uploadState.error = error.toString(); console.error(error); - } this.uploadState.done = true; console.log("Finished upload"); - } returnBlockEnvironment() { @@ -127,11 +139,11 @@ export class UploadDialog { async reconnect() { try { const port = await navigator.usb.requestDevice({ - filters: RobotWiredState.SUPPORTED_VENDORS.map(vendor => ({ - vendorId: vendor - })) - }) - this.uploadState.connectUSB(port) + filters: RobotWiredState.SUPPORTED_VENDORS.map((vendor) => ({ + vendorId: vendor, + })), + }); + this.uploadState.connectUSB(port); } catch (e) {} } } diff --git a/src/app/modules/core/dialogs/variable/variable.dialog.html b/src/app/modules/core/dialogs/variable/variable.dialog.html index 217190d1..4668c945 100644 --- a/src/app/modules/core/dialogs/variable/variable.dialog.html +++ b/src/app/modules/core/dialogs/variable/variable.dialog.html @@ -1,6 +1,12 @@
-
- + +
diff --git a/src/app/modules/core/dialogs/variable/variable.dialog.scss b/src/app/modules/core/dialogs/variable/variable.dialog.scss index 3d491663..8dcaa020 100644 --- a/src/app/modules/core/dialogs/variable/variable.dialog.scss +++ b/src/app/modules/core/dialogs/variable/variable.dialog.scss @@ -1,6 +1,6 @@ .container { - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; } diff --git a/src/app/modules/core/dialogs/variable/variable.dialog.spec.ts b/src/app/modules/core/dialogs/variable/variable.dialog.spec.ts index 9a4cec11..f82f41a2 100644 --- a/src/app/modules/core/dialogs/variable/variable.dialog.spec.ts +++ b/src/app/modules/core/dialogs/variable/variable.dialog.spec.ts @@ -1,25 +1,24 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; -import { VariableDialog } from './variable.dialog'; +import { VariableDialog } from "./variable.dialog"; -describe('NameFileComponent', () => { - let component: VariableDialog; - let fixture: ComponentFixture; +describe("NameFileComponent", () => { + let component: VariableDialog; + let fixture: ComponentFixture; - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ VariableDialog ] - }) - .compileComponents(); - })); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [VariableDialog], + }).compileComponents(); + })); - beforeEach(() => { - fixture = TestBed.createComponent(VariableDialog); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(VariableDialog); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it("should create", () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/modules/core/dialogs/variable/variable.dialog.ts b/src/app/modules/core/dialogs/variable/variable.dialog.ts index 60bc36a2..f496e065 100644 --- a/src/app/modules/core/dialogs/variable/variable.dialog.ts +++ b/src/app/modules/core/dialogs/variable/variable.dialog.ts @@ -1,21 +1,21 @@ -import { Component } from '@angular/core'; -import { MatDialogRef } from '@angular/material/dialog'; -import { AppState } from 'src/app/state/app.state'; +import { Component } from "@angular/core"; +import { MatDialogRef } from "@angular/material/dialog"; +import { AppState } from "src/app/state/app.state"; @Component({ - selector: 'app-name-variable-dialog', - templateUrl: './variable.dialog.html', - styleUrls: ['./variable.dialog.scss'] + selector: "app-name-variable-dialog", + templateUrl: "./variable.dialog.html", + styleUrls: ["./variable.dialog.scss"], }) export class VariableDialog { - constructor( - public dialogRef: MatDialogRef, - public appState: AppState - ) { } + constructor( + public dialogRef: MatDialogRef, + public appState: AppState, + ) {} - public onSubmit(name: string) { - this.dialogRef.close(name); - } + public onSubmit(name: string) { + this.dialogRef.close(name); + } - protected readonly document = document; + protected readonly document = document; } diff --git a/src/app/modules/driver-issues-dutch/driver-issues-routing.module.ts b/src/app/modules/driver-issues-dutch/driver-issues-routing.module.ts index f688b2bb..aa29f076 100644 --- a/src/app/modules/driver-issues-dutch/driver-issues-routing.module.ts +++ b/src/app/modules/driver-issues-dutch/driver-issues-routing.module.ts @@ -1,14 +1,16 @@ -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; -import { DriverIssuesDutchPage } from './driver-issues.page'; +import { NgModule } from "@angular/core"; +import { RouterModule, Routes } from "@angular/router"; +import { DriverIssuesDutchPage } from "./driver-issues.page"; -const routes: Routes = [{ - path: '', - component: DriverIssuesDutchPage -}]; +const routes: Routes = [ + { + path: "", + component: DriverIssuesDutchPage, + }, +]; @NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], }) -export class DriverIssuesRoutingModule { } +export class DriverIssuesRoutingModule {} diff --git a/src/app/modules/driver-issues-dutch/driver-issues.module.ts b/src/app/modules/driver-issues-dutch/driver-issues.module.ts index de9482ed..2e550d91 100644 --- a/src/app/modules/driver-issues-dutch/driver-issues.module.ts +++ b/src/app/modules/driver-issues-dutch/driver-issues.module.ts @@ -1,17 +1,12 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; - -import { DriverIssuesRoutingModule } from './driver-issues-routing.module'; -import { DriverIssuesDutchPage } from './driver-issues.page'; -import { SharedModule } from '../shared/shared.module'; +import { NgModule } from "@angular/core"; +import { CommonModule } from "@angular/common"; +import { DriverIssuesRoutingModule } from "./driver-issues-routing.module"; +import { DriverIssuesDutchPage } from "./driver-issues.page"; +import { SharedModule } from "../shared/shared.module"; @NgModule({ - declarations: [DriverIssuesDutchPage], - imports: [ - CommonModule, - DriverIssuesRoutingModule, - SharedModule - ] + declarations: [DriverIssuesDutchPage], + imports: [CommonModule, DriverIssuesRoutingModule, SharedModule], }) -export class DriverIssuesDutchModule { } +export class DriverIssuesDutchModule {} diff --git a/src/app/modules/driver-issues-dutch/driver-issues.page.html b/src/app/modules/driver-issues-dutch/driver-issues.page.html index 2271069f..6cafc229 100644 --- a/src/app/modules/driver-issues-dutch/driver-issues.page.html +++ b/src/app/modules/driver-issues-dutch/driver-issues.page.html @@ -1,68 +1,82 @@
-
-

Problemen met uploaden?

-

Selecteer eerst uw browser en vervolgens uw besturingssysteem

+
+

Problemen met uploaden?

+

Selecteer eerst uw browser en vervolgens uw besturingssysteem

-
-

Problemen met uploaden in Firefox

-
Als u problemen ondervindt met uploaden in Firefox, volg dan deze stappen...
+        
+

Problemen met uploaden in Firefox

+
+Als u problemen ondervindt met uploaden in Firefox, volg dan deze stappen...
 
       - Het wisselen van browser is de eenvoudigste manier om uploadproblemen op te lossen. Probeer in plaats daarvan Chrome, Edge of Opera.
       - Sinds de laatste update is er geen ondersteuning voor Firefox. Het ondersteunt de gebruikte API niet in alle andere werkende browsers.
-      
-
+
+
-
-

Problemen met uploaden in Safari

-
Als u problemen ondervindt bij het uploaden in Safari, probeer dan de volgende oplossingen...
+        
+

Problemen met uploaden in Safari

+
+Als u problemen ondervindt bij het uploaden in Safari, probeer dan de volgende oplossingen...
 
       - Het wisselen van browser is de eenvoudigste manier om uploadproblemen op te lossen. Probeer in plaats daarvan Chrome, Edge of Opera.
       - Sinds de laatste update is er geen ondersteuning voor Safari. Het ondersteunt de gebruikte API niet in alle andere werkende browsers.
-      
-
+
+
-
-

Problemen met uploaden op Linux

-
Als u Linux gebruikt en te maken heeft met uploaduitdagingen, overweeg dan deze probleemoplossende tips...
+        
+

Problemen met uploaden op Linux

+
+Als u Linux gebruikt en te maken heeft met uploaduitdagingen, overweeg dan deze probleemoplossende tips...
 
       - Zorg ervoor dat u de nieuwste versie van Chrome, Edge of Opera geïnstalleerd heeft.
       - Gebruik dmesg om mogelijke problemen te vinden (bijv. dmesg | grep -i usb). Ik heb persoonlijk ontdekt dat een software genaamd (brltty) problemen veroorzaakt (apt purge brltty)
       - Als u geen oplossing kunt vinden, stuur dan een e-mail naar helpdesk@leaphy.org
-      
-
+
+
-
-

Problemen met uploaden op Windows

-
Als u Windows gebruikt en problemen ondervindt bij het uploaden, volg dan deze stappen...
+        
+

Problemen met uploaden op Windows

+
+Als u Windows gebruikt en problemen ondervindt bij het uploaden, volg dan deze stappen...
 
       - Heeft u de benodigde stuurprogramma's geïnstalleerd? (https://github.com/leaphy-robotics/leaphy-webbased/archive/refs/heads/executables.zip)
       - Zorg ervoor dat u de nieuwste versie van Chrome, Edge of Opera geïnstalleerd heeft.
       - Als u geen oplossing kunt vinden, stuur dan een e-mail naar helpdesk@leaphy.org
-      
-
+
+
-
-

Problemen met uploaden op Mac

-
Als u een Mac gebruikt en problemen ondervindt bij het uploaden, probeer dan deze suggesties...
+        
+

Problemen met uploaden op Mac

+
+Als u een Mac gebruikt en problemen ondervindt bij het uploaden, probeer dan deze suggesties...
 
       - Zorg ervoor dat u de nieuwste versie van Chrome, Edge of Opera geïnstalleerd heeft.
       - Als u geen oplossing kunt vinden, stuur dan een e-mail naar helpdesk@leaphy.org
-      
-
+
+
-
-

Problemen met uploaden op mobiele apparaten

-
Als u een mobiel apparaat gebruikt en problemen ondervindt bij het uploaden, volg dan deze stappen...
+        
+

Problemen met uploaden op mobiele apparaten

+
+Als u een mobiel apparaat gebruikt en problemen ondervindt bij het uploaden, volg dan deze stappen...
 
       - Sinds de laatste update is er geen ondersteuning voor mobiele apparaten. Het ondersteunt de gebruikte API niet in alle andere werkende browsers (zelfs niet op desktop).
-      
-
+
+
-
-

Andere uploadproblemen

-
Als uw uploadproblemen niet in de bovenstaande categorieën vallen, bekijk dan deze oplossingen...
-        Stuur een e-mail naar: helpdesk@leaphy.org
+
+

Andere uploadproblemen

+
+Als uw uploadproblemen niet in de bovenstaande categorieën vallen, bekijk dan deze oplossingen...
+        Stuur een e-mail naar: helpdesk@leaphy.org
+
+
-
-
diff --git a/src/app/modules/driver-issues-dutch/driver-issues.page.scss b/src/app/modules/driver-issues-dutch/driver-issues.page.scss index a872c65a..ba745c3a 100644 --- a/src/app/modules/driver-issues-dutch/driver-issues.page.scss +++ b/src/app/modules/driver-issues-dutch/driver-issues.page.scss @@ -1,42 +1,41 @@ #container { - display: flex; - align-items: stretch; - width: 100vw; + display: flex; + align-items: stretch; + width: 100vw; } #container h1 { - margin-top: 1%; + margin-top: 1%; } #container h3 { - text-align: left; - margin-bottom: 1%; + text-align: left; + margin-bottom: 1%; } .content { - flex: 1 1 auto; - padding: 20px; + flex: 1 1 auto; + padding: 20px; } #content div { - margin-top: 5%; + margin-top: 5%; } #content h2 { - text-align: center; - margin-top: 3%; + text-align: center; + margin-top: 3%; } body { - overflow-y: scroll; /* Override the body's overflow */ + overflow-y: scroll; /* Override the body's overflow */ } h2 { - cursor: pointer; /* Add a pointer cursor to indicate clickability */ - transition: color 0.3s; /* Smooth color transition on hover */ + cursor: pointer; /* Add a pointer cursor to indicate clickability */ + transition: color 0.3s; /* Smooth color transition on hover */ } h2:hover { - color: #007bff; /* Change color on hover */ + color: #007bff; /* Change color on hover */ } - diff --git a/src/app/modules/driver-issues-dutch/driver-issues.page.spec.ts b/src/app/modules/driver-issues-dutch/driver-issues.page.spec.ts index a5fde94c..adaa00bc 100644 --- a/src/app/modules/driver-issues-dutch/driver-issues.page.spec.ts +++ b/src/app/modules/driver-issues-dutch/driver-issues.page.spec.ts @@ -1,25 +1,24 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ComponentFixture, TestBed } from "@angular/core/testing"; -import { DriverIssuesDutchPage } from './driver-issues.page'; +import { DriverIssuesDutchPage } from "./driver-issues.page"; -describe('DriverIssuesDutch', () => { - let component: DriverIssuesDutchPage; - let fixture: ComponentFixture; +describe("DriverIssuesDutch", () => { + let component: DriverIssuesDutchPage; + let fixture: ComponentFixture; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ DriverIssuesDutchPage ] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [DriverIssuesDutchPage], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(DriverIssuesDutchPage); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(DriverIssuesDutchPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it("should create", () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/modules/driver-issues-dutch/driver-issues.page.ts b/src/app/modules/driver-issues-dutch/driver-issues.page.ts index 21ca3ea8..dbd945d3 100644 --- a/src/app/modules/driver-issues-dutch/driver-issues.page.ts +++ b/src/app/modules/driver-issues-dutch/driver-issues.page.ts @@ -1,11 +1,10 @@ -import { Component } from '@angular/core'; +import { Component } from "@angular/core"; @Component({ - selector: 'app-driver-issues-dutch-page', - templateUrl: './driver-issues.page.html', - styleUrls: ['./driver-issues.page.scss'] + selector: "app-driver-issues-dutch-page", + templateUrl: "./driver-issues.page.html", + styleUrls: ["./driver-issues.page.scss"], }) export class DriverIssuesDutchPage { - - constructor() { } + constructor() {} } diff --git a/src/app/modules/driver-issues-english/driver-issues-routing.module.ts b/src/app/modules/driver-issues-english/driver-issues-routing.module.ts index 7353d3f1..999496ed 100644 --- a/src/app/modules/driver-issues-english/driver-issues-routing.module.ts +++ b/src/app/modules/driver-issues-english/driver-issues-routing.module.ts @@ -1,14 +1,16 @@ -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; -import { DriverIssuesEnglishPage } from './driver-issues.page'; +import { NgModule } from "@angular/core"; +import { RouterModule, Routes } from "@angular/router"; +import { DriverIssuesEnglishPage } from "./driver-issues.page"; -const routes: Routes = [{ - path: '', - component: DriverIssuesEnglishPage -}]; +const routes: Routes = [ + { + path: "", + component: DriverIssuesEnglishPage, + }, +]; @NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], }) -export class DriverIssuesRoutingModule { } +export class DriverIssuesRoutingModule {} diff --git a/src/app/modules/driver-issues-english/driver-issues.module.ts b/src/app/modules/driver-issues-english/driver-issues.module.ts index 6492c4b2..125f74bb 100644 --- a/src/app/modules/driver-issues-english/driver-issues.module.ts +++ b/src/app/modules/driver-issues-english/driver-issues.module.ts @@ -1,17 +1,12 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; - -import { DriverIssuesRoutingModule } from './driver-issues-routing.module'; -import { DriverIssuesEnglishPage } from './driver-issues.page'; -import { SharedModule } from '../shared/shared.module'; +import { NgModule } from "@angular/core"; +import { CommonModule } from "@angular/common"; +import { DriverIssuesRoutingModule } from "./driver-issues-routing.module"; +import { DriverIssuesEnglishPage } from "./driver-issues.page"; +import { SharedModule } from "../shared/shared.module"; @NgModule({ - declarations: [DriverIssuesEnglishPage], - imports: [ - CommonModule, - DriverIssuesRoutingModule, - SharedModule - ] + declarations: [DriverIssuesEnglishPage], + imports: [CommonModule, DriverIssuesRoutingModule, SharedModule], }) -export class DriverIssuesEnglishModule { } +export class DriverIssuesEnglishModule {} diff --git a/src/app/modules/driver-issues-english/driver-issues.page.html b/src/app/modules/driver-issues-english/driver-issues.page.html index dded6d7c..d5094ee4 100644 --- a/src/app/modules/driver-issues-english/driver-issues.page.html +++ b/src/app/modules/driver-issues-english/driver-issues.page.html @@ -1,69 +1,81 @@
- -
-

Having uploading problems?

-

Select the most relevant to you, first browser then OS

-
-

Firefox Uploading Issues

-
If you're experiencing problems with uploading in Firefox, follow these steps...
+    
+

Having uploading problems?

+

Select the most relevant to you, first browser then OS

+
+

Firefox Uploading Issues

+
+If you're experiencing problems with uploading in Firefox, follow these steps...
 
       - Switching browsers is the easiest way to solve uploading issues. Try using Chrome or Edge or Opera instead.
       - As of the latest update there is no support for Firefox. It does not support the API used on all other working browsers.
-      
-
+
+
-
-

Safari Uploading Issues

-
If you're encountering uploading difficulties in Safari, try the following solutions...
+        
+

Safari Uploading Issues

+
+If you're encountering uploading difficulties in Safari, try the following solutions...
 
       - Switching browsers is the easiest way to solve uploading issues. Try using Chrome or Edge or Opera instead.
       - As of the latest update there is no support for Safari. It does not support the API used on all other working browsers.
-      
-
+
+
-
-

Linux Uploading Issues

-
If you're using Linux and facing uploading challenges, consider these troubleshooting tips...
+        
+

Linux Uploading Issues

+
+If you're using Linux and facing uploading challenges, consider these troubleshooting tips...
 
       - Make sure you have the latest version of Chrome or Edge or Opera installed.
       - Use dmesg to find potential issues (e.g. dmesg | grep -i usb), personally I found that an software called (brltty) causing issues (apt purge brltty)
       - If you can't find a fix, please send an e-mail to helpdesk@leaphy.org
-      
-
+
+
-
-

Windows Uploading Issues

-
If you're using Windows and having trouble uploading, here are some steps you can take...
+        
+

Windows Uploading Issues

+
+If you're using Windows and having trouble uploading, here are some steps you can take...
 
       - Installed the necessary drivers? (https://github.com/leaphy-robotics/leaphy-webbased/archive/refs/heads/executables.zip)
       - Make sure you have the latest version of Chrome or Edge or Opera installed.
       - If you can't find a fix, please send an e-mail to helpdesk@leaphy.org
-      
-
+
+
-
-

Mac Uploading Issues

-
If you're on a Mac and experiencing uploading problems, try these suggestions...
+        
+

Mac Uploading Issues

+
+If you're on a Mac and experiencing uploading problems, try these suggestions...
 
       - Make sure you have the latest version of Chrome or Edge or Opera installed.
       - If you can't find a fix, please send an e-mail to helpdesk@leaphy.org
-      
-
+
+
-
-

Mobile Device Uploading Issues

-
If you're using a mobile device and encountering uploading difficulties, follow these steps...
+        
+

Mobile Device Uploading Issues

+
+If you're using a mobile device and encountering uploading difficulties, follow these steps...
 
       - As of the latest update there is no support for mobile devices. It does not support the API used on all other working browsers. (Even those who support on desktop)
-      
-
+
+
-
-

Other Uploading Issues

-
If your uploading problems don't fit into the above categories, explore these solutions...
-        Send an e-mail to: helpdesk@leaphy.org
+
+

Other Uploading Issues

+
+If your uploading problems don't fit into the above categories, explore these solutions...
+        Send an e-mail to: helpdesk@leaphy.org
+
+
-
-
- diff --git a/src/app/modules/driver-issues-english/driver-issues.page.scss b/src/app/modules/driver-issues-english/driver-issues.page.scss index 381256d8..3725eddd 100644 --- a/src/app/modules/driver-issues-english/driver-issues.page.scss +++ b/src/app/modules/driver-issues-english/driver-issues.page.scss @@ -1,52 +1,51 @@ #container { - display: flex; - align-items: stretch; - width: 100vw; - overflow-y: scroll; + display: flex; + align-items: stretch; + width: 100vw; + overflow-y: scroll; } #header-container { - position: fixed; /* Fix the position */ - top: 0; /* Position at the top */ - left: 0; /* Position at the left */ - right: 0; /* Position at the right */ - z-index: 1000; /* Set a high z-index to ensure it's above other content */ - width: 100vw; /* Take up the full width */ + position: fixed; /* Fix the position */ + top: 0; /* Position at the top */ + left: 0; /* Position at the left */ + right: 0; /* Position at the right */ + z-index: 1000; /* Set a high z-index to ensure it's above other content */ + width: 100vw; /* Take up the full width */ } #container h1 { - margin-top: 1%; + margin-top: 1%; } #container h3 { - text-align: left; - margin-bottom: 1%; + text-align: left; + margin-bottom: 1%; } .content { - flex: 1 1 auto; - padding: 20px; + flex: 1 1 auto; + padding: 20px; } #content div { - margin-top: 5%; + margin-top: 5%; } #content h2 { - text-align: center; - margin-top: 3%; + text-align: center; + margin-top: 3%; } body { - overflow-y: scroll; /* Override the body's overflow */ + overflow-y: scroll; /* Override the body's overflow */ } h2 { - cursor: pointer; /* Add a pointer cursor to indicate clickability */ - transition: color 0.3s; /* Smooth color transition on hover */ + cursor: pointer; /* Add a pointer cursor to indicate clickability */ + transition: color 0.3s; /* Smooth color transition on hover */ } h2:hover { - color: #007bff; /* Change color on hover */ + color: #007bff; /* Change color on hover */ } - diff --git a/src/app/modules/driver-issues-english/driver-issues.page.spec.ts b/src/app/modules/driver-issues-english/driver-issues.page.spec.ts index 11a676e3..eb3a13fc 100644 --- a/src/app/modules/driver-issues-english/driver-issues.page.spec.ts +++ b/src/app/modules/driver-issues-english/driver-issues.page.spec.ts @@ -1,25 +1,24 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ComponentFixture, TestBed } from "@angular/core/testing"; -import { DriverIssuesEnglishPage } from './driver-issues.page'; +import { DriverIssuesEnglishPage } from "./driver-issues.page"; -describe('DriverIssuesEnglish', () => { - let component: DriverIssuesEnglishPage; - let fixture: ComponentFixture; +describe("DriverIssuesEnglish", () => { + let component: DriverIssuesEnglishPage; + let fixture: ComponentFixture; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ DriverIssuesEnglishPage ] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [DriverIssuesEnglishPage], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(DriverIssuesEnglishPage); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(DriverIssuesEnglishPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it("should create", () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/modules/driver-issues-english/driver-issues.page.ts b/src/app/modules/driver-issues-english/driver-issues.page.ts index 599a699a..659b857b 100644 --- a/src/app/modules/driver-issues-english/driver-issues.page.ts +++ b/src/app/modules/driver-issues-english/driver-issues.page.ts @@ -1,11 +1,10 @@ -import { Component } from '@angular/core'; +import { Component } from "@angular/core"; @Component({ - selector: 'app-driver-issues-english-page', - templateUrl: './driver-issues.page.html', - styleUrls: ['./driver-issues.page.scss'] + selector: "app-driver-issues-english-page", + templateUrl: "./driver-issues.page.html", + styleUrls: ["./driver-issues.page.scss"], }) export class DriverIssuesEnglishPage { - - constructor() { } + constructor() {} } diff --git a/src/app/modules/shared/components/button-bar/button-bar.component.html b/src/app/modules/shared/components/button-bar/button-bar.component.html index e8e20e4d..a8ac6cec 100644 --- a/src/app/modules/shared/components/button-bar/button-bar.component.html +++ b/src/app/modules/shared/components/button-bar/button-bar.component.html @@ -1,24 +1,34 @@
- @if ((appState.codeEditor$ | async) !== CodeEditorType.Python) { - - } + @if ((appState.codeEditor$ | async) !== CodeEditorType.Python) { + + } + @if ((appState.codeEditor$ | async) !== CodeEditorType.Python) { + + } - @if ((appState.codeEditor$ | async) !== CodeEditorType.Python) { - - } - - - @if ((appState.codeEditor$ | async) === CodeEditorType.CPP) { - - } - + @if ((appState.codeEditor$ | async) === CodeEditorType.CPP) { + + }
diff --git a/src/app/modules/shared/components/button-bar/button-bar.component.spec.ts b/src/app/modules/shared/components/button-bar/button-bar.component.spec.ts index 47c4f9bf..b739087d 100644 --- a/src/app/modules/shared/components/button-bar/button-bar.component.spec.ts +++ b/src/app/modules/shared/components/button-bar/button-bar.component.spec.ts @@ -1,25 +1,24 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; -import { ButtonBarComponent } from './button-bar.component'; +import { ButtonBarComponent } from "./button-bar.component"; -describe('ButtonBarComponent', () => { - let component: ButtonBarComponent; - let fixture: ComponentFixture; +describe("ButtonBarComponent", () => { + let component: ButtonBarComponent; + let fixture: ComponentFixture; - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ ButtonBarComponent ] - }) - .compileComponents(); - })); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [ButtonBarComponent], + }).compileComponents(); + })); - beforeEach(() => { - fixture = TestBed.createComponent(ButtonBarComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(ButtonBarComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it("should create", () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/modules/shared/components/button-bar/button-bar.component.ts b/src/app/modules/shared/components/button-bar/button-bar.component.ts index ab69bf04..17b637eb 100644 --- a/src/app/modules/shared/components/button-bar/button-bar.component.ts +++ b/src/app/modules/shared/components/button-bar/button-bar.component.ts @@ -3,7 +3,7 @@ import { MatDialog } from "@angular/material/dialog"; import { BlocklyEditorState } from "src/app/state/blockly-editor.state"; import { AppState } from "src/app/state/app.state"; import { DialogState } from "src/app/state/dialog.state"; -import {CodeEditorType} from "../../../../domain/code-editor.type"; +import { CodeEditorType } from "../../../../domain/code-editor.type"; @Component({ selector: "app-button-bar", @@ -15,9 +15,8 @@ export class ButtonBarComponent { public appState: AppState, public blocklyState: BlocklyEditorState, public dialogState: DialogState, - public dialog: MatDialog - ) { - } + public dialog: MatDialog, + ) {} public onSideNavToggled() { this.blocklyState.isSideNavOpen = !this.blocklyState.isSideNavOpen; } @@ -33,5 +32,3 @@ export class ButtonBarComponent { protected readonly AppState = AppState; protected readonly CodeEditorType = CodeEditorType; } - - diff --git a/src/app/modules/shared/components/library-manager/library-manager.component.html b/src/app/modules/shared/components/library-manager/library-manager.component.html index 5e3a4cf2..8917f03f 100644 --- a/src/app/modules/shared/components/library-manager/library-manager.component.html +++ b/src/app/modules/shared/components/library-manager/library-manager.component.html @@ -1,42 +1,90 @@ -
+
- diff --git a/src/app/modules/shared/components/library-manager/library-manager.component.ts b/src/app/modules/shared/components/library-manager/library-manager.component.ts index 18ff93c2..5715835f 100644 --- a/src/app/modules/shared/components/library-manager/library-manager.component.ts +++ b/src/app/modules/shared/components/library-manager/library-manager.component.ts @@ -1,8 +1,12 @@ -import {MatDialogRef} from "@angular/material/dialog"; -import {DialogState} from "src/app/state/dialog.state"; -import {Component} from "@angular/core"; -import {CodeEditorState} from "src/app/state/code-editor.state"; -import {AnnotatedLibrary, Library, LibraryResponse} from "src/app/domain/library-manager.types"; +import { MatDialogRef } from "@angular/material/dialog"; +import { DialogState } from "src/app/state/dialog.state"; +import { Component } from "@angular/core"; +import { CodeEditorState } from "src/app/state/code-editor.state"; +import { + AnnotatedLibrary, + Library, + LibraryResponse, +} from "src/app/domain/library-manager.types"; @Component({ selector: "app-library-manager", @@ -15,7 +19,7 @@ export class LibraryManagerComponent { constructor( public editorState: CodeEditorState, public dialogState: DialogState, - private dialog: MatDialogRef + private dialog: MatDialogRef, ) { if (this.editorState.libraryCache.length === 0) { this.loadLibraryCache().then(); @@ -25,29 +29,34 @@ export class LibraryManagerComponent { } private async loadLibraryCache() { - const res = await fetch('https://downloads.arduino.cc/libraries/library_index.json') - const { libraries } = await res.json() as LibraryResponse + const res = await fetch( + "https://downloads.arduino.cc/libraries/library_index.json", + ); + const { libraries } = (await res.json()) as LibraryResponse; - const result: Map = new Map() - libraries.forEach(library => { + const result: Map = new Map(); + libraries.forEach((library) => { if (result.has(library.name)) { const existing = result.get(library.name); existing.versions.push(library.version); - existing.versions.sort((a, b) => a.localeCompare(b)*-1); + existing.versions.sort((a, b) => a.localeCompare(b) * -1); return; } if (library.paragraph) { - library.paragraph = library.paragraph.replace(/<\/?br ?\/?>/g, "\n"); + library.paragraph = library.paragraph.replace( + /<\/?br ?\/?>/g, + "\n", + ); } result.set(library.name, { ...library, - versions: [library.version] - }) - }) + versions: [library.version], + }); + }); this.editorState.libraryCache = Array.from(result.values()); this.filter(); @@ -56,16 +65,20 @@ export class LibraryManagerComponent { set libraries(libraries: Library[]) { const installed = this.editorState.installedLibraries; - this.librariesBack = libraries.map(lib => ({ + this.librariesBack = libraries.map((lib) => ({ ...lib, - installed: installed.find(installedLib => installedLib.name === lib.name)?.version - })) + installed: installed.find( + (installedLib) => installedLib.name === lib.name, + )?.version, + })); } public filter(filter = "") { - this.libraries = this.editorState.libraryCache - .filter(lib => lib.name.toLowerCase().includes(filter.toLowerCase())) - .slice(0, 50) + this.libraries = this.editorState.libraryCache + .filter((lib) => + lib.name.toLowerCase().includes(filter.toLowerCase()), + ) + .slice(0, 50); } public close() { @@ -74,13 +87,17 @@ export class LibraryManagerComponent { public install(library: Library, version: string) { // get installed libraries and remove existing version - const installed = this.editorState.installedLibraries - .filter((lib) => lib.name !== library.name); + const installed = this.editorState.installedLibraries.filter( + (lib) => lib.name !== library.name, + ); - this.editorState.installedLibraries = [...installed, { - ...library, - version - }]; + this.editorState.installedLibraries = [ + ...installed, + { + ...library, + version, + }, + ]; this.libraries = this.librariesBack; } @@ -89,7 +106,9 @@ export class LibraryManagerComponent { const current = installed.find((lib) => lib.name === library.name); if (!current) return; - this.editorState.installedLibraries = installed.filter((lib) => lib.name !== library.name); + this.editorState.installedLibraries = installed.filter( + (lib) => lib.name !== library.name, + ); this.libraries = this.librariesBack; } } diff --git a/src/app/modules/shared/components/serial-output/serial-output.component.html b/src/app/modules/shared/components/serial-output/serial-output.component.html index 59af5d0a..9529371b 100644 --- a/src/app/modules/shared/components/serial-output/serial-output.component.html +++ b/src/app/modules/shared/components/serial-output/serial-output.component.html @@ -1,43 +1,100 @@ -
-