import React, { Component, Fragment } from 'react'; // @ts-ignore ts-migrate(2305) FIXME: Module '"react"' has no exported member 'Node'. import type { Node } from 'react'; import classNames from 'classnames'; import { observer } from 'mobx-react'; import { get, includes, upperFirst } from 'lodash'; import { defineMessages, intlShape } from 'react-intl'; import CopyToClipboard from 'react-copy-to-clipboard'; import { PopOver } from 'react-polymorph/lib/components/PopOver'; import { Link } from 'react-polymorph/lib/components/Link'; import { LinkSkin } from 'react-polymorph/lib/skins/simple/LinkSkin'; import SVGInline from 'react-svg-inline'; import { ALLOWED_TIME_DIFFERENCE } from '../../config/timingConfig'; import globalMessages from '../../i18n/global-messages'; import DialogCloseButton from '../widgets/DialogCloseButton'; import closeCrossThin from '../../assets/images/close-cross-thin.inline.svg'; import iconCopy from '../../assets/images/clipboard-ic.inline.svg'; import sandClockIcon from '../../assets/images/sand-clock-xs.inline.svg'; import LocalizableError from '../../i18n/LocalizableError'; import { formattedNumber, formattedSize } from '../../utils/formatters'; import { CardanoNodeStates } from '../../../../common/types/cardano-node.types'; import styles from './DaedalusDiagnostics.scss'; import type { CardanoNodeState } from '../../../../common/types/cardano-node.types'; import type { SystemInfo } from '../../types/systemInfoTypes'; import type { CoreSystemInfo } from '../../types/coreSystemInfoTypes'; import type { TipInfo } from '../../api/network/types'; import { ErrorType } from '../../domains/ApiError'; const messages = defineMessages({ systemInfo: { id: 'daedalus.diagnostics.dialog.system.info', defaultMessage: '!!!SYSTEM INFO', description: 'System info', }, platform: { id: 'daedalus.diagnostics.dialog.platform', defaultMessage: '!!!Platform', description: 'Platform', }, platformVersion: { id: 'daedalus.diagnostics.dialog.platform.version', defaultMessage: '!!!Platform version', description: 'Platform version', }, cpu: { id: 'daedalus.diagnostics.dialog.cpu', defaultMessage: '!!!CPU', description: 'CPU', }, ram: { id: 'daedalus.diagnostics.dialog.ram', defaultMessage: '!!!RAM', description: 'RAM', }, availableDiskSpace: { id: 'daedalus.diagnostics.dialog.availableDiskSpace', defaultMessage: '!!!Available disk space', description: 'Available disk space', }, unknownDiskSpace: { id: 'daedalus.diagnostics.dialog.unknownDiskSpace', defaultMessage: '!!!Unknown', description: 'Unknown amount of disk space', }, unknownDiskSpaceSupportUrl: { id: 'daedalus.diagnostics.dialog.unknownDiskSpaceSupportUrl', defaultMessage: '!!!https://iohk.zendesk.com/hc', description: '"Support" link URL while disk space is unknown', }, hasMetHardwareRequirementsLabel: { id: 'daedalus.diagnostics.dialog.hasMetHardwareRequirementsStatus', defaultMessage: '!!!Recommended system requirements status', description: 'Displayed on the left of the Recommended system requirements status row', }, hasMetHardwareRequirementsStatusLowValue: { id: 'daedalus.diagnostics.dialog.hasMetHardwareRequirementsStatusLowValue', defaultMessage: '!!!Low', description: 'Displayed on the right of the Recommended system requirements status row when hardware requirements are insufficient', }, hasMetHardwareRequirementsStatusGoodValue: { id: 'daedalus.diagnostics.dialog.hasMetHardwareRequirementsStatusGoodValue', defaultMessage: '!!!Good', description: 'Displayed on the right of the Recommended system requirements status row when hardware requirements are ok', }, hasMetHardwareRequirementsStatusLowTooltip: { id: 'daedalus.diagnostics.dialog.hasMetHardwareRequirementsStatusLowTooltip', defaultMessage: '!!!Your system specifications do not meet Daedalus’ recommended hardware requirements. We suggest using a machine with at least 16 GB of RAM', description: 'Visible on hovering over Recommended system requirement status when status is Low', }, hasMetHardwareRequirementsStatusGoodTooltip: { id: 'daedalus.diagnostics.dialog.hasMetHardwareRequirementsStatusGoodTooltip', defaultMessage: '!!!Your system specifications meet Daedalus’ recommended hardware requirements', description: 'Visible on hovering over Recommended system requirement status when status is Good', }, isRTSFlagsModeEnabled: { id: 'daedalus.diagnostics.dialog.isRTSFlagsModeEnabled', defaultMessage: '!!!RTS Flags Mode', description: 'Indicates whether RTS Flags Mode is enabled or not', }, coreInfo: { id: 'daedalus.diagnostics.dialog.coreInfo', defaultMessage: '!!!CORE INFO', description: 'CORE INFO', }, daedalusVersion: { id: 'daedalus.diagnostics.dialog.daedalusVersion', defaultMessage: '!!!Daedalus version', description: 'Daedalus version', }, daedalusBuildNumber: { id: 'daedalus.diagnostics.dialog.daedalusBuildNumber', defaultMessage: '!!!Daedalus build number', description: 'Daedalus build number', }, daedalusMainProcessID: { id: 'daedalus.diagnostics.dialog.daedalusMainProcessID', defaultMessage: '!!!Daedalus main process ID', description: 'Daedalus main process ID', }, daedalusProcessID: { id: 'daedalus.diagnostics.dialog.daedalusProcessID', defaultMessage: '!!!Daedalus renderer process ID', description: 'Daedalus renderer process ID', }, blankScreenFix: { id: 'daedalus.diagnostics.dialog.blankScreenFix', defaultMessage: "!!!Daedalus 'Blank Screen Fix' active", description: "Daedalus 'Blank Screen Fix' active", }, cardanoNodeVersion: { id: 'daedalus.diagnostics.dialog.cardanoNodeVersion', defaultMessage: '!!!Cardano node version', description: 'Cardano node version', }, cardanoNodePID: { id: 'daedalus.diagnostics.dialog.cardanoNodePID', defaultMessage: '!!!Cardano node process ID', description: 'Cardano node process ID', }, cardanoNodeApiPort: { id: 'daedalus.diagnostics.dialog.cardanoNodeApiPort', defaultMessage: '!!!Cardano node port', description: 'Cardano node port', }, cardanoWalletPID: { id: 'daedalus.diagnostics.dialog.cardanoWalletPID', defaultMessage: '!!!Cardano wallet process ID', description: 'Cardano wallet process ID', }, cardanoWalletVersion: { id: 'daedalus.diagnostics.dialog.cardanoWalletVersion', defaultMessage: '!!!Cardano wallet version', description: 'Cardano wallet version', }, cardanoWalletApiPort: { id: 'daedalus.diagnostics.dialog.cardanoWalletApiPort', defaultMessage: '!!!Cardano wallet port', description: 'Cardano wallet port', }, cardanoNetwork: { id: 'daedalus.diagnostics.dialog.cardanoNetwork', defaultMessage: '!!!Cardano network', description: 'Cardano network', }, stateDirectoryPath: { id: 'daedalus.diagnostics.dialog.stateDirectory', defaultMessage: '!!!Daedalus state directory', description: 'Daedalus state directory', }, stateDirectoryPathOpenBtn: { id: 'daedalus.diagnostics.dialog.stateDirectoryPathOpenBtn', defaultMessage: '!!!Open', description: 'Open', }, connectionError: { id: 'daedalus.diagnostics.dialog.connectionError', defaultMessage: '!!!CONNECTION ERROR', description: 'CONNECTION ERROR', }, daedalusStatus: { id: 'daedalus.diagnostics.dialog.daedalusStatus', defaultMessage: '!!!DAEDALUS STATUS', description: 'DAEDALUS STATUS', }, connected: { id: 'daedalus.diagnostics.dialog.connected', defaultMessage: '!!!Connected', description: 'Connected', }, synced: { id: 'daedalus.diagnostics.dialog.synced', defaultMessage: '!!!Synced', description: 'Synced', }, syncPercentage: { id: 'daedalus.diagnostics.dialog.syncPercentage', defaultMessage: '!!!Sync percentage', description: 'Sync percentage', }, localTimeDifference: { id: 'daedalus.diagnostics.dialog.localTimeDifference', defaultMessage: '!!!Local time difference', description: 'Local time difference', }, systemTimeCorrect: { id: 'daedalus.diagnostics.dialog.systemTimeCorrect', defaultMessage: '!!!System time correct', description: 'System time correct', }, systemTimeIgnored: { id: 'daedalus.diagnostics.dialog.systemTimeIgnored', defaultMessage: '!!!System time ignored', description: 'System time ignored', }, checkingNodeTime: { id: 'daedalus.diagnostics.dialog.checkingNodeTime', defaultMessage: '!!!Checking system time', description: 'Checking system time', }, cardanoNodeStatus: { id: 'daedalus.diagnostics.dialog.cardanoNodeStatus', defaultMessage: '!!!CARDANO NODE STATUS', description: 'CARDANO NODE STATUS', }, cardanoNodeStatusRestarting: { id: 'daedalus.diagnostics.dialog.cardanoNodeStatusRestarting', defaultMessage: '!!!Restarting Cardano node...', description: 'Restarting Cardano node...', }, cardanoNodeStatusRestart: { id: 'daedalus.diagnostics.dialog.cardanoNodeStatusRestart', defaultMessage: '!!!Restart Cardano node', description: 'Restart Cardano node', }, cardanoNodeState: { id: 'daedalus.diagnostics.dialog.cardanoNodeState', defaultMessage: '!!!Cardano node state', description: 'Cardano node state', }, nodeHasBeenUpdated: { id: 'daedalus.diagnostics.dialog.nodeHasBeenUpdated', defaultMessage: '!!!Updated', description: 'Updated', }, nodeHasCrashed: { id: 'daedalus.diagnostics.dialog.nodeHasCrashed', defaultMessage: '!!!Crashed', description: 'Crashed', }, nodeHasErrored: { id: 'daedalus.diagnostics.dialog.nodeHasErrored', defaultMessage: '!!!Errored', description: 'Errored', }, nodeHasStopped: { id: 'daedalus.diagnostics.dialog.nodeHasStopped', defaultMessage: '!!!Stopped', description: 'Stopped', }, nodeIsExiting: { id: 'daedalus.diagnostics.dialog.nodeIsExiting', defaultMessage: '!!!Exiting', description: 'Exiting', }, nodeIsRunning: { id: 'daedalus.diagnostics.dialog.nodeIsRunning', defaultMessage: '!!!Running', description: 'Running', }, nodeIsStarting: { id: 'daedalus.diagnostics.dialog.nodeIsStarting', defaultMessage: '!!!Starting', description: 'Starting', }, nodeIsStopping: { id: 'daedalus.diagnostics.dialog.nodeIsStopping', defaultMessage: '!!!Stopping', description: 'Stopping', }, nodeIsUnrecoverable: { id: 'daedalus.diagnostics.dialog.nodeIsUnrecoverable', defaultMessage: '!!!Unrecoverable', description: 'Unrecoverable', }, nodeIsUpdating: { id: 'daedalus.diagnostics.dialog.nodeIsUpdating', defaultMessage: '!!!Updating', description: 'Updating', }, cardanoNodeResponding: { id: 'daedalus.diagnostics.dialog.cardanoNodeResponding', defaultMessage: '!!!Cardano node responding', description: 'Cardano node responding', }, cardanoNodeSubscribed: { id: 'daedalus.diagnostics.dialog.cardanoNodeSubscribed', defaultMessage: '!!!Cardano node subscribed', description: 'Cardano node subscribed', }, cardanoNodeTimeCorrect: { id: 'daedalus.diagnostics.dialog.cardanoNodeTimeCorrect', defaultMessage: '!!!Cardano node time correct', description: 'Cardano node time correct', }, cardanoNodeSyncing: { id: 'daedalus.diagnostics.dialog.cardanoNodeSyncing', defaultMessage: '!!!Cardano node syncing', description: 'Cardano node syncing', }, cardanoNodeInSync: { id: 'daedalus.diagnostics.dialog.cardanoNodeInSync', defaultMessage: '!!!Cardano node in sync', description: 'Cardano node in sync', }, localTimeDifferenceChecking: { id: 'daedalus.diagnostics.dialog.localTimeDifferenceChecking', defaultMessage: '!!!Checking...', description: 'Checking...', }, localTimeDifferenceCheckTime: { id: 'daedalus.diagnostics.dialog.localTimeDifferenceCheckTime', defaultMessage: '!!!Check time', description: 'Check time', }, statusOn: { id: 'daedalus.diagnostics.dialog.statusOn', defaultMessage: '!!!Yes', description: 'Yes', }, statusOff: { id: 'daedalus.diagnostics.dialog.statusOff', defaultMessage: '!!!No', description: 'No', }, statusOnForUserSettings: { id: 'daedalus.diagnostics.dialog.statusOnForUserSettings', defaultMessage: '!!!On', description: 'On', }, statusOffForUserSettings: { id: 'daedalus.diagnostics.dialog.statusOffForUserSettings', defaultMessage: '!!!Off', description: 'Off', }, serviceUnreachable: { id: 'daedalus.diagnostics.dialog.serviceUnreachable', defaultMessage: '!!!NTP service unreachable', description: 'NTP service unreachable', }, message: { id: 'daedalus.diagnostics.dialog.message', defaultMessage: '!!!message', description: 'message', }, code: { id: 'daedalus.diagnostics.dialog.code', defaultMessage: '!!!code', description: 'code', }, lastNetworkBlock: { id: 'daedalus.diagnostics.dialog.lastNetworkBlock', defaultMessage: '!!!Last network block', description: 'Last network block', }, lastSynchronizedBlock: { id: 'daedalus.diagnostics.dialog.lastSynchronizedBlock', defaultMessage: '!!!Last synchronized block', description: 'Last synchronized block', }, epoch: { id: 'daedalus.diagnostics.dialog.epoch', defaultMessage: '!!!epoch', description: 'epoch', }, slot: { id: 'daedalus.diagnostics.dialog.slot', defaultMessage: '!!!slot', description: 'slot', }, }); type Props = { systemInfo: SystemInfo; coreInfo: CoreSystemInfo; cardanoNodeState: CardanoNodeState | null | undefined; isNodeResponding: boolean; // isNodeSubscribed: boolean, isNodeSyncing: boolean; isNodeInSync: boolean; isNodeTimeCorrect: boolean; nodeConnectionError: LocalizableError | null | undefined; isConnected: boolean; isSynced: boolean; syncPercentage: number; localTimeDifference: number | null | undefined; isSystemTimeCorrect: boolean; isSystemTimeIgnored: boolean; isCheckingSystemTime: boolean; isForceCheckingSystemTime: boolean; localTip: TipInfo | null | undefined; networkTip: TipInfo | null | undefined; onOpenStateDirectory: (...args: Array) => any; onOpenExternalLink: (...args: Array) => any; onRestartNode: (...args: Array) => any; onClose: (...args: Array) => any; onCopyStateDirectoryPath: (...args: Array) => any; onForceCheckNetworkClock: (...args: Array) => any; }; type State = { isNodeRestarting: boolean; }; const FINAL_CARDANO_NODE_STATES = [ CardanoNodeStates.RUNNING, CardanoNodeStates.UPDATED, CardanoNodeStates.CRASHED, CardanoNodeStates.ERRORED, CardanoNodeStates.UNRECOVERABLE, ]; @observer class DaedalusDiagnostics extends Component { static contextTypes = { intl: intlShape.isRequired, }; constructor(props: Props) { super(props); this.state = { isNodeRestarting: false, }; } componentDidUpdate(prevProps: Props) { const { cardanoNodeState: prevCardanoNodeState } = prevProps; const { cardanoNodeState } = this.props; if ( cardanoNodeState !== prevCardanoNodeState && includes(FINAL_CARDANO_NODE_STATES, cardanoNodeState) ) { this.setState({ isNodeRestarting: false, }); // eslint-disable-line } } getSectionRow = (messageId: string, content?: Node) => { return (
{this.context.intl.formatMessage(messages[messageId])} {content}
); }; getRow = (messageId: string, value: Node | boolean) => { const { intl } = this.context; const key = intl.formatMessage(messages[messageId]); const colon = intl.formatMessage(globalMessages.punctuationColon); let content = value; let className = classNames([styles[messageId], styles.layoutData]); const classNameHeader = classNames([ styles[messageId], styles.layoutHeader, ]); const classNameRow = classNames([styles.layoutRow, messageId]); if (typeof value === 'boolean') { content = value ? intl.formatMessage(messages.statusOn) : intl.formatMessage(messages.statusOff); className = (value && messageId !== 'systemTimeIgnored') || (!value && messageId === 'systemTimeIgnored') ? classNames([className, styles.green]) : classNames([className, styles.red]); } return (
{key} {colon}
{content}
); }; render() { const { intl } = this.context; const { systemInfo, coreInfo, cardanoNodeState, isNodeResponding, // isNodeSubscribed, isNodeSyncing, isNodeInSync, isNodeTimeCorrect, isConnected, isSynced, syncPercentage, localTimeDifference, isSystemTimeCorrect, isSystemTimeIgnored, localTip, networkTip, onOpenStateDirectory, onClose, onCopyStateDirectoryPath, nodeConnectionError, onOpenExternalLink, isCheckingSystemTime, isForceCheckingSystemTime, } = this.props; const { platform, platformVersion, cpu, ram, availableDiskSpace: availableDiskSpaceInOriginalFormat, hasMetHardwareRequirements, isRTSFlagsModeEnabled, } = systemInfo; const availableDiskSpace = formattedSize( availableDiskSpaceInOriginalFormat ); const { daedalusVersion, daedalusBuildNumber, daedalusProcessID, daedalusMainProcessID, isBlankScreenFixActive, cardanoNodeVersion, cardanoNodePID, cardanoWalletVersion, cardanoWalletPID, cardanoWalletApiPort, cardanoNetwork, daedalusStateDirectoryPath, } = coreInfo; const { isNodeRestarting } = this.state; const isNTPServiceReachable = localTimeDifference != null; const connectionError = get(nodeConnectionError, 'values', '{}'); const { message, code } = connectionError as ErrorType; const unknownDiskSpaceSupportUrl = intl.formatMessage( messages.unknownDiskSpaceSupportUrl ); const cardanoNetworkValue = intl.formatMessage( globalMessages[`network_${cardanoNetwork}`] ); const localTimeDifferenceClasses = isCheckingSystemTime ? classNames([styles.layoutData, styles.localTimeDifference]) : classNames([ styles.layoutData, styles.localTimeDifference, !isNTPServiceReachable || (localTimeDifference && Math.abs(localTimeDifference) > ALLOWED_TIME_DIFFERENCE) ? styles.red : styles.green, ]); const { getSectionRow, getRow } = this; return (
{getSectionRow('systemInfo')} {getRow('platform', platform)} {getRow('platformVersion', platformVersion)} {getRow('cpu', {cpu})} {getRow('ram', ram)} {getRow( 'availableDiskSpace', availableDiskSpace || ( onOpenExternalLink(unknownDiskSpaceSupportUrl) } label={intl.formatMessage(messages.unknownDiskSpace)} skin={LinkSkin} /> ) )} {getRow( 'hasMetHardwareRequirementsLabel',
{intl.formatMessage( hasMetHardwareRequirements ? messages.hasMetHardwareRequirementsStatusGoodValue : messages.hasMetHardwareRequirementsStatusLowValue )}
)} {getRow( 'isRTSFlagsModeEnabled', intl.formatMessage( isRTSFlagsModeEnabled ? messages.statusOnForUserSettings : messages.statusOffForUserSettings ) )}
{getSectionRow('coreInfo')} {getRow('daedalusVersion', daedalusVersion)} {getRow('daedalusBuildNumber', daedalusBuildNumber)} {getRow('daedalusMainProcessID', daedalusMainProcessID)} {getRow('daedalusProcessID', daedalusProcessID)} {getRow( 'blankScreenFix', isBlankScreenFixActive ? intl.formatMessage(messages.statusOnForUserSettings) : intl.formatMessage(messages.statusOffForUserSettings) )} {getRow( 'stateDirectoryPath',
{daedalusStateDirectoryPath}
} >
{daedalusStateDirectoryPath}
)} {getRow('cardanoNodeVersion', cardanoNodeVersion)} {getRow('cardanoNodePID', cardanoNodePID || '-')} {/* getRow('cardanoNodeApiPort', '-') */} {getRow('cardanoWalletVersion', cardanoWalletVersion)} {getRow('cardanoWalletPID', cardanoWalletPID || '-')} {getRow('cardanoWalletApiPort', cardanoWalletApiPort || '-')}
{isConnected && nodeConnectionError ? (
{getSectionRow('connectionError')}
{intl.formatMessage(messages.message)}: {message || '-'}
{intl.formatMessage(messages.code)}: {code || '-'}
) : null}
{getSectionRow('daedalusStatus')} {getRow('cardanoNetwork', cardanoNetworkValue)} {getRow('connected', isConnected)} {getRow('synced', isSynced)} {getRow( 'syncPercentage', `${formattedNumber(syncPercentage, 2)}%` )} {getRow( 'lastNetworkBlock', {intl.formatMessage(messages.epoch)}:{' '} {networkTip && networkTip.epoch ? ( formattedNumber(networkTip.epoch) ) : ( )} {intl.formatMessage(messages.slot)}:{' '} {networkTip && networkTip.slot ? ( formattedNumber(networkTip.slot) ) : ( )} )} {getRow( 'lastSynchronizedBlock', {intl.formatMessage(messages.epoch)}:{' '} {localTip && localTip.epoch ? ( formattedNumber(localTip.epoch) ) : ( )} {intl.formatMessage(messages.slot)}:{' '} {localTip && localTip.slot ? ( formattedNumber(localTip.slot) ) : ( )} )}
{intl.formatMessage(messages.localTimeDifference)} {intl.formatMessage(globalMessages.punctuationColon)}
{ } {isCheckingSystemTime ? ( ) : ( {isNTPServiceReachable ? `${formattedNumber(localTimeDifference || 0)} μs` : intl.formatMessage(messages.serviceUnreachable)} )}
{getRow('systemTimeCorrect', isSystemTimeCorrect)} {getRow('systemTimeIgnored', isSystemTimeIgnored)} {
{intl.formatMessage(messages.checkingNodeTime)} {intl.formatMessage(globalMessages.punctuationColon)}
{isCheckingSystemTime ? intl.formatMessage(messages.statusOn) : intl.formatMessage(messages.statusOff)}
}
{getSectionRow( 'cardanoNodeStatus', )} {getRow( 'cardanoNodeState', upperFirst( cardanoNodeState != null ? intl.formatMessage( this.getLocalisationForCardanoNodeState() ) : 'unknown' ) )} {getRow('cardanoNodeResponding', isNodeResponding)} {/* getRow('cardanoNodeSubscribed', isNodeSubscribed) */} {getRow('cardanoNodeTimeCorrect', isNodeTimeCorrect)} {getRow('cardanoNodeSyncing', isNodeSyncing)} {getRow('cardanoNodeInSync', isNodeInSync)}
); } getLocalisationForCardanoNodeState = () => { const { cardanoNodeState } = this.props; let localisationKey; switch (cardanoNodeState) { case CardanoNodeStates.STARTING: localisationKey = messages.nodeIsStarting; break; case CardanoNodeStates.EXITING: localisationKey = messages.nodeIsExiting; break; case CardanoNodeStates.STOPPING: localisationKey = messages.nodeIsStopping; break; case CardanoNodeStates.STOPPED: localisationKey = messages.nodeHasStopped; break; case CardanoNodeStates.UPDATING: localisationKey = messages.nodeIsUpdating; break; case CardanoNodeStates.UPDATED: localisationKey = messages.nodeHasBeenUpdated; break; case CardanoNodeStates.CRASHED: localisationKey = messages.nodeHasCrashed; break; case CardanoNodeStates.ERRORED: localisationKey = messages.nodeHasErrored; break; case CardanoNodeStates.UNRECOVERABLE: localisationKey = messages.nodeIsUnrecoverable; break; default: localisationKey = messages.nodeIsRunning; break; } return localisationKey; }; restoreDialogCloseOnEscKey = () => { // This method is to be used on buttons which get disabled after click // as without it the ReactModal is not closing if you press the ESC key // even after the button is later re-enabled // @ts-ignore ts-migrate(2339) FIXME: Property 'focus' does not exist on type 'Element'. document.getElementsByClassName('ReactModal__Content')[0].focus(); }; checkTime = () => { this.props.onForceCheckNetworkClock(); this.restoreDialogCloseOnEscKey(); }; restartNode = () => { this.setState({ isNodeRestarting: true, }); // @ts-ignore ts-migrate(2339) FIXME: Property 'trigger' does not exist on type '(...arg... Remove this comment to see the full error message this.props.onRestartNode.trigger(); this.restoreDialogCloseOnEscKey(); }; } export default DaedalusDiagnostics;