1
0
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:
Matthias Kretschmann 2021-11-23 17:00:24 +00:00
parent b6bc38c530
commit 5fd97b11e4
Signed by: m
GPG Key ID: 606EEEF3C479A91F
7 changed files with 135 additions and 127 deletions

View File

@ -2,7 +2,6 @@
font-size: var(--font-size-base);
margin-top: var(--spacer);
margin-bottom: 0;
color: var(--color-secondary);
padding-bottom: calc(var(--spacer) / 4);
}

View File

@ -1,12 +1,14 @@
import React, { ReactElement } from 'react'
import FormHelp from '@shared/FormInput/Help'
import Price from './Price'
import styles from './Dynamic.module.css'
export default function Free({ content }: { content: any }): ReactElement {
return (
<>
<FormHelp>{content.info}</FormHelp>
<Price free />
<h4 className={styles.title}>Price</h4>
<Price />
</>
)
}

View File

@ -8,11 +8,9 @@ import styles from './Price.module.css'
import { FormPublishData } from '../_types'
export default function Price({
firstPrice,
free
firstPrice
}: {
firstPrice?: string
free?: boolean
}): ReactElement {
const [field, meta] = useField('pricing.price')
@ -23,10 +21,10 @@ export default function Price({
<div className={styles.price}>
<div className={styles.grid}>
<div className={styles.form}>
{free ? (
{field.value === 0 ? (
<Input
value="0"
name="price"
name="pricing.price"
type="number"
prefix="OCEAN"
readOnly
@ -34,10 +32,9 @@ export default function Price({
) : (
<Input
value={field.value}
name="price"
name="pricing.price"
type="number"
prefix="OCEAN"
min="1"
{...field}
/>
)}

View File

@ -24,12 +24,12 @@ export default function PricingFields(): ReactElement {
const type = tabName.toLowerCase()
setFieldValue('pricing.type', type)
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
useEffect(() => {
if (type === 'dynamic' || type === 'free') return
if (type === 'fixed' || type === 'free') return
const amountDataToken =
isValidNumber(amountOcean) &&

View File

@ -1,5 +1,4 @@
import React from 'react'
import * as Yup from 'yup'
import { allowDynamicPricing, allowFixedPricing } from '../../../app.config.js'
import { FormPublishData, StepContent } from './_types'
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> = {
// name: '',
// author: '',

View 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()

View File

@ -1,6 +1,7 @@
import React, { ReactElement, useState, useRef } from 'react'
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 { Logger } from '@oceanprotocol/lib'
import { useAccountPurgatory } from '@hooks/useAccountPurgatory'