diff --git a/Caddyfile.dev b/Caddyfile.dev index 2cff439..7f50e52 100644 --- a/Caddyfile.dev +++ b/Caddyfile.dev @@ -13,19 +13,3 @@ timmypidashev.localhost { reverse_proxy landing:8000 } } - -about.timmypidashev.localhost { - encode gzip - - reverse_proxy about:3000 - - @backend_routes { - path /_event/* - path /_upload - path /ping - } - - handle @backend_routes { - reverse_proxy about:8000 - } -} diff --git a/Makefile b/Makefile index 4d01c63..42af042 100644 --- a/Makefile +++ b/Makefile @@ -6,15 +6,10 @@ PROJECT_SOURCES := "https://github.com/timmypidashev/web" PROJECT_REGISTRY := "ghcr.io/timmypidashev/web" PROJECT_ORGANIZATION := "org.opencontainers" -CONTAINER_LANDING_NAME := "landing" -CONTAINER_LANDING_VERSION := "v1.0.0" -CONTAINER_LANDING_LOCATION := "src/landing" -CONTAINER_LANDING_DESCRIPTION := "The landing page for my website." - -CONTAINER_ABOUT_NAME := "about" -CONTAINER_ABOUT_VERSION := "v0.0.0" -CONTAINER_ABOUT_LOCATION := "src/about" -CONTAINER_ABOUT_DESCRIPTION := "The about page for my website." +CONTAINER_WEB_NAME := "web" +CONTAINER_WEB_VERSION := "v1.0.0" +CONTAINER_WEB_LOCATION := "src/web" +CONTAINER_WEB_DESCRIPTION := "My portfolio website!" .DEFAULT_GOAL := help .PHONY: run build push prune bump @@ -147,14 +142,7 @@ define container_build $(eval TAG := $(PROJECT_REGISTRY)/$(CONTAINER):$(VERSION)), \ ) - sudo mkdir -p $(call container_location,$(CONTAINER))/$(CONTAINER)/shared - sudo mount -o bind src/shared $(call container_location,$(CONTAINER))/$(CONTAINER)/shared docker buildx build --load -t $(TAG) -f $(strip $(subst $(SPACE),,$(call container_location,$(CONTAINER))))/Dockerfile.$(ENVIRONMENT) ./$(strip $(subst $(SPACE),,$(call container_location,$(CONTAINER))))/. $(ARGS) $(call labels,$(shell echo $(CONTAINER_NAME) | tr '[:lower:]' '[:upper:]')) --no-cache - sudo umount -l $(call container_location,$(CONTAINER))/$(CONTAINER)/shared - sleep 1 - sudo rm -rf $(call container_location,$(CONTAINER))/$(CONTAINER)/shared - sleep 1 - endef define container_location diff --git a/compose.dev.yml b/compose.dev.yml index bec4aed..b1ae5cf 100644 --- a/compose.dev.yml +++ b/compose.dev.yml @@ -13,28 +13,15 @@ services: networks: - caddy depends_on: - - landing - - about + - web - landing: - container_name: landing - image: landing:dev + web: + container_name: web + image: web:dev volumes: - - ./src/landing/landing:/app/landing - - ./src/landing/assets:/app/assets - - ./src/landing/rxconfig.py:/app/rxconfig.py - - ./src/shared:/app/landing/shared - networks: - - caddy - - about: - container_name: about - image: about:dev - volumes: - - ./src/about/about:/app/about - - ./src/about/assets:/app/assets - - ./src/about/rxconfig.py:/app/rxconfig.py - - ./src/shared:/app/about/shared + - ./src/web/web:/app/web + - ./src/web/assets:/app/assets + - ./src/web/rxconfig.py:/app/rxconfig.py networks: - caddy diff --git a/src/about/.web/package.json b/src/about/.web/package.json deleted file mode 100644 index aab86df..0000000 --- a/src/about/.web/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "reflex", - "scripts": { - "dev": "next dev", - "export": "next build", - "export-sitemap": "next build && next-sitemap", - "prod": "next start" - }, - "dependencies": { - "@emotion/react": "11.11.1", - "axios": "1.6.0", - "json5": "2.2.3", - "next": "14.0.1", - "next-sitemap": "4.1.8", - "next-themes": "0.2.1", - "react": "18.2.0", - "react-dom": "18.2.0", - "socket.io-client": "4.6.1", - "universal-cookie": "4.0.4" - }, - "devDependencies": { - "autoprefixer": "10.4.14", - "postcss": "8.4.31" - } -} \ No newline at end of file diff --git a/src/about/.web/reflex.json b/src/about/.web/reflex.json deleted file mode 100644 index 7aecab7..0000000 --- a/src/about/.web/reflex.json +++ /dev/null @@ -1 +0,0 @@ -{"version": "0.4.3", "project_hash": 326586468133229768661018683044141625593} \ No newline at end of file diff --git a/src/about/Dockerfile.dev b/src/about/Dockerfile.dev deleted file mode 100644 index f5c6b24..0000000 --- a/src/about/Dockerfile.dev +++ /dev/null @@ -1,54 +0,0 @@ -# Stage 1: init -FROM python:3.11 as init - -# Copy local context to `/app` inside container (see .dockerignore) -WORKDIR /app -COPY . . - -# Create virtualenv which will be copied into the final container -ENV VIRTUAL_ENV=/app/.venv -ENV PATH="$VIRTUAL_ENV/bin:$PATH" -RUN python3.11 -m venv $VIRTUAL_ENV - -# Install app requirements and reflex inside virtualenv -RUN pip install -r requirements.txt - -# Deploy templates and prepare app -RUN reflex init - -# Export static copy of frontend to /app/.web/_static -RUN echo "Exporting reflex app to shrink the docker image size, not actually a prod build." -RUN reflex export --frontend-only --no-zip - -# Copy static files out of /app to save space in backend image -RUN mv .web/_static /tmp/_static -RUN rm -rf .web && mkdir .web -RUN mv /tmp/_static .web/_static - -# Stage 2: copy artifacts into slim image -FROM python:3.11-slim -WORKDIR /app -RUN adduser --disabled-password --home /app reflex - -# Install Node.js and unzip -RUN apt-get update && apt-get install -y nodejs unzip curl && curl -fsSL https://bun.sh/install | bash - -# Copy only the necessary files from the "init" stage -COPY --chown=reflex --from=init /app/.venv /app/.venv -COPY --chown=reflex --from=init /app/requirements.txt /app/requirements.txt -COPY --chown=reflex --from=init /app /app - -# Change the ownership and permissions of /app/.local -USER root -RUN mkdir -p /app -RUN chown -R reflex /app -USER reflex - -# Activate the virtual environment and install application requirements -ENV PATH="/app/.venv/bin:$PATH" -RUN python3.11 -m venv /app/.venv -RUN /app/.venv/bin/pip install -r /app/requirements.txt - -# The following lines are for the specific command for the application. -CMD reflex init && reflex run --env dev - diff --git a/src/about/about/about.py b/src/about/about/about.py deleted file mode 100644 index 8ff44ab..0000000 --- a/src/about/about/about.py +++ /dev/null @@ -1,35 +0,0 @@ -"""Welcome to Reflex! This file outlines the steps to create a basic app.""" - -from rxconfig import config - -import reflex as rx - -docs_url = "https://reflex.dev/docs/getting-started/introduction/" -filename = f"{config.app_name}/{config.app_name}.py" - - -class State(rx.State): - """The app state.""" - - -def index() -> rx.Component: - return rx.center( - rx.theme_panel(), - rx.vstack( - rx.heading("Welcome to Reflex!", size="9"), - rx.text("Get started by editing ", rx.code(filename)), - rx.button( - "Check out our docs!", - on_click=lambda: rx.redirect(docs_url), - size="4", - ), - align="center", - spacing="7", - font_size="2em", - ), - height="100vh", - ) - - -app = rx.App() -app.add_page(index) diff --git a/src/about/rxconfig.py b/src/about/rxconfig.py deleted file mode 100644 index 250c229..0000000 --- a/src/about/rxconfig.py +++ /dev/null @@ -1,5 +0,0 @@ -import reflex as rx - -config = rx.Config( - app_name="about", -) \ No newline at end of file diff --git a/src/landing/.dockerignore b/src/landing/.dockerignore deleted file mode 100644 index b289110..0000000 --- a/src/landing/.dockerignore +++ /dev/null @@ -1,3 +0,0 @@ -.web -__pycache__/* -Dockerfile diff --git a/src/landing/.web/.gitignore b/src/landing/.web/.gitignore deleted file mode 100644 index 534bc86..0000000 --- a/src/landing/.web/.gitignore +++ /dev/null @@ -1,39 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -/_static - -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# next.js -/.next/ -/out/ - -# production -/build - -# misc -.DS_Store -*.pem - -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# local env files -.env.local -.env.development.local -.env.test.local -.env.production.local - -# vercel -.vercel - -# DS_Store -.DS_Store \ No newline at end of file diff --git a/src/landing/.web/components/reflex/chakra_color_mode_provider.js b/src/landing/.web/components/reflex/chakra_color_mode_provider.js deleted file mode 100644 index f897522..0000000 --- a/src/landing/.web/components/reflex/chakra_color_mode_provider.js +++ /dev/null @@ -1,21 +0,0 @@ -import { useColorMode as chakraUseColorMode } from "@chakra-ui/react" -import { useTheme } from "next-themes" -import { useEffect } from "react" -import { ColorModeContext } from "/utils/context.js" - -export default function ChakraColorModeProvider({ children }) { - const {colorMode, toggleColorMode} = chakraUseColorMode() - const {theme, setTheme} = useTheme() - - useEffect(() => { - if (colorMode != theme) { - toggleColorMode() - } - }, [theme]) - - return ( - - {children} - - ) -} \ No newline at end of file diff --git a/src/landing/.web/components/reflex/radix_themes_color_mode_provider.js b/src/landing/.web/components/reflex/radix_themes_color_mode_provider.js deleted file mode 100644 index e2dd563..0000000 --- a/src/landing/.web/components/reflex/radix_themes_color_mode_provider.js +++ /dev/null @@ -1,22 +0,0 @@ -import { useTheme } from "next-themes" -import { useEffect, useState } from "react" -import { ColorModeContext, defaultColorMode } from "/utils/context.js" - - -export default function RadixThemesColorModeProvider({ children }) { - const {theme, setTheme} = useTheme() - const [colorMode, setColorMode] = useState(defaultColorMode) - - useEffect(() => { - setColorMode(theme) - }, [theme]) - - const toggleColorMode = () => { - setTheme(theme === "light" ? "dark" : "light") - } - return ( - - {children} - - ) - } \ No newline at end of file diff --git a/src/landing/.web/jsconfig.json b/src/landing/.web/jsconfig.json deleted file mode 100644 index 3c8a325..0000000 --- a/src/landing/.web/jsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "compilerOptions": { - "baseUrl": ".", - "paths": { - "@/*": ["public/*"] - } - } -} \ No newline at end of file diff --git a/src/landing/.web/next.config.js b/src/landing/.web/next.config.js deleted file mode 100644 index 42dad1d..0000000 --- a/src/landing/.web/next.config.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = {basePath: "", compress: true, reactStrictMode: true, trailingSlash: true}; diff --git a/src/landing/.web/postcss.config.js b/src/landing/.web/postcss.config.js deleted file mode 100644 index 33ad091..0000000 --- a/src/landing/.web/postcss.config.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -} diff --git a/src/landing/.web/styles/tailwind.css b/src/landing/.web/styles/tailwind.css deleted file mode 100644 index b5c61c9..0000000 --- a/src/landing/.web/styles/tailwind.css +++ /dev/null @@ -1,3 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; diff --git a/src/landing/.web/utils/client_side_routing.js b/src/landing/.web/utils/client_side_routing.js deleted file mode 100644 index 75fb581..0000000 --- a/src/landing/.web/utils/client_side_routing.js +++ /dev/null @@ -1,36 +0,0 @@ -import { useEffect, useRef, useState } from "react"; -import { useRouter } from "next/router"; - -/** - * React hook for use in /404 page to enable client-side routing. - * - * Uses the next/router to redirect to the provided URL when loading - * the 404 page (for example as a fallback in static hosting situations). - * - * @returns {boolean} routeNotFound - true if the current route is an actual 404 - */ -export const useClientSideRouting = () => { - const [routeNotFound, setRouteNotFound] = useState(false) - const didRedirect = useRef(false) - const router = useRouter() - useEffect(() => { - if ( - router.isReady && - !didRedirect.current // have not tried redirecting yet - ) { - didRedirect.current = true // never redirect twice to avoid "Hard Navigate" error - // attempt to redirect to the route in the browser address bar once - router.replace({ - pathname: window.location.pathname, - query: window.location.search.slice(1), - }) - .catch((e) => { - setRouteNotFound(true) // navigation failed, so this is a real 404 - }) - } - }, [router.isReady]); - - // Return the reactive bool, to avoid flashing 404 page until we know for sure - // the route is not found. - return routeNotFound -} \ No newline at end of file diff --git a/src/landing/.web/utils/helpers/dataeditor.js b/src/landing/.web/utils/helpers/dataeditor.js deleted file mode 100644 index 9ff3682..0000000 --- a/src/landing/.web/utils/helpers/dataeditor.js +++ /dev/null @@ -1,69 +0,0 @@ -import { GridCellKind } from "@glideapps/glide-data-grid"; - -export function getDEColumn(columns, col) { - let c = columns[col]; - c.pos = col; - return c; -} - -export function getDERow(data, row) { - return data[row]; -} - -export function locateCell(row, column) { - if (Array.isArray(row)) { - return row[column.pos]; - } else { - return row[column.id]; - } -} - -export function formatCell(value, column) { - const editable = column.editable ?? true; - switch (column.type) { - case "int": - case "float": - return { - kind: GridCellKind.Number, - data: value, - displayData: value + "", - readonly: !editable, - allowOverlay: editable, - }; - case "datetime": - // value = moment format? - case "str": - return { - kind: GridCellKind.Text, - data: value, - displayData: value, - readonly: !editable, - allowOverlay: editable, - }; - case "bool": - return { - kind: GridCellKind.Boolean, - data: value, - readonly: !editable, - }; - default: - console.log( - "Warning: column.type is undefined for column.title=" + column.title - ); - return { - kind: GridCellKind.Text, - data: value, - displayData: column.type, - }; - } -} - -export function formatDataEditorCells(col, row, columns, data) { - if (row < data.length && col < columns.length) { - const column = getDEColumn(columns, col); - const rowData = getDERow(data, row); - const cellData = locateCell(rowData, column); - return formatCell(cellData, column); - } - return { kind: GridCellKind.Loading }; -} diff --git a/src/landing/.web/utils/helpers/range.js b/src/landing/.web/utils/helpers/range.js deleted file mode 100644 index 7d1aeda..0000000 --- a/src/landing/.web/utils/helpers/range.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Simulate the python range() builtin function. - * inspired by https://dev.to/guyariely/using-python-range-in-javascript-337p - * - * If needed outside of an iterator context, use `Array.from(range(10))` or - * spread syntax `[...range(10)]` to get an array. - * - * @param {number} start: the start or end of the range. - * @param {number} stop: the end of the range. - * @param {number} step: the step of the range. - * @returns {object} an object with a Symbol.iterator method over the range - */ -export default function range(start, stop, step) { - return { - [Symbol.iterator]() { - if (stop === undefined) { - stop = start; - start = 0; - } - if (step === undefined) { - step = 1; - } - - let i = start - step; - - return { - next() { - i += step; - if ((step > 0 && i < stop) || (step < 0 && i > stop)) { - return { - value: i, - done: false, - }; - } - return { - value: undefined, - done: true, - }; - }, - }; - }, - }; - } \ No newline at end of file diff --git a/src/landing/.web/utils/state.js b/src/landing/.web/utils/state.js deleted file mode 100644 index 51e8c6b..0000000 --- a/src/landing/.web/utils/state.js +++ /dev/null @@ -1,728 +0,0 @@ -// State management for Reflex web apps. -import axios from "axios"; -import io from "socket.io-client"; -import JSON5 from "json5"; -import env from "/env.json"; -import Cookies from "universal-cookie"; -import { useEffect, useReducer, useRef, useState } from "react"; -import Router, { useRouter } from "next/router"; -import { - initialEvents, - initialState, - onLoadInternalEvent, - state_name, -} from "utils/context.js"; - -// Endpoint URLs. -const EVENTURL = env.EVENT; -const UPLOADURL = env.UPLOAD; - -// These hostnames indicate that the backend and frontend are reachable via the same domain. -const SAME_DOMAIN_HOSTNAMES = ["localhost", "0.0.0.0", "::", "0:0:0:0:0:0:0:0"]; - -// Global variable to hold the token. -let token; - -// Key for the token in the session storage. -const TOKEN_KEY = "token"; - -// create cookie instance -const cookies = new Cookies(); - -// Dictionary holding component references. -export const refs = {}; - -// Flag ensures that only one event is processing on the backend concurrently. -let event_processing = false; -// Array holding pending events to be processed. -const event_queue = []; - -// Pending upload promises, by id -const upload_controllers = {}; - -/** - * Generate a UUID (Used for session tokens). - * Taken from: https://stackoverflow.com/questions/105034/how-do-i-create-a-guid-uuid - * @returns A UUID. - */ -export const generateUUID = () => { - let d = new Date().getTime(), - d2 = (performance && performance.now && performance.now() * 1000) || 0; - return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => { - let r = Math.random() * 16; - if (d > 0) { - r = (d + r) % 16 | 0; - d = Math.floor(d / 16); - } else { - r = (d2 + r) % 16 | 0; - d2 = Math.floor(d2 / 16); - } - return (c == "x" ? r : (r & 0x7) | 0x8).toString(16); - }); -}; - -/** - * Get the token for the current session. - * @returns The token. - */ -export const getToken = () => { - if (token) { - return token; - } - if (typeof window !== "undefined") { - if (!window.sessionStorage.getItem(TOKEN_KEY)) { - window.sessionStorage.setItem(TOKEN_KEY, generateUUID()); - } - token = window.sessionStorage.getItem(TOKEN_KEY); - } - return token; -}; - -/** - * Get the URL for the backend server - * @param url_str The URL string to parse. - * @returns The given URL modified to point to the actual backend server. - */ -export const getBackendURL = (url_str) => { - // Get backend URL object from the endpoint. - const endpoint = new URL(url_str); - if ( - typeof window !== "undefined" && - SAME_DOMAIN_HOSTNAMES.includes(endpoint.hostname) - ) { - // Use the frontend domain to access the backend - const frontend_hostname = window.location.hostname; - endpoint.hostname = frontend_hostname; - if (window.location.protocol === "https:") { - if (endpoint.protocol === "ws:") { - endpoint.protocol = "wss:"; - } else if (endpoint.protocol === "http:") { - endpoint.protocol = "https:"; - } - endpoint.port = ""; // Assume websocket is on https port via load balancer. - } - } - return endpoint; -}; - -/** - * Apply a delta to the state. - * @param state The state to apply the delta to. - * @param delta The delta to apply. - */ -export const applyDelta = (state, delta) => { - return { ...state, ...delta }; -}; - -/** - * Handle frontend event or send the event to the backend via Websocket. - * @param event The event to send. - * @param socket The socket object to send the event on. - * - * @returns True if the event was sent, false if it was handled locally. - */ -export const applyEvent = async (event, socket) => { - // Handle special events - if (event.name == "_redirect") { - if (event.payload.external) window.open(event.payload.path, "_blank"); - else Router.push(event.payload.path); - return false; - } - - if (event.name == "_console") { - console.log(event.payload.message); - return false; - } - - if (event.name == "_remove_cookie") { - cookies.remove(event.payload.key, { ...event.payload.options }); - queueEvents(initialEvents(), socket); - return false; - } - - if (event.name == "_clear_local_storage") { - localStorage.clear(); - queueEvents(initialEvents(), socket); - return false; - } - - if (event.name == "_remove_local_storage") { - localStorage.removeItem(event.payload.key); - queueEvents(initialEvents(), socket); - return false; - } - - if (event.name == "_set_clipboard") { - const content = event.payload.content; - navigator.clipboard.writeText(content); - return false; - } - - if (event.name == "_download") { - const a = document.createElement("a"); - a.hidden = true; - a.href = event.payload.url; - a.download = event.payload.filename; - a.click(); - a.remove(); - return false; - } - - if (event.name == "_alert") { - alert(event.payload.message); - return false; - } - - if (event.name == "_set_focus") { - const ref = - event.payload.ref in refs ? refs[event.payload.ref] : event.payload.ref; - ref.current.focus(); - return false; - } - - if (event.name == "_set_value") { - const ref = - event.payload.ref in refs ? refs[event.payload.ref] : event.payload.ref; - if (ref.current) { - ref.current.value = event.payload.value; - } - return false; - } - - if (event.name == "_call_script") { - try { - const eval_result = eval(event.payload.javascript_code); - if (event.payload.callback) { - if (!!eval_result && typeof eval_result.then === "function") { - eval(event.payload.callback)(await eval_result); - } else { - eval(event.payload.callback)(eval_result); - } - } - } catch (e) { - console.log("_call_script", e); - } - return false; - } - - // Update token and router data (if missing). - event.token = getToken(); - if ( - event.router_data === undefined || - Object.keys(event.router_data).length === 0 - ) { - event.router_data = (({ pathname, query, asPath }) => ({ - pathname, - query, - asPath, - }))(Router); - } - - // Send the event to the server. - if (socket) { - socket.emit( - "event", - JSON.stringify(event, (k, v) => (v === undefined ? null : v)) - ); - return true; - } - - return false; -}; - -/** - * Send an event to the server via REST. - * @param event The current event. - * @param socket The socket object to send the response event(s) on. - * - * @returns Whether the event was sent. - */ -export const applyRestEvent = async (event, socket) => { - let eventSent = false; - if (event.handler == "uploadFiles") { - // Start upload, but do not wait for it, which would block other events. - uploadFiles( - event.name, - event.payload.files, - event.payload.upload_id, - event.payload.on_upload_progress, - socket - ); - return false; - } - return eventSent; -}; - -/** - * Queue events to be processed and trigger processing of queue. - * @param events Array of events to queue. - * @param socket The socket object to send the event on. - */ -export const queueEvents = async (events, socket) => { - event_queue.push(...events); - await processEvent(socket.current); -}; - -/** - * Process an event off the event queue. - * @param socket The socket object to send the event on. - */ -export const processEvent = async (socket) => { - // Only proceed if the socket is up, otherwise we throw the event into the void - if (!socket) { - return; - } - - // Only proceed if we're not already processing an event. - if (event_queue.length === 0 || event_processing) { - return; - } - - // Set processing to true to block other events from being processed. - event_processing = true; - - // Apply the next event in the queue. - const event = event_queue.shift(); - - let eventSent = false; - // Process events with handlers via REST and all others via websockets. - if (event.handler) { - eventSent = await applyRestEvent(event, socket); - } else { - eventSent = await applyEvent(event, socket); - } - // If no event was sent, set processing to false. - if (!eventSent) { - event_processing = false; - // recursively call processEvent to drain the queue, since there is - // no state update to trigger the useEffect event loop. - await processEvent(socket); - } -}; - -/** - * Connect to a websocket and set the handlers. - * @param socket The socket object to connect. - * @param dispatch The function to queue state update - * @param transports The transports to use. - * @param setConnectErrors The function to update connection error value. - * @param client_storage The client storage object from context.js - */ -export const connect = async ( - socket, - dispatch, - transports, - setConnectErrors, - client_storage = {} -) => { - // Get backend URL object from the endpoint. - const endpoint = getBackendURL(EVENTURL); - - // Create the socket. - socket.current = io(endpoint.href, { - path: endpoint["pathname"], - transports: transports, - autoUnref: false, - }); - - function checkVisibility() { - if (document.visibilityState === "visible") { - if (!socket.current.connected) { - console.log("Socket is disconnected, attempting to reconnect "); - socket.current.connect(); - } else { - console.log("Socket is reconnected "); - } - } - } - - // Once the socket is open, hydrate the page. - socket.current.on("connect", () => { - setConnectErrors([]); - }); - - socket.current.on("connect_error", (error) => { - setConnectErrors((connectErrors) => [connectErrors.slice(-9), error]); - }); - // On each received message, queue the updates and events. - socket.current.on("event", (message) => { - const update = JSON5.parse(message); - for (const substate in update.delta) { - dispatch[substate](update.delta[substate]); - } - applyClientStorageDelta(client_storage, update.delta); - event_processing = !update.final; - if (update.events) { - queueEvents(update.events, socket); - } - }); - - document.addEventListener("visibilitychange", checkVisibility); -}; - -/** - * Upload files to the server. - * - * @param state The state to apply the delta to. - * @param handler The handler to use. - * @param upload_id The upload id to use. - * @param on_upload_progress The function to call on upload progress. - * @param socket the websocket connection - * - * @returns The response from posting to the UPLOADURL endpoint. - */ -export const uploadFiles = async ( - handler, - files, - upload_id, - on_upload_progress, - socket -) => { - // return if there's no file to upload - if (files === undefined || files.length === 0) { - return false; - } - - if (upload_controllers[upload_id]) { - console.log("Upload already in progress for ", upload_id); - return false; - } - - let resp_idx = 0; - const eventHandler = (progressEvent) => { - // handle any delta / event streamed from the upload event handler - const chunks = progressEvent.event.target.responseText.trim().split("\n"); - chunks.slice(resp_idx).map((chunk) => { - try { - socket._callbacks.$event.map((f) => { - f(chunk); - }); - resp_idx += 1; - } catch (e) { - if (progressEvent.progress === 1) { - // Chunk may be incomplete, so only report errors when full response is available. - console.log("Error parsing chunk", chunk, e); - } - return; - } - }); - }; - - const controller = new AbortController(); - const config = { - headers: { - "Reflex-Client-Token": getToken(), - "Reflex-Event-Handler": handler, - }, - signal: controller.signal, - onDownloadProgress: eventHandler, - }; - if (on_upload_progress) { - config["onUploadProgress"] = on_upload_progress; - } - const formdata = new FormData(); - - // Add the token and handler to the file name. - files.forEach((file) => { - formdata.append("files", file, file.path || file.name); - }); - - // Send the file to the server. - upload_controllers[upload_id] = controller; - - try { - return await axios.post(getBackendURL(UPLOADURL), formdata, config); - } catch (error) { - if (error.response) { - // The request was made and the server responded with a status code - // that falls out of the range of 2xx - console.log(error.response.data); - } else if (error.request) { - // The request was made but no response was received - // `error.request` is an instance of XMLHttpRequest in the browser and an instance of - // http.ClientRequest in node.js - console.log(error.request); - } else { - // Something happened in setting up the request that triggered an Error - console.log(error.message); - } - return false; - } finally { - delete upload_controllers[upload_id]; - } -}; - -/** - * Create an event object. - * @param name The name of the event. - * @param payload The payload of the event. - * @param handler The client handler to process event. - * @returns The event object. - */ -export const Event = (name, payload = {}, handler = null) => { - return { name, payload, handler }; -}; - -/** - * Package client-side storage values as payload to send to the - * backend with the hydrate event - * @param client_storage The client storage object from context.js - * @returns payload dict of client storage values - */ -export const hydrateClientStorage = (client_storage) => { - const client_storage_values = {}; - if (client_storage.cookies) { - for (const state_key in client_storage.cookies) { - const cookie_options = client_storage.cookies[state_key]; - const cookie_name = cookie_options.name || state_key; - const cookie_value = cookies.get(cookie_name); - if (cookie_value !== undefined) { - client_storage_values[state_key] = cookies.get(cookie_name); - } - } - } - if (client_storage.local_storage && typeof window !== "undefined") { - for (const state_key in client_storage.local_storage) { - const options = client_storage.local_storage[state_key]; - const local_storage_value = localStorage.getItem( - options.name || state_key - ); - if (local_storage_value !== null) { - client_storage_values[state_key] = local_storage_value; - } - } - } - if (client_storage.cookies || client_storage.local_storage) { - return client_storage_values; - } - return {}; -}; - -/** - * Update client storage values based on backend state delta. - * @param client_storage The client storage object from context.js - * @param delta The state update from the backend - */ -const applyClientStorageDelta = (client_storage, delta) => { - // find the main state and check for is_hydrated - const unqualified_states = Object.keys(delta).filter( - (key) => key.split(".").length === 1 - ); - if (unqualified_states.length === 1) { - const main_state = delta[unqualified_states[0]]; - if (main_state.is_hydrated !== undefined && !main_state.is_hydrated) { - // skip if the state is not hydrated yet, since all client storage - // values are sent in the hydrate event - return; - } - } - // Save known client storage values to cookies and localStorage. - for (const substate in delta) { - for (const key in delta[substate]) { - const state_key = `${substate}.${key}`; - if (client_storage.cookies && state_key in client_storage.cookies) { - const cookie_options = { ...client_storage.cookies[state_key] }; - const cookie_name = cookie_options.name || state_key; - delete cookie_options.name; // name is not a valid cookie option - cookies.set(cookie_name, delta[substate][key], cookie_options); - } else if ( - client_storage.local_storage && - state_key in client_storage.local_storage && - typeof window !== "undefined" - ) { - const options = client_storage.local_storage[state_key]; - localStorage.setItem(options.name || state_key, delta[substate][key]); - } - } - } -}; - -/** - * Establish websocket event loop for a NextJS page. - * @param dispatch The reducer dispatch function to update state. - * @param initial_events The initial app events. - * @param client_storage The client storage object from context.js - * - * @returns [addEvents, connectErrors] - - * addEvents is used to queue an event, and - * connectErrors is an array of reactive js error from the websocket connection (or null if connected). - */ -export const useEventLoop = ( - dispatch, - initial_events = () => [], - client_storage = {} -) => { - const socket = useRef(null); - const router = useRouter(); - const [connectErrors, setConnectErrors] = useState([]); - - // Function to add new events to the event queue. - const addEvents = (events, _e, event_actions) => { - if (event_actions?.preventDefault && _e?.preventDefault) { - _e.preventDefault(); - } - if (event_actions?.stopPropagation && _e?.stopPropagation) { - _e.stopPropagation(); - } - queueEvents(events, socket); - }; - - const sentHydrate = useRef(false); // Avoid double-hydrate due to React strict-mode - useEffect(() => { - if (router.isReady && !sentHydrate.current) { - const events = initial_events(); - addEvents( - events.map((e) => ({ - ...e, - router_data: (({ pathname, query, asPath }) => ({ - pathname, - query, - asPath, - }))(router), - })) - ); - sentHydrate.current = true; - } - }, [router.isReady]); - - // Main event loop. - useEffect(() => { - // Skip if the router is not ready. - if (!router.isReady) { - return; - } - // only use websockets if state is present - if (Object.keys(initialState).length > 1) { - // Initialize the websocket connection. - if (!socket.current) { - connect( - socket, - dispatch, - ["websocket", "polling"], - setConnectErrors, - client_storage - ); - } - (async () => { - // Process all outstanding events. - while (event_queue.length > 0 && !event_processing) { - await processEvent(socket.current); - } - })(); - } - }); - - // localStorage event handling - useEffect(() => { - const storage_to_state_map = {}; - - if (client_storage.local_storage && typeof window !== "undefined") { - for (const state_key in client_storage.local_storage) { - const options = client_storage.local_storage[state_key]; - if (options.sync) { - const local_storage_value_key = options.name || state_key; - storage_to_state_map[local_storage_value_key] = state_key; - } - } - } - - // e is StorageEvent - const handleStorage = (e) => { - if (storage_to_state_map[e.key]) { - const vars = {}; - vars[storage_to_state_map[e.key]] = e.newValue; - const event = Event( - `${state_name}.update_vars_internal_state.update_vars_internal`, - { vars: vars } - ); - addEvents([event], e); - } - }; - - window.addEventListener("storage", handleStorage); - return () => window.removeEventListener("storage", handleStorage); - }); - - // Route after the initial page hydration. - useEffect(() => { - const change_complete = () => addEvents(onLoadInternalEvent()); - router.events.on("routeChangeComplete", change_complete); - return () => { - router.events.off("routeChangeComplete", change_complete); - }; - }, [router]); - - return [addEvents, connectErrors]; -}; - -/*** - * Check if a value is truthy in python. - * @param val The value to check. - * @returns True if the value is truthy, false otherwise. - */ -export const isTrue = (val) => { - return Array.isArray(val) ? val.length > 0 : !!val; -}; - -/** - * Get the value from a ref. - * @param ref The ref to get the value from. - * @returns The value. - */ -export const getRefValue = (ref) => { - if (!ref || !ref.current) { - return; - } - if (ref.current.type == "checkbox") { - return ref.current.checked; // chakra - } else if ( - ref.current.className?.includes("rt-CheckboxButton") || - ref.current.className?.includes("rt-SwitchButton") - ) { - return ref.current.ariaChecked == "true"; // radix - } else if (ref.current.className?.includes("rt-SliderRoot")) { - // find the actual slider - return ref.current.querySelector(".rt-SliderThumb")?.ariaValueNow; - } else { - //querySelector(":checked") is needed to get value from radio_group - return ( - ref.current.value || - (ref.current.querySelector && - ref.current.querySelector(":checked") && - ref.current.querySelector(":checked")?.value) - ); - } -}; - -/** - * Get the values from a ref array. - * @param refs The refs to get the values from. - * @returns The values array. - */ -export const getRefValues = (refs) => { - if (!refs) { - return; - } - // getAttribute is used by RangeSlider because it doesn't assign value - return refs.map((ref) => - ref.current - ? ref.current.value || ref.current.getAttribute("aria-valuenow") - : null - ); -}; - -/** - * Spread two arrays or two objects. - * @param first The first array or object. - * @param second The second array or object. - * @returns The final merged array or object. - */ -export const spreadArraysOrObjects = (first, second) => { - if (Array.isArray(first) && Array.isArray(second)) { - return [...first, ...second]; - } else if (typeof first === "object" && typeof second === "object") { - return { ...first, ...second }; - } else { - throw new Error("Both parameters must be either arrays or objects."); - } -}; diff --git a/src/landing/assets/favicon.ico b/src/landing/assets/favicon.ico deleted file mode 100644 index 166ae99..0000000 Binary files a/src/landing/assets/favicon.ico and /dev/null differ diff --git a/src/landing/landing/__init__.py b/src/landing/landing/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/landing/landing/components/__init__.py b/src/landing/landing/components/__init__.py deleted file mode 100644 index 994f7d0..0000000 --- a/src/landing/landing/components/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from landing.shared.components import navbar -from .footer import footer diff --git a/src/landing/requirements.txt b/src/landing/requirements.txt deleted file mode 100644 index 239ae56..0000000 --- a/src/landing/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -reflex==0.4.4 diff --git a/src/shared/pages/__init__.py b/src/shared/pages/__init__.py deleted file mode 100644 index 895ac1f..0000000 --- a/src/shared/pages/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .page404 import page404 diff --git a/src/about/.dockerignore b/src/web/.dockerignore similarity index 100% rename from src/about/.dockerignore rename to src/web/.dockerignore diff --git a/src/about/.web/.gitignore b/src/web/.web/.gitignore similarity index 100% rename from src/about/.web/.gitignore rename to src/web/.web/.gitignore diff --git a/src/landing/.web/bun.lockb b/src/web/.web/bun.lockb similarity index 100% rename from src/landing/.web/bun.lockb rename to src/web/.web/bun.lockb diff --git a/src/about/.web/components/reflex/chakra_color_mode_provider.js b/src/web/.web/components/reflex/chakra_color_mode_provider.js similarity index 100% rename from src/about/.web/components/reflex/chakra_color_mode_provider.js rename to src/web/.web/components/reflex/chakra_color_mode_provider.js diff --git a/src/about/.web/components/reflex/radix_themes_color_mode_provider.js b/src/web/.web/components/reflex/radix_themes_color_mode_provider.js similarity index 100% rename from src/about/.web/components/reflex/radix_themes_color_mode_provider.js rename to src/web/.web/components/reflex/radix_themes_color_mode_provider.js diff --git a/src/landing/.web/env.json b/src/web/.web/env.json similarity index 100% rename from src/landing/.web/env.json rename to src/web/.web/env.json diff --git a/src/about/.web/jsconfig.json b/src/web/.web/jsconfig.json similarity index 100% rename from src/about/.web/jsconfig.json rename to src/web/.web/jsconfig.json diff --git a/src/about/.web/next.config.js b/src/web/.web/next.config.js similarity index 100% rename from src/about/.web/next.config.js rename to src/web/.web/next.config.js diff --git a/src/landing/.web/package.json b/src/web/.web/package.json similarity index 100% rename from src/landing/.web/package.json rename to src/web/.web/package.json diff --git a/src/landing/.web/pages/404.js b/src/web/.web/pages/404.js similarity index 100% rename from src/landing/.web/pages/404.js rename to src/web/.web/pages/404.js diff --git a/src/landing/.web/pages/_app.js b/src/web/.web/pages/_app.js similarity index 100% rename from src/landing/.web/pages/_app.js rename to src/web/.web/pages/_app.js diff --git a/src/landing/.web/pages/_document.js b/src/web/.web/pages/_document.js similarity index 100% rename from src/landing/.web/pages/_document.js rename to src/web/.web/pages/_document.js diff --git a/src/landing/.web/pages/index.js b/src/web/.web/pages/index.js similarity index 100% rename from src/landing/.web/pages/index.js rename to src/web/.web/pages/index.js diff --git a/src/about/.web/postcss.config.js b/src/web/.web/postcss.config.js similarity index 100% rename from src/about/.web/postcss.config.js rename to src/web/.web/postcss.config.js diff --git a/src/landing/.web/public/css/scrollbar.css b/src/web/.web/public/css/scrollbar.css similarity index 100% rename from src/landing/.web/public/css/scrollbar.css rename to src/web/.web/public/css/scrollbar.css diff --git a/src/about/assets/favicon.ico b/src/web/.web/public/favicon.ico similarity index 100% rename from src/about/assets/favicon.ico rename to src/web/.web/public/favicon.ico diff --git a/src/landing/.web/public/fonts/ComicCode-Bold.otf b/src/web/.web/public/fonts/ComicCode-Bold.otf similarity index 100% rename from src/landing/.web/public/fonts/ComicCode-Bold.otf rename to src/web/.web/public/fonts/ComicCode-Bold.otf diff --git a/src/landing/.web/public/fonts/ComicCode-BoldItalic.otf b/src/web/.web/public/fonts/ComicCode-BoldItalic.otf similarity index 100% rename from src/landing/.web/public/fonts/ComicCode-BoldItalic.otf rename to src/web/.web/public/fonts/ComicCode-BoldItalic.otf diff --git a/src/landing/.web/public/fonts/ComicCode-Italic.otf b/src/web/.web/public/fonts/ComicCode-Italic.otf similarity index 100% rename from src/landing/.web/public/fonts/ComicCode-Italic.otf rename to src/web/.web/public/fonts/ComicCode-Italic.otf diff --git a/src/landing/.web/public/fonts/ComicCode-Medium.otf b/src/web/.web/public/fonts/ComicCode-Medium.otf similarity index 100% rename from src/landing/.web/public/fonts/ComicCode-Medium.otf rename to src/web/.web/public/fonts/ComicCode-Medium.otf diff --git a/src/landing/.web/public/fonts/ComicCode-MediumItalic.otf b/src/web/.web/public/fonts/ComicCode-MediumItalic.otf similarity index 100% rename from src/landing/.web/public/fonts/ComicCode-MediumItalic.otf rename to src/web/.web/public/fonts/ComicCode-MediumItalic.otf diff --git a/src/landing/.web/public/fonts/ComicCode-Regular.otf b/src/web/.web/public/fonts/ComicCode-Regular.otf similarity index 100% rename from src/landing/.web/public/fonts/ComicCode-Regular.otf rename to src/web/.web/public/fonts/ComicCode-Regular.otf diff --git a/src/landing/.web/public/fonts/ComicCode-Regular.svg b/src/web/.web/public/fonts/ComicCode-Regular.svg similarity index 100% rename from src/landing/.web/public/fonts/ComicCode-Regular.svg rename to src/web/.web/public/fonts/ComicCode-Regular.svg diff --git a/src/landing/.web/public/fonts/ComicCodeLigatures-Bold.otf b/src/web/.web/public/fonts/ComicCodeLigatures-Bold.otf similarity index 100% rename from src/landing/.web/public/fonts/ComicCodeLigatures-Bold.otf rename to src/web/.web/public/fonts/ComicCodeLigatures-Bold.otf diff --git a/src/landing/.web/public/fonts/ComicCodeLigatures-BoldItalic.otf b/src/web/.web/public/fonts/ComicCodeLigatures-BoldItalic.otf similarity index 100% rename from src/landing/.web/public/fonts/ComicCodeLigatures-BoldItalic.otf rename to src/web/.web/public/fonts/ComicCodeLigatures-BoldItalic.otf diff --git a/src/landing/.web/public/fonts/ComicCodeLigatures-Italic.otf b/src/web/.web/public/fonts/ComicCodeLigatures-Italic.otf similarity index 100% rename from src/landing/.web/public/fonts/ComicCodeLigatures-Italic.otf rename to src/web/.web/public/fonts/ComicCodeLigatures-Italic.otf diff --git a/src/landing/.web/public/fonts/ComicCodeLigatures-Medium.otf b/src/web/.web/public/fonts/ComicCodeLigatures-Medium.otf similarity index 100% rename from src/landing/.web/public/fonts/ComicCodeLigatures-Medium.otf rename to src/web/.web/public/fonts/ComicCodeLigatures-Medium.otf diff --git a/src/landing/.web/public/fonts/ComicCodeLigatures-MediumItalic.otf b/src/web/.web/public/fonts/ComicCodeLigatures-MediumItalic.otf similarity index 100% rename from src/landing/.web/public/fonts/ComicCodeLigatures-MediumItalic.otf rename to src/web/.web/public/fonts/ComicCodeLigatures-MediumItalic.otf diff --git a/src/landing/.web/public/fonts/ComicCodeLigatures-Regular.otf b/src/web/.web/public/fonts/ComicCodeLigatures-Regular.otf similarity index 100% rename from src/landing/.web/public/fonts/ComicCodeLigatures-Regular.otf rename to src/web/.web/public/fonts/ComicCodeLigatures-Regular.otf diff --git a/src/landing/.web/public/fonts/fonts.css b/src/web/.web/public/fonts/fonts.css similarity index 100% rename from src/landing/.web/public/fonts/fonts.css rename to src/web/.web/public/fonts/fonts.css diff --git a/src/landing/.web/reflex.install_frontend_packages.cached b/src/web/.web/reflex.install_frontend_packages.cached similarity index 100% rename from src/landing/.web/reflex.install_frontend_packages.cached rename to src/web/.web/reflex.install_frontend_packages.cached diff --git a/src/landing/.web/reflex.json b/src/web/.web/reflex.json similarity index 100% rename from src/landing/.web/reflex.json rename to src/web/.web/reflex.json diff --git a/src/landing/.web/styles/styles.css b/src/web/.web/styles/styles.css similarity index 100% rename from src/landing/.web/styles/styles.css rename to src/web/.web/styles/styles.css diff --git a/src/about/.web/styles/tailwind.css b/src/web/.web/styles/tailwind.css similarity index 100% rename from src/about/.web/styles/tailwind.css rename to src/web/.web/styles/tailwind.css diff --git a/src/landing/.web/tailwind.config.js b/src/web/.web/tailwind.config.js similarity index 100% rename from src/landing/.web/tailwind.config.js rename to src/web/.web/tailwind.config.js diff --git a/src/about/.web/utils/client_side_routing.js b/src/web/.web/utils/client_side_routing.js similarity index 100% rename from src/about/.web/utils/client_side_routing.js rename to src/web/.web/utils/client_side_routing.js diff --git a/src/landing/.web/utils/components.js b/src/web/.web/utils/components.js similarity index 100% rename from src/landing/.web/utils/components.js rename to src/web/.web/utils/components.js diff --git a/src/landing/.web/utils/context.js b/src/web/.web/utils/context.js similarity index 100% rename from src/landing/.web/utils/context.js rename to src/web/.web/utils/context.js diff --git a/src/about/.web/utils/helpers/dataeditor.js b/src/web/.web/utils/helpers/dataeditor.js similarity index 100% rename from src/about/.web/utils/helpers/dataeditor.js rename to src/web/.web/utils/helpers/dataeditor.js diff --git a/src/about/.web/utils/helpers/range.js b/src/web/.web/utils/helpers/range.js similarity index 100% rename from src/about/.web/utils/helpers/range.js rename to src/web/.web/utils/helpers/range.js diff --git a/src/about/.web/utils/state.js b/src/web/.web/utils/state.js similarity index 100% rename from src/about/.web/utils/state.js rename to src/web/.web/utils/state.js diff --git a/src/landing/.web/utils/stateful_components.js b/src/web/.web/utils/stateful_components.js similarity index 100% rename from src/landing/.web/utils/stateful_components.js rename to src/web/.web/utils/stateful_components.js diff --git a/src/landing/.web/utils/theme.js b/src/web/.web/utils/theme.js similarity index 100% rename from src/landing/.web/utils/theme.js rename to src/web/.web/utils/theme.js diff --git a/src/landing/Dockerfile.dev b/src/web/Dockerfile.dev similarity index 100% rename from src/landing/Dockerfile.dev rename to src/web/Dockerfile.dev diff --git a/src/landing/assets/css/scrollbar.css b/src/web/assets/css/scrollbar.css similarity index 100% rename from src/landing/assets/css/scrollbar.css rename to src/web/assets/css/scrollbar.css diff --git a/src/landing/.web/public/favicon.ico b/src/web/assets/favicon.ico similarity index 100% rename from src/landing/.web/public/favicon.ico rename to src/web/assets/favicon.ico diff --git a/src/landing/assets/fonts/ComicCode-Bold.otf b/src/web/assets/fonts/ComicCode-Bold.otf similarity index 100% rename from src/landing/assets/fonts/ComicCode-Bold.otf rename to src/web/assets/fonts/ComicCode-Bold.otf diff --git a/src/landing/assets/fonts/ComicCode-BoldItalic.otf b/src/web/assets/fonts/ComicCode-BoldItalic.otf similarity index 100% rename from src/landing/assets/fonts/ComicCode-BoldItalic.otf rename to src/web/assets/fonts/ComicCode-BoldItalic.otf diff --git a/src/landing/assets/fonts/ComicCode-Italic.otf b/src/web/assets/fonts/ComicCode-Italic.otf similarity index 100% rename from src/landing/assets/fonts/ComicCode-Italic.otf rename to src/web/assets/fonts/ComicCode-Italic.otf diff --git a/src/landing/assets/fonts/ComicCode-Medium.otf b/src/web/assets/fonts/ComicCode-Medium.otf similarity index 100% rename from src/landing/assets/fonts/ComicCode-Medium.otf rename to src/web/assets/fonts/ComicCode-Medium.otf diff --git a/src/landing/assets/fonts/ComicCode-MediumItalic.otf b/src/web/assets/fonts/ComicCode-MediumItalic.otf similarity index 100% rename from src/landing/assets/fonts/ComicCode-MediumItalic.otf rename to src/web/assets/fonts/ComicCode-MediumItalic.otf diff --git a/src/landing/assets/fonts/ComicCode-Regular.otf b/src/web/assets/fonts/ComicCode-Regular.otf similarity index 100% rename from src/landing/assets/fonts/ComicCode-Regular.otf rename to src/web/assets/fonts/ComicCode-Regular.otf diff --git a/src/landing/assets/fonts/ComicCode-Regular.svg b/src/web/assets/fonts/ComicCode-Regular.svg similarity index 100% rename from src/landing/assets/fonts/ComicCode-Regular.svg rename to src/web/assets/fonts/ComicCode-Regular.svg diff --git a/src/landing/assets/fonts/ComicCodeLigatures-Bold.otf b/src/web/assets/fonts/ComicCodeLigatures-Bold.otf similarity index 100% rename from src/landing/assets/fonts/ComicCodeLigatures-Bold.otf rename to src/web/assets/fonts/ComicCodeLigatures-Bold.otf diff --git a/src/landing/assets/fonts/ComicCodeLigatures-BoldItalic.otf b/src/web/assets/fonts/ComicCodeLigatures-BoldItalic.otf similarity index 100% rename from src/landing/assets/fonts/ComicCodeLigatures-BoldItalic.otf rename to src/web/assets/fonts/ComicCodeLigatures-BoldItalic.otf diff --git a/src/landing/assets/fonts/ComicCodeLigatures-Italic.otf b/src/web/assets/fonts/ComicCodeLigatures-Italic.otf similarity index 100% rename from src/landing/assets/fonts/ComicCodeLigatures-Italic.otf rename to src/web/assets/fonts/ComicCodeLigatures-Italic.otf diff --git a/src/landing/assets/fonts/ComicCodeLigatures-Medium.otf b/src/web/assets/fonts/ComicCodeLigatures-Medium.otf similarity index 100% rename from src/landing/assets/fonts/ComicCodeLigatures-Medium.otf rename to src/web/assets/fonts/ComicCodeLigatures-Medium.otf diff --git a/src/landing/assets/fonts/ComicCodeLigatures-MediumItalic.otf b/src/web/assets/fonts/ComicCodeLigatures-MediumItalic.otf similarity index 100% rename from src/landing/assets/fonts/ComicCodeLigatures-MediumItalic.otf rename to src/web/assets/fonts/ComicCodeLigatures-MediumItalic.otf diff --git a/src/landing/assets/fonts/ComicCodeLigatures-Regular.otf b/src/web/assets/fonts/ComicCodeLigatures-Regular.otf similarity index 100% rename from src/landing/assets/fonts/ComicCodeLigatures-Regular.otf rename to src/web/assets/fonts/ComicCodeLigatures-Regular.otf diff --git a/src/landing/assets/fonts/fonts.css b/src/web/assets/fonts/fonts.css similarity index 100% rename from src/landing/assets/fonts/fonts.css rename to src/web/assets/fonts/fonts.css diff --git a/src/about/requirements.txt b/src/web/requirements.txt similarity index 100% rename from src/about/requirements.txt rename to src/web/requirements.txt diff --git a/src/landing/rxconfig.py b/src/web/rxconfig.py similarity index 76% rename from src/landing/rxconfig.py rename to src/web/rxconfig.py index 2a54299..537dfe5 100644 --- a/src/landing/rxconfig.py +++ b/src/web/rxconfig.py @@ -1,6 +1,6 @@ import reflex as rx config = rx.Config( - app_name="landing", + app_name="web", api_url="http://localhost:8000", ) diff --git a/src/about/about/__init__.py b/src/web/web/__init__.py similarity index 100% rename from src/about/about/__init__.py rename to src/web/web/__init__.py diff --git a/src/shared/components/__init__.py b/src/web/web/components/__init__.py similarity index 50% rename from src/shared/components/__init__.py rename to src/web/web/components/__init__.py index aa6cfd2..a830f66 100644 --- a/src/shared/components/__init__.py +++ b/src/web/web/components/__init__.py @@ -1 +1,2 @@ from .navbar import navbar +from .footer import footer diff --git a/src/landing/landing/components/footer.py b/src/web/web/components/footer.py similarity index 92% rename from src/landing/landing/components/footer.py rename to src/web/web/components/footer.py index dfbe77d..51e40d3 100644 --- a/src/landing/landing/components/footer.py +++ b/src/web/web/components/footer.py @@ -1,5 +1,5 @@ import reflex as rx -from landing.style import * +from web.style import * def footer(): return rx.box( diff --git a/src/shared/components/navbar.py b/src/web/web/components/navbar.py similarity index 97% rename from src/shared/components/navbar.py rename to src/web/web/components/navbar.py index a7a6bd7..578cd39 100644 --- a/src/shared/components/navbar.py +++ b/src/web/web/components/navbar.py @@ -1,5 +1,5 @@ import reflex as rx -from landing.style import * +from web.style import * def navbar(): return rx.box( diff --git a/src/landing/landing/pages/__init__.py b/src/web/web/pages/__init__.py similarity index 65% rename from src/landing/landing/pages/__init__.py rename to src/web/web/pages/__init__.py index fc95cdc..126ce4b 100644 --- a/src/landing/landing/pages/__init__.py +++ b/src/web/web/pages/__init__.py @@ -1,7 +1,7 @@ -from landing.route import Route +from web.route import Route from .index import index -from landing.shared.pages import page404 +from .page404 import page404 routes = [ *[r for r in locals().values() if isinstance(r, Route)], diff --git a/src/landing/landing/pages/index.py b/src/web/web/pages/index.py similarity index 81% rename from src/landing/landing/pages/index.py rename to src/web/web/pages/index.py index 76fafdd..54a38e9 100644 --- a/src/landing/landing/pages/index.py +++ b/src/web/web/pages/index.py @@ -1,6 +1,6 @@ import reflex as rx -from landing.components import navbar -from landing.templates import webpage +from web.components import navbar +from web.templates import webpage @webpage(path="/", title="Timothy Pidashev") def index() -> rx.Component: diff --git a/src/shared/pages/page404.py b/src/web/web/pages/page404.py similarity index 89% rename from src/shared/pages/page404.py rename to src/web/web/pages/page404.py index 9e78b0c..2c18b77 100644 --- a/src/shared/pages/page404.py +++ b/src/web/web/pages/page404.py @@ -1,5 +1,5 @@ import reflex as rx -from landing.templates import webpage +from web.templates import webpage # TODO: Add a go back here link diff --git a/src/landing/landing/route.py b/src/web/web/route.py similarity index 96% rename from src/landing/landing/route.py rename to src/web/web/route.py index 89c2c6f..741a7d1 100644 --- a/src/landing/landing/route.py +++ b/src/web/web/route.py @@ -26,4 +26,4 @@ def get_path(component_function: Callable): module = inspect.getmodule(component_function) # Create a path based on the module name. - return module.__name__.replace(".", "/").replace("_", "-").split("landing/pages")[1] + return module.__name__.replace(".", "/").replace("_", "-").split("web/pages")[1] diff --git a/src/landing/landing/state/__init__.py b/src/web/web/state/__init__.py similarity index 100% rename from src/landing/landing/state/__init__.py rename to src/web/web/state/__init__.py diff --git a/src/landing/landing/state/state.py b/src/web/web/state/state.py similarity index 100% rename from src/landing/landing/state/state.py rename to src/web/web/state/state.py diff --git a/src/landing/landing/state/theme.py b/src/web/web/state/theme.py similarity index 92% rename from src/landing/landing/state/theme.py rename to src/web/web/state/theme.py index a17e9e5..fb9e517 100644 --- a/src/landing/landing/state/theme.py +++ b/src/web/web/state/theme.py @@ -1,6 +1,6 @@ import reflex as rx from .state import State -from landing.style import * +from web.style import * from typing import Dict, Any, List diff --git a/src/landing/landing/style.py b/src/web/web/style.py similarity index 100% rename from src/landing/landing/style.py rename to src/web/web/style.py diff --git a/src/landing/landing/templates/__init__.py b/src/web/web/templates/__init__.py similarity index 100% rename from src/landing/landing/templates/__init__.py rename to src/web/web/templates/__init__.py diff --git a/src/landing/landing/templates/webpage.py b/src/web/web/templates/webpage.py similarity index 90% rename from src/landing/landing/templates/webpage.py rename to src/web/web/templates/webpage.py index 1c46e31..575e846 100644 --- a/src/landing/landing/templates/webpage.py +++ b/src/web/web/templates/webpage.py @@ -1,6 +1,6 @@ from typing import Callable import reflex as rx -from landing.route import Route +from web.route import Route def webpage(path: str, title: str = "Timothy Pidashev", props=None) -> Callable: """This template wraps the webpage with the navbar and footer. @@ -36,8 +36,8 @@ def webpage(path: str, title: str = "Timothy Pidashev", props=None) -> Callable: The component with the template applied. """ # Import here to avoid circular imports. - from landing.shared.components.navbar import navbar - from landing.components.footer import footer + from web.components.navbar import navbar + from web.components.footer import footer # Wrap the component in the template. return rx.box( diff --git a/src/landing/landing/landing.py b/src/web/web/web.py similarity index 81% rename from src/landing/landing/landing.py rename to src/web/web/web.py index cd79a8e..15a5b8f 100644 --- a/src/landing/landing/landing.py +++ b/src/web/web/web.py @@ -1,8 +1,8 @@ import reflex as rx from rxconfig import config -from landing.state import * -from landing.pages import * -from landing.style import * +from web.state import * +from web.pages import * +from web.style import * # Create app instance and add index page. app = rx.App(