Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
aec507b
WIP yml files, scripts for convenience, updating documentation.
fyang151 Aug 26, 2025
87db34a
Add web:dev:no-api dev option.
fyang151 Aug 31, 2025
0f383e0
breaking, update deps
fyang151 Aug 31, 2025
0ca0738
WIP bare dark mode UI
fyang151 Sep 3, 2025
d570412
Bare minimum.
fyang151 Sep 7, 2025
df5aa36
WIP use real data for graphs.
fyang151 Sep 8, 2025
7b1c480
WIP export data.
fyang151 Sep 8, 2025
db293d1
Hasty rearrange graphs.
fyang151 Sep 8, 2025
53afa36
Fix some css overflow issues.
fyang151 Sep 8, 2025
7eef7dd
CSS fix.
fyang151 Sep 8, 2025
4ab2ab7
Use actual data for maps.
fyang151 Sep 9, 2025
e280006
Reset button for view historic data.
fyang151 Sep 9, 2025
ee6982d
Misc graph improvements.
fyang151 Sep 9, 2025
40bc2c5
Update stats summary to display no stats.
fyang151 Sep 10, 2025
2d953b5
Misc clean.
fyang151 Sep 10, 2025
162181c
RIP EVERYTHING OUT HAHAHAHAHAHA RIP R IP RIP RIP THE CULLING HAHAHAHAA
fyang151 Sep 10, 2025
7259356
Fix client server mismatch bug, useLayoutEffect
fyang151 Sep 10, 2025
9a3840d
Update title.
fyang151 Sep 10, 2025
cf3f0dc
Underline current tab.
fyang151 Sep 10, 2025
e281c25
Remove some css
fyang151 Sep 11, 2025
6fb2315
Revert necessary files and add clarifying comments
fyang151 Sep 11, 2025
f100755
Transition to AppRouter
fyang151 Sep 18, 2025
38d6549
Split some code.
fyang151 Sep 18, 2025
0526516
WIP light mode
fyang151 Sep 23, 2025
37e008c
Merge main into chore/undockerize-website
fyang151 Sep 29, 2025
9c4b85e
Comment ports in docker-compose.yml and don't run website tests in ci.
fyang151 Sep 29, 2025
e903338
Merge branch 'main' into chore/undockerize-website
SPDonaghy Oct 3, 2025
8123b9e
WIP toggle theme
fyang151 Oct 6, 2025
9e3a01a
Merge chore/undocker-website.
fyang151 Oct 6, 2025
facd693
Add ThemeSyncListener.
fyang151 Oct 26, 2025
a4c34ee
Merge branch 'web/ui-overhaul' into user/fyang151/web-light-mode
fyang151 Nov 1, 2025
639838e
Fix empty localstorage bug.
fyang151 Nov 1, 2025
468ec10
Merge branch 'main' into user/fyang151/web-light-mode
fyang151 Nov 1, 2025
2af8803
Merge branch 'main' into user/fyang151/web-light-mode
fyang151 Nov 1, 2025
99586a2
Merge branch 'main' into user/fyang151/web-light-mode
fyang151 Nov 5, 2025
e534bcf
light!
jjun819 Nov 22, 2025
6aa0002
Merge branch 'main' into user/fyang151/web-light-mode
fyang151 Nov 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 33 additions & 33 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,37 +43,37 @@
"yzhang.markdown-all-in-one",
// "zachflower.uncrustify",

