From fd298c90d19446e73909a409fdb0e49c3c356a0f Mon Sep 17 00:00:00 2001 From: Neshura Date: Sat, 17 Dec 2022 21:29:39 +0100 Subject: [PATCH 01/16] Changed .gitignore --- .gitignore | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 4bca52d..67d0346 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,9 @@ # do not track installed modules -node_modules/ -.vscode/ +/node_modules/ +/.vscode/ # do not track built files -.next/ +/.next/ *.tsbuildinfo next-env.d.ts @@ -14,6 +14,6 @@ yarn-error.log* .pnpm-debug.log* # production -build/ -data/ -confs/ \ No newline at end of file +/build/ +/data/ +/confs/ \ No newline at end of file From bb76b0050682b55330d2dfa0871c0981433e378f Mon Sep 17 00:00:00 2001 From: Neshura Date: Sat, 17 Dec 2022 21:30:05 +0100 Subject: [PATCH 02/16] Added API endpoints for navbar and themes --- pages/api/v1/navbar.tsx | 15 ++++++++++++ pages/api/v1/themes.tsx | 15 ++++++++++++ public/data/navbar.json | 20 ++++++++++++++++ public/data/themes.json | 52 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 pages/api/v1/navbar.tsx create mode 100644 pages/api/v1/themes.tsx create mode 100644 public/data/navbar.json create mode 100644 public/data/themes.json diff --git a/pages/api/v1/navbar.tsx b/pages/api/v1/navbar.tsx new file mode 100644 index 0000000..b667b5d --- /dev/null +++ b/pages/api/v1/navbar.tsx @@ -0,0 +1,15 @@ +import fsPromises from 'fs/promises' +import path from 'path' + +export default async function Navbar(req: any, res: any) { + try { + const filePath = path.join(process.cwd(), '/public/data/navbar.json') + const jsonData = await fsPromises.readFile(filePath) + const data = JSON.parse(jsonData.toString()) + res.status(200).json(data) + } + catch (error) { + console.log(error) + res.status(500).json({error: 'Error reading data'}) + } +} \ No newline at end of file diff --git a/pages/api/v1/themes.tsx b/pages/api/v1/themes.tsx new file mode 100644 index 0000000..b19723c --- /dev/null +++ b/pages/api/v1/themes.tsx @@ -0,0 +1,15 @@ +import fsPromises from 'fs/promises' +import path from 'path' + +export default async function Navbar(req: any, res: any) { + try { + const filePath = path.join(process.cwd(), '/public/data/themes.json') + const jsonData = await fsPromises.readFile(filePath) + const data = JSON.parse(jsonData.toString()) + res.status(200).json(data) + } + catch (error) { + console.log(error) + res.status(500).json({error: 'Error reading data'}) + } +} \ No newline at end of file diff --git a/public/data/navbar.json b/public/data/navbar.json new file mode 100644 index 0000000..613e960 --- /dev/null +++ b/public/data/navbar.json @@ -0,0 +1,20 @@ +{ + "links": [ + { + "name": "Home", + "href": "/" + }, + { + "name": "About", + "href": "/about" + }, + { + "name": "Games", + "href": "/games" + }, + { + "name": "Services", + "href": "/services" + } + ] +} \ No newline at end of file diff --git a/public/data/themes.json b/public/data/themes.json new file mode 100644 index 0000000..146375c --- /dev/null +++ b/public/data/themes.json @@ -0,0 +1,52 @@ +{ + "themes": [ + { + "themeName": "Light Theme", + "themeId": 0, + "colors": { + "background": "#ffffff", + "primary": "#00aaff", + "secondary": "#ff5300", + "online": "#00ff00", + "loading": "#ff5300", + "offline": "#ff0000" + } + }, + { + "themeName": "Dark Theme", + "themeId": 1, + "colors": { + "background": "#1f1f1f", + "primary": "#00aaff", + "secondary": "#ff5300", + "online": "#00ff00", + "loading": "#ff5300", + "offline": "#ff0000" + } + }, + { + "themeName": "AMOLED Theme", + "themeId": 2, + "colors": { + "background": "#000000", + "primary": "#00aaff", + "secondary": "#ff5300", + "online": "#00ff00", + "loading": "#ff5300", + "offline": "#ff0000" + } + }, + { + "themeName": "AMOLED Theme 2", + "themeId": 3, + "colors": { + "background": "#000000", + "primary": "#00ffaa", + "secondary": "#aa00ff", + "online": "#00ff00", + "loading": "#ff5300", + "offline": "#ff0000" + } + } + ] +} \ No newline at end of file From f7d3d7c7ca12079caed6d2237eb9bdebedfbc70a Mon Sep 17 00:00:00 2001 From: Neshura Date: Sat, 17 Dec 2022 21:30:31 +0100 Subject: [PATCH 03/16] Extracted fetcher into separate file --- components/fetcher.tsx | 1 + 1 file changed, 1 insertion(+) create mode 100644 components/fetcher.tsx diff --git a/components/fetcher.tsx b/components/fetcher.tsx new file mode 100644 index 0000000..0a37648 --- /dev/null +++ b/components/fetcher.tsx @@ -0,0 +1 @@ +export const fetcher = (url:string) => fetch(url).then((res) => res.json()); \ No newline at end of file From f1780585781777c952e20b15d5c87009b941d6bd Mon Sep 17 00:00:00 2001 From: Neshura Date: Sat, 17 Dec 2022 21:31:03 +0100 Subject: [PATCH 04/16] Removed AMOLED 2 from hardcoded themes --- components/themes.tsx | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/components/themes.tsx b/components/themes.tsx index 7e8ca25..81f0b83 100644 --- a/components/themes.tsx +++ b/components/themes.tsx @@ -56,17 +56,4 @@ export const amoledTheme: DefaultTheme = { loading: '#ff5300', offline: '#ff0000', }, -} - -export const amoled2Theme: DefaultTheme = { - themeName: "AMOLED Theme 2", - themeId: 3, - colors: { - background: '#000000', - primary: '#00ffaa', - secondary:'#aa00ff', - online: '#00ff00', - loading: '#ff5300', - offline: '#ff0000', - }, } \ No newline at end of file From 5ee7c8ef2e8d2cb9a06b77aef11b066e587a72be Mon Sep 17 00:00:00 2001 From: Neshura Date: Sat, 17 Dec 2022 21:35:40 +0100 Subject: [PATCH 05/16] Fixed console errors, added Delay to themeselector transition Transition now only rounds the corners after the dropdown is retracted --- components/styles/navbar.tsx | 2 +- components/styles/themedropdown.tsx | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/components/styles/navbar.tsx b/components/styles/navbar.tsx index d3642ed..7453992 100644 --- a/components/styles/navbar.tsx +++ b/components/styles/navbar.tsx @@ -2,7 +2,7 @@ import styled from 'styled-components' import Link from 'next/link'; interface ActivePropType { - active?: false | true; + active?: number; } export const NavWrap = styled.div` diff --git a/components/styles/themedropdown.tsx b/components/styles/themedropdown.tsx index a11879b..45c7cc7 100644 --- a/components/styles/themedropdown.tsx +++ b/components/styles/themedropdown.tsx @@ -1,11 +1,11 @@ import styled from 'styled-components'; interface DisplayPropType { - show?: false | true; + show?: number; } interface ActivePropType { - active?: false | true; + active?: number; } export const ThemeDropDown = styled.div` @@ -28,6 +28,7 @@ export const ThemeDropDownButton = styled.button` transition-property: color, border-bottom-left-radius, border-bottom-right-radius; transition-timing-function: ease; transition-duration: 0.15s; + transition-delay: 0, ${ props => props.show ? "0s" : "0.6s" }; &:focus,:hover { color: ${({ theme }) => theme.colors.secondary}; @@ -62,6 +63,7 @@ export const ThemeDropDownOptions = styled.div` export const ThemeDropDownOption = styled.button` color: ${ props => props.active ? ({ theme }) => theme.colors.secondary : ({ theme }) => theme.colors.primary }; background-color: ${({ theme }) => theme.colors.background}; + cursor: pointer; align-self: center; border: 0px solid; padding: 0.2rem 0.5rem; From d484ffc0dbfe09c2f6c17c7676369471b4c5ccbc Mon Sep 17 00:00:00 2001 From: Neshura Date: Sun, 18 Dec 2022 00:25:43 +0100 Subject: [PATCH 06/16] Adjust Theme Selector Dropdown --- components/styles/themedropdown.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/styles/themedropdown.tsx b/components/styles/themedropdown.tsx index 45c7cc7..6c2e6ea 100644 --- a/components/styles/themedropdown.tsx +++ b/components/styles/themedropdown.tsx @@ -28,7 +28,7 @@ export const ThemeDropDownButton = styled.button` transition-property: color, border-bottom-left-radius, border-bottom-right-radius; transition-timing-function: ease; transition-duration: 0.15s; - transition-delay: 0, ${ props => props.show ? "0s" : "0.6s" }; + transition-delay: 0s, ${ props => props.show ? "0s, 0s" : "0.6s, 0.6s" }; &:focus,:hover { color: ${({ theme }) => theme.colors.secondary}; From 17f86b4be461eb95476cc6e2e524424746c921ab Mon Sep 17 00:00:00 2001 From: Neshura Date: Sun, 18 Dec 2022 00:38:37 +0100 Subject: [PATCH 07/16] Removed API's in favor of statically linked files --- components/navbar.tsx | 12 +++--------- pages/_app.tsx | 23 ++++++++++++----------- pages/api/services.tsx | 21 --------------------- pages/api/v1/navbar.tsx | 15 --------------- pages/api/v1/themes.tsx | 15 --------------- pages/games.tsx | 19 +++++-------------- pages/services.tsx | 21 ++++++++++----------- 7 files changed, 30 insertions(+), 96 deletions(-) delete mode 100644 pages/api/services.tsx delete mode 100644 pages/api/v1/navbar.tsx delete mode 100644 pages/api/v1/themes.tsx diff --git a/components/navbar.tsx b/components/navbar.tsx index 46eee11..6994205 100644 --- a/components/navbar.tsx +++ b/components/navbar.tsx @@ -1,13 +1,7 @@ import { usePathname } from 'next/navigation' import { NavBar, NavLink, NavWrap } from './styles/navbar'; import { StyleSelector, StyleSelectorPlaceholder } from './themeselector'; - -const navLinks = [ - { name: "Home", href: "/" }, - { name: "About", href: "/about" }, - { name: "Games", href: "/games" }, - { name: "Services", href: "/services" } -] +import Links from '../public/data/navbar.json'; const PageNavbar = () => { const path = usePathname(); @@ -16,8 +10,8 @@ const PageNavbar = () => { - {navLinks.map((item) => ( - + {Links.links.map((item) => ( + {item.name} ))} diff --git a/pages/_app.tsx b/pages/_app.tsx index ec2d25f..52c9c34 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -7,6 +7,7 @@ import { DefaultTheme, ThemeProvider } from 'styled-components'; import { createContext, useContext, useEffect, useState } from 'react' import { darkTheme, GlobalStyle } from '../components/themes'; import { getTheme } from '../components/themeselector'; +import Themes from '../public/data/themes.json'; export type NextPageWithLayout

