generated from railmapgen/seed-project
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
26f587b
commit 2272757
Showing
20 changed files
with
788 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { | ||
Flex, | ||
Image, | ||
Modal, | ||
ModalBody, | ||
ModalCloseButton, | ||
ModalContent, | ||
ModalHeader, | ||
ModalOverlay, | ||
Text, | ||
} from '@chakra-ui/react'; | ||
import rmgRuntime from '@railmapgen/rmg-runtime'; | ||
import { useTranslation } from 'react-i18next'; | ||
|
||
const AboutModal = (props: { isOpen: boolean; onClose: () => void }) => { | ||
const { isOpen, onClose } = props; | ||
const { t } = useTranslation(); | ||
const appVersion = rmgRuntime.getAppVersion(); | ||
|
||
return ( | ||
<Modal isOpen={isOpen} onClose={onClose} size="xl" scrollBehavior="inside"> | ||
<ModalOverlay /> | ||
<ModalContent> | ||
<ModalHeader>{t('header.about.title')}</ModalHeader> | ||
<ModalCloseButton /> | ||
|
||
<ModalBody paddingBottom={10}> | ||
<Flex direction="row"> | ||
<Image boxSize="128px" src={import.meta.env.BASE_URL + '/logo192.png'} /> | ||
<Flex direction="column" width="100%" alignItems="center" justifyContent="center"> | ||
<Text fontSize="xl" as="b"> | ||
{t('RMP Style Generator')} | ||
</Text> | ||
<Text>{appVersion}</Text> | ||
<Text /> | ||
<Text fontSize="sm">{t('header.about.railmapgen')}</Text> | ||
</Flex> | ||
</Flex> | ||
</ModalBody> | ||
</ModalContent> | ||
</Modal> | ||
); | ||
}; | ||
|
||
export default AboutModal; | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import { | ||
Button, | ||
Modal, | ||
ModalBody, | ||
ModalCloseButton, | ||
ModalContent, | ||
ModalFooter, | ||
ModalHeader, | ||
ModalOverlay, | ||
} from '@chakra-ui/react'; | ||
import { RmgFields, RmgFieldsField } from '@railmapgen/rmg-components'; | ||
import React from 'react'; | ||
import { useTranslation } from 'react-i18next'; | ||
import { SvgsAttrs, SvgsType } from '../../constants/svgs'; | ||
import svgs from '../svgs/svgs'; | ||
import { Id, SvgsElem } from '../../constants/constants'; | ||
import { nanoid, roundToNearestN } from '../../util/helper'; | ||
import { addSvg } from '../../redux/param/param-slice'; | ||
import { useRootDispatch } from '../../redux'; | ||
|
||
export const ImportFromSvg = (props: { isOpen: boolean; onClose: () => void }) => { | ||
const { isOpen, onClose } = props; | ||
const { t } = useTranslation(); | ||
const dispatch = useRootDispatch(); | ||
|
||
const [svgString, setSvgString] = React.useState(''); | ||
const field: RmgFieldsField[] = [ | ||
{ | ||
label: 'SVG', | ||
type: 'textarea', | ||
value: '', | ||
onChange: v => setSvgString(v), | ||
}, | ||
]; | ||
|
||
const handleImport = () => { | ||
const parser = new DOMParser(); | ||
const svgDoc = parser.parseFromString(svgString, 'image/svg+xml'); | ||
for (const svgTag of Object.values(SvgsType)) { | ||
const elems = svgDoc.getElementsByTagName(svgTag); | ||
for (let i = 0; i < elems.length; i++) { | ||
const elem = elems[i]; | ||
const id: Id = `id_${nanoid(10)}`; | ||
const x = elem.getAttribute(svgTag === 'circle' ? 'cx' : 'x') ?? '0'; | ||
const y = elem.getAttribute(svgTag === 'circle' ? 'cy' : 'y') ?? '0'; | ||
const attr = svgs[svgTag].inputFromSvg(elem); | ||
console.log(attr); | ||
const newElem: SvgsElem<SvgsAttrs[keyof SvgsAttrs]> = { | ||
id, | ||
type: svgTag, | ||
isCore: false, | ||
x, | ||
y, | ||
attrs: attr, | ||
}; | ||
dispatch(addSvg(newElem)); | ||
} | ||
} | ||
onClose(); | ||
}; | ||
|
||
return ( | ||
<Modal isOpen={isOpen} onClose={onClose} size="xl" scrollBehavior="inside"> | ||
<ModalOverlay /> | ||
<ModalContent> | ||
<ModalHeader>Import from SVG</ModalHeader> | ||
<ModalCloseButton /> | ||
|
||
<ModalBody paddingBottom={10}> | ||
<RmgFields fields={field} minW="full" /> | ||
</ModalBody> | ||
|
||
<ModalFooter> | ||
<Button colorScheme="blue" variant="outline" mr="1" onClick={onClose}> | ||
{t('cancel')} | ||
</Button> | ||
<Button colorScheme="red" mr="1" onClick={handleImport}> | ||
{t('apply')} | ||
</Button> | ||
</ModalFooter> | ||
</ModalContent> | ||
</Modal> | ||
); | ||
} | ||
4 changes: 2 additions & 2 deletions
4
src/components/window-header.test.tsx → src/components/header/window-header.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,11 @@ | ||
import { render } from '../test-utils'; | ||
import { render } from '../../test-utils'; | ||
import { screen } from '@testing-library/react'; | ||
import WindowHeader from './window-header'; | ||
|
||
describe('WindowHeader', () => { | ||
it('Can render window header', () => { | ||
render(<WindowHeader />); | ||
|
||
expect(screen.getByRole('heading').textContent).toContain('Seed Project'); | ||
expect(screen.getByRole('heading').textContent).toContain('RMP Style Generator'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { Heading, HStack, IconButton, Menu, MenuButton, MenuItem, MenuList } from '@chakra-ui/react'; | ||
import { RmgEnvBadge, RmgWindowHeader } from '@railmapgen/rmg-components'; | ||
import rmgRuntime from '@railmapgen/rmg-runtime'; | ||
import React from 'react'; | ||
import { useTranslation } from 'react-i18next'; | ||
import { MdHelp, MdRedo, MdSave, MdUndo, MdUpload } from 'react-icons/md'; | ||
import AboutModal from './about-modal'; | ||
import { ZoomPopover } from './zoom-popover'; | ||
import { ImportFromSvg } from './import-modal'; | ||
import { useRootDispatch, useRootSelector } from '../../redux'; | ||
import { setParam } from '../../redux/param/param-slice'; | ||
import { backupParam, backupRedo, backupRemove, backupUndo } from '../../redux/runtime/runtime-slice'; | ||
|
||
export default function WindowHeader() { | ||
const { t } = useTranslation(); | ||
const dispatch = useRootDispatch(); | ||
const { history, undo_history } = useRootSelector(store => store.runtime); | ||
const param = useRootSelector(store => store.param); | ||
|
||
|
||
const environment = rmgRuntime.getEnv(); | ||
const appVersion = rmgRuntime.getAppVersion(); | ||
|
||
const [openAbout, setOpenAbout] = React.useState(false); | ||
const [openImportSvg, setOpenImportSvg] = React.useState(false); | ||
|
||
return ( | ||
<RmgWindowHeader> | ||
<Heading as="h4" size="md"> | ||
{t('RMP Style Generator')} | ||
</Heading> | ||
<RmgEnvBadge environment={environment} version={appVersion} /> | ||
|
||
<HStack ml="auto"> | ||
<IconButton | ||
size="sm" | ||
variant="ghost" | ||
aria-label="Undo" | ||
icon={<MdUndo />} | ||
isDisabled={history.length === 0} | ||
onClick={() => { | ||
dispatch(backupUndo(param)); | ||
dispatch(setParam(history[history.length - 1])); | ||
dispatch(backupRemove()); | ||
}} | ||
/> | ||
<IconButton | ||
size="sm" | ||
variant="ghost" | ||
aria-label="Redo" | ||
icon={<MdRedo />} | ||
isDisabled={undo_history.length === 0} | ||
onClick={() => { | ||
console.log(undo_history); | ||
dispatch(backupParam(param)); | ||
dispatch(setParam(undo_history[undo_history.length - 1])); | ||
dispatch(backupRedo()); | ||
console.log(param); | ||
}} | ||
/> | ||
<ZoomPopover /> | ||
<Menu id="download"> | ||
<MenuButton as={IconButton} size="sm" variant="ghost" icon={<MdUpload />} /> | ||
<MenuList> | ||
<MenuItem icon={<MdSave />} onClick={() => setOpenImportSvg(true)}> | ||
Import from SVG | ||
</MenuItem> | ||
</MenuList> | ||
</Menu> | ||
<IconButton | ||
size="sm" | ||
variant="ghost" | ||
aria-label={t('Help')} | ||
title={t('Help')} | ||
icon={<MdHelp />} | ||
onClick={() => setOpenAbout(true)} | ||
/> | ||
</HStack> | ||
<AboutModal isOpen={openAbout} onClose={() => setOpenAbout(false)} /> | ||
<ImportFromSvg isOpen={openImportSvg} onClose={() => setOpenImportSvg(false)} /> | ||
</RmgWindowHeader> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import React from 'react'; | ||
import { IconButton, Popover, PopoverBody, PopoverContent, PopoverTrigger } from '@chakra-ui/react'; | ||
import { MdZoomOut, MdZoomIn } from 'react-icons/md'; | ||
import { RmgFields, RmgFieldsField } from '@railmapgen/rmg-components'; | ||
import { useRootSelector, useRootDispatch } from '../../redux'; | ||
import { setSvgViewBoxZoom } from '../../redux/runtime/runtime-slice'; | ||
|
||
/** | ||
* A zoom control displayed in popover component. | ||
* This will greatly decrease the width of the header in mobile device. | ||
*/ | ||
export const ZoomPopover = () => { | ||
const [isOpen, setIsOpen] = React.useState(false); | ||
|
||
const { svgViewBoxZoom } = useRootSelector(state => state.runtime); | ||
const dispatch = useRootDispatch(); | ||
|
||
const fields: RmgFieldsField[] = [ | ||
{ | ||
type: 'slider', | ||
label: '', | ||
value: 400 - svgViewBoxZoom, | ||
min: 10, | ||
max: 390, | ||
step: 1, | ||
onChange: value => dispatch(setSvgViewBoxZoom(400 - value)), | ||
leftIcon: <MdZoomOut />, | ||
rightIcon: <MdZoomIn />, | ||
minW: 160, | ||
}, | ||
]; | ||
|
||
return ( | ||
<Popover isOpen={isOpen} onOpen={() => setIsOpen(true)} onClose={() => setIsOpen(false)}> | ||
<PopoverTrigger> | ||
<IconButton | ||
aria-label="zoom" | ||
variant="ghost" | ||
size="sm" | ||
icon={<MdZoomIn />} | ||
onClick={() => setIsOpen(!isOpen)} | ||
/> | ||
</PopoverTrigger> | ||
<PopoverContent> | ||
<PopoverBody> | ||
<RmgFields fields={fields} noLabel /> | ||
</PopoverBody> | ||
</PopoverContent> | ||
</Popover> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.