Switch to a context store for server stuff to better support things in the future
This commit is contained in:
parent
16e6f3f45f
commit
986285402f
|
@ -0,0 +1,31 @@
|
||||||
|
import http from '@/api/http';
|
||||||
|
|
||||||
|
export interface ServerDatabase {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
username: string;
|
||||||
|
connectionString: string;
|
||||||
|
allowConnectionsFrom: string;
|
||||||
|
password?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const rawDataToServerDatabase = (data: any): ServerDatabase => ({
|
||||||
|
id: data.id,
|
||||||
|
name: data.name,
|
||||||
|
username: data.username,
|
||||||
|
connectionString: `${data.host.address}:${data.host.port}`,
|
||||||
|
allowConnectionsFrom: data.connections_from,
|
||||||
|
password: data.relationships && data.relationships.password ? data.relationships.password.attributes.password : undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default (uuid: string, includePassword: boolean = true): Promise<ServerDatabase[]> => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
http.get(`/api/client/servers/${uuid}/databases`, {
|
||||||
|
params: includePassword ? { include: 'password' } : undefined,
|
||||||
|
})
|
||||||
|
.then(response => resolve(
|
||||||
|
(response.data.data || []).map((item: any) => rawDataToServerDatabase(item.attributes))
|
||||||
|
))
|
||||||
|
.catch(reject);
|
||||||
|
});
|
||||||
|
};
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import MessageBox from '@/components/MessageBox';
|
import MessageBox from '@/components/MessageBox';
|
||||||
import { State, useStoreState } from 'easy-peasy';
|
import { State, useStoreState } from 'easy-peasy';
|
||||||
import { ApplicationState } from '@/state/types';
|
import { ApplicationStore } from '@/state';
|
||||||
|
|
||||||
type Props = Readonly<{
|
type Props = Readonly<{
|
||||||
byKey?: string;
|
byKey?: string;
|
||||||
|
@ -10,7 +10,7 @@ type Props = Readonly<{
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
export default ({ withBottomSpace, spacerClass, byKey }: Props) => {
|
export default ({ withBottomSpace, spacerClass, byKey }: Props) => {
|
||||||
const flashes = useStoreState((state: State<ApplicationState>) => state.flashes.items);
|
const flashes = useStoreState((state: State<ApplicationStore>) => state.flashes.items);
|
||||||
|
|
||||||
let filtered = flashes;
|
let filtered = flashes;
|
||||||
if (byKey) {
|
if (byKey) {
|
||||||
|
|
|
@ -4,14 +4,14 @@ import requestPasswordResetEmail from '@/api/auth/requestPasswordResetEmail';
|
||||||
import { httpErrorToHuman } from '@/api/http';
|
import { httpErrorToHuman } from '@/api/http';
|
||||||
import LoginFormContainer from '@/components/auth/LoginFormContainer';
|
import LoginFormContainer from '@/components/auth/LoginFormContainer';
|
||||||
import { Actions, useStoreActions } from 'easy-peasy';
|
import { Actions, useStoreActions } from 'easy-peasy';
|
||||||
import { ApplicationState } from '@/state/types';
|
|
||||||
import FlashMessageRender from '@/components/FlashMessageRender';
|
import FlashMessageRender from '@/components/FlashMessageRender';
|
||||||
|
import { ApplicationStore } from '@/state';
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const [ isSubmitting, setSubmitting ] = React.useState(false);
|
const [ isSubmitting, setSubmitting ] = React.useState(false);
|
||||||
const [ email, setEmail ] = React.useState('');
|
const [ email, setEmail ] = React.useState('');
|
||||||
|
|
||||||
const { clearFlashes, addFlash } = useStoreActions((actions: Actions<ApplicationState>) => actions.flashes);
|
const { clearFlashes, addFlash } = useStoreActions((actions: Actions<ApplicationStore>) => actions.flashes);
|
||||||
|
|
||||||
const handleFieldUpdate = (e: React.ChangeEvent<HTMLInputElement>) => setEmail(e.target.value);
|
const handleFieldUpdate = (e: React.ChangeEvent<HTMLInputElement>) => setEmail(e.target.value);
|
||||||
|
|
||||||
|
|
|
@ -4,15 +4,15 @@ import loginCheckpoint from '@/api/auth/loginCheckpoint';
|
||||||
import { httpErrorToHuman } from '@/api/http';
|
import { httpErrorToHuman } from '@/api/http';
|
||||||
import LoginFormContainer from '@/components/auth/LoginFormContainer';
|
import LoginFormContainer from '@/components/auth/LoginFormContainer';
|
||||||
import { Actions, useStoreActions } from 'easy-peasy';
|
import { Actions, useStoreActions } from 'easy-peasy';
|
||||||
import { ApplicationState } from '@/state/types';
|
|
||||||
import { StaticContext } from 'react-router';
|
import { StaticContext } from 'react-router';
|
||||||
import FlashMessageRender from '@/components/FlashMessageRender';
|
import FlashMessageRender from '@/components/FlashMessageRender';
|
||||||
|
import { ApplicationStore } from '@/state';
|
||||||
|
|
||||||
export default ({ history, location: { state } }: RouteComponentProps<{}, StaticContext, { token?: string }>) => {
|
export default ({ history, location: { state } }: RouteComponentProps<{}, StaticContext, { token?: string }>) => {
|
||||||
const [ code, setCode ] = useState('');
|
const [ code, setCode ] = useState('');
|
||||||
const [ isLoading, setIsLoading ] = useState(false);
|
const [ isLoading, setIsLoading ] = useState(false);
|
||||||
|
|
||||||
const { clearFlashes, addFlash } = useStoreActions((actions: Actions<ApplicationState>) => actions.flashes);
|
const { clearFlashes, addFlash } = useStoreActions((actions: Actions<ApplicationStore>) => actions.flashes);
|
||||||
|
|
||||||
if (!state || !state.token) {
|
if (!state || !state.token) {
|
||||||
history.replace('/auth/login');
|
history.replace('/auth/login');
|
||||||
|
|
|
@ -5,14 +5,14 @@ import { httpErrorToHuman } from '@/api/http';
|
||||||
import LoginFormContainer from '@/components/auth/LoginFormContainer';
|
import LoginFormContainer from '@/components/auth/LoginFormContainer';
|
||||||
import FlashMessageRender from '@/components/FlashMessageRender';
|
import FlashMessageRender from '@/components/FlashMessageRender';
|
||||||
import { Actions, useStoreActions } from 'easy-peasy';
|
import { Actions, useStoreActions } from 'easy-peasy';
|
||||||
import { ApplicationState } from '@/state/types';
|
import { ApplicationStore } from '@/state';
|
||||||
|
|
||||||
export default ({ history }: RouteComponentProps) => {
|
export default ({ history }: RouteComponentProps) => {
|
||||||
const [ username, setUsername ] = useState('');
|
const [ username, setUsername ] = useState('');
|
||||||
const [ password, setPassword ] = useState('');
|
const [ password, setPassword ] = useState('');
|
||||||
const [ isLoading, setLoading ] = useState(false);
|
const [ isLoading, setLoading ] = useState(false);
|
||||||
|
|
||||||
const { clearFlashes, addFlash } = useStoreActions((actions: Actions<ApplicationState>) => actions.flashes);
|
const { clearFlashes, addFlash } = useStoreActions((actions: Actions<ApplicationStore>) => actions.flashes);
|
||||||
|
|
||||||
const submit = (e: React.FormEvent<HTMLFormElement>) => {
|
const submit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { httpErrorToHuman } from '@/api/http';
|
||||||
import LoginFormContainer from '@/components/auth/LoginFormContainer';
|
import LoginFormContainer from '@/components/auth/LoginFormContainer';
|
||||||
import FlashMessageRender from '@/components/FlashMessageRender';
|
import FlashMessageRender from '@/components/FlashMessageRender';
|
||||||
import { Actions, useStoreActions } from 'easy-peasy';
|
import { Actions, useStoreActions } from 'easy-peasy';
|
||||||
import { ApplicationState } from '@/state/types';
|
import { ApplicationStore } from '@/state';
|
||||||
|
|
||||||
type Props = Readonly<RouteComponentProps<{ token: string }> & {}>;
|
type Props = Readonly<RouteComponentProps<{ token: string }> & {}>;
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ export default (props: Props) => {
|
||||||
const [ password, setPassword ] = useState('');
|
const [ password, setPassword ] = useState('');
|
||||||
const [ passwordConfirm, setPasswordConfirm ] = useState('');
|
const [ passwordConfirm, setPasswordConfirm ] = useState('');
|
||||||
|
|
||||||
const { clearFlashes, addFlash } = useStoreActions((actions: Actions<ApplicationState>) => actions.flashes);
|
const { clearFlashes, addFlash } = useStoreActions((actions: Actions<ApplicationStore>) => actions.flashes);
|
||||||
|
|
||||||
const parsed = parse(props.location.search);
|
const parsed = parse(props.location.search);
|
||||||
if (email.length === 0 && parsed.email) {
|
if (email.length === 0 && parsed.email) {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Actions, State, useStoreActions, useStoreState } from 'easy-peasy';
|
import { Actions, State, useStoreActions, useStoreState } from 'easy-peasy';
|
||||||
import { ApplicationState } from '@/state/types';
|
|
||||||
import { Form, Formik, FormikActions } from 'formik';
|
import { Form, Formik, FormikActions } from 'formik';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
|
import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
|
||||||
import Field from '@/components/elements/Field';
|
import Field from '@/components/elements/Field';
|
||||||
import { httpErrorToHuman } from '@/api/http';
|
import { httpErrorToHuman } from '@/api/http';
|
||||||
|
import { ApplicationStore } from '@/state';
|
||||||
|
|
||||||
interface Values {
|
interface Values {
|
||||||
email: string;
|
email: string;
|
||||||
|
@ -18,10 +18,10 @@ const schema = Yup.object().shape({
|
||||||
});
|
});
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const user = useStoreState((state: State<ApplicationState>) => state.user.data);
|
const user = useStoreState((state: State<ApplicationStore>) => state.user.data);
|
||||||
const updateEmail = useStoreActions((state: Actions<ApplicationState>) => state.user.updateUserEmail);
|
const updateEmail = useStoreActions((state: Actions<ApplicationStore>) => state.user.updateUserEmail);
|
||||||
|
|
||||||
const { clearFlashes, addFlash } = useStoreActions((actions: Actions<ApplicationState>) => actions.flashes);
|
const { clearFlashes, addFlash } = useStoreActions((actions: Actions<ApplicationStore>) => actions.flashes);
|
||||||
|
|
||||||
const submit = (values: Values, { resetForm, setSubmitting }: FormikActions<Values>) => {
|
const submit = (values: Values, { resetForm, setSubmitting }: FormikActions<Values>) => {
|
||||||
clearFlashes('account:email');
|
clearFlashes('account:email');
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Actions, State, useStoreActions, useStoreState } from 'easy-peasy';
|
import { Actions, State, useStoreActions, useStoreState } from 'easy-peasy';
|
||||||
import { ApplicationState } from '@/state/types';
|
|
||||||
import { Form, Formik, FormikActions } from 'formik';
|
import { Form, Formik, FormikActions } from 'formik';
|
||||||
import Field from '@/components/elements/Field';
|
import Field from '@/components/elements/Field';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
|
import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
|
||||||
import updateAccountPassword from '@/api/account/updateAccountPassword';
|
import updateAccountPassword from '@/api/account/updateAccountPassword';
|
||||||
import { httpErrorToHuman } from '@/api/http';
|
import { httpErrorToHuman } from '@/api/http';
|
||||||
|
import { ApplicationStore } from '@/state';
|
||||||
|
|
||||||
interface Values {
|
interface Values {
|
||||||
current: string;
|
current: string;
|
||||||
|
@ -23,8 +23,8 @@ const schema = Yup.object().shape({
|
||||||
});
|
});
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const user = useStoreState((state: State<ApplicationState>) => state.user.data);
|
const user = useStoreState((state: State<ApplicationStore>) => state.user.data);
|
||||||
const { clearFlashes, addFlash } = useStoreActions((actions: Actions<ApplicationState>) => actions.flashes);
|
const { clearFlashes, addFlash } = useStoreActions((actions: Actions<ApplicationStore>) => actions.flashes);
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -2,9 +2,9 @@ import React, { createRef } from 'react';
|
||||||
import { Terminal } from 'xterm';
|
import { 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 { ApplicationState } from '@/state/types';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Websocket } from '@/plugins/Websocket';
|
import { Websocket } from '@/plugins/Websocket';
|
||||||
|
import { ServerStore } from '@/state/server';
|
||||||
|
|
||||||
const theme = {
|
const theme = {
|
||||||
background: 'transparent',
|
background: 'transparent',
|
||||||
|
@ -113,8 +113,8 @@ class Console extends React.PureComponent<Readonly<Props>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
(state: ApplicationState) => ({
|
(state: ServerStore) => ({
|
||||||
connected: state.server.socket.connected,
|
connected: state.socket.connected,
|
||||||
instance: state.server.socket.instance,
|
instance: state.socket.instance,
|
||||||
}),
|
}),
|
||||||
)(Console);
|
)(Console);
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Console from '@/components/server/Console';
|
import Console from '@/components/server/Console';
|
||||||
import { State, useStoreState } from 'easy-peasy';
|
import { ServerContext } from '@/state/server';
|
||||||
import { ApplicationState } from '@/state/types';
|
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const status = useStoreState((state: State<ApplicationState>) => state.server.status);
|
const status = ServerContext.useStoreState(state => state.status.value);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'my-10 flex'}>
|
<div className={'my-10 flex'}>
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
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 (
|
||||||
|
<div className={'my-10'}>
|
||||||
|
<div className={'flex rounded no-underline text-neutral-200 items-center bg-neutral-700 p-4 border border-transparent hover:border-neutral-500'}>
|
||||||
|
<div className={'rounded-full bg-neutral-500 p-3'}>
|
||||||
|
<FontAwesomeIcon icon={faDatabase}/>
|
||||||
|
</div>
|
||||||
|
<div className={'w-1/2 ml-4'}>
|
||||||
|
<p className={'text-lg'}>sfgsfgd</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -1,13 +1,12 @@
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { Actions, State, useStoreActions, useStoreState } from 'easy-peasy';
|
|
||||||
import { ApplicationState } from '@/state/types';
|
|
||||||
import { Websocket } from '@/plugins/Websocket';
|
import { Websocket } from '@/plugins/Websocket';
|
||||||
|
import { ServerContext } from '@/state/server';
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const server = useStoreState((state: State<ApplicationState>) => state.server.data);
|
const server = ServerContext.useStoreState(state => state.server.data);
|
||||||
const instance = useStoreState((state: State<ApplicationState>) => state.server.socket.instance);
|
const instance = ServerContext.useStoreState(state => state.socket.instance);
|
||||||
const setServerStatus = useStoreActions((actions: Actions<ApplicationState>) => actions.server.setServerStatus);
|
const setServerStatus = ServerContext.useStoreActions(actions => actions.status.setServerStatus);
|
||||||
const { setInstance, setConnectionState } = useStoreActions((actions: Actions<ApplicationState>) => actions.server.socket);
|
const { setInstance, setConnectionState } = ServerContext.useStoreActions(actions => actions.socket);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// If there is already an instance or there is no server, just exit out of this process
|
// If there is already an instance or there is no server, just exit out of this process
|
||||||
|
@ -20,7 +19,7 @@ export default () => {
|
||||||
|
|
||||||
const socket = new Websocket(
|
const socket = new Websocket(
|
||||||
`wss://wings.pterodactyl.test:8080/api/servers/${server.uuid}/ws`,
|
`wss://wings.pterodactyl.test:8080/api/servers/${server.uuid}/ws`,
|
||||||
'CC8kHCuMkXPosgzGO6d37wvhNcksWxG6kTrA'
|
'CC8kHCuMkXPosgzGO6d37wvhNcksWxG6kTrA',
|
||||||
);
|
);
|
||||||
|
|
||||||
socket.on('SOCKET_OPEN', () => setConnectionState(true));
|
socket.on('SOCKET_OPEN', () => setConnectionState(true));
|
||||||
|
|
|
@ -3,14 +3,16 @@ import { NavLink, Route, RouteComponentProps, Switch } from 'react-router-dom';
|
||||||
import NavigationBar from '@/components/NavigationBar';
|
import NavigationBar from '@/components/NavigationBar';
|
||||||
import ServerConsole from '@/components/server/ServerConsole';
|
import ServerConsole from '@/components/server/ServerConsole';
|
||||||
import TransitionRouter from '@/TransitionRouter';
|
import TransitionRouter from '@/TransitionRouter';
|
||||||
import { Actions, State, useStoreActions, useStoreState } from 'easy-peasy';
|
|
||||||
import { ApplicationState } from '@/state/types';
|
|
||||||
import Spinner from '@/components/elements/Spinner';
|
import Spinner from '@/components/elements/Spinner';
|
||||||
import WebsocketHandler from '@/components/server/WebsocketHandler';
|
import WebsocketHandler from '@/components/server/WebsocketHandler';
|
||||||
|
import ServerDatabases from '@/components/server/ServerDatabases';
|
||||||
|
import { ServerContext } from '@/state/server';
|
||||||
|
import { Provider } from 'react-redux';
|
||||||
|
|
||||||
export default ({ match, location }: RouteComponentProps<{ id: string }>) => {
|
const ServerRouter = ({ match, location }: RouteComponentProps<{ id: string }>) => {
|
||||||
const server = useStoreState((state: State<ApplicationState>) => state.server.data);
|
const server = ServerContext.useStoreState(state => state.server.data);
|
||||||
const { clearServerState, getServer } = useStoreActions((actions: Actions<ApplicationState>) => actions.server);
|
const getServer = ServerContext.useStoreActions(actions => actions.server.getServer);
|
||||||
|
const clearServerState = ServerContext.useStoreActions(actions => actions.clearServerState);
|
||||||
|
|
||||||
if (!server) {
|
if (!server) {
|
||||||
getServer(match.params.id);
|
getServer(match.params.id);
|
||||||
|
@ -31,22 +33,31 @@ export default ({ match, location }: RouteComponentProps<{ id: string }>) => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<TransitionRouter>
|
<Provider store={ServerContext.useStore()}>
|
||||||
<div className={'w-full mx-auto'} style={{ maxWidth: '1200px' }}>
|
<TransitionRouter>
|
||||||
{!server ?
|
<div className={'w-full mx-auto'} style={{ maxWidth: '1200px' }}>
|
||||||
<div className={'flex justify-center m-20'}>
|
{!server ?
|
||||||
<Spinner large={true}/>
|
<div className={'flex justify-center m-20'}>
|
||||||
</div>
|
<Spinner large={true}/>
|
||||||
:
|
</div>
|
||||||
<React.Fragment>
|
:
|
||||||
<WebsocketHandler/>
|
<React.Fragment>
|
||||||
<Switch location={location}>
|
<WebsocketHandler/>
|
||||||
<Route path={`${match.path}`} component={ServerConsole} exact/>
|
<Switch location={location}>
|
||||||
</Switch>
|
<Route path={`${match.path}`} component={ServerConsole} exact/>
|
||||||
</React.Fragment>
|
<Route path={`${match.path}/databases`} component={ServerDatabases}/>
|
||||||
}
|
</Switch>
|
||||||
</div>
|
</React.Fragment>
|
||||||
</TransitionRouter>
|
}
|
||||||
|
</div>
|
||||||
|
</TransitionRouter>
|
||||||
|
</Provider>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default (props: RouteComponentProps<any>) => (
|
||||||
|
<ServerContext.Provider>
|
||||||
|
<ServerRouter {...props}/>
|
||||||
|
</ServerContext.Provider>
|
||||||
|
);
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { Action, action } from 'easy-peasy';
|
||||||
|
import { FlashMessageType } from '@/components/MessageBox';
|
||||||
|
|
||||||
|
export interface FlashStore {
|
||||||
|
items: FlashMessage[];
|
||||||
|
addFlash: Action<FlashStore, FlashMessage>;
|
||||||
|
clearFlashes: Action<FlashStore, string | void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FlashMessage {
|
||||||
|
id?: string;
|
||||||
|
key?: string;
|
||||||
|
type: FlashMessageType;
|
||||||
|
title?: string;
|
||||||
|
message: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const flashes: FlashStore = {
|
||||||
|
items: [],
|
||||||
|
addFlash: action((state, payload) => {
|
||||||
|
state.items.push(payload);
|
||||||
|
}),
|
||||||
|
clearFlashes: action((state, payload) => {
|
||||||
|
state.items = payload ? state.items.filter(flashes => flashes.key !== payload) : [];
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
export default flashes;
|
|
@ -1,13 +1,15 @@
|
||||||
import { createStore } from 'easy-peasy';
|
import { createStore } from 'easy-peasy';
|
||||||
import { ApplicationState } from '@/state/types';
|
import flashes, { FlashStore } from '@/state/flashes';
|
||||||
import flashes from '@/state/models/flashes';
|
import user, { UserStore } from '@/state/user';
|
||||||
import user from '@/state/models/user';
|
|
||||||
import server from '@/state/models/server';
|
|
||||||
|
|
||||||
const state: ApplicationState = {
|
export interface ApplicationStore {
|
||||||
|
flashes: FlashStore;
|
||||||
|
user: UserStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
const state: ApplicationStore = {
|
||||||
flashes,
|
flashes,
|
||||||
user,
|
user,
|
||||||
server,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const store = createStore(state);
|
export const store = createStore(state);
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
import { action } from 'easy-peasy';
|
|
||||||
import { FlashState } from '@/state/types';
|
|
||||||
|
|
||||||
const flashes: FlashState = {
|
|
||||||
items: [],
|
|
||||||
addFlash: action((state, payload) => {
|
|
||||||
state.items.push(payload);
|
|
||||||
}),
|
|
||||||
clearFlashes: action((state, payload) => {
|
|
||||||
state.items = payload ? state.items.filter(flashes => flashes.key !== payload) : [];
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
export default flashes;
|
|
|
@ -1,43 +0,0 @@
|
||||||
import getServer, { Server } from '@/api/server/getServer';
|
|
||||||
import { action, Action, thunk, Thunk } from 'easy-peasy';
|
|
||||||
import socket, { SocketState } from './socket';
|
|
||||||
|
|
||||||
export type ServerStatus = 'offline' | 'starting' | 'stopping' | 'running';
|
|
||||||
|
|
||||||
export interface ServerState {
|
|
||||||
data?: Server;
|
|
||||||
status: ServerStatus;
|
|
||||||
socket: SocketState;
|
|
||||||
getServer: Thunk<ServerState, string, {}, any, Promise<void>>;
|
|
||||||
setServer: Action<ServerState, Server>;
|
|
||||||
setServerStatus: Action<ServerState, ServerStatus>;
|
|
||||||
clearServerState: Action<ServerState>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const server: ServerState = {
|
|
||||||
socket,
|
|
||||||
status: 'offline',
|
|
||||||
getServer: thunk(async (actions, payload) => {
|
|
||||||
const server = await getServer(payload);
|
|
||||||
actions.setServer(server);
|
|
||||||
}),
|
|
||||||
setServer: action((state, payload) => {
|
|
||||||
state.data = payload;
|
|
||||||
}),
|
|
||||||
setServerStatus: action((state, payload) => {
|
|
||||||
state.status = payload;
|
|
||||||
}),
|
|
||||||
clearServerState: action(state => {
|
|
||||||
state.data = undefined;
|
|
||||||
|
|
||||||
if (state.socket.instance) {
|
|
||||||
state.socket.instance.removeAllListeners();
|
|
||||||
state.socket.instance.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
state.socket.instance = null;
|
|
||||||
state.socket.connected = false;
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
export default server;
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
import getServer, { Server } from '@/api/server/getServer';
|
||||||
|
import { action, Action, createContextStore, thunk, Thunk } from 'easy-peasy';
|
||||||
|
import socket, { SocketStore } from './socket';
|
||||||
|
|
||||||
|
export type ServerStatus = 'offline' | 'starting' | 'stopping' | 'running';
|
||||||
|
|
||||||
|
interface ServerDataStore {
|
||||||
|
data?: Server;
|
||||||
|
getServer: Thunk<ServerDataStore, string, {}, any, Promise<void>>;
|
||||||
|
setServer: Action<ServerDataStore, Server>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const server: ServerDataStore = {
|
||||||
|
getServer: thunk(async (actions, payload) => {
|
||||||
|
const server = await getServer(payload);
|
||||||
|
actions.setServer(server);
|
||||||
|
}),
|
||||||
|
setServer: action((state, payload) => {
|
||||||
|
state.data = payload;
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
interface ServerStatusStore {
|
||||||
|
value: ServerStatus;
|
||||||
|
setServerStatus: Action<ServerStatusStore, ServerStatus>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const status: ServerStatusStore = {
|
||||||
|
value: 'offline',
|
||||||
|
setServerStatus: action((state, payload) => {
|
||||||
|
state.value = payload;
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface ServerStore {
|
||||||
|
server: ServerDataStore;
|
||||||
|
socket: SocketStore;
|
||||||
|
status: ServerStatusStore;
|
||||||
|
clearServerState: Action<ServerStore>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ServerContext = createContextStore<ServerStore>({
|
||||||
|
server,
|
||||||
|
socket,
|
||||||
|
status,
|
||||||
|
clearServerState: action(state => {
|
||||||
|
state.server.data = undefined;
|
||||||
|
|
||||||
|
if (state.socket.instance) {
|
||||||
|
state.socket.instance.removeAllListeners();
|
||||||
|
state.socket.instance.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
state.socket.instance = null;
|
||||||
|
state.socket.connected = false;
|
||||||
|
}),
|
||||||
|
}, { name: 'ServerStore' });
|
|
@ -1,14 +1,14 @@
|
||||||
import { Action, action } from 'easy-peasy';
|
import { Action, action } from 'easy-peasy';
|
||||||
import { Websocket } from '@/plugins/Websocket';
|
import { Websocket } from '@/plugins/Websocket';
|
||||||
|
|
||||||
export interface SocketState {
|
export interface SocketStore {
|
||||||
instance: Websocket | null;
|
instance: Websocket | null;
|
||||||
connected: boolean;
|
connected: boolean;
|
||||||
setInstance: Action<SocketState, Websocket | null>;
|
setInstance: Action<SocketStore, Websocket | null>;
|
||||||
setConnectionState: Action<SocketState, boolean>;
|
setConnectionState: Action<SocketStore, boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const socket: SocketState = {
|
const socket: SocketStore = {
|
||||||
instance: null,
|
instance: null,
|
||||||
connected: false,
|
connected: false,
|
||||||
setInstance: action((state, payload) => {
|
setInstance: action((state, payload) => {
|
|
@ -1,24 +0,0 @@
|
||||||
import { FlashMessageType } from '@/components/MessageBox';
|
|
||||||
import { Action } from 'easy-peasy';
|
|
||||||
import { UserState } from '@/state/models/user';
|
|
||||||
import { ServerState } from '@/state/models/server';
|
|
||||||
|
|
||||||
export interface ApplicationState {
|
|
||||||
flashes: FlashState;
|
|
||||||
user: UserState;
|
|
||||||
server: ServerState;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FlashState {
|
|
||||||
items: FlashMessage[];
|
|
||||||
addFlash: Action<FlashState, FlashMessage>;
|
|
||||||
clearFlashes: Action<FlashState, string | void>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FlashMessage {
|
|
||||||
id?: string;
|
|
||||||
key?: string;
|
|
||||||
type: FlashMessageType;
|
|
||||||
title?: string;
|
|
||||||
message: string;
|
|
||||||
}
|
|
|
@ -12,14 +12,14 @@ export interface UserData {
|
||||||
updatedAt: Date;
|
updatedAt: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UserState {
|
export interface UserStore {
|
||||||
data?: UserData;
|
data?: UserData;
|
||||||
setUserData: Action<UserState, UserData>;
|
setUserData: Action<UserStore, UserData>;
|
||||||
updateUserData: Action<UserState, Partial<UserData>>;
|
updateUserData: Action<UserStore, Partial<UserData>>;
|
||||||
updateUserEmail: Thunk<UserState, { email: string; password: string }, any, {}, Promise<void>>;
|
updateUserEmail: Thunk<UserStore, { email: string; password: string }, any, {}, Promise<void>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const user: UserState = {
|
const user: UserStore = {
|
||||||
data: undefined,
|
data: undefined,
|
||||||
setUserData: action((state, payload) => {
|
setUserData: action((state, payload) => {
|
||||||
state.data = payload;
|
state.data = payload;
|
Loading…
Reference in New Issue