= NextPage & { getLayout?: (page: ReactElement) => ReactNode @@ -16,8 +17,7 @@ export type AppPropsWithLayout = AppProps & { Component: NextPageWithLayout } - -const ThemeUpdateContext = createContext( +export const ThemeUpdateContext = createContext( (theme: DefaultTheme) => console.error("attempted to set theme outside of a ThemeUpdateContext.Provider") ) @@ -25,7 +25,9 @@ export const useUpdateTheme = () => useContext(ThemeUpdateContext); export default function Website({ Component, pageProps }: AppPropsWithLayout) { + const loadedThemes = Themes.themes; const [selectedTheme, setselectedTheme] = useState(darkTheme); + const [themes, setThemes] = useState(loadedThemes); useEffect(() => { @@ -34,10 +36,9 @@ export default function Website({ Component, pageProps }: AppPropsWithLayout) { // if theme data differs set it // if not just exit if (storedThemeIdTemp && parseInt(storedThemeIdTemp) !== selectedTheme.themeId) { - setselectedTheme(getTheme(parseInt(storedThemeIdTemp))) + setselectedTheme(getTheme(parseInt(storedThemeIdTemp), themes)) } - }, [selectedTheme]) - + }, [selectedTheme, themes]) // Use the layout defined at the page level, if available const getLayout = Component.getLayout ?? ((page) => ( @@ -46,12 +47,12 @@ export default function Website({ Component, pageProps }: AppPropsWithLayout) { return ( - - - {getLayout()} - - + + + {getLayout()} + + - + ) } diff --git a/pages/api/services.tsx b/pages/api/services.tsx deleted file mode 100644 index a2627b4..0000000 --- a/pages/api/services.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import fsPromises from 'fs/promises' -import path from 'path' -import { Service, Status } from '../../interfaces/CardTypes'; - -export default async function ServicesAPI(req: any, res: any) { - try { - const filePath = path.join(process.cwd(), '/public/pages.json') - const data = await fsPromises.readFile(filePath) - .then((file) => JSON.parse(file.toString())); - data.services.forEach((service: Service) => { - service.status = Status.loading; - }); - - res.status(200).json(data.services); - } - catch (error) { - console.log(error); - res.status(500).json({ error: 'Error reading data' }); - } -} - diff --git a/pages/api/v1/navbar.tsx b/pages/api/v1/navbar.tsx deleted file mode 100644 index b667b5d..0000000 --- a/pages/api/v1/navbar.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import fsPromises from 'fs/promises' -import path from 'path' - -export default async function Navbar(req: any, res: any) { - try { - const filePath = path.join(process.cwd(), '/public/data/navbar.json') - const jsonData = await fsPromises.readFile(filePath) - const data = JSON.parse(jsonData.toString()) - res.status(200).json(data) - } - catch (error) { - console.log(error) - res.status(500).json({error: 'Error reading data'}) - } -} \ No newline at end of file diff --git a/pages/api/v1/themes.tsx b/pages/api/v1/themes.tsx deleted file mode 100644 index b19723c..0000000 --- a/pages/api/v1/themes.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import fsPromises from 'fs/promises' -import path from 'path' - -export default async function Navbar(req: any, res: any) { - try { - const filePath = path.join(process.cwd(), '/public/data/themes.json') - const jsonData = await fsPromises.readFile(filePath) - const data = JSON.parse(jsonData.toString()) - res.status(200).json(data) - } - catch (error) { - console.log(error) - res.status(500).json({error: 'Error reading data'}) - } -} \ No newline at end of file diff --git a/pages/games.tsx b/pages/games.tsx index 6992a26..f57ba1b 100644 --- a/pages/games.tsx +++ b/pages/games.tsx @@ -1,12 +1,11 @@ import Head from 'next/head' -import fsPromises from 'fs/promises' -import path from 'path' -import { EntryList, Game } from '../interfaces/CardTypes'; +import { Game } from '../interfaces/CardTypes'; import { PageContentBox, PageDescription, PageTitle, CardContentGame } from '../components/styles/content' -import Link from 'next/link' +import GameList from '../public/pages.json'; -function Servers(props: EntryList) { - const serverList = props.games +function Servers() { + // TODO: unuggly this shit + const serverList: Game[] = JSON.parse(JSON.stringify(GameList.games)); return ( <> @@ -32,12 +31,4 @@ function Servers(props: EntryList) { ) } -export async function getServerSideProps() { - const filePath = path.join(process.cwd(), '/public/pages.json') - const jsonData = await fsPromises.readFile(filePath) - const list = JSON.parse(jsonData.toString()) - - return { props: list } -} - export default Servers \ No newline at end of file diff --git a/pages/services.tsx b/pages/services.tsx index 360b689..ec1ea73 100644 --- a/pages/services.tsx +++ b/pages/services.tsx @@ -1,20 +1,19 @@ import Head from 'next/head' -import Link from 'next/link' import { Service, Status, ServiceType, ServiceLocation } from '../interfaces/CardTypes'; import Dockerode from 'dockerode'; import { ReactElement } from 'react' import useSWR from 'swr'; -import { PageCard, CardContentService, PageContentBox, PageDescription, PageTitle } from '../components/styles/content'; +import { CardContentService, PageContentBox, PageDescription, PageTitle } from '../components/styles/content'; +import ServiceList from '../public/pages.json'; const fetcher = (url: string) => fetch(url).then((res) => res.json()) function Services() { - const { initialData, fullData, loadingInitial, loadingFull, error } = useServices(); + const { initialData, fullData, loadingFull, error } = useServices(); let content: ReactElement = <>; if (error) { content =

Error loading data
} - else if (loadingInitial) { content =
Loading
} else if (loadingFull) { content = @@ -22,7 +21,6 @@ function Services() { ))} - } else if (fullData) { content = @@ -171,17 +169,18 @@ const fetchFullDataArray = (containerData: Dockerode.ContainerInfo[], dataSet: S function useServices() { const { data: containerData, error: containerError } = useSWR('/api/containers', fetcher); - const { data: initialData, error: initialError } = useSWR('/api/services', fetcher); - const loadingInitial = !initialData && !initialError - const { data: fullData, error: fullError } = useSWR((initialData && containerData) ? [containerData, initialData] : null, fetchFullDataArray) + // TODO: unfuck this + const initialData: Service[] = JSON.parse(JSON.stringify(ServiceList.services)); + initialData.forEach((service) => { + if (service.status === undefined) service.status = Status.loading; + }) + const { data: fullData, error: fullError } = useSWR((containerData) ? [containerData, initialData] : null, fetchFullDataArray) const loadingFull = !fullData && !fullError - return { initialData, fullData, - loadingInitial, loadingFull, - error: initialError || fullError || containerError, + error: fullError || containerError, }; } From a0264a31cbcfb06de56bd9e9f911c541ca7496c6 Mon Sep 17 00:00:00 2001 From: Neshura Date: Sun, 18 Dec 2022 00:39:08 +0100 Subject: [PATCH 08/16] Added theme, unified href format for pages --- public/data/themes.json | 12 ++++++++++++ public/pages.json | 8 ++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/public/data/themes.json b/public/data/themes.json index 146375c..2d2c150 100644 --- a/public/data/themes.json +++ b/public/data/themes.json @@ -47,6 +47,18 @@ "loading": "#ff5300", "offline": "#ff0000" } + }, + { + "themeName": "Custom Theme 3", + "themeId": 4, + "colors": { + "background": "#000000", + "primary": "#00ffaa", + "secondary": "#aa00ff", + "online": "#00ff00", + "loading": "#ff5300", + "offline": "#ff0000" + } } ] } \ No newline at end of file diff --git a/public/pages.json b/public/pages.json index b97f0da..f7378c9 100644 --- a/public/pages.json +++ b/public/pages.json @@ -3,7 +3,7 @@ { "name": "Nextcloud", "icon": "/icons/nextcloud-logo.svg", - "href": "https://nextcloud.neshweb.net", + "href": "https://nextcloud.neshweb.net/", "desc": "Self-hosted Cloud Storage Service", "warn": "Note: Registration requires approval", "type": "docker", @@ -13,7 +13,7 @@ { "name": "Komga", "icon": "/icons/komga-logo.png", - "href": "https://komga.neshweb.net", + "href": "https://komga.neshweb.net/", "desc": "Self-hosted Comic Library", "warn": "Note: Registration only via Admin", "type": "docker", @@ -32,7 +32,7 @@ { "name": "PeerTube", "icon": "/icons/peertube-logo.svg", - "href": "https://tube.neshweb.net", + "href": "https://tube.neshweb.net/", "desc": "Self-hosted PeerTube Instance", "warn": "Note: Registration only via Admin", "type": "docker", @@ -42,7 +42,7 @@ { "name": "Mastodon", "icon": "/icons/mastodon-logo.svg", - "href": "https://mastodon.neshweb.net", + "href": "https://mastodon.neshweb.net/", "desc": "Self-hosted Mastodon Instance", "warn": "Note: Registration requires approval", "type": "docker", From d1dc7ceca7285b835d4641b9561d4d04a17ef30a Mon Sep 17 00:00:00 2001 From: Neshura Date: Sun, 18 Dec 2022 00:40:24 +0100 Subject: [PATCH 09/16] Updated Theme Selector for use with dynamic themes --- components/themeselector.tsx | 54 ++++++++++-------------------------- 1 file changed, 15 insertions(+), 39 deletions(-) diff --git a/components/themeselector.tsx b/components/themeselector.tsx index 8db0066..f395038 100644 --- a/components/themeselector.tsx +++ b/components/themeselector.tsx @@ -1,17 +1,12 @@ import { useUpdateTheme } from "../pages/_app"; -import { Fragment, useContext, useState } from 'react'; +import { useContext, useState } from 'react'; import { ThemeContext, DefaultTheme } from "styled-components"; -import { darkTheme, amoledTheme, lightTheme, amoled2Theme } from './themes'; +import { darkTheme, lightTheme } from './themes'; import { ThemeDropDown, ThemeDropDownButton, ThemeDropDownOption, ThemeDropDownOptions } from "./styles/themedropdown"; - -const themes = [ - lightTheme, - darkTheme, - amoledTheme, - amoled2Theme, -] +import Themes from '../public/data/themes.json'; export const StyleSelector = () => { + const themes = Themes.themes; const updateTheme = useUpdateTheme(); const currentTheme = useContext(ThemeContext); const [selectedTheme, setSelectedTheme] = useState(themes[currentTheme.themeId]); @@ -21,7 +16,6 @@ export const StyleSelector = () => { } const updateThemeWithStorage = (newTheme: DefaultTheme) => { - if (newTheme.themeId === lightTheme.themeId) { updateLightTheme(newTheme); } @@ -38,27 +32,22 @@ export const StyleSelector = () => { localStorage.setItem("theme", newTheme.themeId.toString()); updateTheme(newTheme) } - else { - - } } - const [test, setTest] = useState(false); + const [visible, setVisible] = useState(false); function handleBlur(event:any) { - console.log(event) if (!event.currentTarget.contains(event.relatedTarget)) { - setTest(false); + setVisible(false); } } return ( - handleBlur(event)}> - setTest(test => !test)}>{selectedTheme.themeName} - + setVisible(visible => !visible)}>{selectedTheme.themeName} + {themes.map((theme) => ( - updateThemeWithStorage(theme)}> + updateThemeWithStorage(theme)}> {theme.themeName} ))} @@ -73,27 +62,14 @@ export const StyleSelectorPlaceholder = () => { ) } -export function getTheme(themeId: number): DefaultTheme { - let theme: DefaultTheme; +export function getTheme(themeId: number, themes: DefaultTheme[]): DefaultTheme { + let retTheme: DefaultTheme = darkTheme; - switch (themeId) { - case 0: - theme = lightTheme; - break; - case 1: - theme = darkTheme; - break; - case 2: - theme = amoledTheme; - break; - case 3: - theme = amoled2Theme; - break; - default: - theme = darkTheme - } + themes.forEach((theme) => { + if (theme.themeId === themeId) { retTheme = theme}; + }) - return theme; + return retTheme; } export default StyleSelector; \ No newline at end of file From 8d41694e0ca1ab12b0f302388402b4f486b66348 Mon Sep 17 00:00:00 2001 From: Neshura Date: Sun, 18 Dec 2022 00:40:52 +0100 Subject: [PATCH 10/16] Small formatting changes --- components/layout.tsx | 15 +++++++-------- components/styles/content.tsx | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/components/layout.tsx b/components/layout.tsx index 780c16b..8482b63 100644 --- a/components/layout.tsx +++ b/components/layout.tsx @@ -1,15 +1,14 @@ -import PageFooter from './footer' -import PageNavbar from './navbar' -import Script from 'next/script' -import { Page, Main } from './styles/generic' - +import PageFooter from './footer'; +import PageNavbar from './navbar'; +import Script from 'next/script'; +import { Page, Main } from './styles/generic'; const Layout = ({ children }: { children: React.ReactNode }) => { return ( -