diff --git a/visions/ui/src/App.tsx b/visions/ui/src/App.tsx
index 9b98110..b6dcf0e 100644
--- a/visions/ui/src/App.tsx
+++ b/visions/ui/src/App.tsx
@@ -1,64 +1,64 @@
-import React, { PropsWithChildren, useContext, useEffect, useState } from 'react';
-import './App.css';
-import { Client } from './client';
-import { createBrowserRouter, RouterProvider } from 'react-router-dom';
-import { DesignPage } from './views/Design/Design';
-import { GmView } from './views/GmView/GmView';
-import { WebsocketProvider } from './components/WebsocketProvider';
-import { PlayerView } from './views/PlayerView/PlayerView';
-import { Admin } from './views/Admin/Admin';
-import Candela from './plugins/Candela';
-import { Authentication } from './views/Authentication/Authentication';
-import { StateContext, StateProvider } from './providers/StateProvider/StateProvider';
+import React, { PropsWithChildren, useContext, useEffect, useState } from 'react'
+import './App.css'
+import { Client } from './client'
+import { createBrowserRouter, RouterProvider } from 'react-router-dom'
+import { DesignPage } from './views/Design/Design'
+import { Admin } from './views/Admin/Admin'
+import Candela from './plugins/Candela'
+import { Authentication } from './views/Authentication/Authentication'
+import { StateContext, StateProvider } from './providers/StateProvider/StateProvider'
+import { MainView } from './views'
-const TEST_CHARSHEET_UUID = "12df9c09-1f2f-4147-8eda-a97bd2a7a803";
+const TEST_CHARSHEET_UUID = "12df9c09-1f2f-4147-8eda-a97bd2a7a803"
interface AppProps {
- client: Client;
+ client: Client
}
const CandelaCharsheet = ({ client }: { client: Client }) => {
- let [sheet, setSheet] = useState(undefined);
+ let [sheet, setSheet] = useState(undefined)
useEffect(
- () => { client.charsheet(TEST_CHARSHEET_UUID).then((c) => setSheet(c)); },
+ () => { client.charsheet(TEST_CHARSHEET_UUID).then((c) => setSheet(c)) },
[client, setSheet]
- );
+ )
return sheet ? :
}
interface AuthedViewProps {
- client: Client;
+ client: Client
}
const AuthedView = ({ client, children }: PropsWithChildren) => {
- const [state, manager] = useContext(StateContext);
+ const [state, manager] = useContext(StateContext)
return (
{
- manager.setAdminPassword(password);
+ manager.setAdminPassword(password)
}} onAuth={(username, password) => manager.auth(username, password)}>
{children}
- );
+ )
}
const App = ({ client }: AppProps) => {
- console.log("rendering app");
- const [websocketUrl, setWebsocketUrl] = useState(undefined);
+ console.log("rendering app")
+ const [websocketUrl, setWebsocketUrl] = useState(undefined)
// useEffect(() => {
// client.registerWebsocket().then((url) => setWebsocketUrl(url))
- // }, [client]);
+ // }, [client])
let router =
createBrowserRouter([
{
path: "/",
- element:
- },
- {
- path: "/gm",
- element: websocketUrl ? :
+ element: (
+
+
+
+
+
+ )
},
{
path: "/admin",
@@ -72,12 +72,12 @@ const App = ({ client }: AppProps) => {
path: "/design",
element:
}
- ]);
+ ])
return (
- );
+ )
}
-export default App;
+export default App
diff --git a/visions/ui/src/client.ts b/visions/ui/src/client.ts
index 37c3e9a..5521429 100644
--- a/visions/ui/src/client.ts
+++ b/visions/ui/src/client.ts
@@ -6,6 +6,7 @@ export type PlayingField = {
export class Client {
private base: URL;
+ private sessionId: string | undefined;
constructor() {
this.base = new URL("http://localhost:8001");
@@ -69,7 +70,9 @@ export class Client {
async auth(username: string, password: string): Promise {
const url = new URL(this.base);
url.pathname = `/api/v1/auth`
- return fetch(url, { method: 'POST', headers: [['Content-Type', 'application/json']], body: JSON.stringify({ 'username': username, 'password': password }) });
+ const response = await fetch(url, { method: 'POST', headers: [['Content-Type', 'application/json']], body: JSON.stringify({ 'username': username, 'password': password }) });
+ const session_id: SessionId = await response.json();
+ return session_id;
}
async health() {
diff --git a/visions/ui/src/components/Profile/Profile.css b/visions/ui/src/components/Profile/Profile.css
new file mode 100644
index 0000000..e69de29
diff --git a/visions/ui/src/components/Profile/Profile.tsx b/visions/ui/src/components/Profile/Profile.tsx
new file mode 100644
index 0000000..9c38a15
--- /dev/null
+++ b/visions/ui/src/components/Profile/Profile.tsx
@@ -0,0 +1,10 @@
+import React from 'react';
+import { Client } from '../../client';
+
+interface ProfileProps {
+ client: Client
+}
+
+export const ProfileElement = ({ client }: ProfileProps) => {
+ return
+}
diff --git a/visions/ui/src/providers/StateProvider/StateProvider.tsx b/visions/ui/src/providers/StateProvider/StateProvider.tsx
index 64a9dc8..6f928fa 100644
--- a/visions/ui/src/providers/StateProvider/StateProvider.tsx
+++ b/visions/ui/src/providers/StateProvider/StateProvider.tsx
@@ -1,51 +1,60 @@
import React, { createContext, PropsWithChildren, useCallback, useEffect, useReducer, useRef } from "react";
-import { Status, Tabletop } from "visions-types";
+import { SessionId, Status, Tabletop } from "visions-types";
import { Client } from "../../client";
import { assertNever } from "../../utils";
-type AuthState = { type: "NoAdmin" } | { type: "Unauthed" } | { type: "Authed", userid: string };
+type AuthState = { type: "NoAdmin" } | { type: "Unauthed" } | { type: "Authed", sessionId: string };
-type LoadingState = { type: "Loading" }
+export enum LoadingState {
+ Loading,
+ Ready,
+}
-type ReadyState = {
- type: "Ready",
+type AppState = {
+ state: LoadingState,
auth: AuthState,
tabletop: Tabletop,
}
-type AppState = LoadingState | ReadyState
-
type Action = { type: "SetAuthState", content: AuthState };
-/*
-const initialState = (): AppState => (
- {
+const initialState = (): AppState => {
+ let state: AppState = {
+ state: LoadingState.Ready,
auth: { type: "NoAdmin" },
- tabletop: { backgroundColor: { red: 0, green: 0, blue: 0 }, backgroundImage: undefined }
+ tabletop: { backgroundColor: { red: 0, green: 0, blue: 0 }, backgroundImage: undefined },
}
-);
-*/
-const initialState = (): AppState => ({ type: "Loading" })
-const loadingReducer = (state: LoadingState, action: Action): AppState => {
- return { type: "Ready", auth: action.content, tabletop: { backgroundColor: { red: 0, green: 0, blue: 0 }, backgroundImage: undefined } }
-}
-
-const readyReducer = (state: ReadyState, action: Action): AppState => {
- return { ...state, auth: action.content }
+ const sessionId = window.localStorage.getItem("sessionId")
+ if (sessionId) {
+ return { ...state, auth: { type: "Authed", sessionId } }
+ } else {
+ return state
+ }
}
const stateReducer = (state: AppState, action: Action): AppState => {
- switch (state.type) {
- case "Loading": {
- return loadingReducer(state, action);
- }
- case "Ready": {
- return readyReducer(state, action);
+ switch (action.type) {
+ case "SetAuthState": {
+ return { ...state, auth: action.content }
}
+ /*
default: {
- assertNever(state);
- return { type: "Loading" };
+ assertNever(action)
+ return state
+ }
+ */
+ }
+}
+
+export const getSessionId = (state: AppState): SessionId | undefined => {
+ switch (state.auth.type) {
+ case "NoAdmin": return undefined
+ case "Unauthed": return undefined
+ case "Authed": return state.auth.sessionId
+ default: {
+ assertNever(state.auth)
+ return undefined
}
}
}
@@ -65,8 +74,6 @@ class StateManager {
const { admin_enabled } = await this.client.health();
if (!admin_enabled) {
this.dispatch({ type: "SetAuthState", content: { type: "NoAdmin" } });
- } else {
- this.dispatch({ type: "SetAuthState", content: { type: "Unauthed" } });
}
}
@@ -80,10 +87,11 @@ class StateManager {
async auth(username: string, password: string) {
if (!this.client || !this.dispatch) return;
- let resp = await this.client.auth(username, password);
- let sessionid = await resp.json();
- console.log("sessionid retrieved", sessionid);
- this.dispatch({ type: "SetAuthState", content: { type: "Authed", sessionid } });
+ let sessionId = await this.client.auth(username, password);
+ if (sessionId) {
+ window.localStorage.setItem("sessionId", sessionId);
+ this.dispatch({ type: "SetAuthState", content: { type: "Authed", sessionId } });
+ }
}
}
diff --git a/visions/ui/src/views/Authentication/Authentication.tsx b/visions/ui/src/views/Authentication/Authentication.tsx
index 95f4be2..baf7d27 100644
--- a/visions/ui/src/views/Authentication/Authentication.tsx
+++ b/visions/ui/src/views/Authentication/Authentication.tsx
@@ -1,5 +1,5 @@
import { PropsWithChildren, useContext, useState } from 'react';
-import { StateContext } from '../../providers/StateProvider/StateProvider';
+import { LoadingState, StateContext } from '../../providers/StateProvider/StateProvider';
import { assertNever } from '../../utils';
import './Authentication.css';
@@ -17,11 +17,11 @@ export const Authentication = ({ onAdminPassword, onAuth, children }: PropsWithC
let [pwField, setPwField] = useState("");
let [state, _] = useContext(StateContext);
- switch (state.type) {
- case "Loading": {
+ switch (state.state) {
+ case LoadingState.Loading: {
return Loading
}
- case "Ready": {
+ case LoadingState.Ready: {
switch (state.auth.type) {
case "NoAdmin": {
return
@@ -53,11 +53,6 @@ export const Authentication = ({ onAdminPassword, onAuth, children }: PropsWithC
return
;
}
}
-
- }
- default: {
- assertNever(state);
- return
}
}
diff --git a/visions/ui/src/views/GmView/GmView.css b/visions/ui/src/views/GmView/GmView.css
deleted file mode 100644
index f3b6a10..0000000
--- a/visions/ui/src/views/GmView/GmView.css
+++ /dev/null
@@ -1,4 +0,0 @@
-.gm-view {
- display: flex;
- width: 100%;
-}
diff --git a/visions/ui/src/views/GmView/GmView.tsx b/visions/ui/src/views/GmView/GmView.tsx
deleted file mode 100644
index 8874f85..0000000
--- a/visions/ui/src/views/GmView/GmView.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-import { useContext, useEffect, useState } from 'react';
-import { Client } from '../../client';
-import { StateContext } from '../../providers/StateProvider/StateProvider';
-import { TabletopElement } from '../../components/Tabletop/Tabletop';
-import { ThumbnailElement } from '../../components/Thumbnail/Thumbnail';
-import { WebsocketContext } from '../../components/WebsocketProvider';
-import './GmView.css';
-import { assertNever } from '../../utils';
-
-interface GmViewProps {
- client: Client
-}
-
-export const GmView = ({ client }: GmViewProps) => {
- const [state, dispatch] = useContext(StateContext);
-
- const [images, setImages] = useState
([]);
- useEffect(() => {
- client.availableImages().then((images) => setImages(images));
- }, [client]);
-
- switch (state.type) {
- case "Loading": return ;
- case "Ready": {
- const backgroundUrl = state.tabletop.backgroundImage ? client.imageUrl(state.tabletop.backgroundImage) : undefined;
- return (
-
- {images.map((imageName) => { client.setBackgroundImage(imageName); }} />)}
-
-
-
)
- }
- default: {
- assertNever(state);
- return ;
- }
- }
-}
-
diff --git a/visions/ui/src/views/Main/Main.css b/visions/ui/src/views/Main/Main.css
new file mode 100644
index 0000000..e69de29
diff --git a/visions/ui/src/views/Main/Main.tsx b/visions/ui/src/views/Main/Main.tsx
new file mode 100644
index 0000000..27ded81
--- /dev/null
+++ b/visions/ui/src/views/Main/Main.tsx
@@ -0,0 +1,16 @@
+import React, { useContext } from 'react';
+import { Client } from '../../client';
+import { getSessionId, StateContext, StateProvider } from '../../providers/StateProvider/StateProvider';
+
+interface MainProps {
+ client: Client
+}
+
+export const MainView = ({ client }: MainProps) => {
+ const [state, manager] = useContext(StateContext)
+
+ const sessionId = getSessionId(state);
+
+ return Profile: {sessionId}
+}
+
diff --git a/visions/ui/src/views/PlayerView/PlayerView.css b/visions/ui/src/views/PlayerView/PlayerView.css
deleted file mode 100644
index daf3bec..0000000
--- a/visions/ui/src/views/PlayerView/PlayerView.css
+++ /dev/null
@@ -1,15 +0,0 @@
-.player-view {
- display: flex;
- width: 100%;
-}
-
-.player-view__left-panel {
- min-width: 100px;
- max-width: 20%;
-}
-
-.player-view__right-panel {
- width: 25%;
-}
-
-
diff --git a/visions/ui/src/views/PlayerView/PlayerView.tsx b/visions/ui/src/views/PlayerView/PlayerView.tsx
deleted file mode 100644
index 017c2c0..0000000
--- a/visions/ui/src/views/PlayerView/PlayerView.tsx
+++ /dev/null
@@ -1,49 +0,0 @@
-import React, { useContext, useEffect, useState } from 'react';
-import './PlayerView.css';
-import { WebsocketContext } from '../../components/WebsocketProvider';
-import { Client } from '../../client';
-import { TabletopElement } from '../../components/Tabletop/Tabletop';
-import Candela from '../../plugins/Candela';
-import { StateContext } from '../../providers/StateProvider/StateProvider';
-import { assertNever } from '../../utils';
-
-const TEST_CHARSHEET_UUID = "12df9c09-1f2f-4147-8eda-a97bd2a7a803";
-
-interface PlayerViewProps {
- client: Client;
-}
-
-export const PlayerView = ({ client }: PlayerViewProps) => {
- const [state, dispatch] = useContext(StateContext);
-
- const [charsheet, setCharsheet] = useState(undefined);
-
- useEffect(
- () => {
- client.charsheet(TEST_CHARSHEET_UUID).then((c) => {
- setCharsheet(c)
- });
- },
- [client, setCharsheet]
- );
-
- switch (state.type) {
- case "Loading": return ;
- case "Ready": {
- const backgroundColor = state.tabletop.backgroundColor;
- const tabletopColorStyle = `rgb(${backgroundColor.red}, ${backgroundColor.green}, ${backgroundColor.blue})`;
- const backgroundUrl = state.tabletop.backgroundImage ? client.imageUrl(state.tabletop.backgroundImage) : undefined;
-
- return ()
- }
- default: {
- assertNever(state);
- return ;
- }
- }
-}
-
diff --git a/visions/ui/src/views/index.ts b/visions/ui/src/views/index.ts
new file mode 100644
index 0000000..0719403
--- /dev/null
+++ b/visions/ui/src/views/index.ts
@@ -0,0 +1,3 @@
+import { MainView } from './Main/Main'
+
+export { MainView }