Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add: walruz fie storage #132

Merged
merged 1 commit into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 125 additions & 0 deletions components/walrus/FileStorage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import React, { useState, useRef } from 'react';
import axios from 'axios';
import { FiUploadCloud, FiDownload, FiShare2 } from 'react-icons/fi';

const PUBLISHER = 'https://publisher-devnet.walrus.space';
const AGGREGATOR = 'https://aggregator-devnet.walrus.space';

interface FileInfo {
name: string;
blobId: string;
}

const FileStorage: React.FC = () => {
const [files, setFiles] = useState<FileInfo[]>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const fileInputRef = useRef<HTMLInputElement>(null);

const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.files) {
setLoading(true);
setError(null);
Array.from(e.target.files).forEach(uploadFile);
}
};

const uploadFile = async (file: File) => {
try {
const formData = new FormData();
formData.append('file', file);

const response = await axios.put(`${PUBLISHER}/v1/store`, formData, {
headers: { 'Content-Type': 'multipart/form-data' },
});

let blobId = '';
if (response.data.newlyCreated) {
blobId = response.data.newlyCreated.blobObject.blobId;
} else if (response.data.alreadyCertified) {
blobId = response.data.alreadyCertified.blobId;
}

setFiles(prev => [...prev, { name: file.name, blobId }]);
} catch (err) {
setError(`Failed to upload ${file.name}. Please try again.`);
console.error(err);
} finally {
setLoading(false);
}
};

const handleDownload = async (fileInfo: FileInfo) => {
try {
const response = await axios.get(`${AGGREGATOR}/v1/${fileInfo.blobId}`, {
responseType: 'blob',
});

const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', fileInfo.name);
document.body.appendChild(link);
link.click();
link.remove();
} catch (err) {
setError(`Failed to download ${fileInfo.name}. Please try again.`);
console.error(err);
}
};

const handleShare = (fileInfo: FileInfo) => {
const shareUrl = `${AGGREGATOR}/v1/${fileInfo.blobId}`;
navigator.clipboard.writeText(shareUrl);
alert(`Share link copied to clipboard: ${shareUrl}`);
};

return (
<div className="bg-[#202333] border border-[#0162FF] rounded-3xl p-6 w-full h-[400px] flex flex-col">
<h2 className="text-2xl font-semibold text-white mb-4">File Storage</h2>

<div
className="flex-shrink-0 flex flex-col items-center justify-center border-2 border-dashed border-[#0162FF] rounded-xl p-6 mb-4 cursor-pointer"
onClick={() => fileInputRef.current?.click()}
>
<FiUploadCloud className="text-[#0162FF] text-6xl mb-4" />
<p className="text-white text-lg mb-2">Click or drag files to upload</p>
<p className="text-gray-400 text-sm">Supports any file type</p>
<input
type="file"
ref={fileInputRef}
onChange={handleFileChange}
className="hidden"
multiple
/>
</div>

{loading && <p className="text-white mb-4">Uploading...</p>}

<div className="flex-grow overflow-hidden">
{files.length > 0 && (
<div className="bg-[#2A2D3E] rounded-xl p-4 h-full overflow-y-auto">
<h3 className="text-white font-semibold mb-2">Uploaded Files</h3>
{files.map((fileInfo, index) => (
<div key={index} className="flex items-center justify-between text-white py-2 border-b border-gray-700 last:border-b-0">
<span className="truncate flex-grow">{fileInfo.name}</span>
<div className="flex space-x-2">
<button onClick={() => handleDownload(fileInfo)} className="p-1 hover:bg-[#0162FF] rounded">
<FiDownload />
</button>
<button onClick={() => handleShare(fileInfo)} className="p-1 hover:bg-[#0162FF] rounded">
<FiShare2 />
</button>
</div>
</div>
))}
</div>
)}
</div>

{error && <p className="text-red-500 mt-2">{error}</p>}
</div>
);
};

export default FileStorage;
9 changes: 8 additions & 1 deletion pages/subscription.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import Image from "next/image";
import SingleSignerTransaction from "../components/transactionFlow/SingleSigner";
import SaveToWalrusButton from "../components/walrus/SaveToWalrusButton";
import DownloadFromWalrusButton from "../components/walrus/DownloadFromWalrusButton";
import FileStorage from "../components/walrus/FileStorage";
const REACT_APP_GATEWAY_URL = process.env.NEXT_PUBLIC_GATEWAY_URL;
const EREBRUS_GATEWAY_URL = process.env.NEXT_PUBLIC_EREBRUS_BASE_URL;
const mynetwork = process.env.NEXT_PUBLIC_NETWORK;
Expand Down Expand Up @@ -843,7 +844,8 @@ const Subscription = () => {
</div>
)}

<div className="flex gap-10 w-1/2">
<div className="flex justify-between">
<div className="w-1/2">
{nftdata && (
<div className="w-1/2">
<NftdataContainer
Expand Down Expand Up @@ -940,6 +942,11 @@ const Subscription = () => {
</div>
</div>
)}
</div>

<div className="h-auto ">
<FileStorage />
</div>
</div>
</>
)}
Expand Down