From cc2f2413f579877ea3054aaa670ce07d005985a1 Mon Sep 17 00:00:00 2001 From: m00n620 Date: Wed, 13 Sep 2023 08:25:15 -0400 Subject: [PATCH 1/6] update cvat job form, fix network select, status tab --- .../client/src/components/Auth/SignInForm.jsx | 2 + .../src/components/Jobs/Create/CreateJob.tsx | 2 +- .../Jobs/Create/CvatJobRequestForm.tsx | 107 ++++++++++-------- .../Jobs/Create/FortuneJobRequestForm.tsx | 5 +- .../src/components/Jobs/Create/schema.ts | 23 ++++ .../components/Jobs/StatusToggleButtons.tsx | 31 +++-- .../client/src/components/Jobs/Table.tsx | 13 ++- .../job-launcher/client/src/hooks/useJobs.ts | 9 -- .../apps/job-launcher/client/src/main.tsx | 2 + .../client/src/pages/Dashboard/index.tsx | 21 +++- .../client/src/pages/Job/JobDetail/index.tsx | 14 +-- .../client/src/pages/Job/JobList/index.tsx | 13 ++- .../job-launcher/client/src/services/job.ts | 6 +- .../job-launcher/client/src/state/index.ts | 3 +- .../client/src/state/jobs/hooks.ts | 26 +++++ .../client/src/state/jobs/reducer.ts | 30 +++++ .../client/src/state/jobs/types.ts | 15 +++ .../job-launcher/client/src/types/index.ts | 11 +- 18 files changed, 223 insertions(+), 110 deletions(-) create mode 100644 packages/apps/job-launcher/client/src/components/Jobs/Create/schema.ts delete mode 100644 packages/apps/job-launcher/client/src/hooks/useJobs.ts create mode 100644 packages/apps/job-launcher/client/src/state/jobs/hooks.ts create mode 100644 packages/apps/job-launcher/client/src/state/jobs/reducer.ts create mode 100644 packages/apps/job-launcher/client/src/state/jobs/types.ts diff --git a/packages/apps/job-launcher/client/src/components/Auth/SignInForm.jsx b/packages/apps/job-launcher/client/src/components/Auth/SignInForm.jsx index 66940f249c..29ed612e54 100644 --- a/packages/apps/job-launcher/client/src/components/Auth/SignInForm.jsx +++ b/packages/apps/job-launcher/client/src/components/Auth/SignInForm.jsx @@ -7,6 +7,7 @@ import { Link } from 'react-router-dom'; import * as authService from '../../services/auth'; import { useAppDispatch } from '../../state'; import { fetchUserBalanceAsync, signIn } from '../../state/auth/reducer'; +import { fetchUserJobsAsync } from '../../state/jobs/reducer'; import { Password } from './Password'; import { LoginValidationSchema } from './schema'; @@ -34,6 +35,7 @@ export const SignInForm = ({ onError }) => { }); dispatch(signIn(data)); dispatch(fetchUserBalanceAsync()); + dispatch(fetchUserJobsAsync()); } catch (err) { onError(err?.response?.data?.message); } diff --git a/packages/apps/job-launcher/client/src/components/Jobs/Create/CreateJob.tsx b/packages/apps/job-launcher/client/src/components/Jobs/Create/CreateJob.tsx index c640f92c5e..04058f15ae 100644 --- a/packages/apps/job-launcher/client/src/components/Jobs/Create/CreateJob.tsx +++ b/packages/apps/job-launcher/client/src/components/Jobs/Create/CreateJob.tsx @@ -31,7 +31,7 @@ export const CreateJob = () => { '0px 1px 5px 0px rgba(233, 235, 250, 0.20), 0px 2px 2px 0px rgba(233, 235, 250, 0.50), 0px 3px 1px -2px #E9EBFA', }} > - + Job Type { error={touched.type && Boolean(errors.type)} onBlur={handleBlur} > - - Binary Classification - Points Bounding Boxes - + + + setFieldValue('description', e.target.value) + } + onBlur={handleBlur} + placeholder="Description" + error={touched.description && Boolean(errors.description)} + helperText={errors.description} + multiline + rows={11} + /> + + + + + + value.map((option, index) => ( + + )) + } + renderInput={(params) => ( + + )} + onChange={(e, value) => setFieldValue('labels', value)} + onBlur={handleBlur} + placeholder="Labels" + /> + + { helperText={errors.dataUrl} /> - + { helperText={errors.groundTruthUrl} /> + + setFieldValue('userGuide', e.target.value)} + onBlur={handleBlur} + placeholder="User Guide" + error={touched.userGuide && Boolean(errors.userGuide)} + helperText={errors.userGuide} + /> + { /> - { const { jobRequest, updateJobRequest, goToPrevStep, goToNextStep } = @@ -29,7 +30,7 @@ export const FortuneJobRequestForm = () => { {({ @@ -43,7 +44,7 @@ export const FortuneJobRequestForm = () => { setFieldValue, }) => (
- + , - newValue: number - ) => { - console.log(newValue); - }; - +export const StatusToggleButtons: FC = (props) => { return ( - + {RANGE_BUTTONS.map(({ label, value }) => ( ); -} +}; diff --git a/packages/apps/job-launcher/client/src/components/Jobs/Table.tsx b/packages/apps/job-launcher/client/src/components/Jobs/Table.tsx index 09b787e5e3..f2642c5033 100644 --- a/packages/apps/job-launcher/client/src/components/Jobs/Table.tsx +++ b/packages/apps/job-launcher/client/src/components/Jobs/Table.tsx @@ -1,13 +1,20 @@ +import { ChainId } from '@human-protocol/sdk'; import { Box, Button, IconButton, Typography } from '@mui/material'; import { Link, useNavigate } from 'react-router-dom'; import { CopyLinkIcon } from '../../components/Icons/CopyLinkIcon'; import { Table } from '../../components/Table'; -import { useJobs } from '../../hooks/useJobs'; +import { useJobs } from '../../state/jobs/hooks'; import { JobStatus } from '../../types'; -export const JobTable = ({ status }: { status: JobStatus }) => { +export const JobTable = ({ + status, + chainId, +}: { + status: JobStatus; + chainId?: ChainId; +}) => { + const { data, isLoading } = useJobs({ status, chainId }); const navigate = useNavigate(); - const { data, isLoading } = useJobs(status); return ( { - return useSWR(`human-protocol-${status}-jobs`, () => - jobService.getJobListByStatus(status) - ); -}; diff --git a/packages/apps/job-launcher/client/src/main.tsx b/packages/apps/job-launcher/client/src/main.tsx index 390234fc54..b0b249debf 100644 --- a/packages/apps/job-launcher/client/src/main.tsx +++ b/packages/apps/job-launcher/client/src/main.tsx @@ -28,6 +28,7 @@ import { LOCAL_STORAGE_KEYS } from './constants'; import reportWebVitals from './reportWebVitals'; import { store } from './state'; import { fetchUserBalanceAsync, signIn } from './state/auth/reducer'; +import { fetchUserJobsAsync } from './state/jobs/reducer'; import theme from './theme'; // import { isJwtExpired } from './utils/jwt'; @@ -108,6 +109,7 @@ loadStripe(publishableKey).then((stripePromise) => { }) ); store.dispatch(fetchUserBalanceAsync()); + store.dispatch(fetchUserJobsAsync()); } root.render( diff --git a/packages/apps/job-launcher/client/src/pages/Dashboard/index.tsx b/packages/apps/job-launcher/client/src/pages/Dashboard/index.tsx index 7b7bdefbc7..a939dc3886 100644 --- a/packages/apps/job-launcher/client/src/pages/Dashboard/index.tsx +++ b/packages/apps/job-launcher/client/src/pages/Dashboard/index.tsx @@ -1,5 +1,6 @@ +import { ChainId } from '@human-protocol/sdk'; import { Box, Grid, Typography } from '@mui/material'; -import React from 'react'; +import React, { useState } from 'react'; import { JobsGraph } from '../../components/Dashboard/JobsGraph'; import { LiquidityData } from '../../components/Dashboard/LiquidityData'; import { OracleReputation } from '../../components/Dashboard/OracleRepuptation'; @@ -7,10 +8,12 @@ import { WorkersPerformance } from '../../components/Dashboard/WorkersPerformanc import { StatusToggleButtons } from '../../components/Jobs/StatusToggleButtons'; import { JobTable } from '../../components/Jobs/Table'; import { NetworkSelect } from '../../components/NetworkSelect'; -import { SearchField } from '../../components/SearchField'; import { JobStatus } from '../../types'; export default function Dashboard() { + const [chainId, setChainId] = useState(); + const [status, setStatus] = useState(JobStatus.ALL); + return ( - - + setChainId(e.target.value as ChainId)} + /> @@ -58,10 +63,14 @@ export default function Dashboard() { }} > Jobs - + setStatus(value)} + /> - + ); } diff --git a/packages/apps/job-launcher/client/src/pages/Job/JobDetail/index.tsx b/packages/apps/job-launcher/client/src/pages/Job/JobDetail/index.tsx index 74b93b667c..9b3e6ccd88 100644 --- a/packages/apps/job-launcher/client/src/pages/Job/JobDetail/index.tsx +++ b/packages/apps/job-launcher/client/src/pages/Job/JobDetail/index.tsx @@ -1,12 +1,9 @@ -import { Box, Card, Grid, IconButton, Stack, Typography } from '@mui/material'; +import { Box, Card, Grid, Stack, Typography } from '@mui/material'; import { styled } from '@mui/material/styles'; import React from 'react'; import { useParams } from 'react-router-dom'; import { CardTextRow } from '../../../components/CardTextRow'; import { CopyAddressButton } from '../../../components/CopyAddressButton'; -import { CopyLinkIcon } from '../../../components/Icons/CopyLinkIcon'; -import { SearchField } from '../../../components/SearchField'; -import { Table } from '../../../components/Table'; import { useJobDetails } from '../../../hooks/useJobDetails'; const CardContainer = styled(Card)(({ theme }) => ({ @@ -34,10 +31,7 @@ export default function JobDetail() { Job details - - - - + @@ -162,7 +156,7 @@ export default function JobDetail() { - + {/* Job solutions @@ -203,7 +197,7 @@ export default function JobDetail() { ]} /> - + */} ); } diff --git a/packages/apps/job-launcher/client/src/pages/Job/JobList/index.tsx b/packages/apps/job-launcher/client/src/pages/Job/JobList/index.tsx index fbfe738cbd..18c1be94d1 100644 --- a/packages/apps/job-launcher/client/src/pages/Job/JobList/index.tsx +++ b/packages/apps/job-launcher/client/src/pages/Job/JobList/index.tsx @@ -1,9 +1,9 @@ +import { ChainId } from '@human-protocol/sdk'; import { Box, Typography } from '@mui/material'; -import React from 'react'; +import React, { useState } from 'react'; import { Navigate, useParams } from 'react-router-dom'; import { JobTable } from '../../../components/Jobs/Table'; import { NetworkSelect } from '../../../components/NetworkSelect'; -import { SearchField } from '../../../components/SearchField'; import { JobStatus } from '../../../types'; const JOB_NAV_ITEMS = [ @@ -16,6 +16,7 @@ const JOB_NAV_ITEMS = [ export default function JobList() { const params = useParams(); + const [chainId, setChainId] = useState(); const item = JOB_NAV_ITEMS.find((x) => x.label === params.status); if (!item) { @@ -44,11 +45,13 @@ export default function JobList() { - - + setChainId(e.target.value as ChainId)} + /> - + ); } diff --git a/packages/apps/job-launcher/client/src/services/job.ts b/packages/apps/job-launcher/client/src/services/job.ts index 06f04d5bcc..94d8d2565a 100644 --- a/packages/apps/job-launcher/client/src/services/job.ts +++ b/packages/apps/job-launcher/client/src/services/job.ts @@ -34,14 +34,14 @@ export const createCvatJob = async ( fundAmount: Number(amount), dataUrl: data.dataUrl, labels: data.labels, - minQuality: Number(data.accuracyTarget), + minQuality: Number(data.accuracyTarget) / 100, gtUrl: data.groundTruthUrl, type: data.type, }; await api.post('/job/cvat', body); }; -export const getJobListByStatus = async (status: JobStatus) => { +export const getJobList = async (status?: JobStatus) => { const { data } = await api.get(`/job/list`, { params: { status } }); return data; }; @@ -52,6 +52,6 @@ export const getJobResult = async (jobId: number) => { }; export const getJobDetails = async (jobId: number) => { - const { data } = await api.get(`/details/${jobId}`); + const { data } = await api.get(`/job/details/${jobId}`); return data; }; diff --git a/packages/apps/job-launcher/client/src/state/index.ts b/packages/apps/job-launcher/client/src/state/index.ts index 526600069a..ab5f61b3ba 100644 --- a/packages/apps/job-launcher/client/src/state/index.ts +++ b/packages/apps/job-launcher/client/src/state/index.ts @@ -3,9 +3,10 @@ import { useDispatch, useSelector, TypedUseSelectorHook } from 'react-redux'; import auth from './auth/reducer'; import dashboard from './dashboard/reducer'; +import jobs from './jobs/reducer'; export const store = configureStore({ - reducer: { auth, dashboard }, + reducer: { auth, dashboard, jobs }, }); export type AppState = ReturnType; diff --git a/packages/apps/job-launcher/client/src/state/jobs/hooks.ts b/packages/apps/job-launcher/client/src/state/jobs/hooks.ts new file mode 100644 index 0000000000..e8a7a6c185 --- /dev/null +++ b/packages/apps/job-launcher/client/src/state/jobs/hooks.ts @@ -0,0 +1,26 @@ +import { ChainId, NETWORKS } from '@human-protocol/sdk'; +import { useAppSelector } from '..'; +import { JobStatus } from '../../types'; + +export const useJobs = ({ + status, + chainId, +}: { + status: JobStatus; + chainId?: ChainId; +}) => { + const network = chainId ? NETWORKS[chainId] : null; + const { jobs, dataLoaded, loadingFailed } = useAppSelector( + (state) => state.jobs + ); + + return { + data: jobs.filter( + (job) => + (status === JobStatus.ALL || job.status === status) && + (!network || network.title === job.network) + ), + isLoading: !dataLoaded && !loadingFailed, + isError: loadingFailed, + }; +}; diff --git a/packages/apps/job-launcher/client/src/state/jobs/reducer.ts b/packages/apps/job-launcher/client/src/state/jobs/reducer.ts new file mode 100644 index 0000000000..56d012b016 --- /dev/null +++ b/packages/apps/job-launcher/client/src/state/jobs/reducer.ts @@ -0,0 +1,30 @@ +import { createAsyncThunk, createReducer } from '@reduxjs/toolkit'; +import { AppState } from '..'; +import * as jobService from '../../services/job'; +import { JobsState, UserJob } from './types'; + +const initialState: JobsState = { + jobs: [], + dataLoaded: false, + loadingFailed: false, +}; + +export const fetchUserJobsAsync = createAsyncThunk< + UserJob[], + void, + { state: AppState } +>('auth/fetchUserJobsAsync', async () => { + const jobs = await jobService.getJobList(); + return jobs; +}); + +export default createReducer(initialState, (builder) => { + builder.addCase(fetchUserJobsAsync.fulfilled, (state, action) => { + state.jobs = action.payload; + state.dataLoaded = true; + }); + builder.addCase(fetchUserJobsAsync.rejected, (state, action) => { + state.loadingFailed = true; + state.dataLoaded = false; + }); +}); diff --git a/packages/apps/job-launcher/client/src/state/jobs/types.ts b/packages/apps/job-launcher/client/src/state/jobs/types.ts new file mode 100644 index 0000000000..196ff6b35e --- /dev/null +++ b/packages/apps/job-launcher/client/src/state/jobs/types.ts @@ -0,0 +1,15 @@ +import { JobStatus } from '../../types'; + +export type UserJob = { + address: string; + fundAmount: number; + jobId: number; + network: string; + status: JobStatus; +}; + +export type JobsState = { + jobs: UserJob[]; + dataLoaded: boolean; + loadingFailed: boolean; +}; diff --git a/packages/apps/job-launcher/client/src/types/index.ts b/packages/apps/job-launcher/client/src/types/index.ts index e9de695e9f..3437f17af8 100644 --- a/packages/apps/job-launcher/client/src/types/index.ts +++ b/packages/apps/job-launcher/client/src/types/index.ts @@ -69,7 +69,6 @@ export enum JobType { } export enum CvatJobType { - IMAGE_LABEL_BINARY = 'IMAGE_LABEL_BINARY', IMAGE_POINTS = 'IMAGE_POINTS', IMAGE_BOXES = 'IMAGE_BOXES', } @@ -86,6 +85,7 @@ export type CvatRequest = { description: string; dataUrl: string; groundTruthUrl: string; + userGuide: string; accuracyTarget: number; }; @@ -97,17 +97,18 @@ export type JobRequest = { }; export enum JobStatus { - PENDING = 'PENDING', - PAID = 'PAID', + ALL = 'ALL', LAUNCHED = 'LAUNCHED', + PENDING = 'PENDING', + CANCELED = 'CANCELED', FAILED = 'FAILED', + PAID = 'PAID', TO_CANCEL = 'TO_CANCEL', - CANCELED = 'CANCELED', } export type JobDetailsResponse = { details: { - escrowAddress: string; + escrowAddess: string; manifestUrl: string; manifestHash: string; balance: number; From e5a70e9e5d6fd0edcd0fe0a965e79d4e37fdf68e Mon Sep 17 00:00:00 2001 From: m00n620 Date: Wed, 13 Sep 2023 08:26:46 -0400 Subject: [PATCH 2/6] fix error request handling --- packages/apps/job-launcher/client/src/utils/api.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/apps/job-launcher/client/src/utils/api.ts b/packages/apps/job-launcher/client/src/utils/api.ts index b6ba2df953..19ff24628d 100644 --- a/packages/apps/job-launcher/client/src/utils/api.ts +++ b/packages/apps/job-launcher/client/src/utils/api.ts @@ -18,8 +18,7 @@ axiosInstance.interceptors.request.use( axiosInstance.interceptors.response.use( (response) => response, (error) => { - console.log(error.response.status); - if (error.response.status === 401) { + if (error?.response?.status === 401) { localStorage.removeItem('HUMAN_JOB_LAUNCHER_REFRESH_TOKEN'); localStorage.removeItem('HUMAN_JOB_LAUNCHER_ACCESS_TOKEN'); window.location.href = '/'; From e5dff95574d904754e8ff94bb186c1c9bd8945fb Mon Sep 17 00:00:00 2001 From: m00n620 Date: Thu, 14 Sep 2023 09:24:49 -0400 Subject: [PATCH 3/6] resolve comments, update job request form, fix error handling --- .../src/components/Auth/ForgotPasswordForm.jsx | 2 +- .../Auth/ResendEmailVerificationForm.jsx | 2 +- .../client/src/components/Auth/SignInForm.jsx | 2 +- .../client/src/components/Auth/SignUpForm.jsx | 2 +- .../src/components/Auth/VerifyEmailForm.tsx | 2 +- .../src/components/Headers/AuthHeader.tsx | 14 +++++++++----- .../components/Jobs/Create/CryptoPayForm.tsx | 17 ++++++++++------- .../Jobs/Create/CvatJobRequestForm.tsx | 15 +++++++++++++-- .../src/components/Jobs/Create/FiatPayForm.tsx | 2 ++ .../Jobs/Create/FortuneJobRequestForm.tsx | 13 +++++++++++-- .../src/components/Jobs/Create/PayJob.tsx | 2 +- .../client/src/components/Jobs/Create/schema.ts | 8 +++++--- .../client/src/components/Jobs/Table.tsx | 2 +- .../components/TopUpAccount/CryptoTopUpForm.tsx | 16 ++++++++++++++-- .../components/TopUpAccount/FiatTopUpForm.tsx | 4 ++-- .../client/src/pages/Dashboard/index.tsx | 3 ++- .../client/src/pages/Job/JobDetail/index.tsx | 6 ++++-- .../client/src/pages/Job/JobList/index.tsx | 10 +++++++--- .../src/providers/CreateJobPageUIProvider.tsx | 5 +---- .../job-launcher/client/src/state/jobs/hooks.ts | 5 ++--- .../apps/job-launcher/client/src/types/index.ts | 4 ++-- 21 files changed, 91 insertions(+), 45 deletions(-) diff --git a/packages/apps/job-launcher/client/src/components/Auth/ForgotPasswordForm.jsx b/packages/apps/job-launcher/client/src/components/Auth/ForgotPasswordForm.jsx index 54825efc1d..a1ffed8cdb 100644 --- a/packages/apps/job-launcher/client/src/components/Auth/ForgotPasswordForm.jsx +++ b/packages/apps/job-launcher/client/src/components/Auth/ForgotPasswordForm.jsx @@ -30,7 +30,7 @@ export const ForgotPasswordForm = () => { await authService.forgotPassword(email); setIsSuccess(true); } catch (err) { - setAlertMsg(err?.message); + setAlertMsg(err?.response?.data?.message ?? err?.message); } setIsLoading(false); }; diff --git a/packages/apps/job-launcher/client/src/components/Auth/ResendEmailVerificationForm.jsx b/packages/apps/job-launcher/client/src/components/Auth/ResendEmailVerificationForm.jsx index 755baf19aa..13297ec976 100644 --- a/packages/apps/job-launcher/client/src/components/Auth/ResendEmailVerificationForm.jsx +++ b/packages/apps/job-launcher/client/src/components/Auth/ResendEmailVerificationForm.jsx @@ -22,7 +22,7 @@ export const ResendEmailVerificationForm = ({ onFinish }) => { await authService.resendEmailVerification(email); onFinish(); } catch (err) { - setAlertMsg(err?.message); + setAlertMsg(err?.response?.data?.message ?? err?.message); } setIsLoading(false); }; diff --git a/packages/apps/job-launcher/client/src/components/Auth/SignInForm.jsx b/packages/apps/job-launcher/client/src/components/Auth/SignInForm.jsx index 29ed612e54..f6d46ec925 100644 --- a/packages/apps/job-launcher/client/src/components/Auth/SignInForm.jsx +++ b/packages/apps/job-launcher/client/src/components/Auth/SignInForm.jsx @@ -37,7 +37,7 @@ export const SignInForm = ({ onError }) => { dispatch(fetchUserBalanceAsync()); dispatch(fetchUserJobsAsync()); } catch (err) { - onError(err?.response?.data?.message); + onError(err?.response?.data?.message ?? err.message); } setIsLoading(false); }; diff --git a/packages/apps/job-launcher/client/src/components/Auth/SignUpForm.jsx b/packages/apps/job-launcher/client/src/components/Auth/SignUpForm.jsx index d70ffafa05..a51512b750 100644 --- a/packages/apps/job-launcher/client/src/components/Auth/SignUpForm.jsx +++ b/packages/apps/job-launcher/client/src/components/Auth/SignUpForm.jsx @@ -27,7 +27,7 @@ export const SignUpForm = ({ onFinish, onError }) => { setIsSuccess(true); } catch (err) { - onError(err?.message); + onError(err?.response?.data?.message ?? err.message); } setIsLoading(false); }; diff --git a/packages/apps/job-launcher/client/src/components/Auth/VerifyEmailForm.tsx b/packages/apps/job-launcher/client/src/components/Auth/VerifyEmailForm.tsx index c6deb9f0d6..1a72cbb4a9 100644 --- a/packages/apps/job-launcher/client/src/components/Auth/VerifyEmailForm.tsx +++ b/packages/apps/job-launcher/client/src/components/Auth/VerifyEmailForm.tsx @@ -29,7 +29,7 @@ export const VerifyEmailForm = () => { await authService.verifyEmail({ token }); setIsSuccess(true); } catch (err) { - setAlertMsg(err?.response?.data?.message); + setAlertMsg(err?.response?.data?.message ?? err.message); } setIsLoading(false); }; diff --git a/packages/apps/job-launcher/client/src/components/Headers/AuthHeader.tsx b/packages/apps/job-launcher/client/src/components/Headers/AuthHeader.tsx index d7c08c4639..48a24b61c8 100644 --- a/packages/apps/job-launcher/client/src/components/Headers/AuthHeader.tsx +++ b/packages/apps/job-launcher/client/src/components/Headers/AuthHeader.tsx @@ -63,12 +63,16 @@ export const AuthHeader = () => { }; const handleLogOut = async () => { - if (refreshToken) { - setIsLoggingOut(true); - await authServices.signOut(refreshToken); - dispatch(signOut()); - setIsLoggingOut(false); + setIsLoggingOut(true); + try { + if (refreshToken) { + await authServices.signOut(refreshToken); + } + } catch (err) { + console.log(err); } + dispatch(signOut()); + setIsLoggingOut(false); }; let segements = pathname.split('/').filter((s) => s); diff --git a/packages/apps/job-launcher/client/src/components/Jobs/Create/CryptoPayForm.tsx b/packages/apps/job-launcher/client/src/components/Jobs/Create/CryptoPayForm.tsx index 0329d60546..c8900a5921 100644 --- a/packages/apps/job-launcher/client/src/components/Jobs/Create/CryptoPayForm.tsx +++ b/packages/apps/job-launcher/client/src/components/Jobs/Create/CryptoPayForm.tsx @@ -1,4 +1,5 @@ import HMTokenABI from '@human-protocol/core/abis/HMToken.json'; +import { NETWORKS } from '@human-protocol/sdk'; import { LoadingButton } from '@mui/lab'; import { Alert, @@ -18,7 +19,6 @@ import React, { useMemo, useState } from 'react'; import { useAccount, useNetwork, useSigner } from 'wagmi'; import { TokenSelect } from '../../../components/TokenSelect'; import { JOB_LAUNCHER_OPERATOR_ADDRESS } from '../../../constants/addresses'; -import { SUPPORTED_CHAIN_IDS } from '../../../constants/chains'; import { JOB_LAUNCHER_FEE } from '../../../constants/payment'; import { useTokenRate } from '../../../hooks/useTokenRate'; import { useCreateJobPageUI } from '../../../providers/CreateJobPageUIProvider'; @@ -71,7 +71,7 @@ export const CryptoPayForm = ({ }, [payWithAccountBalance, totalAmount, accountAmount]); const handlePay = async () => { - if (signer && tokenAddress && amount) { + if (signer && tokenAddress && amount && jobRequest.chainId) { setIsLoading(true); try { if (walletPayAmount > 0) { @@ -117,13 +117,16 @@ export const CryptoPayForm = ({ } }; - if (!chain || chain.unsupported || !SUPPORTED_CHAIN_IDS.includes(chain.id)) + if (!chain || chain.unsupported || chain.id !== jobRequest.chainId) return ( - - - You are on wrong network, please switch to one of the supported - networks. + + + You are on wrong network, please switch to{' '} + {NETWORKS[jobRequest.chainId!]?.title}. + ); diff --git a/packages/apps/job-launcher/client/src/components/Jobs/Create/CvatJobRequestForm.tsx b/packages/apps/job-launcher/client/src/components/Jobs/Create/CvatJobRequestForm.tsx index 27fd4ae806..2bb9ce0f7b 100644 --- a/packages/apps/job-launcher/client/src/components/Jobs/Create/CvatJobRequestForm.tsx +++ b/packages/apps/job-launcher/client/src/components/Jobs/Create/CvatJobRequestForm.tsx @@ -114,6 +114,7 @@ export const CvatJobRequestForm = () => { } onBlur={handleBlur} placeholder="Description" + label="Description" error={touched.description && Boolean(errors.description)} helperText={errors.description} multiline @@ -148,6 +149,7 @@ export const CvatJobRequestForm = () => { onChange={(e) => setFieldValue('dataUrl', e.target.value)} onBlur={handleBlur} placeholder="Data URL" + label="Data URL" error={touched.dataUrl && Boolean(errors.dataUrl)} helperText={errors.dataUrl} /> @@ -161,6 +163,7 @@ export const CvatJobRequestForm = () => { } onBlur={handleBlur} placeholder="Ground Truth URL" + label="Ground Truth URL" error={ touched.groundTruthUrl && Boolean(errors.groundTruthUrl) } @@ -174,6 +177,7 @@ export const CvatJobRequestForm = () => { onChange={(e) => setFieldValue('userGuide', e.target.value)} onBlur={handleBlur} placeholder="User Guide" + label="User Guide URL" error={touched.userGuide && Boolean(errors.userGuide)} helperText={errors.userGuide} /> @@ -188,6 +192,7 @@ export const CvatJobRequestForm = () => { } onBlur={handleBlur} placeholder="Accuracy target %" + label="Accuracy target %" error={ touched.accuracyTarget && Boolean(errors.accuracyTarget) } @@ -205,7 +210,13 @@ export const CvatJobRequestForm = () => { > diff --git a/packages/apps/job-launcher/client/src/components/Jobs/Create/FiatPayForm.tsx b/packages/apps/job-launcher/client/src/components/Jobs/Create/FiatPayForm.tsx index 25f2d386f7..2ead83f7db 100644 --- a/packages/apps/job-launcher/client/src/components/Jobs/Create/FiatPayForm.tsx +++ b/packages/apps/job-launcher/client/src/components/Jobs/Create/FiatPayForm.tsx @@ -155,6 +155,8 @@ export const FiatPayForm = ({ // create job const { jobType, chainId, fortuneRequest, cvatRequest } = jobRequest; + if (!chainId) return; + if (jobType === JobType.Fortune && fortuneRequest) { await jobService.createFortuneJob(chainId, fortuneRequest, fundAmount); } else if (jobType === JobType.CVAT && cvatRequest) { diff --git a/packages/apps/job-launcher/client/src/components/Jobs/Create/FortuneJobRequestForm.tsx b/packages/apps/job-launcher/client/src/components/Jobs/Create/FortuneJobRequestForm.tsx index afcdd01b76..d4884a4de8 100644 --- a/packages/apps/job-launcher/client/src/components/Jobs/Create/FortuneJobRequestForm.tsx +++ b/packages/apps/job-launcher/client/src/components/Jobs/Create/FortuneJobRequestForm.tsx @@ -53,6 +53,7 @@ export const FortuneJobRequestForm = () => { onChange={(e) => setFieldValue('title', e.target.value)} onBlur={handleBlur} placeholder="Title" + label="Title" error={touched.title && Boolean(errors.title)} helperText={errors.title} /> @@ -68,6 +69,7 @@ export const FortuneJobRequestForm = () => { } onBlur={handleBlur} placeholder="Fortunes Requested" + label="Fortunes Requested" type="number" inputProps={{ min: 0, step: 1 }} error={ @@ -88,6 +90,7 @@ export const FortuneJobRequestForm = () => { } onBlur={handleBlur} placeholder="Description" + label="Description" error={touched.description && Boolean(errors.description)} helperText={errors.description} /> @@ -103,7 +106,13 @@ export const FortuneJobRequestForm = () => { > diff --git a/packages/apps/job-launcher/client/src/components/Jobs/Create/PayJob.tsx b/packages/apps/job-launcher/client/src/components/Jobs/Create/PayJob.tsx index e0d5777454..dd3eabd77f 100644 --- a/packages/apps/job-launcher/client/src/components/Jobs/Create/PayJob.tsx +++ b/packages/apps/job-launcher/client/src/components/Jobs/Create/PayJob.tsx @@ -28,7 +28,7 @@ export const PayJob = () => { ) { setErrorMessage(err.code); } else { - setErrorMessage(err.message); + setErrorMessage(err?.response?.data?.message ?? err?.message); } }; diff --git a/packages/apps/job-launcher/client/src/components/Jobs/Create/schema.ts b/packages/apps/job-launcher/client/src/components/Jobs/Create/schema.ts index 139914c5a8..3d97f46091 100644 --- a/packages/apps/job-launcher/client/src/components/Jobs/Create/schema.ts +++ b/packages/apps/job-launcher/client/src/components/Jobs/Create/schema.ts @@ -12,12 +12,14 @@ export const CvatJobRequestValidationSchema = Yup.object().shape({ .url('Invalid URL'), accuracyTarget: Yup.number() .required('Accuracy target is required') - .min(0) - .max(100), + .moreThan(0, 'Accuracy target must be greater than 0') + .max(100, 'Accuracy target must be less than or equal to 100'), }); export const FortuneJobRequestValidationSchema = Yup.object().shape({ title: Yup.string().required('Title is required'), description: Yup.string().required('Description is required'), - fortunesRequested: Yup.number().required('FortunesRequested is required'), + fortunesRequested: Yup.number() + .required('FortunesRequested is required') + .moreThan(0, 'FortunesRequested must be greater than 0'), }); diff --git a/packages/apps/job-launcher/client/src/components/Jobs/Table.tsx b/packages/apps/job-launcher/client/src/components/Jobs/Table.tsx index f2642c5033..3808a64362 100644 --- a/packages/apps/job-launcher/client/src/components/Jobs/Table.tsx +++ b/packages/apps/job-launcher/client/src/components/Jobs/Table.tsx @@ -11,7 +11,7 @@ export const JobTable = ({ chainId, }: { status: JobStatus; - chainId?: ChainId; + chainId: ChainId; }) => { const { data, isLoading } = useJobs({ status, chainId }); const navigate = useNavigate(); diff --git a/packages/apps/job-launcher/client/src/components/TopUpAccount/CryptoTopUpForm.tsx b/packages/apps/job-launcher/client/src/components/TopUpAccount/CryptoTopUpForm.tsx index 03618df157..764c20f2e4 100644 --- a/packages/apps/job-launcher/client/src/components/TopUpAccount/CryptoTopUpForm.tsx +++ b/packages/apps/job-launcher/client/src/components/TopUpAccount/CryptoTopUpForm.tsx @@ -9,6 +9,7 @@ import { Stack, TextField, Typography, + Snackbar, } from '@mui/material'; import { ethers } from 'ethers'; import React, { useMemo, useState } from 'react'; @@ -30,6 +31,7 @@ export const CryptoTopUpForm = () => { const [amount, setAmount] = useState(); const [isSuccess, setIsSuccess] = useState(false); const [isLoading, setIsLoading] = useState(false); + const [errorMessage, setErrorMessage] = useState(null); const { data: signer } = useSigner(); const { data: rate } = useTokenRate('hmt', 'usd'); @@ -66,8 +68,8 @@ export const CryptoTopUpForm = () => { dispatch(fetchUserBalanceAsync()); setIsSuccess(true); - } catch (err) { - console.error(err); + } catch (err: any) { + setErrorMessage(err?.response?.data?.message ?? err?.message); setIsSuccess(false); } @@ -190,6 +192,16 @@ export const CryptoTopUpForm = () => { + setErrorMessage(null)} + anchorOrigin={{ vertical: 'top', horizontal: 'center' }} + > + setErrorMessage(null)} severity="error"> + {errorMessage} + + ); }; diff --git a/packages/apps/job-launcher/client/src/components/TopUpAccount/FiatTopUpForm.tsx b/packages/apps/job-launcher/client/src/components/TopUpAccount/FiatTopUpForm.tsx index 69d3175b22..986fa1cf54 100644 --- a/packages/apps/job-launcher/client/src/components/TopUpAccount/FiatTopUpForm.tsx +++ b/packages/apps/job-launcher/client/src/components/TopUpAccount/FiatTopUpForm.tsx @@ -87,8 +87,8 @@ export const FiatTopUpForm = () => { dispatch(fetchUserBalanceAsync()); setIsSuccess(true); - } catch (err) { - setErrorMessage(err.message); + } catch (err: any) { + setErrorMessage(err?.response?.data?.message ?? err?.message); setIsSuccess(false); } setIsLoading(false); diff --git a/packages/apps/job-launcher/client/src/pages/Dashboard/index.tsx b/packages/apps/job-launcher/client/src/pages/Dashboard/index.tsx index a939dc3886..effb96be94 100644 --- a/packages/apps/job-launcher/client/src/pages/Dashboard/index.tsx +++ b/packages/apps/job-launcher/client/src/pages/Dashboard/index.tsx @@ -11,7 +11,7 @@ import { NetworkSelect } from '../../components/NetworkSelect'; import { JobStatus } from '../../types'; export default function Dashboard() { - const [chainId, setChainId] = useState(); + const [chainId, setChainId] = useState(ChainId.ALL); const [status, setStatus] = useState(JobStatus.ALL); return ( @@ -29,6 +29,7 @@ export default function Dashboard() { setChainId(e.target.value as ChainId)} /> diff --git a/packages/apps/job-launcher/client/src/pages/Job/JobDetail/index.tsx b/packages/apps/job-launcher/client/src/pages/Job/JobDetail/index.tsx index 9b3e6ccd88..4f5b831052 100644 --- a/packages/apps/job-launcher/client/src/pages/Job/JobDetail/index.tsx +++ b/packages/apps/job-launcher/client/src/pages/Job/JobDetail/index.tsx @@ -31,7 +31,7 @@ export default function JobDetail() { Job details - + @@ -156,7 +156,9 @@ export default function JobDetail() { - {/* + {/* + TODO: Add this back in when we have a way to fetch the job solution + Job solutions diff --git a/packages/apps/job-launcher/client/src/pages/Job/JobList/index.tsx b/packages/apps/job-launcher/client/src/pages/Job/JobList/index.tsx index 18c1be94d1..54a2de09b7 100644 --- a/packages/apps/job-launcher/client/src/pages/Job/JobList/index.tsx +++ b/packages/apps/job-launcher/client/src/pages/Job/JobList/index.tsx @@ -1,6 +1,6 @@ import { ChainId } from '@human-protocol/sdk'; import { Box, Typography } from '@mui/material'; -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { Navigate, useParams } from 'react-router-dom'; import { JobTable } from '../../../components/Jobs/Table'; import { NetworkSelect } from '../../../components/NetworkSelect'; @@ -9,14 +9,17 @@ import { JobStatus } from '../../../types'; const JOB_NAV_ITEMS = [ { status: JobStatus.LAUNCHED, label: 'launched' }, { status: JobStatus.PENDING, label: 'pending' }, - // { status: JobStatus.PAID, label: 'completed' }, { status: JobStatus.CANCELED, label: 'cancelled' }, { status: JobStatus.FAILED, label: 'failed' }, ]; export default function JobList() { const params = useParams(); - const [chainId, setChainId] = useState(); + const [chainId, setChainId] = useState(ChainId.ALL); + + useEffect(() => { + setChainId(ChainId.ALL); + }, [params.status]); const item = JOB_NAV_ITEMS.find((x) => x.label === params.status); if (!item) { @@ -46,6 +49,7 @@ export default function JobList() { setChainId(e.target.value as ChainId)} /> diff --git a/packages/apps/job-launcher/client/src/providers/CreateJobPageUIProvider.tsx b/packages/apps/job-launcher/client/src/providers/CreateJobPageUIProvider.tsx index 02f66f66f9..c3d76d6d58 100644 --- a/packages/apps/job-launcher/client/src/providers/CreateJobPageUIProvider.tsx +++ b/packages/apps/job-launcher/client/src/providers/CreateJobPageUIProvider.tsx @@ -1,5 +1,4 @@ import React, { createContext, useContext, useState } from 'react'; -import { SUPPORTED_CHAIN_IDS } from '../constants/chains'; import { CreateJobStep, JobRequest, JobType, PayMethod } from '../types'; export type CreateJobPageUIType = { @@ -21,7 +20,7 @@ const initialData: Omit< payMethod: PayMethod.Crypto, jobRequest: { jobType: JobType.Fortune, - chainId: SUPPORTED_CHAIN_IDS[0], + chainId: undefined, }, }; @@ -39,7 +38,6 @@ export const CreateJobPageUIProvider = ({ const [payMethod, setPayMethod] = useState(PayMethod.Crypto); const [jobRequest, setJobRequest] = useState({ jobType: JobType.Fortune, - chainId: SUPPORTED_CHAIN_IDS[0], }); const goToPrevStep = () => { @@ -60,7 +58,6 @@ export const CreateJobPageUIProvider = ({ setPayMethod(PayMethod.Crypto); setJobRequest({ jobType: JobType.Fortune, - chainId: SUPPORTED_CHAIN_IDS[0], }); }; diff --git a/packages/apps/job-launcher/client/src/state/jobs/hooks.ts b/packages/apps/job-launcher/client/src/state/jobs/hooks.ts index e8a7a6c185..a74bedbbfa 100644 --- a/packages/apps/job-launcher/client/src/state/jobs/hooks.ts +++ b/packages/apps/job-launcher/client/src/state/jobs/hooks.ts @@ -7,9 +7,8 @@ export const useJobs = ({ chainId, }: { status: JobStatus; - chainId?: ChainId; + chainId: ChainId; }) => { - const network = chainId ? NETWORKS[chainId] : null; const { jobs, dataLoaded, loadingFailed } = useAppSelector( (state) => state.jobs ); @@ -18,7 +17,7 @@ export const useJobs = ({ data: jobs.filter( (job) => (status === JobStatus.ALL || job.status === status) && - (!network || network.title === job.network) + (chainId === ChainId.ALL || NETWORKS[chainId]?.title === job.network) ), isLoading: !dataLoaded && !loadingFailed, isError: loadingFailed, diff --git a/packages/apps/job-launcher/client/src/types/index.ts b/packages/apps/job-launcher/client/src/types/index.ts index 3437f17af8..718195eb8e 100644 --- a/packages/apps/job-launcher/client/src/types/index.ts +++ b/packages/apps/job-launcher/client/src/types/index.ts @@ -91,7 +91,7 @@ export type CvatRequest = { export type JobRequest = { jobType: JobType; - chainId: ChainId; + chainId?: ChainId; fortuneRequest?: FortuneRequest; cvatRequest?: CvatRequest; }; @@ -108,7 +108,7 @@ export enum JobStatus { export type JobDetailsResponse = { details: { - escrowAddess: string; + escrowAddress: string; manifestUrl: string; manifestHash: string; balance: number; From d7d3c8e417b43770c69eb3746966adff92c0ba9e Mon Sep 17 00:00:00 2001 From: m00n620 Date: Fri, 15 Sep 2023 08:27:15 -0400 Subject: [PATCH 4/6] vercel build command --- packages/apps/job-launcher/client/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/apps/job-launcher/client/package.json b/packages/apps/job-launcher/client/package.json index 82ae79a229..7fdf0d85ff 100644 --- a/packages/apps/job-launcher/client/package.json +++ b/packages/apps/job-launcher/client/package.json @@ -38,7 +38,8 @@ "test": "vitest run -u", "format:prettier": "prettier --write \"**/*.{ts,tsx,js,jsx}\"", "format:lint": "eslint --fix \"**/*.{ts,tsx,js,jsx}\"", - "format": "npm run format:prettier && npm run format:lint" + "format": "npm run format:prettier && npm run format:lint", + "vercel-build": "yarn workspace @human-protocol/sdk build && yarn build" }, "browserslist": { "production": [ From 63aa94bb2b46ab8a8ca41d39cb66d290f58bef51 Mon Sep 17 00:00:00 2001 From: m00n620 Date: Fri, 15 Sep 2023 09:14:43 -0400 Subject: [PATCH 5/6] fix build issue --- packages/apps/job-launcher/client/package.json | 3 +-- packages/apps/job-launcher/client/vite.config.ts | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/apps/job-launcher/client/package.json b/packages/apps/job-launcher/client/package.json index 7fdf0d85ff..da5e000230 100644 --- a/packages/apps/job-launcher/client/package.json +++ b/packages/apps/job-launcher/client/package.json @@ -6,7 +6,6 @@ "@emotion/react": "^11.10.5", "@emotion/styled": "^11.10.5", "@hcaptcha/react-hcaptcha": "^1.8.1", - "@human-protocol/core": "*", "@human-protocol/sdk": "*", "@mui/lab": "^5.0.0-alpha.141", "@mui/material": "^5.11.7", @@ -34,7 +33,7 @@ "start": "vite --port 3005", "build": "vite build", "preview": "vite preview", - "start-prod": "serve -s build", + "start-prod": "serve -s dist", "test": "vitest run -u", "format:prettier": "prettier --write \"**/*.{ts,tsx,js,jsx}\"", "format:lint": "eslint --fix \"**/*.{ts,tsx,js,jsx}\"", diff --git a/packages/apps/job-launcher/client/vite.config.ts b/packages/apps/job-launcher/client/vite.config.ts index 34e4111e25..de99d2b115 100644 --- a/packages/apps/job-launcher/client/vite.config.ts +++ b/packages/apps/job-launcher/client/vite.config.ts @@ -30,11 +30,11 @@ export default defineConfig({ }, }, optimizeDeps: { - include: ['@human-protocol/sdk'], + include: ['@human-protocol/core', '@human-protocol/sdk'], }, build: { commonjsOptions: { - include: [/human-protocol-sdk/, /node_modules/], + include: [/core/, /human-protocol-sdk/, /node_modules/], }, }, server: { From bc26bad6dfb49f3e751383ceb3fcff0e9f5eafd8 Mon Sep 17 00:00:00 2001 From: m00n620 Date: Fri, 15 Sep 2023 10:49:32 -0400 Subject: [PATCH 6/6] fix vite config --- packages/apps/job-launcher/client/vite.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/apps/job-launcher/client/vite.config.ts b/packages/apps/job-launcher/client/vite.config.ts index de99d2b115..51fb0ed37b 100644 --- a/packages/apps/job-launcher/client/vite.config.ts +++ b/packages/apps/job-launcher/client/vite.config.ts @@ -30,7 +30,7 @@ export default defineConfig({ }, }, optimizeDeps: { - include: ['@human-protocol/core', '@human-protocol/sdk'], + include: ['@human-protocol/sdk'], }, build: { commonjsOptions: {