diff options
author | Galen Guyer <galen@galenguyer.com> | 2022-08-31 20:53:52 -0400 |
---|---|---|
committer | Galen Guyer <galen@galenguyer.com> | 2022-08-31 20:53:52 -0400 |
commit | 66525a58f29313b66c407121d6b1b25ed8670d52 (patch) | |
tree | 2f81ef6e18f9a808d26b800376166caacb9d0c3e | |
parent | 2c5666633b749b2de6baca0fbd7c74f3a37c766e (diff) |
Add zone creation
-rw-r--r-- | src/routes/Records.js | 4 | ||||
-rw-r--r-- | src/routes/Zones.js | 143 |
2 files changed, 118 insertions, 29 deletions
diff --git a/src/routes/Records.js b/src/routes/Records.js index cd69f72..2a21fab 100644 --- a/src/routes/Records.js +++ b/src/routes/Records.js @@ -157,7 +157,9 @@ export function Records() { return ( <RequireAuth> <main className="records-table-container"> - <h1>DNS Records for {zoneName}</h1> + <h1> + DNS Records for <b>{zoneName}</b> + </h1> {zone && ( <RecordTable records={zone} diff --git a/src/routes/Zones.js b/src/routes/Zones.js index 36c034e..338e0ec 100644 --- a/src/routes/Zones.js +++ b/src/routes/Zones.js @@ -1,20 +1,22 @@ import { RequireAuth, useAuth } from '../hooks/useAuth' import { useErrorModal } from '../hooks/useErrorModal' import useFetch from '../hooks/useFetch' +import Button from '../uikit/Button' +import StyledInput from '../uikit/Input' +import { AlignRight } from './SignUp' import { styled } from '@stitches/react' +import { useState } from 'react' +import Modal from 'react-modal' import { Link } from 'react-router-dom' - -const Container = styled('main', { - maxWidth: '800px', - margin: 'auto', - padding: '12px', -}) +import { useNavigate } from 'react-router-dom' const Card = styled('div', { - padding: '16px 48px', + padding: '18px 36px', + margin: '12px', borderRadius: '8px', + fontSize: '1.2em', flexBasis: '100%', - border: '1px solid #D4D4D8', + border: '1px solid #a4a4a8', backgroundColor: '#F4F4F5', transition: 'box-shadow 0.2s', '&:hover': { @@ -22,14 +24,26 @@ const Card = styled('div', { }, }) -const LinkStyled = styled(Link, { +const StyledLink = styled(Link, { textDecoration: 'none', color: 'inherit', + width: '50%', +}) + +const ZoneContainer = styled('div', { + display: 'flex', + alignItems: 'flex-start', + justifyContent: 'space-between', + maxWidth: '800px', + flexWrap: 'wrap', + margin: '0 auto', }) export default function Zones() { const auth = useAuth() const errorModal = useErrorModal() + const [showZoneCreateModal, setShowZoneCreateModal] = useState(false) + let { data, loading, error } = useFetch('/api/v1/zones', { headers: { Authorization: auth.token, @@ -39,12 +53,10 @@ export default function Zones() { if (loading) { return ( <RequireAuth> - <Container> - <div style={{ padding: '0px 32px' }}> - <h1>Available Zones</h1> - <h2>Loading zones...</h2> - </div> - </Container> + <div style={{ padding: '0px 32px' }}> + <h1>Available Zones</h1> + <h2>Loading zones...</h2> + </div> </RequireAuth> ) } @@ -54,20 +66,95 @@ export default function Zones() { return ( <RequireAuth> - <Container> - <div style={{ padding: '0px 32px' }}> - <h1>Available Zones</h1> - <div style={{ display: 'flex' }}> - {data.map((zone) => { - return ( - <LinkStyled to={'/zones/' + zone.id}> - <Card>{zone.id}</Card> - </LinkStyled> - ) - })} + <div style={{ padding: '0px 32px' }}> + <h1>Available Zones</h1> + <ZoneContainer> + {data.map((zone) => { + return ( + <StyledLink to={'/zones/' + zone.id}> + <Card>{zone.id}</Card> + </StyledLink> + ) + })} + <div style={{ width: '100%' }}> + <Card onClick={() => setShowZoneCreateModal(true)}>Add Zone</Card> </div> - </div> - </Container> + </ZoneContainer> + <CreateZoneModal + showZoneCreateModal={showZoneCreateModal} + setShowZoneCreateModal={setShowZoneCreateModal} + /> + </div> </RequireAuth> ) } + +function CreateZoneModal({ showZoneCreateModal, setShowZoneCreateModal }) { + const [zoneName, setZoneName] = useState('') + const errorModal = useErrorModal() + const auth = useAuth() + const navigate = useNavigate() + + const addZone = () => { + fetch(`/api/v1/zones/${zoneName}`, { + method: 'POST', + headers: { + Authorization: `Bearer ${auth.token}`, + }, + }).then((res) => { + if (res.status === 200) { + setShowZoneCreateModal(false) + navigate(`/zones/${zoneName}`) + } else { + res + .json() + .then((data) => { + errorModal.show( + data.error + (data.message ? ` (${data.message})` : '') + ) + }) + .catch((err) => { + errorModal.show('Unknown error creating zone') + }) + } + }) + } + + const modalStyle = { + content: { + top: '50%', + left: '50%', + right: 'auto', + bottom: 'auto', + marginRight: '-50%', + padding: '2em', + transform: 'translate(-50%, -50%)', + }, + } + + return ( + <Modal + isOpen={showZoneCreateModal} + onRequestClose={() => setShowZoneCreateModal(false)} + style={modalStyle} + > + <h2 style={{ fontWeight: '500', marginTop: '0px' }}>Add Zone</h2> + <StyledInput + style={{ width: '24em' }} + onChange={(e) => setZoneName(e.target.value)} + ></StyledInput> + <AlignRight> + <Button + style={{ marginTop: '1em' }} + secondary + onClick={() => setShowZoneCreateModal(false)} + > + Cancel + </Button> + <Button style={{ marginTop: '1em' }} primary onClick={() => addZone()}> + Confirm + </Button> + </AlignRight> + </Modal> + ) +} |