mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
declarative metadata & services form setup, prepare transformPublishFormToDdo method
This commit is contained in:
parent
cdbe413765
commit
66adc097b6
@ -1,6 +1,6 @@
|
||||
{
|
||||
"metadata": {
|
||||
"title": "Enter details",
|
||||
"title": "Metadata",
|
||||
"fields": [
|
||||
{
|
||||
"name": "name",
|
||||
@ -38,7 +38,7 @@
|
||||
]
|
||||
},
|
||||
"services": {
|
||||
"title": "Create services",
|
||||
"title": "Access",
|
||||
"fields": [
|
||||
{
|
||||
"name": "dataTokenOptions",
|
||||
@ -87,13 +87,12 @@
|
||||
"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
|
||||
"placeholder": "e.g. https://provider.polygon.oceanprotocol.com/"
|
||||
}
|
||||
]
|
||||
},
|
||||
"pricing": {
|
||||
"title": "Create pricing schema",
|
||||
"title": "Pricing",
|
||||
"fields": [
|
||||
{
|
||||
"name": "dummy content, as content is defined under 'create' key in ../price.json"
|
||||
|
16
src/@types/Form.d.ts
vendored
16
src/@types/Form.d.ts
vendored
@ -1,13 +1,8 @@
|
||||
import { AssetSelectionAsset } from '@shared/Form/FormFields/AssetSelection'
|
||||
|
||||
// declaring into global scope to be able to use this as
|
||||
// ambiant types despite the above imports
|
||||
declare global {
|
||||
interface FormFieldProps {
|
||||
interface FormFieldContent {
|
||||
label: string
|
||||
name: string
|
||||
type?: string
|
||||
options?: string[] | AssetSelectionAsset[]
|
||||
options?: string[]
|
||||
sortOptions?: boolean
|
||||
required?: boolean
|
||||
multiple?: boolean
|
||||
@ -19,11 +14,10 @@ declare global {
|
||||
disclaimer?: string
|
||||
disclaimerValues?: string[]
|
||||
advanced?: boolean
|
||||
}
|
||||
}
|
||||
|
||||
interface FormStepContent {
|
||||
interface FormStepContent {
|
||||
title: string
|
||||
description?: string
|
||||
fields: FormFieldProps[]
|
||||
}
|
||||
fields: FormFieldContent[]
|
||||
}
|
||||
|
5
src/@types/aquarius/MetaData.d.ts
vendored
5
src/@types/aquarius/MetaData.d.ts
vendored
@ -7,6 +7,11 @@ import {
|
||||
// declaring into global scope to be able to use this as
|
||||
// ambiant types despite the above imports
|
||||
declare global {
|
||||
interface DdoMarket {
|
||||
metadata: any
|
||||
services: any[]
|
||||
}
|
||||
|
||||
interface AdditionalInformationMarket extends AdditionalInformation {
|
||||
termsAndConditions: boolean
|
||||
}
|
||||
|
97
src/@utils/ddo.ts
Normal file
97
src/@utils/ddo.ts
Normal file
@ -0,0 +1,97 @@
|
||||
import axios from 'axios'
|
||||
import { toast } from 'react-toastify'
|
||||
import isUrl from 'is-url-superb'
|
||||
import slugify from 'slugify'
|
||||
import { MetadataAlgorithm, Logger } from '@oceanprotocol/lib'
|
||||
|
||||
export function dateToStringNoMS(date: Date): string {
|
||||
return date.toISOString().replace(/\.[0-9]{3}Z/, 'Z')
|
||||
}
|
||||
|
||||
export function transformTags(value: string): string[] {
|
||||
const originalTags = value?.split(',')
|
||||
const transformedTags = originalTags?.map((tag) => slugify(tag).toLowerCase())
|
||||
return transformedTags
|
||||
}
|
||||
|
||||
export function mapTimeoutStringToSeconds(timeout: string): number {
|
||||
switch (timeout) {
|
||||
case 'Forever':
|
||||
return 0
|
||||
case '1 day':
|
||||
return 86400
|
||||
case '1 week':
|
||||
return 604800
|
||||
case '1 month':
|
||||
return 2630000
|
||||
case '1 year':
|
||||
return 31556952
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
function numberEnding(number: number): string {
|
||||
return number > 1 ? 's' : ''
|
||||
}
|
||||
|
||||
export function secondsToString(numberOfSeconds: number): string {
|
||||
if (numberOfSeconds === 0) return 'Forever'
|
||||
|
||||
const years = Math.floor(numberOfSeconds / 31536000)
|
||||
const months = Math.floor((numberOfSeconds %= 31536000) / 2630000)
|
||||
const weeks = Math.floor((numberOfSeconds %= 31536000) / 604800)
|
||||
const days = Math.floor((numberOfSeconds %= 604800) / 86400)
|
||||
const hours = Math.floor((numberOfSeconds %= 86400) / 3600)
|
||||
const minutes = Math.floor((numberOfSeconds %= 3600) / 60)
|
||||
const seconds = numberOfSeconds % 60
|
||||
|
||||
return years
|
||||
? `${years} year${numberEnding(years)}`
|
||||
: months
|
||||
? `${months} month${numberEnding(months)}`
|
||||
: weeks
|
||||
? `${weeks} week${numberEnding(weeks)}`
|
||||
: days
|
||||
? `${days} day${numberEnding(days)}`
|
||||
: hours
|
||||
? `${hours} hour${numberEnding(hours)}`
|
||||
: minutes
|
||||
? `${minutes} minute${numberEnding(minutes)}`
|
||||
: seconds
|
||||
? `${seconds} second${numberEnding(seconds)}`
|
||||
: 'less than a second'
|
||||
}
|
||||
|
||||
export function checkIfTimeoutInPredefinedValues(
|
||||
timeout: string,
|
||||
timeoutOptions: string[]
|
||||
): boolean {
|
||||
if (timeoutOptions.indexOf(timeout) > -1) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export function getAlgorithmComponent(
|
||||
image: string,
|
||||
containerTag: string,
|
||||
entrypoint: string,
|
||||
algorithmLanguage: string
|
||||
): MetadataAlgorithm {
|
||||
return {
|
||||
language: algorithmLanguage,
|
||||
format: 'docker-image',
|
||||
version: '0.1',
|
||||
container: {
|
||||
entrypoint: entrypoint,
|
||||
image: image,
|
||||
tag: containerTag
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getAlgorithmFileExtension(fileUrl: string): string {
|
||||
const splitedFileUrl = fileUrl.split('.')
|
||||
return splitedFileUrl[splitedFileUrl.length - 1]
|
||||
}
|
63
src/@utils/docker.ts
Normal file
63
src/@utils/docker.ts
Normal file
@ -0,0 +1,63 @@
|
||||
import { Logger } from '@oceanprotocol/lib'
|
||||
import axios from 'axios'
|
||||
import isUrl from 'is-url-superb'
|
||||
import { toast } from 'react-toastify'
|
||||
|
||||
async function isDockerHubImageValid(
|
||||
image: string,
|
||||
tag: string
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
const response = await axios.post(
|
||||
`https://dockerhub-proxy.oceanprotocol.com`,
|
||||
{ image, tag }
|
||||
)
|
||||
if (
|
||||
!response ||
|
||||
response.status !== 200 ||
|
||||
response.data.status !== 'success'
|
||||
) {
|
||||
toast.error(
|
||||
'Could not fetch docker hub image info. Please check image name and tag and try again'
|
||||
)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
} catch (error) {
|
||||
Logger.error(error.message)
|
||||
toast.error(
|
||||
'Could not fetch docker hub image info. Please check image name and tag and try again'
|
||||
)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
async function is3rdPartyImageValid(imageURL: string): Promise<boolean> {
|
||||
try {
|
||||
const response = await axios.head(imageURL)
|
||||
if (!response || response.status !== 200) {
|
||||
toast.error(
|
||||
'Could not fetch docker image info. Please check URL and try again'
|
||||
)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} catch (error) {
|
||||
Logger.error(error.message)
|
||||
toast.error(
|
||||
'Could not fetch docker image info. Please check URL and try again'
|
||||
)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export async function validateDockerImage(
|
||||
dockerImage: string,
|
||||
tag: string
|
||||
): Promise<boolean> {
|
||||
const isValid = isUrl(dockerImage)
|
||||
? await is3rdPartyImageValid(dockerImage)
|
||||
: await isDockerHubImageValid(dockerImage, tag)
|
||||
return isValid
|
||||
}
|
@ -1,237 +0,0 @@
|
||||
import axios from 'axios'
|
||||
import { toast } from 'react-toastify'
|
||||
import isUrl from 'is-url-superb'
|
||||
import slugify from 'slugify'
|
||||
import { DDO, MetadataAlgorithm, Logger } from '@oceanprotocol/lib'
|
||||
import { FormPublishData } from '../components/Publish/_types'
|
||||
|
||||
export function dateToStringNoMS(date: Date): string {
|
||||
return date.toISOString().replace(/\.[0-9]{3}Z/, 'Z')
|
||||
}
|
||||
|
||||
export function transformTags(value: string): string[] {
|
||||
const originalTags = value?.split(',')
|
||||
const transformedTags = originalTags?.map((tag) => slugify(tag).toLowerCase())
|
||||
return transformedTags
|
||||
}
|
||||
|
||||
export function mapTimeoutStringToSeconds(timeout: string): number {
|
||||
switch (timeout) {
|
||||
case 'Forever':
|
||||
return 0
|
||||
case '1 day':
|
||||
return 86400
|
||||
case '1 week':
|
||||
return 604800
|
||||
case '1 month':
|
||||
return 2630000
|
||||
case '1 year':
|
||||
return 31556952
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
function numberEnding(number: number): string {
|
||||
return number > 1 ? 's' : ''
|
||||
}
|
||||
|
||||
export function secondsToString(numberOfSeconds: number): string {
|
||||
if (numberOfSeconds === 0) return 'Forever'
|
||||
|
||||
const years = Math.floor(numberOfSeconds / 31536000)
|
||||
const months = Math.floor((numberOfSeconds %= 31536000) / 2630000)
|
||||
const weeks = Math.floor((numberOfSeconds %= 31536000) / 604800)
|
||||
const days = Math.floor((numberOfSeconds %= 604800) / 86400)
|
||||
const hours = Math.floor((numberOfSeconds %= 86400) / 3600)
|
||||
const minutes = Math.floor((numberOfSeconds %= 3600) / 60)
|
||||
const seconds = numberOfSeconds % 60
|
||||
|
||||
return years
|
||||
? `${years} year${numberEnding(years)}`
|
||||
: months
|
||||
? `${months} month${numberEnding(months)}`
|
||||
: weeks
|
||||
? `${weeks} week${numberEnding(weeks)}`
|
||||
: days
|
||||
? `${days} day${numberEnding(days)}`
|
||||
: hours
|
||||
? `${hours} hour${numberEnding(hours)}`
|
||||
: minutes
|
||||
? `${minutes} minute${numberEnding(minutes)}`
|
||||
: seconds
|
||||
? `${seconds} second${numberEnding(seconds)}`
|
||||
: 'less than a second'
|
||||
}
|
||||
|
||||
export function checkIfTimeoutInPredefinedValues(
|
||||
timeout: string,
|
||||
timeoutOptions: string[]
|
||||
): boolean {
|
||||
if (timeoutOptions.indexOf(timeout) > -1) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function getAlgorithmComponent(
|
||||
image: string,
|
||||
containerTag: string,
|
||||
entrypoint: string,
|
||||
algorithmLanguace: string
|
||||
): MetadataAlgorithm {
|
||||
return {
|
||||
language: algorithmLanguace,
|
||||
format: 'docker-image',
|
||||
version: '0.1',
|
||||
container: {
|
||||
entrypoint: entrypoint,
|
||||
image: image,
|
||||
tag: containerTag
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getAlgorithmFileExtension(fileUrl: string): string {
|
||||
const splitedFileUrl = fileUrl.split('.')
|
||||
return splitedFileUrl[splitedFileUrl.length - 1]
|
||||
}
|
||||
|
||||
// export function transformPublishFormToMetadata(
|
||||
// {
|
||||
// name,
|
||||
// author,
|
||||
// description,
|
||||
// tags,
|
||||
// links,
|
||||
// termsAndConditions,
|
||||
// files
|
||||
// }: Partial<FormPublishData>,
|
||||
// ddo?: DDO
|
||||
// ): MetadataMarket {
|
||||
// const currentTime = dateToStringNoMS(new Date())
|
||||
|
||||
// const metadata: MetadataMarket = {
|
||||
// main: {
|
||||
// name,
|
||||
// author,
|
||||
// dateCreated: ddo ? ddo.created : currentTime,
|
||||
// datePublished: '',
|
||||
// files: typeof files !== 'string' && files,
|
||||
// license: 'https://market.oceanprotocol.com/terms'
|
||||
// },
|
||||
// additionalInformation: {
|
||||
// description,
|
||||
// tags: transformTags(tags),
|
||||
// links: typeof links !== 'string' ? links : [],
|
||||
// termsAndConditions
|
||||
// }
|
||||
// }
|
||||
|
||||
// return metadata
|
||||
// }
|
||||
|
||||
// async function isDockerHubImageValid(
|
||||
// image: string,
|
||||
// tag: string
|
||||
// ): Promise<boolean> {
|
||||
// try {
|
||||
// const response = await axios.post(
|
||||
// `https://dockerhub-proxy.oceanprotocol.com`,
|
||||
// {
|
||||
// image,
|
||||
// tag
|
||||
// }
|
||||
// )
|
||||
// if (
|
||||
// !response ||
|
||||
// response.status !== 200 ||
|
||||
// response.data.status !== 'success'
|
||||
// ) {
|
||||
// toast.error(
|
||||
// 'Could not fetch docker hub image info. Please check image name and tag and try again'
|
||||
// )
|
||||
// return false
|
||||
// }
|
||||
|
||||
// return true
|
||||
// } catch (error) {
|
||||
// Logger.error(error.message)
|
||||
// toast.error(
|
||||
// 'Could not fetch docker hub image info. Please check image name and tag and try again'
|
||||
// )
|
||||
// return false
|
||||
// }
|
||||
// }
|
||||
|
||||
async function is3rdPartyImageValid(imageURL: string): Promise<boolean> {
|
||||
try {
|
||||
const response = await axios.head(imageURL)
|
||||
if (!response || response.status !== 200) {
|
||||
toast.error(
|
||||
'Could not fetch docker image info. Please check URL and try again'
|
||||
)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} catch (error) {
|
||||
Logger.error(error.message)
|
||||
toast.error(
|
||||
'Could not fetch docker image info. Please check URL and try again'
|
||||
)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// export async function validateDockerImage(
|
||||
// dockerImage: string,
|
||||
// tag: string
|
||||
// ): Promise<boolean> {
|
||||
// const isValid = isUrl(dockerImage)
|
||||
// ? await is3rdPartyImageValid(dockerImage)
|
||||
// : await isDockerHubImageValid(dockerImage, tag)
|
||||
// return isValid
|
||||
// }
|
||||
|
||||
// export function transformPublishAlgorithmFormToMetadata(
|
||||
// {
|
||||
// name,
|
||||
// author,
|
||||
// description,
|
||||
// tags,
|
||||
// image,
|
||||
// containerTag,
|
||||
// entrypoint,
|
||||
// termsAndConditions,
|
||||
// files
|
||||
// }: Partial<FormPublishData>,
|
||||
// ddo?: DDO
|
||||
// ): MetadataMarket {
|
||||
// const currentTime = dateToStringNoMS(new Date())
|
||||
// const fileUrl = typeof files !== 'string' && files[0].url
|
||||
// const algorithmLanguage = getAlgorithmFileExtension(fileUrl)
|
||||
// const algorithm = getAlgorithmComponent(
|
||||
// image,
|
||||
// containerTag,
|
||||
// entrypoint,
|
||||
// algorithmLanguage
|
||||
// )
|
||||
// const metadata: MetadataMarket = {
|
||||
// main: {
|
||||
// name,
|
||||
// type: 'algorithm',
|
||||
// author,
|
||||
// dateCreated: ddo ? ddo.created : currentTime,
|
||||
// files: typeof files !== 'string' && files,
|
||||
// license: 'https://market.oceanprotocol.com/terms',
|
||||
// algorithm
|
||||
// },
|
||||
// additionalInformation: {
|
||||
// description,
|
||||
// tags: transformTags(tags),
|
||||
// termsAndConditions
|
||||
// }
|
||||
// }
|
||||
|
||||
// return metadata
|
||||
// }
|
@ -8,7 +8,7 @@ export default function AdvancedSettings(prop: {
|
||||
content: FormStepContent
|
||||
handleFieldChange: (
|
||||
e: ChangeEvent<HTMLInputElement>,
|
||||
field: FormFieldProps
|
||||
field: FormFieldContent
|
||||
) => void
|
||||
}): ReactElement {
|
||||
const [showAdvancedSettings, setShowAdvancedSettings] =
|
||||
@ -30,7 +30,7 @@ export default function AdvancedSettings(prop: {
|
||||
</Button>
|
||||
{showAdvancedSettings &&
|
||||
prop.content.fields.map(
|
||||
(field: FormFieldProps) =>
|
||||
(field: FormFieldContent) =>
|
||||
field.advanced === true && (
|
||||
<Field
|
||||
key={field.name}
|
||||
|
@ -47,7 +47,7 @@ export default function BoxSelection({
|
||||
type="radio"
|
||||
className={styleClassesInput}
|
||||
defaultChecked={value.checked}
|
||||
onChange={(event) => handleChange(event)}
|
||||
// onChange={(event) => handleChange(event)}
|
||||
{...props}
|
||||
disabled={disabled}
|
||||
value={value.name}
|
||||
|
@ -15,10 +15,10 @@ export default function Datatoken(props: InputProps): ReactElement {
|
||||
|
||||
// Generate new DT name & symbol on first mount
|
||||
useEffect(() => {
|
||||
if (field.value.name !== '') return
|
||||
if (field.value?.name !== '') return
|
||||
|
||||
generateName()
|
||||
}, [field.value.name])
|
||||
}, [field.value?.name])
|
||||
|
||||
return (
|
||||
<div className={styles.datatoken}>
|
||||
|
@ -6,7 +6,7 @@ import styles from './Terms.module.css'
|
||||
export default function Terms(props: InputProps): ReactElement {
|
||||
const termsProps: InputProps = {
|
||||
...props,
|
||||
defaultChecked: props.value.toString() === 'true'
|
||||
defaultChecked: props.value?.toString() === 'true'
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -1,11 +1,4 @@
|
||||
import React, {
|
||||
FormEvent,
|
||||
ChangeEvent,
|
||||
ReactElement,
|
||||
ReactNode,
|
||||
useEffect,
|
||||
useState
|
||||
} from 'react'
|
||||
import React, { ReactElement, ReactNode, useEffect, useState } from 'react'
|
||||
import InputElement from './InputElement'
|
||||
import Label from './Label'
|
||||
import styles from './index.module.css'
|
||||
@ -17,8 +10,7 @@ import Markdown from '@shared/Markdown'
|
||||
|
||||
const cx = classNames.bind(styles)
|
||||
|
||||
export interface InputProps {
|
||||
name: string
|
||||
export interface InputProps extends FieldInputProps<any> {
|
||||
label?: string | ReactNode
|
||||
placeholder?: string
|
||||
required?: boolean
|
||||
@ -28,23 +20,7 @@ export interface InputProps {
|
||||
options?: string[]
|
||||
sortOptions?: boolean
|
||||
additionalComponent?: ReactElement
|
||||
value?: string
|
||||
onChange?(
|
||||
e:
|
||||
| FormEvent<HTMLInputElement>
|
||||
| ChangeEvent<HTMLInputElement>
|
||||
| ChangeEvent<HTMLSelectElement>
|
||||
| ChangeEvent<HTMLTextAreaElement>
|
||||
): void
|
||||
onKeyPress?(
|
||||
e:
|
||||
| React.KeyboardEvent<HTMLInputElement>
|
||||
| React.KeyboardEvent<HTMLInputElement>
|
||||
| React.KeyboardEvent<HTMLSelectElement>
|
||||
| React.KeyboardEvent<HTMLTextAreaElement>
|
||||
): void
|
||||
rows?: number
|
||||
multiple?: boolean
|
||||
pattern?: string
|
||||
min?: string
|
||||
max?: string
|
||||
@ -58,7 +34,6 @@ export interface InputProps {
|
||||
defaultChecked?: boolean
|
||||
size?: 'mini' | 'small' | 'large' | 'default'
|
||||
className?: string
|
||||
checked?: boolean
|
||||
disclaimer?: string
|
||||
disclaimerValues?: string[]
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ export default function FormStartCompute({
|
||||
|
||||
return (
|
||||
<Form className={styles.form}>
|
||||
{content.form.data.map((field: FormFieldProps) => (
|
||||
{content.form.data.map((field: FormFieldContent) => (
|
||||
<Field
|
||||
key={field.name}
|
||||
{...field}
|
||||
|
@ -30,9 +30,9 @@ import axios from 'axios'
|
||||
import FormStartComputeDataset from './FormComputeDataset'
|
||||
import styles from './index.module.css'
|
||||
import SuccessConfetti from '@shared/SuccessConfetti'
|
||||
import { secondsToString } from '@utils/metadata'
|
||||
import { secondsToString } from '@utils/ddo'
|
||||
import { AssetSelectionAsset } from '@shared/Form/FormFields/AssetSelection'
|
||||
import AlgorithmDatasetsListForCompute from '../../AssetContent/AlgorithmDatasetsListForCompute'
|
||||
import AlgorithmDatasetsListForCompute from './AlgorithmDatasetsListForCompute'
|
||||
import { getPreviousOrders, getPrice } from '@utils/subgraph'
|
||||
import AssetActionHistoryTable from '../AssetActionHistoryTable'
|
||||
import ComputeJobs from '../../../Profile/History/ComputeJobs'
|
||||
|
@ -14,8 +14,8 @@ import { useWeb3 } from '@context/Web3'
|
||||
import { usePricing } from '@hooks/usePricing'
|
||||
import { useConsume } from '@hooks/useConsume'
|
||||
import ButtonBuy from '@shared/ButtonBuy'
|
||||
import { secondsToString } from '@utils/metadata'
|
||||
import AlgorithmDatasetsListForCompute from '../AssetContent/AlgorithmDatasetsListForCompute'
|
||||
import { secondsToString } from '@utils/ddo'
|
||||
import AlgorithmDatasetsListForCompute from './Compute/AlgorithmDatasetsListForCompute'
|
||||
import styles from './Consume.module.css'
|
||||
import { useIsMounted } from '@hooks/useIsMounted'
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { ReactElement, useEffect, useState } from 'react'
|
||||
import { Field, Form, FormikContextType, useFormikContext } from 'formik'
|
||||
import Input from '@shared/Form/Input'
|
||||
import Input, { InputProps } from '@shared/Form/Input'
|
||||
import { AssetSelectionAsset } from '@shared/Form/FormFields/AssetSelection'
|
||||
import stylesIndex from './index.module.css'
|
||||
import styles from './FormEditMetadata.module.css'
|
||||
@ -22,7 +22,7 @@ export default function FormEditComputeDataset({
|
||||
title,
|
||||
setShowEdit
|
||||
}: {
|
||||
data: FormFieldProps[]
|
||||
data: InputProps[]
|
||||
title: string
|
||||
setShowEdit: (show: boolean) => void
|
||||
}): ReactElement {
|
||||
@ -64,7 +64,7 @@ export default function FormEditComputeDataset({
|
||||
return (
|
||||
<Form className={styles.form}>
|
||||
<h3 className={stylesIndex.title}>{title}</h3>
|
||||
{data.map((field: FormFieldProps) => (
|
||||
{data.map((field: InputProps) => (
|
||||
<Field
|
||||
key={field.name}
|
||||
{...field}
|
||||
|
@ -1,14 +1,14 @@
|
||||
import React, { ChangeEvent, ReactElement } from 'react'
|
||||
import { Field, Form, FormikContextType, useFormikContext } from 'formik'
|
||||
import { useOcean } from '@context/Ocean'
|
||||
import Input from '@shared/Form/Input'
|
||||
import { checkIfTimeoutInPredefinedValues } from '@utils/metadata'
|
||||
import Input, { InputProps } from '@shared/Form/Input'
|
||||
import { checkIfTimeoutInPredefinedValues } from '@utils/ddo'
|
||||
import FormActions from './FormActions'
|
||||
import styles from './FormEditMetadata.module.css'
|
||||
import { FormPublishData } from '../../../Publish/_types'
|
||||
|
||||
// function handleTimeoutCustomOption(
|
||||
// data: FormFieldProps[],
|
||||
// data: FormFieldContent[],
|
||||
// values: Partial<FormPublishData>
|
||||
// ) {
|
||||
// const timeoutFieldContent = data.filter(
|
||||
@ -48,7 +48,7 @@ export default function FormEditMetadata({
|
||||
showPrice,
|
||||
isComputeDataset
|
||||
}: {
|
||||
data: FormFieldProps[]
|
||||
data: InputProps[]
|
||||
setShowEdit: (show: boolean) => void
|
||||
setTimeoutStringValue: (value: string) => void
|
||||
values: Partial<FormPublishData>
|
||||
@ -65,7 +65,7 @@ export default function FormEditMetadata({
|
||||
// Workaround for default `validateOnChange` not kicking in
|
||||
function handleFieldChange(
|
||||
e: ChangeEvent<HTMLInputElement>,
|
||||
field: FormFieldProps
|
||||
field: InputProps
|
||||
) {
|
||||
validateField(field.name)
|
||||
setFieldValue(field.name, e.target.value)
|
||||
@ -89,7 +89,7 @@ export default function FormEditMetadata({
|
||||
return (
|
||||
<Form className={styles.form}>
|
||||
{data.map(
|
||||
(field: FormFieldProps) =>
|
||||
(field: InputProps) =>
|
||||
(!showPrice && field.name === 'price') || (
|
||||
<Field
|
||||
key={field.name}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { secondsToString } from '@utils/metadata'
|
||||
import { secondsToString } from '@utils/ddo'
|
||||
import { EditableMetadataLinks } from '@oceanprotocol/lib'
|
||||
import * as Yup from 'yup'
|
||||
|
||||
|
@ -6,7 +6,7 @@ import { useUserPreferences } from '@context/UserPreferences'
|
||||
// import Debug from './DebugEditMetadata'
|
||||
import Web3Feedback from '@shared/Web3Feedback'
|
||||
import FormEditMetadata from './FormEditMetadata'
|
||||
import { mapTimeoutStringToSeconds } from '@utils/metadata'
|
||||
import { mapTimeoutStringToSeconds } from '@utils/ddo'
|
||||
import styles from './index.module.css'
|
||||
import { Logger } from '@oceanprotocol/lib'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
|
@ -8,7 +8,7 @@ import React, {
|
||||
// import { useStaticQuery, graphql } from 'gatsby'
|
||||
// import { useFormikContext, Field, Form, FormikContextType } from 'formik'
|
||||
// import Input from '../../atoms/Input'
|
||||
// import { FormContent, FormFieldProps } from '../../../@types/Form'
|
||||
// import { FormContent, FormFieldContent } from '../../../@types/Form'
|
||||
// import { MetadataPublishFormAlgorithm } from '../../../@types/MetaData'
|
||||
// import { initialValues as initialValuesAlgorithm } from '../../../@types/FormAlgoPublish'
|
||||
// import AdvancedSettings from '../../molecules/FormFields/AdvancedSettings'
|
||||
@ -116,7 +116,7 @@ import React, {
|
||||
// // Workaround for default `validateOnChange` not kicking in
|
||||
// function handleFieldChange(
|
||||
// e: ChangeEvent<HTMLInputElement>,
|
||||
// field: FormFieldProps
|
||||
// field: InputProps
|
||||
// ) {
|
||||
// const value =
|
||||
// field.type === 'checkbox' || field.type === 'terms'
|
||||
@ -148,7 +148,7 @@ import React, {
|
||||
// <FormTitle title={content.title} />
|
||||
|
||||
// {content.data.map(
|
||||
// (field: FormFieldProps) =>
|
||||
// (field: InputProps) =>
|
||||
// field.advanced !== true &&
|
||||
// ((field.name !== 'entrypoint' &&
|
||||
// field.name !== 'image' &&
|
||||
|
@ -2,18 +2,45 @@ import Input from '@shared/Form/Input'
|
||||
import { Field } from 'formik'
|
||||
import React, { ReactElement } from 'react'
|
||||
import content from '../../../../../content/publish/form.json'
|
||||
import { getFieldContent } from '../../_utils'
|
||||
|
||||
export default function MetadataFields(): ReactElement {
|
||||
return (
|
||||
<>
|
||||
{content.metadata.fields.map((field: FormFieldProps) => (
|
||||
<Field
|
||||
{...getFieldContent('name', content.metadata.fields)}
|
||||
component={Input}
|
||||
name="metadata.name"
|
||||
/>
|
||||
<Field
|
||||
{...getFieldContent('description', content.metadata.fields)}
|
||||
component={Input}
|
||||
name="metadata.description"
|
||||
/>
|
||||
<Field
|
||||
{...getFieldContent('author', content.metadata.fields)}
|
||||
component={Input}
|
||||
name="metadata.author"
|
||||
/>
|
||||
<Field
|
||||
{...getFieldContent('tags', content.metadata.fields)}
|
||||
component={Input}
|
||||
name="metadata.tags"
|
||||
/>
|
||||
<Field
|
||||
{...getFieldContent('termsAndConditions', content.metadata.fields)}
|
||||
component={Input}
|
||||
name="metadata.termsAndConditions"
|
||||
/>
|
||||
|
||||
{/* {content.metadata.fields.map((field: FormFieldContent) => (
|
||||
<Field
|
||||
{...field}
|
||||
key={`metadata-${field.name}`}
|
||||
component={Input}
|
||||
name={`metadata.${field.name}`}
|
||||
/>
|
||||
))}
|
||||
))} */}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import Tags from '@shared/atoms/Tags'
|
||||
import MetaItem from '../../../Asset/AssetContent/MetaItem'
|
||||
import FileIcon from '@shared/FileIcon'
|
||||
import Button from '@shared/atoms/Button'
|
||||
import { transformTags } from '@utils/metadata'
|
||||
import { transformTags } from '@utils/ddo'
|
||||
import NetworkName from '@shared/NetworkName'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import styles from './MetadataPreview.module.css'
|
||||
|
@ -4,6 +4,7 @@ import React, { ReactElement } from 'react'
|
||||
import IconDownload from '@images/download.svg'
|
||||
import IconCompute from '@images/compute.svg'
|
||||
import content from '../../../../../content/publish/form.json'
|
||||
import { getFieldContent } from '../../_utils'
|
||||
|
||||
const accessTypeOptions = [
|
||||
{
|
||||
@ -21,8 +22,45 @@ const accessTypeOptions = [
|
||||
export default function ServicesFields(): ReactElement {
|
||||
return (
|
||||
<>
|
||||
{content.services.fields.map(
|
||||
(field: FormFieldProps) =>
|
||||
<Field
|
||||
{...getFieldContent('dataTokenOptions', content.services.fields)}
|
||||
component={Input}
|
||||
name="services[0].dataTokenOptions"
|
||||
/>
|
||||
<Field
|
||||
{...getFieldContent('files', content.services.fields)}
|
||||
component={Input}
|
||||
name="services[0].files"
|
||||
/>
|
||||
<Field
|
||||
{...getFieldContent('links', content.services.fields)}
|
||||
component={Input}
|
||||
name="services[0].links"
|
||||
/>
|
||||
<Field
|
||||
{...getFieldContent('links', content.services.fields)}
|
||||
component={Input}
|
||||
name="services[0].links"
|
||||
/>
|
||||
<Field
|
||||
{...getFieldContent('access', content.services.fields)}
|
||||
component={Input}
|
||||
name="services[0].access"
|
||||
options={accessTypeOptions}
|
||||
/>
|
||||
<Field
|
||||
{...getFieldContent('timeout', content.services.fields)}
|
||||
component={Input}
|
||||
name="services[0].timeout"
|
||||
/>
|
||||
<Field
|
||||
{...getFieldContent('providerUri', content.services.fields)}
|
||||
component={Input}
|
||||
name="services[0].providerUri"
|
||||
/>
|
||||
|
||||
{/* {content.services.fields.map(
|
||||
(field: FormFieldContent) =>
|
||||
field.advanced !== true && (
|
||||
<Field
|
||||
{...field}
|
||||
@ -34,7 +72,7 @@ export default function ServicesFields(): ReactElement {
|
||||
}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
)} */}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { DataTokenOptions } from '@hooks/usePublish'
|
||||
import { EditableMetadataLinks } from '@oceanprotocol/lib'
|
||||
import { EditableMetadataLinks, File } from '@oceanprotocol/lib'
|
||||
|
||||
export interface FormPublishService {
|
||||
files: string | File[]
|
||||
@ -7,6 +7,9 @@ export interface FormPublishService {
|
||||
timeout: string
|
||||
dataTokenOptions: DataTokenOptions
|
||||
access: 'Download' | 'Compute' | string
|
||||
image?: string
|
||||
containerTag?: string
|
||||
entrypoint?: string
|
||||
providerUri?: string
|
||||
}
|
||||
|
||||
|
56
src/components/Publish/_utils.ts
Normal file
56
src/components/Publish/_utils.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import {
|
||||
dateToStringNoMS,
|
||||
transformTags,
|
||||
getAlgorithmComponent,
|
||||
getAlgorithmFileExtension
|
||||
} from '@utils/ddo'
|
||||
import { FormPublishData } from './_types'
|
||||
|
||||
export function getFieldContent(
|
||||
fieldName: string,
|
||||
fields: FormFieldContent[]
|
||||
): FormFieldContent {
|
||||
return fields.filter((field: FormFieldContent) => field.name === fieldName)[0]
|
||||
}
|
||||
|
||||
export function transformPublishFormToDdo(
|
||||
data: Partial<FormPublishData>,
|
||||
ddo?: DdoMarket
|
||||
): DdoMarket {
|
||||
const currentTime = dateToStringNoMS(new Date())
|
||||
const { type } = data
|
||||
const { name, description, tags, author, termsAndConditions } = data.metadata
|
||||
const { files, links, image, containerTag, entrypoint, providerUri } =
|
||||
data.services[0]
|
||||
|
||||
const fileUrl = typeof files !== 'string' && files[0].url
|
||||
const algorithmLanguage = getAlgorithmFileExtension(fileUrl)
|
||||
const algorithm = getAlgorithmComponent(
|
||||
image,
|
||||
containerTag,
|
||||
entrypoint,
|
||||
algorithmLanguage
|
||||
)
|
||||
|
||||
const service = {
|
||||
files: typeof files !== 'string' && files,
|
||||
links: typeof links !== 'string' ? links : [],
|
||||
...(type === 'algorithm' && { ...algorithm })
|
||||
}
|
||||
|
||||
const newDdo: DdoMarket = {
|
||||
metadata: {
|
||||
name,
|
||||
description,
|
||||
tags: transformTags(tags),
|
||||
author,
|
||||
dateCreated: ddo ? ddo.metadata.dateCreated : currentTime,
|
||||
datePublished: '',
|
||||
termsAndConditions,
|
||||
license: 'https://market.oceanprotocol.com/terms'
|
||||
},
|
||||
services: [service]
|
||||
}
|
||||
|
||||
return newDdo
|
||||
}
|
@ -2,15 +2,12 @@ import React, { ReactElement, useState, useEffect } from 'react'
|
||||
import { Formik, FormikState } from 'formik'
|
||||
import { usePublish } from '@hooks/usePublish'
|
||||
import { initialValues, validationSchema } from './_constants'
|
||||
// import {
|
||||
// transformPublishFormToMetadata,
|
||||
// mapTimeoutStringToSeconds,
|
||||
// validateDockerImage
|
||||
// } from '@utils/metadata'
|
||||
import { validateDockerImage } from '@utils/docker'
|
||||
import { Logger, Metadata } from '@oceanprotocol/lib'
|
||||
import { useAccountPurgatory } from '@hooks/useAccountPurgatory'
|
||||
import { useWeb3 } from '@context/Web3'
|
||||
import { FormPublishData } from './_types'
|
||||
import { transformPublishFormToDdo } from './_utils'
|
||||
import PageHeader from '@shared/Page/PageHeader'
|
||||
import Title from './Title'
|
||||
import styles from './index.module.css'
|
||||
|
Loading…
Reference in New Issue
Block a user