import React from 'react'; import { connect } from 'react-redux'; import { InfoModal, Body, css, spacing } from '@mongodb-js/compass-components'; import { ServerType, TopologyType } from 'mongodb-instance-model'; import type { ConnectionInfo as ConnectionStorageConnectionInfo } from '@mongodb-js/connection-storage/renderer'; import type { RootState } from '../modules'; import type { Database } from '../modules/databases'; type ConnectionInfo = { term: string; description: React.ReactChild; }; const infoContainer = css({ margin: `${spacing[3]}px 0`, }); function InfoTerm({ children }: { children: React.ReactChild }) { return {children}; } function InfoDescription({ children }: { children: React.ReactChild }) { return {children}; } function Info({ term, children, }: { term: React.ReactChild; children: React.ReactChild; }) { return (
{term}
{children}
); } export function ConnectionInfoModal({ isVisible, close, infos, }: { isVisible: boolean; close: () => void; infos: ConnectionInfo[]; }) { return (
{infos.map((info, i) => ( {info.description} ))}
); } function getVersionDistro({ isEnterprise, isAtlas, isLocalAtlas, }: { isEnterprise?: boolean; isAtlas?: boolean; isLocalAtlas?: boolean; }): string { if (isAtlas) { return 'Atlas'; } if (isLocalAtlas) { return 'AtlasLocalDev'; } // it is unknown until instance details are loaded if (typeof isEnterprise === 'undefined') { return ''; } return isEnterprise ? 'Enterprise' : 'Community'; } type InfoParameters = Pick & { databases: Database[]; connectionInfo: Partial; }; function getStatsInfo({ instance, databases }: InfoParameters): ConnectionInfo { const isReady = instance?.refreshingStatus === 'ready'; const numDbs = isReady ? databases.length : '-'; const numCollections = isReady ? databases.map((db) => db.collectionsLength).reduce((acc, n) => acc + n, 0) : '-'; return { term: 'Stats', description: (
{`${numDbs} DB${numDbs === 1 ? '' : 's'}`}
{`${numCollections} Collection${ numCollections === 1 ? '' : 's' }`}
), }; } function getHostInfo({ instance }: InfoParameters): ConnectionInfo { const { type, servers = [] } = instance?.topologyDescription ?? {}; let heading = servers.length === 1 ? 'Host' : 'Hosts'; if (type === TopologyType.LOAD_BALANCED) { heading += ' (Load Balancer)'; } const hosts = servers.length === 1 ? ( servers[0].address ) : (
{servers.map((server, i) => (
{server.address}
))}
); return { term: heading, description: hosts, }; } function makeNodesInfo( numNodes: number, single: string, plural: string ): string { return numNodes === 1 ? `1 ${single}` : `${numNodes} ${plural}`; } function getClusterInfo({ instance }: InfoParameters): ConnectionInfo { const { type, setName, servers = [] } = instance?.topologyDescription ?? {}; let clusterType: string; let nodesInfo; switch (type) { case TopologyType.SHARDED: clusterType = 'Sharded'; nodesInfo = makeNodesInfo(servers.length, 'Mongos', 'Mongoses'); break; case TopologyType.REPLICA_SET_NO_PRIMARY: case TopologyType.REPLICA_SET_WITH_PRIMARY: clusterType = `Replica Set ${setName}`; nodesInfo = makeNodesInfo(servers.length, 'Node', 'Nodes'); break; default: clusterType = ServerType.humanize(servers[0].type); break; } return { term: 'Cluster', description: nodesInfo ? (
{clusterType}
{nodesInfo}
) : ( clusterType ), }; } function getVersionInfo({ instance }: InfoParameters): ConnectionInfo { return { term: 'Edition', description: instance?.dataLake.isDataLake ? `Atlas Data Federation ${instance?.dataLake.version ?? ''}` : `MongoDB ${instance?.build.version} ${getVersionDistro({ isEnterprise: instance?.build.isEnterprise, isLocalAtlas: instance?.isLocalAtlas, isAtlas: instance?.isAtlas, })}`, }; } function getSSHTunnelInfo({ connectionOptions, }: InfoParameters): ConnectionInfo { const { sshTunnelHostPortString } = connectionOptions; return { term: 'SSH Connection Via', description: sshTunnelHostPortString, }; } function getInfos(infoParameters: InfoParameters) { const infos: ConnectionInfo[] = []; const { instance, connectionOptions } = infoParameters; if (!instance) { return infos; } infos.push(getStatsInfo(infoParameters)); infos.push(getHostInfo(infoParameters)); if ( instance.dataLake.isDataLake === false && instance.topologyDescription.type !== TopologyType.LOAD_BALANCED ) { infos.push(getClusterInfo(infoParameters)); } infos.push(getVersionInfo(infoParameters)); if (connectionOptions.sshTunnel) { infos.push(getSSHTunnelInfo(infoParameters)); } return infos; } const mapStateToProps = (state: RootState) => { const { instance, databases, connectionOptions } = state; const { connectionInfo } = state.connectionInfo; return { infos: getInfos({ instance, databases: databases.databases, connectionInfo, connectionOptions, }), }; }; const MappedConnectionInfoModal = connect( mapStateToProps, {} )(ConnectionInfoModal); export default MappedConnectionInfoModal;