feat: add experimental fdp (#681)
* feat: add experimental fdp * ci: update swarm-actions to v1 * fix: fix eslint violations * refactor: decaf
This commit is contained in:
@@ -70,7 +70,7 @@ jobs:
|
||||
run: npm run build:component
|
||||
|
||||
- name: Create preview
|
||||
uses: ethersphere/swarm-actions/pr-preview@v0
|
||||
uses: ethersphere/swarm-actions/pr-preview@v1
|
||||
continue-on-error: true
|
||||
with:
|
||||
bee-url: https://unlimited.gateway.ethswarm.org
|
||||
@@ -79,7 +79,7 @@ jobs:
|
||||
headers: '${{ secrets.GATEWAY_AUTHORIZATION_HEADER }}'
|
||||
|
||||
- name: Upload to testnet
|
||||
uses: ethersphere/swarm-actions/upload-dir@v0
|
||||
uses: ethersphere/swarm-actions/upload-dir@v1
|
||||
continue-on-error: true
|
||||
with:
|
||||
index-document: index.html
|
||||
|
||||
Generated
+248
-4
@@ -11,6 +11,7 @@
|
||||
"dependencies": {
|
||||
"@ethersphere/bee-js": "^7.1.0",
|
||||
"@ethersphere/swarm-cid": "^0.1.0",
|
||||
"@fairdatasociety/fdp-storage": "^0.19.0",
|
||||
"@material-ui/core": "4.12.3",
|
||||
"@material-ui/icons": "4.11.2",
|
||||
"@material-ui/lab": "4.0.0-alpha.57",
|
||||
@@ -3164,6 +3165,106 @@
|
||||
"@ethersproject/strings": "^5.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@fairdatasociety/fdp-contracts-js": {
|
||||
"version": "3.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@fairdatasociety/fdp-contracts-js/-/fdp-contracts-js-3.12.0.tgz",
|
||||
"integrity": "sha512-pfmRucv40GMGAMfXB8hFDRvdxkY5nX172dQFnWh4vGCS2iRKbz6p78cqnF8Xyu9lYSjtSVEWAnXOk9Yug6X5OQ==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"ethers": ">=5.6.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@fairdatasociety/fdp-storage": {
|
||||
"version": "0.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@fairdatasociety/fdp-storage/-/fdp-storage-0.19.0.tgz",
|
||||
"integrity": "sha512-tN1mosanu4nAxLx+uxuRSdbSV+/HSgAIsakR1jsgJ2Lneycc4i9Yd7but2LFyOQ5okNh6TM5P6S4hlPUpWk/jQ==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@ethersphere/bee-js": "^6.2.0",
|
||||
"@fairdatasociety/fdp-contracts-js": "^3.11.0",
|
||||
"crypto-js": "^4.2.0",
|
||||
"elliptic": "^6.5.4",
|
||||
"ethers": "^5.5.2",
|
||||
"js-sha3": "^0.9.2",
|
||||
"pako": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.0.0",
|
||||
"npm": ">=9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@fairdatasociety/fdp-storage/node_modules/@ethersphere/bee-js": {
|
||||
"version": "6.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@ethersphere/bee-js/-/bee-js-6.9.1.tgz",
|
||||
"integrity": "sha512-aZaoD4Q9BH2jOPU049vIsN3N/RID/CTrXdpMb593PREU9S9PksZkxVPS95sgLWnUsOK1IzW9a8WtkOIjcRZswA==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@ethersphere/swarm-cid": "^0.1.0",
|
||||
"@types/readable-stream": "^2.3.13",
|
||||
"axios": "^0.28.0",
|
||||
"cafe-utility": "^15.0.2",
|
||||
"elliptic": "^6.5.4",
|
||||
"fetch-blob": "2.1.2",
|
||||
"isomorphic-ws": "^4.0.1",
|
||||
"js-sha3": "^0.8.0",
|
||||
"semver": "^7.3.5",
|
||||
"tar-js": "^0.3.0",
|
||||
"web-streams-polyfill": "^4.0.0-beta.3",
|
||||
"ws": "^8.7.0"
|
||||
},
|
||||
"engines": {
|
||||
"bee": "1.18.2-759f56f",
|
||||
"beeApiVersion": "4.0.0",
|
||||
"beeDebugApiVersion": "4.0.0",
|
||||
"node": ">=14.0.0",
|
||||
"npm": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@fairdatasociety/fdp-storage/node_modules/@ethersphere/bee-js/node_modules/js-sha3": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz",
|
||||
"integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@fairdatasociety/fdp-storage/node_modules/cafe-utility": {
|
||||
"version": "15.0.2",
|
||||
"resolved": "https://registry.npmjs.org/cafe-utility/-/cafe-utility-15.0.2.tgz",
|
||||
"integrity": "sha512-TNKSfA/q/XRd86NwYtF5QImQB8U5n/hKZuWblYFgYW4aveHcSg2RGOfR3+xquXRXF7BCeNoAXe2/snWFKviPzw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@fairdatasociety/fdp-storage/node_modules/js-sha3": {
|
||||
"version": "0.9.3",
|
||||
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.9.3.tgz",
|
||||
"integrity": "sha512-BcJPCQeLg6WjEx3FE591wVAevlli8lxsxm9/FzV4HXkV49TmBH38Yvrpce6fjbADGMKFrBMGTqrVz3qPIZ88Gg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@fairdatasociety/fdp-storage/node_modules/pako": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz",
|
||||
"integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==",
|
||||
"license": "(MIT AND Zlib)"
|
||||
},
|
||||
"node_modules/@fairdatasociety/fdp-storage/node_modules/ws": {
|
||||
"version": "8.18.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
|
||||
"integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": ">=5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@humanwhocodes/config-array": {
|
||||
"version": "0.9.5",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz",
|
||||
@@ -4910,8 +5011,7 @@
|
||||
"node_modules/@types/node": {
|
||||
"version": "16.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.6.tgz",
|
||||
"integrity": "sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w==",
|
||||
"dev": true
|
||||
"integrity": "sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w=="
|
||||
},
|
||||
"node_modules/@types/parse-json": {
|
||||
"version": "4.0.0",
|
||||
@@ -5028,6 +5128,16 @@
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
|
||||
"integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
|
||||
},
|
||||
"node_modules/@types/readable-stream": {
|
||||
"version": "2.3.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-2.3.15.tgz",
|
||||
"integrity": "sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"safe-buffer": "~5.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/resolve": {
|
||||
"version": "1.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
|
||||
@@ -7758,6 +7868,12 @@
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/crypto-js": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
|
||||
"integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/crypto-random-string": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
|
||||
@@ -10179,6 +10295,20 @@
|
||||
"pend": "~1.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fetch-blob": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-2.1.2.tgz",
|
||||
"integrity": "sha512-YKqtUDwqLyfyMnmbw8XD6Q8j9i/HggKtPEI+pZ1+8bvheBu78biSmNaXWusx1TauGqtUUGx/cBb1mKdq2rLYow==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^10.17.0 || >=12.3.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"domexception": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/file-entry-cache": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
|
||||
@@ -18754,6 +18884,14 @@
|
||||
"tar-stream": "^2.1.4"
|
||||
}
|
||||
},
|
||||
"node_modules/tar-js": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/tar-js/-/tar-js-0.3.0.tgz",
|
||||
"integrity": "sha512-9uqP2hJUZNKRkwPDe5nXxXdzo6w+BFBPq9x/tyi5/U/DneuSesO/HMb0y5TeWpfcv49YDJTs7SrrZeeu8ZHWDA==",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/tar-stream": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
|
||||
@@ -19603,6 +19741,15 @@
|
||||
"minimalistic-assert": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/web-streams-polyfill": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0.tgz",
|
||||
"integrity": "sha512-0zJXHRAYEjM2tUfZ2DiSOHAa2aw1tisnnhU3ufD57R8iefL+DcdJyRBRyJpG+NUimDgbTI/lH+gAE1PAvV3Cgw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/web-vitals": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-2.1.2.tgz",
|
||||
@@ -22639,6 +22786,75 @@
|
||||
"@ethersproject/strings": "^5.7.0"
|
||||
}
|
||||
},
|
||||
"@fairdatasociety/fdp-contracts-js": {
|
||||
"version": "3.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@fairdatasociety/fdp-contracts-js/-/fdp-contracts-js-3.12.0.tgz",
|
||||
"integrity": "sha512-pfmRucv40GMGAMfXB8hFDRvdxkY5nX172dQFnWh4vGCS2iRKbz6p78cqnF8Xyu9lYSjtSVEWAnXOk9Yug6X5OQ==",
|
||||
"requires": {}
|
||||
},
|
||||
"@fairdatasociety/fdp-storage": {
|
||||
"version": "0.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@fairdatasociety/fdp-storage/-/fdp-storage-0.19.0.tgz",
|
||||
"integrity": "sha512-tN1mosanu4nAxLx+uxuRSdbSV+/HSgAIsakR1jsgJ2Lneycc4i9Yd7but2LFyOQ5okNh6TM5P6S4hlPUpWk/jQ==",
|
||||
"requires": {
|
||||
"@ethersphere/bee-js": "^6.2.0",
|
||||
"@fairdatasociety/fdp-contracts-js": "^3.11.0",
|
||||
"crypto-js": "^4.2.0",
|
||||
"elliptic": "^6.5.4",
|
||||
"ethers": "^5.5.2",
|
||||
"js-sha3": "^0.9.2",
|
||||
"pako": "^2.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ethersphere/bee-js": {
|
||||
"version": "6.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@ethersphere/bee-js/-/bee-js-6.9.1.tgz",
|
||||
"integrity": "sha512-aZaoD4Q9BH2jOPU049vIsN3N/RID/CTrXdpMb593PREU9S9PksZkxVPS95sgLWnUsOK1IzW9a8WtkOIjcRZswA==",
|
||||
"requires": {
|
||||
"@ethersphere/swarm-cid": "^0.1.0",
|
||||
"@types/readable-stream": "^2.3.13",
|
||||
"axios": "^0.28.0",
|
||||
"cafe-utility": "^15.0.2",
|
||||
"elliptic": "^6.5.4",
|
||||
"fetch-blob": "2.1.2",
|
||||
"isomorphic-ws": "^4.0.1",
|
||||
"js-sha3": "^0.8.0",
|
||||
"semver": "^7.3.5",
|
||||
"tar-js": "^0.3.0",
|
||||
"web-streams-polyfill": "^4.0.0-beta.3",
|
||||
"ws": "^8.7.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"js-sha3": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz",
|
||||
"integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"cafe-utility": {
|
||||
"version": "15.0.2",
|
||||
"resolved": "https://registry.npmjs.org/cafe-utility/-/cafe-utility-15.0.2.tgz",
|
||||
"integrity": "sha512-TNKSfA/q/XRd86NwYtF5QImQB8U5n/hKZuWblYFgYW4aveHcSg2RGOfR3+xquXRXF7BCeNoAXe2/snWFKviPzw=="
|
||||
},
|
||||
"js-sha3": {
|
||||
"version": "0.9.3",
|
||||
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.9.3.tgz",
|
||||
"integrity": "sha512-BcJPCQeLg6WjEx3FE591wVAevlli8lxsxm9/FzV4HXkV49TmBH38Yvrpce6fjbADGMKFrBMGTqrVz3qPIZ88Gg=="
|
||||
},
|
||||
"pako": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz",
|
||||
"integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug=="
|
||||
},
|
||||
"ws": {
|
||||
"version": "8.18.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
|
||||
"integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
|
||||
"requires": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@humanwhocodes/config-array": {
|
||||
"version": "0.9.5",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz",
|
||||
@@ -23913,8 +24129,7 @@
|
||||
"@types/node": {
|
||||
"version": "16.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.6.tgz",
|
||||
"integrity": "sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w==",
|
||||
"dev": true
|
||||
"integrity": "sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w=="
|
||||
},
|
||||
"@types/parse-json": {
|
||||
"version": "4.0.0",
|
||||
@@ -24033,6 +24248,15 @@
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/readable-stream": {
|
||||
"version": "2.3.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-2.3.15.tgz",
|
||||
"integrity": "sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ==",
|
||||
"requires": {
|
||||
"@types/node": "*",
|
||||
"safe-buffer": "~5.1.1"
|
||||
}
|
||||
},
|
||||
"@types/resolve": {
|
||||
"version": "1.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
|
||||
@@ -26165,6 +26389,11 @@
|
||||
"randomfill": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"crypto-js": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
|
||||
"integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="
|
||||
},
|
||||
"crypto-random-string": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
|
||||
@@ -27989,6 +28218,11 @@
|
||||
"pend": "~1.2.0"
|
||||
}
|
||||
},
|
||||
"fetch-blob": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-2.1.2.tgz",
|
||||
"integrity": "sha512-YKqtUDwqLyfyMnmbw8XD6Q8j9i/HggKtPEI+pZ1+8bvheBu78biSmNaXWusx1TauGqtUUGx/cBb1mKdq2rLYow=="
|
||||
},
|
||||
"file-entry-cache": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
|
||||
@@ -34331,6 +34565,11 @@
|
||||
"tar-stream": "^2.1.4"
|
||||
}
|
||||
},
|
||||
"tar-js": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/tar-js/-/tar-js-0.3.0.tgz",
|
||||
"integrity": "sha512-9uqP2hJUZNKRkwPDe5nXxXdzo6w+BFBPq9x/tyi5/U/DneuSesO/HMb0y5TeWpfcv49YDJTs7SrrZeeu8ZHWDA=="
|
||||
},
|
||||
"tar-stream": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
|
||||
@@ -34953,6 +35192,11 @@
|
||||
"minimalistic-assert": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"web-streams-polyfill": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0.tgz",
|
||||
"integrity": "sha512-0zJXHRAYEjM2tUfZ2DiSOHAa2aw1tisnnhU3ufD57R8iefL+DcdJyRBRyJpG+NUimDgbTI/lH+gAE1PAvV3Cgw=="
|
||||
},
|
||||
"web-vitals": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-2.1.2.tgz",
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
"dependencies": {
|
||||
"@ethersphere/bee-js": "^7.1.0",
|
||||
"@ethersphere/swarm-cid": "^0.1.0",
|
||||
"@fairdatasociety/fdp-storage": "^0.19.0",
|
||||
"@material-ui/core": "4.12.3",
|
||||
"@material-ui/icons": "4.11.2",
|
||||
"@material-ui/lab": "4.0.0-alpha.57",
|
||||
|
||||
@@ -7,6 +7,7 @@ import FilesIcon from 'remixicon-react/ArrowUpDownLineIcon'
|
||||
import DocsIcon from 'remixicon-react/BookOpenLineIcon'
|
||||
import ExternalLinkIcon from 'remixicon-react/ExternalLinkLineIcon'
|
||||
import GithubIcon from 'remixicon-react/GithubFillIcon'
|
||||
import FdpIcon from 'remixicon-react/HardDrive2LineIcon'
|
||||
import HomeIcon from 'remixicon-react/Home3LineIcon'
|
||||
import SettingsIcon from 'remixicon-react/Settings2LineIcon'
|
||||
import AccountIcon from 'remixicon-react/Wallet3LineIcon'
|
||||
@@ -76,6 +77,12 @@ export default function SideBar(): ReactElement {
|
||||
path: ROUTES.INFO,
|
||||
icon: HomeIcon,
|
||||
},
|
||||
{
|
||||
label: 'FDP',
|
||||
path: ROUTES.FDP,
|
||||
icon: FdpIcon,
|
||||
pathMatcherSubstring: '/fdp',
|
||||
},
|
||||
{
|
||||
label: 'Files',
|
||||
path: nodeInfo?.beeMode === BeeModes.ULTRA_LIGHT ? ROUTES.DOWNLOAD : ROUTES.UPLOAD,
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
import { FdpStorage } from '@fairdatasociety/fdp-storage'
|
||||
import { Checkbox, InputBase, Typography } from '@material-ui/core'
|
||||
import { useSnackbar } from 'notistack'
|
||||
import { useEffect, useState } from 'react'
|
||||
import RegisterIcon from 'remixicon-react/AddBoxLineIcon'
|
||||
import LoginIcon from 'remixicon-react/LoginBoxLineIcon'
|
||||
import { SwarmButton } from '../../components/SwarmButton'
|
||||
import { Horizontal } from './Horizontal'
|
||||
import { Vertical } from './Vertical'
|
||||
|
||||
interface Props {
|
||||
fdp: FdpStorage
|
||||
onSuccessfulLogin: () => void
|
||||
}
|
||||
|
||||
export function FdpLogin({ fdp, onSuccessfulLogin }: Props) {
|
||||
const [username, setUsername] = useState<string>('')
|
||||
const [password, setPassword] = useState<string>('')
|
||||
const [remember, setRemember] = useState<boolean>(false)
|
||||
const [sepolia, setSepolia] = useState<string>('https://sepolia.drpc.org')
|
||||
const { enqueueSnackbar } = useSnackbar()
|
||||
|
||||
const inputStyle = { background: 'white', padding: '2px 8px', width: '100%' }
|
||||
|
||||
useEffect(() => {
|
||||
const storedSepolia = localStorage.getItem('sepolia')
|
||||
|
||||
if (storedSepolia) {
|
||||
setSepolia(storedSepolia)
|
||||
}
|
||||
const fdpCredentials = localStorage.getItem('fdpCredentials')
|
||||
|
||||
if (fdpCredentials) {
|
||||
const { username, password } = JSON.parse(fdpCredentials)
|
||||
setUsername(username)
|
||||
setPassword(password)
|
||||
setRemember(true)
|
||||
}
|
||||
}, [])
|
||||
|
||||
async function onLogin() {
|
||||
localStorage.setItem('sepolia', sepolia)
|
||||
|
||||
if (remember) {
|
||||
localStorage.setItem('fdpCredentials', JSON.stringify({ username, password }))
|
||||
} else {
|
||||
localStorage.removeItem('fdpCredentials')
|
||||
}
|
||||
enqueueSnackbar('Logging in...', { variant: 'info' })
|
||||
try {
|
||||
await fdp.account.login(username, password)
|
||||
enqueueSnackbar('Logged in successfully', { variant: 'success' })
|
||||
onSuccessfulLogin()
|
||||
} catch {
|
||||
enqueueSnackbar('Login failed', { variant: 'error' })
|
||||
} finally {
|
||||
setUsername('')
|
||||
setPassword('')
|
||||
setRemember(false)
|
||||
}
|
||||
}
|
||||
|
||||
function onRegister() {
|
||||
window.open('https://create.fairdatasociety.org/', '_blank')
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
maxWidth: '500px',
|
||||
margin: 'auto',
|
||||
}}
|
||||
>
|
||||
<Vertical gap={16} full>
|
||||
<Vertical gap={8} left full>
|
||||
<Typography variant="body2">Sepolia JSON RPC</Typography>
|
||||
<InputBase value={sepolia} onChange={e => setSepolia(e.target.value)} style={inputStyle} />
|
||||
</Vertical>
|
||||
<Vertical gap={8} left full>
|
||||
<Typography variant="body2">Username</Typography>
|
||||
<InputBase value={username} onChange={e => setUsername(e.target.value)} style={inputStyle} />
|
||||
</Vertical>
|
||||
<Vertical gap={8} left full>
|
||||
<Typography variant="body2">Password</Typography>
|
||||
<InputBase value={password} onChange={e => setPassword(e.target.value)} style={inputStyle} type="password" />
|
||||
</Vertical>
|
||||
<Vertical gap={8} left full>
|
||||
<Horizontal>
|
||||
<Checkbox checked={remember} onChange={e => setRemember(e.target.checked)} />
|
||||
<Typography variant="body2">Remember me</Typography>
|
||||
</Horizontal>
|
||||
</Vertical>
|
||||
<Vertical left full>
|
||||
<Horizontal gap={4}>
|
||||
<SwarmButton iconType={LoginIcon} onClick={onLogin}>
|
||||
Login
|
||||
</SwarmButton>
|
||||
<SwarmButton iconType={RegisterIcon} onClick={onRegister}>
|
||||
Registration
|
||||
</SwarmButton>
|
||||
</Horizontal>
|
||||
</Vertical>
|
||||
</Vertical>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
import { FdpStorage } from '@fairdatasociety/fdp-storage'
|
||||
import { useState } from 'react'
|
||||
import { CafeReactFs } from '../../react-fs/CafeReactFs'
|
||||
import { FsItem, FsItemType } from '../../react-fs/CafeReactType'
|
||||
import { joinUrl } from '../../react-fs/Utility'
|
||||
|
||||
interface Props {
|
||||
fdp: FdpStorage
|
||||
name: string
|
||||
}
|
||||
|
||||
export function FdpPod({ fdp, name }: Props) {
|
||||
const [reloader, setReloader] = useState(0)
|
||||
|
||||
function reload() {
|
||||
setReloader(reloader + 1)
|
||||
}
|
||||
|
||||
return (
|
||||
<CafeReactFs
|
||||
rootAlias={`/${name}`}
|
||||
backgroundColor="#ffffff"
|
||||
reloader={reloader}
|
||||
onDeleteFile={async (path: string) => {
|
||||
await fdp.file.delete(name, path)
|
||||
reload()
|
||||
}}
|
||||
onDeleteDirectory={async (path: string) => {
|
||||
await fdp.directory.delete(name, path)
|
||||
reload()
|
||||
}}
|
||||
onUpload={(path: string) => {
|
||||
const input = document.createElement('input')
|
||||
input.type = 'file'
|
||||
input.multiple = true
|
||||
input.click()
|
||||
|
||||
return new Promise<void>(resolve => {
|
||||
input.onchange = async () => {
|
||||
if (!input.files || !input.files.length) {
|
||||
resolve()
|
||||
|
||||
return
|
||||
}
|
||||
for (const file of Array.from(input.files)) {
|
||||
const data = await file.arrayBuffer()
|
||||
await fdp.file.uploadData(name, joinUrl(path, file.name), new Uint8Array(data))
|
||||
}
|
||||
reload()
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
}}
|
||||
onCreateDirectory={async (path: string) => {
|
||||
// eslint-disable-next-line no-alert
|
||||
const newDirectoryName = prompt('Directory name')
|
||||
|
||||
if (!newDirectoryName) {
|
||||
return
|
||||
}
|
||||
await fdp.directory.create(name, joinUrl(path, newDirectoryName))
|
||||
reload()
|
||||
}}
|
||||
// eslint-disable-next-line require-await
|
||||
onSync={async () => {
|
||||
setReloader(reloader + 1)
|
||||
}}
|
||||
download={async (path: string) => {
|
||||
const data = await fdp.file.downloadData(name, path)
|
||||
const url = URL.createObjectURL(new Blob([data]))
|
||||
const a = document.createElement('a')
|
||||
a.href = url
|
||||
a.download = path.split('/').pop() || 'Untitled'
|
||||
a.click()
|
||||
}}
|
||||
list={async (path: string) => {
|
||||
const fdpResponse = await fdp.directory.read(name, path)
|
||||
const items: FsItem[] = []
|
||||
for (const directory of fdpResponse.directories) {
|
||||
items.push({
|
||||
name: directory.name,
|
||||
$type: FsItemType.DIRECTORY,
|
||||
id: directory.name,
|
||||
})
|
||||
}
|
||||
for (const file of fdpResponse.files) {
|
||||
items.push({
|
||||
name: file.name,
|
||||
$type: FsItemType.FILE,
|
||||
id: file.name,
|
||||
})
|
||||
}
|
||||
|
||||
return items
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import { FdpStorage } from '@fairdatasociety/fdp-storage'
|
||||
import { Pod } from '@fairdatasociety/fdp-storage/dist/pod/types'
|
||||
import { CircularProgress, Typography } from '@material-ui/core'
|
||||
import { FdpPod } from './FdpPod'
|
||||
import { Vertical } from './Vertical'
|
||||
|
||||
interface Props {
|
||||
fdp: FdpStorage
|
||||
pods: Pod[]
|
||||
loadingPods: boolean
|
||||
}
|
||||
|
||||
export function FdpPods({ fdp, pods, loadingPods }: Props) {
|
||||
if (loadingPods) {
|
||||
return (
|
||||
<Vertical gap={32} full>
|
||||
<CircularProgress />
|
||||
<Typography>Loading your pods...</Typography>
|
||||
</Vertical>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Vertical gap={16} full left>
|
||||
{pods.map(pod => (
|
||||
<FdpPod key={pod.index} fdp={fdp} name={pod.name} />
|
||||
))}
|
||||
</Vertical>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
interface Props {
|
||||
children: React.ReactNode
|
||||
p?: string
|
||||
gap?: number
|
||||
between?: boolean
|
||||
background?: string
|
||||
}
|
||||
|
||||
export function Horizontal({ children, p = '0', gap = 8, between, background }: Props) {
|
||||
const style = {
|
||||
display: 'flex',
|
||||
flexDirection: 'row' as 'row', //eslint-disable-line
|
||||
alignItems: 'center',
|
||||
justifyContent: between ? 'space-between' : 'flex-start',
|
||||
gap: `${gap}px`,
|
||||
padding: p,
|
||||
background,
|
||||
width: between ? '100%' : 'auto',
|
||||
}
|
||||
|
||||
return <div style={style}>{children}</div>
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
interface Props {
|
||||
children: React.ReactNode
|
||||
p?: number
|
||||
gap?: number
|
||||
left?: boolean
|
||||
full?: boolean
|
||||
}
|
||||
|
||||
export function Vertical({ children, p = 0, gap = 0, left = false, full = false }: Props) {
|
||||
const style = {
|
||||
display: 'flex',
|
||||
flexDirection: 'column' as 'column', //eslint-disable-line
|
||||
alignItems: left ? 'flex-start' : 'center',
|
||||
gap: `${gap}px`,
|
||||
width: full ? '100%' : 'auto',
|
||||
padding: `${p}px`,
|
||||
}
|
||||
|
||||
return <div style={style}>{children}</div>
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
import { Bee } from '@ethersphere/bee-js'
|
||||
import { FdpStorage } from '@fairdatasociety/fdp-storage'
|
||||
import { Pod } from '@fairdatasociety/fdp-storage/dist/pod/types'
|
||||
import { CircularProgress, Typography } from '@material-ui/core'
|
||||
import { useSnackbar } from 'notistack'
|
||||
import { ReactElement, useEffect, useState } from 'react'
|
||||
import ImportIcon from 'remixicon-react/AddBoxLineIcon'
|
||||
import PlusCircle from 'remixicon-react/AddCircleLineIcon'
|
||||
import { SwarmButton } from '../../components/SwarmButton'
|
||||
import { joinUrl } from '../../react-fs/Utility'
|
||||
import { ManifestJs } from '../../utils/manifest'
|
||||
import { FdpLogin } from './FdpLogin'
|
||||
import { FdpPods } from './FdpPods'
|
||||
import { Horizontal } from './Horizontal'
|
||||
import { Vertical } from './Vertical'
|
||||
|
||||
async function makeFdp(): Promise<FdpStorage | null> {
|
||||
const bee = new Bee('http://localhost:1633')
|
||||
const sepolia = localStorage.getItem('sepolia') ?? 'https://sepolia.drpc.org'
|
||||
const postageBatches = await bee.getAllPostageBatch()
|
||||
const usableBatches = postageBatches.filter(batch => batch.usable)
|
||||
const highestCapacityBatch = usableBatches.length ? usableBatches.reduce((a, b) => (a.depth > b.depth ? a : b)) : null
|
||||
|
||||
if (!highestCapacityBatch) {
|
||||
return null
|
||||
}
|
||||
|
||||
return new FdpStorage('http://localhost:1633', highestCapacityBatch.batchID, {
|
||||
ensOptions: {
|
||||
rpcUrl: sepolia,
|
||||
contractAddresses: {
|
||||
ensRegistry: '0x42a96D45d787685ac4b36292d218B106Fb39be7F',
|
||||
fdsRegistrar: '0xFBF00389140C00384d88d458239833E3231a7414',
|
||||
nameResolver: '0xE20ECe6Ea93c4edE41e4d3B973f6679F1E89986A',
|
||||
publicResolver: '0xC904989B579c2B216A75723688C784038AA99B56',
|
||||
reverseResolver: '0xbDC8D98d3cbFd68EA9c165E1f15Df6e77A2ae0C5',
|
||||
},
|
||||
gasEstimation: 1,
|
||||
performChecks: true,
|
||||
},
|
||||
providerOptions: {
|
||||
url: sepolia,
|
||||
},
|
||||
ensDomain: 'fds',
|
||||
})
|
||||
}
|
||||
|
||||
export default function FDP(): ReactElement {
|
||||
const [fdp, setFdp] = useState<FdpStorage | null>(null)
|
||||
const [pods, setPods] = useState<Pod[]>([])
|
||||
const [loggedIn, setLoggedIn] = useState<boolean>(false)
|
||||
const [loadingPods, setLoadingPods] = useState<boolean>(false)
|
||||
const [creatingPod, setCreatingPod] = useState<boolean>(false)
|
||||
const { enqueueSnackbar } = useSnackbar()
|
||||
|
||||
useEffect(() => {
|
||||
makeFdp().then(fdp => {
|
||||
if (!fdp) {
|
||||
enqueueSnackbar('FDP could not be initialized. Do you have a postage batch?', { variant: 'error' })
|
||||
}
|
||||
setFdp(fdp)
|
||||
})
|
||||
}, [enqueueSnackbar])
|
||||
|
||||
useEffect(() => {
|
||||
if (fdp && loggedIn) {
|
||||
setLoadingPods(true)
|
||||
fdp.personalStorage.list().then(pods => {
|
||||
setPods(pods.pods)
|
||||
setLoadingPods(false)
|
||||
})
|
||||
}
|
||||
}, [fdp, loggedIn])
|
||||
|
||||
function onSuccessfulLogin() {
|
||||
setLoggedIn(true)
|
||||
}
|
||||
|
||||
function onCreatePod() {
|
||||
if (!fdp) {
|
||||
return
|
||||
}
|
||||
|
||||
if (loadingPods || creatingPod) {
|
||||
enqueueSnackbar('Please wait until the pods are loaded', { variant: 'info' })
|
||||
|
||||
return
|
||||
}
|
||||
// eslint-disable-next-line no-alert
|
||||
const name = prompt('Enter a name for the new pod')
|
||||
|
||||
if (name) {
|
||||
setCreatingPod(true)
|
||||
fdp.personalStorage.create(name).then(() => {
|
||||
fdp.personalStorage.list().then(pods => {
|
||||
setPods(pods.pods)
|
||||
setCreatingPod(false)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async function onImportPod() {
|
||||
if (!fdp) {
|
||||
return
|
||||
}
|
||||
|
||||
if (loadingPods || creatingPod) {
|
||||
enqueueSnackbar('Please wait until the pods are loaded', { variant: 'info' })
|
||||
|
||||
return
|
||||
}
|
||||
// eslint-disable-next-line no-alert
|
||||
const name = prompt('Enter a name for the new pod')
|
||||
// eslint-disable-next-line no-alert
|
||||
const importHash = prompt('Enter the Swarm reference')
|
||||
|
||||
if (!name || !importHash) {
|
||||
return
|
||||
}
|
||||
setCreatingPod(true)
|
||||
const bee = new Bee('http://localhost:1633')
|
||||
const manifestJs = new ManifestJs(bee)
|
||||
const entries = await manifestJs.getHashes(importHash)
|
||||
await fdp.personalStorage.create(name)
|
||||
for (const [path, hash] of Object.entries(entries)) {
|
||||
await fdp.file.uploadData(name, joinUrl('/', path), await bee.downloadData(hash))
|
||||
}
|
||||
const pods = await fdp.personalStorage.list()
|
||||
setPods(pods.pods)
|
||||
setCreatingPod(false)
|
||||
}
|
||||
|
||||
if (!fdp) {
|
||||
return <CircularProgress />
|
||||
}
|
||||
|
||||
return (
|
||||
<Vertical gap={32} full left>
|
||||
<Horizontal between>
|
||||
<Typography variant="h1">Files</Typography>
|
||||
{loggedIn && (
|
||||
<Horizontal gap={4}>
|
||||
<SwarmButton onClick={onCreatePod} iconType={PlusCircle}>
|
||||
Create
|
||||
</SwarmButton>
|
||||
<SwarmButton onClick={onImportPod} iconType={ImportIcon}>
|
||||
Import
|
||||
</SwarmButton>
|
||||
</Horizontal>
|
||||
)}
|
||||
</Horizontal>
|
||||
{!loggedIn && <FdpLogin fdp={fdp} onSuccessfulLogin={onSuccessfulLogin} />}
|
||||
{loggedIn && <FdpPods fdp={fdp} pods={pods} loadingPods={loadingPods || creatingPod} />}
|
||||
{loggedIn && !loadingPods && !creatingPod && pods.length === 0 && (
|
||||
<Typography>
|
||||
<strong>You do not have any pods yet.</strong> Get started by clicking the Create or Import button on the top
|
||||
right.
|
||||
</Typography>
|
||||
)}
|
||||
</Vertical>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { CafeReactFsCreate } from './CafeReactFsCreate'
|
||||
import { CafeReactFsItem } from './CafeReactFsItem'
|
||||
import { CafeReactFsLoading } from './CafeReactFsLoading'
|
||||
import { CafeReactFsPath } from './CafeReactFsPath'
|
||||
import { CafeReactFsSync } from './CafeReactFsSync'
|
||||
import { CafeReactFsUpload } from './CafeReactFsUpload'
|
||||
import { FsItem } from './CafeReactType'
|
||||
|
||||
const DEFAULT_BACKGROUND_COLOR = '#f0f0f0'
|
||||
|
||||
interface Props {
|
||||
download: (path: string) => Promise<void>
|
||||
list: (path: string) => Promise<FsItem[]>
|
||||
onUpload: (path: string) => Promise<void>
|
||||
onCreateDirectory: (path: string) => Promise<void>
|
||||
onDeleteFile: (path: string) => Promise<void>
|
||||
onDeleteDirectory: (path: string) => Promise<void>
|
||||
onSync: () => Promise<void>
|
||||
reloader: number
|
||||
backgroundColor?: string
|
||||
rootAlias?: string
|
||||
}
|
||||
|
||||
export function CafeReactFs({
|
||||
download,
|
||||
list,
|
||||
onUpload,
|
||||
onCreateDirectory,
|
||||
onDeleteFile,
|
||||
onDeleteDirectory,
|
||||
onSync,
|
||||
reloader,
|
||||
backgroundColor,
|
||||
rootAlias,
|
||||
}: Props) {
|
||||
const [path, setPath] = useState('/')
|
||||
const [items, setItems] = useState<FsItem[]>([])
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
function setItemsSorted(items: FsItem[]) {
|
||||
// directories first, all alphabetically
|
||||
const sortedItems = items.slice().sort((a, b) => {
|
||||
if (a.$type === b.$type) {
|
||||
return a.name.localeCompare(b.name)
|
||||
}
|
||||
|
||||
return a.$type === 'directory' ? -1 : 1
|
||||
})
|
||||
setItems(sortedItems)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true)
|
||||
list(path)
|
||||
.then(setItemsSorted)
|
||||
.finally(() => setLoading(false))
|
||||
}, [reloader, list, path])
|
||||
|
||||
const pathParts = ['/', ...path.split('/').filter(x => x)]
|
||||
|
||||
function jumpToDirectory(fullPath: string) {
|
||||
setPath(fullPath)
|
||||
setLoading(true)
|
||||
list(fullPath)
|
||||
.then(setItemsSorted)
|
||||
.finally(() => setLoading(false))
|
||||
}
|
||||
|
||||
function enterDirectory(name: string) {
|
||||
const newPath = path.endsWith('/') ? `${path}${name}` : `${path}/${name}`
|
||||
setPath(newPath)
|
||||
setLoading(true)
|
||||
list(newPath)
|
||||
.then(setItemsSorted)
|
||||
.finally(() => setLoading(false))
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>
|
||||
<CafeReactFsPath
|
||||
pathParts={pathParts}
|
||||
jumpToDirectory={jumpToDirectory}
|
||||
backgroundColor={backgroundColor ?? DEFAULT_BACKGROUND_COLOR}
|
||||
rootAlias={rootAlias}
|
||||
/>
|
||||
<div style={{ display: 'flex', flexDirection: 'row', flexWrap: 'wrap', gap: '4px' }}>
|
||||
{loading && <CafeReactFsLoading backgroundColor={backgroundColor ?? DEFAULT_BACKGROUND_COLOR} />}
|
||||
{!loading &&
|
||||
items.map(item => (
|
||||
<CafeReactFsItem
|
||||
key={item.id}
|
||||
path={path}
|
||||
item={item}
|
||||
enterDirectory={enterDirectory}
|
||||
onDeleteFile={onDeleteFile}
|
||||
onDeleteDirectory={onDeleteDirectory}
|
||||
download={download}
|
||||
backgroundColor={backgroundColor ?? DEFAULT_BACKGROUND_COLOR}
|
||||
/>
|
||||
))}
|
||||
{!loading && (
|
||||
<>
|
||||
<CafeReactFsUpload
|
||||
onUpload={() => onUpload(path)}
|
||||
backgroundColor={backgroundColor ?? DEFAULT_BACKGROUND_COLOR}
|
||||
/>
|
||||
<CafeReactFsCreate
|
||||
onCreateDirectory={() => onCreateDirectory(path)}
|
||||
backgroundColor={backgroundColor ?? DEFAULT_BACKGROUND_COLOR}
|
||||
/>
|
||||
<CafeReactFsSync backgroundColor={backgroundColor ?? DEFAULT_BACKGROUND_COLOR} onSync={onSync} />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import { useState } from 'react'
|
||||
import { CafeReactFsLoading } from './CafeReactFsLoading'
|
||||
|
||||
interface Props {
|
||||
backgroundColor: string
|
||||
onCreateDirectory: () => Promise<void>
|
||||
}
|
||||
|
||||
export function CafeReactFsCreate({ backgroundColor, onCreateDirectory }: Props) {
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
function proxyUpload() {
|
||||
setLoading(true)
|
||||
onCreateDirectory().finally(() => setLoading(false))
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
return <CafeReactFsLoading backgroundColor={backgroundColor} />
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: '80px',
|
||||
height: '80px',
|
||||
position: 'relative',
|
||||
background: backgroundColor,
|
||||
borderRadius: '2px',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
onClick={proxyUpload}
|
||||
>
|
||||
<img
|
||||
alt="Create"
|
||||
style={{ width: '64px', height: '64px', position: 'absolute', left: '8px', top: 0 }}
|
||||
src="data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%3Csvg%20width%3D%22512%22%20height%3D%22512%22%20viewBox%3D%220%200%20512%20512%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M%20106%20131%20l%20100%200%20l%2025%2025%20l%20175%200%20l%200%20200%20l%20-300%200%20z%22%20stroke%3D%22%231F2D3D%22%20stroke-width%3D%2220%22%20fill%3D%22none%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%20%20%2F%3E%3Cpath%20d%3D%22M%20206%20256%20l%20100%200%22%20stroke%3D%22%23B83B5E%22%20stroke-width%3D%2220%22%20fill%3D%22none%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%20%20%2F%3E%3Cpath%20d%3D%22M%20256%20206%20l%200%20100%22%20stroke%3D%22%23B83B5E%22%20stroke-width%3D%2220%22%20fill%3D%22none%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%20%20%2F%3E%3C%2Fsvg%3E"
|
||||
/>
|
||||
<p
|
||||
style={{
|
||||
margin: 0,
|
||||
fontFamily: 'sans-serif',
|
||||
fontSize: '12px',
|
||||
textAlign: 'center',
|
||||
width: '80px',
|
||||
position: 'absolute',
|
||||
bottom: '5px',
|
||||
left: 0,
|
||||
}}
|
||||
>
|
||||
New Folder
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
interface Props {
|
||||
onDelete: () => Promise<void>
|
||||
}
|
||||
|
||||
export function CafeReactFsDelete({ onDelete }: Props) {
|
||||
return (
|
||||
<img
|
||||
alt="Delete"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: '2px',
|
||||
right: '2px',
|
||||
width: '20px',
|
||||
height: '20px',
|
||||
cursor: 'pointer',
|
||||
zIndex: 1,
|
||||
}}
|
||||
src="data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%3Csvg%20width%3D%22128%22%20height%3D%22128%22%20viewBox%3D%220%200%20128%20128%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Ccircle%20cx%3D%2264%22%20cy%3D%2264%22%20r%3D%2264%22%20fill%3D%22%231F2D3D%22%20stroke%3D%22none%22%20stroke-width%3D%220%22%20%20%2F%3E%3Cpath%20d%3D%22M%2032%2064%20l%2064%200%22%20stroke%3D%22%23B83B5E%22%20stroke-width%3D%2220%22%20fill%3D%22none%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%20%20%2F%3E%3C%2Fsvg%3E"
|
||||
onClick={event => {
|
||||
onDelete()
|
||||
event.stopPropagation()
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import { useState } from 'react'
|
||||
import { CafeReactFsDelete } from './CafeReactFsDelete'
|
||||
import { CafeReactFsLoading } from './CafeReactFsLoading'
|
||||
import { CafeReactFsName } from './CafeReactFsName'
|
||||
import { VirtualDirectory } from './CafeReactType'
|
||||
|
||||
interface Props {
|
||||
directory: VirtualDirectory
|
||||
enterDirectory: (name: string) => void
|
||||
deleteDirectory: (name: string) => Promise<void>
|
||||
backgroundColor: string
|
||||
}
|
||||
|
||||
export function CafeReactFsDirectory({ directory, enterDirectory, deleteDirectory, backgroundColor }: Props) {
|
||||
const [hovered, setHovered] = useState(false)
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
function proxyDelete() {
|
||||
setLoading(true)
|
||||
|
||||
return deleteDirectory(directory.name).finally(() => setLoading(false))
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
return <CafeReactFsLoading backgroundColor={backgroundColor} />
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: '80px',
|
||||
height: '80px',
|
||||
position: 'relative',
|
||||
background: backgroundColor,
|
||||
borderRadius: '2px',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
onClick={() => enterDirectory(directory.name)}
|
||||
onMouseEnter={() => setHovered(true)}
|
||||
onMouseLeave={() => setHovered(false)}
|
||||
>
|
||||
{hovered && <CafeReactFsDelete onDelete={proxyDelete} />}
|
||||
<img
|
||||
alt="Directory"
|
||||
src="data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%3Csvg%20width%3D%22512%22%20height%3D%22512%22%20viewBox%3D%220%200%20512%20512%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M%20106%20131%20l%20100%200%20l%2025%2025%20l%20175%200%20l%200%20200%20l%20-300%200%20z%22%20stroke%3D%22%231F2D3D%22%20stroke-width%3D%2220%22%20fill%3D%22none%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%20%20%2F%3E%3C%2Fsvg%3E"
|
||||
style={{ width: '64px', height: '64px', position: 'absolute', left: '8px', top: 0 }}
|
||||
/>
|
||||
<CafeReactFsName name={directory.name} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import { useState } from 'react'
|
||||
import { CafeReactFsDelete } from './CafeReactFsDelete'
|
||||
import { CafeReactFsLoading } from './CafeReactFsLoading'
|
||||
import { CafeReactFsName } from './CafeReactFsName'
|
||||
import { VirtualFile } from './CafeReactType'
|
||||
import { joinUrl } from './Utility'
|
||||
|
||||
interface Props {
|
||||
path: string
|
||||
file: VirtualFile
|
||||
download: (path: string) => Promise<void>
|
||||
deleteFile: (path: string) => Promise<void>
|
||||
backgroundColor: string
|
||||
}
|
||||
|
||||
export function CafeReactFsFile({ path, file, download, deleteFile, backgroundColor }: Props) {
|
||||
const [hovered, setHovered] = useState(false)
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
if (loading) {
|
||||
return <CafeReactFsLoading backgroundColor={backgroundColor} />
|
||||
}
|
||||
|
||||
function proxyDelete() {
|
||||
setLoading(true)
|
||||
|
||||
return deleteFile(joinUrl(path, file.name)).finally(() => setLoading(false))
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
onClick={() => download(joinUrl(path, file.name))}
|
||||
onMouseEnter={() => setHovered(true)}
|
||||
onMouseLeave={() => setHovered(false)}
|
||||
style={{
|
||||
width: '80px',
|
||||
height: '80px',
|
||||
position: 'relative',
|
||||
background: backgroundColor,
|
||||
borderRadius: '2px',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
>
|
||||
{hovered && <CafeReactFsDelete onDelete={proxyDelete} />}
|
||||
<img
|
||||
alt="File"
|
||||
style={{ width: '64px', height: '64px', position: 'absolute', left: '8px', top: 0 }}
|
||||
src="data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%3Csvg%20width%3D%22512%22%20height%3D%22512%22%20viewBox%3D%220%200%20512%20512%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M%20156%20131%20l%20150%200%20l%2050%2050%20l%200%20200%20l%20-200%200%20z%22%20stroke%3D%22%231F2D3D%22%20stroke-width%3D%2220%22%20fill%3D%22none%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%20%20%2F%3E%3Cpath%20d%3D%22M%20306%20131%20l%200%2050%20l%2050%200%22%20stroke%3D%22%231F2D3D%22%20stroke-width%3D%2220%22%20fill%3D%22none%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%20%20%2F%3E%3C%2Fsvg%3E"
|
||||
/>
|
||||
<CafeReactFsName name={file.name} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import { CafeReactFsDirectory } from './CafeReactFsDirectory'
|
||||
import { CafeReactFsFile } from './CafeReactFsFile'
|
||||
import { FsItem, isVirtualDirectory, isVirtualFile } from './CafeReactType'
|
||||
|
||||
interface Props {
|
||||
path: string
|
||||
item: FsItem
|
||||
download: (path: string) => Promise<void>
|
||||
enterDirectory: (name: string) => void
|
||||
onDeleteFile: (path: string) => Promise<void>
|
||||
onDeleteDirectory: (path: string) => Promise<void>
|
||||
backgroundColor: string
|
||||
}
|
||||
|
||||
export function CafeReactFsItem({
|
||||
path,
|
||||
item,
|
||||
download,
|
||||
enterDirectory,
|
||||
onDeleteFile,
|
||||
onDeleteDirectory,
|
||||
backgroundColor,
|
||||
}: Props) {
|
||||
if (isVirtualFile(item)) {
|
||||
return (
|
||||
<CafeReactFsFile
|
||||
path={path}
|
||||
file={item}
|
||||
download={download}
|
||||
deleteFile={onDeleteFile}
|
||||
backgroundColor={backgroundColor}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
if (isVirtualDirectory(item)) {
|
||||
return (
|
||||
<CafeReactFsDirectory
|
||||
directory={item}
|
||||
enterDirectory={enterDirectory}
|
||||
deleteDirectory={onDeleteDirectory}
|
||||
backgroundColor={backgroundColor}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import { CSSProperties } from 'react'
|
||||
|
||||
interface Props {
|
||||
backgroundColor: string
|
||||
}
|
||||
|
||||
export function CafeReactFsLoading({ backgroundColor }: Props) {
|
||||
const spinnerStyle = {
|
||||
width: '80px',
|
||||
height: '80px',
|
||||
borderRadius: '2px',
|
||||
position: 'relative',
|
||||
background: backgroundColor,
|
||||
} as CSSProperties
|
||||
|
||||
const bounceStyle = {
|
||||
width: '32px',
|
||||
height: '32px',
|
||||
borderRadius: '50%',
|
||||
backgroundColor: '#333',
|
||||
top: '24px',
|
||||
left: '24px',
|
||||
opacity: 0.6,
|
||||
position: 'absolute',
|
||||
animation: 'bounce 2.0s infinite ease-in-out',
|
||||
} as CSSProperties
|
||||
|
||||
const bounceStyle2 = {
|
||||
...bounceStyle,
|
||||
animationDelay: '-1.0s',
|
||||
}
|
||||
|
||||
const keyframes = `
|
||||
@keyframes bounce {
|
||||
0%, 100% {
|
||||
transform: scale(0.0);
|
||||
} 50% {
|
||||
transform: scale(1.0);
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
return (
|
||||
<>
|
||||
<style>{keyframes}</style>
|
||||
<div style={spinnerStyle}>
|
||||
<div style={bounceStyle}></div>
|
||||
<div style={bounceStyle2}></div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
interface Props {
|
||||
name: string
|
||||
}
|
||||
|
||||
export function CafeReactFsName({ name }: Props) {
|
||||
const shortName = name.length > 10 ? name.slice(0, 10) + '...' : name
|
||||
|
||||
return (
|
||||
<p
|
||||
title={name}
|
||||
style={{
|
||||
margin: 0,
|
||||
fontFamily: 'sans-serif',
|
||||
fontSize: '12px',
|
||||
textAlign: 'center',
|
||||
width: '80px',
|
||||
position: 'absolute',
|
||||
bottom: '5px',
|
||||
left: 0,
|
||||
}}
|
||||
>
|
||||
{shortName}
|
||||
</p>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import { joinUrl } from './Utility'
|
||||
|
||||
interface Props {
|
||||
pathParts: string[]
|
||||
jumpToDirectory: (fullPath: string) => void
|
||||
backgroundColor: string
|
||||
rootAlias?: string
|
||||
}
|
||||
|
||||
export function CafeReactFsPath({ pathParts, jumpToDirectory, backgroundColor, rootAlias }: Props) {
|
||||
const absolutePaths: string[] = []
|
||||
|
||||
for (const pathPart of pathParts) {
|
||||
if (absolutePaths.length === 0) {
|
||||
absolutePaths.push(pathPart)
|
||||
} else {
|
||||
absolutePaths.push(joinUrl(absolutePaths[absolutePaths.length - 1], pathPart))
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ display: 'flex', flexDirection: 'row', flexWrap: 'wrap', gap: '4px' }}>
|
||||
{pathParts.map((part, index) => (
|
||||
<button
|
||||
key={index}
|
||||
style={{
|
||||
background: backgroundColor,
|
||||
borderRadius: '2px',
|
||||
cursor: 'pointer',
|
||||
outline: 'none',
|
||||
border: 'none',
|
||||
fontSize: '20px',
|
||||
padding: '4px 16px',
|
||||
}}
|
||||
onClick={() => {
|
||||
jumpToDirectory(absolutePaths[index])
|
||||
}}
|
||||
>
|
||||
{rootAlias && part === '/' ? rootAlias : part}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
interface Props {
|
||||
backgroundColor: string
|
||||
onSync: () => Promise<void>
|
||||
}
|
||||
|
||||
export function CafeReactFsSync({ backgroundColor, onSync }: Props) {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: '80px',
|
||||
height: '80px',
|
||||
position: 'relative',
|
||||
background: backgroundColor,
|
||||
borderRadius: '2px',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
onClick={onSync}
|
||||
>
|
||||
<img
|
||||
alt="Sync"
|
||||
style={{ width: '64px', height: '64px', position: 'absolute', left: '8px', top: 0 }}
|
||||
src="data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%3Csvg%20width%3D%22512%22%20height%3D%22512%22%20viewBox%3D%220%200%20512%20512%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M%20156%20156%20l%20250%200%20l%200%20150%22%20stroke%3D%22%231F2D3D%22%20stroke-width%3D%2220%22%20fill%3D%22none%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%20%20%2F%3E%3Cpath%20d%3D%22M%20356%20256%20l%2050%2050%20l%2050%20-50%22%20stroke%3D%22%231F2D3D%22%20stroke-width%3D%2220%22%20fill%3D%22none%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%20%20%2F%3E%3Cpath%20d%3D%22M%20356%20356%20l%20-250%200%20l%200%20-150%22%20stroke%3D%22%231F2D3D%22%20stroke-width%3D%2220%22%20fill%3D%22none%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%20%20%2F%3E%3Cpath%20d%3D%22M%20156%20256%20l%20-50%20-50%20l%20-50%2050%22%20stroke%3D%22%231F2D3D%22%20stroke-width%3D%2220%22%20fill%3D%22none%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%20%20%2F%3E%3C%2Fsvg%3E"
|
||||
/>
|
||||
<p
|
||||
style={{
|
||||
margin: 0,
|
||||
fontFamily: 'sans-serif',
|
||||
fontSize: '12px',
|
||||
textAlign: 'center',
|
||||
width: '80px',
|
||||
position: 'absolute',
|
||||
bottom: '5px',
|
||||
left: 0,
|
||||
}}
|
||||
>
|
||||
Sync
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import { useState } from 'react'
|
||||
import { CafeReactFsLoading } from './CafeReactFsLoading'
|
||||
|
||||
interface Props {
|
||||
onUpload: () => Promise<void>
|
||||
backgroundColor: string
|
||||
}
|
||||
|
||||
export function CafeReactFsUpload({ onUpload, backgroundColor }: Props) {
|
||||
const [uploading, setUploading] = useState(false)
|
||||
|
||||
function proxyUpload() {
|
||||
setUploading(true)
|
||||
onUpload().finally(() => setUploading(false))
|
||||
}
|
||||
|
||||
if (uploading) {
|
||||
return <CafeReactFsLoading backgroundColor={backgroundColor} />
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: '80px',
|
||||
height: '80px',
|
||||
position: 'relative',
|
||||
background: backgroundColor,
|
||||
borderRadius: '2px',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
onClick={proxyUpload}
|
||||
>
|
||||
<img
|
||||
alt="Upload"
|
||||
style={{ width: '64px', height: '64px', position: 'absolute', left: '8px', top: 0 }}
|
||||
src="data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%3Csvg%20width%3D%22512%22%20height%3D%22512%22%20viewBox%3D%220%200%20512%20512%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M%20156%20131%20l%20150%200%20l%2050%2050%20l%200%20200%20l%20-200%200%20z%22%20stroke%3D%22%231F2D3D%22%20stroke-width%3D%2220%22%20fill%3D%22none%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%20%20%2F%3E%3Cpath%20d%3D%22M%20306%20131%20l%200%2050%20l%2050%200%22%20stroke%3D%22%231F2D3D%22%20stroke-width%3D%2220%22%20fill%3D%22none%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%20%20%2F%3E%3Cpath%20d%3D%22M%20206%20256%20l%20100%200%22%20stroke%3D%22%23B83B5E%22%20stroke-width%3D%2220%22%20fill%3D%22none%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%20%20%2F%3E%3Cpath%20d%3D%22M%20256%20206%20l%200%20100%22%20stroke%3D%22%23B83B5E%22%20stroke-width%3D%2220%22%20fill%3D%22none%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%20%20%2F%3E%3C%2Fsvg%3E"
|
||||
/>
|
||||
<p
|
||||
style={{
|
||||
margin: 0,
|
||||
fontFamily: 'sans-serif',
|
||||
fontSize: '12px',
|
||||
textAlign: 'center',
|
||||
width: '80px',
|
||||
position: 'absolute',
|
||||
bottom: '5px',
|
||||
left: 0,
|
||||
}}
|
||||
>
|
||||
Upload
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
export enum FsItemType {
|
||||
FILE = 'file',
|
||||
DIRECTORY = 'directory',
|
||||
}
|
||||
|
||||
export interface VirtualFile {
|
||||
id: string | number
|
||||
name: string
|
||||
$type: FsItemType.FILE
|
||||
}
|
||||
|
||||
export interface VirtualDirectory {
|
||||
id: string | number
|
||||
name: string
|
||||
$type: FsItemType.DIRECTORY
|
||||
}
|
||||
|
||||
export type FsItem = VirtualFile | VirtualDirectory
|
||||
|
||||
export function isVirtualFile(item: FsItem): item is VirtualFile {
|
||||
return item.$type === FsItemType.FILE
|
||||
}
|
||||
|
||||
export function isVirtualDirectory(item: FsItem): item is VirtualDirectory {
|
||||
return item.$type === FsItemType.DIRECTORY
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
export function joinUrl(...parts: unknown[]): string {
|
||||
return parts
|
||||
.filter(x => x)
|
||||
.join('/')
|
||||
.replace(/(?<!:)\/+/g, '/')
|
||||
}
|
||||
+4
-1
@@ -5,6 +5,7 @@ import { AccountFeeds } from './pages/account/feeds/AccountFeeds'
|
||||
import { AccountStaking } from './pages/account/staking/AccountStaking'
|
||||
import { AccountStamps } from './pages/account/stamps/AccountStamps'
|
||||
import { AccountWallet } from './pages/account/wallet/AccountWallet'
|
||||
import FDP from './pages/fdp'
|
||||
import CreateNewFeed from './pages/feeds/CreateNewFeed'
|
||||
import { FeedSubpage } from './pages/feeds/FeedSubpage'
|
||||
import UpdateFeed from './pages/feeds/UpdateFeed'
|
||||
@@ -17,6 +18,7 @@ import Info from './pages/info'
|
||||
import LightModeRestart from './pages/restart/LightModeRestart'
|
||||
import Settings from './pages/settings'
|
||||
import { CreatePostageStampPage } from './pages/stamps/CreatePostageStampAdvancedPage'
|
||||
import { CreatePostageStampBasicPage } from './pages/stamps/CreatePostageStampStandardPage'
|
||||
import Status from './pages/status'
|
||||
import TopUp from './pages/top-up'
|
||||
import { BankCardTopUpIndex } from './pages/top-up/BankCardTopUpIndex'
|
||||
@@ -25,7 +27,6 @@ import { GiftCardFund } from './pages/top-up/GiftCardFund'
|
||||
import { GiftCardTopUpIndex } from './pages/top-up/GiftCardTopUpIndex'
|
||||
import { Swap } from './pages/top-up/Swap'
|
||||
import { Context as SettingsContext } from './providers/Settings'
|
||||
import { CreatePostageStampBasicPage } from './pages/stamps/CreatePostageStampStandardPage'
|
||||
|
||||
export enum ROUTES {
|
||||
INFO = '/',
|
||||
@@ -55,6 +56,7 @@ export enum ROUTES {
|
||||
ACCOUNT_FEEDS_VIEW = '/account/feeds/:uuid',
|
||||
ACCOUNT_INVITATIONS = '/account/invitations',
|
||||
ACCOUNT_STAKING = '/account/staking',
|
||||
FDP = '/fdp',
|
||||
}
|
||||
|
||||
export const ACCOUNT_TABS = [
|
||||
@@ -95,6 +97,7 @@ const BaseRouter = (): ReactElement => {
|
||||
<Route path={ROUTES.ACCOUNT_FEEDS_UPDATE} element={<UpdateFeed />} />
|
||||
<Route path={ROUTES.ACCOUNT_FEEDS_VIEW} element={<FeedSubpage />} />
|
||||
<Route path={ROUTES.ACCOUNT_STAKING} element={<AccountStaking />} />
|
||||
<Route path={ROUTES.FDP} element={<FDP />} />
|
||||
{isDesktop && <Route path={ROUTES.ACCOUNT_INVITATIONS} element={<GiftCards />} />}
|
||||
</Routes>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user