import React, { type FormEvent, useCallback, useEffect, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Button, Form, ModalHeader, ModalBody, ModalFooter, Stack, TextInput } from '@carbon/react'; import { addImportMapOverride, addRouteMapOverride, enableImportMapOverride, getImportMapNextPageMap, isImportMapOverrideDisabled, removeImportMapOverride, removeRouteMapOverride, } from '@openmrs/esm-framework/src/internal'; import type { Module } from './types'; type ImportMapModalProps = ({ module: Module; isNew: false } | { module: never; isNew: true }) & { close: () => void }; const isPortRegex = /^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$/; async function getUrlFromPort(moduleName: string, port: string) { const latestImportMap = await getImportMapNextPageMap(); const moduleUrl = latestImportMap.imports[moduleName]; if (!moduleUrl) { const fileName = moduleName.replace(/@/g, '').replace(/\//g, '-'); return `${window.location.protocol}//localhost:${port}/${fileName}.js`; } if (moduleUrl.endsWith('/')) { return `${window.location.protocol}//localhost:${port}${moduleUrl}`; } return `${window.location.protocol}//localhost:${port}/${moduleUrl.substring(moduleUrl.lastIndexOf('/') + 1)}`; } const ImportMapModal: React.FC = ({ module, isNew, close }) => { const { t } = useTranslation(); const [moduleName, setModuleName] = useState(module?.moduleName); const moduleNameRef = useRef(); const inputRef = useRef(); const handleSubmit = useCallback( async (evt: FormEvent) => { evt.preventDefault(); if (!moduleName) { return; } if (isImportMapOverrideDisabled(moduleName)) { enableImportMapOverride(moduleName); } if (isNew) { let newUrl = inputRef.current.value || null; if (newUrl) { if (isPortRegex.test(newUrl)) { newUrl = await getUrlFromPort(moduleName, newUrl); } addImportMapOverride(moduleName, newUrl); const baseUrl = newUrl.substring(0, newUrl.lastIndexOf('/')); addRouteMapOverride(moduleName, new URL('routes.json', baseUrl)); } } else { let newUrl = inputRef.current.value || null; if (newUrl === null) { removeImportMapOverride(moduleName); removeRouteMapOverride(moduleName); } else { if (isPortRegex.test(newUrl)) { newUrl = await getUrlFromPort(moduleName, newUrl); } addImportMapOverride(moduleName, newUrl); const baseUrl = newUrl.substring(0, newUrl.lastIndexOf('/')); addRouteMapOverride(moduleName, new URL('routes.json', baseUrl)); } } close(); }, [moduleName, isNew, close], ); useEffect( () => (isNew ? moduleNameRef.current?.focus() : inputRef.current?.focus()), // Only fired on initial mount [], ); return ( <>
{isNew && ( ) => { evt.preventDefault(); setModuleName(evt.target.value); }} labelText={t('moduleName', 'Module Name')} /> )} {!isNew && ( )}
); }; export default ImportMapModal;