1
0
mirror of https://github.com/oceanprotocol/market.git synced 2024-12-02 05:57:29 +01:00

Merge pull request #394 from oceanprotocol/publish-algo-tabs

refactor publish page for tab usage
This commit is contained in:
Matthias Kretschmann 2021-02-23 11:30:57 +01:00 committed by GitHub
commit 7b8c11ea36
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 137 additions and 150 deletions

View File

@ -1,5 +1,5 @@
{ {
"title": "Publish", "title": "Publish an Algorithm",
"data": [ "data": [
{ {
"name": "name", "name": "name",

View File

@ -1,5 +1,5 @@
{ {
"title": "Publish", "title": "Publish a Data Set",
"data": [ "data": [
{ {
"name": "name", "name": "name",

View File

@ -1,5 +1,5 @@
{ {
"title": "Publish", "title": "Publish",
"description": "Highlight the important features of your data set to make it more discoverable and catch the interest of data consumers.", "description": "Highlight the important features of your data set or algorithm to make it more discoverable and catch the interest of data consumers.",
"warning": "Given the beta status, publishing on Ropsten or Rinkeby first is strongly recommended. Please familiarize yourself with [the market](https://oceanprotocol.com/technology/marketplaces), [the risks](https://blog.oceanprotocol.com/on-staking-on-data-in-ocean-market-3d8e09eb0a13), and the [Terms of Use](/terms)." "warning": "Given the beta status, publishing on Ropsten or Rinkeby first is strongly recommended. Please familiarize yourself with [the market](https://oceanprotocol.com/technology/marketplaces), [the risks](https://blog.oceanprotocol.com/on-staking-on-data-in-ocean-market-3d8e09eb0a13), and the [Terms of Use](/terms)."
} }

View File

@ -13,6 +13,7 @@
text-transform: uppercase; text-transform: uppercase;
cursor: pointer; cursor: pointer;
color: var(--color-secondary); color: var(--color-secondary);
background-color: var(--background-body);
border: 1px solid var(--border-color); border: 1px solid var(--border-color);
margin-right: -1px; margin-right: -1px;
min-width: 100px; min-width: 100px;
@ -29,7 +30,7 @@
} }
.tab[aria-selected='true'] { .tab[aria-selected='true'] {
background: var(--font-color-heading); background-color: var(--font-color-heading);
color: var(--background-body); color: var(--background-body);
border-color: var(--font-color-heading); border-color: var(--font-color-heading);
} }

View File

@ -1,5 +1,6 @@
.preview { .preview {
font-size: var(--font-size-small); font-size: var(--font-size-small);
margin-top: calc(var(--spacer) / 2);
margin-bottom: var(--spacer); margin-bottom: var(--spacer);
} }

View File

@ -3,7 +3,6 @@ import styles from './index.module.css'
import Compute from './Compute' import Compute from './Compute'
import Consume from './Consume' import Consume from './Consume'
import { Logger } from '@oceanprotocol/lib' import { Logger } from '@oceanprotocol/lib'
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
import Tabs from '../../atoms/Tabs' import Tabs from '../../atoms/Tabs'
import { useOcean } from '@oceanprotocol/react' import { useOcean } from '@oceanprotocol/react'
import compareAsBN from '../../../utils/compareAsBN' import compareAsBN from '../../../utils/compareAsBN'

View File

@ -7,15 +7,16 @@ import Input from '../../atoms/Input'
import Button from '../../atoms/Button' import Button from '../../atoms/Button'
import { FormContent, FormFieldProps } from '../../../@types/Form' import { FormContent, FormFieldProps } from '../../../@types/Form'
import { MetadataPublishFormAlgorithm } from '../../../@types/MetaData' import { MetadataPublishFormAlgorithm } from '../../../@types/MetaData'
import stylesIndex from './index.module.css'
const query = graphql` const query = graphql`
query { query {
content: allFile( content: allFile(
filter: { relativePath: { eq: "pages/form-algorithm.json" } } filter: { relativePath: { eq: "pages/publish/form-algorithm.json" } }
) { ) {
edges { edges {
node { node {
childPagesJson { childPublishJson {
title title
data { data {
name name
@ -38,7 +39,7 @@ const query = graphql`
export default function FormPublish(): ReactElement { export default function FormPublish(): ReactElement {
const data = useStaticQuery(query) const data = useStaticQuery(query)
const content: FormContent = data.content.edges[0].node.childPagesJson const content: FormContent = data.content.edges[0].node.childPublishJson
const { ocean, account } = useOcean() const { ocean, account } = useOcean()
const { const {
status, status,
@ -56,7 +57,7 @@ export default function FormPublish(): ReactElement {
useEffect(() => { useEffect(() => {
setErrors({}) setErrors({})
setTouched({}) setTouched({})
resetForm({ values: initialValues, status: 'empty' })
// setSubmitting(false) // setSubmitting(false)
}, [setErrors, setTouched]) }, [setErrors, setTouched])
@ -124,6 +125,7 @@ export default function FormPublish(): ReactElement {
// do we need this? // do we need this?
onChange={() => status === 'empty' && setStatus(null)} onChange={() => status === 'empty' && setStatus(null)}
> >
<h2 className={stylesIndex.formTitle}>{content.title}</h2>
{content.data.map((field: FormFieldProps) => ( {content.data.map((field: FormFieldProps) => (
<Field <Field
key={field.name} key={field.name}

View File

@ -1,6 +1,9 @@
.form { .form {
composes: box from '../../atoms/Box.module.css'; composes: box from '../../atoms/Box.module.css';
margin-bottom: var(--spacer); margin-bottom: var(--spacer);
border-top: none;
border-top-left-radius: 0;
border-top-right-radius: 0;
} }
.actions { .actions {

View File

@ -7,15 +7,16 @@ import Input from '../../atoms/Input'
import Button from '../../atoms/Button' import Button from '../../atoms/Button'
import { FormContent, FormFieldProps } from '../../../@types/Form' import { FormContent, FormFieldProps } from '../../../@types/Form'
import { MetadataPublishFormDataset } from '../../../@types/MetaData' import { MetadataPublishFormDataset } from '../../../@types/MetaData'
import stylesIndex from './index.module.css'
const query = graphql` const query = graphql`
query { query {
content: allFile( content: allFile(
filter: { relativePath: { eq: "pages/form-dataset.json" } } filter: { relativePath: { eq: "pages/publish/form-dataset.json" } }
) { ) {
edges { edges {
node { node {
childPagesJson { childPublishJson {
title title
data { data {
name name
@ -38,7 +39,7 @@ const query = graphql`
export default function FormPublish(): ReactElement { export default function FormPublish(): ReactElement {
const data = useStaticQuery(query) const data = useStaticQuery(query)
const content: FormContent = data.content.edges[0].node.childPagesJson const content: FormContent = data.content.edges[0].node.childPublishJson
const { ocean, account } = useOcean() const { ocean, account } = useOcean()
const { const {
status, status,
@ -82,6 +83,7 @@ export default function FormPublish(): ReactElement {
// do we need this? // do we need this?
onChange={() => status === 'empty' && setStatus(null)} onChange={() => status === 'empty' && setStatus(null)}
> >
<h2 className={stylesIndex.formTitle}>{content.title}</h2>
{content.data.map((field: FormFieldProps) => ( {content.data.map((field: FormFieldProps) => (
<Field <Field
key={field.name} key={field.name}

View File

@ -1,29 +0,0 @@
.tabElement,
button.tabElement,
.tabElement:hover,
.tabElement:active,
.tabElement:focus {
border: 1px solid var(--border-color);
text-transform: uppercase;
border-radius: var(--border-radius);
margin-right: calc(var(--spacer) / 6);
margin-bottom: calc(var(--spacer) / 6);
color: var(--color-secondary);
background: var(--background-body);
/* the only thing not possible to overwrite button style="text" with more specifity of selectors, so sledgehammer */
padding: calc(var(--spacer) / 5) !important;
}
.tabElement:hover,
.tabElement:focus {
color: var(--font-color-text);
background: inherit;
transform: none;
}
.tabElement.selected {
color: var(--background-body);
background: var(--font-color-text);
border-color: var(--background-body);
}

View File

@ -1,48 +0,0 @@
import React, { ReactElement, useEffect } from 'react'
import styles from './PublishType.module.css'
import classNames from 'classnames/bind'
import Button from '../../atoms/Button'
const cx = classNames.bind(styles)
export const TypeOfPublish = {
dataset: 'dataset',
algorithm: 'algorithm'
} as const
type TypeOfPublish = typeof TypeOfPublish[keyof typeof TypeOfPublish]
export function PublishType({
type,
setType
}: {
type: string
setType: React.Dispatch<React.SetStateAction<string>>
}): ReactElement {
useEffect(() => {
setType(TypeOfPublish.dataset)
}, [])
return (
<div>
{Object.keys(TypeOfPublish).map((key, index) => {
const tabElement = cx({
[styles.selected]: key === type,
[styles.tabElement]: true
})
return (
<Button
size="small"
style="text"
key={index}
className={tabElement}
onClick={async () => {
setType(key)
}}
>
{key}
</Button>
)
})}
</div>
)
}

View File

@ -1,3 +1,16 @@
.tabs ul[class*='tabList'] {
background-color: var(--background-body);
border: 1px solid var(--border-color);
border-top-left-radius: var(--border-radius);
border-top-right-radius: var(--border-radius);
}
.tabs div[class*='tabContent'] {
padding-left: 0;
padding-right: 0;
padding-top: 0;
}
.grid { .grid {
display: grid; display: grid;
gap: calc(var(--spacer) * 1.5); gap: calc(var(--spacer) * 1.5);
@ -16,8 +29,17 @@ div.alert {
grid-template-columns: 1.618fr 1fr; grid-template-columns: 1.618fr 1fr;
} }
.tabs ul[class*='tabList'] {
/* fake the above 1.618fr column */
max-width: calc((100% / 1.618) - calc(var(--spacer) / 1.075));
}
.sticky { .sticky {
position: sticky; position: sticky;
top: calc(var(--spacer) / 2); top: calc(var(--spacer) / 2);
} }
} }
.formTitle {
font-size: var(--font-size-h4);
}

View File

@ -4,9 +4,8 @@ import { usePublish, useOcean } from '@oceanprotocol/react'
import styles from './index.module.css' import styles from './index.module.css'
import FormPublish from './FormPublish' import FormPublish from './FormPublish'
import FormAlgoPublish from './FormAlgoPublish' import FormAlgoPublish from './FormAlgoPublish'
import { PublishType, TypeOfPublish } from './PublishType'
import Web3Feedback from '../../molecules/Wallet/Feedback' import Web3Feedback from '../../molecules/Wallet/Feedback'
import { FormContent } from '../../../@types/Form' import Tabs from '../../atoms/Tabs'
import { initialValues, validationSchema } from '../../../models/FormPublish' import { initialValues, validationSchema } from '../../../models/FormPublish'
import { import {
initialValues as initialValuesAlgorithm, initialValues as initialValuesAlgorithm,
@ -27,14 +26,40 @@ import {
MetadataPublishFormAlgorithm MetadataPublishFormAlgorithm
} from '../../../@types/MetaData' } from '../../../@types/MetaData'
import { useUserPreferences } from '../../../providers/UserPreferences' import { useUserPreferences } from '../../../providers/UserPreferences'
import { Logger, Metadata } from '@oceanprotocol/lib' import { Logger, Metadata, MetadataMain } from '@oceanprotocol/lib'
import { Persist } from '../../atoms/FormikPersist' import { Persist } from '../../atoms/FormikPersist'
import Debug from './Debug' import Debug from './Debug'
import Alert from '../../atoms/Alert' import Alert from '../../atoms/Alert'
import MetadataFeedback from '../../molecules/MetadataFeedback' import MetadataFeedback from '../../molecules/MetadataFeedback'
import Button from '../../atoms/Button'
const formName = 'ocean-publish-form' const formNameDatasets = 'ocean-publish-form-datasets'
const formNameAlgorithms = 'ocean-publish-form-algorithms'
function TabContent({
publishType,
values
}: {
publishType: MetadataMain['type']
values: Partial<MetadataPublishFormAlgorithm | MetadataPublishFormDataset>
}) {
return (
<article className={styles.grid}>
{publishType === 'dataset' ? <FormPublish /> : <FormAlgoPublish />}
<aside>
<div className={styles.sticky}>
{publishType === 'dataset' ? (
<MetadataPreview values={values} />
) : (
<MetadataAlgorithmPreview values={values} />
)}
<Web3Feedback />
</div>
</aside>
</article>
)
}
export default function PublishPage({ export default function PublishPage({
content content
@ -48,12 +73,14 @@ export default function PublishPage({
const [error, setError] = useState<string>() const [error, setError] = useState<string>()
const [title, setTitle] = useState<string>() const [title, setTitle] = useState<string>()
const [did, setDid] = useState<string>() const [did, setDid] = useState<string>()
const [publishType, setPublishType] = useState<string>() const [publishType, setPublishType] = useState<MetadataMain['type']>(
'dataset'
)
const hasFeedback = isLoading || error || success const hasFeedback = isLoading || error || success
useEffect(() => { useEffect(() => {
publishType === TypeOfPublish.dataset publishType === 'dataset'
? setTitle('Publishing Data Set') ? setTitle('Publishing Data Set')
: setTitle('Publishing Algorithm') : setTitle('Publishing Algorithm')
}, [publishType]) }, [publishType])
@ -137,73 +164,78 @@ export default function PublishPage({
return isInPurgatory && purgatoryData ? null : ( return isInPurgatory && purgatoryData ? null : (
<Formik <Formik
initialValues={ initialValues={
publishType === TypeOfPublish.dataset publishType === 'dataset' ? initialValues : initialValuesAlgorithm
? initialValues
: initialValuesAlgorithm
} }
initialStatus="empty" initialStatus="empty"
validationSchema={ validationSchema={
publishType === TypeOfPublish.dataset publishType === 'dataset' ? validationSchema : validationSchemaAlgorithm
? validationSchema
: validationSchemaAlgorithm
} }
onSubmit={async (values, { resetForm }) => { onSubmit={async (values, { resetForm }) => {
// move user's focus to top of screen // move user's focus to top of screen
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' }) window.scrollTo({ top: 0, left: 0, behavior: 'smooth' })
// kick off publishing // kick off publishing
publishType === TypeOfPublish.dataset publishType === 'dataset'
? await handleSubmit(values, resetForm) ? await handleSubmit(values, resetForm)
: await handleAlgorithmSubmit(values, resetForm) : await handleAlgorithmSubmit(values, resetForm)
}} }}
> >
{({ values }) => ( {({ values }) => {
<> const tabs = [
<Persist name={formName} ignoreFields={['isSubmitting']} /> {
title: 'Data Set',
content: <TabContent values={values} publishType={publishType} />
},
{
title: 'Algorithm',
content: <TabContent values={values} publishType={publishType} />
}
]
{hasFeedback ? ( return (
<MetadataFeedback <>
title={title} <Persist
error={error} name={
success={success} publishType === 'dataset'
loading={publishStepText} ? formNameDatasets
setError={setError} : formNameAlgorithms
successAction={{ }
name: 'Go to data set →', ignoreFields={['isSubmitting']}
to: `/asset/${did}`
}}
/> />
) : (
<> {hasFeedback ? (
<PublishType type={publishType} setType={setPublishType} /> <MetadataFeedback
<Alert title={title}
text={content.warning} error={error}
state="info" success={success}
className={styles.alert} loading={publishStepText}
setError={setError}
successAction={{
name: 'Go to data set →',
to: `/asset/${did}`
}}
/> />
<article className={styles.grid}> ) : (
{publishType === TypeOfPublish.dataset ? ( <>
<FormPublish /> <Alert
) : ( text={content.warning}
<FormAlgoPublish /> state="info"
)} className={styles.alert}
/>
<aside> <Tabs
<div className={styles.sticky}> className={styles.tabs}
{publishType === TypeOfPublish.dataset ? ( items={tabs}
<MetadataPreview values={values} /> handleTabChange={(title) =>
) : ( setPublishType(title.toLowerCase().replace(' ', '') as any)
<MetadataAlgorithmPreview values={values} /> }
)} />
<Web3Feedback /> </>
</div> )}
</aside>
</article>
</>
)}
{debug === true && <Debug values={values} />} {debug === true && <Debug values={values} />}
</> </>
)} )
}}
</Formik> </Formik>
) )
} }

View File

@ -4,7 +4,7 @@ import Page from '../components/templates/Page'
import { graphql, PageProps } from 'gatsby' import { graphql, PageProps } from 'gatsby'
export default function PageGatsbyPublish(props: PageProps): ReactElement { export default function PageGatsbyPublish(props: PageProps): ReactElement {
const content = (props.data as any).content.edges[0].node.childPagesJson const content = (props.data as any).content.edges[0].node.childPublishJson
const { title, description } = content const { title, description } = content
return ( return (
@ -16,10 +16,12 @@ export default function PageGatsbyPublish(props: PageProps): ReactElement {
export const contentQuery = graphql` export const contentQuery = graphql`
query PublishPageQuery { query PublishPageQuery {
content: allFile(filter: { relativePath: { eq: "pages/index.json" } }) { content: allFile(
filter: { relativePath: { eq: "pages/publish/index.json" } }
) {
edges { edges {
node { node {
childPagesJson { childPublishJson {
title title
description description
warning warning

View File

@ -1,7 +1,7 @@
import React from 'react' import React from 'react'
import { render } from '@testing-library/react' import { render } from '@testing-library/react'
import Publish from '../../../src/components/pages/Publish' import Publish from '../../../src/components/pages/Publish'
import content from '../../../content/pages/index.json' import content from '../../../content/pages/publish/index.json'
describe('Home', () => { describe('Home', () => {
it('renders without crashing', () => { it('renders without crashing', () => {