add breadcrumbs service
This commit is contained in:
parent
3fd9d12526
commit
0059344083
@ -3,12 +3,12 @@ import { AuthGuard } from './modules/auth/auth.guard';
|
||||
import { CompositeRouteGuard, CustomRouteReuseStrategy } from '@iqser/common-ui';
|
||||
import { RedRoleGuard } from './modules/auth/red-role.guard';
|
||||
import { BaseScreenComponent } from '@components/base-screen/base-screen.component';
|
||||
import { RouteReuseStrategy, RouterModule } from '@angular/router';
|
||||
import { RouteReuseStrategy, RouterModule, Routes } from '@angular/router';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { DownloadsListScreenComponent } from '@components/downloads-list-screen/downloads-list-screen.component';
|
||||
import { AppStateGuard } from '@state/app-state.guard';
|
||||
|
||||
const routes = [
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
redirectTo: 'main/dossiers',
|
||||
|
||||
@ -35,6 +35,7 @@ import * as links from '../assets/help-mode/links.json';
|
||||
import { HELP_DOCS, IqserHelpModeModule, MAX_RETRIES_ON_SERVER_ERROR, ServerErrorInterceptor, ToastComponent } from '@iqser/common-ui';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
import { GeneralSettingsService } from '@services/general-settings.service';
|
||||
import { BreadcrumbsComponent } from './components/breadcrumbs/breadcrumbs.component';
|
||||
|
||||
export function httpLoaderFactory(httpClient: HttpClient): PruningTranslationLoader {
|
||||
return new PruningTranslationLoader(httpClient, '/assets/i18n/', '.json');
|
||||
@ -55,7 +56,7 @@ const screens = [BaseScreenComponent, DownloadsListScreenComponent];
|
||||
const components = [AppComponent, AuthErrorComponent, NotificationsComponent, SpotlightSearchComponent, ...screens];
|
||||
|
||||
@NgModule({
|
||||
declarations: [...components],
|
||||
declarations: [...components, BreadcrumbsComponent],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
BrowserAnimationsModule,
|
||||
|
||||
@ -4,41 +4,7 @@
|
||||
<div *ngIf="!currentUser.isUser" class="menu-placeholder"></div>
|
||||
|
||||
<div *ngIf="currentUser.isUser" class="menu flex-2 visible-lg breadcrumbs-container">
|
||||
<a *ngIf="(isDossiersView$ | async) === false" class="breadcrumb back" redactionNavigateLastDossiersScreen>
|
||||
<mat-icon svgIcon="iqser:expand"></mat-icon>
|
||||
{{ 'top-bar.navigation-items.back' | translate }}
|
||||
</a>
|
||||
|
||||
<ng-container *ngIf="isDossiersView$ | async">
|
||||
<a
|
||||
[routerLinkActiveOptions]="{ exact: true }"
|
||||
class="breadcrumb"
|
||||
routerLink="/main/dossiers"
|
||||
routerLinkActive="active"
|
||||
translate="top-bar.navigation-items.dossiers"
|
||||
></a>
|
||||
|
||||
<!-- <ng-container *ngIf="activeDossier$ | async as dossier">-->
|
||||
<!-- <mat-icon svgIcon="iqser:arrow-right"></mat-icon>-->
|
||||
|
||||
<!-- <a-->
|
||||
<!-- [routerLinkActiveOptions]="{ exact: true }"-->
|
||||
<!-- [routerLink]="dossier.routerLink"-->
|
||||
<!-- class="breadcrumb"-->
|
||||
<!-- routerLinkActive="active"-->
|
||||
<!-- >-->
|
||||
<!-- {{ dossier.dossierName }}-->
|
||||
<!-- </a>-->
|
||||
<!-- </ng-container>-->
|
||||
|
||||
<!-- <ng-container *ngIf="appStateService.activeFile as activeFile">-->
|
||||
<!-- <mat-icon svgIcon="iqser:arrow-right"></mat-icon>-->
|
||||
|
||||
<!-- <a [routerLink]="activeFile.routerLink" class="breadcrumb" routerLinkActive="active">-->
|
||||
<!-- {{ activeFile.filename }}-->
|
||||
<!-- </a>-->
|
||||
<!-- </ng-container>-->
|
||||
</ng-container>
|
||||
<redaction-breadcrumbs></redaction-breadcrumbs>
|
||||
</div>
|
||||
|
||||
<div class="center">
|
||||
|
||||
@ -11,6 +11,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { filter, map, startWith } from 'rxjs/operators';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { shareDistinctLast } from '@iqser/common-ui';
|
||||
import { BreadcrumbsService } from '@services/breadcrumbs.service';
|
||||
|
||||
interface MenuItem {
|
||||
readonly name: string;
|
||||
@ -21,7 +22,6 @@ interface MenuItem {
|
||||
}
|
||||
|
||||
const isNavigationStart = event => event instanceof NavigationStart;
|
||||
const isDossiersView = url => url.includes('/main/dossiers') && !url.includes('/search');
|
||||
const isSearchScreen = url => url.includes('/main/dossiers') && url.includes('/search');
|
||||
|
||||
@Component({
|
||||
@ -62,8 +62,8 @@ export class BaseScreenComponent {
|
||||
{
|
||||
text: this._translateService.instant('search.this-dossier'),
|
||||
icon: 'red:enter',
|
||||
hide: (): boolean => true, // TODO
|
||||
action: (query): void => this._search(query, 'todo'), // TODO
|
||||
hide: (): boolean => this._hideSearchThisDossier,
|
||||
action: (query): void => this._searchThisDossier(query),
|
||||
},
|
||||
{
|
||||
text: this._translateService.instant('search.entire-platform'),
|
||||
@ -77,7 +77,6 @@ export class BaseScreenComponent {
|
||||
startWith(this._router.url),
|
||||
shareDistinctLast(),
|
||||
);
|
||||
readonly isDossiersView$ = this._navigationStart$.pipe(map(isDossiersView));
|
||||
readonly isSearchScreen$ = this._navigationStart$.pipe(map(isSearchScreen));
|
||||
|
||||
constructor(
|
||||
@ -89,8 +88,19 @@ export class BaseScreenComponent {
|
||||
readonly fileDownloadService: FileDownloadService,
|
||||
private readonly _router: Router,
|
||||
private readonly _translateService: TranslateService,
|
||||
readonly breadcrumbsService: BreadcrumbsService,
|
||||
) {}
|
||||
|
||||
private get _hideSearchThisDossier() {
|
||||
const routerLink = this.breadcrumbsService.breadcrumbs[1]?.routerLink;
|
||||
if (!routerLink) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const isDossierOverview = routerLink.includes('dossiers') && routerLink.length === 3;
|
||||
return !isDossierOverview;
|
||||
}
|
||||
|
||||
trackByName(index: number, item: MenuItem) {
|
||||
return item.name;
|
||||
}
|
||||
@ -99,4 +109,13 @@ export class BaseScreenComponent {
|
||||
const queryParams = { query, dossierId };
|
||||
this._router.navigate(['main/dossiers/search'], { queryParams }).then();
|
||||
}
|
||||
|
||||
private _searchThisDossier(query: string) {
|
||||
const routerLink = this.breadcrumbsService.breadcrumbs[1]?.routerLink;
|
||||
if (!routerLink) {
|
||||
return this._search(query);
|
||||
}
|
||||
const dossierId = routerLink[2];
|
||||
return this._search(query, dossierId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
<ng-container *ngIf="breadcrumbsService.breadcrumbs$ | async as breadcrumbs">
|
||||
<a
|
||||
*ngIf="breadcrumbs.length === 0 || (breadcrumbsService.showGoBack$ | async) === true; else items"
|
||||
class="breadcrumb back"
|
||||
redactionNavigateLastDossiersScreen
|
||||
>
|
||||
<mat-icon svgIcon="iqser:expand"></mat-icon>
|
||||
{{ 'top-bar.navigation-items.back' | translate }}
|
||||
</a>
|
||||
|
||||
<ng-template #items>
|
||||
<ng-container *ngFor="let breadcrumb of breadcrumbs; first as first">
|
||||
<mat-icon *ngIf="!first" svgIcon="iqser:arrow-right"></mat-icon>
|
||||
|
||||
<a
|
||||
[routerLinkActiveOptions]="breadcrumb.routerLinkActiveOptions ?? { exact: false }"
|
||||
[routerLink]="breadcrumb.routerLink"
|
||||
class="breadcrumb"
|
||||
routerLinkActive="active"
|
||||
>
|
||||
{{ breadcrumb.name$ | async }}
|
||||
</a>
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
@ -0,0 +1,10 @@
|
||||
:host {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
|
||||
> *:not(:last-child) {
|
||||
margin-right: 6px;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { BreadcrumbsService } from '@services/breadcrumbs.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-breadcrumbs',
|
||||
templateUrl: './breadcrumbs.component.html',
|
||||
styleUrls: ['./breadcrumbs.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class BreadcrumbsComponent {
|
||||
constructor(readonly breadcrumbsService: BreadcrumbsService) {}
|
||||
}
|
||||
18
apps/red-ui/src/app/guards/go-back-guard.service.ts
Normal file
18
apps/red-ui/src/app/guards/go-back-guard.service.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CanActivate, CanDeactivate } from '@angular/router';
|
||||
import { BreadcrumbsService } from '@services/breadcrumbs.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class GoBackGuard implements CanActivate, CanDeactivate<unknown> {
|
||||
constructor(private readonly _breadcrumbsService: BreadcrumbsService) {}
|
||||
|
||||
canActivate(): boolean {
|
||||
this._breadcrumbsService.showGoBack();
|
||||
return true;
|
||||
}
|
||||
|
||||
canDeactivate() {
|
||||
this._breadcrumbsService.hideGoBack();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1,24 +1,29 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { CompositeRouteGuard } from '@iqser/common-ui';
|
||||
import { SearchScreenComponent } from './screens/search-screen/search-screen.component';
|
||||
import { FilePreviewScreenComponent } from './screens/file-preview-screen/file-preview-screen.component';
|
||||
import { FilesGuard } from './utils/file.guard';
|
||||
import { FilesGuard } from './guards/file.guard';
|
||||
import { DossiersGuard } from './guards/dossiers.guard';
|
||||
import { GoBackGuard } from '@guards/go-back-guard.service';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: 'search',
|
||||
component: SearchScreenComponent,
|
||||
canActivate: [GoBackGuard],
|
||||
canDeactivate: [GoBackGuard],
|
||||
},
|
||||
{
|
||||
path: ':dossierId',
|
||||
canActivate: [CompositeRouteGuard],
|
||||
canActivate: [DossiersGuard],
|
||||
canDeactivate: [DossiersGuard],
|
||||
loadChildren: () => import('./screens/dossier-overview/dossier-overview.module').then(m => m.DossierOverviewModule),
|
||||
},
|
||||
{
|
||||
path: ':dossierId/file/:fileId',
|
||||
component: FilePreviewScreenComponent,
|
||||
canActivate: [FilesGuard],
|
||||
canActivate: [DossiersGuard, FilesGuard],
|
||||
canDeactivate: [FilesGuard],
|
||||
data: {
|
||||
reuse: true,
|
||||
},
|
||||
@ -27,6 +32,8 @@ const routes: Routes = [
|
||||
path: '',
|
||||
pathMatch: 'full',
|
||||
loadChildren: () => import('./screens/dossiers-listing/dossiers-listing.module').then(m => m.DossiersListingModule),
|
||||
canActivate: [DossiersGuard],
|
||||
canDeactivate: [DossiersGuard],
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@ -40,7 +40,11 @@ import { OverlayModule } from '@angular/cdk/overlay';
|
||||
import { SharedDossiersModule } from './shared/shared-dossiers.module';
|
||||
import { PlatformSearchService } from './shared/services/platform-search.service';
|
||||
import { ResizeAnnotationDialogComponent } from './dialogs/resize-annotation-dialog/resize-annotation-dialog.component';
|
||||
import { FilesGuard } from './utils/file.guard';
|
||||
import { BreadcrumbsService } from '@services/breadcrumbs.service';
|
||||
import { of } from 'rxjs';
|
||||
import { FilesGuard } from './guards/file.guard';
|
||||
import { DossiersGuard } from './guards/dossiers.guard';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
const screens = [FilePreviewScreenComponent, SearchScreenComponent];
|
||||
|
||||
@ -91,7 +95,15 @@ const services = [
|
||||
|
||||
@NgModule({
|
||||
declarations: [...components],
|
||||
providers: [...services, FilesGuard],
|
||||
providers: [...services, FilesGuard, DossiersGuard],
|
||||
imports: [CommonModule, SharedModule, SharedDossiersModule, FileUploadDownloadModule, DossiersRoutingModule, OverlayModule],
|
||||
})
|
||||
export class DossiersModule {}
|
||||
export class DossiersModule {
|
||||
constructor(breadcrumbsService: BreadcrumbsService, translateService: TranslateService) {
|
||||
breadcrumbsService.append({
|
||||
name$: of(translateService.instant('top-bar.navigation-items.dossiers')),
|
||||
routerLink: ['/main', 'dossiers'],
|
||||
routerLinkActiveOptions: { exact: true },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
61
apps/red-ui/src/app/modules/dossier/guards/dossiers.guard.ts
Normal file
61
apps/red-ui/src/app/modules/dossier/guards/dossiers.guard.ts
Normal file
@ -0,0 +1,61 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivate, CanDeactivate, Router, RouterStateSnapshot } from '@angular/router';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { BreadcrumbsService } from '@services/breadcrumbs.service';
|
||||
import { pluck } from 'rxjs/operators';
|
||||
import { LoadingService } from '@iqser/common-ui';
|
||||
|
||||
@Injectable()
|
||||
export class DossiersGuard implements CanActivate, CanDeactivate<unknown> {
|
||||
constructor(
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _breadcrumbsService: BreadcrumbsService,
|
||||
private readonly _router: Router,
|
||||
) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
|
||||
if (state.url === '/main/dossiers') {
|
||||
this._breadcrumbsService.hideGoBack();
|
||||
return true;
|
||||
}
|
||||
|
||||
const dossierId = route.paramMap.get('dossierId');
|
||||
|
||||
if (!this._dossiersService.find(dossierId)) {
|
||||
this._loadingService.start();
|
||||
await this._appStateService.loadAllDossiers();
|
||||
this._loadingService.stop();
|
||||
|
||||
if (!this._dossiersService.find(dossierId)) {
|
||||
await this._router.navigate(['/main', 'dossiers']);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
this._breadcrumbsService.append({
|
||||
name$: this._dossiersService.getEntityChanged$(dossierId).pipe(pluck('dossierName')),
|
||||
routerLink: ['/main', 'dossiers', dossierId],
|
||||
routerLinkActiveOptions: { exact: true },
|
||||
});
|
||||
|
||||
this._breadcrumbsService.hideGoBack();
|
||||
return true;
|
||||
}
|
||||
|
||||
canDeactivate(
|
||||
component: unknown,
|
||||
currentRoute: ActivatedRouteSnapshot,
|
||||
currentState: RouterStateSnapshot,
|
||||
nextState?: RouterStateSnapshot,
|
||||
) {
|
||||
const dossierId = currentRoute.paramMap.get('dossierId');
|
||||
this._breadcrumbsService.remove(['/main', 'dossiers', dossierId]);
|
||||
if (!nextState.url.startsWith('/main/dossiers')) {
|
||||
this._breadcrumbsService.showGoBack();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
65
apps/red-ui/src/app/modules/dossier/guards/file.guard.ts
Normal file
65
apps/red-ui/src/app/modules/dossier/guards/file.guard.ts
Normal file
@ -0,0 +1,65 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivate, CanDeactivate, Router, RouterStateSnapshot } from '@angular/router';
|
||||
import { FilesMapService } from '@services/entity-services/files-map.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { BreadcrumbsService } from '@services/breadcrumbs.service';
|
||||
import { pluck } from 'rxjs/operators';
|
||||
import { LoadingService } from '@iqser/common-ui';
|
||||
|
||||
@Injectable()
|
||||
export class FilesGuard implements CanActivate, CanDeactivate<unknown> {
|
||||
constructor(
|
||||
private readonly _filesMapService: FilesMapService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _breadcrumbsService: BreadcrumbsService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _router: Router,
|
||||
) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot): Promise<boolean> {
|
||||
const dossierId = route.paramMap.get('dossierId');
|
||||
const fileId = route.paramMap.get('fileId');
|
||||
|
||||
if (!this._filesMapService.get(dossierId, fileId)) {
|
||||
this._loadingService.start();
|
||||
const dossier = this._dossiersService.find(dossierId);
|
||||
await this._appStateService.getFiles(dossier);
|
||||
this._loadingService.stop();
|
||||
|
||||
if (!this._filesMapService.get(dossierId, fileId)) {
|
||||
await this._router.navigate([dossier.routerLink]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
this._breadcrumbsService.append({
|
||||
name$: this._filesMapService.watch$(dossierId, fileId).pipe(pluck('filename')),
|
||||
routerLink: ['/main', 'dossiers', dossierId, 'file', fileId],
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
canDeactivate(
|
||||
component: unknown,
|
||||
currentRoute: ActivatedRouteSnapshot,
|
||||
currentState: RouterStateSnapshot,
|
||||
nextState?: RouterStateSnapshot,
|
||||
) {
|
||||
const dossierId = currentRoute.paramMap.get('dossierId');
|
||||
const fileId = currentRoute.paramMap.get('fileId');
|
||||
this._breadcrumbsService.remove(['/main', 'dossiers', dossierId, 'file', fileId]);
|
||||
|
||||
if (!nextState.root.paramMap.get('dossierId')) {
|
||||
this._breadcrumbsService.remove(['/main', 'dossiers', dossierId]);
|
||||
}
|
||||
|
||||
if (!nextState.url.startsWith('/main/dossiers')) {
|
||||
this._breadcrumbsService.showGoBack();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -122,11 +122,12 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
private readonly _userPreferenceService: UserPreferenceService,
|
||||
) {
|
||||
super();
|
||||
this._loadingService.start();
|
||||
_loadingService.start();
|
||||
this.dossierId = _activatedRoute.snapshot.paramMap.get('dossierId');
|
||||
this.dossier$ = this._dossiersService.getEntityChanged$(this.dossierId);
|
||||
this.dossier$ = _dossiersService.getEntityChanged$(this.dossierId);
|
||||
this.fileId = _activatedRoute.snapshot.paramMap.get('fileId');
|
||||
this.file$ = _filesMapService.watch$(this.dossierId, this.fileId);
|
||||
|
||||
document.documentElement.addEventListener('fullscreenchange', () => {
|
||||
if (!document.fullscreenElement) {
|
||||
this.fullScreen = false;
|
||||
@ -259,10 +260,9 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
}
|
||||
|
||||
async ngOnInit(): Promise<void> {
|
||||
this._loadingService.start();
|
||||
await this._userPreferenceService.saveLastOpenedFileForDossier(this.dossierId, this.fileId);
|
||||
|
||||
await this._loadFileData();
|
||||
this.displayPDFViewer = true;
|
||||
this._updateCanPerformActions();
|
||||
this._subscribeToFileUpdates();
|
||||
|
||||
@ -270,6 +270,9 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
if (file?.analysisRequired) {
|
||||
this.fileActions.reanalyseFile();
|
||||
}
|
||||
|
||||
this._loadingService.stop();
|
||||
this.displayPDFViewer = true;
|
||||
}
|
||||
|
||||
rebuildFilters(deletePreviousAnnotations = false): void {
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivate, Router } from '@angular/router';
|
||||
import { FilesMapService } from '@services/entity-services/files-map.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
|
||||
@Injectable()
|
||||
export class FilesGuard implements CanActivate {
|
||||
constructor(
|
||||
private readonly _filesMapService: FilesMapService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _router: Router,
|
||||
) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot): Promise<boolean> {
|
||||
const dossierId = route.paramMap.get('dossierId');
|
||||
const fileId = route.paramMap.get('fileId');
|
||||
|
||||
if (!this._filesMapService.get(dossierId, fileId)) {
|
||||
const dossier = this._dossiersService.find(dossierId);
|
||||
await this._appStateService.getFiles(dossier);
|
||||
|
||||
if (!this._filesMapService.get(dossierId, fileId)) {
|
||||
await this._router.navigate([dossier.routerLink]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
57
apps/red-ui/src/app/services/breadcrumbs.service.ts
Normal file
57
apps/red-ui/src/app/services/breadcrumbs.service.ts
Normal file
@ -0,0 +1,57 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { List, shareDistinctLast } from '@iqser/common-ui';
|
||||
import { IsActiveMatchOptions } from '@angular/router';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
|
||||
export type RouterLinkActiveOptions = { exact: boolean } | IsActiveMatchOptions;
|
||||
|
||||
export interface Breadcrumb {
|
||||
readonly name$: Observable<string>;
|
||||
readonly routerLink?: string[];
|
||||
readonly routerLinkActiveOptions?: RouterLinkActiveOptions;
|
||||
}
|
||||
|
||||
export type Breadcrumbs = List<Breadcrumb>;
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class BreadcrumbsService {
|
||||
readonly breadcrumbs$: Observable<Breadcrumbs>;
|
||||
readonly showGoBack$: Observable<boolean>;
|
||||
private readonly _showGoBack$ = new BehaviorSubject<boolean>(false);
|
||||
private readonly _store$ = new BehaviorSubject<Breadcrumbs>([]);
|
||||
|
||||
constructor() {
|
||||
this.breadcrumbs$ = this._store$.asObservable();
|
||||
this.showGoBack$ = this._showGoBack$.asObservable().pipe(shareDistinctLast());
|
||||
}
|
||||
|
||||
get breadcrumbs() {
|
||||
return this._store$.value;
|
||||
}
|
||||
|
||||
append(breadcrumb: Breadcrumb) {
|
||||
const existing = this._store$.value.find(item => item.routerLink.toString() === breadcrumb.routerLink.toString());
|
||||
if (existing) {
|
||||
this.remove(existing.routerLink);
|
||||
}
|
||||
this._store$.next([...this._store$.value, breadcrumb]);
|
||||
}
|
||||
|
||||
clear() {
|
||||
this._store$.next([]);
|
||||
}
|
||||
|
||||
remove(routerLink: string[]) {
|
||||
this._store$.next(this._store$.value.filter(item => item.routerLink.toString() !== routerLink.toString()));
|
||||
}
|
||||
|
||||
showGoBack() {
|
||||
this._showGoBack$.next(true);
|
||||
}
|
||||
|
||||
hideGoBack() {
|
||||
this._showGoBack$.next(false);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user