import { sortBy } from 'lodash' ; import { BehaviorSubject , combineLatest , Observable , ReplaySubject } from 'rxjs' ; import { map , takeUntil } from 'rxjs/operators' ; import { InternalApplicationStart } from '../../application' ; import { HttpStart } from '../../http' ; import { ChromeNavLink , ChromeNavLinkUpdateableFields , NavLinkWrapper } from './nav_link' ; import { toNavLink } from './to_nav_link' ; interface StartDeps { application : InternalApplicationStart ; http : HttpStart ; } /**
 *  ChromeNavLinks for manipulating nav links.
 *
 *  public export interface ChromeNavLinks { /**
     * Get an observable for a sorted list of navlinks.
     */ getNavLinks$ ( ) : Observable < Array < Readonly < ChromeNavLink > > > ; param id get ( id ) : ChromeNavLink | undefined ; /**
     * Get the current state of all navlinks.
     */ getAll ( ) : Array < Readonly < ChromeNavLink > > ; param id has ( id ) : boolean ; remarks param id showOnly ( id ) : void ; deprecated Uses the  AppBase . updater$ property when registering
     * your application with  ApplicationSetup . register instead.
     *
     *  param id param values update ( id , values ) : ChromeNavLink | undefined ; remarks enableForcedAppSwitcherNavigation ( ) : void ; /**
     * An observable of the forced app switcher state.
     */ getForceAppSwitcherNavigation$ ( ) : Observable < boolean > ; } type LinksUpdater = ( navLinks : Map < string , NavLinkWrapper > ) => Map < string , NavLinkWrapper > ; export class NavLinksService { private readonly stop$ = new ReplaySubject ( 1 ) ; public start ( { application , http } ) { const appLinks$ = application . applications$ . pipe ( map ( ( apps ) => { return new Map ( [ ... apps ] . filter ( ( [ , app ] ) => ! app . chromeless ) . map ( ( [ appId , app ] ) => [ appId , toNavLink ( app , http . basePath ) ] ) ) ; } ) ) ; const linkUpdaters$ = new BehaviorSubject < LinksUpdater [ ] > ( [ ] ) ; const navLinks$ = new BehaviorSubject < ReadonlyMap < string , NavLinkWrapper > > ( new Map ( ) ) ; combineLatest ( [ appLinks$ , linkUpdaters$ ] ) . pipe ( map ( ( [ appLinks , linkUpdaters ] ) => { return linkUpdaters . reduce ( ( links , updater ) => updater ( links ) , appLinks ) ; } ) ) . subscribe ( ( navlinks ) => { navLinks$ . next ( navlinks ) ; } ) ; const forceAppSwitcherNavigation$ = new BehaviorSubject ( false ) ; return { getNavLinks$ : ( ) => { return navLinks$ . pipe ( map ( sortNavLinks ) , takeUntil ( this . stop$ ) ) ; } , get ( id ) { const link = navLinks$ . value . get ( id ) ; return link && link . properties ; } , getAll ( ) { return sortNavLinks ( navLinks$ . value ) ; } , has ( id ) { return navLinks$ . value . has ( id ) ; } , showOnly ( id ) { if ( ! this . has ( id ) ) { return ; } const updater = ( navLinks ) => new Map ( [ ... navLinks . entries ( ) ] . filter ( ( [ linkId ] ) => linkId === id ) ) ; linkUpdaters$ . next ( [ ... linkUpdaters$ . value , updater ] ) ; } , update ( id , values ) { if ( ! this . has ( id ) ) { return ; } const updater = ( navLinks ) => new Map ( [ ... navLinks . entries ( ) ] . map ( ( [ linkId , link ] ) => { return [ linkId , link . id === id ? link . update ( values ) : link ] as [ string , NavLinkWrapper ] ; } ) ) ; linkUpdaters$ . next ( [ ... linkUpdaters$ . value , updater ] ) ; return this . get ( id ) ; } , enableForcedAppSwitcherNavigation ( ) { forceAppSwitcherNavigation$ . next ( true ) ; } , getForceAppSwitcherNavigation$ ( ) { return forceAppSwitcherNavigation$ . asObservable ( ) ; } , } ; } public stop ( ) { this . stop$ . next ( ) ; } } function sortNavLinks ( navLinks ) { return sortBy ( [ ... navLinks . values ( ) ] . map ( ( link ) => link . properties ) , 'order' ) ; }