diff options
| author | Max Nanis | 2026-09-11 07:49:51 -0700 |
|---|---|---|
| committer | Max Nanis | 2026-09-11 07:49:51 -0700 |
| commit | cb5e40f9b5fb0ae4bb9a769dd7a9c83c2af18a65 (patch) | |
| tree | 0b974d33b6b10559bc5356c4a10c0bdc294b5b5e | |
| parent | 2759f4cdfd1450cb891dfa806dc93d1101533d96 (diff) | |
| download | amt-jb-cb5e40f9b5fb0ae4bb9a769dd7a9c83c2af18a65.tar.gz amt-jb-cb5e40f9b5fb0ae4bb9a769dd7a9c83c2af18a65.zip | |
Transfer page. Jenkins CDN. Layout url check
| -rw-r--r-- | jb-ui/Jenkinsfile | 6 | ||||
| -rw-r--r-- | jb-ui/src/JBApp.tsx | 18 | ||||
| -rw-r--r-- | jb-ui/src/components/EventMarquee.tsx | 2 | ||||
| -rw-r--r-- | jb-ui/src/pages/LinkAmtAccount.tsx | 84 | ||||
| -rw-r--r-- | jb-ui/src/pages/Transfer.tsx | 171 | ||||
| -rw-r--r-- | jb-ui/vite.config.ts | 102 |
6 files changed, 207 insertions, 176 deletions
diff --git a/jb-ui/Jenkinsfile b/jb-ui/Jenkinsfile index 27a0ab9..faf63de 100644 --- a/jb-ui/Jenkinsfile +++ b/jb-ui/Jenkinsfile @@ -82,7 +82,7 @@ pipeline { expression { env.BRANCH_NAME == 'master' } } steps { - sh "/usr/bin/rsync -avz ${WORKSPACE}/jb-ui/${env.BUILD_DIR}/ thl-cdn:/root/amt-jb-cdn/" + sh "/usr/bin/rsync -avz ${WORKSPACE}/jb-ui/${env.BUILD_DIR}/ cdn-jb:/var/www/amt-jb-cdn/" } } @@ -101,7 +101,7 @@ pipeline { sh "cp ${env.JS_FILENAME}.js ${versioned_js}.js" sh "cp ${env.CSS_FILENAME}.js ${versioned_css}.js" - sh "/usr/bin/rsync -avz ${WORKSPACE}/jb-ui/${env.BUILD_DIR}/ thl-cdn:/root/amt-jb-cdn/" + sh "/usr/bin/rsync -avz ${WORKSPACE}/jb-ui/${env.BUILD_DIR}/ cdn-jb:/var/www/amt-jb-cdn/" } } } @@ -126,7 +126,7 @@ pipeline { sh "cp ${env.JS_FILENAME}.js ${versioned}.js" sh "cp ${env.CSS_FILENAME}.js ${versioned}.js" - sh "/usr/bin/rsync -avz ${WORKSPACE}/jb-ui/${env.BUILD_DIR}/ thl-cdn:/root/amt-jb-cdn/" + sh "/usr/bin/rsync -avz ${WORKSPACE}/jb-ui/${env.BUILD_DIR}/ cdn-jb:/var/www/amt-jb-cdn/" } } } diff --git a/jb-ui/src/JBApp.tsx b/jb-ui/src/JBApp.tsx index 472b976..7c99315 100644 --- a/jb-ui/src/JBApp.tsx +++ b/jb-ui/src/JBApp.tsx @@ -27,11 +27,15 @@ import Home from "@/pages/Home"; import MagicLink from "@/pages/MagicLink"; import Preview from "@/pages/Preview"; import Result from "@/pages/Result"; +import clsx from "clsx"; + import Work from "@/pages/Work"; import Transfer from "@/pages/Transfer"; import { BrowserRouter, Outlet, + useLocation, + useMatch, Route, Routes, useSearchParams, @@ -118,6 +122,9 @@ function QueryParamProcessor() { } const Layout = () => { + const location = useLocation(); + const isSpecialSubview = useMatch("/work/*"); + return ( <div className="flex flex-col min-h-screen"> <header className="bg-amber-400 text-amber-950 py-2 text-center"> @@ -134,13 +141,10 @@ const Layout = () => { <main className="flex flex-1 bg-zinc-200"> <div className="flex flex-col items-center justify-center flex-1"> <div - className=" - w-full max-w-full - p-2 bg-white shadow-lg - text-center space-y-4 - md:max-w-5/8 md:rounded-lg - rounded-none - " + className={clsx( + "w-full max-w-full p-2 bg-white shadow-lg text-center space-y-4 md:max-w-5/8 md:rounded-lg rounded-none", + isSpecialSubview && "border-6 border-amber-400", + )} > <Wallet /> <Profiling /> diff --git a/jb-ui/src/components/EventMarquee.tsx b/jb-ui/src/components/EventMarquee.tsx index 6aab3f8..46508ff 100644 --- a/jb-ui/src/components/EventMarquee.tsx +++ b/jb-ui/src/components/EventMarquee.tsx @@ -148,7 +148,7 @@ export default function NewsTicker() { // the browser, which is more accurate for measuring frame intervals // than Date.now() const loop = (timestamp: number) => { - console.log("RAF loop, timestamp:", timestamp, lastTime.current); + // console.log("RAF loop, timestamp:", timestamp, lastTime.current); if (!lastTime.current) lastTime.current = timestamp; const delta = (timestamp - lastTime.current) / 1000; diff --git a/jb-ui/src/pages/LinkAmtAccount.tsx b/jb-ui/src/pages/LinkAmtAccount.tsx deleted file mode 100644 index a72626f..0000000 --- a/jb-ui/src/pages/LinkAmtAccount.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { type FormEvent, useState } from "react"; - -import { Button } from "@/components/ui/button"; - -type RequestState = "idle" | "working" | "sent" | "failed" | "missing-worker"; - -const LinkAmtAccount = function () { - const [email, setEmail] = useState(""); - const [state, setState] = useState<RequestState>("idle"); - const [mockLink, setMockLink] = useState<string | null>(null); - const amtWorkerId = new URLSearchParams(window.location.search).get( - "workerId", - ); - - const submit = async (event: FormEvent<HTMLFormElement>) => { - event.preventDefault(); - if (!amtWorkerId) { - setState("missing-worker"); - return; - } - - setState("working"); - setMockLink(null); - try { - const response = await fetch("/auth/link-amt/request", { - method: "POST", - credentials: "include", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - email: email, - amt_worker_id: amtWorkerId, - }), - }); - if (!response.ok) throw new Error("Account-link request failed"); - const body = (await response.json()) as { magic_link?: string }; - setMockLink(body.magic_link ?? null); - setState("sent"); - } catch { - setState("failed"); - } - }; - - return ( - <main className="flex min-h-screen items-center justify-center bg-zinc-200 p-4"> - <section className="w-full max-w-md space-y-4 rounded-lg bg-white p-6 shadow-lg"> - <h1 className="text-xl font-semibold">Link your MTurk account</h1> - <p>Enter the email address you want to use for James Billings.</p> - <form className="space-y-4" onSubmit={submit}> - <input - className="w-full rounded-md border px-3 py-2" - type="email" - autoComplete="email" - required - value={email} - onChange={(event) => setEmail(event.target.value)} - placeholder="you@example.com" - /> - <Button type="submit" disabled={state === "working"}> - {state === "working" ? "Sendingā¦" : "Send link"} - </Button> - </form> - {state === "sent" && ( - <p>Check your email to finish linking your account.</p> - )} - {state === "failed" && ( - <p>Unable to send the link. Please try again.</p> - )} - {state === "missing-worker" && ( - <p>This page is missing your MTurk worker ID.</p> - )} - {mockLink && ( - <p> - Development link:{" "} - <a className="underline" href={mockLink}> - continue - </a> - </p> - )} - </section> - </main> - ); -}; - -export default LinkAmtAccount; diff --git a/jb-ui/src/pages/Transfer.tsx b/jb-ui/src/pages/Transfer.tsx index 6e087d6..bef40d4 100644 --- a/jb-ui/src/pages/Transfer.tsx +++ b/jb-ui/src/pages/Transfer.tsx @@ -1,50 +1,167 @@ -import { clsx } from "clsx"; +import { type FormEvent, useState } from "react"; +import { useAppDispatch, useAppSelector } from "@/hooks"; +import { Button } from "@/components/ui/button"; +import max_lulu from "./max-and-lulu.jpg"; -import { useSelector } from "react-redux"; +// const handleInputChange = ( +// event: React.KeyboardEvent<HTMLInputElement>, +// ) => {}; -const Transfer = function () { - let error = []; +// const handleKeyPress = (event: KeyboardEvent<HTMLInputElement>) => {}; +// const handleSubmit = (e) => { +// e.preventDefault(); +// console.log("Form submitted successfully!"); +// }; + +const TransferComplete = function () { + return ( + <div className="px-6 my-6"> + <h2 + className=" + bg-emerald-400 rounded py-2 + text-white text-2xl font-semibold text-center" + > + Please check your email. + </h2> + <p className="text-slate-600 text-l font-semibold text-center py-5 px-6"> + If you don't recieve anything, please check your spam folder, or try + again shortly. + </p> + <p className="bg-slate-200 text-xs font-semibold text-center p-3 my-3"> + We will be assisting account transfers throughout the rest of the month. + If you have any further questions or concerns, please email us directly + with your desired account email and the AMT ID to associate with your + worker history. + </p> + <img src={max_lulu} alt="Max and Lulu" className="object-contain" /> + </div> + ); +}; + +type RequestState = "idle" | "working" | "sent" | "failed"; - const handleInputChange = ( - event: React.KeyboardEvent<HTMLInputElement>, - ) => {}; +const TransferSubmit = function ({ onSubmitSuccess }) { + const [email, setEmail] = useState(""); + const [state, setState] = useState<RequestState>("idle"); + const bpuid = useAppSelector((state) => state.app.bpuid); - const handleKeyPress = (event: KeyboardEvent<HTMLInputElement>) => {}; + const submit = async (event: FormEvent<HTMLFormElement>) => { + event.preventDefault(); + setState("working"); - const handleSubmit = (e) => { - e.preventDefault(); - console.log("Form submitted successfully!"); + try { + const response = await fetch("/auth/link-amt/request", { + method: "POST", + credentials: "include", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + email: email, + amt_worker_id: bpuid, + }), + }); + + if (!response.ok) throw new Error("Account-link request failed"); + + const body = (await response.json()) as { magic_link?: string }; + console.log(body.magic_link ?? null); + onSubmitSuccess(); + } catch { + setState("failed"); + } }; return ( <div className="px-6 my-6"> <h2 className=" - bg-red-500 rounded py-2 + bg-red-700 rounded py-2 text-white text-2xl font-semibold text-center" > Transfer Required </h2> - <p + <h4 className=" - py-4 - text-zinc-500 text-2xl font-semibold text-center" + mt-2 + bg-slate-500 rounded p-2 + text-white text-sm font-semibold text-center" > - James Billings is finished š Just Kidding!!! - </p> + James Billings is no longer available on Amazon Mechanical Turk. Our + dedicated platform will enable you to do the same work as always, paid + directly to you. + <br /> + Enter your email below to transfer your account history. + <br /> + This will allow you to keep your full account history and wallet + balance. + </h4> + + <form onSubmit={submit}> + <input + className="w-full rounded-md border-3 border-slate-700 px-3 py-2 font-semibold my-5" + type="email" + autoComplete="email" + required + value={email} + onChange={(event) => setEmail(event.target.value)} + placeholder="you@example.com" + /> + <Button + className="w-1/2 font-semibold bg-slate-600 cursor-pointer hover:bg-blue-950" + type="submit" + disabled={state === "working"} + > + {state === "working" ? "Sendingā¦" : "Send link"} + </Button> + </form> - <input - type="text" - id="text-entry-input" - aria-describedby="" - // defaultValue={answer?.values.length ? answer?.values[0] : ""} - // onKeyUp={handleInputChange} - // onKeyDown={handleKeyPress} // Use onKeyDown to listen for the key press - // title={error ? answer?.error_msg : ""} - className={clsx("w-full border-1 rounded px-2 py-1")} - /> + {state === "sent" && ( + <h4 + className=" + mt-2 + bg-slate-500 rounded py-2 + text-white text-l font-semibold text-center" + > + Check your email to finish linking your account. + </h4> + )} + + {state === "failed" && <p>Unable to send the link. Please try again.</p>} </div> ); }; +const Transfer = function () { + const assignment_id = useAppSelector((state) => state.app.assignment_id); + const bpuid = useAppSelector((state) => state.app.bpuid); + const [submitted, setSubmitted] = useState(false); + + if (!bpuid) { + return ( + <p className="text-center text-2xl py-3 text-red-800 font-semibold"> + No Worker ID found. Please access this page through the Amazon + Mechanical Turk platform. + </p> + ); + } + + if (!assignment_id) { + return ( + <p className="text-center text-2xl py-3 text-red-800 font-semibold"> + No Assignment ID found. Please access this page through the Amazon + Mechanical Turk platform. + </p> + ); + } + + return ( + <> + {submitted ? ( + <TransferComplete /> + ) : ( + <TransferSubmit onSubmitSuccess={() => setSubmitted(true)} /> + )} + </> + ); +}; + export default Transfer; diff --git a/jb-ui/vite.config.ts b/jb-ui/vite.config.ts index 6b0e530..2336e4a 100644 --- a/jb-ui/vite.config.ts +++ b/jb-ui/vite.config.ts @@ -1,62 +1,56 @@ -import react from "@vitejs/plugin-react" -import {defineConfig} from "vite" -import path from 'path'; -import tailwindcss from '@tailwindcss/vite' - +import react from "@vitejs/plugin-react"; +import { defineConfig } from "vite"; +import path from "path"; +import tailwindcss from "@tailwindcss/vite"; export default defineConfig({ - plugins: [ - react(), - tailwindcss(), - - ], + plugins: [react(), tailwindcss()], - resolve: { - alias: { - '@': path.resolve(__dirname, './src'), - }, + resolve: { + alias: { + "@": path.resolve(__dirname, "./src"), }, - - server: { - // host: "0.0.0.0", - // port: 8001, - - // This forwards requests to the FastAPI development server - // that must also be running - proxy: { - '^/(status|statuses|report|survey)(/|$)': { - target: 'http://localhost:8000', - changeOrigin: true, - } - } + }, + + server: { + // host: "0.0.0.0", + // port: 8001, + + // This forwards requests to the FastAPI development server + // that must also be running + proxy: { + "^/(auth|status|statuses|report|survey)(/|$)": { + target: "http://localhost:8000", + changeOrigin: true, + }, }, + }, - define: { - 'process.env.NODE_ENV': JSON.stringify('production') - }, + define: { + "process.env.NODE_ENV": JSON.stringify("production"), + }, - build: { - cssCodeSplit: false, - lib: { - name: "jb-ui", - entry: 'src/main.tsx', + build: { + cssCodeSplit: false, + lib: { + name: "jb-ui", + entry: "src/main.tsx", + }, + rollupOptions: { + output: { + entryFileNames: "james-billings.js", + assetFileNames: (assetInfo) => { + if (assetInfo.names[0].endsWith(".css")) { + return "james-has-style.css"; + } + + return "assets/[name].[hash][extname]"; }, - rollupOptions: { - output: { - entryFileNames: 'james-billings.js', - assetFileNames: (assetInfo) => { - - if (assetInfo.names[0].endsWith('.css')) { - return 'james-has-style.css'; - } - - return 'assets/[name].[hash][extname]'; - }, - globals: { - react: 'React', - 'react-dom': 'ReactDOM' - } - } - } - } -})
\ No newline at end of file + globals: { + react: "React", + "react-dom": "ReactDOM", + }, + }, + }, + }, +}); |