// UBCSailbot
"awesomektvn.toggle-semicolon",
"bierner.github-markdown-preview",
"christian-kohler.path-intellisense",
"cschlosser.doxdocgen",
"DavidAnson.vscode-markdownlint",
"eamodio.gitlens",
// "github.copilot",
"github.vscode-github-actions",
"Gruntfuggly.todo-tree",
"jebbs.plantuml",
"jeff-hykin.better-cpp-syntax",
"KevinRose.vsc-python-indent",
"llvm-vs-code-extensions.vscode-clangd",
"matepek.vscode-catch2-test-adapter",
"mechatroner.rainbow-csv",
"mongodb.mongodb-vscode",
"ranch-hand-robotics.rde-ros-2",
"ms-python.black-formatter",
"ms-python.isort",
"ms-python.vscode-pylance",
"ms-toolsai.jupyter",
"ms-vsliveshare.vsliveshare",
"ms-python.mypy-type-checker",
"njpwerner.autodocstring",
"randomfractalsinc.geo-data-viewer",
"stevejpurves.cucumber",
"streetsidesoftware.code-spell-checker",
"vscode-icons-team.vscode-icons",
"zxh404.vscode-proto3"
]
}
}
// UBCSailbot
"awesomektvn.toggle-semicolon",
"bierner.github-markdown-preview",
"christian-kohler.path-intellisense",
"cschlosser.doxdocgen",
"DavidAnson.vscode-markdownlint",
"eamodio.gitlens",
// "github.copilot",
"github.vscode-github-actions",
"Gruntfuggly.todo-tree",
"jebbs.plantuml",
"jeff-hykin.better-cpp-syntax",
"KevinRose.vsc-python-indent",
"llvm-vs-code-extensions.vscode-clangd",
"matepek.vscode-catch2-test-adapter",
"mechatroner.rainbow-csv",
"mongodb.mongodb-vscode",
"ranch-hand-robotics.rde-ros-2",
"ms-python.black-formatter",
"ms-python.isort",
"ms-python.vscode-pylance",
"ms-toolsai.jupyter",
"ms-vsliveshare.vsliveshare",
"ms-python.mypy-type-checker",
"njpwerner.autodocstring",
"randomfractalsinc.geo-data-viewer",
"stevejpurves.cucumber",
"streetsidesoftware.code-spell-checker",
"vscode-icons-team.vscode-icons",
"zxh404.vscode-proto3"
]
}
}
}
7 changes: 6 additions & 1 deletion src/website/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React from 'react';
import { Providers } from '@/lib/providers';
import '../styles/globals.css';
import { SET_THEME } from './themeNoFlashScript';
import '@/styles/variables.css';
import '@/styles/globals.css';

