mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
pricing validation tweaks
This commit is contained in:
parent
b6bc38c530
commit
5fd97b11e4
@ -2,7 +2,6 @@
|
|||||||
font-size: var(--font-size-base);
|
font-size: var(--font-size-base);
|
||||||
margin-top: var(--spacer);
|
margin-top: var(--spacer);
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
color: var(--color-secondary);
|
|
||||||
padding-bottom: calc(var(--spacer) / 4);
|
padding-bottom: calc(var(--spacer) / 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
import React, { ReactElement } from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
import FormHelp from '@shared/FormInput/Help'
|
import FormHelp from '@shared/FormInput/Help'
|
||||||
import Price from './Price'
|
import Price from './Price'
|
||||||
|
import styles from './Dynamic.module.css'
|
||||||
|
|
||||||
export default function Free({ content }: { content: any }): ReactElement {
|
export default function Free({ content }: { content: any }): ReactElement {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<FormHelp>{content.info}</FormHelp>
|
<FormHelp>{content.info}</FormHelp>
|
||||||
<Price free />
|
<h4 className={styles.title}>Price</h4>
|
||||||
|
<Price />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -8,11 +8,9 @@ import styles from './Price.module.css'
|
|||||||
import { FormPublishData } from '../_types'
|
import { FormPublishData } from '../_types'
|
||||||
|
|
||||||
export default function Price({
|
export default function Price({
|
||||||
firstPrice,
|
firstPrice
|
||||||
free
|
|
||||||
}: {
|
}: {
|
||||||
firstPrice?: string
|
firstPrice?: string
|
||||||
free?: boolean
|
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const [field, meta] = useField('pricing.price')
|
const [field, meta] = useField('pricing.price')
|
||||||
|
|
||||||
@ -23,10 +21,10 @@ export default function Price({
|
|||||||
<div className={styles.price}>
|
<div className={styles.price}>
|
||||||
<div className={styles.grid}>
|
<div className={styles.grid}>
|
||||||
<div className={styles.form}>
|
<div className={styles.form}>
|
||||||
{free ? (
|
{field.value === 0 ? (
|
||||||
<Input
|
<Input
|
||||||
value="0"
|
value="0"
|
||||||
name="price"
|
name="pricing.price"
|
||||||
type="number"
|
type="number"
|
||||||
prefix="OCEAN"
|
prefix="OCEAN"
|
||||||
readOnly
|
readOnly
|
||||||
@ -34,10 +32,9 @@ export default function Price({
|
|||||||
) : (
|
) : (
|
||||||
<Input
|
<Input
|
||||||
value={field.value}
|
value={field.value}
|
||||||
name="price"
|
name="pricing.price"
|
||||||
type="number"
|
type="number"
|
||||||
prefix="OCEAN"
|
prefix="OCEAN"
|
||||||
min="1"
|
|
||||||
{...field}
|
{...field}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -24,12 +24,12 @@ export default function PricingFields(): ReactElement {
|
|||||||
const type = tabName.toLowerCase()
|
const type = tabName.toLowerCase()
|
||||||
setFieldValue('pricing.type', type)
|
setFieldValue('pricing.type', type)
|
||||||
type === 'dynamic' && setFieldValue('pricing.amountDataToken', 1000)
|
type === 'dynamic' && setFieldValue('pricing.amountDataToken', 1000)
|
||||||
type === 'free' && price < 1 && setFieldValue('pricing.price', 1)
|
setFieldValue('pricing.price', type === 'free' ? 0 : 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always update everything when price value changes
|
// Always update everything when price value changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (type === 'dynamic' || type === 'free') return
|
if (type === 'fixed' || type === 'free') return
|
||||||
|
|
||||||
const amountDataToken =
|
const amountDataToken =
|
||||||
isValidNumber(amountOcean) &&
|
isValidNumber(amountOcean) &&
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import * as Yup from 'yup'
|
|
||||||
import { allowDynamicPricing, allowFixedPricing } from '../../../app.config.js'
|
import { allowDynamicPricing, allowFixedPricing } from '../../../app.config.js'
|
||||||
import { FormPublishData, StepContent } from './_types'
|
import { FormPublishData, StepContent } from './_types'
|
||||||
import content from '../../../content/publish/form.json'
|
import content from '../../../content/publish/form.json'
|
||||||
@ -76,120 +75,6 @@ export const initialValues: FormPublishData = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: conditional validation
|
|
||||||
// e.g. when algo is selected, Docker image is required
|
|
||||||
const validationMetadata = {
|
|
||||||
type: Yup.string()
|
|
||||||
.matches(/dataset|algorithm/g, { excludeEmptyString: true })
|
|
||||||
.required('Required'),
|
|
||||||
name: Yup.string()
|
|
||||||
.min(4, (param) => `Title must be at least ${param.min} characters`)
|
|
||||||
.required('Required'),
|
|
||||||
description: Yup.string()
|
|
||||||
.min(10, (param) => `Description must be at least ${param.min} characters`)
|
|
||||||
.required('Required'),
|
|
||||||
author: Yup.string().required('Required'),
|
|
||||||
tags: Yup.string().nullable(),
|
|
||||||
termsAndConditions: Yup.boolean().required('Required').isTrue()
|
|
||||||
}
|
|
||||||
|
|
||||||
const validationService = {
|
|
||||||
files: Yup.array<{ url: string; valid: boolean }[]>()
|
|
||||||
.of(
|
|
||||||
Yup.object().shape({
|
|
||||||
url: Yup.string().required('Required'),
|
|
||||||
valid: Yup.boolean().isTrue().required('File must be valid.')
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.min(1, (param) => `At least one file is required.`)
|
|
||||||
.required('Enter a valid URL and click ADD FILE.'),
|
|
||||||
links: Yup.array<{ url: string; valid: boolean }[]>()
|
|
||||||
.of(
|
|
||||||
Yup.object().shape({
|
|
||||||
url: Yup.string().required('Required'),
|
|
||||||
valid: Yup.boolean().isTrue().required('File must be valid.')
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.nullable(),
|
|
||||||
dataTokenOptions: Yup.object().shape({
|
|
||||||
name: Yup.string(),
|
|
||||||
symbol: Yup.string()
|
|
||||||
}),
|
|
||||||
timeout: Yup.string().required('Required'),
|
|
||||||
access: Yup.string()
|
|
||||||
.matches(/compute|download/g)
|
|
||||||
.required('Required'),
|
|
||||||
providerUrl: Yup.string().url().required('Required')
|
|
||||||
}
|
|
||||||
|
|
||||||
const validationPricing = {
|
|
||||||
price: Yup.number()
|
|
||||||
.min(1, (param) => `Must be more or equal to ${param.min}`)
|
|
||||||
.required('Required'),
|
|
||||||
amountDataToken: Yup.number()
|
|
||||||
.min(50, (param) => `Must be more or equal to ${param.min}`)
|
|
||||||
.required('Required'),
|
|
||||||
amountOcean: Yup.number()
|
|
||||||
.min(50, (param) => `Must be more or equal to ${param.min}`)
|
|
||||||
.required('Required'),
|
|
||||||
type: Yup.string()
|
|
||||||
.matches(/fixed|dynamic|free/g, { excludeEmptyString: true })
|
|
||||||
.required('Required'),
|
|
||||||
weightOnDataToken: Yup.string().required('Required'),
|
|
||||||
weightOnOcean: Yup.string().required('Required'),
|
|
||||||
swapFee: Yup.number()
|
|
||||||
.min(0.1, (param) => `Must be more or equal to ${param.min}`)
|
|
||||||
.max(10, 'Maximum is 10%')
|
|
||||||
.required('Required')
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: make Yup.SchemaOf<FormPublishData> work, requires conditional validation
|
|
||||||
// of all the custom docker image stuff.
|
|
||||||
// export const validationSchema: Yup.SchemaOf<FormPublishData> =
|
|
||||||
export const validationSchema: Yup.SchemaOf<any> = Yup.object().shape({
|
|
||||||
user: Yup.object().shape({
|
|
||||||
stepCurrent: Yup.number(),
|
|
||||||
chainId: Yup.number().required('Required'),
|
|
||||||
accountId: Yup.string().required('Required')
|
|
||||||
}),
|
|
||||||
metadata: Yup.object().shape(validationMetadata),
|
|
||||||
services: Yup.array().of(Yup.object().shape(validationService)),
|
|
||||||
pricing: Yup.object().shape(validationPricing)
|
|
||||||
})
|
|
||||||
|
|
||||||
// export const validationSchemaAlgo: Yup.SchemaOf<MetadataPublishFormAlgorithm> =
|
|
||||||
// Yup.object()
|
|
||||||
// .shape({
|
|
||||||
// // ---- required fields ----
|
|
||||||
// name: Yup.string()
|
|
||||||
// .min(4, (param) => `Title must be at least ${param.min} characters`)
|
|
||||||
// .required('Required'),
|
|
||||||
// description: Yup.string().min(10).required('Required'),
|
|
||||||
// files: Yup.array<FileMetadata>().required('Required').nullable(),
|
|
||||||
// timeout: Yup.string().required('Required'),
|
|
||||||
// dataTokenOptions: Yup.object()
|
|
||||||
// .shape({
|
|
||||||
// name: Yup.string(),
|
|
||||||
// symbol: Yup.string()
|
|
||||||
// })
|
|
||||||
// .required('Required'),
|
|
||||||
// dockerImage: Yup.string()
|
|
||||||
// .matches(/node:latest|python:latest|custom image/g, {
|
|
||||||
// excludeEmptyString: true
|
|
||||||
// })
|
|
||||||
// .required('Required'),
|
|
||||||
// image: Yup.string().required('Required'),
|
|
||||||
// containerTag: Yup.string().required('Required'),
|
|
||||||
// entrypoint: Yup.string().required('Required'),
|
|
||||||
// author: Yup.string().required('Required'),
|
|
||||||
// termsAndConditions: Yup.boolean().required('Required'),
|
|
||||||
// // ---- optional fields ----
|
|
||||||
// algorithmPrivacy: Yup.boolean().nullable(),
|
|
||||||
// tags: Yup.string().nullable(),
|
|
||||||
// links: Yup.array<FileMetadata[]>().nullable()
|
|
||||||
// })
|
|
||||||
// .defined()
|
|
||||||
|
|
||||||
// export const initialValuesAlgo: Partial<MetadataPublishFormAlgorithm> = {
|
// export const initialValuesAlgo: Partial<MetadataPublishFormAlgorithm> = {
|
||||||
// name: '',
|
// name: '',
|
||||||
// author: '',
|
// author: '',
|
||||||
|
124
src/components/Publish/_validation.ts
Normal file
124
src/components/Publish/_validation.ts
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
import * as Yup from 'yup'
|
||||||
|
|
||||||
|
// TODO: conditional validation
|
||||||
|
// e.g. when algo is selected, Docker image is required
|
||||||
|
// hint, hint: https://github.com/jquense/yup#mixedwhenkeys-string--arraystring-builder-object--value-schema-schema-schema
|
||||||
|
const validationMetadata = {
|
||||||
|
type: Yup.string()
|
||||||
|
.matches(/dataset|algorithm/g, { excludeEmptyString: true })
|
||||||
|
.required('Required'),
|
||||||
|
name: Yup.string()
|
||||||
|
.min(4, (param) => `Title must be at least ${param.min} characters`)
|
||||||
|
.required('Required'),
|
||||||
|
description: Yup.string()
|
||||||
|
.min(10, (param) => `Description must be at least ${param.min} characters`)
|
||||||
|
.required('Required'),
|
||||||
|
author: Yup.string().required('Required'),
|
||||||
|
tags: Yup.string().nullable(),
|
||||||
|
termsAndConditions: Yup.boolean().required('Required').isTrue()
|
||||||
|
}
|
||||||
|
|
||||||
|
const validationService = {
|
||||||
|
files: Yup.array<{ url: string; valid: boolean }[]>()
|
||||||
|
.of(
|
||||||
|
Yup.object().shape({
|
||||||
|
url: Yup.string().required('Required'),
|
||||||
|
valid: Yup.boolean().isTrue().required('File must be valid.')
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.min(1, (param) => `At least one file is required.`)
|
||||||
|
.required('Enter a valid URL and click ADD FILE.'),
|
||||||
|
links: Yup.array<{ url: string; valid: boolean }[]>()
|
||||||
|
.of(
|
||||||
|
Yup.object().shape({
|
||||||
|
url: Yup.string().required('Required'),
|
||||||
|
valid: Yup.boolean().isTrue().required('File must be valid.')
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.nullable(),
|
||||||
|
dataTokenOptions: Yup.object().shape({
|
||||||
|
name: Yup.string(),
|
||||||
|
symbol: Yup.string()
|
||||||
|
}),
|
||||||
|
timeout: Yup.string().required('Required'),
|
||||||
|
access: Yup.string()
|
||||||
|
.matches(/compute|download/g)
|
||||||
|
.required('Required'),
|
||||||
|
providerUrl: Yup.string().url().required('Required')
|
||||||
|
}
|
||||||
|
|
||||||
|
const validationPricing = {
|
||||||
|
type: Yup.string()
|
||||||
|
.matches(/fixed|dynamic|free/g, { excludeEmptyString: true })
|
||||||
|
.required('Required'),
|
||||||
|
// https://github.com/jquense/yup#mixedwhenkeys-string--arraystring-builder-object--value-schema-schema-schema
|
||||||
|
price: Yup.number()
|
||||||
|
.when('type', (type, schema) =>
|
||||||
|
type === 'free'
|
||||||
|
? schema
|
||||||
|
: schema.min(
|
||||||
|
1,
|
||||||
|
(param: { min: number }) => `Must be more or equal to ${param.min}`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.required('Required'),
|
||||||
|
amountDataToken: Yup.number()
|
||||||
|
.min(50, (param) => `Must be more or equal to ${param.min}`)
|
||||||
|
.required('Required'),
|
||||||
|
amountOcean: Yup.number()
|
||||||
|
.min(50, (param) => `Must be more or equal to ${param.min}`)
|
||||||
|
.required('Required'),
|
||||||
|
weightOnDataToken: Yup.string().required('Required'),
|
||||||
|
weightOnOcean: Yup.string().required('Required'),
|
||||||
|
swapFee: Yup.number()
|
||||||
|
.min(0.1, (param) => `Must be more or equal to ${param.min}`)
|
||||||
|
.max(10, 'Maximum is 10%')
|
||||||
|
.required('Required')
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: make Yup.SchemaOf<FormPublishData> work, requires conditional validation
|
||||||
|
// of all the custom docker image stuff.
|
||||||
|
// export const validationSchema: Yup.SchemaOf<FormPublishData> =
|
||||||
|
export const validationSchema: Yup.SchemaOf<any> = Yup.object().shape({
|
||||||
|
user: Yup.object().shape({
|
||||||
|
stepCurrent: Yup.number(),
|
||||||
|
chainId: Yup.number().required('Required'),
|
||||||
|
accountId: Yup.string().required('Required')
|
||||||
|
}),
|
||||||
|
metadata: Yup.object().shape(validationMetadata),
|
||||||
|
services: Yup.array().of(Yup.object().shape(validationService)),
|
||||||
|
pricing: Yup.object().shape(validationPricing)
|
||||||
|
})
|
||||||
|
|
||||||
|
// export const validationSchemaAlgo: Yup.SchemaOf<MetadataPublishFormAlgorithm> =
|
||||||
|
// Yup.object()
|
||||||
|
// .shape({
|
||||||
|
// // ---- required fields ----
|
||||||
|
// name: Yup.string()
|
||||||
|
// .min(4, (param) => `Title must be at least ${param.min} characters`)
|
||||||
|
// .required('Required'),
|
||||||
|
// description: Yup.string().min(10).required('Required'),
|
||||||
|
// files: Yup.array<FileMetadata>().required('Required').nullable(),
|
||||||
|
// timeout: Yup.string().required('Required'),
|
||||||
|
// dataTokenOptions: Yup.object()
|
||||||
|
// .shape({
|
||||||
|
// name: Yup.string(),
|
||||||
|
// symbol: Yup.string()
|
||||||
|
// })
|
||||||
|
// .required('Required'),
|
||||||
|
// dockerImage: Yup.string()
|
||||||
|
// .matches(/node:latest|python:latest|custom image/g, {
|
||||||
|
// excludeEmptyString: true
|
||||||
|
// })
|
||||||
|
// .required('Required'),
|
||||||
|
// image: Yup.string().required('Required'),
|
||||||
|
// containerTag: Yup.string().required('Required'),
|
||||||
|
// entrypoint: Yup.string().required('Required'),
|
||||||
|
// author: Yup.string().required('Required'),
|
||||||
|
// termsAndConditions: Yup.boolean().required('Required'),
|
||||||
|
// // ---- optional fields ----
|
||||||
|
// algorithmPrivacy: Yup.boolean().nullable(),
|
||||||
|
// tags: Yup.string().nullable(),
|
||||||
|
// links: Yup.array<FileMetadata[]>().nullable()
|
||||||
|
// })
|
||||||
|
// .defined()
|
@ -1,6 +1,7 @@
|
|||||||
import React, { ReactElement, useState, useRef } from 'react'
|
import React, { ReactElement, useState, useRef } from 'react'
|
||||||
import { Form, Formik, FormikState } from 'formik'
|
import { Form, Formik, FormikState } from 'formik'
|
||||||
import { initialValues, validationSchema } from './_constants'
|
import { initialValues } from './_constants'
|
||||||
|
import { validationSchema } from './_validation'
|
||||||
import { validateDockerImage } from '@utils/docker'
|
import { validateDockerImage } from '@utils/docker'
|
||||||
import { Logger } from '@oceanprotocol/lib'
|
import { Logger } from '@oceanprotocol/lib'
|
||||||
import { useAccountPurgatory } from '@hooks/useAccountPurgatory'
|
import { useAccountPurgatory } from '@hooks/useAccountPurgatory'
|
||||||
|
Loading…
Reference in New Issue
Block a user