add frontend skeleton
This commit is contained in:
		
							parent
							
								
									0c52ebb7bc
								
							
						
					
					
						commit
						a80f89d038
					
				
					 23 changed files with 2110 additions and 3 deletions
				
			
		
							
								
								
									
										6
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -1,3 +1,9 @@ | |||
| __pycache__/ | ||||
| .pytest_cache/ | ||||
| .env | ||||
| node_modules | ||||
| build | ||||
| .svelte-kit | ||||
| package | ||||
| vite.config.js.timestamp-* | ||||
| vite.config.ts.timestamp-* | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ from quart import Quart, g, request | |||
| from quart_cors import cors | ||||
| from quart_schema import QuartSchema, RequestSchemaValidationError | ||||
| 
 | ||||
| from .blueprints import members_blueprint, users_blueprint | ||||
| from . import blueprints | ||||
| from .db.aio import async_session | ||||
| from .db.util import validate_token | ||||
| from .exceptions import ErrorCode, ExpectedError | ||||
|  | @ -17,7 +17,11 @@ app = cors( | |||
| ) | ||||
| QuartSchema(app) | ||||
| 
 | ||||
| for bp in (users_blueprint, members_blueprint): | ||||
| for bp in ( | ||||
|     blueprints.users_blueprint, | ||||
|     blueprints.members_blueprint, | ||||
|     blueprints.meta_blueprint, | ||||
| ): | ||||
|     app.register_blueprint(bp) | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,4 +1,5 @@ | |||
| from .v2.members import bp as members_blueprint | ||||
| from .v2.users import bp as users_blueprint | ||||
| from .v2.meta import bp as meta_blueprint | ||||
| 
 | ||||
| __all__ = [users_blueprint, members_blueprint] | ||||
| __all__ = [users_blueprint, members_blueprint, meta_blueprint] | ||||
|  |  | |||
							
								
								
									
										26
									
								
								foxnouns/blueprints/v2/meta.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								foxnouns/blueprints/v2/meta.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,26 @@ | |||
| from pydantic import BaseModel | ||||
| from quart import Blueprint | ||||
| from quart_schema import validate_response | ||||
| from sqlalchemy import select | ||||
| from sqlalchemy.sql import func | ||||
| 
 | ||||
| from foxnouns.db import User, Member | ||||
| from foxnouns.db.aio import async_session | ||||
| from foxnouns.settings import BASE_DOMAIN | ||||
| 
 | ||||
| bp = Blueprint("meta_v2", __name__) | ||||
| 
 | ||||
| 
 | ||||
| class MetaResponse(BaseModel): | ||||
|     users: int | ||||
|     members: int | ||||
| 
 | ||||
| 
 | ||||
| @bp.get("/api/v2/meta", host=BASE_DOMAIN) | ||||
| @validate_response(MetaResponse) | ||||
| async def meta(): | ||||
|     async with async_session() as session: | ||||
|         user_count = await session.scalar(select(func.count()).select_from(User)) | ||||
|         member_count = await session.scalar(select(func.count()).select_from(Member)) | ||||
| 
 | ||||
|         return MetaResponse(users=user_count, members=member_count) | ||||
							
								
								
									
										13
									
								
								frontend/.eslintignore
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								frontend/.eslintignore
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | |||
| .DS_Store | ||||
| node_modules | ||||
| /build | ||||
| /.svelte-kit | ||||
| /package | ||||
| .env | ||||
| .env.* | ||||
| !.env.example | ||||
| 
 | ||||
| # Ignore files for PNPM, NPM and YARN | ||||
| pnpm-lock.yaml | ||||
| package-lock.json | ||||
| yarn.lock | ||||
							
								
								
									
										31
									
								
								frontend/.eslintrc.cjs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								frontend/.eslintrc.cjs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,31 @@ | |||
| /** @type { import("eslint").Linter.Config } */ | ||||
| module.exports = { | ||||
| 	root: true, | ||||
| 	extends: [ | ||||
| 		"eslint:recommended", | ||||
| 		"plugin:@typescript-eslint/recommended", | ||||
| 		"plugin:svelte/recommended", | ||||
| 		"prettier", | ||||
| 	], | ||||
| 	parser: "@typescript-eslint/parser", | ||||
| 	plugins: ["@typescript-eslint"], | ||||
| 	parserOptions: { | ||||
| 		sourceType: "module", | ||||
| 		ecmaVersion: 2020, | ||||
| 		extraFileExtensions: [".svelte"], | ||||
| 	}, | ||||
| 	env: { | ||||
| 		browser: true, | ||||
| 		es2017: true, | ||||
| 		node: true, | ||||
| 	}, | ||||
| 	overrides: [ | ||||
| 		{ | ||||
| 			files: ["*.svelte"], | ||||
| 			parser: "svelte-eslint-parser", | ||||
| 			parserOptions: { | ||||
| 				parser: "@typescript-eslint/parser", | ||||
| 			}, | ||||
| 		}, | ||||
| 	], | ||||
| }; | ||||
							
								
								
									
										1
									
								
								frontend/.npmrc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								frontend/.npmrc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | |||
