From b36d8d4f123dd0479942c8a6c8cf902774f5491e Mon Sep 17 00:00:00 2001 From: Thad Kerosky Date: Wed, 18 Oct 2023 01:19:06 +0000 Subject: [PATCH] Form trial ensemble programming Co-authored-by: plocket Co-authored-by: Gavin Kimball Co-authored-by: Leopardfoot Co-authored-by: Jeff Korenstein --- heat-stack/app/root-original.tsx | 501 ++++++++++++++++++++ heat-stack/app/root.tsx | 122 +++-- heat-stack/app/routes/_marketing+/index.tsx | 24 - 3 files changed, 578 insertions(+), 69 deletions(-) create mode 100644 heat-stack/app/root-original.tsx diff --git a/heat-stack/app/root-original.tsx b/heat-stack/app/root-original.tsx new file mode 100644 index 00000000..83f3d10a --- /dev/null +++ b/heat-stack/app/root-original.tsx @@ -0,0 +1,501 @@ +import { useForm } from '@conform-to/react' +import { parse } from '@conform-to/zod' +import { cssBundleHref } from '@remix-run/css-bundle' +import { + json, + type DataFunctionArgs, + type HeadersFunction, + type LinksFunction, + type MetaFunction, +} from '@remix-run/node' +import { + Form, + Link, + Links, + LiveReload, + Meta, + Outlet, + Scripts, + ScrollRestoration, + useFetcher, + useFetchers, + useLoaderData, + useMatches, + useSubmit, +} from '@remix-run/react' +import { withSentry } from '@sentry/remix' +import { Suspense, lazy, useEffect, useRef, useState } from 'react' +import { object, z } from 'zod' +import { Confetti } from './components/confetti.tsx' +import { GeneralErrorBoundary } from './components/error-boundary.tsx' +import { ErrorList } from './components/forms.tsx' +import { SearchBar } from './components/search-bar.tsx' +import { EpicToaster } from './components/toaster.tsx' +import { Button } from './components/ui/button.tsx' +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuPortal, + DropdownMenuTrigger, +} from './components/ui/dropdown-menu.tsx' +import { Icon, href as iconsHref } from './components/ui/icon.tsx' +import fontStyleSheetUrl from './styles/font.css' +import tailwindStyleSheetUrl from './styles/tailwind.css' +import { authenticator, getUserId } from './utils/auth.server.ts' +import { ClientHintCheck, getHints, useHints } from './utils/client-hints.tsx' +import { getConfetti } from './utils/confetti.server.ts' +import { prisma } from './utils/db.server.ts' +import { getEnv } from './utils/env.server.ts' +import { + combineHeaders, + getDomainUrl, + getUserImgSrc, + invariantResponse, +} from './utils/misc.tsx' +import { useNonce } from './utils/nonce-provider.ts' +import { useRequestInfo } from './utils/request-info.ts' +import { type Theme, setTheme, getTheme } from './utils/theme.server.ts' +import { makeTimings, time } from './utils/timing.server.ts' +import { getToast } from './utils/toast.server.ts' +import { useOptionalUser, useUser } from './utils/user.ts' + +import { WeatherExample } from './components/WeatherExample.tsx' +import type { Weather } from './WeatherExample.d.ts'; + +import * as pyodideModule from 'pyodide' +import engine from '../../rules-engine/src/rules_engine/engine.py'; + +const getPyodide = async () => { + // public folder: + return await pyodideModule.loadPyodide({ + indexURL: 'pyodide-env/', + }) +} +declare global { + interface Window { + pydd?: any; + } + } + +const runPythonScript = async () => { + const pyodide: any = await getPyodide(); + // console.log(engine); + await pyodide.loadPackage("numpy") + await pyodide.runPythonAsync(engine); + window.pydd = pyodide as null; + + return pyodide; +}; + + +export const links: LinksFunction = () => { + return [ + // Preload svg sprite as a resource to avoid render blocking + { rel: 'preload', href: iconsHref, as: 'image' }, + // Preload CSS as a resource to avoid render blocking + { rel: 'preload', href: fontStyleSheetUrl, as: 'style' }, + { rel: 'preload', href: tailwindStyleSheetUrl, as: 'style' }, + cssBundleHref ? { rel: 'preload', href: cssBundleHref, as: 'style' } : null, + { rel: 'mask-icon', href: '/favicons/mask-icon.svg' }, + { + rel: 'alternate icon', + type: 'image/png', + href: '/favicons/favicon-32x32.png', + }, + { rel: 'apple-touch-icon', href: '/favicons/apple-touch-icon.png' }, + { + rel: 'manifest', + href: '/site.webmanifest', + crossOrigin: 'use-credentials', + } as const, // necessary to make typescript happy + //These should match the css preloads above to avoid css as render blocking resource + { rel: 'icon', type: 'image/svg+xml', href: '/favicons/favicon.svg' }, + { rel: 'stylesheet', href: fontStyleSheetUrl }, + { rel: 'stylesheet', href: tailwindStyleSheetUrl }, + cssBundleHref ? { rel: 'stylesheet', href: cssBundleHref } : null, + ].filter(Boolean) +} + +export const meta: MetaFunction = ({ data }) => { + return [ + { title: data ? 'Epic Notes' : 'Error | Epic Notes' }, + { name: 'description', content: `Your own captain's log` }, + ] +} + +// We can only have one `loader()`. More requires special gymnastics. +export async function loader({ request }: DataFunctionArgs) { + const timings = makeTimings('root loader') + const userId = await time(() => getUserId(request), { + timings, + type: 'getUserId', + desc: 'getUserId in root', + }) + + const user = userId + ? await time( + () => + prisma.user.findUniqueOrThrow({ + select: { + id: true, + name: true, + username: true, + image: { select: { id: true } }, + roles: { + select: { + name: true, + permissions: { + select: { entity: true, action: true, access: true }, + }, + }, + }, + }, + where: { id: userId }, + }), + { timings, type: 'find user', desc: 'find user in root' }, + ) + : null + if (userId && !user) { + console.info('something weird happened') + // something weird happened... The user is authenticated but we can't find + // them in the database. Maybe they were deleted? Let's log them out. + await authenticator.logout(request, { redirectTo: '/' }) + } + const { toast, headers: toastHeaders } = await getToast(request) + const { confettiId, headers: confettiHeaders } = getConfetti(request) + + // Weather station data + const w_href: string = 'https://archive-api.open-meteo.com/v1/archive?latitude=52.52&longitude=13.41&daily=temperature_2m_max&timezone=America%2FNew_York&start_date=2022-01-01&end_date=2023-08-30&temperature_unit=fahrenheit'; + const w_res: Response = await fetch(w_href); + const weather: Weather = (await w_res.json()) as Weather + + return json( + { + weather: weather, + user, + requestInfo: { + hints: getHints(request), + origin: getDomainUrl(request), + path: new URL(request.url).pathname, + userPrefs: { + theme: getTheme(request), + }, + }, + ENV: getEnv(), + toast, + confettiId, + }, + { + headers: combineHeaders( + { 'Server-Timing': timings.toString() }, + toastHeaders, + confettiHeaders, + ), + }, + ) +} + +export const headers: HeadersFunction = ({ loaderHeaders }) => { + const headers = { + 'Server-Timing': loaderHeaders.get('Server-Timing') ?? '', + } + return headers +} + +const ThemeFormSchema = z.object({ + theme: z.enum(['system', 'light', 'dark']), +}) + +export async function action({ request }: DataFunctionArgs) { + const formData = await request.formData() + invariantResponse( + formData.get('intent') === 'update-theme', + 'Invalid intent', + { status: 400 }, + ) + const submission = parse(formData, { + schema: ThemeFormSchema, + }) + if (submission.intent !== 'submit') { + return json({ status: 'success', submission } as const) + } + if (!submission.value) { + return json({ status: 'error', submission } as const, { status: 400 }) + } + const { theme } = submission.value + + const responseInit = { + headers: { 'set-cookie': setTheme(theme) }, + } + return json({ success: true, submission }, responseInit) +} + +function Document({ + children, + nonce, + theme = 'light', + env = {}, +}: { + children: React.ReactNode + nonce: string + theme?: Theme + env?: Record +}) { + // const [output, setOutput] = useState('(loading python...)'); + + // useEffect(() => { + // const run = async () => { + // const pyodide: any = await runPythonScript(); + // // console.log(pyodide); + // const result = await pyodide.runPythonAsync("hdd(57, 60)"); + // setOutput(result); + // }; + // run(); + // }, []); + return ( + + + + + + + + + +
+
Output:
+ {/* {output} */} +
+ + {children} +