From a9aaf8753efb9c407832f348e19cd06eb6df62cc Mon Sep 17 00:00:00 2001 From: cyrbuzz Date: Wed, 13 Dec 2023 17:23:23 +0800 Subject: [PATCH] feat: category --- public/sw.js | 2 +- src/containers/ProjectMetadata.ts | 1 + src/containers/ProjectRegistry.ts | 6 +- src/hooks/useCreateProject.tsx | 2 +- src/models.tsx | 1 + src/pages/studio/Create/Create.module.css | 46 --------- src/pages/studio/Create/Create.module.less | 105 +++++++++++++++++++++ src/pages/studio/Create/Create.tsx | 83 +++++++++++++++- src/pages/studio/Project/Project.tsx | 29 +++++- 9 files changed, 219 insertions(+), 56 deletions(-) delete mode 100644 src/pages/studio/Create/Create.module.css create mode 100644 src/pages/studio/Create/Create.module.less diff --git a/public/sw.js b/public/sw.js index afac9fa11..0c4b24ca7 100644 --- a/public/sw.js +++ b/public/sw.js @@ -11,7 +11,7 @@ workbox.setConfig({ workbox.routing.registerRoute( // \/{0,1} will also match dev.thechaindata.comxxxyyy, but this is would not a valid suffix, so it can be use. // for match dev.thechaindata.com & dev.thechaindata.com/ - /((localhost:3006)|((dev|kepler)\.thechaindata\.com)|(kepler\.subquery\.network))\/{0,1}(?=((dashboard)|(explorer)|(profile)|(indexer)|(delegator)|(consumer)|(swap)|(studio))|\?|$).*/g, + /(((dev|kepler)\.thechaindata\.com)|(kepler\.subquery\.network))\/{0,1}(?=((dashboard)|(explorer)|(profile)|(indexer)|(delegator)|(consumer)|(swap)|(studio))|\?|$).*/g, // https://developers.google.com/web/tools/workbox/reference-docs/latest/workbox.strategies new workbox.strategies.NetworkFirst({ cacheName: 'workbox:html', diff --git a/src/containers/ProjectMetadata.ts b/src/containers/ProjectMetadata.ts index 01fbd86c2..e3f1ef61c 100644 --- a/src/containers/ProjectMetadata.ts +++ b/src/containers/ProjectMetadata.ts @@ -16,6 +16,7 @@ function useProjectMetadataImpl() { const getMetadataFromCid = async (cid: string): Promise => { const result = await catSingle(cid); + const rawMeta = JSON.parse(Buffer.from(result).toString('utf8')); return projectMetadataSchema.validate({ type: 'SUBQUERY', ...rawMeta }); }; diff --git a/src/containers/ProjectRegistry.ts b/src/containers/ProjectRegistry.ts index 0e3fb84cb..2905475ec 100644 --- a/src/containers/ProjectRegistry.ts +++ b/src/containers/ProjectRegistry.ts @@ -122,7 +122,11 @@ function useProjectRegistryImpl(logger: Logger) { projectRegistry.tokenURI(id), ]); - const deploymentInfo = await projectRegistry.deploymentInfos(cidToBytes32(project.latestDeploymentId)); + const deploymentInfo = await projectRegistry.deploymentInfos( + project.latestDeploymentId.startsWith('Qm') + ? cidToBytes32(project.latestDeploymentId) + : project.latestDeploymentId, + ); projectCache.current[BigNumber.from(id).toString()] = { owner, diff --git a/src/hooks/useCreateProject.tsx b/src/hooks/useCreateProject.tsx index c8f92ea8a..ec3d50ef7 100644 --- a/src/hooks/useCreateProject.tsx +++ b/src/hooks/useCreateProject.tsx @@ -43,7 +43,7 @@ export function useCreateProject(): (params: P) => Promise { throw new Error('No successful events'); } - return event.args?.['queryId']; + return event.args?.['tokenId']; }, [ipfs, uploadMetadata, registerProject, uploadVersionMetadata], ); diff --git a/src/models.tsx b/src/models.tsx index 95a67d497..200200dcb 100644 --- a/src/models.tsx +++ b/src/models.tsx @@ -18,6 +18,7 @@ export const projectMetadataSchema = yup.object({ websiteUrl: yup.string().optional().url(), codeUrl: yup.string().optional().url(), versionDescription: yup.string().default('').optional(), + categories: yup.array().max(2), }); export type ProjectMetadata = yup.Asserts; diff --git a/src/pages/studio/Create/Create.module.css b/src/pages/studio/Create/Create.module.css deleted file mode 100644 index eecc65ee1..000000000 --- a/src/pages/studio/Create/Create.module.css +++ /dev/null @@ -1,46 +0,0 @@ -.form { - display: flex; - flex-direction: row; - align-items: flex-start; - padding: 0 80px 80px 80px; -} - -.deployment { - font-family: Futura; - font-weight: 500; - font-size: 18px; - line-height: 28px; - color: var(--gray900); - margin-top: 8px; -} - -.header { - display: flex; - flex-direction: row; - justify-content: space-between; - padding: 64px 80px 40px 80px; -} - -.name { - font-family: Futura; - font-weight: 500; - font-size: 32px; - line-height: 48px; - - color: var(--gray900); - padding-left: 22px; -} - -.details { - display: flex; - flex-direction: row; - gap: 22px; -} - -.fields { - display: flex; - flex-direction: column; - gap: 16px; - max-width: 845px; - flex: 1; -} diff --git a/src/pages/studio/Create/Create.module.less b/src/pages/studio/Create/Create.module.less new file mode 100644 index 000000000..2e860d200 --- /dev/null +++ b/src/pages/studio/Create/Create.module.less @@ -0,0 +1,105 @@ +.form { + display: flex; + flex-direction: row; + align-items: flex-start; + padding: 0 80px 80px 80px; +} + +.deployment { + font-family: Futura; + font-weight: 500; + font-size: 18px; + line-height: 28px; + color: var(--gray900); + margin-top: 8px; +} + +.header { + display: flex; + flex-direction: row; + justify-content: space-between; + padding: 64px 80px 40px 80px; +} + +.name { + font-family: Futura; + font-weight: 500; + font-size: 32px; + line-height: 48px; + + color: var(--gray900); + padding-left: 22px; +} + +.details { + display: flex; + flex-direction: row; + gap: 22px; +} + +.fields { + display: flex; + flex-direction: column; + gap: 16px; + max-width: 845px; + flex: 1; +} + +.successModal { + :global { + .ant-modal-confirm-body { + flex-direction: column; + } + + .ant-modal-confirm-paragraph.ant-modal-confirm-paragraph { + max-width: 100%; + } + } +} + +.checkbox { + :global { + .ant-checkbox-group { + .ant-checkbox-wrapper { + background: var(--sq-gray200); + color: var(--sq-gray500); + padding: 5px 16px; + border-radius: 100px; + font-family: var(--sq-font-family); + .ant-checkbox { + &-inner { + width: 0px; + height: 0px; + border: none; + &::after { + width: 0px; + height: 0px; + } + } + } + } + + .ant-checkbox-wrapper.ant-checkbox-wrapper-checked { + color: var(--sq-blue600); + background: rgba(67, 136, 221, 0.10); + + .ant-checkbox { + display: inline-flex; + + &-inner { + // override the antd style. a lazy way. + background: transparent!important; + border: none; + width: 16px; + height: 16px; + &::after { + border-color: var(--sq-blue600); + width: 6px; + height: 9px; + } + } + } + } + } + } +} diff --git a/src/pages/studio/Create/Create.tsx b/src/pages/studio/Create/Create.tsx index b77923e79..e9d195284 100644 --- a/src/pages/studio/Create/Create.tsx +++ b/src/pages/studio/Create/Create.tsx @@ -7,18 +7,41 @@ import { useNavigate } from 'react-router'; import { CloseOutlined } from '@ant-design/icons'; import { BigNumber } from '@ethersproject/bignumber'; import { Markdown, Spinner, Typography } from '@subql/components'; -import { Button, Modal, Result } from 'antd'; +import { Button, Checkbox, Modal, Radio, Result } from 'antd'; import clsx from 'clsx'; -import { Field, Form, Formik } from 'formik'; +import { Field, FieldArray, Form, Formik } from 'formik'; import { FTextInput, ImageInput } from '../../../components'; import { useCreateProject, useProject, useRouteQuery, useUpdateProjectMetadata } from '../../../hooks'; import { FormCreateProjectMetadata, newDeploymentSchema, projectMetadataSchema } from '../../../models'; import { isEthError, parseError, ROUTES } from '../../../utils'; -import styles from './Create.module.css'; +import styles from './Create.module.less'; const { STUDIO_PROJECT_NAV } = ROUTES; +const categoriesOptions = [ + { + label: 'Dictionary', + value: 'Dictionary', + }, + { + label: 'DeFi', + value: 'DeFi', + }, + { + label: 'Oracle', + value: 'Oracle', + }, + { + label: 'Wallet', + value: 'Wallet', + }, + { + label: 'NFT', + value: 'NFT', + }, +]; + const Create: React.FC = () => { const { t } = useTranslation(); @@ -47,6 +70,7 @@ const Create: React.FC = () => { version: project.version, versionDescription: project.versionDescription, type: project.type, + categories: project.categories, }; await updateMetadata(payload); } else { @@ -56,7 +80,8 @@ const Create: React.FC = () => { resultId = BigNumber.from(queryId).toHexString(); } - const { destroy } = Modal.info({ + const { destroy } = Modal.success({ + className: styles.successModal, width: 572, icon: (
@@ -80,6 +105,7 @@ const Create: React.FC = () => { size="large" onClick={() => { navigate(`${STUDIO_PROJECT_NAV}/${resultId}`); + destroy(); }} > View project in Explorer @@ -122,6 +148,7 @@ const Create: React.FC = () => { version: '1.0.0', versionDescription: '', deploymentId: query.get('deploymentId') ?? '', + categories: [], ...(isEdit ? asyncProject.data?.metadata : {}), }} validationSchema={ @@ -186,6 +213,54 @@ const Create: React.FC = () => { ); }} + + Categories + + Select up to 2 + + + + { + return ( +
+ { + arrayHelper.form.setFieldValue('categories', e); + }} + > +
+ ); + }} + >
+ + Project Type + + {({ + field, + form, + }: { + field: { name: string; value: string }; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + form: { setFieldValue: (field: string, val: any) => void }; + }) => { + return ( + { + form.setFieldValue(field.name, val.target.value); + }} + disabled={isEdit ? true : false} + > + SubQuery + RPC + + ); + }} + {isEdit ? ( diff --git a/src/pages/studio/Project/Project.tsx b/src/pages/studio/Project/Project.tsx index 1660f2d55..2b9482d76 100644 --- a/src/pages/studio/Project/Project.tsx +++ b/src/pages/studio/Project/Project.tsx @@ -12,7 +12,7 @@ import clsx from 'clsx'; import { IPFSImage, Spinner } from '../../../components'; import { useWeb3 } from '../../../containers'; import { useCreateDeployment, useProject } from '../../../hooks'; -import { renderAsync } from '../../../utils'; +import { parseError, renderAsync } from '../../../utils'; import DeploymentsTab from './Deployments'; import styles from './Project.module.css'; @@ -34,7 +34,9 @@ const Project: React.FC = () => { return renderAsync(asyncProject, { loading: () => , - error: (error: Error) => {`Failed to load project: ${error.message}`}, + error: (error: Error) => { + return {`Failed to load project: ${parseError(error)}`}; + }, data: (project) => { if (!project) { // Should never happen @@ -134,7 +136,7 @@ const Project: React.FC = () => {
- + Project Detail @@ -142,6 +144,27 @@ const Project: React.FC = () => { {project.metadata.description} + + Categories + + +
+ {project.metadata.categories?.map((category) => { + return ( +
+ {category} +
+ ); + })} +
+