| engine-strict=true | ||||
							
								
								
									
										4
									
								
								frontend/.prettierignore
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								frontend/.prettierignore
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | |||
| pnpm-lock.yaml | ||||
| package-lock.json | ||||
| yarn.lock | ||||
| .svelte-kit | ||||
							
								
								
									
										6
									
								
								frontend/.prettierrc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								frontend/.prettierrc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | |||
| { | ||||
| 	"useTabs": true, | ||||
| 	"printWidth": 100, | ||||
| 	"plugins": ["prettier-plugin-svelte"], | ||||
| 	"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] | ||||
| } | ||||
							
								
								
									
										38
									
								
								frontend/README.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								frontend/README.md
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,38 @@ | |||
| # create-svelte | ||||
| 
 | ||||
| Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte). | ||||
| 
 | ||||
| ## Creating a project | ||||
| 
 | ||||
| If you're seeing this, you've probably already done this step. Congrats! | ||||
| 
 | ||||
| ```bash | ||||
| # create a new project in the current directory | ||||
| npm create svelte@latest | ||||
| 
 | ||||
| # create a new project in my-app | ||||
| npm create svelte@latest my-app | ||||
| ``` | ||||
| 
 | ||||
| ## Developing | ||||
| 
 | ||||
| Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: | ||||
| 
 | ||||
| ```bash | ||||
| npm run dev | ||||
| 
 | ||||
| # or start the server and open the app in a new browser tab | ||||
| npm run dev -- --open | ||||
| ``` | ||||
| 
 | ||||
| ## Building | ||||
| 
 | ||||
| To create a production version of your app: | ||||
| 
 | ||||
| ```bash | ||||
| npm run build | ||||
| ``` | ||||
| 
 | ||||
| You can preview the production build with `npm run preview`. | ||||
| 
 | ||||
