import { isEmpty } from 'lodash' ; import React from 'react' ; import { from as observableFrom , Subject } from 'rxjs' ; import { takeUntil } from 'rxjs/operators' ; import type { Application , IFunction , IOverridableProps } from '@spinnaker/core' ; import { AccountTag , CollapsibleSection , Details , Overrides } from '@spinnaker/core' ; import { FunctionActions } from './FunctionActions' ; import type { IAmazonFunction , IAmazonFunctionSourceData } from '../../domain' ; import { AwsReactInjector } from '../../reactShims' ; export interface IFunctionFromStateParams { account : string ; region : string ; functionName : string ; } export interface IAmazonFunctionDetailsProps extends IOverridableProps { app : Application ; functionObj : IFunction ; } @ Overrides ( 'function.details' , 'aws' ) export class AmazonFunctionDetails extends React . Component < IAmazonFunctionDetailsProps , any > { private destroy$ = new Subject ( ) ; constructor ( props ) { super ( props ) ; this . state = { loading : true , } ; } public extractFunction ( ) { const { app , functionObj : functionFromProps } = this . props ; const functionDef = app . functions . data . find ( ( test ) => { return ( test . functionName === functionFromProps . functionName && test . region === functionFromProps . region && test . account === functionFromProps . account ) ; } ) ; if ( functionDef ) { observableFrom ( AwsReactInjector . functionReader . getFunctionDetails ( 'aws' , functionFromProps . account , functionFromProps . region , functionFromProps . functionName ) ) . pipe ( takeUntil ( this . destroy$ ) ) . subscribe ( ( details ) => { if ( details . length ) { this . setState ( { functionDef : details [ 0 ] as IAmazonFunction , loading : false , } ) ; } } ) ; } else { this . setState ( { functionDef : { } , loading : false , } ) ; } } public componentDidMount ( ) { const { app } = this . props ; const dataSource = app . functions ; observableFrom ( dataSource . ready ( ) ) . pipe ( takeUntil ( this . destroy$ ) ) . subscribe ( ( ) => { const dataSourceUnsubscribe = dataSource . onRefresh ( null , ( ) => this . extractFunction ( ) ) ; this . setState ( { dataSourceUnsubscribe } ) ; this . extractFunction ( ) ; } ) ; } public componentWillUnmount ( ) { this . state . dataSourceUnsubscribe && this . state . dataSourceUnsubscribe ( ) ; this . destroy$ . next ( ) ; } public render ( ) { const { app } = this . props ; const { loading , functionDef } = this . state ; if ( loading ) { return < Details loading = { loading } />; } const functionDetails = ( < dl className = "horizontal-when-filters-collapsed dl-horizontal dl-narrow" > < dt > Last Modified < /dt> < dd > { functionDef . lastModified } < /dd> < dt > In < /dt> < dd > < AccountTag account = { functionDef . account } /> {functionDef.region} < /dd> < dt > VPC < /dt> < dd > { functionDef . vpcConfig ? functionDef . vpcConfig . vpcId : 'Default' } < /dd> < dt > Function ARN < /dt> < dd > { functionDef . functionArn } < /dd> < dt > Revision ID < /dt> < dd > { functionDef . revisionId } < /dd> < dt > Version < /dt> < dd > { functionDef . version } < /dd> < /dl>); const eventSourceDetails = ( < dl className = "horizontal-when-filters-collapsed dl-horizontal dl-narrow" > { functionDef . eventSourceMappings && functionDef . eventSourceMappings . length !== 0 ? functionDef . eventSourceMappings . map ( ( value ) => ( < > < h5 > < strong > Event Source < /strong> < /h5> < dl > < dt > ARN < /dt> < dd > { value . eventSourceArn } < /dd> < dt > State < /dt> < dd > { value . state } < /dd> < /dl> < />)) : 'None' } < /dl>); const aliasConfigurationDetails = ( < dl className = "horizontal-when-filters-collapsed dl-horizontal dl-narrow" > { functionDef . aliasConfigurations && functionDef . aliasConfigurations . length !== 0 ? functionDef . aliasConfigurations . map ( ( value ) => ( < > < h5 > < strong > Alias Details < /strong> < /h5> < dl > < dt > Name < /dt> < dd > { value . name } < /dd> < dt > ARN < /dt> < dd > { value . aliasArn } < /dd> < /dl> < />)) : 'None' } < /dl>); const functionDetailsSection = ( < CollapsibleSection heading = "Function Details" > { functionDetails } < /CollapsibleSection>); const eventSourceDetailsSection = ( < CollapsibleSection heading = "Event Source Details" > { eventSourceDetails } < /CollapsibleSection>); const aliasConfigurationDetailsSection = ( < CollapsibleSection heading = "Alias Configuration Details" > { aliasConfigurationDetails } < /CollapsibleSection>); return ( < Details loading = { this . state . loading } > { isEmpty ( this . state . functionDef ) ? ( 'Function not found.' ) : ( < Details . Header icon = { < i className = "fa fa-xs fa-fw fa-asterisk" / > } name = { this . state . functionDef . functionName } > < div className = "actions" > < FunctionActions app = { app } functionDef = { functionDef } functionFromParams = { { account : this . state . functionDef . account , region : this . state . functionDef . region , functionName : this . state . functionDef . functionName , } } /> < /div> < /Details.Header>)} { ! isEmpty ( this . state . functionDef ) ? functionDetailsSection : '' } { ! isEmpty ( this . state . functionDef ) && ! isEmpty ( this . state . functionDef . eventSourceMappings ) ? eventSourceDetailsSection : '' } { ! isEmpty ( this . state . functionDef ) && ! isEmpty ( this . state . functionDef . aliasConfigurations ) ? aliasConfigurationDetailsSection : '' } < /Details>); } }