Update database screens
This commit is contained in:
parent
a288374027
commit
7e8a5f1271
5 changed files with 86 additions and 76 deletions
|
@ -1,12 +1,10 @@
|
||||||
import styled from 'styled-components/macro';
|
import styled from 'styled-components/macro';
|
||||||
import tw from 'twin.macro';
|
import tw from 'twin.macro';
|
||||||
|
|
||||||
export default styled.div`
|
export default styled.div<{ $hoverable?: boolean }>`
|
||||||
${tw`flex rounded no-underline text-neutral-200 items-center bg-neutral-700 p-4 border border-transparent transition-colors duration-150`};
|
${tw`flex rounded no-underline text-neutral-200 items-center bg-neutral-700 p-4 border border-transparent transition-colors duration-150`};
|
||||||
|
|
||||||
&:not(.no-hover):hover {
|
${props => props.$hoverable !== false && tw`hover:border-neutral-500`};
|
||||||
${tw`border-neutral-500`};
|
|
||||||
}
|
|
||||||
|
|
||||||
& > div.icon {
|
& > div.icon {
|
||||||
${tw`rounded-full bg-neutral-500 p-3`};
|
${tw`rounded-full bg-neutral-500 p-3`};
|
||||||
|
|
|
@ -9,6 +9,8 @@ import { httpErrorToHuman } from '@/api/http';
|
||||||
import FlashMessageRender from '@/components/FlashMessageRender';
|
import FlashMessageRender from '@/components/FlashMessageRender';
|
||||||
import useFlash from '@/plugins/useFlash';
|
import useFlash from '@/plugins/useFlash';
|
||||||
import useServer from '@/plugins/useServer';
|
import useServer from '@/plugins/useServer';
|
||||||
|
import Button from '@/components/elements/Button';
|
||||||
|
import tw from 'twin.macro';
|
||||||
|
|
||||||
interface Values {
|
interface Values {
|
||||||
databaseName: string;
|
databaseName: string;
|
||||||
|
@ -48,7 +50,7 @@ export default () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<>
|
||||||
<Formik
|
<Formik
|
||||||
onSubmit={submit}
|
onSubmit={submit}
|
||||||
initialValues={{ databaseName: '', connectionsFrom: '%' }}
|
initialValues={{ databaseName: '', connectionsFrom: '%' }}
|
||||||
|
@ -65,9 +67,9 @@ export default () => {
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<FlashMessageRender byKey={'database:create'} className={'mb-6'}/>
|
<FlashMessageRender byKey={'database:create'} css={tw`mb-6`}/>
|
||||||
<h3 className={'mb-6'}>Create new database</h3>
|
<h2 css={tw`text-2xl mb-6`}>Create new database</h2>
|
||||||
<Form className={'m-0'}>
|
<Form css={tw`m-0`}>
|
||||||
<Field
|
<Field
|
||||||
type={'string'}
|
type={'string'}
|
||||||
id={'database_name'}
|
id={'database_name'}
|
||||||
|
@ -75,7 +77,7 @@ export default () => {
|
||||||
label={'Database Name'}
|
label={'Database Name'}
|
||||||
description={'A descriptive name for your database instance.'}
|
description={'A descriptive name for your database instance.'}
|
||||||
/>
|
/>
|
||||||
<div className={'mt-6'}>
|
<div css={tw`mt-6`}>
|
||||||
<Field
|
<Field
|
||||||
type={'string'}
|
type={'string'}
|
||||||
id={'connections_from'}
|
id={'connections_from'}
|
||||||
|
@ -84,26 +86,27 @@ export default () => {
|
||||||
description={'Where connections should be allowed from. Use % for wildcards.'}
|
description={'Where connections should be allowed from. Use % for wildcards.'}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className={'mt-6 text-right'}>
|
<div css={tw`mt-6 text-right`}>
|
||||||
<button
|
<Button
|
||||||
type={'button'}
|
type={'button'}
|
||||||
className={'btn btn-sm btn-secondary mr-2'}
|
isSecondary
|
||||||
|
css={tw`mr-2`}
|
||||||
onClick={() => setVisible(false)}
|
onClick={() => setVisible(false)}
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</Button>
|
||||||
<button className={'btn btn-sm btn-primary'} type={'submit'}>
|
<Button type={'submit'}>
|
||||||
Create Database
|
Create Database
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
</Formik>
|
</Formik>
|
||||||
<button className={'btn btn-primary btn-sm'} onClick={() => setVisible(true)}>
|
<Button onClick={() => setVisible(true)}>
|
||||||
New Database
|
New Database
|
||||||
</button>
|
</Button>
|
||||||
</React.Fragment>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,6 +17,11 @@ import Can from '@/components/elements/Can';
|
||||||
import { ServerDatabase } from '@/api/server/getServerDatabases';
|
import { ServerDatabase } from '@/api/server/getServerDatabases';
|
||||||
import useServer from '@/plugins/useServer';
|
import useServer from '@/plugins/useServer';
|
||||||
import useFlash from '@/plugins/useFlash';
|
import useFlash from '@/plugins/useFlash';
|
||||||
|
import tw from 'twin.macro';
|
||||||
|
import Button from '@/components/elements/Button';
|
||||||
|
import Label from '@/components/elements/Label';
|
||||||
|
import Input from '@/components/elements/Input';
|
||||||
|
import GreyRowBox from '@/components/elements/GreyRowBox';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
database: ServerDatabase;
|
database: ServerDatabase;
|
||||||
|
@ -53,11 +58,12 @@ export default ({ database, className }: Props) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<>
|
||||||
<Formik
|
<Formik
|
||||||
onSubmit={submit}
|
onSubmit={submit}
|
||||||
initialValues={{ confirm: '' }}
|
initialValues={{ confirm: '' }}
|
||||||
validationSchema={schema}
|
validationSchema={schema}
|
||||||
|
isInitialValid={false}
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
({ isSubmitting, isValid, resetForm }) => (
|
({ isSubmitting, isValid, resetForm }) => (
|
||||||
|
@ -70,13 +76,13 @@ export default ({ database, className }: Props) => {
|
||||||
resetForm();
|
resetForm();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<FlashMessageRender byKey={'database:delete'} className={'mb-6'}/>
|
<FlashMessageRender byKey={'database:delete'} css={tw`mb-6`}/>
|
||||||
<h3 className={'mb-6'}>Confirm database deletion</h3>
|
<h2 css={tw`text-2xl mb-6`}>Confirm database deletion</h2>
|
||||||
<p className={'text-sm'}>
|
<p css={tw`text-sm`}>
|
||||||
Deleting a database is a permanent action, it cannot be undone. This will permanetly
|
Deleting a database is a permanent action, it cannot be undone. This will permanetly
|
||||||
delete the <strong>{database.name}</strong> database and remove all associated data.
|
delete the <strong>{database.name}</strong> database and remove all associated data.
|
||||||
</p>
|
</p>
|
||||||
<Form className={'m-0 mt-6'}>
|
<Form css={tw`m-0 mt-6`}>
|
||||||
<Field
|
<Field
|
||||||
type={'text'}
|
type={'text'}
|
||||||
id={'confirm_name'}
|
id={'confirm_name'}
|
||||||
|
@ -84,21 +90,22 @@ export default ({ database, className }: Props) => {
|
||||||
label={'Confirm Database Name'}
|
label={'Confirm Database Name'}
|
||||||
description={'Enter the database name to confirm deletion.'}
|
description={'Enter the database name to confirm deletion.'}
|
||||||
/>
|
/>
|
||||||
<div className={'mt-6 text-right'}>
|
<div css={tw`mt-6 text-right`}>
|
||||||
<button
|
<Button
|
||||||
type={'button'}
|
type={'button'}
|
||||||
className={'btn btn-sm btn-secondary mr-2'}
|
isSecondary
|
||||||
|
css={tw`mr-2`}
|
||||||
onClick={() => setVisible(false)}
|
onClick={() => setVisible(false)}
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</Button>
|
||||||
<button
|
<Button
|
||||||
type={'submit'}
|
type={'submit'}
|
||||||
className={'btn btn-sm btn-red'}
|
color={'red'}
|
||||||
disabled={!isValid}
|
disabled={!isValid}
|
||||||
>
|
>
|
||||||
Delete Database
|
Delete Database
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
@ -106,62 +113,61 @@ export default ({ database, className }: Props) => {
|
||||||
}
|
}
|
||||||
</Formik>
|
</Formik>
|
||||||
<Modal visible={connectionVisible} onDismissed={() => setConnectionVisible(false)}>
|
<Modal visible={connectionVisible} onDismissed={() => setConnectionVisible(false)}>
|
||||||
<FlashMessageRender byKey={'database-connection-modal'} className={'mb-6'}/>
|
<FlashMessageRender byKey={'database-connection-modal'} css={tw`mb-6`}/>
|
||||||
<h3 className={'mb-6'}>Database connection details</h3>
|
<h3 css={tw`mb-6`}>Database connection details</h3>
|
||||||
<Can action={'database.view_password'}>
|
<Can action={'database.view_password'}>
|
||||||
<div>
|
<div>
|
||||||
<label className={'input-dark-label'}>Password</label>
|
<Label>Password</Label>
|
||||||
<input type={'text'} className={'input-dark'} readOnly={true} value={database.password}/>
|
<Input type={'text'} readOnly value={database.password}/>
|
||||||
</div>
|
</div>
|
||||||
</Can>
|
</Can>
|
||||||
<div className={'mt-6'}>
|
<div css={tw`mt-6`}>
|
||||||
<label className={'input-dark-label'}>JBDC Connection String</label>
|
<Label>JBDC Connection String</Label>
|
||||||
<input
|
<Input
|
||||||
type={'text'}
|
type={'text'}
|
||||||
className={'input-dark'}
|
readOnly
|
||||||
readOnly={true}
|
|
||||||
value={`jdbc:mysql://${database.username}:${database.password}@${database.connectionString}/${database.name}`}
|
value={`jdbc:mysql://${database.username}:${database.password}@${database.connectionString}/${database.name}`}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className={'mt-6 text-right'}>
|
<div css={tw`mt-6 text-right`}>
|
||||||
<Can action={'database.update'}>
|
<Can action={'database.update'}>
|
||||||
<RotatePasswordButton databaseId={database.id} onUpdate={appendDatabase}/>
|
<RotatePasswordButton databaseId={database.id} onUpdate={appendDatabase}/>
|
||||||
</Can>
|
</Can>
|
||||||
<button className={'btn btn-sm btn-secondary'} onClick={() => setConnectionVisible(false)}>
|
<Button isSecondary onClick={() => setConnectionVisible(false)}>
|
||||||
Close
|
Close
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
<div className={classNames('grey-row-box no-hover', className)}>
|
<GreyRowBox $hoverable={false} className={className}>
|
||||||
<div className={'icon'}>
|
<div>
|
||||||
<FontAwesomeIcon icon={faDatabase} fixedWidth={true}/>
|
<FontAwesomeIcon icon={faDatabase} fixedWidth/>
|
||||||
</div>
|
</div>
|
||||||
<div className={'flex-1 ml-4'}>
|
<div css={tw`flex-1 ml-4`}>
|
||||||
<p className={'text-lg'}>{database.name}</p>
|
<p css={tw`text-lg`}>{database.name}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className={'ml-8 text-center'}>
|
<div css={tw`ml-8 text-center`}>
|
||||||
<p className={'text-sm'}>{database.connectionString}</p>
|
<p css={tw`text-sm`}>{database.connectionString}</p>
|
||||||
<p className={'mt-1 text-2xs text-neutral-500 uppercase select-none'}>Endpoint</p>
|
<p css={tw`mt-1 text-2xs text-neutral-500 uppercase select-none`}>Endpoint</p>
|
||||||
</div>
|
</div>
|
||||||
<div className={'ml-8 text-center'}>
|
<div css={tw`ml-8 text-center`}>
|
||||||
<p className={'text-sm'}>{database.allowConnectionsFrom}</p>
|
<p css={tw`text-sm`}>{database.allowConnectionsFrom}</p>
|
||||||
<p className={'mt-1 text-2xs text-neutral-500 uppercase select-none'}>Connections from</p>
|
<p css={tw`mt-1 text-2xs text-neutral-500 uppercase select-none`}>Connections from</p>
|
||||||
</div>
|
</div>
|
||||||
<div className={'ml-8 text-center'}>
|
<div css={tw`ml-8 text-center`}>
|
||||||
<p className={'text-sm'}>{database.username}</p>
|
<p css={tw`text-sm`}>{database.username}</p>
|
||||||
<p className={'mt-1 text-2xs text-neutral-500 uppercase select-none'}>Username</p>
|
<p css={tw`mt-1 text-2xs text-neutral-500 uppercase select-none`}>Username</p>
|
||||||
</div>
|
</div>
|
||||||
<div className={'ml-8'}>
|
<div css={tw`ml-8`}>
|
||||||
<button className={'btn btn-sm btn-secondary mr-2'} onClick={() => setConnectionVisible(true)}>
|
<Button isSecondary css={tw`mr-2`} onClick={() => setConnectionVisible(true)}>
|
||||||
<FontAwesomeIcon icon={faEye} fixedWidth={true}/>
|
<FontAwesomeIcon icon={faEye} fixedWidth/>
|
||||||
</button>
|
</Button>
|
||||||
<Can action={'database.delete'}>
|
<Can action={'database.delete'}>
|
||||||
<button className={'btn btn-sm btn-secondary btn-red'} onClick={() => setVisible(true)}>
|
<Button color={'red'} isSecondary onClick={() => setVisible(true)}>
|
||||||
<FontAwesomeIcon icon={faTrashAlt} fixedWidth={true}/>
|
<FontAwesomeIcon icon={faTrashAlt} fixedWidth/>
|
||||||
</button>
|
</Button>
|
||||||
</Can>
|
</Can>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</GreyRowBox>
|
||||||
</React.Fragment>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,6 +11,8 @@ import Can from '@/components/elements/Can';
|
||||||
import useFlash from '@/plugins/useFlash';
|
import useFlash from '@/plugins/useFlash';
|
||||||
import useServer from '@/plugins/useServer';
|
import useServer from '@/plugins/useServer';
|
||||||
import PageContentBlock from '@/components/elements/PageContentBlock';
|
import PageContentBlock from '@/components/elements/PageContentBlock';
|
||||||
|
import tw from 'twin.macro';
|
||||||
|
import Fade from '@/components/elements/Fade';
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const { uuid, featureLimits } = useServer();
|
const { uuid, featureLimits } = useServer();
|
||||||
|
@ -35,11 +37,11 @@ export default () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContentBlock>
|
<PageContentBlock>
|
||||||
<FlashMessageRender byKey={'databases'} className={'mb-4'}/>
|
<FlashMessageRender byKey={'databases'} css={tw`mb-4`}/>
|
||||||
{(!databases.length && loading) ?
|
{(!databases.length && loading) ?
|
||||||
<Spinner size={'large'} centered={true}/>
|
<Spinner size={'large'} centered/>
|
||||||
:
|
:
|
||||||
<CSSTransition classNames={'fade'} timeout={250}>
|
<Fade timeout={250}>
|
||||||
<>
|
<>
|
||||||
{databases.length > 0 ?
|
{databases.length > 0 ?
|
||||||
databases.map((database, index) => (
|
databases.map((database, index) => (
|
||||||
|
@ -50,28 +52,28 @@ export default () => {
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
:
|
:
|
||||||
<p className={'text-center text-sm text-neutral-400'}>
|
<p css={tw`text-center text-sm text-neutral-400`}>
|
||||||
{featureLimits.databases > 0 ?
|
{featureLimits.databases > 0 ?
|
||||||
`It looks like you have no databases.`
|
'It looks like you have no databases.'
|
||||||
:
|
:
|
||||||
`Databases cannot be created for this server.`
|
'Databases cannot be created for this server.'
|
||||||
}
|
}
|
||||||
</p>
|
</p>
|
||||||
}
|
}
|
||||||
<Can action={'database.create'}>
|
<Can action={'database.create'}>
|
||||||
{(featureLimits.databases > 0 && databases.length > 0) &&
|
{(featureLimits.databases > 0 && databases.length > 0) &&
|
||||||
<p className="text-center text-xs text-neutral-400 mt-2">
|
<p css={tw`text-center text-xs text-neutral-400 mt-2`}>
|
||||||
{databases.length} of {featureLimits.databases} databases have been allocated to this server.
|
{databases.length} of {featureLimits.databases} databases have been allocated to this server.
|
||||||
</p>
|
</p>
|
||||||
}
|
}
|
||||||
{featureLimits.databases > 0 && featureLimits.databases !== databases.length &&
|
{featureLimits.databases > 0 && featureLimits.databases !== databases.length &&
|
||||||
<div className={'mt-6 flex justify-end'}>
|
<div css={tw`mt-6 flex justify-end`}>
|
||||||
<CreateDatabaseButton/>
|
<CreateDatabaseButton/>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</Can>
|
</Can>
|
||||||
</>
|
</>
|
||||||
</CSSTransition>
|
</Fade>
|
||||||
}
|
}
|
||||||
</PageContentBlock>
|
</PageContentBlock>
|
||||||
);
|
);
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { ServerContext } from '@/state/server';
|
||||||
import { ServerDatabase } from '@/api/server/getServerDatabases';
|
import { ServerDatabase } from '@/api/server/getServerDatabases';
|
||||||
import { httpErrorToHuman } from '@/api/http';
|
import { httpErrorToHuman } from '@/api/http';
|
||||||
import Button from '@/components/elements/Button';
|
import Button from '@/components/elements/Button';
|
||||||
|
import tw from 'twin.macro';
|
||||||
|
|
||||||
export default ({ databaseId, onUpdate }: {
|
export default ({ databaseId, onUpdate }: {
|
||||||
databaseId: string;
|
databaseId: string;
|
||||||
|
@ -38,7 +39,7 @@ export default ({ databaseId, onUpdate }: {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button className={'btn-secondary mr-2'} onClick={rotate} isLoading={loading}>
|
<Button isSecondary color={'primary'} css={tw`mr-2`} onClick={rotate} isLoading={loading}>
|
||||||
Rotate Password
|
Rotate Password
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in a new issue