diff --git a/.gitea/workflows/build-and-deploy.yml b/.gitea/workflows/build-and-deploy.yml index 8efd101..3d26d79 100644 --- a/.gitea/workflows/build-and-deploy.yml +++ b/.gitea/workflows/build-and-deploy.yml @@ -4,6 +4,7 @@ on: push: branches: - main + - fix-left-side-menu jobs: build-and-deploy: diff --git a/frontend/src/app/components/side-menu/categories-menu/categories-menu.component.html b/frontend/src/app/components/side-menu/categories-menu/categories-menu.component.html index 8a83dab..4b0ccf2 100644 --- a/frontend/src/app/components/side-menu/categories-menu/categories-menu.component.html +++ b/frontend/src/app/components/side-menu/categories-menu/categories-menu.component.html @@ -1,6 +1,6 @@ -@for (category of categories$ | async; track category) { +@for (category of categories(); track category.id) {
-
+
{{ category.name }} chevron_right
diff --git a/frontend/src/app/components/side-menu/categories-menu/categories-menu.component.ts b/frontend/src/app/components/side-menu/categories-menu/categories-menu.component.ts index 226a9c2..87d2ff4 100644 --- a/frontend/src/app/components/side-menu/categories-menu/categories-menu.component.ts +++ b/frontend/src/app/components/side-menu/categories-menu/categories-menu.component.ts @@ -1,8 +1,7 @@ import {CommonModule} from "@angular/common"; -import {Component, EventEmitter, inject, OnInit, Output} from "@angular/core"; +import {Component, inject, OnInit, output, Signal} from "@angular/core"; import {MatIconModule} from "@angular/material/icon"; import {DisplayableCategory, SideMenuService} from "../side-menu.service"; -import {Observable} from "rxjs"; import {RouterModule} from "@angular/router"; @Component({ @@ -16,45 +15,44 @@ import {RouterModule} from "@angular/router"; styleUrl: './categories-menu.component.scss' }) export class CategoriesMenuComponent implements OnInit { - private sideMenuService = inject(SideMenuService); - @Output() - categoryClicked = new EventEmitter(); + readonly #sideMenuService = inject(SideMenuService); + categoryClicked = output(); ngOnInit(): void { - this.sideMenuService.loadCategories(); + this.#sideMenuService.loadCategories(); } - get categories$(): Observable { - return this.sideMenuService.categories$; + get categories(): Signal { + return this.#sideMenuService.categories; } - setOpenned(category: DisplayableCategory): void { + setOpened(category: DisplayableCategory): void { if (category.isOpenned) { const categoryDiv = document.getElementById(`category-${category.id}`); if (categoryDiv) { - this.closeAccordion(categoryDiv); + this.#closeAccordion(categoryDiv); } } else { const categoriesDivs = document.getElementsByClassName('category-header'); Array.from(categoriesDivs) .map(category => category as HTMLElement) - .forEach(categoryDiv => this.closeAccordion(categoryDiv)); + .forEach(categoryDiv => this.#closeAccordion(categoryDiv)); const categoryDiv = document.getElementById(`category-${category.id}`); if (categoryDiv) { - this.openAccordion(categoryDiv); + this.#openAccordion(categoryDiv); } } - this.sideMenuService.setOpenned(category); + this.#sideMenuService.setOpened(category); } - private closeAccordion(categoryDiv: HTMLElement): void { + #closeAccordion(categoryDiv: HTMLElement): void { const divContent = categoryDiv?.nextElementSibling as HTMLElement; divContent.style.maxHeight = '0'; } - private openAccordion(categoryDiv: HTMLElement): void { + #openAccordion(categoryDiv: HTMLElement): void { const divContent = categoryDiv?.nextElementSibling as HTMLElement; divContent.style.maxHeight = `${divContent.scrollHeight}px`; } diff --git a/frontend/src/app/components/side-menu/side-menu.component.html b/frontend/src/app/components/side-menu/side-menu.component.html index 583647e..82a67e6 100644 --- a/frontend/src/app/components/side-menu/side-menu.component.html +++ b/frontend/src/app/components/side-menu/side-menu.component.html @@ -14,6 +14,6 @@

Categories

- +
diff --git a/frontend/src/app/components/side-menu/side-menu.service.ts b/frontend/src/app/components/side-menu/side-menu.service.ts index c878ea1..b594410 100644 --- a/frontend/src/app/components/side-menu/side-menu.service.ts +++ b/frontend/src/app/components/side-menu/side-menu.service.ts @@ -1,6 +1,5 @@ -import {inject, Injectable} from '@angular/core'; +import {inject, Injectable, Signal, signal} from '@angular/core'; import {MatSnackBar} from '@angular/material/snack-bar'; -import {BehaviorSubject, Observable} from 'rxjs'; import {CategoryRestService} from '../../core/rest-services/category/category.rest-service'; import {Category} from '../../core/rest-services/category/model/category'; @@ -20,68 +19,60 @@ export interface DisplayableSubCategory { providedIn: 'root' }) export class SideMenuService { - private categoryRestService = inject(CategoryRestService); - private snackBar = inject(MatSnackBar); - private categoriesSubject = new BehaviorSubject([]); - private isLoadingSubject = new BehaviorSubject(false); - private isLoadedSubject = new BehaviorSubject(false); + readonly #categoryRestService = inject(CategoryRestService); + readonly #snackBar = inject(MatSnackBar); + #categories = signal([]); + #isLoading = signal(false); + isLoaded = signal(false); - private mapToDisplayableCategory(category: Category): DisplayableCategory { + #mapToDisplayableCategory(category: Category): DisplayableCategory { return { id: category.id, name: category.name, - subCategories: category.subCategories.map(subCategory => this.mapToDisplayableSubCategory(subCategory)), + subCategories: category.subCategories.map(subCategory => this.#mapToDisplayableSubCategory(subCategory)), isOpenned: false }; } - private mapToDisplayableSubCategory(subCategory: Category): DisplayableSubCategory { + #mapToDisplayableSubCategory(subCategory: Category): DisplayableSubCategory { return { id: subCategory.id, name: subCategory.name } } - private get categories(): DisplayableCategory[] { - return this.categoriesSubject.value; + get categories(): Signal { + return this.#categories.asReadonly(); } - private save(categories: DisplayableCategory[]): void { - this.categoriesSubject.next(categories); - } - - get categories$(): Observable { - return this.categoriesSubject.asObservable(); - } - - get isLoading$(): Observable { - return this.isLoadingSubject.asObservable(); + get isLoading(): Signal { + return this.#isLoading.asReadonly(); } loadCategories(): void { - this.isLoadingSubject.next(true); - this.isLoadedSubject.next(false); + this.#isLoading.set(true); + this.isLoaded.set(false); - this.categoryRestService.getCategories() + this.#categoryRestService.getCategories() .then(categories => { const displayableCategories = categories .filter(category => category.subCategories?.length) - .map(category => this.mapToDisplayableCategory(category)); - this.categoriesSubject.next(displayableCategories); + .map(category => this.#mapToDisplayableCategory(category)); + this.#categories.set(displayableCategories); }) .catch(error => { const errorMessage = $localize`An error occured while loading categories.`; console.error(errorMessage, error); - this.snackBar.open(errorMessage, $localize`Close`, {duration: 5000}); + this.#snackBar.open(errorMessage, $localize`Close`, {duration: 5000}); }) .finally(() => { - this.isLoadingSubject.next(false); - this.isLoadedSubject.next(true); + this.#isLoading.set(false); + this.isLoaded.set(true); }); } - setOpenned(category: DisplayableCategory): void { - const categories = this.categories; + setOpened(category: DisplayableCategory): void { + const categories = this.#categories(); const matchingCategory = categories.find(categoryTemp => categoryTemp.id === category.id); if (matchingCategory) { const actualOpennedCategory = categories.find(category => category.isOpenned); @@ -91,7 +82,7 @@ export class SideMenuService { categories.forEach(categoryTemp => categoryTemp.isOpenned = false); matchingCategory.isOpenned = true; } - this.save(categories); + this.#categories.set(categories); } } }