Conversation
❌ Deploy Preview for cutetix-admin failed.
|
There was a problem hiding this comment.
Pull request overview
Adds a linting toolchain (ESLint + Prettier + Stylelint) and CI enforcement for an Angular app, along with stricter TypeScript compiler options and broad formatting/import updates to align the codebase with the new rules.
Changes:
- Add lint scripts and dependencies (Angular ESLint, Prettier, Stylelint) and wire Angular lint target.
- Introduce GitHub Actions CI workflow to run lint on pushes/PRs and publish Docker on master pushes after lint passes.
- Tighten TS compiler options and reformat/update TS/HTML/SCSS files to match new lint/format rules.
Reviewed changes
Copilot reviewed 90 out of 109 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| tsconfig.json | Enable stricter TS compiler flags (strictness, unused checks, comment stripping). |
| src/styles/_typography.scss | SCSS reformat for Stylelint/Prettier compliance. |
| src/styles/_fonts.scss | SCSS reformat and quoting normalization. |
| src/styles/_colors.scss | SCSS reformat + hex casing normalization. |
| src/styles/_button.scss | SCSS reformat and structural cleanup. |
| src/styles.scss | Global styles reformat and quote normalization. |
| src/main.ts | Import/format updates for lint/Prettier. |
| src/index.html | HTML formatting changes for Prettier. |
| src/environments/environment.development.ts | Formatting/indentation normalization. |
| src/app/utils/deepEqual.ts | Formatting cleanup (file later excluded from ESLint). |
| src/app/user-profile/user-profile.component.ts | Import/style formatting changes. |
| src/app/user-profile/user-profile.component.scss | SCSS reformat. |
| src/app/user-profile/user-profile.component.html | Template formatting changes. |
| src/app/types/auth.types.ts | Type formatting (but retains a misspelled field name). |
| src/app/tokens/storage.tokens.ts | Type expression formatting/parentheses. |
| src/app/tokens/lock.tokens.ts | Type expression formatting/parentheses. |
| src/app/shared/shared.module.ts | Import ordering + NgModule metadata formatting. |
| src/app/services/visibility.service.ts | Import formatting + decorator metadata formatting. |
| src/app/services/update.service.ts | Import type-splitting + formatting. |
| src/app/services/storage.service.ts | Type-only import + formatting + minor refactors. |
| src/app/services/logging.service.ts | Formatting + type expression formatting. |
| src/app/services/auth.service.ts | Formatting + minor structural refactors (refresh scheduling/lock handling area touched). |
| src/app/not-found/not-found.component.ts | Formatting cleanup. |
| src/app/not-found/not-found.component.scss | SCSS reformat. |
| src/app/not-found/not-found.component.html | Template formatting. |
| src/app/login-page/login-page.component.ts | Formatting + minor line wrapping. |
| src/app/login-page/login-page.component.scss | SCSS reformat. |
| src/app/login-page/login-page.component.html | Template formatting and wrapping. |
| src/app/interceptors/auth.interceptor.ts | Type-only import + formatting. |
| src/app/hello/hello.component.ts | Type-only import + formatting. |
| src/app/hello/hello.component.scss | SCSS reformat. |
| src/app/hello/hello.component.html | Template formatting. |
| src/app/guards/logout.guard.ts | Type-only import + formatting. |
| src/app/guards/auth.guard.ts | Formatting + braces. |
| src/app/components/user-info/user-info.component.ts | Type-only import + formatting + minor refactors. |
| src/app/components/user-info/user-info.component.scss | SCSS reformat. |
| src/app/components/user-info/user-info.component.html | Template formatting. |
| src/app/components/local-storage-field/local-storage-field.component.ts | Type-only imports + formatting + minor refactors. |
| src/app/components/local-storage-field/local-storage-field.component.scss | SCSS reformat + selector spacing normalization. |
| src/app/components/local-storage-field/local-storage-field.component.html | Template formatting. |
| src/app/components/copyright/copyright.component.ts | Formatting + minor spacing changes. |
| src/app/components/copyright/copyright.component.scss | SCSS reformat. |
| src/app/components/copyright/copyright.component.html | Template formatting. |
| src/app/app.routes.ts | Import sorting + route config formatting; export changed to const. |
| src/app/app.module.ts | Import ordering + module metadata formatting. |
| src/app/app.component.ts | Import ordering + minor formatting. |
| src/app/app.component.spec.ts | Test formatting (quotes/arrays). |
| src/app/app.component.html | Formatting only. |
| src/app/administration/tickets/tickets.types.ts | Convert interface→type + type-only import. |
| src/app/administration/tickets/tickets.service.ts | Type-only imports + formatting + map callbacks simplified. |
| src/app/administration/tickets/new/tickets-new.component.ts | Type-only imports + formatting. |
| src/app/administration/tickets/new/tickets-new.component.html | Template formatting. |
| src/app/administration/tickets/list/tickets-list.component.ts | Type-only imports + formatting + filter helpers refactor. |
| src/app/administration/tickets/list/tickets-list.component.scss | SCSS reformat. |
| src/app/administration/tickets/list/tickets-list.component.html | Template formatting. |
| src/app/administration/ticket_groups/ticket_groups.types.ts | Convert interfaces→types + type-only import. |
| src/app/administration/ticket_groups/ticket_groups.service.ts | Type-only imports + formatting + map callbacks simplified. |
| src/app/administration/ticket_groups/new/ticket_groups-new.component.ts | Type-only imports + formatting. |
| src/app/administration/ticket_groups/new/ticket_groups-new.component.html | Template formatting. |
| src/app/administration/ticket_groups/list/ticket_groups-list.component.ts | Type-only imports + formatting. |
| src/app/administration/ticket_groups/list/ticket_groups-list.component.scss | SCSS reformat. |
| src/app/administration/ticket_groups/list/ticket_groups-list.component.html | Template formatting. |
| src/app/administration/ticket_groups/edit/events-edit.component.ts | Type-only imports + formatting. |
| src/app/administration/ticket_groups/edit/events-edit.component.html | Template formatting. |
| src/app/administration/loading/loading.component.ts | Formatting + import spacing. |
| src/app/administration/loading/loading.component.scss | SCSS reformat. |
| src/app/administration/loading/loading.component.html | Formatting only. |
| src/app/administration/layout/nav-bar/nav-bar.component.ts | Type-only imports + formatting. |
| src/app/administration/layout/nav-bar/nav-bar.component.scss | SCSS reformat. |
| src/app/administration/layout/nav-bar/nav-bar.component.html | Template formatting. |
| src/app/administration/layout/nav-bar/menu-items.ts | Type-only import + formatting. |
| src/app/administration/layout/nav-bar/menu-builder.ts | Type-only import + formatting. |
| src/app/administration/layout/nav-bar-subitem/nav-bar-subitem.component.ts | Formatting + default value normalization. |
| src/app/administration/layout/nav-bar-subitem/nav-bar-subitem.component.scss | SCSS reformat. |
| src/app/administration/layout/nav-bar-subitem/nav-bar-subitem.component.html | Template formatting. |
| src/app/administration/layout/nav-bar-item/nav-bar-item.component.ts | Type-only import + formatting. |
| src/app/administration/layout/nav-bar-item/nav-bar-item.component.scss | SCSS reformat. |
| src/app/administration/layout/nav-bar-item/nav-bar-item.component.html | Template formatting. |
| src/app/administration/layout/logged-user/logged-user.component.ts | Type-only import + formatting. |
| src/app/administration/layout/logged-user/logged-user.component.scss | SCSS reformat. |
| src/app/administration/layout/logged-user/logged-user.component.html | Template formatting. |
| src/app/administration/layout/layout.component.ts | Formatting cleanup. |
| src/app/administration/layout/layout.component.scss | SCSS reformat. |
| src/app/administration/layout/layout.component.html | Template formatting. |
| src/app/administration/events/list/events-list.component.ts | Type-only imports + formatting. |
| src/app/administration/events/list/events-list.component.scss | SCSS reformat. |
| src/app/administration/events/list/events-list.component.html | Template formatting. |
| src/app/administration/events/form/events-form.component.ts | Type-only imports + formatting. |
| src/app/administration/events/form/events-form.component.html | Template formatting. |
| src/app/administration/events/events.types.ts | Convert interfaces→types + type-only import. |
| src/app/administration/events/events.service.ts | Type-only imports + formatting + map callbacks simplified. |
| src/app/administration/dashboard/event-overview/dashboard-event-overview.component.ts | Type-only imports + formatting. |
| src/app/administration/dashboard/event-overview/dashboard-event-overview.component.scss | SCSS reformat + color casing normalization. |
| src/app/administration/dashboard/event-overview/dashboard-event-overview.component.html | Minor formatting only. |
| src/app/administration/dashboard/dashboard.component.ts | Formatting cleanup. |
| src/app/administration/dashboard/dashboard.component.html | Template formatting. |
| src/app/administration/common/styles.scss | Shared admin SCSS reformat. |
| src/app/administration/administration.module.ts | Import ordering + module metadata formatting. |
| package.json | Add lint scripts/deps; remove watch/test scripts. |
| angular.json | Add Angular ESLint lint target; set schematic collection for ESLint. |
| .stylelintrc | Added Stylelint config file (currently empty). |
| .prettierrc.ts | Add repository Prettier config. |
| .github/workflows/publish-docker.yml | Removed legacy Docker publishing workflow. |
| .github/workflows/ci.yml | Add CI workflow for lint + Docker publish gating. |
| .gitattributes | Enforce LF line endings via attributes. |
| .eslintrc.json | Introduce/strengthen ESLint rules and Angular ESLint integration. |
| .eslintignore | Exclude deepEqual and index.html from ESLint. |
| .editorconfig | Enforce LF + adjust global editor settings. |
Comments suppressed due to low confidence (1)
src/app/services/update.service.ts:58
- Typo in log message: "Error ocurred" → "Error occurred".
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| quote_type = double | ||
| max_line_length=120 |
There was a problem hiding this comment.
The [*.ts] section was removed, so quote_type / max_line_length now apply to all files under [*]. If the intent was to scope these settings to TypeScript only, reintroduce the [*.ts] header (or split settings per file type) to avoid unintended editor behavior.
| quote_type = double | |
| max_line_length=120 | |
| [*.ts] | |
| quote_type = double | |
| max_line_length = 120 |
| "@typescript-eslint/explicit-function-return-type": "error", | ||
|
|
||
| "no-multiple-empty-lines": ["error", { "max": 1, "maxEOF": 1 }], | ||
| "comma-spacing": ["error", { "before": false, "after": true }], | ||
| "eqeqeq": ["error", "always"], |
There was a problem hiding this comment.
@typescript-eslint/explicit-function-return-type is enabled as error, but multiple updated TS files still have methods/getters without explicit return types; this will make ng lint fail in CI. Either relax/replace this rule (e.g. prefer explicit-module-boundary-types) or update the codebase to add explicit return types everywhere.
| <label for="send_mail">Send e-mail</label> | ||
| <input type="checkbox" name="send_mail" formControlName="send_mail"> | ||
|
|
There was a problem hiding this comment.
This template binds formControlName="send_mail", but the component’s FormGroup does not define a send_mail control. Reactive Forms will throw "Cannot find control with name: 'send_mail'" at runtime. Add the control to the FormGroup (and handle it in newTicket()), or remove this field from the template.
| public newTicket() { | ||
| this.ticketService.create({ |
There was a problem hiding this comment.
With @typescript-eslint/explicit-function-return-type enabled, this method needs an explicit return type (likely : void) or the lint job will fail. If you don’t want to annotate every method, consider relaxing that rule in the ESLint config.
| private matchesGroup(ticket: Ticket, group: FilterState["group"]): boolean { | ||
| if (group === "any") { | ||
| return true; | ||
| } | ||
| return group == ticket.group?.id; | ||
| } | ||
|
|
||
| private matchesEvent(ticket: Ticket, eventF: FilterState['event']): boolean { | ||
| if (eventF === 'any') return true; | ||
| private matchesEvent(ticket: Ticket, eventF: FilterState["event"]): boolean { | ||
| if (eventF === "any") { | ||
| return true; | ||
| } | ||
| return eventF == ticket.group?.event?.id; | ||
| } |
There was a problem hiding this comment.
== comparisons here will violate the new eqeqeq: ["error","always"] rule, and they also hide implicit coercions between the filter’s string values and numeric IDs. Prefer normalizing types explicitly (e.g. compare String(...) or Number(...)) and then use ===.
| protected loginWithPassword() { | ||
| // Show loading spinner | ||
| this.loggingIn = true; | ||
|
|
||
| this.#auth.login( | ||
| this.loginForm.value.username ?? '', | ||
| this.loginForm.value.password ?? '' | ||
| ); | ||
| this.#auth.login(this.loginForm.value.username ?? "", this.loginForm.value.password ?? ""); | ||
|
|
||
| // Hide loading spinner | ||
| this.loggingIn = false; |
There was a problem hiding this comment.
loggingIn is set back to false immediately after calling auth.login(), so the loading UI won’t remain visible while the request is in flight. Move the reset into the login success/error handling (or have login() return an Observable/Promise you can await) so the spinner reflects the real state.
| export type AuthTokenResponse = { | ||
| access_token: string; | ||
| refrresh_token: string; | ||
| token_type: string; | ||
| } | ||
| access_token: string; | ||
| refrresh_token: string; | ||
| token_type: string; |
There was a problem hiding this comment.
Property name looks misspelled: refrresh_token → refresh_token. Keeping the typo in a public type can propagate incorrect field names to API consumers.
| "scripts": { | ||
| "ng": "ng", | ||
| "start": "ng serve --watch --host 0.0.0.0 --port 4200", | ||
| "build": "ng build", | ||
| "watch": "ng build --watch --configuration development", | ||
| "test": "ng test" | ||
| "lint:ng": "ng lint", | ||
| "lint:prettier": "prettier --check 'src/**/*.{ts,html,scss,css}'", | ||
| "lint:scss": "stylelint \"src/**/*.scss\"", | ||
| "lint": "npm run lint:prettier && npm run lint:ng && npm run lint:scss", | ||
| "lint:fix": "prettier --write 'src/**/*.{ts,html,scss,css}' && ng lint --fix && stylelint --fix \"src/**/*.scss\"" | ||
| }, |
There was a problem hiding this comment.
The test (and previously watch) npm scripts were removed. This can break existing workflows and CI conventions that rely on npm test/npm run watch. Consider keeping these scripts (even if CI focuses on linting) and adding lint scripts alongside them.
| "lint:prettier": "prettier --check 'src/**/*.{ts,html,scss,css}'", | ||
| "lint:scss": "stylelint \"src/**/*.scss\"", | ||
| "lint": "npm run lint:prettier && npm run lint:ng && npm run lint:scss", | ||
| "lint:fix": "prettier --write 'src/**/*.{ts,html,scss,css}' && ng lint --fix && stylelint --fix \"src/**/*.scss\"" |
There was a problem hiding this comment.
lint:prettier uses single quotes around the glob. On Windows shells this often won’t expand correctly, causing false failures. Prefer double quotes (or no quotes) for cross-platform npm scripts.
| "lint:prettier": "prettier --check 'src/**/*.{ts,html,scss,css}'", | |
| "lint:scss": "stylelint \"src/**/*.scss\"", | |
| "lint": "npm run lint:prettier && npm run lint:ng && npm run lint:scss", | |
| "lint:fix": "prettier --write 'src/**/*.{ts,html,scss,css}' && ng lint --fix && stylelint --fix \"src/**/*.scss\"" | |
| "lint:prettier": "prettier --check \"src/**/*.{ts,html,scss,css}\"", | |
| "lint:scss": "stylelint \"src/**/*.scss\"", | |
| "lint": "npm run lint:prettier && npm run lint:ng && npm run lint:scss", | |
| "lint:fix": "prettier --write \"src/**/*.{ts,html,scss,css}\" && ng lint --fix && stylelint --fix \"src/**/*.scss\"" |
| const accessToken = this.getAccessToken()!; | ||
| if (accessToken === null) { | ||
| this.refresh(); | ||
| } | ||
| const parsedAccessToken = jwtDecode(accessToken); |
There was a problem hiding this comment.
In #scheduleNextRefresh(), when accessToken is null you call this.refresh() but then continue to jwtDecode(accessToken), which will throw and immediately trigger logout() via the catch. Add an early return after refresh(), and consider removing the non-null assertion (!) so the null check is type-correct.
No description provided.