diff --git a/content/form-algorithm.json b/content/form-algorithm.json deleted file mode 100644 index ff186be54..000000000 --- a/content/form-algorithm.json +++ /dev/null @@ -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!" -} diff --git a/content/publish/form.json b/content/publish/form.json index 1aaa11fbb..a612b9d11 100644 --- a/content/publish/form.json +++ b/content/publish/form.json @@ -2,6 +2,13 @@ "metadata": { "title": "Metadata", "fields": [ + { + "name": "type", + "label": "Asset Type", + "type": "boxSelection", + "options": ["Dataset", "Algorithm"], + "required": true + }, { "name": "name", "label": "Title", @@ -28,6 +35,35 @@ "placeholder": "e.g. logistics, ai", "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", "label": "Terms & Conditions", @@ -40,13 +76,6 @@ "services": { "title": "Access", "fields": [ - { - "name": "type", - "label": "Asset Type", - "type": "boxSelection", - "options": ["Dataset", "Algorithm"], - "required": true - }, { "name": "dataTokenOptions", "label": "Datatoken Name & Symbol", @@ -55,11 +84,11 @@ "required": true }, { - "name": "dataTokenOptions", - "label": "Datatoken Name & Symbol", - "type": "datatoken", - "help": "The datatoken for this data set will be created with this name & symbol.", - "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/" }, { "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.", "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", "label": "Access Type", @@ -94,14 +131,6 @@ "options": ["Forever", "1 day", "1 week", "1 month", "1 year"], "sortOptions": false, "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/" } ] }, diff --git a/src/@types/DDO/Metadata.d.ts b/src/@types/DDO/Metadata.d.ts index b41963f20..4227acd75 100644 --- a/src/@types/DDO/Metadata.d.ts +++ b/src/@types/DDO/Metadata.d.ts @@ -14,7 +14,7 @@ interface Metadata { updated: string name: string description: string - type: 'dataset' | 'algorithm' + type: 'dataset' | 'algorithm' | string author: string license: string links?: string[] diff --git a/src/components/Publish/Metadata/index.tsx b/src/components/Publish/Metadata/index.tsx index 5eedc2fd0..b092f9143 100644 --- a/src/components/Publish/Metadata/index.tsx +++ b/src/components/Publish/Metadata/index.tsx @@ -7,19 +7,23 @@ import { getFieldContent } from '../_utils' const assetTypeOptionsTitles = getFieldContent( 'type', - content.services.fields + content.metadata.fields ).options -const assetTypeOptions = [ - { - name: assetTypeOptionsTitles[0].toLowerCase(), - title: assetTypeOptionsTitles[0] - }, - { - name: assetTypeOptionsTitles[1].toLowerCase(), - title: assetTypeOptionsTitles[1] - } -] +const dockerImageOptionsTitles = getFieldContent( + 'dockerImage', + content.metadata.fields +).options + +const assetTypeOptions = assetTypeOptionsTitles.map((title) => ({ + name: title.toLowerCase(), + title +})) + +const dockerImageOptions = dockerImageOptionsTitles.map((title) => ({ + name: title.toLowerCase(), + title +})) export default function MetadataFields(): ReactElement { // connect with Form state, use for conditional field rendering @@ -28,9 +32,9 @@ export default function MetadataFields(): ReactElement { return ( <> + {values.metadata.type === 'algorithm' && ( + <> + + {values.metadata.dockerImage === 'custom' && ( + <> + + + + + )} + + )} +
Fancy NFT display