export default function RootLayout({
children,
Expand All @@ -9,6 +11,9 @@ export default function RootLayout({
}) {
return (
<html lang='en'>
<head>
<script dangerouslySetInnerHTML={{ __html: SET_THEME }} />
</head>
<body>
<Providers>{children}</Providers>
</body>
Expand Down
57 changes: 0 additions & 57 deletions src/website/app/style.module.css

This file was deleted.

9 changes: 9 additions & 0 deletions src/website/app/themeNoFlashScript.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// this is a very gimmicky way of setting theme without using cookies
// i dont think its worth it so we should just use cookies instead lol

export const SET_THEME = `
(function(){
var stored = localStorage.getItem('theme');
document.documentElement.classList.toggle(stored ?? 'dark');
})();
`;
29 changes: 29 additions & 0 deletions src/website/lib/ThemeSyncListener.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use client';

// very strange component.
// it doesnt return anything, we just need this to be a component because we need to use react hooks

import { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { setTheme, Theme } from '@/lib/redux/theme/themeSlice';

export function ThemeSyncListener() {
const dispatch = useDispatch();

useEffect(() => {
const handleStorageChange = (e: StorageEvent) => {
if (e.key === 'theme' && e.newValue) {
const newTheme = e.newValue === 'dark' ? Theme.Dark : Theme.Light;
dispatch(setTheme(newTheme));
}
};

window.addEventListener('storage', handleStorageChange);

return () => {
window.removeEventListener('storage', handleStorageChange);
};
}, [dispatch]);

return null;
}
8 changes: 7 additions & 1 deletion src/website/lib/providers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ import { Provider } from 'react-redux';

/* Instruments */
import { reduxStore } from '@/lib/redux';
import { ThemeSyncListener } from '@/lib/ThemeSyncListener';

export const Providers = (props: React.PropsWithChildren) => {
return <Provider store={reduxStore}>{props.children}</Provider>;
return (
<Provider store={reduxStore}>
<ThemeSyncListener />
{props.children}
</Provider>
);
};
2 changes: 2 additions & 0 deletions src/website/lib/redux/rootReducer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* Instruments */
import { combineReducers } from 'redux';
import themeReducer from './theme/themeSlice';
import GPSReducer from '@/stores/GPS/GPSReducers';
import GlobalPathReducer from '@/stores/GlobalPath/GlobalPathReducers';
import AISShipsReducer from '@/stores/AISShips/AISShipsReducers';
Expand All @@ -12,6 +13,7 @@ import DataFilterReducer from '@/stores/DataFilter/DataFilterReducers';

export function rootReducer() {
const reducerMap = {
theme: themeReducer,
gps: new GPSReducer().reducer,
aisShips: new AISShipsReducer().reducer,
localPath: new LocalPathReducer().reducer,
Expand Down
24 changes: 24 additions & 0 deletions src/website/lib/redux/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,35 @@ import createSagaMiddleware from 'redux-saga';
import { rootReducer } from './rootReducer';
import { middleware } from './middleware';
import { rootSaga } from './rootSaga';
import { Theme } from './theme/themeSlice';

const getPreloadedTheme = () => {
if (typeof window === 'undefined') {
return Theme.Dark;
}

try {
const stored = localStorage.getItem('theme');
if (stored === 'dark') return Theme.Dark;
if (stored === 'light') return Theme.Light;
} catch {
// may error out if user disables localstorage or something. thats fine.
}

return Theme.Dark;
};

const createReduxStore = () => {
const sagaMiddleWare = createSagaMiddleware();
const preloadedState =
typeof window !== 'undefined'
? {
theme: { current: getPreloadedTheme() },
}
: undefined;
const store = configureStore({
reducer: rootReducer(),
preloadedState,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat([sagaMiddleWare, ...middleware]),
enhancers: [applyMiddleware(sagaMiddleWare)],
Expand Down
46 changes: 46 additions & 0 deletions src/website/lib/redux/theme/themeSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit';

export enum Theme {
Light = 'light',
Dark = 'dark',
}

interface ThemeState {
current: Theme;
}

export const themeSlice = createSlice({
name: 'theme',
initialState: {
current: Theme.Dark,
},
reducers: {
setTheme: (state, action: PayloadAction<Theme>) => {
state.current = action.payload;
document.documentElement.classList.toggle(
'dark',
action.payload === Theme.Dark,
);
localStorage.setItem(
'theme',
action.payload === Theme.Dark ? 'dark' : 'light',
);
},
toggleTheme: (state) => {
const newTheme = state.current === Theme.Light ? Theme.Dark : Theme.Light;
state.current = newTheme;
document.documentElement.classList.toggle(
'dark',
newTheme === Theme.Dark,
);
localStorage.setItem('theme', newTheme === Theme.Dark ? 'dark' : 'light');
},
},
});

export const { setTheme, toggleTheme } = themeSlice.actions;

export default themeSlice.reducer;

export const selectTheme = (state: { theme: ThemeState }) =>
state.theme.current;
1 change: 1 addition & 0 deletions src/website/public/icons/dark_mode.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/website/public/icons/light_mode.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions src/website/styles/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
margin: 0;
padding: 0;
box-sizing: border-box;
background-color: #090909;
color: #ffffff;
background-color: var(--accent-color-1);
color: var(--accent-color-2);
}

html,
Expand All @@ -31,5 +31,5 @@ a {
}

svg {
fill: white;
fill: var(--accent-color-2);
}
27 changes: 27 additions & 0 deletions src/website/styles/variables.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
:root {
--light-accent-1: white;
--light-accent-2: #090909;
--light-accent-3: #262626;

--dark-accent-1: #090909;
--dark-accent-2: white;
--dark-accent-3: #6b6b6b;

--blue: #0059EB;
--purple: #8F42D9;
--pink: #E7006E;
--red: #E60F26;
--yellow: #FF9200;
--green: #009534;
--teal: #00937C;

--accent-color-1: var(--light-accent-1);
--accent-color-2: var(--light-accent-2);
--accent-color-3: var(--light-accent-3);
}

.dark {
--accent-color-1: var(--dark-accent-1);
--accent-color-2: var(--dark-accent-2);
--accent-color-3: var(--dark-accent-3);
}
Loading
Loading