import React from 'react'; import FontFaceObserver from 'fontfaceobserver'; import FilterSidebar from './filter-sidebar.component'; import ConnectionMap from './map/connection-map.class'; import './scss/main.scss'; import cloneDeep from 'lodash/cloneDeep'; import { getAvailableFilters, getDataTree, IAvailableFilters } from './data'; import RootCompany from './root-company.component'; export type ExternalAction = (scoutId: string) => void; export interface ExternalActions { onNavigateToConnectionMap: ExternalAction; onNavigateToCompanyPage: ExternalAction; onViewCompany: ExternalAction; onViewLatestNews: ExternalAction; onAddToTargetList: ExternalAction; onBackAction?: () => void; } export interface IConnectionScoutCompanyData { [x: string]: any; scoutId: string; } export interface IConnectionCompanyData { entityId: string; parentEntityId: string; ultimateParentId: string; name: string; isScoutCompany: boolean; country: string; country_iso3: string; company?: IConnectionScoutCompanyData; subsidiaryCount?: number; directSubsidiaryCount?: number; parent?: IConnectionCompanyData; subsidiaries?: Array; active?: boolean; node?: any; link?: any; } interface IConnectionMapComponentProps extends ExternalActions { connectionsData: Array; requestId: string; } interface IConnectionMapComponentState { didError: boolean; processedConnectionsData?: IConnectionCompanyData; renderMap: boolean; availableFilters: IAvailableFilters; } export default class ConnectionMapComponent extends React.Component< IConnectionMapComponentProps, IConnectionMapComponentState > { node: SVGSVGElement; connectionMap: ConnectionMap; state = { didError: false, processedConnectionsData: null, renderMap: false, availableFilters: { countries: [] } }; componentDidMount() { const { connectionsData, requestId } = this.props; let processedConnectionsData; let availableFilters; try { const clonedData = cloneDeep(connectionsData); availableFilters = getAvailableFilters(connectionsData); processedConnectionsData = getDataTree(clonedData, requestId); this.setState( { processedConnectionsData, availableFilters, renderMap: true }, () => { this.connectionMap = new ConnectionMap(this.node); this.connectionMap.bindConnectionMapNavigationEventToNodes( this.props.onNavigateToConnectionMap ); this.connectionMap.bindCompanyPageNavigationEventToNodes( this.props.onNavigateToCompanyPage ); this.connectionMap.bindCompanyViewEventToNodes( this.props.onViewCompany ); this.connectionMap.bindLatestNewsViewEventToNodes( this.props.onViewLatestNews ); this.connectionMap.bindAddToTargetListNavigationEventToNodes( this.props.onAddToTargetList ); this.forceUpdate(); // ensure that filter bar picks up the connection map prop } ); try { const font = new FontFaceObserver('MetricWeb', { weight: 400 }); font.load().then( () => { this.connectionMap.render(processedConnectionsData); }, () => { console.log('Font is not available'); this.connectionMap.render(processedConnectionsData); } ); } catch (error) { if (console && console.error) console.error('Error in connection map rendering'); this.componentDidCatch(error); } } catch (err) { if (console && console.error) console.error( 'Error in connection map data processing', err, processedConnectionsData ); this.componentDidCatch(err); } } componentDidCatch(error: Error) { this.setState(oldState => ({ didError: true })); if (console && console.error) console.error(error); } componentDidUpdate() { if (this.connectionMap) this.connectionMap.updateNode(this.node); } render() { const { processedConnectionsData } = this.state; if (this.state.didError) { return (
Oops, the connection map can't be displayed as an error occurred, please try again later.
); } return (
{processedConnectionsData ? (() => { const output = []; let company = processedConnectionsData; while (company.parent) { output.push( ); company = company.parent; } return output.length ? (
{output}
) : null; })() : null}
{this.state.renderMap ? (
(this.node = node)} />
) : null}
); } }