Skip to content

Commit e3db564

Browse files
committed
Add basic support for listing a server's databases
1 parent 9862854 commit e3db564

File tree

7 files changed

+110
-138
lines changed

7 files changed

+110
-138
lines changed

resources/scripts/components/dashboard/DashboardContainer.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import { Link } from 'react-router-dom';
99

1010
export default () => (
1111
<div className={'my-10'}>
12-
<Link to={'/server/e9d6c836'} className={'flex no-underline text-neutral-200 cursor-pointer items-center bg-neutral-700 p-4 border border-transparent hover:border-neutral-500'}>
13-
<div className={'rounded-full bg-neutral-500 p-3'}>
12+
<Link to={'/server/e9d6c836'} className={'grey-row-box cursor-pointer'}>
13+
<div className={'icon'}>
1414
<FontAwesomeIcon icon={faServer}/>
1515
</div>
1616
<div className={'w-1/2 ml-4'}>
@@ -49,8 +49,8 @@ export default () => (
4949
</div>
5050
</div>
5151
</Link>
52-
<div className={'flex mt-px cursor-pointer items-center bg-neutral-700 p-4 border border-transparent hover:border-neutral-500'}>
53-
<div className={'rounded-full bg-neutral-500 p-3'}>
52+
<div className={'grey-row-box cursor-pointer mt-2'}>
53+
<div className={'icon'}>
5454
<FontAwesomeIcon icon={faServer}/>
5555
</div>
5656
<div className={'w-1/2 ml-4'}>
Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import React from 'react';
22
import classNames from 'classnames';
33

4-
export default ({ large }: { large?: boolean }) => (
5-
<div className={classNames('spinner-circle spinner-white', { 'spinner-lg': large })}/>
4+
export default ({ large, centered }: { large?: boolean; centered?: boolean }) => (
5+
centered ?
6+
<div className={classNames('flex justify-center', { 'm-20': large, 'm-6': !large })}>
7+
<div className={classNames('spinner-circle spinner-white', { 'spinner-lg': large })}/>
8+
</div>
9+
:
10+
<div className={classNames('spinner-circle spinner-white', { 'spinner-lg': large })}/>
611
);

resources/scripts/components/server/ServerDatabases.tsx

Lines changed: 0 additions & 24 deletions
This file was deleted.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import React from 'react';
2+
import { ServerDatabase } from '@/api/server/getServerDatabases';
3+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
4+
import { faDatabase } from '@fortawesome/free-solid-svg-icons/faDatabase';
5+
import { faTrashAlt } from '@fortawesome/free-solid-svg-icons/faTrashAlt';
6+
import { faEye } from '@fortawesome/free-solid-svg-icons/faEye';
7+
8+
export default ({ database }: { database: ServerDatabase }) => {
9+
return (
10+
<div className={'grey-row-box no-hover'}>
11+
<div className={'icon'}>
12+
<FontAwesomeIcon icon={faDatabase}/>
13+
</div>
14+
<div className={'flex-1 ml-4'}>
15+
<p className={'text-lg'}>{database.name}</p>
16+
</div>
17+
<div className={'ml-6'}>
18+
<p className={'text-center text-xs text-neutral-500 uppercase mb-1 select-none'}>Endpoint:</p>
19+
<p className={'text-center text-sm'}>{database.connectionString}</p>
20+
</div>
21+
<div className={'ml-6'}>
22+
<p className={'text-center text-xs text-neutral-500 uppercase mb-1 select-none'}>Connections From:</p>
23+
<p className={'text-center text-sm'}>{database.allowConnectionsFrom}</p>
24+
</div>
25+
<div className={'ml-6'}>
26+
<p className={'text-center text-xs text-neutral-500 uppercase mb-1 select-none'}>Username:</p>
27+
<p className={'text-center text-sm'}>{database.username}</p>
28+
</div>
29+
<div className={'ml-6'}>
30+
<button className={'btn btn-sm btn-secondary mr-2'}>
31+
<FontAwesomeIcon icon={faEye}/>
32+
</button>
33+
<button className={'btn btn-sm btn-secondary btn-red'}>
34+
<FontAwesomeIcon icon={faTrashAlt}/>
35+
</button>
36+
</div>
37+
</div>
38+
);
39+
};
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import React, { useEffect, useState } from 'react';
2+
import getServerDatabases, { ServerDatabase } from '@/api/server/getServerDatabases';
3+
import { ServerContext } from '@/state/server';
4+
import { Actions, useStoreActions } from 'easy-peasy';
5+
import { ApplicationStore } from '@/state';
6+
import { httpErrorToHuman } from '@/api/http';
7+
import FlashMessageRender from '@/components/FlashMessageRender';
8+
import DatabaseRow from '@/components/server/databases/DatabaseRow';
9+
import Spinner from '@/components/elements/Spinner';
10+
import { CSSTransition } from 'react-transition-group';
11+
12+
export default () => {
13+
const [ loading, setLoading ] = useState(true);
14+
const [ databases, setDatabases ] = useState<ServerDatabase[]>([]);
15+
const server = ServerContext.useStoreState(state => state.server.data!);
16+
const { addFlash, clearFlashes } = useStoreActions((actions: Actions<ApplicationStore>) => actions.flashes);
17+
18+
useEffect(() => {
19+
clearFlashes('databases');
20+
getServerDatabases(server.uuid)
21+
.then(databases => {
22+
setDatabases(databases);
23+
setLoading(false);
24+
})
25+
.catch(error => addFlash({
26+
key: 'databases',
27+
title: 'Error',
28+
message: httpErrorToHuman(error),
29+
type: 'error',
30+
}));
31+
}, []);
32+
33+
return (
34+
<div className={'my-10'}>
35+
<FlashMessageRender byKey={'databases'}/>
36+
{loading ?
37+
<Spinner large={true} centered={true}/>
38+
:
39+
<CSSTransition classNames={'fade'} timeout={250}>
40+
<React.Fragment>
41+
{databases.length > 0 ?
42+
databases.map(database => <DatabaseRow key={database.id} database={database}/>)
43+
:
44+
<p className={'text-sm text-neutral-200'}>No databases. :(</p>
45+
}
46+
</React.Fragment>
47+
</CSSTransition>
48+
}
49+
</div>
50+
);
51+
};

resources/scripts/routers/ServerRouter.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import ServerConsole from '@/components/server/ServerConsole';
55
import TransitionRouter from '@/TransitionRouter';
66
import Spinner from '@/components/elements/Spinner';
77
import WebsocketHandler from '@/components/server/WebsocketHandler';
8-
import ServerDatabases from '@/components/server/ServerDatabases';
98
import { ServerContext } from '@/state/server';
109
import { Provider } from 'react-redux';
10+
import DatabasesContainer from '@/components/server/databases/DatabasesContainer';
1111

1212
const ServerRouter = ({ match, location }: RouteComponentProps<{ id: string }>) => {
1313
const server = ServerContext.useStoreState(state => state.server.data);
@@ -45,7 +45,7 @@ const ServerRouter = ({ match, location }: RouteComponentProps<{ id: string }>)
4545
<WebsocketHandler/>
4646
<Switch location={location}>
4747
<Route path={`${match.path}`} component={ServerConsole} exact/>
48-
<Route path={`${match.path}/databases`} component={ServerDatabases}/>
48+
<Route path={`${match.path}/databases`} component={DatabasesContainer}/>
4949
</Switch>
5050
</React.Fragment>
5151
}

resources/styles/components/miscellaneous.css

Lines changed: 7 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -7,114 +7,15 @@ code.clean {
77
display: inline-block;
88
}
99

10-
/**
11-
* Indicators for server online status.
12-
*/
13-
.indicator {
14-
@apply .bg-neutral-800 .border .border-primary-500;
15-
border-radius: 50%;
16-
width: 16px;
17-
height: 16px;
10+
.grey-row-box {
11+
@apply .flex .rounded .no-underline .text-neutral-200 .items-center .bg-neutral-700 .p-4 .border .border-transparent;
12+
transition: border-color 150ms linear;
1813

19-
&.online {
20-
@apply .bg-green-600 .border-green-500;
21-
animation: onlineblink 2s infinite alternate;
14+
&:not(.no-hover):hover {
15+
@apply .border-neutral-500;
2216
}
2317

24-
&.offline {
25-
@apply .bg-green-600 .border-red-500;
26-
animation: offlineblink 2s infinite alternate;
27-
}
28-
}
29-
30-
/**
31-
* Usage indicator labels for the server listing.
32-
*/
33-
.usage {
34-
@apply .flex-1 .text-center .relative;
35-
36-
& > .indicator-title {
37-
@apply .text-xs .uppercase .font-hairline .bg-white .absolute .text-primary-500;
38-
margin-top:-9px;
39-
padding: 0 8px;
40-
left: 50%;
41-
transform: translate(-50%, 0);
42-
}
43-
}
44-
45-
/**
46-
* Styling for elements that contain the core page content.
47-
*/
48-
.content-box {
49-
@apply .bg-white .p-6 .rounded .shadow .border .border-neutral-100;
50-
}
51-
52-
/**
53-
* Flex boxes for server listing on user dashboard.
54-
*/
55-
.server-card-container {
56-
@apply .mb-4 .w-full;
57-
58-
@screen md {
59-
@apply .w-1/2 .pr-4;
60-
61-
&:nth-of-type(2n) {
62-
@apply .pr-0;
63-
}
64-
}
65-
66-
@screen lg {
67-
@apply .w-1/3 .pr-4;
68-
69-
&:nth-of-type(2n) {
70-
@apply .pr-4;
71-
}
72-
73-
&:nth-of-type(3n) {
74-
@apply .pr-0;
75-
}
76-
}
77-
78-
& > div {
79-
@apply .flex .flex-col;
80-
transition: box-shadow 150ms ease-in;
81-
82-
&:hover {
83-
@apply .shadow-md;
84-
}
85-
}
86-
87-
& > div > .server-card {
88-
@apply .flex .flex-col .p-4 .border .border-t-4 .border-neutral-100 .bg-white;
89-
transition: all 100ms ease-in;
90-
91-
& .identifier-icon {
92-
@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;
93-
}
94-
95-
& a, & a:visited {
96-
@apply .no-underline .text-neutral-800;
97-
}
98-
}
99-
100-
& > div > .footer {
101-
@apply .border .border-neutral-100 .border-t-0 .bg-neutral-50 .shadow-inner;
102-
}
103-
}
104-
105-
.pillbox {
106-
@apply .rounded-full .px-2 .py-1 .text-white .font-medium .leading-none .text-xs;
107-
}
108-
109-
.server-search {
110-
@apply .w-full .my-4;
111-
112-
& > input[type="text"] {
113-
@apply .w-full .p-4 .rounded .border .border-neutral-200 .text-neutral-500;
114-
transition: border 150ms ease-in;
115-
116-
&:focus {
117-
@apply .border-primary-500;
118-
}
18+
& > div.icon {
19+
@apply .rounded-full .bg-neutral-500 .p-3;
11920
}
12021
}

0 commit comments

Comments
 (0)