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

add in all conditional fields

* switch between dataset & algorithm fields
* switch between algo privacy & access type fields
* switch between docker image & custom docker image fields
This commit is contained in:
Matthias Kretschmann 2021-11-15 12:44:27 +00:00
parent 5285efd9c0
commit e79dcf2342
Signed by: m
GPG Key ID: 606EEEF3C479A91F
8 changed files with 159 additions and 197 deletions

View File

@ -1,111 +0,0 @@
{
"title": "Publish an Algorithm",
"data": [
{
"name": "name",
"label": "Title",
"placeholder": "e.g. Shapes of Desert Plants",
"help": "Enter a concise title.",
"required": true
},
{
"name": "description",
"label": "Description",
"help": "Add a thorough description with as much detail as possible. You can use [Markdown](https://daringfireball.net/projects/markdown/basics). You can change the description at any time. If you provide personal data, please note that it will remain in the transaction history. For more information on how personal data is handled within the metadata, please refer to our [privacy policy](/privacy/en).",
"type": "textarea",
"required": true
},
{
"name": "files",
"label": "File",
"placeholder": "e.g. https://file.com/file.json",
"help": "Please enter the URL to your algorithm file and click \"ADD FILE\" to validate the data. This URL will be stored encrypted after publishing. Some restrictions apply:\n\n- max. running time: 1 min.\n- [Writing Algorithms for Compute to Data](https://docs.oceanprotocol.com/tutorials/compute-to-data-algorithms/)",
"type": "files",
"required": true
},
{
"name": "dockerImage",
"label": "Docker Image",
"placeholder": "e.g. python3.7",
"help": "Please select an image to run your algorithm.",
"type": "boxSelection",
"options": [],
"required": true
},
{
"name": "image",
"label": "Image URL",
"placeholder": "e.g. oceanprotocol/algo_dockers or https://example.com/image_path",
"help": "Provide the name of a public Docker image or the full url if you have it hosted in a 3rd party repo",
"required": false
},
{
"name": "containerTag",
"label": "Docker Image Tag",
"placeholder": "e.g. latest",
"help": "Provide the tag for your Docker image.",
"required": false
},
{
"name": "timeout",
"label": "Timeout",
"help": "Define how long buyers should be able to download the algorithm again after the initial purchase.",
"placeholder": "Forever",
"type": "select",
"options": ["Forever", "1 day", "1 week", "1 month", "1 year"],
"sortOptions": false,
"required": true
},
{
"name": "dataTokenOptions",
"label": "Datatoken Name & Symbol",
"type": "datatoken",
"help": "The datatoken for this algorithm will be created with this name & symbol.",
"required": true
},
{
"name": "entrypoint",
"label": "Entrypoint",
"placeholder": "e.g. python $ALGO",
"help": "Provide the entrypoint for your algorithm.",
"required": false
},
{
"name": "algorithmPrivacy",
"label": "Algorithm Privacy",
"type": "checkbox",
"options": ["Keep my algorithm private"],
"help": "By default, your algorithm can be downloaded for a fixed or dynamic price in addition to running in compute jobs. Enabling this option will prevent downloading, so your algorithm can only be run as part of a compute job on a data set.",
"required": false
},
{
"name": "author",
"label": "Author",
"placeholder": "e.g. Jelly McJellyfish",
"help": "Give proper attribution for your data set. You are welcome to use a pseudonym, and you can change your author name at any time. Please note that it will remain in the transaction history. For more information on how personal data is handled within the metadata, please refer to our [privacy policy](/privacy/en).",
"required": true
},
{
"name": "tags",
"label": "Tags",
"placeholder": "e.g. logistics, ai",
"help": "Separate tags with comma."
},
{
"name": "providerUri",
"label": "Custom Provider URL",
"type": "providerUri",
"help": "Enter the URL for your custom provider or leave blank to use the default provider. [Learn more](https://github.com/oceanprotocol/provider/).",
"placeholder": "https://provider.polygon.oceanprotocol.com/",
"advanced": true
},
{
"name": "termsAndConditions",
"label": "Terms & Conditions",
"type": "terms",
"options": ["I agree to these Terms and Conditions"],
"required": true
}
],
"success": "Algorithm Published!"
}

View File

