forked from Alex/Pterodactyl-Panel
Get compilation back to working
This commit is contained in:
parent
2193916fe4
commit
94e3acb9c4
@ -36,6 +36,9 @@ rules:
|
|||||||
comma-dangle:
|
comma-dangle:
|
||||||
- error
|
- error
|
||||||
- always-multiline
|
- always-multiline
|
||||||
|
array-bracket-spacing:
|
||||||
|
- warn
|
||||||
|
- always
|
||||||
"react-hooks/rules-of-hooks":
|
"react-hooks/rules-of-hooks":
|
||||||
- error
|
- error
|
||||||
"react-hooks/exhaustive-deps": 0
|
"react-hooks/exhaustive-deps": 0
|
||||||
@ -45,6 +48,8 @@ rules:
|
|||||||
"@typescript-eslint/no-unused-vars": 0
|
"@typescript-eslint/no-unused-vars": 0
|
||||||
"@typescript-eslint/no-explicit-any": 0
|
"@typescript-eslint/no-explicit-any": 0
|
||||||
"@typescript-eslint/no-non-null-assertion": 0
|
"@typescript-eslint/no-non-null-assertion": 0
|
||||||
|
# @todo this would be nice to have, but don't want to deal with the warning spam at the moment.
|
||||||
|
"@typescript-eslint/explicit-module-boundary-types": 0
|
||||||
no-restricted-imports:
|
no-restricted-imports:
|
||||||
- error
|
- error
|
||||||
- paths:
|
- paths:
|
||||||
|
@ -2,15 +2,11 @@ import React from 'react';
|
|||||||
import { Route } from 'react-router';
|
import { Route } from 'react-router';
|
||||||
import { CSSTransition, TransitionGroup } from 'react-transition-group';
|
import { CSSTransition, TransitionGroup } from 'react-transition-group';
|
||||||
|
|
||||||
type Props = Readonly<{
|
const TransitionRouter: React.FC = ({ children }) => (
|
||||||
children: React.ReactNode;
|
|
||||||
}>;
|
|
||||||
|
|
||||||
export default ({ children }: Props) => (
|
|
||||||
<Route
|
<Route
|
||||||
render={({ location }) => (
|
render={({ location }) => (
|
||||||
<TransitionGroup className={'route-transition-group'}>
|
<TransitionGroup className={'route-transition-group'}>
|
||||||
<CSSTransition key={location.key} timeout={250} in={true} appear={true} classNames={'fade'}>
|
<CSSTransition key={location.key} timeout={250} in appear classNames={'fade'}>
|
||||||
<section>
|
<section>
|
||||||
{children}
|
{children}
|
||||||
</section>
|
</section>
|
||||||
@ -19,3 +15,5 @@ export default ({ children }: Props) => (
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export default TransitionRouter;
|
||||||
|
@ -8,9 +8,9 @@ import ServerRouter from '@/routers/ServerRouter';
|
|||||||
import AuthenticationRouter from '@/routers/AuthenticationRouter';
|
import AuthenticationRouter from '@/routers/AuthenticationRouter';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import { SiteSettings } from '@/state/settings';
|
import { SiteSettings } from '@/state/settings';
|
||||||
import { DefaultTheme, ThemeProvider } from 'styled-components';
|
|
||||||
import ProgressBar from '@/components/elements/ProgressBar';
|
import ProgressBar from '@/components/elements/ProgressBar';
|
||||||
import NotFound from '@/components/screens/NotFound';
|
import NotFound from '@/components/screens/NotFound';
|
||||||
|
import tw from 'twin.macro';
|
||||||
|
|
||||||
interface ExtendedWindow extends Window {
|
interface ExtendedWindow extends Window {
|
||||||
SiteConfiguration?: SiteSettings;
|
SiteConfiguration?: SiteSettings;
|
||||||
@ -28,16 +28,6 @@ interface ExtendedWindow extends Window {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const theme: DefaultTheme = {
|
|
||||||
breakpoints: {
|
|
||||||
xs: 0,
|
|
||||||
sm: 576,
|
|
||||||
md: 768,
|
|
||||||
lg: 992,
|
|
||||||
xl: 1200,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const { PterodactylUser, SiteConfiguration } = (window as ExtendedWindow);
|
const { PterodactylUser, SiteConfiguration } = (window as ExtendedWindow);
|
||||||
if (PterodactylUser && !store.getState().user.data) {
|
if (PterodactylUser && !store.getState().user.data) {
|
||||||
@ -58,23 +48,21 @@ const App = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={theme}>
|
<StoreProvider store={store}>
|
||||||
<StoreProvider store={store}>
|
<Provider store={store}>
|
||||||
<Provider store={store}>
|
<ProgressBar/>
|
||||||
<ProgressBar/>
|
<div css={tw`mx-auto w-auto`}>
|
||||||
<div className={'mx-auto w-auto'}>
|
<BrowserRouter basename={'/'} key={'root-router'}>
|
||||||
<BrowserRouter basename={'/'} key={'root-router'}>
|
<Switch>
|
||||||
<Switch>
|
<Route path="/server/:id" component={ServerRouter}/>
|
||||||
<Route path="/server/:id" component={ServerRouter}/>
|
<Route path="/auth" component={AuthenticationRouter}/>
|
||||||
<Route path="/auth" component={AuthenticationRouter}/>
|
<Route path="/" component={DashboardRouter}/>
|
||||||
<Route path="/" component={DashboardRouter}/>
|
<Route path={'*'} component={NotFound}/>
|
||||||
<Route path={'*'} component={NotFound}/>
|
</Switch>
|
||||||
</Switch>
|
</BrowserRouter>
|
||||||
</BrowserRouter>
|
</div>
|
||||||
</div>
|
</Provider>
|
||||||
</Provider>
|
</StoreProvider>
|
||||||
</StoreProvider>
|
|
||||||
</ThemeProvider>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6,10 +6,9 @@ import { ApplicationStore } from '@/state';
|
|||||||
type Props = Readonly<{
|
type Props = Readonly<{
|
||||||
byKey?: string;
|
byKey?: string;
|
||||||
spacerClass?: string;
|
spacerClass?: string;
|
||||||
className?: string;
|
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
export default ({ className, spacerClass, byKey }: Props) => {
|
export default ({ spacerClass, byKey }: Props) => {
|
||||||
const flashes = useStoreState((state: State<ApplicationStore>) => state.flashes.items);
|
const flashes = useStoreState((state: State<ApplicationStore>) => state.flashes.items);
|
||||||
|
|
||||||
let filtered = flashes;
|
let filtered = flashes;
|
||||||
@ -22,11 +21,11 @@ export default ({ className, spacerClass, byKey }: Props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={className}>
|
<div>
|
||||||
{
|
{
|
||||||
filtered.map((flash, index) => (
|
filtered.map((flash, index) => (
|
||||||
<React.Fragment key={flash.id || flash.type + flash.message}>
|
<React.Fragment key={flash.id || flash.type + flash.message}>
|
||||||
{index > 0 && <div className={spacerClass || 'mt-2'}></div>}
|
{index > 0 && <div css={tw`${spacerClass || 'mt-2'}`}></div>}
|
||||||
<MessageBox type={flash.type} title={flash.title}>
|
<MessageBox type={flash.type} title={flash.title}>
|
||||||
{flash.message}
|
{flash.message}
|
||||||
</MessageBox>
|
</MessageBox>
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import React, { forwardRef } from 'react';
|
import React, { forwardRef } from 'react';
|
||||||
import { Form } from 'formik';
|
import { Form } from 'formik';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components/macro';
|
||||||
import { breakpoint } from 'styled-components-breakpoint';
|
import { breakpoint } from 'styled-components-breakpoint';
|
||||||
import FlashMessageRender from '@/components/FlashMessageRender';
|
import FlashMessageRender from '@/components/FlashMessageRender';
|
||||||
|
import tw from 'twin.macro';
|
||||||
|
|
||||||
type Props = React.DetailedHTMLProps<React.FormHTMLAttributes<HTMLFormElement>, HTMLFormElement> & {
|
type Props = React.DetailedHTMLProps<React.FormHTMLAttributes<HTMLFormElement>, HTMLFormElement> & {
|
||||||
title?: string;
|
title?: string;
|
||||||
|
@ -3,9 +3,10 @@ import ContentBox from '@/components/elements/ContentBox';
|
|||||||
import UpdatePasswordForm from '@/components/dashboard/forms/UpdatePasswordForm';
|
import UpdatePasswordForm from '@/components/dashboard/forms/UpdatePasswordForm';
|
||||||
import UpdateEmailAddressForm from '@/components/dashboard/forms/UpdateEmailAddressForm';
|
import UpdateEmailAddressForm from '@/components/dashboard/forms/UpdateEmailAddressForm';
|
||||||
import ConfigureTwoFactorForm from '@/components/dashboard/forms/ConfigureTwoFactorForm';
|
import ConfigureTwoFactorForm from '@/components/dashboard/forms/ConfigureTwoFactorForm';
|
||||||
import styled from 'styled-components';
|
|
||||||
import { breakpoint } from 'styled-components-breakpoint';
|
|
||||||
import PageContentBlock from '@/components/elements/PageContentBlock';
|
import PageContentBlock from '@/components/elements/PageContentBlock';
|
||||||
|
import tw from 'twin.macro';
|
||||||
|
import { breakpoint } from '@/theme';
|
||||||
|
import styled from 'styled-components/macro';
|
||||||
|
|
||||||
const Container = styled.div`
|
const Container = styled.div`
|
||||||
${tw`flex flex-wrap my-10`};
|
${tw`flex flex-wrap my-10`};
|
||||||
@ -31,13 +32,13 @@ export default () => {
|
|||||||
<UpdatePasswordForm/>
|
<UpdatePasswordForm/>
|
||||||
</ContentBox>
|
</ContentBox>
|
||||||
<ContentBox
|
<ContentBox
|
||||||
className={'mt-8 md:mt-0 md:ml-8'}
|
css={tw`mt-8 md:mt-0 md:ml-8`}
|
||||||
title={'Update Email Address'}
|
title={'Update Email Address'}
|
||||||
showFlashes={'account:email'}
|
showFlashes={'account:email'}
|
||||||
>
|
>
|
||||||
<UpdateEmailAddressForm/>
|
<UpdateEmailAddressForm/>
|
||||||
</ContentBox>
|
</ContentBox>
|
||||||
<ContentBox className={'xl:ml-8 mt-8 xl:mt-0'} title={'Configure Two Factor'}>
|
<ContentBox css={tw`xl:ml-8 mt-8 xl:mt-0`} title={'Configure Two Factor'}>
|
||||||
<ConfigureTwoFactorForm/>
|
<ConfigureTwoFactorForm/>
|
||||||
</ContentBox>
|
</ContentBox>
|
||||||
</Container>
|
</Container>
|
||||||
|
@ -11,7 +11,8 @@ import { Server } from '@/api/server/getServer';
|
|||||||
import { ApplicationStore } from '@/state';
|
import { ApplicationStore } from '@/state';
|
||||||
import { httpErrorToHuman } from '@/api/http';
|
import { httpErrorToHuman } from '@/api/http';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components/macro';
|
||||||
|
import tw from 'twin.macro';
|
||||||
|
|
||||||
type Props = RequiredModalProps;
|
type Props = RequiredModalProps;
|
||||||
|
|
||||||
@ -102,7 +103,7 @@ export default ({ ...props }: Props) => {
|
|||||||
</FormikFieldWrapper>
|
</FormikFieldWrapper>
|
||||||
</Form>
|
</Form>
|
||||||
{servers.length > 0 &&
|
{servers.length > 0 &&
|
||||||
<div className={'mt-6'}>
|
<div css={tw`mt-6`}>
|
||||||
{
|
{
|
||||||
servers.map(server => (
|
servers.map(server => (
|
||||||
<ServerResult
|
<ServerResult
|
||||||
@ -111,8 +112,8 @@ export default ({ ...props }: Props) => {
|
|||||||
onClick={() => props.onDismissed()}
|
onClick={() => props.onDismissed()}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<p className={'text-sm'}>{server.name}</p>
|
<p css={tw`text-sm`}>{server.name}</p>
|
||||||
<p className={'mt-1 text-xs text-neutral-400'}>
|
<p css={tw`mt-1 text-xs text-neutral-400`}>
|
||||||
{
|
{
|
||||||
server.allocations.filter(alloc => alloc.default).map(allocation => (
|
server.allocations.filter(alloc => alloc.default).map(allocation => (
|
||||||
<span key={allocation.ip + allocation.port.toString()}>{allocation.alias || allocation.ip}:{allocation.port}</span>
|
<span key={allocation.ip + allocation.port.toString()}>{allocation.alias || allocation.ip}:{allocation.port}</span>
|
||||||
@ -120,8 +121,8 @@ export default ({ ...props }: Props) => {
|
|||||||
}
|
}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className={'flex-1 text-right'}>
|
<div css={tw`flex-1 text-right`}>
|
||||||
<span className={'text-xs py-1 px-2 bg-cyan-800 text-cyan-100 rounded'}>
|
<span css={tw`text-xs py-1 px-2 bg-cyan-800 text-cyan-100 rounded`}>
|
||||||
{server.node}
|
{server.node}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,7 +3,7 @@ import useRouter from 'use-react-router';
|
|||||||
import { ServerContext } from '@/state/server';
|
import { ServerContext } from '@/state/server';
|
||||||
import ace, { Editor } from 'brace';
|
import ace, { Editor } from 'brace';
|
||||||
import getFileContents from '@/api/server/files/getFileContents';
|
import getFileContents from '@/api/server/files/getFileContents';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components/macro';
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
require('brace/ext/modelist');
|
require('brace/ext/modelist');
|
||||||
@ -113,7 +113,7 @@ export default ({ style, initialContent, initialModePath, fetchContent, onConten
|
|||||||
return (
|
return (
|
||||||
<EditorContainer style={style}>
|
<EditorContainer style={style}>
|
||||||
<div id={'editor'} ref={ref}/>
|
<div id={'editor'} ref={ref}/>
|
||||||
<div className={'absolute pin-r pin-b z-50'}>
|
<div className={'absolute right-0 bottom-0 z-50'}>
|
||||||
<div className={'m-3 rounded bg-neutral-900 border border-black'}>
|
<div className={'m-3 rounded bg-neutral-900 border border-black'}>
|
||||||
<select
|
<select
|
||||||
className={'input-dark'}
|
className={'input-dark'}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React, { useEffect, useRef, useState } from 'react';
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
import { CSSTransition } from 'react-transition-group';
|
import { CSSTransition } from 'react-transition-group';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components/macro';
|
||||||
|
import tw from 'twin.macro';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
@ -12,10 +13,7 @@ export const DropdownButtonRow = styled.button<{ danger?: boolean }>`
|
|||||||
transition: 150ms all ease;
|
transition: 150ms all ease;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
${props => props.danger
|
${props => props.danger ? tw`text-red-700 bg-red-100` : tw`text-neutral-700 bg-neutral-100`};
|
||||||
? tw`text-red-700 bg-red-100`
|
|
||||||
: tw`text-neutral-700 bg-neutral-100`
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ const InputSpinner = ({ visible, children }: { visible: boolean, children: React
|
|||||||
appear={true}
|
appear={true}
|
||||||
classNames={'fade'}
|
classNames={'fade'}
|
||||||
>
|
>
|
||||||
<div className={'absolute pin-r h-full flex items-center justify-end pr-3'}>
|
<div className={'absolute right-0 h-full flex items-center justify-end pr-3'}>
|
||||||
<Spinner size={'tiny'}/>
|
<Spinner size={'tiny'}/>
|
||||||
</div>
|
</div>
|
||||||
</CSSTransition>
|
</CSSTransition>
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import React, { useEffect, useRef, useState } from 'react';
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components/macro';
|
||||||
import { useStoreActions, useStoreState } from 'easy-peasy';
|
import { useStoreActions, useStoreState } from 'easy-peasy';
|
||||||
import { randomInt } from '@/helpers';
|
import { randomInt } from '@/helpers';
|
||||||
import { CSSTransition } from 'react-transition-group';
|
import { CSSTransition } from 'react-transition-group';
|
||||||
|
import tw from 'twin.macro';
|
||||||
|
|
||||||
const BarFill = styled.div`
|
const BarFill = styled.div`
|
||||||
${tw`h-full bg-cyan-400`};
|
${tw`h-full bg-cyan-400`};
|
||||||
|
@ -13,7 +13,7 @@ interface Props {
|
|||||||
const SpinnerOverlay = ({ size, fixed, visible, backgroundOpacity }: Props) => (
|
const SpinnerOverlay = ({ size, fixed, visible, backgroundOpacity }: Props) => (
|
||||||
<CSSTransition timeout={150} classNames={'fade'} in={visible} unmountOnExit={true}>
|
<CSSTransition timeout={150} classNames={'fade'} in={visible} unmountOnExit={true}>
|
||||||
<div
|
<div
|
||||||
className={classNames('pin-t pin-l flex items-center justify-center w-full h-full rounded', {
|
className={classNames('top-0 left-0 flex items-center justify-center w-full h-full rounded', {
|
||||||
absolute: !fixed,
|
absolute: !fixed,
|
||||||
fixed: fixed,
|
fixed: fixed,
|
||||||
})}
|
})}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components/macro';
|
||||||
import v4 from 'uuid/v4';
|
import v4 from 'uuid/v4';
|
||||||
import classNames from 'classnames';
|
import tw from 'twin.macro';
|
||||||
|
|
||||||
const ToggleContainer = styled.div`
|
const ToggleContainer = styled.div`
|
||||||
${tw`relative select-none w-12 leading-normal`};
|
${tw`relative select-none w-12 leading-normal`};
|
||||||
@ -47,8 +47,8 @@ const Switch = ({ name, label, description, defaultChecked, onChange, children }
|
|||||||
const uuid = useMemo(() => v4(), []);
|
const uuid = useMemo(() => v4(), []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'flex items-center'}>
|
<div css={tw`flex items-center`}>
|
||||||
<ToggleContainer className={'flex-none'}>
|
<ToggleContainer css={tw`flex-none`}>
|
||||||
{children
|
{children
|
||||||
|| <input
|
|| <input
|
||||||
id={uuid}
|
id={uuid}
|
||||||
@ -61,12 +61,15 @@ const Switch = ({ name, label, description, defaultChecked, onChange, children }
|
|||||||
<label htmlFor={uuid}/>
|
<label htmlFor={uuid}/>
|
||||||
</ToggleContainer>
|
</ToggleContainer>
|
||||||
{(label || description) &&
|
{(label || description) &&
|
||||||
<div className={'ml-4 w-full'}>
|
<div css={tw`ml-4 w-full`}>
|
||||||
{label &&
|
{label &&
|
||||||
<label
|
<label
|
||||||
className={classNames('input-dark-label cursor-pointer', { 'mb-0': !!description })}
|
css={[ tw`cursor-pointer`, !!description && tw`mb-0` ]}
|
||||||
|
className={'input-dark-label'}
|
||||||
htmlFor={uuid}
|
htmlFor={uuid}
|
||||||
>{label}</label>
|
>
|
||||||
|
{label}
|
||||||
|
</label>
|
||||||
}
|
}
|
||||||
{description &&
|
{description &&
|
||||||
<p className={'input-help'}>
|
<p className={'input-help'}>
|
||||||
|
@ -4,7 +4,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|||||||
import { faArrowLeft } from '@fortawesome/free-solid-svg-icons/faArrowLeft';
|
import { faArrowLeft } from '@fortawesome/free-solid-svg-icons/faArrowLeft';
|
||||||
import { faSyncAlt } from '@fortawesome/free-solid-svg-icons/faSyncAlt';
|
import { faSyncAlt } from '@fortawesome/free-solid-svg-icons/faSyncAlt';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components/macro';
|
||||||
|
import tw from 'twin.macro';
|
||||||
|
|
||||||
interface BaseProps {
|
interface BaseProps {
|
||||||
title: string;
|
title: string;
|
||||||
@ -42,10 +43,10 @@ const ActionButton = styled.button`
|
|||||||
|
|
||||||
export default ({ title, image, message, onBack, onRetry }: Props) => (
|
export default ({ title, image, message, onBack, onRetry }: Props) => (
|
||||||
<PageContentBlock>
|
<PageContentBlock>
|
||||||
<div className={'flex justify-center'}>
|
<div css={tw`flex justify-center`}>
|
||||||
<div className={'w-full sm:w-3/4 md:w-1/2 p-12 md:p-20 bg-neutral-100 rounded-lg shadow-lg text-center relative'}>
|
<div css={tw`w-full sm:w-3/4 md:w-1/2 p-12 md:p-20 bg-neutral-100 rounded-lg shadow-lg text-center relative`}>
|
||||||
{(typeof onBack === 'function' || typeof onRetry === 'function') &&
|
{(typeof onBack === 'function' || typeof onRetry === 'function') &&
|
||||||
<div className={'absolute pin-l pin-t ml-4 mt-4'}>
|
<div css={tw`absolute left-0 top-0 ml-4 mt-4`}>
|
||||||
<ActionButton
|
<ActionButton
|
||||||
onClick={() => onRetry ? onRetry() : (onBack ? onBack() : null)}
|
onClick={() => onRetry ? onRetry() : (onBack ? onBack() : null)}
|
||||||
className={classNames('btn btn-primary', { 'hover:spin': !!onRetry })}
|
className={classNames('btn btn-primary', { 'hover:spin': !!onRetry })}
|
||||||
@ -54,9 +55,9 @@ export default ({ title, image, message, onBack, onRetry }: Props) => (
|
|||||||
</ActionButton>
|
</ActionButton>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<img src={image} className={'w-2/3 h-auto select-none'}/>
|
<img src={image} css={tw`w-2/3 h-auto select-none`}/>
|
||||||
<h2 className={'mt-6 text-neutral-900 font-bold'}>{title}</h2>
|
<h2 css={tw`mt-6 text-neutral-900 font-bold`}>{title}</h2>
|
||||||
<p className={'text-sm text-neutral-700 mt-2'}>
|
<p css={tw`text-sm text-neutral-700 mt-2`}>
|
||||||
{message}
|
{message}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components/macro';
|
||||||
import ScreenBlock from '@/components/screens/ScreenBlock';
|
import ScreenBlock from '@/components/screens/ScreenBlock';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
@ -3,10 +3,11 @@ import { ITerminalOptions, Terminal } from 'xterm';
|
|||||||
import * as TerminalFit from 'xterm/lib/addons/fit/fit';
|
import * as TerminalFit from 'xterm/lib/addons/fit/fit';
|
||||||
import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
|
import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
|
||||||
import { ServerContext } from '@/state/server';
|
import { ServerContext } from '@/state/server';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components/macro';
|
||||||
import Can from '@/components/elements/Can';
|
import Can from '@/components/elements/Can';
|
||||||
import { usePermissions } from '@/plugins/usePermissions';
|
import { usePermissions } from '@/plugins/usePermissions';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import tw from 'twin.macro';
|
||||||
|
|
||||||
const theme = {
|
const theme = {
|
||||||
background: 'transparent',
|
background: 'transparent',
|
||||||
|
@ -8,7 +8,7 @@ import { Actions, useStoreActions, useStoreState } from 'easy-peasy';
|
|||||||
import { ApplicationStore } from '@/state';
|
import { ApplicationStore } from '@/state';
|
||||||
import TitledGreyBox from '@/components/elements/TitledGreyBox';
|
import TitledGreyBox from '@/components/elements/TitledGreyBox';
|
||||||
import Checkbox from '@/components/elements/Checkbox';
|
import Checkbox from '@/components/elements/Checkbox';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components/macro';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import createOrUpdateSubuser from '@/api/server/users/createOrUpdateSubuser';
|
import createOrUpdateSubuser from '@/api/server/users/createOrUpdateSubuser';
|
||||||
import { ServerContext } from '@/state/server';
|
import { ServerContext } from '@/state/server';
|
||||||
@ -17,6 +17,7 @@ import FlashMessageRender from '@/components/FlashMessageRender';
|
|||||||
import Can from '@/components/elements/Can';
|
import Can from '@/components/elements/Can';
|
||||||
import { usePermissions } from '@/plugins/usePermissions';
|
import { usePermissions } from '@/plugins/usePermissions';
|
||||||
import { useDeepMemo } from '@/plugins/useDeepMemo';
|
import { useDeepMemo } from '@/plugins/useDeepMemo';
|
||||||
|
import tw from 'twin.macro';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
subuser?: Subuser;
|
subuser?: Subuser;
|
||||||
@ -82,17 +83,17 @@ const EditSubuserModal = forwardRef<HTMLHeadingElement, Props>(({ subuser, ...pr
|
|||||||
'Create new subuser'
|
'Create new subuser'
|
||||||
}
|
}
|
||||||
</h3>
|
</h3>
|
||||||
<FlashMessageRender byKey={'user:edit'} className={'mt-4'}/>
|
<FlashMessageRender byKey={'user:edit'} css={tw`mt-4`}/>
|
||||||
{(!user.rootAdmin && loggedInPermissions[0] !== '*') &&
|
{(!user.rootAdmin && loggedInPermissions[0] !== '*') &&
|
||||||
<div className={'mt-4 pl-4 py-2 border-l-4 border-cyan-400'}>
|
<div css={tw`mt-4 pl-4 py-2 border-l-4 border-cyan-400`}>
|
||||||
<p className={'text-sm text-neutral-300'}>
|
<p css={tw`text-sm text-neutral-300`}>
|
||||||
Only permissions which your account is currently assigned may be selected when creating or
|
Only permissions which your account is currently assigned may be selected when creating or
|
||||||
modifying other users.
|
modifying other users.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
{!subuser &&
|
{!subuser &&
|
||||||
<div className={'mt-6'}>
|
<div css={tw`mt-6`}>
|
||||||
<Field
|
<Field
|
||||||
name={'email'}
|
name={'email'}
|
||||||
label={'User Email'}
|
label={'User Email'}
|
||||||
@ -100,13 +101,13 @@ const EditSubuserModal = forwardRef<HTMLHeadingElement, Props>(({ subuser, ...pr
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<div className={'my-6'}>
|
<div css={tw`my-6`}>
|
||||||
{Object.keys(permissions).filter(key => key !== 'websocket').map((key, index) => (
|
{Object.keys(permissions).filter(key => key !== 'websocket').map((key, index) => (
|
||||||
<TitledGreyBox
|
<TitledGreyBox
|
||||||
key={key}
|
key={key}
|
||||||
title={
|
title={
|
||||||
<div className={'flex items-center'}>
|
<div css={tw`flex items-center`}>
|
||||||
<p className={'text-sm uppercase flex-1'}>{key}</p>
|
<p css={tw`text-sm uppercase flex-1`}>{key}</p>
|
||||||
{canEditUser && editablePermissions.indexOf(key) >= 0 &&
|
{canEditUser && editablePermissions.indexOf(key) >= 0 &&
|
||||||
<input
|
<input
|
||||||
type={'checkbox'}
|
type={'checkbox'}
|
||||||
@ -134,7 +135,7 @@ const EditSubuserModal = forwardRef<HTMLHeadingElement, Props>(({ subuser, ...pr
|
|||||||
}
|
}
|
||||||
className={index !== 0 ? 'mt-4' : undefined}
|
className={index !== 0 ? 'mt-4' : undefined}
|
||||||
>
|
>
|
||||||
<p className={'text-sm text-neutral-400 mb-4'}>
|
<p css={tw`text-sm text-neutral-400 mb-4`}>
|
||||||
{permissions[key].description}
|
{permissions[key].description}
|
||||||
</p>
|
</p>
|
||||||
{Object.keys(permissions[key].keys).map((pkey, index) => (
|
{Object.keys(permissions[key].keys).map((pkey, index) => (
|
||||||
@ -146,21 +147,21 @@ const EditSubuserModal = forwardRef<HTMLHeadingElement, Props>(({ subuser, ...pr
|
|||||||
disabled: !canEditUser || editablePermissions.indexOf(`${key}.${pkey}`) < 0,
|
disabled: !canEditUser || editablePermissions.indexOf(`${key}.${pkey}`) < 0,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<div className={'p-2'}>
|
<div css={tw`p-2`}>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
id={`permission_${key}_${pkey}`}
|
id={`permission_${key}_${pkey}`}
|
||||||
name={'permissions'}
|
name={'permissions'}
|
||||||
value={`${key}.${pkey}`}
|
value={`${key}.${pkey}`}
|
||||||
className={'w-5 h-5 mr-2'}
|
css={tw`w-5 h-5 mr-2`}
|
||||||
disabled={!canEditUser || editablePermissions.indexOf(`${key}.${pkey}`) < 0}
|
disabled={!canEditUser || editablePermissions.indexOf(`${key}.${pkey}`) < 0}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className={'flex-1'}>
|
<div css={tw`flex-1`}>
|
||||||
<span className={'input-dark-label font-medium'}>
|
<span css={tw`font-medium`} className={'input-dark-label'}>
|
||||||
{pkey}
|
{pkey}
|
||||||
</span>
|
</span>
|
||||||
{permissions[key].keys[pkey].length > 0 &&
|
{permissions[key].keys[pkey].length > 0 &&
|
||||||
<p className={'text-xs text-neutral-400 mt-1'}>
|
<p css={tw`text-xs text-neutral-400 mt-1`}>
|
||||||
{permissions[key].keys[pkey]}
|
{permissions[key].keys[pkey]}
|
||||||
</p>
|
</p>
|
||||||
}
|
}
|
||||||
@ -171,7 +172,7 @@ const EditSubuserModal = forwardRef<HTMLHeadingElement, Props>(({ subuser, ...pr
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<Can action={subuser ? 'user.update' : 'user.create'}>
|
<Can action={subuser ? 'user.update' : 'user.create'}>
|
||||||
<div className={'pb-6 flex justify-end'}>
|
<div css={tw`pb-6 flex justify-end`}>
|
||||||
<button className={'btn btn-primary btn-sm'} type={'submit'}>
|
<button className={'btn btn-primary btn-sm'} type={'submit'}>
|
||||||
{subuser ? 'Save' : 'Invite User'}
|
{subuser ? 'Save' : 'Invite User'}
|
||||||
</button>
|
</button>
|
||||||
|
@ -3,8 +3,8 @@ import { BreakpointFunction, createBreakpoint } from 'styled-components-breakpoi
|
|||||||
type Breakpoints = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
type Breakpoints = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
||||||
export const breakpoint: BreakpointFunction<Breakpoints> = createBreakpoint<Breakpoints>({
|
export const breakpoint: BreakpointFunction<Breakpoints> = createBreakpoint<Breakpoints>({
|
||||||
xs: 0,
|
xs: 0,
|
||||||
sm: 640,
|
sm: 576,
|
||||||
md: 768,
|
md: 768,
|
||||||
lg: 1024,
|
lg: 992,
|
||||||
xl: 1280,
|
xl: 1200,
|
||||||
});
|
});
|
||||||
|
@ -22,7 +22,7 @@ div.route-transition-group {
|
|||||||
@apply .relative;
|
@apply .relative;
|
||||||
|
|
||||||
& section {
|
& section {
|
||||||
@apply .absolute .w-full .pin-t .pin-l;
|
@apply .absolute .w-full .top-0 .left-0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*! purgecss end ignore */
|
/*! purgecss end ignore */
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
& > .modal-close-icon {
|
& > .modal-close-icon {
|
||||||
@apply .absolute .pin-r .p-2 .text-white .cursor-pointer .opacity-50;
|
@apply .absolute .right-0 .p-2 .text-white .cursor-pointer .opacity-50;
|
||||||
transition: opacity 150ms linear, transform 150ms ease-in;
|
transition: opacity 150ms linear, transform 150ms ease-in;
|
||||||
top: -2rem;
|
top: -2rem;
|
||||||
|
|
||||||
|
@ -34,9 +34,11 @@ module.exports = {
|
|||||||
'monospace',
|
'monospace',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
|
||||||
extend: {
|
|
||||||
colors: {
|
colors: {
|
||||||
|
transparent: 'transparent',
|
||||||
|
black: 'hsl(210, 27%, 10%)',
|
||||||
|
white: '#ffffff',
|
||||||
|
'basically-white': '#fafafb',
|
||||||
primary: {
|
primary: {
|
||||||
50: 'hsl(202, 100%, 95%)', // lightest
|
50: 'hsl(202, 100%, 95%)', // lightest
|
||||||
100: 'hsl(204, 100%, 86%)', // lighter
|
100: 'hsl(204, 100%, 86%)', // lighter
|
||||||
|
Loading…
Reference in New Issue
Block a user