@@ -68,15 +111,6 @@ export default function MetadataFields(): ReactElement { component={Input} name="metadata.termsAndConditions" /> - - {/* {content.metadata.fields.map((field: FormFieldContent) => ( - - ))} */} ) } diff --git a/src/components/Publish/Services/index.tsx b/src/components/Publish/Services/index.tsx index 849f74b9d..ec2eb4956 100644 --- a/src/components/Publish/Services/index.tsx +++ b/src/components/Publish/Services/index.tsx @@ -1,6 +1,6 @@ import Input from '@shared/Form/Input' import { Field, useFormikContext } from 'formik' -import React, { ReactElement } from 'react' +import React, { ReactElement, useEffect } from 'react' import IconDownload from '@images/download.svg' import IconCompute from '@images/compute.svg' import content from '../../../../content/publish/form.json' @@ -27,10 +27,33 @@ const accessTypeOptions = [ export default function ServicesFields(): ReactElement { // connect with Form state, use for conditional field rendering - const { values } = useFormikContext() + const { values, setFieldValue } = useFormikContext() + + // 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 ( <> + {values.metadata.type === 'algorithm' ? ( + + ) : ( + + )} - - - {/* {content.services.fields.map( - (field: FormFieldContent) => - field.advanced !== true && ( - - ) - )} */} ) } diff --git a/src/components/Publish/_constants.tsx b/src/components/Publish/_constants.tsx index 606af3d05..76229e446 100644 --- a/src/components/Publish/_constants.tsx +++ b/src/components/Publish/_constants.tsx @@ -36,13 +36,17 @@ export const initialValues: FormPublishData = { chainId: 1, accountId: '', metadata: { - type: 'dataset', + type: '', name: '', author: '', description: '', tags: '', links: [], - termsAndConditions: false + termsAndConditions: false, + dockerImage: '', + dockerImageCustom: '', + dockerImageCustomTag: '', + dockerImageCustomEntrypoint: '' }, services: [ { diff --git a/src/components/Publish/_types.ts b/src/components/Publish/_types.ts index 8aebd8f9e..e2556613e 100644 --- a/src/components/Publish/_types.ts +++ b/src/components/Publish/_types.ts @@ -6,10 +6,8 @@ export interface FormPublishService { timeout: string dataTokenOptions: DataTokenOptions access: 'Download' | 'Compute' | string - image?: string - containerTag?: string - entrypoint?: string providerUrl?: string + algorithmPrivacy?: boolean } export interface FormPublishData { @@ -17,13 +15,17 @@ export interface FormPublishData { accountId: string chainId: number metadata: { - type: 'dataset' | 'algorithm' + type: 'Dataset' | 'Algorithm' | string name: string description: string author: string termsAndConditions: boolean tags?: string links?: string[] + dockerImage?: string + dockerImageCustom?: string + dockerImageCustomTag?: string + dockerImageCustomEntrypoint?: string } services: FormPublishService[] pricing: PriceOptions diff --git a/src/components/Publish/_utils.ts b/src/components/Publish/_utils.ts index 1d91b36f1..a92c450c9 100644 --- a/src/components/Publish/_utils.ts +++ b/src/components/Publish/_utils.ts @@ -55,17 +55,19 @@ export async function transformPublishFormToDdo( const { chainId, accountId, metadata, services } = values const did = sha256(`${nftAddress}${chainId}`) const currentTime = dateToStringNoMS(new Date()) - const { type, name, description, tags, links, author, termsAndConditions } = - metadata const { - access, - files, - image, - containerTag, - entrypoint, - providerUrl, - timeout - } = services[0] + type, + name, + description, + tags, + links, + author, + termsAndConditions, + dockerImageCustom, + dockerImageCustomTag, + dockerImageCustomEntrypoint + } = metadata + const { access, files, providerUrl, timeout } = services[0] const filesEncrypted = await getEncryptedFileUrls( files as string[], @@ -92,9 +94,9 @@ export async function transformPublishFormToDdo( language: getUrlFileExtension(files[0]), version: '0.1', container: { - entrypoint, - image, - tag: containerTag, + entrypoint: dockerImageCustomEntrypoint, + image: dockerImageCustom, + tag: dockerImageCustomTag, checksum: '' // how to get? Is it user input? } } @@ -109,7 +111,7 @@ export async function transformPublishFormToDdo( timeout, ...(access === 'compute' && { compute: { - namespace: '', + namespace: 'ocean-compute', cpu: 1, gpu: 1, gpuType: '',