import { ICompileProvider , IHttpProvider , IHttpService , ILocationProvider , IModule , IRootScopeService , } from 'angular' ; import $ from 'jquery' ; import { set } from '@elastic/safer-lodash-set' ; import { get } from 'lodash' ; import * as Rx from 'rxjs' ; import { ChromeBreadcrumb , EnvironmentMode , PackageInfo } from 'opensearch-dashboards/public' ; import { History } from 'history' ; import { CoreStart } from 'opensearch-dashboards/public' ; import { isSystemApiRequest } from '../utils' ; import { formatAngularHttpError , isAngularHttpError } from '../notify/lib' ; export interface RouteConfiguration { controller ? : string | ( ( ... args : any [ ] ) => void ) ; redirectTo ? : string ; resolveRedirectTo ? : ( ... args : any [ ] ) => void ; reloadOnSearch ? : boolean ; reloadOnUrl ? : boolean ; outerAngularWrapperRoute ? : boolean ; resolve ? : object ; template ? : string ; k7Breadcrumbs ? : ( ... args : any [ ] ) => ChromeBreadcrumb [ ] ; requireUICapability ? : string ; } param $route param isLocalAngular function isDummyRoute ( $route , isLocalAngular ) { return ( ( $route . current && $route . current . $$route && $route . current . $$route . outerAngularWrapperRoute ) || ( ! $route . current && isLocalAngular ) ) ; } export const configureAppAngularModule = ( angularModule , newPlatform , isLocalAngular , getHistory ? ) => { const core = 'core' in newPlatform ? newPlatform . core : newPlatform ; const packageInfo = newPlatform . env . packageInfo ; angularModule . value ( 'osdVersion' , packageInfo . version ) . value ( 'buildNum' , packageInfo . buildNum ) . value ( 'buildSha' , packageInfo . buildSha ) . value ( 'opensearchUrl' , getOpenSearchUrl ( core ) ) . value ( 'uiCapabilities' , core . application . capabilities ) . config ( setupCompileProvider ( newPlatform . env . mode . dev ) ) . config ( setupLocationProvider ( ) ) . config ( $setupXsrfRequestInterceptor ( packageInfo . version ) ) . run ( capture$httpLoadingCount ( core ) ) . run ( digestOnHashChange ( getHistory ) ) . run ( $setupBreadcrumbsAutoClear ( core , isLocalAngular ) ) . run ( $setupBadgeAutoClear ( core , isLocalAngular ) ) . run ( $setupHelpExtensionAutoClear ( core , isLocalAngular ) ) . run ( $setupUICapabilityRedirect ( core ) ) ; } ; const getOpenSearchUrl = ( newPlatform ) => { const a = document . createElement ( 'a' ) ; a . href = newPlatform . http . basePath . prepend ( '/opensearch' ) ; const protocolPort = /https/ . test ( a . protocol ) ? 443 : 80 ; const port = a . port || protocolPort ; return { host : a . hostname , port , protocol : a . protocol , pathname : a . pathname , } ; } ; const digestOnHashChange = ( getHistory ? ) => ( $rootScope ) => { if ( ! getHistory ) return ; const unlisten = getHistory ( ) . listen ( ( ) => { setTimeout ( ( ) => { window . dispatchEvent ( new HashChangeEvent ( 'hashchange' ) ) ; } , 0 ) ; } ) ; $rootScope . $on ( '$destroy' , unlisten ) ; } ; const setupCompileProvider = ( devMode ) => ( $compileProvider ) => { if ( ! devMode ) { $compileProvider . debugInfoEnabled ( false ) ; } } ; const setupLocationProvider = ( ) => ( $locationProvider ) => { $locationProvider . html5Mode ( { enabled : false , requireBase : false , rewriteLinks : false , } ) ; $locationProvider . hashPrefix ( '' ) ; } ; export const $setupXsrfRequestInterceptor = ( version ) => { $ . ajaxPrefilter ( ( { osdXsrfToken = true } , originalOptions , jqXHR ) => { if ( osdXsrfToken ) { jqXHR . setRequestHeader ( 'osd-version' , version ) ; } } ) ; return ( $httpProvider ) => { $httpProvider . interceptors . push ( ( ) => { return { request ( opts ) { const { osdXsrfToken = true } = opts as any ; if ( osdXsrfToken ) { set ( opts , [ 'headers' , 'osd-version' ] , version ) ; } return opts ; } , } ; } ) ; } ; } ; /**
 * Injected into angular module by ui/chrome angular integration
 * and adds a root-level watcher that will capture the count of
 * active $http requests on each digest loop and expose the count to
 * the core.loadingCount api
 */ const capture$httpLoadingCount = ( newPlatform ) => ( $rootScope , $http ) => { newPlatform . http . addLoadingCountSource ( new Rx . Observable ( ( observer ) => { const unwatch = $rootScope . $watch ( ( ) => { const reqs = $http . pendingRequests || [ ] ; observer . next ( reqs . filter ( ( req ) => ! isSystemApiRequest ( req ) ) . length ) ; } ) ; return unwatch ; } ) ) ; } ; /**
 * integrates with angular to automatically redirect to home if required
 * capability is not met
 */ const $setupUICapabilityRedirect = ( newPlatform ) => ( $rootScope , $injector ) => { const isOpenSearchDashboardsAppRoute = window . location . pathname . endsWith ( '/app/opensearch-dashboards' ) ; if ( ! isOpenSearchDashboardsAppRoute ) { return ; } $rootScope . $on ( '$routeChangeStart' , ( event , { $$route : route } = { } ) => { if ( ! route || ! route . requireUICapability ) { return ; } if ( ! get ( newPlatform . application . capabilities , route . requireUICapability ) ) { $injector . get ( '$location' ) . url ( '/home' ) ; event . preventDefault ( ) ; } } ) ; } ; /**
 * internal angular run function that will be called when angular bootstraps and
 * lets us integrate with the angular router so that we can automatically clear
 * the breadcrumbs if we switch to a OpenSearch Dashboards app that does not use breadcrumbs correctly
 */ const $setupBreadcrumbsAutoClear = ( newPlatform , isLocalAngular ) => ( $rootScope , $injector ) => { let breadcrumbSetSinceRouteChange = false ; const $route = $injector . has ( '$route' ) ? $injector . get ( '$route' ) : { } ; newPlatform . chrome . getBreadcrumbs$ ( ) . subscribe ( { next ( ) { breadcrumbSetSinceRouteChange = true ; } , } ) ; $rootScope . $on ( '$routeChangeStart' , ( ) => { breadcrumbSetSinceRouteChange = false ; } ) ; $rootScope . $on ( '$routeChangeSuccess' , ( ) => { if ( isDummyRoute ( $route , isLocalAngular ) ) { return ; } const current = $route . current || { } ; if ( breadcrumbSetSinceRouteChange || ( current . $$route && current . $$route . redirectTo ) ) { return ; } const k7BreadcrumbsProvider = current . k7Breadcrumbs ; if ( ! k7BreadcrumbsProvider ) { newPlatform . chrome . setBreadcrumbs ( [ ] ) ; return ; } try { newPlatform . chrome . setBreadcrumbs ( $injector . invoke ( k7BreadcrumbsProvider ) ) ; } catch ( error ) { if ( isAngularHttpError ( error ) ) { error = formatAngularHttpError ( error ) ; } newPlatform . fatalErrors . add ( error , 'location' ) ; } } ) ; } ; /**
 * internal angular run function that will be called when angular bootstraps and
 * lets us integrate with the angular router so that we can automatically clear
 * the badge if we switch to a OpenSearch Dashboards app that does not use the badge correctly
 */ const $setupBadgeAutoClear = ( newPlatform , isLocalAngular ) => ( $rootScope , $injector ) => { let badgeSetSinceRouteChange = false ; const $route = $injector . has ( '$route' ) ? $injector . get ( '$route' ) : { } ; $rootScope . $on ( '$routeChangeStart' , ( ) => { badgeSetSinceRouteChange = false ; } ) ; $rootScope . $on ( '$routeChangeSuccess' , ( ) => { if ( isDummyRoute ( $route , isLocalAngular ) ) { return ; } const current = $route . current || { } ; if ( badgeSetSinceRouteChange || ( current . $$route && current . $$route . redirectTo ) ) { return ; } const badgeProvider = current . badge ; if ( ! badgeProvider ) { newPlatform . chrome . setBadge ( undefined ) ; return ; } try { newPlatform . chrome . setBadge ( $injector . invoke ( badgeProvider ) ) ; } catch ( error ) { if ( isAngularHttpError ( error ) ) { error = formatAngularHttpError ( error ) ; } newPlatform . fatalErrors . add ( error , 'location' ) ; } } ) ; } ; /**
 * internal angular run function that will be called when angular bootstraps and
 * lets us integrate with the angular router so that we can automatically clear
 * the helpExtension if we switch to a OpenSearch Dashboards app that does not set its own
 * helpExtension
 */ const $setupHelpExtensionAutoClear = ( newPlatform , isLocalAngular ) => ( $rootScope , $injector ) => { /**
     * reset helpExtensionSetSinceRouteChange any time the helpExtension changes, even
     * if it was done directly through the new platform
     */ let helpExtensionSetSinceRouteChange = false ; newPlatform . chrome . getHelpExtension$ ( ) . subscribe ( { next ( ) { helpExtensionSetSinceRouteChange = true ; } , } ) ; const $route = $injector . has ( '$route' ) ? $injector . get ( '$route' ) : { } ; $rootScope . $on ( '$routeChangeStart' , ( ) => { if ( isDummyRoute ( $route , isLocalAngular ) ) { return ; } helpExtensionSetSinceRouteChange = false ; } ) ; $rootScope . $on ( '$routeChangeSuccess' , ( ) => { if ( isDummyRoute ( $route , isLocalAngular ) ) { return ; } const current = $route . current || { } ; if ( helpExtensionSetSinceRouteChange || ( current . $$route && current . $$route . redirectTo ) ) { return ; } newPlatform . chrome . setHelpExtension ( current . helpExtension ) ; } ) ; } ;