From 7b12a4563cdf2c7983e76a491a20bff277e23a92 Mon Sep 17 00:00:00 2001 From: Shaun Orssaud <72015533+Shorssaud@users.noreply.github.com> Date: Fri, 10 Nov 2023 14:44:28 +0900 Subject: [PATCH 1/3] FIX missing cid when upload --- frontend/src/pages/data/tabs/upload/UploadTab.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/pages/data/tabs/upload/UploadTab.tsx b/frontend/src/pages/data/tabs/upload/UploadTab.tsx index b31a188..adb44e9 100644 --- a/frontend/src/pages/data/tabs/upload/UploadTab.tsx +++ b/frontend/src/pages/data/tabs/upload/UploadTab.tsx @@ -55,8 +55,8 @@ function UploadTab() { }, }) .then((response) => { - console.log(response.data); - newCid = response.data.cid; + console.log(newCid); + newCid = response.data; }); console.log(newCid); From 6b524e610a9c910e1222575fff3fec85fb9fc149 Mon Sep 17 00:00:00 2001 From: Shaun Orssaud <72015533+Shorssaud@users.noreply.github.com> Date: Fri, 10 Nov 2023 15:56:06 +0900 Subject: [PATCH 2/3] UPD prepared marketplace pages for development --- frontend/src/App.tsx | 7 +- .../src/pages/data/tabs/upload/UploadTab.tsx | 2 - .../src/pages/marketplace/Marketplace.tsx | 32 ++++ .../tabs/available/AvailableTab.tsx | 150 ++++++++++++++++++ .../marketplace/tabs/create/CreateTab.tsx | 117 ++++++++++++++ 5 files changed, 301 insertions(+), 7 deletions(-) create mode 100644 frontend/src/pages/marketplace/Marketplace.tsx create mode 100644 frontend/src/pages/marketplace/tabs/available/AvailableTab.tsx create mode 100644 frontend/src/pages/marketplace/tabs/create/CreateTab.tsx diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index a15834b..6391e93 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -4,6 +4,7 @@ import styled from "styled-components"; import DataPage from "./pages/data/DataPage"; import DebugPage from "./pages/debug/DebugPage"; import SettingsPage from "./pages/settings/SettingsPage"; +import MarketplacePage from "./pages/marketplace/Marketplace"; function PlacehoderPage(props: { name: string }) { return ( @@ -24,13 +25,9 @@ export default function App() { - } /> - + }/> } /> diff --git a/frontend/src/pages/data/tabs/upload/UploadTab.tsx b/frontend/src/pages/data/tabs/upload/UploadTab.tsx index adb44e9..ae32295 100644 --- a/frontend/src/pages/data/tabs/upload/UploadTab.tsx +++ b/frontend/src/pages/data/tabs/upload/UploadTab.tsx @@ -55,10 +55,8 @@ function UploadTab() { }, }) .then((response) => { - console.log(newCid); newCid = response.data; }); - console.log(newCid); filesCopy.current = filesCopy.current.filter( (file) => file.cid !== cid diff --git a/frontend/src/pages/marketplace/Marketplace.tsx b/frontend/src/pages/marketplace/Marketplace.tsx new file mode 100644 index 0000000..875f76d --- /dev/null +++ b/frontend/src/pages/marketplace/Marketplace.tsx @@ -0,0 +1,32 @@ +import React from "react"; +import TabBarView from "../../components/layout/tabBarView/TabBarView"; +import styled from "styled-components"; + +import { MdFileUpload, MdFileDownload } from "react-icons/md"; +import UploadTab from "./tabs/available/AvailableTab"; +import DownloadTab from "./tabs/create/CreateTab"; + +function MarketplacePage() { + return ( +
+ + + + + + +
+ ); +} + +export default MarketplacePage; + +const TabBarViewPage = styled.div` + flex: 1; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100%; + width: 100%; +`; diff --git a/frontend/src/pages/marketplace/tabs/available/AvailableTab.tsx b/frontend/src/pages/marketplace/tabs/available/AvailableTab.tsx new file mode 100644 index 0000000..50719a5 --- /dev/null +++ b/frontend/src/pages/marketplace/tabs/available/AvailableTab.tsx @@ -0,0 +1,150 @@ +import { useCallback, useEffect, useRef } from "react"; +import { useDropzone } from "react-dropzone"; +import styled from "styled-components"; +import UploadedItemModel, { + UploadedItemStatus, +} from "../../../../data/models/UploadedItemModel"; +import UploadedItemComponent from "../../../../components/uploadedItem/UploadedItemComponent"; +import axios from "axios"; + +import { useDexyStore } from "../../../../store"; +import constants from "../../../../util/Constants"; + +function AvailableTab() { +// const { uploads, setUploads, nodeInfo } = useDexyStore(); +// var filesCopy = useRef(uploads); + +// useEffect(() => { +// console.log(uploads); +// // setUploads([]); +// }, [uploads]); + +// const onDrop = useCallback( +// async (acceptedFiles: File[]) => { +// console.log(acceptedFiles); +// for (let i = 0; i < acceptedFiles.length; i++) { +// new Promise(async (resolve, reject) => { +// let cid: string = (Math.random() * 1000000).toString(); +// console.log(cid + acceptedFiles[i].name); +// filesCopy.current.push({ +// cid: cid, +// fileName: acceptedFiles[i].name, +// fileSize: acceptedFiles[i].size, +// lastModified: new Date( +// acceptedFiles[i].lastModified +// ).toLocaleString(), +// type: acceptedFiles[i].type, +// status: UploadedItemStatus.UPLOADING, +// }); +// setUploads(filesCopy.current); + +// var bytes = await acceptedFiles[i].arrayBuffer(); +// bytes = new Uint8Array(bytes); + +// var newCid = ""; +// try { +// await axios +// .post(`/api/codex/v1/upload`, bytes, { +// headers: (nodeInfo.auth !== null && { +// "Base-Url": nodeInfo.nodeToConnectTo || nodeInfo.baseUrl, +// "Content-Type": "application/octet-stream", +// "Auth-String": nodeInfo.auth, +// }) || { +// "Base-Url": nodeInfo.nodeToConnectTo || nodeInfo.baseUrl, +// "Content-Type": "application/octet-stream", +// }, +// }) +// .then((response) => { +// newCid = response.data; +// }); + +// filesCopy.current = filesCopy.current.filter( +// (file) => file.cid !== cid +// ); +// filesCopy.current.push({ +// cid: newCid, +// fileName: acceptedFiles[i].name, +// fileSize: acceptedFiles[i].size, +// lastModified: new Date( +// acceptedFiles[i].lastModified +// ).toLocaleString(), +// type: acceptedFiles[i].type, +// status: UploadedItemStatus.UPLOADED, +// }); +// setUploads(filesCopy.current); +// console.log("filesCopy"); +// console.log(filesCopy.current); +// } catch (error) { +// console.log(error); +// filesCopy.current = filesCopy.current.filter( +// (file) => file.cid !== cid +// ); +// filesCopy.current.push({ +// cid: "Failed", +// fileName: acceptedFiles[i].name, +// fileSize: acceptedFiles[i].size, +// lastModified: new Date( +// acceptedFiles[i].lastModified +// ).toLocaleString(), +// type: acceptedFiles[i].type, +// status: UploadedItemStatus.FAILED, +// }); +// console.log("filesCopy failed"); +// console.log(filesCopy.current); +// setUploads(filesCopy.current); +// } +// console.log(cid + acceptedFiles[i].name); +// resolve("done"); +// }); +// } +// }, +// [setUploads, filesCopy, nodeInfo] +// ); + +// const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop }); + + return ( + +
+
+
+ ); +} + +export default AvailableTab; + +const AvailableTabWrapper = styled.div` + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100%; + width: 100%; + padding: 16px; + + #dropzone { + flex: 1; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + width: 100%; + border: 2px dashed #9e9e9e; + border-radius: 8px; + } + + p { + font-size: 1rem; + text-align: center; + } + + #uploaded-items-wrap { + display: flex; + flex-direction: column; + align-items: center; + justify-content: start; + width: 100%; + overflow-y: scroll; + margin-top: 16px; + } +`; diff --git a/frontend/src/pages/marketplace/tabs/create/CreateTab.tsx b/frontend/src/pages/marketplace/tabs/create/CreateTab.tsx new file mode 100644 index 0000000..e86e5dd --- /dev/null +++ b/frontend/src/pages/marketplace/tabs/create/CreateTab.tsx @@ -0,0 +1,117 @@ +import { useState } from "react"; +import constants from "../../../../util/Constants"; +import styled from "styled-components"; +import { useDexyStore } from "../../../../store"; + +function CreateTab() { + const { ftdCid, setFtdCid, nodeInfo } = useDexyStore(); + + const [filename, setFilename] = useState("file"); + + function download(cid: string) { + // console.log(filename); + // console.log(cid); + // fetch( + // `/api/codex/v1/download/${cid}`, + // { + // headers: + // (nodeInfo.auth !== null && { + // Authorization: + // (nodeInfo.auth && "Basic " + btoa(nodeInfo.auth)) || "", + // }) || + // {}, + // } + // ) + // .then((response) => response.blob()) + // .then((blob) => { + // const url = window.URL.createObjectURL(new Blob([blob])); + // const link = document.createElement("a"); + // link.href = url; + // link.setAttribute("download", filename); + // document.body.appendChild(link); + // link.click(); + // link.parentNode?.removeChild(link); + // }); + } + + return ( + + { + setFtdCid(e.target.value); + }} + value={ftdCid} + /> +
+ setFilename(e.target.value)} + /> + +
+ ); +} + +export default CreateTab; + +const CreateTabWrapper = styled.div` + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + width: 75%; + + input { + flex: 3; + height: 60px; + padding: 10px 20px; + border: none; + background-color: ${constants.surfaceColor}; + color: ${constants.onSurfaceColor}; + width: 100%; + } + + input:focus { + outline: none; + border: 2px solid ${constants.primaryColor}; + } + + input:nth-child(1) { + border-top-left-radius: 8px; + border-bottom-left-radius: 8px; + } + + #divider { + width: 2.5px; + height: 60px; + background-color: #555555; + } + + button { + flex: 2; + height: 60px; + border: none; + background-color: ${constants.primaryColor}; + color: ${constants.onPrimaryColor}; + font-size: 1rem; + cursor: pointer; + border-top-right-radius: 8px; + border-bottom-right-radius: 8px; + width: 100%; + } + + @media (max-width: 1180px) { + width: 80%; + } + + @media (max-width: 768px) { + width: 85%; + } + + @media (max-width: 450px) { + width: 90%; + } +`; From 22c06afe7561b263672064ab9ad6d859c5d3a15f Mon Sep 17 00:00:00 2001 From: Shaun Orssaud <72015533+Shorssaud@users.noreply.github.com> Date: Fri, 17 Nov 2023 15:18:46 +0900 Subject: [PATCH 3/3] WIP adding marketplace functionality --- docker-compose.yml | 2 +- .../models/RequestForStorageContractModel.ts | 17 ++ .../src/pages/marketplace/Marketplace.tsx | 10 +- .../tabs/available/AvailableTab.tsx | 150 ------------------ .../marketplace/tabs/create/CreateTab.tsx | 81 ++++++---- .../pages/marketplace/tabs/status/status.tsx | 92 +++++++++++ frontend/src/store.ts | 6 +- 7 files changed, 174 insertions(+), 184 deletions(-) create mode 100644 frontend/src/data/models/RequestForStorageContractModel.ts delete mode 100644 frontend/src/pages/marketplace/tabs/available/AvailableTab.tsx create mode 100644 frontend/src/pages/marketplace/tabs/status/status.tsx diff --git a/docker-compose.yml b/docker-compose.yml index 020ea5d..a66f994 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,6 +7,6 @@ services: ports: - "3000:80" environment: - - codex_url=http://host.docker.internal:8080 + - codex_url=http://kubernetes.docker.internal:31942 volumes: - ./deployment/nginx.template:/etc/nginx/templates/10-variables.conf.template:ro \ No newline at end of file diff --git a/frontend/src/data/models/RequestForStorageContractModel.ts b/frontend/src/data/models/RequestForStorageContractModel.ts new file mode 100644 index 0000000..8272892 --- /dev/null +++ b/frontend/src/data/models/RequestForStorageContractModel.ts @@ -0,0 +1,17 @@ +enum RequestForStorageContractStatus { + UPLOADING = "UPLOADING", + UPLOADED = "UPLOADED", + FAILED = "FAILED", +} + +type RequestForStorageContractModel = { + purchaseid: string; + lastModified: string; + reward: string; + duration: string; + collateral: string; + status: RequestForStorageContractStatus; +}; + +export default RequestForStorageContractModel; +export { RequestForStorageContractStatus }; diff --git a/frontend/src/pages/marketplace/Marketplace.tsx b/frontend/src/pages/marketplace/Marketplace.tsx index 875f76d..8e1f971 100644 --- a/frontend/src/pages/marketplace/Marketplace.tsx +++ b/frontend/src/pages/marketplace/Marketplace.tsx @@ -3,16 +3,18 @@ import TabBarView from "../../components/layout/tabBarView/TabBarView"; import styled from "styled-components"; import { MdFileUpload, MdFileDownload } from "react-icons/md"; -import UploadTab from "./tabs/available/AvailableTab"; +import UploadTab from "./tabs/status/status"; import DownloadTab from "./tabs/create/CreateTab"; +import AvailableTab from "./tabs/status/status"; +import CreateTab from "./tabs/create/CreateTab"; function MarketplacePage() { return (
- - + + - +
diff --git a/frontend/src/pages/marketplace/tabs/available/AvailableTab.tsx b/frontend/src/pages/marketplace/tabs/available/AvailableTab.tsx deleted file mode 100644 index 50719a5..0000000 --- a/frontend/src/pages/marketplace/tabs/available/AvailableTab.tsx +++ /dev/null @@ -1,150 +0,0 @@ -import { useCallback, useEffect, useRef } from "react"; -import { useDropzone } from "react-dropzone"; -import styled from "styled-components"; -import UploadedItemModel, { - UploadedItemStatus, -} from "../../../../data/models/UploadedItemModel"; -import UploadedItemComponent from "../../../../components/uploadedItem/UploadedItemComponent"; -import axios from "axios"; - -import { useDexyStore } from "../../../../store"; -import constants from "../../../../util/Constants"; - -function AvailableTab() { -// const { uploads, setUploads, nodeInfo } = useDexyStore(); -// var filesCopy = useRef(uploads); - -// useEffect(() => { -// console.log(uploads); -// // setUploads([]); -// }, [uploads]); - -// const onDrop = useCallback( -// async (acceptedFiles: File[]) => { -// console.log(acceptedFiles); -// for (let i = 0; i < acceptedFiles.length; i++) { -// new Promise(async (resolve, reject) => { -// let cid: string = (Math.random() * 1000000).toString(); -// console.log(cid + acceptedFiles[i].name); -// filesCopy.current.push({ -// cid: cid, -// fileName: acceptedFiles[i].name, -// fileSize: acceptedFiles[i].size, -// lastModified: new Date( -// acceptedFiles[i].lastModified -// ).toLocaleString(), -// type: acceptedFiles[i].type, -// status: UploadedItemStatus.UPLOADING, -// }); -// setUploads(filesCopy.current); - -// var bytes = await acceptedFiles[i].arrayBuffer(); -// bytes = new Uint8Array(bytes); - -// var newCid = ""; -// try { -// await axios -// .post(`/api/codex/v1/upload`, bytes, { -// headers: (nodeInfo.auth !== null && { -// "Base-Url": nodeInfo.nodeToConnectTo || nodeInfo.baseUrl, -// "Content-Type": "application/octet-stream", -// "Auth-String": nodeInfo.auth, -// }) || { -// "Base-Url": nodeInfo.nodeToConnectTo || nodeInfo.baseUrl, -// "Content-Type": "application/octet-stream", -// }, -// }) -// .then((response) => { -// newCid = response.data; -// }); - -// filesCopy.current = filesCopy.current.filter( -// (file) => file.cid !== cid -// ); -// filesCopy.current.push({ -// cid: newCid, -// fileName: acceptedFiles[i].name, -// fileSize: acceptedFiles[i].size, -// lastModified: new Date( -// acceptedFiles[i].lastModified -// ).toLocaleString(), -// type: acceptedFiles[i].type, -// status: UploadedItemStatus.UPLOADED, -// }); -// setUploads(filesCopy.current); -// console.log("filesCopy"); -// console.log(filesCopy.current); -// } catch (error) { -// console.log(error); -// filesCopy.current = filesCopy.current.filter( -// (file) => file.cid !== cid -// ); -// filesCopy.current.push({ -// cid: "Failed", -// fileName: acceptedFiles[i].name, -// fileSize: acceptedFiles[i].size, -// lastModified: new Date( -// acceptedFiles[i].lastModified -// ).toLocaleString(), -// type: acceptedFiles[i].type, -// status: UploadedItemStatus.FAILED, -// }); -// console.log("filesCopy failed"); -// console.log(filesCopy.current); -// setUploads(filesCopy.current); -// } -// console.log(cid + acceptedFiles[i].name); -// resolve("done"); -// }); -// } -// }, -// [setUploads, filesCopy, nodeInfo] -// ); - -// const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop }); - - return ( - -
-
-
- ); -} - -export default AvailableTab; - -const AvailableTabWrapper = styled.div` - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - height: 100%; - width: 100%; - padding: 16px; - - #dropzone { - flex: 1; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - width: 100%; - border: 2px dashed #9e9e9e; - border-radius: 8px; - } - - p { - font-size: 1rem; - text-align: center; - } - - #uploaded-items-wrap { - display: flex; - flex-direction: column; - align-items: center; - justify-content: start; - width: 100%; - overflow-y: scroll; - margin-top: 16px; - } -`; diff --git a/frontend/src/pages/marketplace/tabs/create/CreateTab.tsx b/frontend/src/pages/marketplace/tabs/create/CreateTab.tsx index e86e5dd..80ec572 100644 --- a/frontend/src/pages/marketplace/tabs/create/CreateTab.tsx +++ b/frontend/src/pages/marketplace/tabs/create/CreateTab.tsx @@ -6,32 +6,39 @@ import { useDexyStore } from "../../../../store"; function CreateTab() { const { ftdCid, setFtdCid, nodeInfo } = useDexyStore(); - const [filename, setFilename] = useState("file"); + const [reward, setReward,] = useState("file"); + const [duration, setDuration,] = useState("file"); + const [proofProbability, setProofProbability,] = useState("file"); + const [collateral, setCollateral,] = useState("file"); + - function download(cid: string) { - // console.log(filename); - // console.log(cid); - // fetch( - // `/api/codex/v1/download/${cid}`, - // { - // headers: - // (nodeInfo.auth !== null && { - // Authorization: - // (nodeInfo.auth && "Basic " + btoa(nodeInfo.auth)) || "", - // }) || - // {}, - // } - // ) - // .then((response) => response.blob()) - // .then((blob) => { - // const url = window.URL.createObjectURL(new Blob([blob])); - // const link = document.createElement("a"); - // link.href = url; - // link.setAttribute("download", filename); - // document.body.appendChild(link); - // link.click(); - // link.parentNode?.removeChild(link); - // }); + function upload(cid: string) { + fetch( + `/api/codex/v1/storage/request/${cid}`, + { + method: 'POST', + headers: + (nodeInfo.auth !== null && { + Authorization: + (nodeInfo.auth && "Basic " + btoa(nodeInfo.auth)) || "", + }) || + {}, + body: JSON.stringify({ + reward: reward, + duration: duration, + proofProbability: proofProbability, + collateral: collateral + }) + } + ) + // create a popup in the browser to show if the upload was successful + .then((response) => { + if (response.status === 200) { + alert("Upload successful!"); + } else { + alert("Upload failed!"); + } + }) } return ( @@ -47,10 +54,28 @@ function CreateTab() {
setFilename(e.target.value)} + placeholder="Reward" + onChange={(e) => setReward(e.target.value)} /> - +
+ setDuration(e.target.value)} + /> +
+ setProofProbability(e.target.value)} + /> +
+ setCollateral(e.target.value)} + /> + ); } diff --git a/frontend/src/pages/marketplace/tabs/status/status.tsx b/frontend/src/pages/marketplace/tabs/status/status.tsx new file mode 100644 index 0000000..05177e4 --- /dev/null +++ b/frontend/src/pages/marketplace/tabs/status/status.tsx @@ -0,0 +1,92 @@ +import { useCallback, useEffect, useRef } from "react"; +import { useDropzone } from "react-dropzone"; +import styled from "styled-components"; +import UploadedItemModel, { + UploadedItemStatus, +} from "../../../../data/models/UploadedItemModel"; +import UploadedItemComponent from "../../../../components/uploadedItem/UploadedItemComponent"; +import axios from "axios"; + +import { useDexyStore } from "../../../../store"; +import constants from "../../../../util/Constants"; + +function AvailableTab() { +// fetch( +// `/api/codex/v1/storage/request/${cid}`, +// { +// headers: +// (nodeInfo.auth !== null && { +// Authorization: +// (nodeInfo.auth && "Basic " + btoa(nodeInfo.auth)) || "", +// }) || +// {}, +// body: JSON.stringify({ +// reward: reward, +// duration: duration, +// proofProbability: proofProbability, +// collateral: collateral +// }) +// } +// ) +// // create a popup in the browser to show if the upload was successful +// .then((response) => { +// if (response.status === 200) { +// alert("Upload successful!"); +// } else { +// alert("Upload failed!"); +// } +// }) +// } + return ( + + {/*
0 ? "60vh" : "0%", + }} + > + {uploads.map((file) => ( + + ))} +
*/} +
+ ); +} + +export default AvailableTab; + +const AvailableTabWrapper = styled.div` + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100%; + width: 100%; + padding: 16px; + + #dropzone { + flex: 1; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + width: 100%; + border: 2px dashed #9e9e9e; + border-radius: 8px; + } + + p { + font-size: 1rem; + text-align: center; + } + + #uploaded-items-wrap { + display: flex; + flex-direction: column; + align-items: center; + justify-content: start; + width: 100%; + overflow-y: scroll; + margin-top: 16px; + } +`; diff --git a/frontend/src/store.ts b/frontend/src/store.ts index 19a17b2..b01be82 100644 --- a/frontend/src/store.ts +++ b/frontend/src/store.ts @@ -1,7 +1,7 @@ import { create } from "zustand"; import { persist } from "zustand/middleware"; import UploadedItemModel from "./data/models/UploadedItemModel"; - +import RequestForStorageContractModel from "./data/models/RequestForStorageContractModel"; interface NodeInfo { baseUrl: string; nodeToConnectTo: string | null; @@ -14,6 +14,8 @@ interface NodeInfo { interface DexyState { uploads: UploadedItemModel[]; setUploads: (uploads: UploadedItemModel[]) => void; + storageRequests: RequestForStorageContractModel[]; + setStorageRequests: (storageRequests: RequestForStorageContractModel[]) => void; ftdCid: string; setFtdCid: (cid: string) => void; nodeInfo: NodeInfo; @@ -25,6 +27,8 @@ export const useDexyStore = create()( (set, get) => ({ uploads: [], setUploads: (uploads) => set({ uploads }), + storageRequests: [], + setStorageRequests: (storageRequests) => set({ storageRequests }), ftdCid: "", setFtdCid: (cid) => set({ ftdCid: cid }), nodeInfo: {