diff --git a/src/app/home/home.component.html b/src/app/home/home.component.html index a2756c5..679440d 100644 --- a/src/app/home/home.component.html +++ b/src/app/home/home.component.html @@ -29,7 +29,7 @@
- +
diff --git a/src/app/home/home.component.spec.ts b/src/app/home/home.component.spec.ts index 5016e86..7231e42 100644 --- a/src/app/home/home.component.spec.ts +++ b/src/app/home/home.component.spec.ts @@ -3,8 +3,8 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ActivatedRoute } from '@angular/router'; import { RouterTestingModule } from '@angular/router/testing'; import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; -import { MatTabsModule } from '@angular/material/tabs'; -import { MatPaginatorModule } from '@angular/material/paginator'; +import { MatTabChangeEvent, MatTabsModule } from '@angular/material/tabs'; +import { MatPaginatorModule, PageEvent } from '@angular/material/paginator'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { FormsModule } from '@angular/forms'; import { NO_ERRORS_SCHEMA } from '@angular/core'; @@ -57,12 +57,43 @@ describe('HomeComponent', () => { }); beforeEach(() => { + sessionStorage.clear(); fixture = TestBed.createComponent(HomeComponent); component = fixture.componentInstance; fixture.detectChanges(); }); + afterEach(() => { + sessionStorage.clear(); + }); + it('should create', () => { expect(component).toBeTruthy(); }); + + it('should restore the current page from session storage', () => { + sessionStorage.setItem('azerothcore.catalogue.page', '2'); + + const restoredFixture = TestBed.createComponent(HomeComponent); + + expect(restoredFixture.componentInstance.page).toBe(2); + restoredFixture.destroy(); + }); + + it('should save the current page and route when pagination changes', () => { + component.onPageChange({ pageIndex: 2 } as PageEvent); + + expect(sessionStorage.getItem('azerothcore.catalogue.page')).toBe('2'); + expect(sessionStorage.getItem('azerothcore.catalogue.returnHash')).toBe('#/home'); + }); + + it('should reset the page when changing tabs', () => { + component.page = 2; + + component.onTabChange({ index: 0 } as MatTabChangeEvent); + + expect(component.page).toBe(0); + expect(sessionStorage.getItem('azerothcore.catalogue.page')).toBe('0'); + expect(sessionStorage.getItem('azerothcore.catalogue.returnHash')).toBe('#/tab/test'); + }); }); diff --git a/src/app/home/home.component.ts b/src/app/home/home.component.ts index c9d577a..3302746 100644 --- a/src/app/home/home.component.ts +++ b/src/app/home/home.component.ts @@ -6,6 +6,9 @@ import { faSearch, IconDefinition } from '@fortawesome/free-solid-svg-icons'; import { Repository } from 'src/@types'; import { CatalogueService } from '../services/catalogue/catalogue.service'; +const PAGE_STORAGE_KEY = 'azerothcore.catalogue.page'; +const RETURN_HASH_STORAGE_KEY = 'azerothcore.catalogue.returnHash'; + @Component({ selector: 'app-home', templateUrl: './home.component.html', @@ -14,24 +17,54 @@ import { CatalogueService } from '../services/catalogue/catalogue.service'; export class HomeComponent { constructor(public catalogueService: CatalogueService, public cdRef: ChangeDetectorRef, private location: Location) { window.parent.document.title = 'GitCatalogue'; + this.saveRoute(); } - page = 0; + page = this.readPage(); search: string; readonly faSearch: IconDefinition = faSearch; + readPage(): number { + try { + const page = parseInt(sessionStorage.getItem(PAGE_STORAGE_KEY) || '0', 10); + return isNaN(page) || page < 0 ? 0 : page; + } catch (error) { + return 0; + } + } + + savePage(): void { + try { + sessionStorage.setItem(PAGE_STORAGE_KEY, String(this.page)); + } catch (error) {} + } + + saveRoute(path?: string): void { + try { + const route = path || this.location.path() || '/home'; + sessionStorage.setItem(RETURN_HASH_STORAGE_KEY, `#${route}`); + } catch (error) {} + } + + resetPage(): void { + this.page = 0; + this.savePage(); + this.saveRoute(); + this.refresh(); + } + refresh(): void { this.cdRef.detectChanges(); } onSearchChange(value: string): void { - // Ensure we reset to the first page when the search term changes - this.page = 0; - this.refresh(); + this.resetPage(); } onPageChange(page: PageEvent): void { this.page = page.pageIndex; + this.savePage(); + this.saveRoute(); } onTabChange(tab: MatTabChangeEvent): void { @@ -39,6 +72,10 @@ export class HomeComponent { const tabName = Object.keys(this.catalogueService.CONF.tabs)[index]; const path = `/tab${this.catalogueService.CONF.tabs[tabName].path}`; + this.page = 0; + this.savePage(); + this.saveRoute(path); + if (this.location.path() !== path) { this.location.go(path); } diff --git a/src/app/repo-details/repo-details.component.html b/src/app/repo-details/repo-details.component.html index 6c426bd..179ad25 100644 --- a/src/app/repo-details/repo-details.component.html +++ b/src/app/repo-details/repo-details.component.html @@ -1,4 +1,4 @@ -   back to Catalogue +   back to Catalogue
diff --git a/src/app/repo-details/repo-details.component.spec.ts b/src/app/repo-details/repo-details.component.spec.ts index ffa6d0a..9514a86 100644 --- a/src/app/repo-details/repo-details.component.spec.ts +++ b/src/app/repo-details/repo-details.component.spec.ts @@ -18,12 +18,35 @@ describe('RepoDetailsComponent', () => { }); beforeEach(() => { + sessionStorage.clear(); fixture = TestBed.createComponent(RepoDetailsComponent); component = fixture.componentInstance; fixture.detectChanges(); }); + afterEach(() => { + sessionStorage.clear(); + }); + it('should create', () => { expect(component).toBeTruthy(); }); + + it('should use the stored catalogue route for the back link', () => { + sessionStorage.setItem('azerothcore.catalogue.returnHash', '#/tab/modules'); + + const restoredFixture = TestBed.createComponent(RepoDetailsComponent); + + expect(restoredFixture.componentInstance.returnHash).toBe('#/tab/modules'); + restoredFixture.destroy(); + }); + + it('should fall back to the catalogue home for invalid return routes', () => { + sessionStorage.setItem('azerothcore.catalogue.returnHash', 'https://example.com'); + + const restoredFixture = TestBed.createComponent(RepoDetailsComponent); + + expect(restoredFixture.componentInstance.returnHash).toBe('#/home'); + restoredFixture.destroy(); + }); }); diff --git a/src/app/repo-details/repo-details.component.ts b/src/app/repo-details/repo-details.component.ts index 6b9dc88..a6ec8d0 100644 --- a/src/app/repo-details/repo-details.component.ts +++ b/src/app/repo-details/repo-details.component.ts @@ -17,6 +17,8 @@ import { Observable } from 'rxjs'; import { pluck, tap } from 'rxjs/operators'; import { RepoDetailsData } from '../services/resolvers/repo-details-resolver.service'; +const RETURN_HASH_STORAGE_KEY = 'azerothcore.catalogue.returnHash'; + @Component({ selector: 'app-repo-details', templateUrl: './repo-details.component.html', @@ -45,6 +47,18 @@ export class RepoDetailsComponent { readonly faClock = faClock; readonly faBalanceScale = faBalanceScale; readonly faSync = faSync; + readonly returnHash = this.readReturnHash(); data$: Observable; + + private readReturnHash(): string { + try { + const returnHash = sessionStorage.getItem(RETURN_HASH_STORAGE_KEY); + if (returnHash && returnHash.indexOf('#/') === 0 && returnHash.indexOf('#/details/') !== 0) { + return returnHash; + } + } catch (error) {} + + return '#/home'; + } }