aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGalen Guyer <galen@galenguyer.com>2022-08-31 20:53:52 -0400
committerGalen Guyer <galen@galenguyer.com>2022-08-31 20:53:52 -0400
commit66525a58f29313b66c407121d6b1b25ed8670d52 (patch)
tree2f81ef6e18f9a808d26b800376166caacb9d0c3e
parent2c5666633b749b2de6baca0fbd7c74f3a37c766e (diff)
Add zone creation
-rw-r--r--src/routes/Records.js4
-rw-r--r--src/routes/Zones.js143
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>
+ )
+}