| > To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment. | ||||
							
								
								
									
										39
									
								
								frontend/package.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								frontend/package.json
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,39 @@ | |||
| { | ||||
| 	"name": "frontend", | ||||
| 	"version": "0.0.1", | ||||
| 	"private": true, | ||||
| 	"scripts": { | ||||
| 		"dev": "vite dev", | ||||
| 		"build": "vite build", | ||||
| 		"preview": "vite preview", | ||||
| 		"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", | ||||
| 		"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", | ||||
| 		"lint": "prettier --check . && eslint .", | ||||
| 		"format": "prettier --write ." | ||||
| 	}, | ||||
| 	"devDependencies": { | ||||
| 		"@sveltejs/adapter-auto": "^3.0.0", | ||||
| 		"@sveltejs/kit": "^2.0.0", | ||||
| 		"@sveltejs/vite-plugin-svelte": "^3.0.0", | ||||
| 		"@types/eslint": "^8.56.0", | ||||
| 		"@typescript-eslint/eslint-plugin": "^7.0.0", | ||||
| 		"@typescript-eslint/parser": "^7.0.0", | ||||
| 		"eslint": "^8.56.0", | ||||
| 		"eslint-config-prettier": "^9.1.0", | ||||
| 		"eslint-plugin-svelte": "^2.35.1", | ||||
| 		"prettier": "^3.1.1", | ||||
| 		"prettier-plugin-svelte": "^3.1.2", | ||||
| 		"sass": "^1.72.0", | ||||
| 		"svelte": "^4.2.7", | ||||
| 		"svelte-check": "^3.6.0", | ||||
| 		"tslib": "^2.4.1", | ||||
| 		"typescript": "^5.0.0", | ||||
| 		"vite": "^5.0.3" | ||||
| 	}, | ||||
| 	"type": "module", | ||||
| 	"dependencies": { | ||||
| 		"@sveltestrap/sveltestrap": "^6.2.7", | ||||
| 		"bootstrap": "^5.3.3", | ||||
| 		"bootstrap-icons": "^1.11.3" | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										13
									
								
								frontend/src/app.d.ts
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								frontend/src/app.d.ts
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | |||
| // See https://kit.svelte.dev/docs/types#app
 | ||||
| // for information about these interfaces
 | ||||
| declare global { | ||||
| 	namespace App { | ||||
| 		// interface Error {}
 | ||||
| 		// interface Locals {}
 | ||||
| 		// interface PageData {}
 | ||||
| 		// interface PageState {}
 | ||||
| 		// interface Platform {}
 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| export {}; | ||||
							
								
								
									
										12
									
								
								frontend/src/app.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								frontend/src/app.html
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,12 @@ | |||
| <!doctype html> | ||||
| <html lang="en"> | ||||
| 	<head> | ||||
| 		<meta charset="utf-8" /> | ||||
| 		<link rel="icon" href="%sveltekit.assets%/favicon.png" /> | ||||
| 		<meta name="viewport" content="width=device-width, initial-scale=1" /> | ||||
| 		%sveltekit.head% | ||||
| 	</head> | ||||
| 	<body data-sveltekit-preload-data="hover"> | ||||
| 		<div style="display: contents">%sveltekit.body%</div> | ||||
| 	</body> | ||||
| </html> | ||||
							
								
								
									
										1
									
								
								frontend/src/lib/index.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								frontend/src/lib/index.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | |||
| // place files you want to import through the `$lib` alias in this folder.
 | ||||
							
								
								
									
										63
									
								
								frontend/src/lib/request.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								frontend/src/lib/request.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,63 @@ | |||
| export type FetchOptions = { | ||||
| 	fetchFn?: typeof fetch; | ||||
| 	// eslint-disable-next-line @typescript-eslint/no-explicit-any
 | ||||
| 	data?: any; | ||||
| 	version?: number; | ||||
| 	extraHeaders?: Record<string, string>; | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * Fetch a path from the API and parse the response. | ||||
|  * To make sure the request is authenticated in load functions, | ||||
|  * pass `fetch` from the request object into opts. | ||||
|  * | ||||
|  * @param method The HTTP method, i.e. GET, POST, PATCH | ||||
|  * @param path The path to request, minus the leading `/api/v2` | ||||
|  * @param opts Extra options for this request | ||||
|  * @returns T | ||||
|  * @throws APIError | ||||
|  */ | ||||
| export default async function request<T>( | ||||
| 	method: string, | ||||
| 	path: string, | ||||
| 	opts: FetchOptions = {}, | ||||
| ): Promise<T> { | ||||
| 	const { data, version, extraHeaders } = opts; | ||||
| 	const fetchFn = opts.fetchFn ?? fetch; | ||||
| 
 | ||||
| 	const resp = await fetchFn(`/api/v${version ?? 2}${path}`, { | ||||
| 		method, | ||||
| 		body: data ? JSON.stringify(data) : undefined, | ||||
| 		headers: { ...extraHeaders, "Content-Type": "application/json" }, | ||||
| 	}); | ||||
| 
 | ||||
| 	if (resp.status < 200 || resp.status >= 400) throw await resp.json(); | ||||
| 	return (await resp.json()) as T; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Fetch a path from the API and discard the response. | ||||
|  * To make sure the request is authenticated in load functions, | ||||
|  * pass `fetch` from the request object into opts. | ||||
|  * | ||||
|  * @param method The HTTP method, i.e. GET, POST, PATCH | ||||
|  * @param path The path to request, minus the leading `/api/v2` | ||||
|  * @param opts Extra options for this request | ||||
|  * @throws APIError | ||||
|  */ | ||||
| export async function fastRequest( | ||||
| 	method: string, | ||||
| 	path: string, | ||||
| 	opts: FetchOptions = {}, | ||||
| ): Promise<void> { | ||||
| 	const { data, version, extraHeaders } = opts; | ||||
| 	const fetchFn = opts.fetchFn ?? fetch; | ||||
| 
 | ||||
| 	const resp = await fetchFn(`/api/v2${version ?? 2}${path}`, { | ||||
| 		method, | ||||
| 		body: data ? JSON.stringify(data) : undefined, | ||||
| 		headers: { ...extraHeaders, "Content-Type": "application/json" }, | ||||
| 	}); | ||||
| 
 | ||||
| 	if (resp.status < 200 || resp.status >= 400) throw await resp.json(); | ||||
| } | ||||
							
								
								
									
										12
									
								
								frontend/src/routes/+layout.server.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								frontend/src/routes/+layout.server.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,12 @@ | |||
| import request from "$lib/request"; | ||||
| 
 | ||||
| export async function load({ fetch, cookies }) { | ||||
| 	const meta = await request("GET", "/meta", { fetchFn: fetch }); | ||||
| 
 | ||||
| 	let user; | ||||
| 	if (cookies.get("pronounscc-token")) { | ||||
| 		user = await request("GET", "/users/@me", { fetchFn: fetch }); | ||||
| 	} | ||||
| 
 | ||||
| 	return { meta, user }; | ||||
| } | ||||
							
								
								
									
										11
									
								
								frontend/src/routes/+layout.svelte
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								frontend/src/routes/+layout.svelte
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | |||
| <script lang="ts"> | ||||
| 	import "bootstrap/scss/bootstrap.scss"; | ||||
| 	import "bootstrap-icons/font/bootstrap-icons.scss"; | ||||
| 	import type { LayoutData } from "./$types"; | ||||
| 
 | ||||
| 	export let data: LayoutData | ||||
| </script> | ||||
| 
 | ||||
| {JSON.stringify(data.meta)} | ||||
| 
 | ||||
| <slot /> | ||||
							
								
								
									
										2
									
								
								frontend/src/routes/+page.svelte
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								frontend/src/routes/+page.svelte
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,2 @@ | |||
| <h1>Welcome to SvelteKit</h1> | ||||
| <p>Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p> | ||||
							
								
								
									
										
											BIN
										
									
								
								frontend/static/favicon.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								frontend/static/favicon.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 1.5 KiB | 
							
								
								
									
										22
									
								
								frontend/svelte.config.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								frontend/svelte.config.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | |||
| import adapter from "@sveltejs/adapter-auto"; | ||||
| import { vitePreprocess } from "@sveltejs/vite-plugin-svelte"; | ||||
| import * as child_process from "node:child_process"; | ||||
| 
 | ||||
| /** @type {import('@sveltejs/kit').Config} */ | ||||
| const config = { | ||||
| 	// Consult https://kit.svelte.dev/docs/integrations#preprocessors
 | ||||
| 	// for more information about preprocessors
 | ||||
| 	preprocess: vitePreprocess(), | ||||
| 
 | ||||
| 	kit: { | ||||
| 		// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
 | ||||
| 		// If your environment is not supported or you settled on a specific environment, switch out the adapter.
 | ||||
| 		// See https://kit.svelte.dev/docs/adapters for more information about adapters.
 | ||||
| 		adapter: adapter(), | ||||
| 		version: { | ||||
| 			name: child_process.execSync("git describe --tags --long --always").toString().trim(), | ||||
| 		}, | ||||
| 	}, | ||||
| }; | ||||
| 
 | ||||
| export default config; | ||||
							
								
								
									
										19
									
								
								frontend/tsconfig.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								frontend/tsconfig.json
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | |||
| { | ||||
| 	"extends": "./.svelte-kit/tsconfig.json", | ||||
| 	"compilerOptions": { | ||||
| 		"allowJs": true, | ||||
| 		"checkJs": true, | ||||
| 		"esModuleInterop": true, | ||||
| 		"forceConsistentCasingInFileNames": true, | ||||
| 		"resolveJsonModule": true, | ||||
| 		"skipLibCheck": true, | ||||
| 		"sourceMap": true, | ||||
| 		"strict": true, | ||||
| 		"moduleResolution": "bundler" | ||||
| 	} | ||||
| 	// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias | ||||
| 	// except $lib which is handled by https://kit.svelte.dev/docs/configuration#files | ||||
| 	// | ||||
| 	// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes | ||||
| 	// from the referenced tsconfig.json - TypeScript does not merge them in | ||||
| } | ||||
							
								
								
									
										23
									
								
								frontend/vite.config.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								frontend/vite.config.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,23 @@ | |||
| import { sveltekit } from "@sveltejs/kit/vite"; | ||||
| import { defineConfig } from "vite"; | ||||
| 
 | ||||
| export default defineConfig({ | ||||
| 	plugins: [sveltekit()], | ||||
| 	server: { | ||||
| 		host: "127.0.0.1", | ||||
| 		proxy: { | ||||
| 			"/api": { | ||||
| 				target: "http://localhost:5000", | ||||
| 				changeOrigin: true, | ||||
| 			}, | ||||
| 			"/media": { | ||||
| 				target: "http://localhost:9000", | ||||
| 				changeOrigin: true, | ||||
| 				rewrite: (path) => path.replace(/^\/media/, "/pronouns.cc"), | ||||
| 			}, | ||||
| 		}, | ||||
| 	}, | ||||
| 	ssr: { | ||||
| 		noExternal: ["@popperjs/core"], | ||||
| 	}, | ||||
| }); | ||||
							
								
								
									
										1760
									
								
								frontend/yarn.lock
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1760
									
								
								frontend/yarn.lock
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue