1
0
mirror of https://github.com/oceanprotocol/market.git synced 2024-12-02 05:57:29 +01:00

Restore edit functionality (#1107)

* add content on edit pages

* display edit for user only

* add form actions

* add restore part of edit metadata logic

* adjust edit metadata

* wip edit compute settings

* added console logs

* wip edit compute

* updated edit compute flow

* updated style

* fix pricing various fixes

* fix edit acctions

* add debug on edit compute tab

* add debug on edit metadata  tab

* more fixes

* lint fixes

* add pricing to edit metada

* restore timout edit

* protect edit route

* small fixes

* fixes and add edit feetback, loading, error, succes on submit

* timeout init values fix

* added setNftMetadata helper

* moved transfor asset to assetSelection from aquarius class

* fixed links, removed dispenser hacks

* fixed sample

Co-authored-by: mihaisc <mihai@oceanprotocol.com>
This commit is contained in:
Bogdan Fazakas 2022-02-25 12:33:07 +02:00 committed by GitHub
parent ed9b1ce2d2
commit 73f3080daf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 1034 additions and 622 deletions

206
package-lock.json generated
View File

@ -5003,9 +5003,9 @@
}
},
"node_modules/@truffle/abi-utils": {
"version": "0.2.8",
"resolved": "https://registry.npmjs.org/@truffle/abi-utils/-/abi-utils-0.2.8.tgz",
"integrity": "sha512-n/9ojMthWuP1hg9JveuxctxWoRoKTh+/17RTSwlTlXTyP/kfoNxr1JcLecybXUDOIsLJ4uskqxVUZQDvj1B0PQ==",
"version": "0.2.9",
"resolved": "https://registry.npmjs.org/@truffle/abi-utils/-/abi-utils-0.2.9.tgz",
"integrity": "sha512-Nv4MGsA2vdI7G34nI0DfR/eSd5pbAUu+5EafYNqzgrS46y0LWhbIrSZ1NcM7cbhIrkpUn6OfNk49AjNM67TkSg==",
"dependencies": {
"change-case": "3.0.2",
"faker": "^5.3.1",
@ -5018,12 +5018,12 @@
"integrity": "sha512-9mzYXPQkjOc23rHQM1i630i3ackITWP1cxf3PvBObaAnGqwPCQuqtmZtNDPdvN+YpOLpBGpZIdYolI91xLdJNQ=="
},
"node_modules/@truffle/codec": {
"version": "0.11.26",
"resolved": "https://registry.npmjs.org/@truffle/codec/-/codec-0.11.26.tgz",
"integrity": "sha512-wNVw66vSL5RSzgNMkiQVIExz7ZF1ZDNdOSPTnFlTiZCvkpJn8QJ9OpDiow9w8HmXIftt+YjueBsKu4ByyBuAPA==",
"version": "0.11.27",
"resolved": "https://registry.npmjs.org/@truffle/codec/-/codec-0.11.27.tgz",
"integrity": "sha512-zPlbrGSZ975jscoJ4NhQpaJGwJXkasnpSoUAEjzppr6FCLKtutxssy6yfz4EUHaQDTg1SqxlVBfBhqYcrCyjvw==",
"dependencies": {
"@truffle/abi-utils": "^0.2.8",
"@truffle/compile-common": "^0.7.27",
"@truffle/abi-utils": "^0.2.9",
"@truffle/compile-common": "^0.7.28",
"big.js": "^5.2.2",
"bn.js": "^5.1.3",
"cbor": "^5.1.0",
@ -5094,23 +5094,23 @@
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
},
"node_modules/@truffle/compile-common": {
"version": "0.7.27",
"resolved": "https://registry.npmjs.org/@truffle/compile-common/-/compile-common-0.7.27.tgz",
"integrity": "sha512-gs266BQTRnVoskoWj7wNrNGACMOhU6Yt+8YhaSp6k5e4/a2NBEluxXWxKIi32yWz4q7Ip306do1wcQR2fFOf8w==",
"version": "0.7.28",
"resolved": "https://registry.npmjs.org/@truffle/compile-common/-/compile-common-0.7.28.tgz",
"integrity": "sha512-mZCEQ6fkOqbKYCJDT82q0vZCxOEsKRQ0zrPfKuSJEb0gF9DXIQcnMkyJpBSWzmyvien9/A7/jPiGQoC7PmNEUg==",
"dependencies": {
"@truffle/error": "^0.1.0",
"colors": "1.4.0"
}
},
"node_modules/@truffle/contract": {
"version": "4.4.8",
"resolved": "https://registry.npmjs.org/@truffle/contract/-/contract-4.4.8.tgz",
"integrity": "sha512-zZVgIJ4zbdKX1dWubX5m9w7StMpcdEXuQorSpPQ23SUD1RwzSgnRi9Iw2rmSLNbHcO+w6L6+JFeVzFrfmI/VKA==",
"version": "4.4.9",
"resolved": "https://registry.npmjs.org/@truffle/contract/-/contract-4.4.9.tgz",
"integrity": "sha512-LSIxnpFDr824wUp4tiw2UHmDPr8io5UnzjlZX/QKuNIq+BB+JPRmkzItjwtvWzzIG3QOAGiqjtIgp1U6Mab/bw==",
"dependencies": {
"@ensdomains/ensjs": "^2.0.1",
"@truffle/blockchain-utils": "^0.1.0",
"@truffle/contract-schema": "^3.4.4",
"@truffle/debug-utils": "^6.0.8",
"@truffle/contract-schema": "^3.4.5",
"@truffle/debug-utils": "^6.0.9",
"@truffle/error": "^0.1.0",
"@truffle/interface-adapter": "^0.5.11",
"bignumber.js": "^7.2.1",
@ -5124,9 +5124,9 @@
}
},
"node_modules/@truffle/contract-schema": {
"version": "3.4.4",
"resolved": "https://registry.npmjs.org/@truffle/contract-schema/-/contract-schema-3.4.4.tgz",
"integrity": "sha512-xWgrm6WRM2jmT04w7dP7aVbS2qyP9XPmH/mybQtFXMjJ/8BZlp0yltC8QOs8sGl6q8Ws7acp19YtRkLdK6SsmQ==",
"version": "3.4.5",
"resolved": "https://registry.npmjs.org/@truffle/contract-schema/-/contract-schema-3.4.5.tgz",
"integrity": "sha512-heaGV9QWqef259HaF+0is/tsmhlZIbUSWhqvj0iwKmxoN92fghKijWwdVYhPIbsmGlrQuwPTZHSCnaOlO+gsFg==",
"dependencies": {
"ajv": "^6.10.0",
"debug": "^4.3.1"
@ -5455,16 +5455,16 @@
}
},
"node_modules/@truffle/debug-utils": {
"version": "6.0.8",
"resolved": "https://registry.npmjs.org/@truffle/debug-utils/-/debug-utils-6.0.8.tgz",
"integrity": "sha512-bkrHQZj6OVw5FCs0li69e0f6gdW+6FuOR8dgedfy8qpsVVtGQB+8cN7hnoFUwMs60vo7vW90grZu1c4855zVQw==",
"version": "6.0.9",
"resolved": "https://registry.npmjs.org/@truffle/debug-utils/-/debug-utils-6.0.9.tgz",
"integrity": "sha512-CVKVsbEWE0TzmTdGcxEeQvNhTKxkojIRox3LWh2Z8ZARtPiWwYl/lmPqfugh1665xmc2NVLI9qyP4ygVFPkvIQ==",
"dependencies": {
"@truffle/codec": "^0.11.26",
"@trufflesuite/chromafi": "^2.2.2",
"@truffle/codec": "^0.11.27",
"@trufflesuite/chromafi": "^3.0.0",
"bn.js": "^5.1.3",
"chalk": "^2.4.2",
"debug": "^4.3.1",
"highlightjs-solidity": "^2.0.3"
"highlightjs-solidity": "^2.0.4"
}
},
"node_modules/@truffle/debug-utils/node_modules/bn.js": {
@ -5959,24 +5959,18 @@
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
},
"node_modules/@trufflesuite/chromafi": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@trufflesuite/chromafi/-/chromafi-2.2.2.tgz",
"integrity": "sha512-mItQwVBsb8qP/vaYHQ1kDt2vJLhjoEXJptT6y6fJGvFophMFhOI/NsTVUa0nJL1nyMeFiS6hSYuNVdpQZzB1gA==",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@trufflesuite/chromafi/-/chromafi-3.0.0.tgz",
"integrity": "sha512-oqWcOqn8nT1bwlPPfidfzS55vqcIDdpfzo3HbU9EnUmcSTX+I8z0UyUFI3tZQjByVJulbzxHxUGS3ZJPwK/GPQ==",
"dependencies": {
"ansi-mark": "^1.0.0",
"ansi-regex": "^3.0.0",
"array-uniq": "^1.0.3",
"camelcase": "^4.1.0",
"chalk": "^2.3.2",
"cheerio": "^1.0.0-rc.2",
"detect-indent": "^5.0.0",
"he": "^1.1.1",
"highlight.js": "^10.4.1",
"lodash.merge": "^4.6.2",
"min-indent": "^1.0.0",
"strip-ansi": "^4.0.0",
"strip-indent": "^2.0.0",
"super-split": "^1.1.0"
"strip-indent": "^2.0.0"
}
},
"node_modules/@trufflesuite/chromafi/node_modules/camelcase": {
@ -7083,18 +7077,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/ansi-mark": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/ansi-mark/-/ansi-mark-1.0.4.tgz",
"integrity": "sha1-HNS6jVfxXxCdaq9uycqXhsik7mw=",
"dependencies": {
"ansi-regex": "^3.0.0",
"array-uniq": "^1.0.3",
"chalk": "^2.3.2",
"strip-ansi": "^4.0.0",
"super-split": "^1.1.0"
}
},
"node_modules/ansi-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
@ -8355,14 +8337,6 @@
"node": ">=8"
}
},
"node_modules/array-uniq": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
"integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/array.prototype.flat": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz",
@ -14723,6 +14697,7 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
"peer": true,
"bin": {
"he": "bin/he"
}
@ -17365,14 +17340,6 @@
"dom-walk": "^0.1.0"
}
},
"node_modules/min-indent": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
"integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
"engines": {
"node": ">=4"
}
},
"node_modules/minimalistic-assert": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
@ -20612,9 +20579,9 @@
]
},
"node_modules/simple-get": {
"version": "2.8.2",
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.2.tgz",
"integrity": "sha512-Ijd/rV5o+mSBBs4F/x9oDPtTx9Zb6X9brmnXvMW4J7IR15ngi9q5xxqWBKU744jTZiaXtxaPL7uHG6vtN8kUkw==",
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz",
"integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==",
"dependencies": {
"decompress-response": "^3.3.0",
"once": "^1.3.1",
@ -21258,11 +21225,6 @@
}
}
},
"node_modules/super-split": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/super-split/-/super-split-1.1.0.tgz",
"integrity": "sha512-I4bA5mgcb6Fw5UJ+EkpzqXfiuvVGS/7MuND+oBxNFmxu3ugLNrdIatzBLfhFRMVMLxgSsRy+TjIktgkF9RFSNQ=="
},
"node_modules/supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
@ -26299,7 +26261,6 @@
"cross-fetch": "^3.1.5",
"crypto-js": "^4.1.1",
"decimal.js": "^10.3.1",
"web3": "^1.7.0",
"web3-core": "^1.7.0",
"web3-eth-contract": "^1.7.0"
}
@ -26402,7 +26363,6 @@
"integrity": "sha512-5vwpq6kbvwkQwKqAoOU3L72GZ3Ta8RRrewKj9OJRolx28KLJJ8Dg9Rf7obRwt5jQA9bkYd8gqzMTrI7H3xLfaw==",
"dev": true,
"requires": {
"@oclif/config": "^1.15.1",
"@oclif/errors": "^1.3.3",
"@oclif/parser": "^3.8.3",
"@oclif/plugin-help": "^3",
@ -27509,9 +27469,9 @@
}
},
"@truffle/abi-utils": {
"version": "0.2.8",
"resolved": "https://registry.npmjs.org/@truffle/abi-utils/-/abi-utils-0.2.8.tgz",
"integrity": "sha512-n/9ojMthWuP1hg9JveuxctxWoRoKTh+/17RTSwlTlXTyP/kfoNxr1JcLecybXUDOIsLJ4uskqxVUZQDvj1B0PQ==",
"version": "0.2.9",
"resolved": "https://registry.npmjs.org/@truffle/abi-utils/-/abi-utils-0.2.9.tgz",
"integrity": "sha512-Nv4MGsA2vdI7G34nI0DfR/eSd5pbAUu+5EafYNqzgrS46y0LWhbIrSZ1NcM7cbhIrkpUn6OfNk49AjNM67TkSg==",
"requires": {
"change-case": "3.0.2",
"faker": "^5.3.1",
@ -27524,12 +27484,12 @@
"integrity": "sha512-9mzYXPQkjOc23rHQM1i630i3ackITWP1cxf3PvBObaAnGqwPCQuqtmZtNDPdvN+YpOLpBGpZIdYolI91xLdJNQ=="
},
"@truffle/codec": {
"version": "0.11.26",
"resolved": "https://registry.npmjs.org/@truffle/codec/-/codec-0.11.26.tgz",
"integrity": "sha512-wNVw66vSL5RSzgNMkiQVIExz7ZF1ZDNdOSPTnFlTiZCvkpJn8QJ9OpDiow9w8HmXIftt+YjueBsKu4ByyBuAPA==",
"version": "0.11.27",
"resolved": "https://registry.npmjs.org/@truffle/codec/-/codec-0.11.27.tgz",
"integrity": "sha512-zPlbrGSZ975jscoJ4NhQpaJGwJXkasnpSoUAEjzppr6FCLKtutxssy6yfz4EUHaQDTg1SqxlVBfBhqYcrCyjvw==",
"requires": {
"@truffle/abi-utils": "^0.2.8",
"@truffle/compile-common": "^0.7.27",
"@truffle/abi-utils": "^0.2.9",
"@truffle/compile-common": "^0.7.28",
"big.js": "^5.2.2",
"bn.js": "^5.1.3",
"cbor": "^5.1.0",
@ -27597,23 +27557,23 @@
}
},
"@truffle/compile-common": {
"version": "0.7.27",
"resolved": "https://registry.npmjs.org/@truffle/compile-common/-/compile-common-0.7.27.tgz",
"integrity": "sha512-gs266BQTRnVoskoWj7wNrNGACMOhU6Yt+8YhaSp6k5e4/a2NBEluxXWxKIi32yWz4q7Ip306do1wcQR2fFOf8w==",
"version": "0.7.28",
"resolved": "https://registry.npmjs.org/@truffle/compile-common/-/compile-common-0.7.28.tgz",
"integrity": "sha512-mZCEQ6fkOqbKYCJDT82q0vZCxOEsKRQ0zrPfKuSJEb0gF9DXIQcnMkyJpBSWzmyvien9/A7/jPiGQoC7PmNEUg==",
"requires": {
"@truffle/error": "^0.1.0",
"colors": "1.4.0"
}
},
"@truffle/contract": {
"version": "4.4.8",
"resolved": "https://registry.npmjs.org/@truffle/contract/-/contract-4.4.8.tgz",
"integrity": "sha512-zZVgIJ4zbdKX1dWubX5m9w7StMpcdEXuQorSpPQ23SUD1RwzSgnRi9Iw2rmSLNbHcO+w6L6+JFeVzFrfmI/VKA==",
"version": "4.4.9",
"resolved": "https://registry.npmjs.org/@truffle/contract/-/contract-4.4.9.tgz",
"integrity": "sha512-LSIxnpFDr824wUp4tiw2UHmDPr8io5UnzjlZX/QKuNIq+BB+JPRmkzItjwtvWzzIG3QOAGiqjtIgp1U6Mab/bw==",
"requires": {
"@ensdomains/ensjs": "^2.0.1",
"@truffle/blockchain-utils": "^0.1.0",
"@truffle/contract-schema": "^3.4.4",
"@truffle/debug-utils": "^6.0.8",
"@truffle/contract-schema": "^3.4.5",
"@truffle/debug-utils": "^6.0.9",
"@truffle/error": "^0.1.0",
"@truffle/interface-adapter": "^0.5.11",
"bignumber.js": "^7.2.1",
@ -27889,25 +27849,25 @@
}
},
"@truffle/contract-schema": {
"version": "3.4.4",
"resolved": "https://registry.npmjs.org/@truffle/contract-schema/-/contract-schema-3.4.4.tgz",
"integrity": "sha512-xWgrm6WRM2jmT04w7dP7aVbS2qyP9XPmH/mybQtFXMjJ/8BZlp0yltC8QOs8sGl6q8Ws7acp19YtRkLdK6SsmQ==",
"version": "3.4.5",
"resolved": "https://registry.npmjs.org/@truffle/contract-schema/-/contract-schema-3.4.5.tgz",
"integrity": "sha512-heaGV9QWqef259HaF+0is/tsmhlZIbUSWhqvj0iwKmxoN92fghKijWwdVYhPIbsmGlrQuwPTZHSCnaOlO+gsFg==",
"requires": {
"ajv": "^6.10.0",
"debug": "^4.3.1"
}
},
"@truffle/debug-utils": {
"version": "6.0.8",
"resolved": "https://registry.npmjs.org/@truffle/debug-utils/-/debug-utils-6.0.8.tgz",
"integrity": "sha512-bkrHQZj6OVw5FCs0li69e0f6gdW+6FuOR8dgedfy8qpsVVtGQB+8cN7hnoFUwMs60vo7vW90grZu1c4855zVQw==",
"version": "6.0.9",
"resolved": "https://registry.npmjs.org/@truffle/debug-utils/-/debug-utils-6.0.9.tgz",
"integrity": "sha512-CVKVsbEWE0TzmTdGcxEeQvNhTKxkojIRox3LWh2Z8ZARtPiWwYl/lmPqfugh1665xmc2NVLI9qyP4ygVFPkvIQ==",
"requires": {
"@truffle/codec": "^0.11.26",
"@trufflesuite/chromafi": "^2.2.2",
"@truffle/codec": "^0.11.27",
"@trufflesuite/chromafi": "^3.0.0",
"bn.js": "^5.1.3",
"chalk": "^2.4.2",
"debug": "^4.3.1",
"highlightjs-solidity": "^2.0.3"
"highlightjs-solidity": "^2.0.4"
},
"dependencies": {
"bn.js": {
@ -28349,24 +28309,18 @@
}
},
"@trufflesuite/chromafi": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@trufflesuite/chromafi/-/chromafi-2.2.2.tgz",
"integrity": "sha512-mItQwVBsb8qP/vaYHQ1kDt2vJLhjoEXJptT6y6fJGvFophMFhOI/NsTVUa0nJL1nyMeFiS6hSYuNVdpQZzB1gA==",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@trufflesuite/chromafi/-/chromafi-3.0.0.tgz",
"integrity": "sha512-oqWcOqn8nT1bwlPPfidfzS55vqcIDdpfzo3HbU9EnUmcSTX+I8z0UyUFI3tZQjByVJulbzxHxUGS3ZJPwK/GPQ==",
"requires": {
"ansi-mark": "^1.0.0",
"ansi-regex": "^3.0.0",
"array-uniq": "^1.0.3",
"camelcase": "^4.1.0",
"chalk": "^2.3.2",
"cheerio": "^1.0.0-rc.2",
"detect-indent": "^5.0.0",
"he": "^1.1.1",
"highlight.js": "^10.4.1",
"lodash.merge": "^4.6.2",
"min-indent": "^1.0.0",
"strip-ansi": "^4.0.0",
"strip-indent": "^2.0.0",
"super-split": "^1.1.0"
"strip-indent": "^2.0.0"
},
"dependencies": {
"camelcase": {
@ -29328,18 +29282,6 @@
"type-fest": "^0.21.3"
}
},
"ansi-mark": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/ansi-mark/-/ansi-mark-1.0.4.tgz",
"integrity": "sha1-HNS6jVfxXxCdaq9uycqXhsik7mw=",
"requires": {
"ansi-regex": "^3.0.0",
"array-uniq": "^1.0.3",
"chalk": "^2.3.2",
"strip-ansi": "^4.0.0",
"super-split": "^1.1.0"
}
},
"ansi-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
@ -30483,11 +30425,6 @@
"integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
"dev": true
},
"array-uniq": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
"integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY="
},
"array.prototype.flat": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz",
@ -35547,7 +35484,8 @@
"he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
"peer": true
},
"header-case": {
"version": "1.0.1",
@ -37589,11 +37527,6 @@
"dom-walk": "^0.1.0"
}
},
"min-indent": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
"integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg=="
},
"minimalistic-assert": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
@ -40054,9 +39987,9 @@
"integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="
},
"simple-get": {
"version": "2.8.2",
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.2.tgz",
"integrity": "sha512-Ijd/rV5o+mSBBs4F/x9oDPtTx9Zb6X9brmnXvMW4J7IR15ngi9q5xxqWBKU744jTZiaXtxaPL7uHG6vtN8kUkw==",
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz",
"integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==",
"requires": {
"decompress-response": "^3.3.0",
"once": "^1.3.1",
@ -40568,11 +40501,6 @@
"integrity": "sha512-qUqsWoBquEdERe10EW8vLp3jT25s/ssG1/qX5gZ4wu15OZpmSMFI2v+fWlRhLfykA5rFtlJ1ME8A8pm/peV4WA==",
"requires": {}
},
"super-split": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/super-split/-/super-split-1.1.0.tgz",
"integrity": "sha512-I4bA5mgcb6Fw5UJ+EkpzqXfiuvVGS/7MuND+oBxNFmxu3ugLNrdIatzBLfhFRMVMLxgSsRy+TjIktgkF9RFSNQ=="
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",

View File

@ -1,10 +1,5 @@
import {
Asset,
LoggerInstance,
PublisherTrustedAlgorithm
} from '@oceanprotocol/lib'
import { Asset, LoggerInstance } from '@oceanprotocol/lib'
import { AssetSelectionAsset } from '@shared/FormFields/AssetSelection'
import { PriceList } from './subgraph'
import axios, { CancelToken, AxiosResponse } from 'axios'
import { OrdersData_orders as OrdersData } from '../@types/subgraph/OrdersData'
import { metadataCacheUri } from '../../app.config'
@ -12,7 +7,7 @@ import {
SortDirectionOptions,
SortTermOptions
} from '../@types/aquarius/SearchQuery'
import { getServiceByName } from './ddo'
import { transformAssetToAssetSelection } from './assetConvertor'
export const MAXIMUM_NUMBER_OF_PAGES_WITH_RESULTS = 476
@ -202,58 +197,6 @@ export async function retrieveDDOListByDIDs(
}
}
export async function transformDDOToAssetSelection(
datasetProviderEndpoint: string,
ddoList: Asset[],
selectedAlgorithms?: PublisherTrustedAlgorithm[],
cancelToken?: CancelToken
): Promise<AssetSelectionAsset[]> {
const didList: string[] = []
// const priceList: PriceList = await getAssetsPriceList(ddoList)
const priceList: PriceList = null
const symbolList: any = {}
const didProviderEndpointMap: any = {}
for (const ddo of ddoList) {
didList.push(ddo.id)
symbolList[ddo.id] = ddo.datatokens[0].symbol
const algoComputeService = getServiceByName(ddo, 'compute')
algoComputeService?.serviceEndpoint &&
(didProviderEndpointMap[ddo.id] = algoComputeService?.serviceEndpoint)
}
const ddoNames = await getAssetsNames(didList, cancelToken)
const algorithmList: AssetSelectionAsset[] = []
didList?.forEach((did: string) => {
if (
priceList[did] &&
(!didProviderEndpointMap[did] ||
didProviderEndpointMap[did] === datasetProviderEndpoint)
) {
let selected = false
selectedAlgorithms?.forEach((algorithm: PublisherTrustedAlgorithm) => {
if (algorithm.did === did) {
selected = true
}
})
selected
? algorithmList.unshift({
did: did,
name: ddoNames[did],
price: priceList[did],
checked: selected,
symbol: symbolList[did]
})
: algorithmList.push({
did: did,
name: ddoNames[did],
price: priceList[did],
checked: selected,
symbol: symbolList[did]
})
}
})
return algorithmList
}
export async function getAlgorithmDatasetsForCompute(
algorithmId: string,
datasetProviderUri: string,
@ -264,7 +207,7 @@ export async function getAlgorithmDatasetsForCompute(
chainIds: [datasetChainId],
filters: [
getFilterTerm(
'service.attributes.main.privacy.publisherTrustedAlgorithms.did',
'service.compite.publisherTrustedAlgorithms.did',
algorithmId
)
],
@ -279,11 +222,10 @@ export async function getAlgorithmDatasetsForCompute(
if (computeDatasets.totalResults === 0) return []
const datasets = await transformDDOToAssetSelection(
const datasets = await transformAssetToAssetSelection(
datasetProviderUri,
computeDatasets.results,
[],
cancelToken
[]
)
return datasets
}

View File

@ -0,0 +1,43 @@
import { getAccessDetailsForAssets } from './accessDetailsAndPricing'
import { AssetExtended } from 'src/@types/AssetExtended'
import { PublisherTrustedAlgorithm, Asset } from '@oceanprotocol/lib'
import { AssetSelectionAsset } from '@shared/FormFields/AssetSelection'
import { getServiceByName } from './ddo'
export async function transformAssetToAssetSelection(
datasetProviderEndpoint: string,
assets: Asset[],
selectedAlgorithms?: PublisherTrustedAlgorithm[]
): Promise<AssetSelectionAsset[]> {
const extendedAssets: AssetExtended[] = await getAccessDetailsForAssets(
assets
)
const algorithmList: AssetSelectionAsset[] = []
for (const asset of extendedAssets) {
const algoComputeService = getServiceByName(asset, 'compute')
if (
asset?.accessDetails.price &&
algoComputeService?.serviceEndpoint === datasetProviderEndpoint
) {
let selected = false
selectedAlgorithms?.forEach((algorithm: PublisherTrustedAlgorithm) => {
if (algorithm.did === asset.id) {
selected = true
}
})
const algorithmAsset: AssetSelectionAsset = {
did: asset.id,
name: asset.datatokens[0].name,
price: asset.accessDetails.price,
checked: selected,
symbol: asset.datatokens[0].symbol
}
selected
? algorithmList.unshift(algorithmAsset)
: algorithmList.push(algorithmAsset)
}
}
return algorithmList
}

View File

@ -9,10 +9,20 @@
// Account
// } from '@oceanprotocol/lib'
// import { ComputeJob } from '@oceanprotocol/lib/dist/node/ocean/interfaces/Compute'
import { Asset } from '@oceanprotocol/lib'
import {
Asset,
ServiceComputeOptions,
PublisherTrustedAlgorithm,
getHash
} from '@oceanprotocol/lib'
import { CancelToken } from 'axios'
import { gql } from 'urql'
import { queryMetadata, getFilterTerm, generateBaseQuery } from './aquarius'
import {
queryMetadata,
getFilterTerm,
generateBaseQuery,
retrieveDDOListByDIDs
} from './aquarius'
import { fetchDataForMultipleChains } from './subgraph'
const getComputeOrders = gql`
@ -258,37 +268,50 @@ function getServiceEndpoints(data: TokenOrder[], assets: Asset[]): string[] {
// return computeResult
// }
// export async function createTrustedAlgorithmList(
// selectedAlgorithms: string[], // list of DIDs
// ocean: Ocean
// ): Promise<PublisherTrustedAlgorithm[]> {
// const trustedAlgorithms = []
export async function createTrustedAlgorithmList(
selectedAlgorithms: string[], // list of DIDs,
assetChainId: number,
cancelToken: CancelToken
): Promise<PublisherTrustedAlgorithm[]> {
const trustedAlgorithms: PublisherTrustedAlgorithm[] = []
// for (const selectedAlgorithm of selectedAlgorithms) {
// const trustedAlgorithm =
// await ocean.compute.createPublisherTrustedAlgorithmfromDID(
// selectedAlgorithm
// )
// trustedAlgorithms.push(trustedAlgorithm)
// }
// return trustedAlgorithms
// }
const selectedAssets = await retrieveDDOListByDIDs(
selectedAlgorithms,
[assetChainId],
cancelToken
)
// export async function transformComputeFormToServiceComputePrivacy(
// values: ComputePrivacyForm,
// ocean: Ocean
// ): Promise<ServiceComputePrivacy> {
// const { allowAllPublishedAlgorithms } = values
// const publisherTrustedAlgorithms = values.allowAllPublishedAlgorithms
// ? []
// : await createTrustedAlgorithmList(values.publisherTrustedAlgorithms, ocean)
for (const selectedAlgorithm of selectedAssets) {
const trustedAlgorithm = {
did: selectedAlgorithm.id,
containerSectionChecksum: getHash(
JSON.stringify(selectedAlgorithm.metadata.algorithm.container)
),
filesChecksum: getHash(selectedAlgorithm.services[0].files)
}
trustedAlgorithms.push(trustedAlgorithm)
}
return trustedAlgorithms
}
// const privacy: ServiceComputePrivacy = {
// allowNetworkAccess: false,
// allowRawAlgorithm: false,
// allowAllPublishedAlgorithms,
// publisherTrustedAlgorithms
// }
export async function transformComputeFormToServiceComputeOptions(
values: ComputePrivacyForm,
currentOptions: ServiceComputeOptions,
assetChainId: number,
cancelToken: CancelToken
): Promise<ServiceComputeOptions> {
const publisherTrustedAlgorithms = values.allowAllPublishedAlgorithms
? []
: await createTrustedAlgorithmList(
values.publisherTrustedAlgorithms,
assetChainId,
cancelToken
)
// return privacy
// }
const privacy: ServiceComputeOptions = {
...currentOptions,
publisherTrustedAlgorithms
}
return privacy
}

48
src/@utils/dispenser.ts Normal file
View File

@ -0,0 +1,48 @@
import { LoggerInstance, Dispenser, Datatoken } from '@oceanprotocol/lib'
import Web3 from 'web3'
import { TransactionReceipt } from 'web3-core'
export async function setMinterToPublisher(
web3: Web3,
dispenserAddress: string,
datatokenAddress: string,
accountId: string,
setError: (msg: string) => void
): Promise<TransactionReceipt> {
const dispenserInstance = new Dispenser(web3, dispenserAddress)
const status = await dispenserInstance.status(datatokenAddress)
if (!status?.active) return
const datatokenInstance = new Datatoken(web3)
const response = await datatokenInstance.removeMinter(
datatokenAddress,
accountId,
accountId
)
if (!response) {
setError('Updating DDO failed.')
LoggerInstance.error('Failed at cancelMinter')
}
return response
}
export async function setMinterToDispenser(
web3: Web3,
datatokenAddress: string,
accountId: string,
setError: (msg: string) => void
): Promise<TransactionReceipt> {
const datatokenInstance = new Datatoken(web3)
const response = await datatokenInstance.addMinter(
datatokenAddress,
accountId,
accountId
)
if (!response) {
setError('Updating DDO failed.')
LoggerInstance.error('Failed at makeMinter')
}
return response
}

View File

@ -1,4 +1,14 @@
import { SvgWaves } from './SvgWaves'
import {
Asset,
LoggerInstance,
getHash,
Nft,
ProviderInstance,
DDO
} from '@oceanprotocol/lib'
import Web3 from 'web3'
import { TransactionReceipt } from 'web3-core'
// https://docs.opensea.io/docs/metadata-standards
export interface NftMetadata {
@ -71,3 +81,50 @@ export function generateNftCreateData(nftMetadata: NftMetadata): any {
return nftCreateData
}
export async function setNftMetadata(
asset: Asset | DDO,
accountId: string,
web3: Web3,
signal: AbortSignal
): Promise<TransactionReceipt> {
const encryptedDdo = await ProviderInstance.encrypt(
asset,
asset.services[0].serviceEndpoint,
signal
)
LoggerInstance.log('[setNftMetadata] Got encrypted DDO', encryptedDdo)
const metadataHash = getHash(JSON.stringify(asset))
const nft = new Nft(web3)
// theoretically used by aquarius or provider, not implemented yet, will remain hardcoded
const flags = '0x2'
const estGasSetMetadata = await nft.estGasSetMetadata(
asset.nftAddress,
accountId,
0,
asset.services[0].serviceEndpoint,
'',
flags,
encryptedDdo,
'0x' + metadataHash,
[]
)
console.log('[setNftMetadata] est Gas set metadata --', estGasSetMetadata)
const setMetadataTx = await nft.setMetadata(
asset.nftAddress,
accountId,
0,
asset.services[0].serviceEndpoint,
'',
flags,
encryptedDdo,
'0x' + metadataHash
)
return setMetadataTx
}

View File

@ -1,4 +1,4 @@
import React, { ReactElement, useState } from 'react'
import React, { ReactElement, useCallback, useEffect, useState } from 'react'
import { useField, useFormikContext } from 'formik'
import { toast } from 'react-toastify'
import FileInfo from './Info'
@ -13,24 +13,43 @@ export default function FilesInput(props: InputProps): ReactElement {
const [isLoading, setIsLoading] = useState(false)
const { values } = useFormikContext<FormPublishData>()
function loadFileInfo(url: string) {
const providerUri = values.services[0].providerUrl.url
const loadFileInfo = useCallback(
(url: string) => {
const providerUri =
(values.services && values.services[0].providerUrl.url) ||
'https://provider.mainnet.oceanprotocol.com'
async function validateUrl() {
try {
setIsLoading(true)
const checkedFile = await getFileUrlInfo(url, providerUri)
checkedFile && helpers.setValue([{ url, ...checkedFile[0] }])
} catch (error) {
toast.error('Could not fetch file info. Please check URL and try again')
console.error(error.message)
} finally {
setIsLoading(false)
async function validateUrl() {
try {
setIsLoading(true)
const checkedFile = await getFileUrlInfo(url, providerUri)
checkedFile && helpers.setValue([{ url, ...checkedFile[0] }])
} catch (error) {
toast.error(
'Could not fetch file info. Please check URL and try again'
)
console.error(error.message)
} finally {
setIsLoading(false)
}
}
}
validateUrl()
}
validateUrl()
},
[helpers, values.services]
)
useEffect(() => {
// try load from initial values, kinda hacky but it works
if (
props.value &&
props.value.length > 0 &&
typeof props.value[0] === 'string'
) {
console.log('loadFileInfo eff')
loadFileInfo(props.value[0].toString())
}
}, [loadFileInfo, props])
async function handleButtonClick(e: React.SyntheticEvent, url: string) {
// File example 'https://oceanprotocol.com/tech-whitepaper.pdf'

View File

@ -17,8 +17,7 @@ import { useWeb3 } from '@context/Web3'
import {
generateBaseQuery,
getFilterTerm,
queryMetadata,
transformDDOToAssetSelection
queryMetadata
} from '@utils/aquarius'
import { Formik } from 'formik'
import { getInitialValues, validationSchema } from './_constants'
@ -37,6 +36,7 @@ import { useIsMounted } from '@hooks/useIsMounted'
import { SortTermOptions } from '../../../../@types/aquarius/SearchQuery'
import { getAccessDetails } from '@utils/accessDetailsAndPricing'
import { AccessDetails } from 'src/@types/Price'
import { transformAssetToAssetSelection } from '@utils/assetConvertor'
export default function Compute({
ddo,
@ -158,11 +158,10 @@ export default function Compute({
)
setDdoAlgorithmList(gueryResults.results)
algorithmSelectionList = await transformDDOToAssetSelection(
algorithmSelectionList = await transformAssetToAssetSelection(
computeService?.serviceEndpoint,
gueryResults.results,
[],
newCancelToken()
[]
)
}
return algorithmSelectionList

View File

@ -1,4 +1,5 @@
import React, { ReactElement } from 'react'
import React, { ReactElement, useState, useEffect } from 'react'
import Link from 'next/link'
import Markdown from '@shared/Markdown'
import MetaFull from './MetaFull'
import MetaSecondary from './MetaSecondary'
@ -14,6 +15,7 @@ import styles from './index.module.css'
import NetworkName from '@shared/NetworkName'
import content from '../../../../content/purgatory.json'
import { AssetExtended } from 'src/@types/AssetExtended'
import { useWeb3 } from '@context/Web3'
export default function AssetContent({
asset
@ -21,7 +23,16 @@ export default function AssetContent({
asset: AssetExtended
}): ReactElement {
const { debug } = useUserPreferences()
const { isInPurgatory, purgatoryData } = useAsset()
const [isOwner, setIsOwner] = useState(false)
const { accountId } = useWeb3()
const { isInPurgatory, purgatoryData, owner, isAssetNetwork } = useAsset()
useEffect(() => {
if (!accountId || !owner) return
const isOwner = accountId.toLowerCase() === owner.toLowerCase()
setIsOwner(isOwner)
}, [accountId, owner, asset])
return (
<>
@ -62,35 +73,13 @@ export default function AssetContent({
<div className={styles.actions}>
<AssetActions asset={asset} />
{/*
TODO: restore edit actions, ideally put edit screens on new page
with own URL instead of switching out AssetContent in place.
Simple way would be modal usage
*/}
{/* {isOwner && isAssetNetwork && (
{isOwner && isAssetNetwork && (
<div className={styles.ownerActions}>
<Button
style="text"
size="small"
onClick={handleEditButton}
>
Edit Metadata
</Button>
{serviceCompute && ddo?.metadata.type === 'dataset' && (
<>
<span className={styles.separator}>|</span>
<Button
style="text"
size="small"
onClick={handleEditComputeButton}
>
Edit Compute Settings
</Button>
</>
)}
<Link href={`/asset/${asset?.id}/edit`}>
<a>Edit</a>
</Link>
</div>
)} */}
)}
</div>
</article>
</>

View File

@ -2,24 +2,32 @@ import { Asset, ServiceComputeOptions } from '@oceanprotocol/lib'
import React, { ReactElement, useEffect, useState } from 'react'
// import { transformComputeFormToServiceComputePrivacy } from '@utils/compute'
import DebugOutput from '@shared/DebugOutput'
import { useCancelToken } from '@hooks/useCancelToken'
import { transformComputeFormToServiceComputeOptions } from '@utils/compute'
export default function DebugEditCompute({
values,
ddo
asset
}: {
values: ComputePrivacyForm
ddo: Asset
asset: Asset
}): ReactElement {
const [formTransformed, setFormTransformed] =
useState<ServiceComputeOptions>()
const newCancelToken = useCancelToken()
useEffect(() => {
// async function transformValues() {
// const privacy = await transformComputeFormToServiceComputePrivacy(values)
// setFormTransformed(privacy)
// }
// transformValues()
}, [values, ddo])
async function transformValues() {
const privacy = await transformComputeFormToServiceComputeOptions(
values,
asset.services[0].compute,
asset.chainId,
newCancelToken()
)
setFormTransformed(privacy)
}
transformValues()
}, [values, asset])
return (
<>

View File

@ -0,0 +1,39 @@
import { Asset, Metadata, Service } from '@oceanprotocol/lib'
import React, { ReactElement } from 'react'
import DebugOutput from '@shared/DebugOutput'
import { MetadataEditForm } from './_types'
import { mapTimeoutStringToSeconds } from '@utils/ddo'
export default function DebugEditMetadata({
values,
asset
}: {
values: Partial<MetadataEditForm>
asset: Asset
}): ReactElement {
const linksTransformed = values.links?.length &&
values.links[0].valid && [values.links[0].url.replace('javascript:', '')]
const newMetadata: Metadata = {
...asset.metadata,
name: values.name,
description: values.description,
links: linksTransformed,
author: values.author
}
const updatedService: Service = {
...asset.services[0],
timeout: mapTimeoutStringToSeconds(values.timeout)
}
const updatedAsset: Asset = {
...asset,
metadata: newMetadata,
services: [updatedService]
}
return (
<>
<DebugOutput title="Collected Form Values" output={values} />
<DebugOutput title="Transformed Asset Values" output={updatedAsset} />
</>
)
}

View File

@ -1,95 +1,131 @@
import { useWeb3 } from '@context/Web3'
import { Formik } from 'formik'
import React, { ReactElement, useState } from 'react'
import { useAsset } from '@context/Asset'
import FormEditComputeDataset from './FormEditComputeDataset'
import { LoggerInstance, ServiceComputeOptions } from '@oceanprotocol/lib'
import {
LoggerInstance,
ServiceComputeOptions,
Service,
ProviderInstance,
getHash,
Nft,
Asset
} from '@oceanprotocol/lib'
import { useUserPreferences } from '@context/UserPreferences'
import DebugEditCompute from './DebugEditCompute'
import styles from './index.module.css'
// import { transformComputeFormToServiceComputePrivacy } from '@utils/compute'
import Web3Feedback from '@shared/Web3Feedback'
import { getInitialValues, validationSchema } from './_constants'
import { useCancelToken } from '@hooks/useCancelToken'
import {
getComputeSettingsInitialValues,
computeSettingsValidationSchema
} from './_constants'
import content from '../../../../content/pages/editComputeDataset.json'
import { AssetExtended } from 'src/@types/AssetExtended'
import { getServiceByName } from '@utils/ddo'
import { setMinterToPublisher, setMinterToDispenser } from '@utils/dispenser'
import { transformComputeFormToServiceComputeOptions } from '@utils/compute'
import { useAbortController } from '@hooks/useAbortController'
import DebugEditCompute from './DebugEditCompute'
import { useAsset } from '@context/Asset'
import EditFeedback from './EditFeedback'
import { setNftMetadata } from '@utils/nft'
export default function EditComputeDataset({
setShowEdit
asset
}: {
setShowEdit: (show: boolean) => void
asset: AssetExtended
}): ReactElement {
const { debug } = useUserPreferences()
const { accountId } = useWeb3()
const { asset, isAssetNetwork, fetchAsset } = useAsset()
const { accountId, web3 } = useWeb3()
const { fetchAsset, isAssetNetwork } = useAsset()
const [success, setSuccess] = useState<string>()
const [error, setError] = useState<string>()
const newAbortController = useAbortController()
const newCancelToken = useCancelToken()
const hasFeedback = error || success
async function handleSubmit(
values: ComputePrivacyForm,
resetForm: () => void
) {
// try {
// if (price.type === 'free') {
// const tx = await setMinterToPublisher(
// ocean,
// ddo.services[0].datatokenAddress,
// accountId,
// setError
// )
// if (!tx) return
// }
// const privacy = await transformComputeFormToServiceComputePrivacy(
// values,
// ocean
// )
// const ddoEditedComputePrivacy = await ocean.compute.editComputePrivacy(
// ddo,
// 1,
// privacy as ServiceComputePrivacy
// )
// if (!ddoEditedComputePrivacy) {
// setError(content.form.error)
// LoggerInstance.error(content.form.error)
// return
// }
// const storedddo = await ocean.assets.updateMetadata(
// ddoEditedComputePrivacy,
// accountId
// )
// if (!storedddo) {
// setError(content.form.error)
// LoggerInstance.error(content.form.error)
// return
// } else {
// if (price.type === 'free') {
// const tx = await setMinterToDispenser(
// ocean,
// ddo.services[0].datatokenAddress,
// accountId,
// setError
// )
// if (!tx) return
// }
// // Edit succeeded
// setSuccess(content.form.success)
// resetForm()
// }
// } catch (error) {
// LoggerInstance.error(error.message)
// setError(error.message)
// }
try {
if (asset?.accessDetails?.type === 'free') {
const tx = await setMinterToPublisher(
web3,
asset?.accessDetails?.addressOrId,
asset?.accessDetails?.datatoken?.address,
accountId,
setError
)
if (!tx) return
}
const newComputeSettings: ServiceComputeOptions =
await transformComputeFormToServiceComputeOptions(
values,
asset.services[0].compute,
asset.chainId,
newCancelToken()
)
LoggerInstance.log(
'[edit compute settings] newComputeSettings',
newComputeSettings
)
const updatedService: Service = {
...asset.services[0],
compute: newComputeSettings
}
LoggerInstance.log(
'[edit compute settings] updatedService',
updatedService
)
const updatedAsset: Asset = {
...asset,
services: [updatedService]
}
const setMetadataTx = await setNftMetadata(
updatedAsset,
accountId,
web3,
newAbortController()
)
LoggerInstance.log('[edit] setMetadata result', setMetadataTx)
if (!setMetadataTx) {
setError(content.form.error)
LoggerInstance.error(content.form.error)
return
} else {
if (asset.accessDetails.type === 'free') {
const tx = await setMinterToDispenser(
web3,
asset?.accessDetails?.datatoken?.address,
accountId,
setError
)
if (!tx) return
}
}
// Edit succeeded
setSuccess(content.form.success)
resetForm()
} catch (error) {
LoggerInstance.error(error.message)
setError(error.message)
}
}
return (
<Formik
initialValues={
{}
// getInitialValues(
// ddo.findServiceByType('compute').attributes.main.privacy
// )
}
validationSchema={validationSchema}
initialValues={getComputeSettingsInitialValues(
getServiceByName(asset, 'compute')?.compute
)}
validationSchema={computeSettingsValidationSchema}
onSubmit={async (values, { resetForm }) => {
// move user's focus to top of screen
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' })
@ -99,15 +135,26 @@ export default function EditComputeDataset({
>
{({ values, isSubmitting }) =>
isSubmitting || hasFeedback ? (
<div />
<EditFeedback
title="Updating Data Set"
error={error}
success={success}
setError={setError}
successAction={{
name: 'View Asset',
onClick: async () => {
await fetchAsset()
},
to: `/asset/${asset.id}`
}}
/>
) : (
<>
<p className={styles.description}>{content.description}</p>
<article className={styles.grid}>
<article>
<FormEditComputeDataset
title={content.form.title}
data={content.form.data}
setShowEdit={setShowEdit}
/>
</article>
<Web3Feedback
@ -116,7 +163,7 @@ export default function EditComputeDataset({
/>
{debug === true && (
<div className={styles.grid}>
{/* <DebugEditCompute values={values} ddo={ddo} /> */}
<DebugEditCompute values={values} asset={asset} />
</div>
)}
</>

View File

@ -0,0 +1,43 @@
.feedback {
width: 100%;
min-height: 40vh;
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
text-align: center;
}
.box {
composes: box from '@shared/atoms/Box.module.css';
width: 100%;
}
.feedback h3 {
font-size: var(--font-size-large);
text-align: center;
margin-bottom: calc(var(--spacer) / 2);
}
.feedback h3 + div {
text-align: left;
}
@media (min-width: 40rem) {
.feedback {
max-width: 30rem;
margin: 0 auto;
}
}
.feedback [class*='loaderWrap'] {
justify-content: center;
text-align: center;
}
.action {
margin-top: calc(var(--spacer) / 1.5);
}
.moreInfo {
padding: calc(var(--spacer) / 4) calc(var(--spacer) / 2) !important;
}

View File

@ -0,0 +1,94 @@
import Alert from '@shared/atoms/Alert'
import Button from '@shared/atoms/Button'
import Loader from '@shared/atoms/Loader'
import SuccessConfetti from '@shared/SuccessConfetti'
import React, { ReactElement, useState, FormEvent } from 'react'
import styles from './EditFeedback.module.css'
interface Action {
name: string
onClick?: () => void
to?: string
}
function ActionSuccess({ action }: { action: Action }) {
const { name, onClick, to } = action
return (
<Button
style="primary"
size="small"
onClick={onClick || null}
to={to || null}
className={styles.action}
>
{name}
</Button>
)
}
function ActionError({ setError }: { setError: (error: string) => void }) {
return (
<Button
style="primary"
size="small"
className={styles.action}
onClick={() => setError(undefined)}
>
Try Again
</Button>
)
}
export default function EditFeedback({
title,
error,
success,
loading,
successAction,
setError
}: {
title: string
error: string
success: string
loading?: string
successAction: Action
setError: (error: string) => void
}): ReactElement {
const [moreInfo, setMoreInfo] = useState<boolean>(false)
function toggleMoreInfo(e: FormEvent<Element>) {
e.preventDefault()
moreInfo === true ? setMoreInfo(false) : setMoreInfo(true)
}
return (
<div className={styles.feedback}>
<div className={styles.box}>
<h3>{title}</h3>
{error ? (
<>
<p>Sorry, something went wrong. Please try again.</p>
{moreInfo && <Alert text={error} state="error" />}
<Button
style="text"
size="small"
onClick={toggleMoreInfo}
className={styles.moreInfo}
>
{moreInfo === false ? 'More Info' : 'Hide error'}
</Button>
<ActionError setError={setError} />
</>
) : success ? (
<SuccessConfetti
success={success}
action={<ActionSuccess action={successAction} />}
/>
) : (
<Loader message={loading} />
)}
</div>
</div>
)
}

View File

@ -0,0 +1,178 @@
import React, { ReactElement, useState } from 'react'
import { Formik } from 'formik'
import {
LoggerInstance,
Metadata,
FixedRateExchange,
Asset,
Service
} from '@oceanprotocol/lib'
import { validationSchema, getInitialValues } from './_constants'
import { MetadataEditForm } from './_types'
import { useWeb3 } from '@context/Web3'
import { useUserPreferences } from '@context/UserPreferences'
import Web3Feedback from '@shared/Web3Feedback'
import FormEditMetadata from './FormEditMetadata'
import { mapTimeoutStringToSeconds } from '@utils/ddo'
import styles from './index.module.css'
import content from '../../../../content/pages/edit.json'
import { AssetExtended } from 'src/@types/AssetExtended'
import { setMinterToPublisher, setMinterToDispenser } from '@utils/dispenser'
import { useAbortController } from '@hooks/useAbortController'
import DebugEditMetadata from './DebugEditMetadata'
import { getOceanConfig } from '@utils/ocean'
import EditFeedback from './EditFeedback'
import { useAsset } from '@context/Asset'
import { setNftMetadata } from '@utils/nft'
export default function Edit({
asset
}: {
asset: AssetExtended
}): ReactElement {
const { debug } = useUserPreferences()
const { fetchAsset, isAssetNetwork } = useAsset()
const { accountId, web3 } = useWeb3()
const newAbortController = useAbortController()
const [success, setSuccess] = useState<string>()
const [error, setError] = useState<string>()
const [timeoutStringValue, setTimeoutStringValue] = useState<string>()
const isComputeType = asset?.services[0]?.type === 'compute'
const hasFeedback = error || success
async function updateFixedPrice(newPrice: string) {
const config = getOceanConfig(asset.chainId)
const fixedRateInstance = new FixedRateExchange(
web3,
config.fixedRateExchangeAddress
)
const setPriceResp = await fixedRateInstance.setRate(
accountId,
asset.accessDetails.addressOrId,
newPrice
)
LoggerInstance.log('[edit] setFixedRate result', setPriceResp)
if (!setPriceResp) {
setError(content.form.error)
LoggerInstance.error(content.form.error)
}
}
async function handleSubmit(
values: Partial<MetadataEditForm>,
resetForm: () => void
) {
try {
const linksTransformed = values.links?.length &&
values.links[0].valid && [
values.links[0].url.replace('javascript:', '')
]
const updatedMetadata: Metadata = {
...asset.metadata,
name: values.name,
description: values.description,
links: linksTransformed,
author: values.author
}
asset?.accessDetails?.type === 'fixed' &&
values.price !== asset.accessDetails.price &&
(await updateFixedPrice(values.price))
const updatedService: Service = {
...asset.services[0],
timeout: mapTimeoutStringToSeconds(values.timeout)
}
const updatedAsset: Asset = {
...asset,
metadata: updatedMetadata,
services: [updatedService]
}
const setMetadataTx = await setNftMetadata(
updatedAsset,
accountId,
web3,
newAbortController()
)
LoggerInstance.log('[edit] setMetadata result', setMetadataTx)
if (!setMetadataTx) {
setError(content.form.error)
LoggerInstance.error(content.form.error)
return
}
// Edit succeeded
setSuccess(content.form.success)
resetForm()
} catch (error) {
LoggerInstance.error(error.message)
setError(error.message)
}
}
return (
<Formik
initialValues={getInitialValues(
asset?.metadata,
asset?.services[0]?.timeout,
asset?.accessDetails?.price
)}
validationSchema={validationSchema}
onSubmit={async (values, { resetForm }) => {
// move user's focus to top of screen
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' })
// kick off editing
await handleSubmit(values, resetForm)
}}
>
{({ isSubmitting, values, initialValues }) =>
isSubmitting || hasFeedback ? (
<EditFeedback
title="Updating Data Set"
error={error}
success={success}
setError={setError}
successAction={{
name: 'View Asset',
onClick: async () => {
await fetchAsset()
},
to: `/asset/${asset.id}`
}}
/>
) : (
<>
<p className={styles.description}>{content.description}</p>
<article>
<FormEditMetadata
data={content.form.data}
setTimeoutStringValue={setTimeoutStringValue}
values={initialValues}
showPrice={asset?.accessDetails?.type === 'fixed'}
isComputeDataset={isComputeType}
/>
<aside>
<Web3Feedback
networkId={asset?.chainId}
isAssetNetwork={isAssetNetwork}
/>
</aside>
{debug === true && (
<div className={styles.grid}>
<DebugEditMetadata values={values} asset={asset} />
</div>
)}
</article>
</>
)
}
</Formik>
)
}

View File

@ -3,12 +3,11 @@ import { Field, Form, FormikContextType, useFormikContext } from 'formik'
import Input, { InputProps } from '@shared/FormInput'
import { AssetSelectionAsset } from '@shared/FormFields/AssetSelection'
import stylesIndex from './index.module.css'
import styles from './FormEditMetadata.module.css'
import styles from './FormEdit.module.css'
import {
generateBaseQuery,
getFilterTerm,
queryMetadata,
transformDDOToAssetSelection
queryMetadata
} from '@utils/aquarius'
import { useAsset } from '@context/Asset'
import { PublisherTrustedAlgorithm } from '@oceanprotocol/lib'
@ -17,25 +16,25 @@ import FormActions from './FormActions'
import { useCancelToken } from '@hooks/useCancelToken'
import { SortTermOptions } from '../../../@types/aquarius/SearchQuery'
import { getServiceByName } from '@utils/ddo'
import { transformAssetToAssetSelection } from '@utils/assetConvertor'
export default function FormEditComputeDataset({
data,
title,
setShowEdit
title
}: {
data: InputProps[]
title: string
setShowEdit: (show: boolean) => void
}): ReactElement {
const { appConfig } = useSiteMetadata()
const { asset } = useAsset()
const [showEditCompute, setShowEditCompute] = useState<boolean>()
const { values }: FormikContextType<ComputePrivacyForm> = useFormikContext()
const [allAlgorithms, setAllAlgorithms] = useState<AssetSelectionAsset[]>()
const newCancelToken = useCancelToken()
const { publisherTrustedAlgorithms } = getServiceByName(
asset,
'compute'
).compute
)?.compute
async function getAlgorithmList(
publisherTrustedAlgorithms: PublisherTrustedAlgorithm[]
@ -43,17 +42,16 @@ export default function FormEditComputeDataset({
const baseParams = {
chainIds: [asset.chainId],
sort: { sortBy: SortTermOptions.Created },
filters: [getFilterTerm('service.attributes.main.type', 'algorithm')]
filters: [getFilterTerm('metadata.type', 'algorithm')]
} as BaseQueryParams
const query = generateBaseQuery(baseParams)
const querryResult = await queryMetadata(query, newCancelToken())
const datasetComputeService = getServiceByName(asset, 'compute')
const algorithmSelectionList = await transformDDOToAssetSelection(
const algorithmSelectionList = await transformAssetToAssetSelection(
datasetComputeService?.serviceEndpoint,
querryResult.results,
publisherTrustedAlgorithms,
newCancelToken()
querryResult?.results,
publisherTrustedAlgorithms
)
return algorithmSelectionList
}
@ -85,7 +83,8 @@ export default function FormEditComputeDataset({
/>
))}
<FormActions setShowEdit={setShowEdit} />
{/* <FormActions setShowEdit={setShowEdit} /> */}
<FormActions setShowEdit={setShowEditCompute} />
</Form>
)
}

View File

@ -1,64 +1,75 @@
import React, { ChangeEvent, ReactElement } from 'react'
import React, { ChangeEvent, ReactElement, useState } from 'react'
import { Field, Form, FormikContextType, useFormikContext } from 'formik'
import Input, { InputProps } from '@shared/FormInput'
import FormActions from './FormActions'
import styles from './FormEditMetadata.module.css'
import styles from './FormEdit.module.css'
import { FormPublishData } from '../../Publish/_types'
import { useAsset } from '@context/Asset'
import { MetadataEditForm } from './_types'
export function checkIfTimeoutInPredefinedValues(
timeout: string,
timeoutOptions: string[]
): boolean {
if (timeoutOptions.indexOf(timeout) > -1) {
return true
}
return false
}
function handleTimeoutCustomOption(
data: FormFieldContent[],
values: Partial<FormPublishData>
) {
const timeoutFieldContent = data.filter(
(field) => field.name === 'timeout'
)[0]
const timeoutInputIndex = data.findIndex(
(element) => element.name === 'timeout'
)
if (
data[timeoutInputIndex].options.length < 6 &&
!checkIfTimeoutInPredefinedValues(
values?.services[0]?.timeout,
timeoutFieldContent.options
)
) {
data[timeoutInputIndex].options.push(values?.services[0]?.timeout)
} else if (
data[timeoutInputIndex].options.length === 6 &&
checkIfTimeoutInPredefinedValues(
values?.services[0]?.timeout,
timeoutFieldContent.options
)
) {
data[timeoutInputIndex].options.pop()
} else if (
data[timeoutInputIndex].options.length === 6 &&
data[timeoutInputIndex].options[5] !== values?.services[0]?.timeout
) {
data[timeoutInputIndex].options[5] = values?.services[0]?.timeout
}
}
// function handleTimeoutCustomOption(
// data: FormFieldContent[],
// values: Partial<FormPublishData>
// ) {
// const timeoutFieldContent = data.filter(
// (field) => field.name === 'timeout'
// )[0]
// const timeoutInputIndex = data.findIndex(
// (element) => element.name === 'timeout'
// )
// if (
// data[timeoutInputIndex].options.length < 6 &&
// !checkIfTimeoutInPredefinedValues(
// values.timeout,
// timeoutFieldContent.options
// )
// ) {
// data[timeoutInputIndex].options.push(values.timeout)
// } else if (
// data[timeoutInputIndex].options.length === 6 &&
// checkIfTimeoutInPredefinedValues(
// values.timeout,
// timeoutFieldContent.options
// )
// ) {
// data[timeoutInputIndex].options.pop()
// } else if (
// data[timeoutInputIndex].options.length === 6 &&
// data[timeoutInputIndex].options[5] !== values.timeout
// ) {
// data[timeoutInputIndex].options[5] = values.timeout
// }
// }
export default function FormEditMetadata({
data,
setShowEdit,
setTimeoutStringValue,
values,
showPrice,
isComputeDataset
}: {
data: InputProps[]
setShowEdit: (show: boolean) => void
setTimeoutStringValue: (value: string) => void
values: Partial<FormPublishData>
values: Partial<MetadataEditForm>
showPrice: boolean
isComputeDataset: boolean
}): ReactElement {
const { oceanConfig } = useAsset()
const [showEdit, setShowEdit] = useState<boolean>()
const {
validateField,
setFieldValue
}: FormikContextType<Partial<FormPublishData>> = useFormikContext()
}: FormikContextType<Partial<MetadataEditForm>> = useFormikContext()
// Manually handle change events instead of using `handleChange` from Formik.
// Workaround for default `validateOnChange` not kicking in
@ -78,12 +89,12 @@ export default function FormEditMetadata({
(field) => field.name === 'timeout'
)[0].options
// if (isComputeDataset && timeoutOptionsArray.includes('Forever')) {
// const foreverOptionIndex = timeoutOptionsArray.indexOf('Forever')
// timeoutOptionsArray.splice(foreverOptionIndex, 1)
// } else if (!isComputeDataset && !timeoutOptionsArray.includes('Forever')) {
// timeoutOptionsArray.push('Forever')
// }
if (isComputeDataset && timeoutOptionsArray.includes('Forever')) {
const foreverOptionIndex = timeoutOptionsArray.indexOf('Forever')
timeoutOptionsArray.splice(foreverOptionIndex, 1)
} else if (!isComputeDataset && !timeoutOptionsArray.includes('Forever')) {
timeoutOptionsArray.push('Forever')
}
return (
<Form className={styles.form}>
@ -107,10 +118,10 @@ export default function FormEditMetadata({
)
)}
{/* <FormActions
<FormActions
setShowEdit={setShowEdit}
handleClick={() => setTimeoutStringValue(values.timeout)}
/> */}
// handleClick={() => setTimeoutStringValue(values?.services[0]?.timeout)}
/>
</Form>
)
}

View File

@ -1,6 +1,5 @@
import { Metadata } from '@oceanprotocol/lib'
import { Metadata, ServiceComputeOptions } from '@oceanprotocol/lib'
import { mapTimeoutStringToSeconds, secondsToString } from '@utils/ddo'
// import { EditableMetadataLinks } from '@oceanprotocol/lib'
import * as Yup from 'yup'
import { MetadataEditForm } from './_types'
@ -18,35 +17,41 @@ export const validationSchema = Yup.object().shape({
export function getInitialValues(
metadata: Metadata,
timeout: number,
price: number
price: string
): Partial<MetadataEditForm> {
return {
name: metadata.name,
description: metadata.description,
name: metadata?.name,
description: metadata?.description,
price,
timeout,
author: metadata.author
links: metadata?.links,
timeout: secondsToString(timeout),
author: metadata?.author
}
}
// export const validationSchema: Yup.SchemaOf<ComputePrivacyForm> =
// Yup.object().shape({
// allowAllPublishedAlgorithms: Yup.boolean().nullable(),
// publisherTrustedAlgorithms: Yup.array().nullable()
// })
export const computeSettingsValidationSchema = Yup.object().shape({
allowAllPublishedAlgorithms: Yup.boolean().nullable(),
publisherTrustedAlgorithms: Yup.array().nullable()
})
// export function getInitialValues(
// compute: ServiceComputePrivacy
// ): ComputePrivacyForm {
// // TODO: ocean.js needs allowAllAlgoritms setting
// const { allowAllPublishedAlgorithms, publisherTrustedAlgorithms } = compute
export function getComputeSettingsInitialValues(
compute: ServiceComputeOptions
): ComputePrivacyForm {
const { publisherTrustedAlgorithmPublishers, publisherTrustedAlgorithms } =
compute
const allowAllPublishedAlgorithms = !(
publisherTrustedAlgorithms?.length > 0 ||
publisherTrustedAlgorithmPublishers?.length > 0
)
// const publisherTrustedAlgorithmsForForm = (
// publisherTrustedAlgorithms || []
// ).map((algo) => algo.did)
const publisherTrustedAlgorithmsForForm = (
publisherTrustedAlgorithms || []
).map((algo) => algo.did)
// return {
// allowAllPublishedAlgorithms,
// publisherTrustedAlgorithms: publisherTrustedAlgorithmsForForm
// }
// }
// TODO: should we add publisherTrustedAlgorithmPublishers to the form?
return {
allowAllPublishedAlgorithms,
publisherTrustedAlgorithms: publisherTrustedAlgorithmsForForm
}
}

View File

@ -3,8 +3,8 @@
export interface MetadataEditForm {
name: string
description: string
timeout: number
price?: number
timeout: string
price?: string
links?: string | any[]
author?: string
}

View File

@ -1,12 +1,37 @@
.edit ul > li[class*='Tabs_tab'] {
padding: calc(var(--spacer) / 4) var(--spacer);
}
.edit [class*='Tabs_tabContent'] {
padding-left: 0;
padding-right: 0;
padding-top: 0;
}
.grid {
composes: grid from '../../AssetContent/index.module.css';
margin-top: var(--spacer);
display: grid;
gap: calc(var(--spacer) * 1.5);
position: relative;
margin-top: -1rem;
}
.grid > div {
overflow: hidden;
}
.contianer {
composes: box from '@shared/atoms/Box.module.css';
position: relative;
}
@media (min-width: 60rem) {
.grid {
grid-template-columns: 1.5fr 1fr;
}
}
.description {
font-size: var(--font-size-large);
margin-top: -1.5rem;
max-width: 50rem;
}
.title {

View File

@ -1,161 +1,73 @@
import { Formik } from 'formik'
import React, { ReactElement, useState } from 'react'
import { validationSchema, getInitialValues } from './_constants'
import { useAsset } from '@context/Asset'
import { useUserPreferences } from '@context/UserPreferences'
// import Debug from './DebugEditMetadata'
import Web3Feedback from '@shared/Web3Feedback'
import FormEditMetadata from './FormEditMetadata'
import { getServiceByName, mapTimeoutStringToSeconds } from '@utils/ddo'
import styles from './index.module.css'
import React, { ReactElement, useState, useEffect } from 'react'
import { LoggerInstance } from '@oceanprotocol/lib'
import { useAsset } from '@context/Asset'
import styles from './index.module.css'
import Tabs from '@shared/atoms/Tabs'
import EditMetadata from './EditMetadata'
import EditComputeDataset from './EditComputeDataset'
import Page from '@shared/Page'
import Loader from '@shared/atoms/Loader'
import { useWeb3 } from '@context/Web3'
import content from '../../../../content/pages/edit.json'
import { MetadataEditForm } from './_types'
import Alert from '@shared/atoms/Alert'
export default function Edit({
setShowEdit,
isComputeType
}: {
setShowEdit: (show: boolean) => void
isComputeType?: boolean
}): ReactElement {
const { debug } = useUserPreferences()
export default function Edit({ uri }: { uri: string }): ReactElement {
const { asset, error, loading, owner } = useAsset()
const [isCompute, setIsCompute] = useState(false)
const [isOnwer, setIsOwner] = useState(false)
const { accountId } = useWeb3()
const { asset, fetchAsset } = useAsset()
const [success, setSuccess] = useState<string>()
const [error, setError] = useState<string>()
const [timeoutStringValue, setTimeoutStringValue] = useState<string>()
const { timeout } = asset.services[0]
const hasFeedback = error || success
async function updateFixedPrice(newPrice: number) {
// const setPriceResp = await ocean.fixedRateExchange.setRate(
// price.address,
// newPrice,
// accountId
// )
// if (!setPriceResp) {
// setError(content.form.error)
// LoggerInstance.error(content.form.error)
// }
// Switch type value upon tab change
function handleTabChange(tabName: string) {
LoggerInstance.log('switched to tab', tabName)
// add store restore from
}
async function handleSubmit(
values: Partial<MetadataEditForm>,
resetForm: () => void
) {
// try {
// if (price.type === 'free') {
// const tx = await setMinterToPublisher(
// ocean,
// ddo.services[0].datatokenAddress,
// accountId,
// setError
// )
// if (!tx) return
// }
// // Construct new DDO with new values
// const ddoEditedMetdata = await ocean.assets.editMetadata(ddo as any, {
// title: values.name,
// description: values.description,
// links: typeof values.links !== 'string' ? values.links : [],
// author: values.author === '' ? ' ' : values.author
// })
// price.type === 'exchange' &&
// values.price !== price.value &&
// (await updateFixedPrice(values.price))
// if (!ddoEditedMetdata) {
// setError(content.form.error)
// LoggerInstance.error(content.form.error)
// return
// }
// let ddoEditedTimeout = ddoEditedMetdata
// if (timeoutStringValue !== values.timeout) {
// const service =
// getServiceByName(ddoEditedMetdata, 'access') ||
// getServiceByName(ddoEditedMetdata, 'compute')
// const timeout = mapTimeoutStringToSeconds(values.timeout)
// ddoEditedTimeout = await ocean.assets.editServiceTimeout(
// ddoEditedMetdata,
// service.index,
// timeout
// )
// }
// if (!ddoEditedTimeout) {
// setError(content.form.error)
// LoggerInstance.error(content.form.error)
// return
// }
// const storedddo = await ocean.assets.updateMetadata(
// ddoEditedTimeout,
// accountId
// )
// if (!storedddo) {
// setError(content.form.error)
// LoggerInstance.error(content.form.error)
// return
// } else {
// if (price.type === 'free') {
// const tx = await setMinterToDispenser(
// ocean,
// ddo.services[0].datatokenAddress,
// accountId,
// setError
// )
// if (!tx) return
// }
// // Edit succeeded
// setSuccess(content.form.success)
// resetForm()
// }
// } catch (error) {
// LoggerInstance.error(error.message)
// setError(error.message)
// }
}
useEffect(() => {
if (!asset || error) {
return
}
setIsCompute(asset?.services[0]?.type === 'compute')
setIsOwner(owner === accountId)
}, [asset, error])
return (
<Formik
initialValues={getInitialValues(
asset.metadata,
timeout,
asset.accessDetails.price
)}
validationSchema={validationSchema}
onSubmit={async (values, { resetForm }) => {
// move user's focus to top of screen
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' })
// kick off editing
await handleSubmit(values, resetForm)
}}
const tabs = [
{
title: 'Edit Metadata',
content: <EditMetadata asset={asset} />
},
{
title: 'Edit Compute Settings',
content: <EditComputeDataset asset={asset} />,
disabled: !isCompute
}
].filter((tab) => tab !== undefined)
return asset && !loading && isOnwer ? (
<Page uri={uri}>
<div className={styles.contianer}>
<Tabs
items={tabs}
handleTabChange={handleTabChange}
defaultIndex={0}
className={styles.edit}
/>
</div>
</Page>
) : !isOnwer ? (
<Page
title="Edit action available only to asset owner"
noPageHeader
uri={uri}
>
{({ isSubmitting, values, initialValues }) =>
isSubmitting || hasFeedback ? (
<div />
) : (
<>
<p className={styles.description}>{content.description}</p>
<article className={styles.grid}>
{/* <FormEditMetadata
data={content.form.data}
setShowEdit={setShowEdit}
setTimeoutStringValue={setTimeoutStringValue}
// values={initialValues}
showPrice={price.type === 'exchange'}
isComputeDataset={isComputeType}
/> */}
<aside>
<Web3Feedback networkId={asset?.chainId} />
</aside>
{/* {debug === true && <Debug values={values} ddo={ddo} />} */}
</article>
</>
)
}
</Formik>
<Alert
title="Edit action available only to asset owner"
text={error}
state="error"
/>
</Page>
) : (
<Page title={undefined} uri={uri}>
<Loader />
</Page>
)
}

View File

@ -24,6 +24,7 @@ import {
import { getOceanConfig } from '@utils/ocean'
import { validationSchema } from './_validation'
import { useAbortController } from '@hooks/useAbortController'
import { setNftMetadata } from '@utils/nft'
// TODO: restore FormikPersist, add back clear form action
const formName = 'ocean-publish-form'
@ -172,23 +173,11 @@ export default function PublishPage({
if (!_ddo || !_encryptedDdo) throw new Error('No DDO received.')
// TODO: this whole setMetadata needs to go in a function ,too many hardcoded/calculated params
// TODO: hash generation : this needs to be moved in a function (probably on ocean.js) after we figure out what is going on in provider, leave it here for now
const metadataHash = getHash(JSON.stringify(_ddo))
const nft = new Nft(web3)
// theoretically used by aquarius or provider, not implemented yet, will remain hardcoded
const flags = '0x2'
const res = await nft.setMetadata(
_erc721Address,
const res = await setNftMetadata(
_ddo,
accountId,
0,
values.services[0].providerUrl.url,
'',
flags,
_encryptedDdo,
'0x' + metadataHash
web3,
newAbortController()
)
LoggerInstance.log('[publish] setMetadata result', res)

View File

@ -0,0 +1,14 @@
import React, { ReactElement } from 'react'
import { useRouter } from 'next/router'
import EditPage from '../../../components/Asset/Edit'
import AssetProvider from '@context/Asset'
export default function PageEditAsset(): ReactElement {
const router = useRouter()
const { did } = router.query
return (
<AssetProvider did={did as string}>
<EditPage uri={router.pathname} />
</AssetProvider>
)
}

View File

@ -1,6 +1,6 @@
import React, { ReactElement } from 'react'
import { useRouter } from 'next/router'
import PageTemplateAssetDetails from '../../components/Asset'
import PageTemplateAssetDetails from '../../../components/Asset'
import AssetProvider from '@context/Asset'
export default function PageAssetDetails(): ReactElement {