diff --git a/resources/scripts/components/elements/Modal.tsx b/resources/scripts/components/elements/Modal.tsx new file mode 100644 index 000000000..ce15572f8 --- /dev/null +++ b/resources/scripts/components/elements/Modal.tsx @@ -0,0 +1,61 @@ +import React, { useEffect, useState } from 'react'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faTimes } from '@fortawesome/free-solid-svg-icons/faTimes'; +import { CSSTransition } from 'react-transition-group'; + +interface Props { + visible: boolean; + onDismissed: () => void; + dismissable?: boolean; + closeOnEscape?: boolean; + closeOnBackground?: boolean; + children: React.ReactChild; +} + +export default (props: Props) => { + const [render, setRender] = useState(props.visible); + + const handleEscapeEvent = (e: KeyboardEvent) => { + if (props.dismissable !== false && props.closeOnEscape !== false && e.key === 'Escape') { + setRender(false); + } + }; + + useEffect(() => setRender(props.visible), [props.visible]); + + useEffect(() => { + window.addEventListener('keydown', handleEscapeEvent); + + return () => window.removeEventListener('keydown', handleEscapeEvent); + }, [render]); + + return ( + props.onDismissed()} + > +
{ + if (props.dismissable !== false && props.closeOnBackground !== false) { + e.stopPropagation(); + if (e.target === e.currentTarget) { + setRender(false); + } + } + }}> +
+ {props.dismissable !== false && +
setRender(false)}> + +
+ } +
+ {props.children} +
+
+
+
+ ); +}; diff --git a/resources/scripts/components/server/databases/CreateDatabaseButton.tsx b/resources/scripts/components/server/databases/CreateDatabaseButton.tsx new file mode 100644 index 000000000..30d353e9a --- /dev/null +++ b/resources/scripts/components/server/databases/CreateDatabaseButton.tsx @@ -0,0 +1,18 @@ +import React, { useState } from 'react'; +import { ServerDatabase } from '@/api/server/getServerDatabases'; +import Modal from '@/components/elements/Modal'; + +export default ({ onCreated }: { onCreated: (database: ServerDatabase) => void }) => { + const [ visible, setVisible ] = useState(false); + + return ( + + setVisible(false)}> +

Testing

+
+ +
+ ); +}; diff --git a/resources/scripts/components/server/databases/DatabasesContainer.tsx b/resources/scripts/components/server/databases/DatabasesContainer.tsx index 1f16b5a69..680efc391 100644 --- a/resources/scripts/components/server/databases/DatabasesContainer.tsx +++ b/resources/scripts/components/server/databases/DatabasesContainer.tsx @@ -8,6 +8,7 @@ import FlashMessageRender from '@/components/FlashMessageRender'; import DatabaseRow from '@/components/server/databases/DatabaseRow'; import Spinner from '@/components/elements/Spinner'; import { CSSTransition } from 'react-transition-group'; +import CreateDatabaseButton from '@/components/server/databases/CreateDatabaseButton'; export default () => { const [ loading, setLoading ] = useState(true); @@ -45,10 +46,8 @@ export default () => { It looks like you have no databases. Click the button below to create one now.

} -
- +
+ setDatabases(s => [...s, database])}/>
diff --git a/resources/styles/components/modal.css b/resources/styles/components/modal.css index 4deb58cbf..650a7ec8f 100644 --- a/resources/styles/components/modal.css +++ b/resources/styles/components/modal.css @@ -7,13 +7,13 @@ @apply .relative .w-full .max-w-md .m-auto .flex-col .flex; &.top { - margin-top: 15%; + margin-top: 10%; } & > .modal-close-icon { @apply .absolute .pin-r .p-2 .text-white .cursor-pointer .opacity-50; transition: opacity 150ms linear, transform 150ms ease-in; - top: -2.5rem; + top: -2rem; &:hover { @apply .opacity-100; @@ -22,7 +22,7 @@ } & > .modal-content { - @apply .bg-white .rounded .shadow-md; + @apply .bg-neutral-900 .rounded .shadow-md; transition: all 250ms ease; }