@ -2,6 +2,13 @@
"metadata": { "metadata": {
"title": "Metadata", "title": "Metadata",
"fields": [ "fields": [
{
"name": "type",
"label": "Asset Type",
"type": "boxSelection",
"options": ["Dataset", "Algorithm"],
"required": true
},
{ {
"name": "name", "name": "name",
"label": "Title", "label": "Title",
@ -28,6 +35,35 @@
"placeholder": "e.g. logistics, ai", "placeholder": "e.g. logistics, ai",
"help": "Separate tags with comma." "help": "Separate tags with comma."
}, },
{
"name": "dockerImage",
"label": "Docker Image",
"help": "Please select an image to run your algorithm.",
"type": "boxSelection",
"options": ["node:latest", "python:latest", "Custom"],
"required": true
},
{
"name": "dockerImageCustom",
"label": "Docker Image URL",
"placeholder": "e.g. oceanprotocol/algo_dockers or https://example.com/image_path",
"help": "Provide the name of a public Docker image or the full url if you have it hosted in a 3rd party repo",
"required": true
},
{
"name": "dockerImageCustomTag",
"label": "Docker Image Tag",
"placeholder": "e.g. latest",
"help": "Provide the tag for your Docker image.",
"required": true
},
{
"name": "dockerImageCustomEntrypoint",
"label": "Docker Entrypoint",
"placeholder": "e.g. python $ALGO",
"help": "Provide the entrypoint for your algorithm.",
"required": true
},
{ {
"name": "termsAndConditions", "name": "termsAndConditions",
"label": "Terms & Conditions", "label": "Terms & Conditions",
@ -40,13 +76,6 @@
"services": { "services": {
"title": "Access", "title": "Access",
"fields": [ "fields": [
{
"name": "type",
"label": "Asset Type",
"type": "boxSelection",
"options": ["Dataset", "Algorithm"],
"required": true
},
{ {
"name": "dataTokenOptions", "name": "dataTokenOptions",
"label": "Datatoken Name & Symbol", "label": "Datatoken Name & Symbol",
@ -55,11 +84,11 @@
"required": true "required": true
}, },
{ {
"name": "dataTokenOptions", "name": "providerUrl",
"label": "Datatoken Name & Symbol", "label": "Custom Provider URL",
"type": "datatoken", "type": "providerUrl",
"help": "The datatoken for this data set will be created with this name & symbol.", "help": "Enter the URL for your custom provider or leave blank to use the default provider. [Learn more](https://github.com/oceanprotocol/provider/).",
"required": true "placeholder": "e.g. https://provider.polygon.oceanprotocol.com/"
}, },
{ {
"name": "files", "name": "files",
@ -76,6 +105,14 @@
"help": "Please enter the URL to a sample of your data set file and click \"ADD FILE\" to validate the data. This file should reveal the data structure of your data set, e.g. by including the header and one line of a CSV file. This file URL will be publicly available after publishing.", "help": "Please enter the URL to a sample of your data set file and click \"ADD FILE\" to validate the data. This file should reveal the data structure of your data set, e.g. by including the header and one line of a CSV file. This file URL will be publicly available after publishing.",
"type": "files" "type": "files"
}, },
{
"name": "algorithmPrivacy",
"label": "Algorithm Privacy",
"type": "checkbox",
"options": ["Keep my algorithm private"],
"help": "By default, your algorithm can be downloaded for a fixed or dynamic price in addition to running in compute jobs. Enabling this option will prevent downloading, so your algorithm can only be run as part of a compute job on a data set.",
"required": false
},
{ {
"name": "access", "name": "access",
"label": "Access Type", "label": "Access Type",
@ -94,14 +131,6 @@
"options": ["Forever", "1 day", "1 week", "1 month", "1 year"], "options": ["Forever", "1 day", "1 week", "1 month", "1 year"],
"sortOptions": false, "sortOptions": false,
"required": true "required": true
},
{
"name": "providerUrl",
"label": "Custom Provider URL",
"type": "providerUrl",
"help": "Enter the URL for your custom provider or leave blank to use the default provider. [Learn more](https://github.com/oceanprotocol/provider/).",
"placeholder": "e.g. https://provider.polygon.oceanprotocol.com/"
} }
] ]
}, },

View File

@ -14,7 +14,7 @@ interface Metadata {
updated: string updated: string
name: string name: string
description: string description: string
type: 'dataset' | 'algorithm' type: 'dataset' | 'algorithm' | string
author: string author: string
license: string license: string
links?: string[] links?: string[]

View File

@ -7,19 +7,23 @@ import { getFieldContent } from '../_utils'
const assetTypeOptionsTitles = getFieldContent( const assetTypeOptionsTitles = getFieldContent(
'type', 'type',
content.services.fields content.metadata.fields
).options ).options
const assetTypeOptions = [ const dockerImageOptionsTitles = getFieldContent(
{ 'dockerImage',
name: assetTypeOptionsTitles[0].toLowerCase(), content.metadata.fields
title: assetTypeOptionsTitles[0] ).options
},
{ const assetTypeOptions = assetTypeOptionsTitles.map((title) => ({
name: assetTypeOptionsTitles[1].toLowerCase(), name: title.toLowerCase(),
title: assetTypeOptionsTitles[1] title
} }))
]
const dockerImageOptions = dockerImageOptionsTitles.map((title) => ({
name: title.toLowerCase(),
title
}))
export default function MetadataFields(): ReactElement { export default function MetadataFields(): ReactElement {
// connect with Form state, use for conditional field rendering // connect with Form state, use for conditional field rendering
@ -28,9 +32,9 @@ export default function MetadataFields(): ReactElement {
return ( return (
<> <>
<Field <Field
{...getFieldContent('type', content.services.fields)} {...getFieldContent('type', content.metadata.fields)}
component={Input} component={Input}
name="type" name="metadata.type"
options={assetTypeOptions} options={assetTypeOptions}
/> />
<Field <Field
@ -54,6 +58,45 @@ export default function MetadataFields(): ReactElement {
name="metadata.tags" name="metadata.tags"
/> />
{values.metadata.type === 'algorithm' && (
<>
<Field
{...getFieldContent('dockerImage', content.metadata.fields)}
component={Input}
name="metadata.dockerImage"
options={dockerImageOptions}
/>
{values.metadata.dockerImage === 'custom' && (
<>
<Field
{...getFieldContent(
'dockerImageCustom',
content.metadata.fields
)}
component={Input}
name="metadata.dockerImageCustom"
/>
<Field
{...getFieldContent(
'dockerImageCustomTag',
content.metadata.fields
)}
component={Input}
name="metadata.dockerImageCustomTag"
/>
<Field
{...getFieldContent(
'dockerImageCustomEntrypoint',
content.metadata.fields
)}
component={Input}
name="metadata.dockerImageCustomEntrypoint"
/>
</>
)}
</>
)}
<div> <div>
<strong>Fancy NFT display</strong> <strong>Fancy NFT display</strong>
<p> <p>
@ -68,15 +111,6 @@ export default function MetadataFields(): ReactElement {
component={Input} component={Input}
name="metadata.termsAndConditions" name="metadata.termsAndConditions"
/> />
{/* {content.metadata.fields.map((field: FormFieldContent) => (
<Field
{...field}
key={`metadata-${field.name}`}
component={Input}
name={`metadata.${field.name}`}
/>
))} */}
</> </>
) )
} }

View File

@ -1,6 +1,6 @@
import Input from '@shared/Form/Input' import Input from '@shared/Form/Input'
import { Field, useFormikContext } from 'formik' import { Field, useFormikContext } from 'formik'
import React, { ReactElement } from 'react' import React, { ReactElement, useEffect } from 'react'
import IconDownload from '@images/download.svg' import IconDownload from '@images/download.svg'
import IconCompute from '@images/compute.svg' import IconCompute from '@images/compute.svg'
import content from '../../../../content/publish/form.json' import content from '../../../../content/publish/form.json'
@ -27,10 +27,33 @@ const accessTypeOptions = [
export default function ServicesFields(): ReactElement { export default function ServicesFields(): ReactElement {
// connect with Form state, use for conditional field rendering // connect with Form state, use for conditional field rendering
const { values } = useFormikContext<FormPublishData>() const { values, setFieldValue } = useFormikContext<FormPublishData>()
// Auto-change access type based on algo privacy boolean.
// Could be also done later in transformPublishFormToDdo().
useEffect(() => {
setFieldValue(
'services[0].access',
values.services[0].algorithmPrivacy === true ? 'compute' : 'download'
)
}, [values.services[0].algorithmPrivacy])
return ( return (
<> <>
{values.metadata.type === 'algorithm' ? (
<Field
{...getFieldContent('algorithmPrivacy', content.services.fields)}
component={Input}
name="services[0].algorithmPrivacy"
/>
) : (
<Field
{...getFieldContent('access', content.services.fields)}
component={Input}
name="services[0].access"
options={accessTypeOptions}
/>
)}
<Field <Field
{...getFieldContent('dataTokenOptions', content.services.fields)} {...getFieldContent('dataTokenOptions', content.services.fields)}
component={Input} component={Input}
@ -51,32 +74,11 @@ export default function ServicesFields(): ReactElement {
component={Input} component={Input}
name="services[0].links" name="services[0].links"
/> />
<Field
{...getFieldContent('access', content.services.fields)}
component={Input}
name="services[0].access"
options={accessTypeOptions}
/>
<Field <Field
{...getFieldContent('timeout', content.services.fields)} {...getFieldContent('timeout', content.services.fields)}
component={Input} component={Input}
name="services[0].timeout" name="services[0].timeout"
/> />
{/* {content.services.fields.map(
(field: FormFieldContent) =>
field.advanced !== true && (
<Field
{...field}
key={`services-${field.name}`}
component={Input}
name={`services[0].${field.name}`}
options={
field.name === 'access' ? accessTypeOptions : field.options
}
/>
)
)} */}
</> </>
) )
} }

View File

@ -36,13 +36,17 @@ export const initialValues: FormPublishData = {
chainId: 1, chainId: 1,
accountId: '', accountId: '',
metadata: { metadata: {
type: 'dataset', type: '',
name: '', name: '',
author: '', author: '',
description: '', description: '',
tags: '', tags: '',
links: [], links: [],
termsAndConditions: false termsAndConditions: false,
dockerImage: '',
dockerImageCustom: '',
dockerImageCustomTag: '',
dockerImageCustomEntrypoint: ''
}, },
services: [ services: [
{ {

View File

@ -6,10 +6,8 @@ export interface FormPublishService {
timeout: string timeout: string
dataTokenOptions: DataTokenOptions dataTokenOptions: DataTokenOptions
access: 'Download' | 'Compute' | string access: 'Download' | 'Compute' | string
image?: string
containerTag?: string
entrypoint?: string
providerUrl?: string providerUrl?: string
algorithmPrivacy?: boolean
} }
export interface FormPublishData { export interface FormPublishData {
@ -17,13 +15,17 @@ export interface FormPublishData {
accountId: string accountId: string
chainId: number chainId: number
metadata: { metadata: {
type: 'dataset' | 'algorithm' type: 'Dataset' | 'Algorithm' | string
name: string name: string
description: string description: string
author: string author: string
termsAndConditions: boolean termsAndConditions: boolean
tags?: string tags?: string
links?: string[] links?: string[]
dockerImage?: string
dockerImageCustom?: string
dockerImageCustomTag?: string
dockerImageCustomEntrypoint?: string
} }
services: FormPublishService[] services: FormPublishService[]
pricing: PriceOptions pricing: PriceOptions

View File

@ -55,17 +55,19 @@ export async function transformPublishFormToDdo(
const { chainId, accountId, metadata, services } = values const { chainId, accountId, metadata, services } = values
const did = sha256(`${nftAddress}${chainId}`) const did = sha256(`${nftAddress}${chainId}`)
const currentTime = dateToStringNoMS(new Date()) const currentTime = dateToStringNoMS(new Date())
const { type, name, description, tags, links, author, termsAndConditions } =
metadata
const { const {
access, type,
files, name,
image, description,
containerTag, tags,
entrypoint, links,
providerUrl, author,
timeout termsAndConditions,
} = services[0] dockerImageCustom,
dockerImageCustomTag,
dockerImageCustomEntrypoint
} = metadata
const { access, files, providerUrl, timeout } = services[0]
const filesEncrypted = await getEncryptedFileUrls( const filesEncrypted = await getEncryptedFileUrls(
files as string[], files as string[],
@ -92,9 +94,9 @@ export async function transformPublishFormToDdo(
language: getUrlFileExtension(files[0]), language: getUrlFileExtension(files[0]),
version: '0.1', version: '0.1',
container: { container: {
entrypoint, entrypoint: dockerImageCustomEntrypoint,
image, image: dockerImageCustom,
tag: containerTag, tag: dockerImageCustomTag,
checksum: '' // how to get? Is it user input? checksum: '' // how to get? Is it user input?
} }
} }
@ -109,7 +111,7 @@ export async function transformPublishFormToDdo(
timeout, timeout,
...(access === 'compute' && { ...(access === 'compute' && {
compute: { compute: {
namespace: '', namespace: 'ocean-compute',
cpu: 1, cpu: 1,
gpu: 1, gpu: 1,
gpuType: '', gpuType: '',