diff --git a/resources/scripts/components/dashboard/DashboardContainer.tsx b/resources/scripts/components/dashboard/DashboardContainer.tsx index 052d00034..a9c59a679 100644 --- a/resources/scripts/components/dashboard/DashboardContainer.tsx +++ b/resources/scripts/components/dashboard/DashboardContainer.tsx @@ -9,8 +9,8 @@ import { Link } from 'react-router-dom'; export default () => (
- -
+ +
@@ -49,8 +49,8 @@ export default () => (
-
-
+
+
diff --git a/resources/scripts/components/elements/Spinner.tsx b/resources/scripts/components/elements/Spinner.tsx index 090980e3f..d1704916f 100644 --- a/resources/scripts/components/elements/Spinner.tsx +++ b/resources/scripts/components/elements/Spinner.tsx @@ -1,6 +1,11 @@ import React from 'react'; import classNames from 'classnames'; -export default ({ large }: { large?: boolean }) => ( -
+export default ({ large, centered }: { large?: boolean; centered?: boolean }) => ( + centered ? +
+
+
+ : +
); diff --git a/resources/scripts/components/server/ServerDatabases.tsx b/resources/scripts/components/server/ServerDatabases.tsx deleted file mode 100644 index a0cf75aac..000000000 --- a/resources/scripts/components/server/ServerDatabases.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import React, { useEffect } from 'react'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { faDatabase } from '@fortawesome/free-solid-svg-icons/faDatabase'; -import getServerDatabases from '@/api/server/getServerDatabases'; -import { useStoreState } from 'easy-peasy'; - -export default () => { - useEffect(() => { - getServerDatabases('s'); - }, []); - - return ( -
-
-
- -
-
-

sfgsfgd

-
-
-
- ); -}; diff --git a/resources/scripts/components/server/databases/DatabaseRow.tsx b/resources/scripts/components/server/databases/DatabaseRow.tsx new file mode 100644 index 000000000..5638839b9 --- /dev/null +++ b/resources/scripts/components/server/databases/DatabaseRow.tsx @@ -0,0 +1,39 @@ +import React from 'react'; +import { ServerDatabase } from '@/api/server/getServerDatabases'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faDatabase } from '@fortawesome/free-solid-svg-icons/faDatabase'; +import { faTrashAlt } from '@fortawesome/free-solid-svg-icons/faTrashAlt'; +import { faEye } from '@fortawesome/free-solid-svg-icons/faEye'; + +export default ({ database }: { database: ServerDatabase }) => { + return ( +
+
+ +
+
+

{database.name}

+
+
+

Endpoint:

+

{database.connectionString}

+
+
+

Connections From:

+

{database.allowConnectionsFrom}

+
+
+

Username:

+

{database.username}

+
+
+ + +
+
+ ); +}; diff --git a/resources/scripts/components/server/databases/DatabasesContainer.tsx b/resources/scripts/components/server/databases/DatabasesContainer.tsx new file mode 100644 index 000000000..a4843cc80 --- /dev/null +++ b/resources/scripts/components/server/databases/DatabasesContainer.tsx @@ -0,0 +1,51 @@ +import React, { useEffect, useState } from 'react'; +import getServerDatabases, { ServerDatabase } from '@/api/server/getServerDatabases'; +import { ServerContext } from '@/state/server'; +import { Actions, useStoreActions } from 'easy-peasy'; +import { ApplicationStore } from '@/state'; +import { httpErrorToHuman } from '@/api/http'; +import FlashMessageRender from '@/components/FlashMessageRender'; +import DatabaseRow from '@/components/server/databases/DatabaseRow'; +import Spinner from '@/components/elements/Spinner'; +import { CSSTransition } from 'react-transition-group'; + +export default () => { + const [ loading, setLoading ] = useState(true); + const [ databases, setDatabases ] = useState([]); + const server = ServerContext.useStoreState(state => state.server.data!); + const { addFlash, clearFlashes } = useStoreActions((actions: Actions) => actions.flashes); + + useEffect(() => { + clearFlashes('databases'); + getServerDatabases(server.uuid) + .then(databases => { + setDatabases(databases); + setLoading(false); + }) + .catch(error => addFlash({ + key: 'databases', + title: 'Error', + message: httpErrorToHuman(error), + type: 'error', + })); + }, []); + + return ( +
+ + {loading ? + + : + + + {databases.length > 0 ? + databases.map(database => ) + : +

No databases. :(

+ } +
+
+ } +
+ ); +}; diff --git a/resources/scripts/routers/ServerRouter.tsx b/resources/scripts/routers/ServerRouter.tsx index 4e2708b86..4b01f0b63 100644 --- a/resources/scripts/routers/ServerRouter.tsx +++ b/resources/scripts/routers/ServerRouter.tsx @@ -5,9 +5,9 @@ import ServerConsole from '@/components/server/ServerConsole'; import TransitionRouter from '@/TransitionRouter'; import Spinner from '@/components/elements/Spinner'; import WebsocketHandler from '@/components/server/WebsocketHandler'; -import ServerDatabases from '@/components/server/ServerDatabases'; import { ServerContext } from '@/state/server'; import { Provider } from 'react-redux'; +import DatabasesContainer from '@/components/server/databases/DatabasesContainer'; const ServerRouter = ({ match, location }: RouteComponentProps<{ id: string }>) => { const server = ServerContext.useStoreState(state => state.server.data); @@ -45,7 +45,7 @@ const ServerRouter = ({ match, location }: RouteComponentProps<{ id: string }>) - + } diff --git a/resources/styles/components/miscellaneous.css b/resources/styles/components/miscellaneous.css index 158970f9b..f023a834b 100644 --- a/resources/styles/components/miscellaneous.css +++ b/resources/styles/components/miscellaneous.css @@ -7,114 +7,15 @@ code.clean { display: inline-block; } -/** - * Indicators for server online status. - */ -.indicator { - @apply .bg-neutral-800 .border .border-primary-500; - border-radius: 50%; - width: 16px; - height: 16px; +.grey-row-box { + @apply .flex .rounded .no-underline .text-neutral-200 .items-center .bg-neutral-700 .p-4 .border .border-transparent; + transition: border-color 150ms linear; - &.online { - @apply .bg-green-600 .border-green-500; - animation: onlineblink 2s infinite alternate; + &:not(.no-hover):hover { + @apply .border-neutral-500; } - &.offline { - @apply .bg-green-600 .border-red-500; - animation: offlineblink 2s infinite alternate; - } -} - -/** - * Usage indicator labels for the server listing. - */ -.usage { - @apply .flex-1 .text-center .relative; - - & > .indicator-title { - @apply .text-xs .uppercase .font-hairline .bg-white .absolute .text-primary-500; - margin-top:-9px; - padding: 0 8px; - left: 50%; - transform: translate(-50%, 0); - } -} - -/** - * Styling for elements that contain the core page content. - */ -.content-box { - @apply .bg-white .p-6 .rounded .shadow .border .border-neutral-100; -} - -/** - * Flex boxes for server listing on user dashboard. - */ -.server-card-container { - @apply .mb-4 .w-full; - - @screen md { - @apply .w-1/2 .pr-4; - - &:nth-of-type(2n) { - @apply .pr-0; - } - } - - @screen lg { - @apply .w-1/3 .pr-4; - - &:nth-of-type(2n) { - @apply .pr-4; - } - - &:nth-of-type(3n) { - @apply .pr-0; - } - } - - & > div { - @apply .flex .flex-col; - transition: box-shadow 150ms ease-in; - - &:hover { - @apply .shadow-md; - } - } - - & > div > .server-card { - @apply .flex .flex-col .p-4 .border .border-t-4 .border-neutral-100 .bg-white; - transition: all 100ms ease-in; - - & .identifier-icon { - @apply .select-none .inline-block .rounded-full .text-white .text-center .leading-none .justify-center .w-8 .h-8 .mr-2 .flex .flex-row .items-center; - } - - & a, & a:visited { - @apply .no-underline .text-neutral-800; - } - } - - & > div > .footer { - @apply .border .border-neutral-100 .border-t-0 .bg-neutral-50 .shadow-inner; - } -} - -.pillbox { - @apply .rounded-full .px-2 .py-1 .text-white .font-medium .leading-none .text-xs; -} - -.server-search { - @apply .w-full .my-4; - - & > input[type="text"] { - @apply .w-full .p-4 .rounded .border .border-neutral-200 .text-neutral-500; - transition: border 150ms ease-in; - - &:focus { - @apply .border-primary-500; - } + & > div.icon { + @apply .rounded-full .bg-neutral-500 .p-3; } }