mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
Edit screen fixes (#1546)
* edit refactors * fix logic around `publisherTrustedAlgorithms` * typing fix * copy & typos * conditionally add compute tab to edit screen * more logic fixes * fix various app crashes because of Debug component * semi-deal with publisherTrustedAlgorithmPublishers * more fixes, bound submit button to touched state
This commit is contained in:
parent
5387b9a3dd
commit
02beb0f8c3
@ -1,67 +1,3 @@
|
|||||||
{
|
{
|
||||||
"description": "Update selected metadata of this data set. Updating metadata will create an on-chain transaction you have to approve in your wallet.",
|
"description": "Updating metadata or updating compute settings will create an on-chain transaction you have to approve in your wallet."
|
||||||
"form": {
|
|
||||||
"success": "🎉 Successfully updated. 🎉",
|
|
||||||
"successAction": "Close",
|
|
||||||
"error": "Updating DDO failed.",
|
|
||||||
"data": [
|
|
||||||
{
|
|
||||||
"name": "name",
|
|
||||||
"label": "New Title",
|
|
||||||
"placeholder": "e.g. Shapes of Desert Plants",
|
|
||||||
"help": "Enter a concise title.",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "description",
|
|
||||||
"label": "New Description",
|
|
||||||
"help": "Add a thorough description with as much detail as possible. You can use [Markdown](https://daringfireball.net/projects/markdown/basics).",
|
|
||||||
"type": "textarea",
|
|
||||||
"rows": 10,
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "price",
|
|
||||||
"label": "New Price",
|
|
||||||
"type": "number",
|
|
||||||
"min": "1",
|
|
||||||
"placeholder": "0",
|
|
||||||
"help": "Enter a new price.",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "files",
|
|
||||||
"label": "New file",
|
|
||||||
"placeholder": "e.g. https://file.com/file.json",
|
|
||||||
"help": "This URL will be stored encrypted after publishing. **Please make sure that the endpoint is accessible over the internet and is not protected by a firewall or by credentials.** For a compute data set, your file should match the file type required by the algorithm, and should not exceed 1 GB in file size. Leaving this field empty will not remove the current value.",
|
|
||||||
"prominentHelp": true,
|
|
||||||
"type": "files"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "links",
|
|
||||||
"label": "New sample file",
|
|
||||||
"placeholder": "e.g. https://file.com/samplefile.json",
|
|
||||||
"help": "Please provide a URL to a sample of your data set file. 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. **Please make sure that the endpoint is accessible over the internet and is not protected by a firewall or by credentials.** Leaving this field empty will not remove the current value.",
|
|
||||||
"prominentHelp": true,
|
|
||||||
"type": "files"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"name": "timeout",
|
|
||||||
"label": "Timeout",
|
|
||||||
"help": "Define how long buyers should be able to download the data set again after the initial purchase.",
|
|
||||||
"type": "select",
|
|
||||||
"options": ["Forever", "1 day", "1 week", "1 month", "1 year"],
|
|
||||||
"sortOptions": false,
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "author",
|
|
||||||
"label": "New Author",
|
|
||||||
"placeholder": "e.g. Mrs McJellyfish",
|
|
||||||
"help": "Give proper attribution for your data set.",
|
|
||||||
"required": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
{
|
{
|
||||||
"description": "Only selected algorithms are allowed to run on this data set. Updating these settings will create an on-chain transaction you have to approve in your wallet.",
|
|
||||||
"form": {
|
"form": {
|
||||||
"title": "Set allowed algorithms",
|
"title": "Set allowed algorithms",
|
||||||
"success": "🎉 Successfully updated. 🎉",
|
"description": "Only the algorithms selected here will be allowed to run on your data set. Uncheck all to remove any access to your data set.",
|
||||||
"successAction": "Close",
|
"success": "🎉 Successfully updated. 🎉\n\nUpdates might not show up right away on your asset. In this case, wait some seconds and reload your asset details page in your browser.",
|
||||||
"error": "Updating DDO failed.",
|
"error": "Updating DDO failed.",
|
||||||
"data": [
|
"data": [
|
||||||
{
|
{
|
||||||
|
65
content/pages/editMetadata.json
Normal file
65
content/pages/editMetadata.json
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
{
|
||||||
|
"form": {
|
||||||
|
"success": "🎉 Successfully updated. 🎉\n\nUpdates might not show up right away on your asset. In this case, wait some seconds and reload your asset details page in your browser.",
|
||||||
|
"error": "Updating DDO failed.",
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"label": "New Title",
|
||||||
|
"placeholder": "e.g. Shapes of Desert Plants",
|
||||||
|
"help": "Enter a concise title.",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "description",
|
||||||
|
"label": "New Description",
|
||||||
|
"help": "Add a thorough description with as much detail as possible. You can use [Markdown](https://daringfireball.net/projects/markdown/basics).",
|
||||||
|
"type": "textarea",
|
||||||
|
"rows": 10,
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "price",
|
||||||
|
"label": "New Price",
|
||||||
|
"type": "number",
|
||||||
|
"min": "1",
|
||||||
|
"placeholder": "0",
|
||||||
|
"help": "Enter a new price.",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "files",
|
||||||
|
"label": "New file",
|
||||||
|
"placeholder": "e.g. https://file.com/file.json",
|
||||||
|
"help": "This URL will be stored encrypted after publishing. **Please make sure that the endpoint is accessible over the internet and is not protected by a firewall or by credentials.** For a compute data set, your file should match the file type required by the algorithm, and should not exceed 1 GB in file size. Leaving this field empty will not remove the current value.",
|
||||||
|
"prominentHelp": true,
|
||||||
|
"type": "files"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "links",
|
||||||
|
"label": "New sample file",
|
||||||
|
"placeholder": "e.g. https://file.com/samplefile.json",
|
||||||
|
"help": "Please provide a URL to a sample of your data set file. 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. **Please make sure that the endpoint is accessible over the internet and is not protected by a firewall or by credentials.** Leaving this field empty will not remove the current value.",
|
||||||
|
"prominentHelp": true,
|
||||||
|
"type": "files"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "timeout",
|
||||||
|
"label": "Timeout",
|
||||||
|
"help": "Define how long buyers should be able to download the data set again after the initial purchase.",
|
||||||
|
"type": "select",
|
||||||
|
"options": ["Forever", "1 day", "1 week", "1 month", "1 year"],
|
||||||
|
"sortOptions": false,
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "author",
|
||||||
|
"label": "New Author",
|
||||||
|
"placeholder": "e.g. Mrs McJellyfish",
|
||||||
|
"help": "Give proper attribution for your data set.",
|
||||||
|
"required": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
5
src/@types/Compute.d.ts
vendored
5
src/@types/Compute.d.ts
vendored
@ -15,11 +15,6 @@ declare global {
|
|||||||
name: string
|
name: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ComputePrivacyForm {
|
|
||||||
allowAllPublishedAlgorithms: boolean
|
|
||||||
publisherTrustedAlgorithms: string[]
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TokenOrder {
|
interface TokenOrder {
|
||||||
id: string
|
id: string
|
||||||
serviceIndex: number
|
serviceIndex: number
|
||||||
|
@ -25,6 +25,7 @@ import { SortTermOptions } from 'src/@types/aquarius/SearchQuery'
|
|||||||
import { AssetSelectionAsset } from '@shared/FormFields/AssetSelection'
|
import { AssetSelectionAsset } from '@shared/FormFields/AssetSelection'
|
||||||
import { transformAssetToAssetSelection } from './assetConvertor'
|
import { transformAssetToAssetSelection } from './assetConvertor'
|
||||||
import { AssetExtended } from 'src/@types/AssetExtended'
|
import { AssetExtended } from 'src/@types/AssetExtended'
|
||||||
|
import { ComputeEditForm } from 'src/components/Asset/Edit/_types'
|
||||||
|
|
||||||
const getComputeOrders = gql`
|
const getComputeOrders = gql`
|
||||||
query ComputeOrders($user: String!) {
|
query ComputeOrders($user: String!) {
|
||||||
@ -329,6 +330,7 @@ export async function createTrustedAlgorithmList(
|
|||||||
assetChainId: number,
|
assetChainId: number,
|
||||||
cancelToken: CancelToken
|
cancelToken: CancelToken
|
||||||
): Promise<PublisherTrustedAlgorithm[]> {
|
): Promise<PublisherTrustedAlgorithm[]> {
|
||||||
|
if (!selectedAlgorithms || selectedAlgorithms.length === 0) return []
|
||||||
const trustedAlgorithms: PublisherTrustedAlgorithm[] = []
|
const trustedAlgorithms: PublisherTrustedAlgorithm[] = []
|
||||||
|
|
||||||
const selectedAssets = await retrieveDDOListByDIDs(
|
const selectedAssets = await retrieveDDOListByDIDs(
|
||||||
@ -337,6 +339,8 @@ export async function createTrustedAlgorithmList(
|
|||||||
cancelToken
|
cancelToken
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (!selectedAssets || selectedAssets.length === 0) return []
|
||||||
|
|
||||||
for (const selectedAlgorithm of selectedAssets) {
|
for (const selectedAlgorithm of selectedAssets) {
|
||||||
const sanitizedAlgorithmContainer = {
|
const sanitizedAlgorithmContainer = {
|
||||||
entrypoint: selectedAlgorithm.metadata.algorithm.container.entrypoint,
|
entrypoint: selectedAlgorithm.metadata.algorithm.container.entrypoint,
|
||||||
@ -357,22 +361,28 @@ export async function createTrustedAlgorithmList(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function transformComputeFormToServiceComputeOptions(
|
export async function transformComputeFormToServiceComputeOptions(
|
||||||
values: ComputePrivacyForm,
|
values: ComputeEditForm,
|
||||||
currentOptions: ServiceComputeOptions,
|
currentOptions: ServiceComputeOptions,
|
||||||
assetChainId: number,
|
assetChainId: number,
|
||||||
cancelToken: CancelToken
|
cancelToken: CancelToken
|
||||||
): Promise<ServiceComputeOptions> {
|
): Promise<ServiceComputeOptions> {
|
||||||
const publisherTrustedAlgorithms = values.allowAllPublishedAlgorithms
|
const publisherTrustedAlgorithms = values.allowAllPublishedAlgorithms
|
||||||
? []
|
? null
|
||||||
: await createTrustedAlgorithmList(
|
: await createTrustedAlgorithmList(
|
||||||
values.publisherTrustedAlgorithms,
|
values.publisherTrustedAlgorithms,
|
||||||
assetChainId,
|
assetChainId,
|
||||||
cancelToken
|
cancelToken
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO: add support for selecting trusted publishers and transforming here.
|
||||||
|
// This only deals with basics so we don't accidentially allow all accounts
|
||||||
|
// to be trusted.
|
||||||
|
const publisherTrustedAlgorithmPublishers: string[] = []
|
||||||
|
|
||||||
const privacy: ServiceComputeOptions = {
|
const privacy: ServiceComputeOptions = {
|
||||||
...currentOptions,
|
...currentOptions,
|
||||||
publisherTrustedAlgorithms
|
publisherTrustedAlgorithms,
|
||||||
|
publisherTrustedAlgorithmPublishers
|
||||||
}
|
}
|
||||||
|
|
||||||
return privacy
|
return privacy
|
||||||
|
6
src/@utils/form.ts
Normal file
6
src/@utils/form.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export function getFieldContent(
|
||||||
|
fieldName: string,
|
||||||
|
fields: FormFieldContent[]
|
||||||
|
): FormFieldContent {
|
||||||
|
return fields.filter((field: FormFieldContent) => field.name === fieldName)[0]
|
||||||
|
}
|
@ -1,15 +1,15 @@
|
|||||||
import { Asset, ServiceComputeOptions } from '@oceanprotocol/lib'
|
import { Asset, ServiceComputeOptions } from '@oceanprotocol/lib'
|
||||||
import React, { ReactElement, useEffect, useState } from 'react'
|
import React, { ReactElement, useEffect, useState } from 'react'
|
||||||
// import { transformComputeFormToServiceComputePrivacy } from '@utils/compute'
|
|
||||||
import DebugOutput from '@shared/DebugOutput'
|
import DebugOutput from '@shared/DebugOutput'
|
||||||
import { useCancelToken } from '@hooks/useCancelToken'
|
import { useCancelToken } from '@hooks/useCancelToken'
|
||||||
import { transformComputeFormToServiceComputeOptions } from '@utils/compute'
|
import { transformComputeFormToServiceComputeOptions } from '@utils/compute'
|
||||||
|
import { ComputeEditForm } from './_types'
|
||||||
|
|
||||||
export default function DebugEditCompute({
|
export default function DebugEditCompute({
|
||||||
values,
|
values,
|
||||||
asset
|
asset
|
||||||
}: {
|
}: {
|
||||||
values: ComputePrivacyForm
|
values: ComputeEditForm
|
||||||
asset: Asset
|
asset: Asset
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const [formTransformed, setFormTransformed] =
|
const [formTransformed, setFormTransformed] =
|
||||||
|
@ -6,9 +6,6 @@ import {
|
|||||||
LoggerInstance,
|
LoggerInstance,
|
||||||
ServiceComputeOptions,
|
ServiceComputeOptions,
|
||||||
Service,
|
Service,
|
||||||
ProviderInstance,
|
|
||||||
getHash,
|
|
||||||
Nft,
|
|
||||||
Asset
|
Asset
|
||||||
} from '@oceanprotocol/lib'
|
} from '@oceanprotocol/lib'
|
||||||
import { useUserPreferences } from '@context/UserPreferences'
|
import { useUserPreferences } from '@context/UserPreferences'
|
||||||
@ -29,6 +26,7 @@ import DebugEditCompute from './DebugEditCompute'
|
|||||||
import { useAsset } from '@context/Asset'
|
import { useAsset } from '@context/Asset'
|
||||||
import EditFeedback from './EditFeedback'
|
import EditFeedback from './EditFeedback'
|
||||||
import { setNftMetadata } from '@utils/nft'
|
import { setNftMetadata } from '@utils/nft'
|
||||||
|
import { ComputeEditForm } from './_types'
|
||||||
|
|
||||||
export default function EditComputeDataset({
|
export default function EditComputeDataset({
|
||||||
asset
|
asset
|
||||||
@ -44,10 +42,7 @@ export default function EditComputeDataset({
|
|||||||
const newCancelToken = useCancelToken()
|
const newCancelToken = useCancelToken()
|
||||||
const hasFeedback = error || success
|
const hasFeedback = error || success
|
||||||
|
|
||||||
async function handleSubmit(
|
async function handleSubmit(values: ComputeEditForm, resetForm: () => void) {
|
||||||
values: ComputePrivacyForm,
|
|
||||||
resetForm: () => void
|
|
||||||
) {
|
|
||||||
try {
|
try {
|
||||||
if (asset?.accessDetails?.type === 'free') {
|
if (asset?.accessDetails?.type === 'free') {
|
||||||
const tx = await setMinterToPublisher(
|
const tx = await setMinterToPublisher(
|
||||||
@ -130,18 +125,19 @@ export default function EditComputeDataset({
|
|||||||
// move user's focus to top of screen
|
// move user's focus to top of screen
|
||||||
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' })
|
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' })
|
||||||
// kick off editing
|
// kick off editing
|
||||||
await handleSubmit(values as any, resetForm)
|
await handleSubmit(values, resetForm)
|
||||||
}}
|
}}
|
||||||
|
enableReinitialize
|
||||||
>
|
>
|
||||||
{({ values, isSubmitting }) =>
|
{({ values, isSubmitting }) =>
|
||||||
isSubmitting || hasFeedback ? (
|
isSubmitting || hasFeedback ? (
|
||||||
<EditFeedback
|
<EditFeedback
|
||||||
title="Updating Data Set"
|
loading="Updating data set with new compute settings..."
|
||||||
error={error}
|
error={error}
|
||||||
success={success}
|
success={success}
|
||||||
setError={setError}
|
setError={setError}
|
||||||
successAction={{
|
successAction={{
|
||||||
name: 'View Asset',
|
name: 'Back to Asset',
|
||||||
onClick: async () => {
|
onClick: async () => {
|
||||||
await fetchAsset()
|
await fetchAsset()
|
||||||
},
|
},
|
||||||
@ -150,13 +146,7 @@ export default function EditComputeDataset({
|
|||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<p className={styles.description}>{content.description}</p>
|
<FormEditComputeDataset />
|
||||||
<article>
|
|
||||||
<FormEditComputeDataset
|
|
||||||
title={content.form.title}
|
|
||||||
data={content.form.data}
|
|
||||||
/>
|
|
||||||
</article>
|
|
||||||
<Web3Feedback
|
<Web3Feedback
|
||||||
networkId={asset?.chainId}
|
networkId={asset?.chainId}
|
||||||
isAssetNetwork={isAssetNetwork}
|
isAssetNetwork={isAssetNetwork}
|
||||||
|
@ -1,16 +1,10 @@
|
|||||||
.feedback {
|
.feedback {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
min-height: 40vh;
|
min-height: 40vh;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
text-align: center;
|
justify-content: center;
|
||||||
}
|
|
||||||
|
|
||||||
.box {
|
|
||||||
composes: box from '@shared/atoms/Box.module.css';
|
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.feedback h3 {
|
.feedback h3 {
|
||||||
|
@ -41,17 +41,15 @@ function ActionError({ setError }: { setError: (error: string) => void }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function EditFeedback({
|
export default function EditFeedback({
|
||||||
title,
|
|
||||||
error,
|
error,
|
||||||
success,
|
success,
|
||||||
loading,
|
loading,
|
||||||
successAction,
|
successAction,
|
||||||
setError
|
setError
|
||||||
}: {
|
}: {
|
||||||
title: string
|
|
||||||
error: string
|
error: string
|
||||||
success: string
|
success: string
|
||||||
loading?: string
|
loading: string
|
||||||
successAction: Action
|
successAction: Action
|
||||||
setError: (error: string) => void
|
setError: (error: string) => void
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
@ -64,31 +62,28 @@ export default function EditFeedback({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.feedback}>
|
<div className={styles.feedback}>
|
||||||
<div className={styles.box}>
|
{error ? (
|
||||||
<h3>{title}</h3>
|
<>
|
||||||
{error ? (
|
<p>Sorry, something went wrong. Please try again.</p>
|
||||||
<>
|
{moreInfo && <Alert text={error} state="error" />}
|
||||||
<p>Sorry, something went wrong. Please try again.</p>
|
<Button
|
||||||
{moreInfo && <Alert text={error} state="error" />}
|
style="text"
|
||||||
<Button
|
size="small"
|
||||||
style="text"
|
onClick={toggleMoreInfo}
|
||||||
size="small"
|
className={styles.moreInfo}
|
||||||
onClick={toggleMoreInfo}
|
>
|
||||||
className={styles.moreInfo}
|
{moreInfo === false ? 'More Info' : 'Hide error'}
|
||||||
>
|
</Button>
|
||||||
{moreInfo === false ? 'More Info' : 'Hide error'}
|
<ActionError setError={setError} />
|
||||||
</Button>
|
</>
|
||||||
<ActionError setError={setError} />
|
) : success ? (
|
||||||
</>
|
<SuccessConfetti
|
||||||
) : success ? (
|
success={success}
|
||||||
<SuccessConfetti
|
action={<ActionSuccess action={successAction} />}
|
||||||
success={success}
|
/>
|
||||||
action={<ActionSuccess action={successAction} />}
|
) : (
|
||||||
/>
|
<Loader message={loading} />
|
||||||
) : (
|
)}
|
||||||
<Loader message={loading} />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ import Web3Feedback from '@shared/Web3Feedback'
|
|||||||
import FormEditMetadata from './FormEditMetadata'
|
import FormEditMetadata from './FormEditMetadata'
|
||||||
import { mapTimeoutStringToSeconds } from '@utils/ddo'
|
import { mapTimeoutStringToSeconds } from '@utils/ddo'
|
||||||
import styles from './index.module.css'
|
import styles from './index.module.css'
|
||||||
import content from '../../../../content/pages/edit.json'
|
import content from '../../../../content/pages/editMetadata.json'
|
||||||
import { AssetExtended } from 'src/@types/AssetExtended'
|
import { AssetExtended } from 'src/@types/AssetExtended'
|
||||||
import { useAbortController } from '@hooks/useAbortController'
|
import { useAbortController } from '@hooks/useAbortController'
|
||||||
import DebugEditMetadata from './DebugEditMetadata'
|
import DebugEditMetadata from './DebugEditMetadata'
|
||||||
@ -159,12 +159,12 @@ export default function Edit({
|
|||||||
{({ isSubmitting, values }) =>
|
{({ isSubmitting, values }) =>
|
||||||
isSubmitting || hasFeedback ? (
|
isSubmitting || hasFeedback ? (
|
||||||
<EditFeedback
|
<EditFeedback
|
||||||
title="Updating Data Set"
|
loading="Updating asset with new metadata..."
|
||||||
error={error}
|
error={error}
|
||||||
success={success}
|
success={success}
|
||||||
setError={setError}
|
setError={setError}
|
||||||
successAction={{
|
successAction={{
|
||||||
name: 'View Asset',
|
name: 'Back to Asset',
|
||||||
onClick: async () => {
|
onClick: async () => {
|
||||||
await fetchAsset()
|
await fetchAsset()
|
||||||
},
|
},
|
||||||
@ -173,27 +173,22 @@ export default function Edit({
|
|||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<p className={styles.description}>{content.description}</p>
|
<FormEditMetadata
|
||||||
<article>
|
data={content.form.data}
|
||||||
<FormEditMetadata
|
showPrice={asset?.accessDetails?.type === 'fixed'}
|
||||||
data={content.form.data}
|
isComputeDataset={isComputeType}
|
||||||
showPrice={asset?.accessDetails?.type === 'fixed'}
|
/>
|
||||||
isComputeDataset={isComputeType}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<aside>
|
<Web3Feedback
|
||||||
<Web3Feedback
|
networkId={asset?.chainId}
|
||||||
networkId={asset?.chainId}
|
isAssetNetwork={isAssetNetwork}
|
||||||
isAssetNetwork={isAssetNetwork}
|
/>
|
||||||
/>
|
|
||||||
</aside>
|
|
||||||
|
|
||||||
{debug === true && (
|
{debug === true && (
|
||||||
<div className={styles.grid}>
|
<div className={styles.grid}>
|
||||||
<DebugEditMetadata values={values} asset={asset} />
|
<DebugEditMetadata values={values} asset={asset} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</article>
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import { useAsset } from '@context/Asset'
|
|||||||
import Button from '@shared/atoms/Button'
|
import Button from '@shared/atoms/Button'
|
||||||
import styles from './FormActions.module.css'
|
import styles from './FormActions.module.css'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
import { ComputeEditForm, MetadataEditForm } from './_types'
|
||||||
|
|
||||||
export default function FormActions({
|
export default function FormActions({
|
||||||
handleClick
|
handleClick
|
||||||
@ -11,15 +12,17 @@ export default function FormActions({
|
|||||||
handleClick?: () => void
|
handleClick?: () => void
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const { isAssetNetwork, asset } = useAsset()
|
const { isAssetNetwork, asset } = useAsset()
|
||||||
const { isValid }: FormikContextType<Partial<any>> = useFormikContext()
|
const {
|
||||||
|
isValid,
|
||||||
|
touched
|
||||||
|
}: FormikContextType<MetadataEditForm | ComputeEditForm> = useFormikContext()
|
||||||
|
|
||||||
|
const isSubmitDisabled =
|
||||||
|
!isValid || !isAssetNetwork || Object.keys(touched).length === 0
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<footer className={styles.actions}>
|
<footer className={styles.actions}>
|
||||||
<Button
|
<Button style="primary" disabled={isSubmitDisabled} onClick={handleClick}>
|
||||||
style="primary"
|
|
||||||
disabled={!isValid || !isAssetNetwork}
|
|
||||||
onClick={handleClick}
|
|
||||||
>
|
|
||||||
Submit
|
Submit
|
||||||
</Button>
|
</Button>
|
||||||
<Link href={`/asset/${asset?.id}`} key={asset?.id}>
|
<Link href={`/asset/${asset?.id}`} key={asset?.id}>
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
.form {
|
|
||||||
composes: box from '@shared/atoms/Box.module.css';
|
|
||||||
}
|
|
||||||
|
|
||||||
.form select[multiple] {
|
|
||||||
height: 130px;
|
|
||||||
}
|
|
@ -1,9 +1,14 @@
|
|||||||
import React, { ReactElement, useEffect, useState } from 'react'
|
import React, {
|
||||||
|
ChangeEvent,
|
||||||
|
ReactElement,
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useState
|
||||||
|
} from 'react'
|
||||||
import { Field, Form, FormikContextType, useFormikContext } from 'formik'
|
import { Field, Form, FormikContextType, useFormikContext } from 'formik'
|
||||||
import Input, { InputProps } from '@shared/FormInput'
|
import Input, { InputProps } from '@shared/FormInput'
|
||||||
import { AssetSelectionAsset } from '@shared/FormFields/AssetSelection'
|
import { AssetSelectionAsset } from '@shared/FormFields/AssetSelection'
|
||||||
import stylesIndex from './index.module.css'
|
import stylesIndex from './index.module.css'
|
||||||
import styles from './FormEdit.module.css'
|
|
||||||
import {
|
import {
|
||||||
generateBaseQuery,
|
generateBaseQuery,
|
||||||
getFilterTerm,
|
getFilterTerm,
|
||||||
@ -16,71 +21,100 @@ import { useCancelToken } from '@hooks/useCancelToken'
|
|||||||
import { SortTermOptions } from '../../../@types/aquarius/SearchQuery'
|
import { SortTermOptions } from '../../../@types/aquarius/SearchQuery'
|
||||||
import { getServiceByName } from '@utils/ddo'
|
import { getServiceByName } from '@utils/ddo'
|
||||||
import { transformAssetToAssetSelection } from '@utils/assetConvertor'
|
import { transformAssetToAssetSelection } from '@utils/assetConvertor'
|
||||||
import { useMarketMetadata } from '@context/MarketMetadata'
|
import { ComputeEditForm } from './_types'
|
||||||
|
import content from '../../../../content/pages/editComputeDataset.json'
|
||||||
|
import { getFieldContent } from '@utils/form'
|
||||||
|
|
||||||
export default function FormEditComputeDataset({
|
export default function FormEditComputeDataset(): ReactElement {
|
||||||
data,
|
|
||||||
title
|
|
||||||
}: {
|
|
||||||
data: InputProps[]
|
|
||||||
title: string
|
|
||||||
}): ReactElement {
|
|
||||||
const { appConfig } = useMarketMetadata()
|
|
||||||
const { asset } = useAsset()
|
const { asset } = useAsset()
|
||||||
const { values }: FormikContextType<ComputePrivacyForm> = useFormikContext()
|
const { values }: FormikContextType<ComputeEditForm> = useFormikContext()
|
||||||
const [allAlgorithms, setAllAlgorithms] = useState<AssetSelectionAsset[]>()
|
|
||||||
const newCancelToken = useCancelToken()
|
const newCancelToken = useCancelToken()
|
||||||
const { publisherTrustedAlgorithms } = getServiceByName(
|
|
||||||
asset,
|
|
||||||
'compute'
|
|
||||||
).compute
|
|
||||||
|
|
||||||
async function getAlgorithmList(
|
const [allAlgorithms, setAllAlgorithms] = useState<AssetSelectionAsset[]>()
|
||||||
publisherTrustedAlgorithms: PublisherTrustedAlgorithm[]
|
|
||||||
): Promise<AssetSelectionAsset[]> {
|
|
||||||
const baseParams = {
|
|
||||||
chainIds: [asset.chainId],
|
|
||||||
sort: { sortBy: SortTermOptions.Created },
|
|
||||||
filters: [getFilterTerm('metadata.type', 'algorithm')]
|
|
||||||
} as BaseQueryParams
|
|
||||||
|
|
||||||
const query = generateBaseQuery(baseParams)
|
const {
|
||||||
const querryResult = await queryMetadata(query, newCancelToken())
|
validateField,
|
||||||
const datasetComputeService = getServiceByName(asset, 'compute')
|
setFieldValue,
|
||||||
const algorithmSelectionList = await transformAssetToAssetSelection(
|
setFieldTouched
|
||||||
datasetComputeService?.serviceEndpoint,
|
}: FormikContextType<Partial<ComputeEditForm>> = useFormikContext()
|
||||||
querryResult?.results,
|
|
||||||
publisherTrustedAlgorithms
|
// Manually handle change events instead of using `handleChange` from Formik.
|
||||||
)
|
// Workaround for default `validateOnChange` not kicking in unless user
|
||||||
return algorithmSelectionList
|
// clicks outside of form field.
|
||||||
|
function handleFieldChange(e: ChangeEvent<HTMLInputElement>, name: string) {
|
||||||
|
validateField(name)
|
||||||
|
setFieldTouched(name, true)
|
||||||
|
setFieldValue(name, e.target.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getAlgorithmList = useCallback(
|
||||||
|
async (
|
||||||
|
publisherTrustedAlgorithms: PublisherTrustedAlgorithm[]
|
||||||
|
): Promise<AssetSelectionAsset[]> => {
|
||||||
|
const baseParams = {
|
||||||
|
chainIds: [asset.chainId],
|
||||||
|
sort: { sortBy: SortTermOptions.Created },
|
||||||
|
filters: [getFilterTerm('metadata.type', 'algorithm')]
|
||||||
|
} as BaseQueryParams
|
||||||
|
|
||||||
|
const query = generateBaseQuery(baseParams)
|
||||||
|
const queryResult = await queryMetadata(query, newCancelToken())
|
||||||
|
const datasetComputeService = getServiceByName(asset, 'compute')
|
||||||
|
const algorithmSelectionList = await transformAssetToAssetSelection(
|
||||||
|
datasetComputeService?.serviceEndpoint,
|
||||||
|
queryResult?.results,
|
||||||
|
publisherTrustedAlgorithms
|
||||||
|
)
|
||||||
|
return algorithmSelectionList
|
||||||
|
},
|
||||||
|
[asset, newCancelToken]
|
||||||
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!asset) return
|
||||||
|
|
||||||
|
const { publisherTrustedAlgorithms } = getServiceByName(
|
||||||
|
asset,
|
||||||
|
'compute'
|
||||||
|
).compute
|
||||||
|
|
||||||
getAlgorithmList(publisherTrustedAlgorithms).then((algorithms) => {
|
getAlgorithmList(publisherTrustedAlgorithms).then((algorithms) => {
|
||||||
setAllAlgorithms(algorithms)
|
setAllAlgorithms(algorithms)
|
||||||
})
|
})
|
||||||
}, [appConfig, appConfig.metadataCacheUri, publisherTrustedAlgorithms])
|
}, [asset, getAlgorithmList])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form className={styles.form}>
|
<Form>
|
||||||
<h3 className={stylesIndex.title}>{title}</h3>
|
<header className={stylesIndex.headerForm}>
|
||||||
{data.map((field: InputProps) => (
|
<h3 className={stylesIndex.titleForm}>{content.form.title}</h3>
|
||||||
<Field
|
<p className={stylesIndex.descriptionForm}>
|
||||||
key={field.name}
|
{content.form.description}
|
||||||
{...field}
|
</p>
|
||||||
options={
|
</header>
|
||||||
field.name === 'publisherTrustedAlgorithms'
|
|
||||||
? allAlgorithms
|
<Field
|
||||||
: field.options
|
{...getFieldContent('publisherTrustedAlgorithms', content.form.data)}
|
||||||
}
|
component={Input}
|
||||||
disabled={
|
name="publisherTrustedAlgorithms"
|
||||||
field.name === 'publisherTrustedAlgorithms'
|
options={allAlgorithms}
|
||||||
? values.allowAllPublishedAlgorithms
|
disabled={values.allowAllPublishedAlgorithms}
|
||||||
: false
|
onChange={(e: ChangeEvent<HTMLInputElement>) =>
|
||||||
}
|
handleFieldChange(e, 'publisherTrustedAlgorithms')
|
||||||
component={Input}
|
}
|
||||||
/>
|
/>
|
||||||
))}
|
|
||||||
|
<Field
|
||||||
|
{...getFieldContent('allowAllPublishedAlgorithms', content.form.data)}
|
||||||
|
component={Input}
|
||||||
|
name="allowAllPublishedAlgorithms"
|
||||||
|
options={
|
||||||
|
getFieldContent('allowAllPublishedAlgorithms', content.form.data)
|
||||||
|
.options
|
||||||
|
}
|
||||||
|
onChange={(e: ChangeEvent<HTMLInputElement>) =>
|
||||||
|
handleFieldChange(e, 'allowAllPublishedAlgorithms')
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<FormActions />
|
<FormActions />
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -2,7 +2,6 @@ import React, { ChangeEvent, ReactElement } from 'react'
|
|||||||
import { Field, Form, FormikContextType, useFormikContext } from 'formik'
|
import { Field, Form, FormikContextType, useFormikContext } from 'formik'
|
||||||
import Input, { InputProps } from '@shared/FormInput'
|
import Input, { InputProps } from '@shared/FormInput'
|
||||||
import FormActions from './FormActions'
|
import FormActions from './FormActions'
|
||||||
import styles from './FormEdit.module.css'
|
|
||||||
import { useAsset } from '@context/Asset'
|
import { useAsset } from '@context/Asset'
|
||||||
import { MetadataEditForm } from './_types'
|
import { MetadataEditForm } from './_types'
|
||||||
|
|
||||||
@ -28,18 +27,22 @@ export default function FormEditMetadata({
|
|||||||
const { oceanConfig } = useAsset()
|
const { oceanConfig } = useAsset()
|
||||||
const {
|
const {
|
||||||
validateField,
|
validateField,
|
||||||
setFieldValue
|
setFieldValue,
|
||||||
|
setFieldTouched
|
||||||
}: FormikContextType<Partial<MetadataEditForm>> = useFormikContext()
|
}: FormikContextType<Partial<MetadataEditForm>> = useFormikContext()
|
||||||
|
|
||||||
// Manually handle change events instead of using `handleChange` from Formik.
|
// Manually handle change events instead of using `handleChange` from Formik.
|
||||||
// Workaround for default `validateOnChange` not kicking in
|
// Workaround for default `validateOnChange` not kicking in unless user
|
||||||
|
// clicks outside of form field.
|
||||||
function handleFieldChange(
|
function handleFieldChange(
|
||||||
e: ChangeEvent<HTMLInputElement>,
|
e: ChangeEvent<HTMLInputElement>,
|
||||||
field: InputProps
|
field: InputProps
|
||||||
) {
|
) {
|
||||||
validateField(field.name)
|
validateField(field.name)
|
||||||
|
setFieldTouched(field.name, true)
|
||||||
setFieldValue(field.name, e.target.value)
|
setFieldValue(field.name, e.target.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This component is handled by Formik so it's not rendered like a "normal" react component,
|
// This component is handled by Formik so it's not rendered like a "normal" react component,
|
||||||
// so handleTimeoutCustomOption is called only once.
|
// so handleTimeoutCustomOption is called only once.
|
||||||
// https://github.com/oceanprotocol/market/pull/324#discussion_r561132310
|
// https://github.com/oceanprotocol/market/pull/324#discussion_r561132310
|
||||||
@ -57,7 +60,7 @@ export default function FormEditMetadata({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form className={styles.form}>
|
<Form>
|
||||||
{data.map(
|
{data.map(
|
||||||
(field: InputProps) =>
|
(field: InputProps) =>
|
||||||
(!showPrice && field.name === 'price') || (
|
(!showPrice && field.name === 'price') || (
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { FileInfo, Metadata, ServiceComputeOptions } from '@oceanprotocol/lib'
|
import { FileInfo, Metadata, ServiceComputeOptions } from '@oceanprotocol/lib'
|
||||||
import { secondsToString } from '@utils/ddo'
|
import { secondsToString } from '@utils/ddo'
|
||||||
import * as Yup from 'yup'
|
import * as Yup from 'yup'
|
||||||
import { MetadataEditForm } from './_types'
|
import { ComputeEditForm, MetadataEditForm } from './_types'
|
||||||
|
|
||||||
export const validationSchema = Yup.object().shape({
|
export const validationSchema = Yup.object().shape({
|
||||||
name: Yup.string()
|
name: Yup.string()
|
||||||
@ -33,27 +33,22 @@ export function getInitialValues(
|
|||||||
|
|
||||||
export const computeSettingsValidationSchema = Yup.object().shape({
|
export const computeSettingsValidationSchema = Yup.object().shape({
|
||||||
allowAllPublishedAlgorithms: Yup.boolean().nullable(),
|
allowAllPublishedAlgorithms: Yup.boolean().nullable(),
|
||||||
publisherTrustedAlgorithms: Yup.array().nullable()
|
publisherTrustedAlgorithms: Yup.array().nullable(),
|
||||||
|
publisherTrustedAlgorithmPublishers: Yup.array().nullable()
|
||||||
})
|
})
|
||||||
|
|
||||||
export function getComputeSettingsInitialValues(
|
export function getComputeSettingsInitialValues({
|
||||||
compute: ServiceComputeOptions
|
publisherTrustedAlgorithms,
|
||||||
): ComputePrivacyForm {
|
publisherTrustedAlgorithmPublishers
|
||||||
const { publisherTrustedAlgorithmPublishers, publisherTrustedAlgorithms } =
|
}: ServiceComputeOptions): ComputeEditForm {
|
||||||
compute
|
const allowAllPublishedAlgorithms = publisherTrustedAlgorithms === null
|
||||||
const allowAllPublishedAlgorithms = !(
|
const publisherTrustedAlgorithmsForForm = allowAllPublishedAlgorithms
|
||||||
publisherTrustedAlgorithms?.length > 0 ||
|
? null
|
||||||
publisherTrustedAlgorithmPublishers?.length > 0
|
: publisherTrustedAlgorithms.map((algo) => algo.did)
|
||||||
)
|
|
||||||
|
|
||||||
const publisherTrustedAlgorithmsForForm = (
|
|
||||||
publisherTrustedAlgorithms || []
|
|
||||||
).map((algo) => algo.did)
|
|
||||||
|
|
||||||
// TODO: should we add publisherTrustedAlgorithmPublishers to the form?
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
allowAllPublishedAlgorithms,
|
allowAllPublishedAlgorithms,
|
||||||
publisherTrustedAlgorithms: publisherTrustedAlgorithmsForForm
|
publisherTrustedAlgorithms: publisherTrustedAlgorithmsForForm,
|
||||||
|
publisherTrustedAlgorithmPublishers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// import { EditableMetadataLinks } from '@oceanprotocol/lib'
|
|
||||||
|
|
||||||
export interface MetadataEditForm {
|
export interface MetadataEditForm {
|
||||||
name: string
|
name: string
|
||||||
description: string
|
description: string
|
||||||
@ -9,3 +7,9 @@ export interface MetadataEditForm {
|
|||||||
files: string | any[]
|
files: string | any[]
|
||||||
author?: string
|
author?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ComputeEditForm {
|
||||||
|
allowAllPublishedAlgorithms: boolean
|
||||||
|
publisherTrustedAlgorithms: string[]
|
||||||
|
publisherTrustedAlgorithmPublishers: string[]
|
||||||
|
}
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
.edit ul > li[class*='Tabs_tab'] {
|
.container {
|
||||||
padding: calc(var(--spacer) / 4) var(--spacer);
|
composes: box from '@shared/atoms/Box.module.css';
|
||||||
}
|
padding: 0;
|
||||||
|
position: relative;
|
||||||
.edit [class*='Tabs_tabContent'] {
|
|
||||||
padding-left: 0;
|
|
||||||
padding-right: 0;
|
|
||||||
padding-top: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid {
|
.grid {
|
||||||
@ -19,30 +15,18 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.contianer {
|
|
||||||
composes: box from '@shared/atoms/Box.module.css';
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 60rem) {
|
@media (min-width: 60rem) {
|
||||||
.grid {
|
.grid {
|
||||||
grid-template-columns: 1.5fr 1fr;
|
grid-template-columns: 1.5fr 1fr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.description {
|
.headerForm {
|
||||||
font-size: var(--font-size-large);
|
margin-bottom: var(--spacer);
|
||||||
margin: calc(var(--spacer) * 0.3 / var(--line-height)) 0
|
|
||||||
calc(var(--spacer) / var(--line-height)) 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.titleForm {
|
||||||
font-size: var(--font-size-large);
|
font-size: var(--font-size-h4);
|
||||||
border-bottom: 1px solid var(--border-color);
|
margin-bottom: calc(var(--spacer) / 8);
|
||||||
padding-bottom: calc(var(--spacer) / 2);
|
max-width: 50rem;
|
||||||
margin-top: -1rem;
|
|
||||||
margin-left: -2rem;
|
|
||||||
margin-right: -2rem;
|
|
||||||
padding-left: 2rem;
|
|
||||||
padding-right: 2rem;
|
|
||||||
}
|
}
|
||||||
|
@ -6,57 +6,58 @@ import EditMetadata from './EditMetadata'
|
|||||||
import EditComputeDataset from './EditComputeDataset'
|
import EditComputeDataset from './EditComputeDataset'
|
||||||
import Page from '@shared/Page'
|
import Page from '@shared/Page'
|
||||||
import Loader from '@shared/atoms/Loader'
|
import Loader from '@shared/atoms/Loader'
|
||||||
import { useWeb3 } from '@context/Web3'
|
|
||||||
import Alert from '@shared/atoms/Alert'
|
import Alert from '@shared/atoms/Alert'
|
||||||
|
import contentPage from '../../../../content/pages/edit.json'
|
||||||
|
import Container from '@shared/atoms/Container'
|
||||||
|
|
||||||
export default function Edit({ uri }: { uri: string }): ReactElement {
|
export default function Edit({ uri }: { uri: string }): ReactElement {
|
||||||
const { asset, error, isInPurgatory, owner, title } = useAsset()
|
const { asset, error, isInPurgatory, title, isOwner } = useAsset()
|
||||||
const [isCompute, setIsCompute] = useState(false)
|
const [isCompute, setIsCompute] = useState(false)
|
||||||
const [pageTitle, setPageTitle] = useState<string>('')
|
const [pageTitle, setPageTitle] = useState<string>('')
|
||||||
const { accountId } = useWeb3()
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!asset || error || accountId !== owner) {
|
if (!asset) return
|
||||||
setPageTitle('Edit action not available')
|
|
||||||
return
|
const pageTitle = isInPurgatory
|
||||||
}
|
? ''
|
||||||
setPageTitle(isInPurgatory ? '' : `Edit ${title}`)
|
: !isOwner
|
||||||
|
? 'Edit action not available'
|
||||||
|
: `Edit ${title}`
|
||||||
|
|
||||||
|
setPageTitle(pageTitle)
|
||||||
setIsCompute(asset?.services[0]?.type === 'compute')
|
setIsCompute(asset?.services[0]?.type === 'compute')
|
||||||
}, [asset, error, isInPurgatory, title])
|
}, [asset, isInPurgatory, title, isOwner])
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{
|
{
|
||||||
title: 'Edit Metadata',
|
title: 'Edit Metadata',
|
||||||
content: <EditMetadata asset={asset} />
|
content: <EditMetadata asset={asset} />
|
||||||
},
|
},
|
||||||
{
|
...[
|
||||||
title: 'Edit Compute Settings',
|
isCompute && asset?.metadata.type !== 'algorithm'
|
||||||
content: <EditComputeDataset asset={asset} />,
|
? {
|
||||||
disabled: !isCompute || asset?.metadata?.type === 'algorithm'
|
title: 'Edit Compute Settings',
|
||||||
}
|
content: <EditComputeDataset asset={asset} />
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
]
|
||||||
].filter((tab) => tab !== undefined)
|
].filter((tab) => tab !== undefined)
|
||||||
|
|
||||||
return asset &&
|
return (
|
||||||
asset?.accessDetails &&
|
<Page title={pageTitle} description={contentPage.description} uri={uri}>
|
||||||
accountId?.toLowerCase() === owner?.toLowerCase() ? (
|
{!asset?.accessDetails ? (
|
||||||
<Page title={pageTitle} noPageHeader uri={uri}>
|
<Loader />
|
||||||
<div className={styles.container}>
|
) : !isOwner ? (
|
||||||
<Tabs items={tabs} defaultIndex={0} className={styles.edit} />
|
<Alert
|
||||||
</div>
|
title="Edit action available only to asset owner"
|
||||||
</Page>
|
text={error}
|
||||||
) : asset &&
|
state="error"
|
||||||
asset?.accessDetails &&
|
/>
|
||||||
accountId?.toLowerCase() !== owner?.toLowerCase() ? (
|
) : (
|
||||||
<Page title={pageTitle} noPageHeader uri={uri}>
|
<Container className={styles.container}>
|
||||||
<Alert
|
<Tabs items={tabs} defaultIndex={0} className={styles.edit} />
|
||||||
title="Edit action available only to asset owner"
|
</Container>
|
||||||
text={error}
|
)}
|
||||||
state="error"
|
|
||||||
/>
|
|
||||||
</Page>
|
|
||||||
) : (
|
|
||||||
<Page title={pageTitle} noPageHeader uri={uri}>
|
|
||||||
<Loader />
|
|
||||||
</Page>
|
</Page>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,13 @@ import { Field, useFormikContext } from 'formik'
|
|||||||
import React, { ReactElement, useEffect } from 'react'
|
import React, { ReactElement, useEffect } from 'react'
|
||||||
import content from '../../../../content/publish/form.json'
|
import content from '../../../../content/publish/form.json'
|
||||||
import { FormPublishData } from '../_types'
|
import { FormPublishData } from '../_types'
|
||||||
import { getFieldContent } from '../_utils'
|
|
||||||
import IconDataset from '@images/dataset.svg'
|
import IconDataset from '@images/dataset.svg'
|
||||||
import IconAlgorithm from '@images/algorithm.svg'
|
import IconAlgorithm from '@images/algorithm.svg'
|
||||||
import styles from './index.module.css'
|
import styles from './index.module.css'
|
||||||
import { algorithmContainerPresets } from '../_constants'
|
import { algorithmContainerPresets } from '../_constants'
|
||||||
import Alert from '@shared/atoms/Alert'
|
import Alert from '@shared/atoms/Alert'
|
||||||
import { useMarketMetadata } from '@context/MarketMetadata'
|
import { useMarketMetadata } from '@context/MarketMetadata'
|
||||||
|
import { getFieldContent } from '@utils/form'
|
||||||
|
|
||||||
const assetTypeOptionsTitles = getFieldContent(
|
const assetTypeOptionsTitles = getFieldContent(
|
||||||
'type',
|
'type',
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import Conversion from '@shared/Price/Conversion'
|
import Conversion from '@shared/Price/Conversion'
|
||||||
import { Field, useField, useFormikContext } from 'formik'
|
import { Field, useField, useFormikContext } from 'formik'
|
||||||
import React, { ReactElement, useEffect } from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
import Input from '@shared/FormInput'
|
import Input from '@shared/FormInput'
|
||||||
import Error from '@shared/FormInput/Error'
|
import Error from '@shared/FormInput/Error'
|
||||||
import PriceUnit from '@shared/Price/PriceUnit'
|
import PriceUnit from '@shared/Price/PriceUnit'
|
||||||
import styles from './Price.module.css'
|
import styles from './Price.module.css'
|
||||||
import { FormPublishData } from '../_types'
|
import { FormPublishData } from '../_types'
|
||||||
import { getFieldContent } from '../_utils'
|
import { getFieldContent } from '@utils/form'
|
||||||
|
|
||||||
export default function Price({
|
export default function Price({
|
||||||
firstPrice,
|
firstPrice,
|
||||||
|
@ -4,7 +4,7 @@ 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'
|
||||||
import { getFieldContent } from '../_utils'
|
import { getFieldContent } from '@utils/form'
|
||||||
import { FormPublishData } from '../_types'
|
import { FormPublishData } from '../_types'
|
||||||
import Alert from '@shared/atoms/Alert'
|
import Alert from '@shared/atoms/Alert'
|
||||||
import { useMarketMetadata } from '@context/MarketMetadata'
|
import { useMarketMetadata } from '@context/MarketMetadata'
|
||||||
|
@ -33,13 +33,6 @@ import {
|
|||||||
} from '../../../app.config'
|
} from '../../../app.config'
|
||||||
import { sanitizeUrl } from '@utils/url'
|
import { sanitizeUrl } from '@utils/url'
|
||||||
|
|
||||||
export function getFieldContent(
|
|
||||||
fieldName: string,
|
|
||||||
fields: FormFieldContent[]
|
|
||||||
): FormFieldContent {
|
|
||||||
return fields.filter((field: FormFieldContent) => field.name === fieldName)[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
function getUrlFileExtension(fileUrl: string): string {
|
function getUrlFileExtension(fileUrl: string): string {
|
||||||
const splittedFileUrl = fileUrl.split('.')
|
const splittedFileUrl = fileUrl.split('.')
|
||||||
return splittedFileUrl[splittedFileUrl.length - 1]
|
return splittedFileUrl[splittedFileUrl.length - 1]
|
||||||
|
@ -195,13 +195,13 @@ export async function addExistingParamsToUrl(
|
|||||||
const parsed = queryString.parse(location.search)
|
const parsed = queryString.parse(location.search)
|
||||||
let urlLocation = '/search?'
|
let urlLocation = '/search?'
|
||||||
if (Object.keys(parsed).length > 0) {
|
if (Object.keys(parsed).length > 0) {
|
||||||
for (const querryParam in parsed) {
|
for (const queryParam in parsed) {
|
||||||
if (!excludedParams.includes(querryParam)) {
|
if (!excludedParams.includes(queryParam)) {
|
||||||
if (querryParam === 'page' && excludedParams.includes('text')) {
|
if (queryParam === 'page' && excludedParams.includes('text')) {
|
||||||
LoggerInstance.log('remove page when starting a new search')
|
LoggerInstance.log('remove page when starting a new search')
|
||||||
} else {
|
} else {
|
||||||
const value = parsed[querryParam]
|
const value = parsed[queryParam]
|
||||||
urlLocation = `${urlLocation}${querryParam}=${value}&`
|
urlLocation = `${urlLocation}${queryParam}=${value}&`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user