-
{{ item.seriesCount }} Series
-
{{ item.issueCount }} Issues
+
+
{{ item.title }}
+
+ {{t('series-count', {num: item.seriesCount | compactNumber})}}
+ {{t('issue-count', {num: item.issueCount | compactNumber})}}
diff --git a/UI/Web/src/app/browse/browse-genres/browse-genres.component.scss b/UI/Web/src/app/browse/browse-genres/browse-genres.component.scss
new file mode 100644
index 000000000..90c313b37
--- /dev/null
+++ b/UI/Web/src/app/browse/browse-genres/browse-genres.component.scss
@@ -0,0 +1 @@
+@use '../../../tag-card-common';
diff --git a/UI/Web/src/app/all-genres/browse-genres.component.ts b/UI/Web/src/app/browse/browse-genres/browse-genres.component.ts
similarity index 60%
rename from UI/Web/src/app/all-genres/browse-genres.component.ts
rename to UI/Web/src/app/browse/browse-genres/browse-genres.component.ts
index b5d92f396..d854c5385 100644
--- a/UI/Web/src/app/all-genres/browse-genres.component.ts
+++ b/UI/Web/src/app/browse/browse-genres/browse-genres.component.ts
@@ -1,35 +1,29 @@
-import {
- ChangeDetectionStrategy,
- ChangeDetectorRef,
- Component,
- DestroyRef,
- EventEmitter,
- inject,
- OnInit
-} from '@angular/core';
-import {CardDetailLayoutComponent} from "../cards/card-detail-layout/card-detail-layout.component";
+import {ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, inject, OnInit} from '@angular/core';
+import {CardDetailLayoutComponent} from "../../cards/card-detail-layout/card-detail-layout.component";
import {DecimalPipe} from "@angular/common";
import {
SideNavCompanionBarComponent
-} from "../sidenav/_components/side-nav-companion-bar/side-nav-companion-bar.component";
+} from "../../sidenav/_components/side-nav-companion-bar/side-nav-companion-bar.component";
import {TranslocoDirective} from "@jsverse/transloco";
-import {JumpbarService} from "../_services/jumpbar.service";
-import {BrowsePerson} from "../_models/person/browse-person";
-import {Pagination} from "../_models/pagination";
-import {JumpKey} from "../_models/jumpbar/jump-key";
-import {MetadataService} from "../_services/metadata.service";
-import {BrowseGenre} from "../_models/metadata/browse-genre";
-import {FilterField} from "../_models/metadata/v2/filter-field";
-import {FilterComparison} from "../_models/metadata/v2/filter-comparison";
-import {FilterUtilitiesService} from "../shared/_services/filter-utilities.service";
+import {JumpbarService} from "../../_services/jumpbar.service";
+import {BrowsePerson} from "../../_models/person/browse-person";
+import {Pagination} from "../../_models/pagination";
+import {JumpKey} from "../../_models/jumpbar/jump-key";
+import {MetadataService} from "../../_services/metadata.service";
+import {BrowseGenre} from "../../_models/metadata/browse/browse-genre";
+import {FilterField} from "../../_models/metadata/v2/filter-field";
+import {FilterComparison} from "../../_models/metadata/v2/filter-comparison";
+import {FilterUtilitiesService} from "../../shared/_services/filter-utilities.service";
+import {CompactNumberPipe} from "../../_pipes/compact-number.pipe";
@Component({
- selector: 'app-all-genres',
+ selector: 'app-browse-genres',
imports: [
CardDetailLayoutComponent,
DecimalPipe,
SideNavCompanionBarComponent,
- TranslocoDirective
+ TranslocoDirective,
+ CompactNumberPipe
],
templateUrl: './browse-genres.component.html',
styleUrl: './browse-genres.component.scss',
@@ -39,7 +33,6 @@ export class BrowseGenresComponent implements OnInit {
protected readonly FilterField = FilterField;
- private readonly destroyRef = inject(DestroyRef);
private readonly cdRef = inject(ChangeDetectorRef);
private readonly metadataService = inject(MetadataService);
private readonly jumpbarService = inject(JumpbarService);
diff --git a/UI/Web/src/app/browse-people/browse-authors.component.html b/UI/Web/src/app/browse/browse-people/browse-authors.component.html
similarity index 100%
rename from UI/Web/src/app/browse-people/browse-authors.component.html
rename to UI/Web/src/app/browse/browse-people/browse-authors.component.html
diff --git a/UI/Web/src/app/browse-people/browse-authors.component.scss b/UI/Web/src/app/browse/browse-people/browse-authors.component.scss
similarity index 100%
rename from UI/Web/src/app/browse-people/browse-authors.component.scss
rename to UI/Web/src/app/browse/browse-people/browse-authors.component.scss
diff --git a/UI/Web/src/app/browse-people/browse-authors.component.ts b/UI/Web/src/app/browse/browse-people/browse-authors.component.ts
similarity index 71%
rename from UI/Web/src/app/browse-people/browse-authors.component.ts
rename to UI/Web/src/app/browse/browse-people/browse-authors.component.ts
index dd80e4a67..91bd61b57 100644
--- a/UI/Web/src/app/browse-people/browse-authors.component.ts
+++ b/UI/Web/src/app/browse/browse-people/browse-authors.component.ts
@@ -9,20 +9,20 @@ import {
} from '@angular/core';
import {
SideNavCompanionBarComponent
-} from "../sidenav/_components/side-nav-companion-bar/side-nav-companion-bar.component";
-import {CardDetailLayoutComponent} from "../cards/card-detail-layout/card-detail-layout.component";
+} from "../../sidenav/_components/side-nav-companion-bar/side-nav-companion-bar.component";
+import {CardDetailLayoutComponent} from "../../cards/card-detail-layout/card-detail-layout.component";
import {DecimalPipe} from "@angular/common";
-import {Series} from "../_models/series";
-import {Pagination} from "../_models/pagination";
-import {JumpKey} from "../_models/jumpbar/jump-key";
+import {Series} from "../../_models/series";
+import {Pagination} from "../../_models/pagination";
+import {JumpKey} from "../../_models/jumpbar/jump-key";
import {Router} from "@angular/router";
-import {PersonService} from "../_services/person.service";
-import {BrowsePerson} from "../_models/person/browse-person";
-import {JumpbarService} from "../_services/jumpbar.service";
-import {PersonCardComponent} from "../cards/person-card/person-card.component";
-import {ImageService} from "../_services/image.service";
+import {PersonService} from "../../_services/person.service";
+import {BrowsePerson} from "../../_models/person/browse-person";
+import {JumpbarService} from "../../_services/jumpbar.service";
+import {PersonCardComponent} from "../../cards/person-card/person-card.component";
+import {ImageService} from "../../_services/image.service";
import {TranslocoDirective} from "@jsverse/transloco";
-import {CompactNumberPipe} from "../_pipes/compact-number.pipe";
+import {CompactNumberPipe} from "../../_pipes/compact-number.pipe";
@Component({
diff --git a/UI/Web/src/app/browse/browse-tags/browse-tags.component.html b/UI/Web/src/app/browse/browse-tags/browse-tags.component.html
new file mode 100644
index 000000000..a6b740c3d
--- /dev/null
+++ b/UI/Web/src/app/browse/browse-tags/browse-tags.component.html
@@ -0,0 +1,34 @@
+
+
+
+
+ {{t('title')}}
+
+ {{t('genre-count', {num: pagination.totalItems | number})}}
+
+
+
+
+
+
+
+
{{ item.title }}
+
+ {{t('series-count', {num: item.seriesCount | compactNumber})}}
+ {{t('issue-count', {num: item.issueCount | compactNumber})}}
+
+
+
+
+
+
+
+
diff --git a/UI/Web/src/app/browse/browse-tags/browse-tags.component.scss b/UI/Web/src/app/browse/browse-tags/browse-tags.component.scss
new file mode 100644
index 000000000..90c313b37
--- /dev/null
+++ b/UI/Web/src/app/browse/browse-tags/browse-tags.component.scss
@@ -0,0 +1 @@
+@use '../../../tag-card-common';
diff --git a/UI/Web/src/app/browse/browse-tags/browse-tags.component.ts b/UI/Web/src/app/browse/browse-tags/browse-tags.component.ts
new file mode 100644
index 000000000..58a246bfa
--- /dev/null
+++ b/UI/Web/src/app/browse/browse-tags/browse-tags.component.ts
@@ -0,0 +1,63 @@
+import {ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, inject, OnInit} from '@angular/core';
+import {CardDetailLayoutComponent} from "../../cards/card-detail-layout/card-detail-layout.component";
+import {DecimalPipe} from "@angular/common";
+import {
+ SideNavCompanionBarComponent
+} from "../../sidenav/_components/side-nav-companion-bar/side-nav-companion-bar.component";
+import {TranslocoDirective} from "@jsverse/transloco";
+import {MetadataService} from "../../_services/metadata.service";
+import {JumpbarService} from "../../_services/jumpbar.service";
+import {FilterUtilitiesService} from "../../shared/_services/filter-utilities.service";
+import {BrowseGenre} from "../../_models/metadata/browse/browse-genre";
+import {Pagination} from "../../_models/pagination";
+import {JumpKey} from "../../_models/jumpbar/jump-key";
+import {BrowsePerson} from "../../_models/person/browse-person";
+import {FilterField} from "../../_models/metadata/v2/filter-field";
+import {FilterComparison} from "../../_models/metadata/v2/filter-comparison";
+import {BrowseTag} from "../../_models/metadata/browse/browse-tag";
+import {CompactNumberPipe} from "../../_pipes/compact-number.pipe";
+
+@Component({
+ selector: 'app-browse-tags',
+ imports: [
+ CardDetailLayoutComponent,
+ DecimalPipe,
+ SideNavCompanionBarComponent,
+ TranslocoDirective,
+ CompactNumberPipe
+ ],
+ templateUrl: './browse-tags.component.html',
+ styleUrl: './browse-tags.component.scss',
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class BrowseTagsComponent implements OnInit {
+ protected readonly FilterField = FilterField;
+
+ private readonly cdRef = inject(ChangeDetectorRef);
+ private readonly metadataService = inject(MetadataService);
+ private readonly jumpbarService = inject(JumpbarService);
+ protected readonly filterUtilityService = inject(FilterUtilitiesService);
+
+ isLoading = false;
+ tags: Array
= [];
+ pagination: Pagination = {currentPage: 0, totalPages: 0, totalItems: 0, itemsPerPage: 0};
+ refresh: EventEmitter = new EventEmitter();
+ jumpKeys: Array = [];
+ trackByIdentity = (index: number, item: BrowsePerson) => `${item.id}`;
+
+ ngOnInit() {
+ this.isLoading = true;
+ this.cdRef.markForCheck();
+ this.metadataService.getTagWithCounts(undefined, undefined).subscribe(d => {
+ this.tags = d.result;
+ this.pagination = d.pagination;
+ this.jumpKeys = this.jumpbarService.getJumpKeys(this.tags, (d: BrowseGenre) => d.title);
+ this.isLoading = false;
+ this.cdRef.markForCheck();
+ });
+ }
+
+ openFilter(field: FilterField, value: string | number) {
+ this.filterUtilityService.applyFilter(['all-series'], field, FilterComparison.Equal, `${value}`).subscribe();
+ }
+}
diff --git a/UI/Web/src/assets/langs/en.json b/UI/Web/src/assets/langs/en.json
index ed4f38dbb..483c864cf 100644
--- a/UI/Web/src/assets/langs/en.json
+++ b/UI/Web/src/assets/langs/en.json
@@ -1118,6 +1118,13 @@
"series-count": "{{common.series-count}}"
},
+ "browse-tags": {
+ "title": "Browse Tags",
+ "genre-count": "{{num}} Tags",
+ "issue-count": "{{common.issue-count}}",
+ "series-count": "{{common.series-count}}"
+ },
+
"person-detail": {
"aka-title": "Also known as ",
"known-for-title": "Known For",