Better ui

This commit is contained in:
Pavel Murygin
2021-07-22 02:27:32 +03:00
parent 5a787dcf22
commit aa094a9f1d
9 changed files with 154 additions and 201 deletions

View File

@ -3,7 +3,7 @@ $color2: rgb(214, 214, 214);
$accent-color: rgb(225, 30, 90);
.logo {
height: 15vmin;
height: 10vmin;
pointer-events: none;
}
@ -16,7 +16,7 @@ $accent-color: rgb(225, 30, 90);
}
header {
margin-top: 10vmin;
margin-top: 3vmin;
}
header,
@ -44,23 +44,13 @@ li {
padding: 0;
}
.p {
width: 550px;
p {
margin: 0.5em;
text-align: left;
}
.btn-clipboard {
border: none;
background-color: transparent;
cursor: pointer;
&:hover,
&:focus {
color: $accent-color;
}
&:focus {
outline: none;
}
.row {
width: 100%;
}
.btn {
@ -88,27 +78,49 @@ li {
}
}
.btn-hello {
width: 200px;
.btn-right {
width: 250px;
display: inline;
float: right;
}
.btn-inline {
background-color: transparent;
margin: 5px;
display: inline;
border: none;
font-size: inherit;
font-family: inherit;
color: $accent-color;
outline: none;
&:hover,
&:focus {
outline: none;
text-decoration: underline;
cursor: pointer;
}
}
table {
text-align: right;
}
.label {
width: 240px;
width: 30%;
display: inline-block;
text-align: right;
margin-right: 5px;
}
.input {
width: 500px;
width: calc(70% - 15px);
height: 26px;
box-sizing: border-box;
margin: 5px;
padding: 0 5px;
border: 1px solid;
border-color: $color2;
@ -125,75 +137,15 @@ table {
}
}
.gg-clipboard {
.input-ro {
display: inline;
width: 500px;
height: 26px;
box-sizing: border-box;
position: relative;
display: block;
transform: scale(var(--ggs, 1));
width: 18px;
height: 18px;
border: 2px solid;
border-radius: 2px;
}
.gg-clipboard::after,
.gg-clipboard::before {
content: "";
display: block;
box-sizing: border-box;
position: absolute;
border-radius: 2px;
width: 10px;
left: 2px;
}
.gg-clipboard::before {
border: 2px solid;
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
top: -2px;
height: 6px;
}
.gg-clipboard::after {
height: 2px;
background: currentColor;
box-shadow: 0 -4px 0 0;
bottom: 2px;
margin: 5px;
}
.gg-trash {
box-sizing: border-box;
position: relative;
display: block;
transform: scale(var(--ggs, 1));
width: 10px;
height: 12px;
border: 2px solid transparent;
box-shadow: 0 0 0 2px, inset -2px 0 0, inset 2px 0 0;
border-bottom-left-radius: 1px;
border-bottom-right-radius: 1px;
margin-top: 4px;
}
.gg-trash::after,
.gg-trash::before {
content: "";
display: block;
box-sizing: border-box;
position: absolute;
}
.gg-trash::after {
background: currentColor;
border-radius: 3px;
width: 16px;
height: 2px;
top: -4px;
left: -5px;
}
.gg-trash::before {
width: 10px;
height: 4px;
border: 2px solid;
border-bottom: transparent;
border-top-left-radius: 2px;
border-top-right-radius: 2px;
top: -7px;
left: -2px;
.article {
margin-bottom: 10px;
}

View File

@ -2,18 +2,25 @@ import React from "react";
import logo from "./logo.svg";
import "./App.scss";
import { gotRpcAddrState, isConnectedState, isDeployedState } from "./state";
import {
gotRpcAddrState,
hasResultState,
isConnectedState,
isDeployedState,
} from "./state";
import { useRecoilValue } from "recoil";
import { ConnectedInfo } from "./Components/ConnectedInfo";
import { ConnectionForm } from "./Components/ConnectionForm";
import { IpfsForm } from "./Components/IpfsForm";
import { IpfsDeploymentInfo } from "./Components/IpfsDeploymentInfo";
import { SizeCalcForm } from "./Components/SizeCalcForm";
import { SizeCalcResult } from "./Components/SizeCalcResult";
function App() {
const isConnected = useRecoilValue(isConnectedState);
const gotRpcAddr = useRecoilValue(gotRpcAddrState);
const isDeployed = useRecoilValue(isDeployedState);
const hasResult = useRecoilValue(hasResultState);
console.log(
"isConnected gotRpcAddr deployed\n",
@ -38,6 +45,7 @@ function App() {
<SizeCalcForm />
</>
)}
{isDeployed && hasResult && <SizeCalcResult />}
</div>
</div>
);

View File

@ -1,6 +1,6 @@
import { useRecoilValue } from "recoil";
import { clientState } from "../state";
import { copyToClipboard } from "../util";
import { TextWithLabel } from "./TextInput";
export const ConnectedInfo = () => {
const client = useRecoilValue(clientState);
@ -11,34 +11,8 @@ export const ConnectedInfo = () => {
return (
<>
<h1>Connected</h1>
<table>
<thead>
<tr>
<td className="bold">Peer id:</td>
<td className="mono">{client.selfPeerId}</td>
<td>
<button
className="btn-clipboard"
onClick={() => copyToClipboard(client.selfPeerId)}
>
<i className="gg-clipboard"></i>
</button>
</td>
</tr>
<tr>
<td className="bold">Relay peer id:</td>
<td className="mono">{client.relayPeerId}</td>
<td>
<button
className="btn-clipboard"
onClick={() => copyToClipboard(client.relayPeerId!)}
>
<i className="gg-clipboard"></i>
</button>
</td>
</tr>
</thead>
</table>
<TextWithLabel text={"Peer id:"} value={client.selfPeerId} />
<TextWithLabel text={"Relay peer id:"} value={client.selfPeerId} />
</>
);
};

View File

@ -1,36 +1,29 @@
import { useRecoilValue } from "recoil";
import { serviceIdState, useRemoveServuce, wasmState } from "../state";
import { serviceIdState, useRemoveService, wasmState } from "../state";
import { copyToClipboard } from "../util";
import { TextWithLabel } from "./TextInput";
export const IpfsDeploymentInfo = () => {
const wasm = useRecoilValue(wasmState);
const serviceId = useRecoilValue(serviceIdState);
const removeService = useRemoveServuce;
const removeService = useRemoveService();
return (
<>
<h2>Deployed</h2>
<table>
<tr>
<td className="bold">process_files.wasm CID:</td>
<td className="mono">{wasm}</td>
<td>
<button
className="btn-clipboard"
onClick={() => copyToClipboard(wasm)}
>
<i className="gg-clipboard"></i>
<h2>
Service deployed{" "}
<button className="btn-inline" onClick={removeService}>
remove
</button>
</td>
</tr>
<tr>
<td className="bold">ProcessFiles service ID:</td>
<td className="mono">{serviceId}</td>
<button className="btn-clipboard" onClick={removeService}>
<i className="gg-trash"></i>
</button>
</tr>
</table>
</h2>
<div className="article">
<p>
Service deployed into Fluence network. You can observe it's service ID
as well as the CID of the wasm file used to create the service
</p>
</div>
<TextWithLabel text={"CID:"} value={wasm} />
<TextWithLabel text={"Service ID:"} value={serviceId} />
</>
);
};

View File

@ -9,17 +9,19 @@ export const IpfsForm = () => {
return (
<>
<h2>Ipfs</h2>
<h2>Deploy service from IPFS</h2>
<div className="article">
<p>Now we can deploy service from IPFS into Fluence network</p>
<p>
process_files.wasm will be downloaded via IPFS to the Fluence node, and
then a service will be dynamically created from it! After that, you will
be able to use that service to get sizes of IPFS files!
<br />
To do so, please specify IPFS RPC address to download process_files.wasm
from
<br />
And specify CID of WebAssembly module.
process_files.wasm will be downloaded via IPFS to the Fluence node,
and then a service will be dynamically created from it! After that,
you will be able to use that service to get sizes of IPFS files!
</p>
<p>
To do so, please specify IPFS RPC address of process_files.wasm from,
and the CIP of WebAssembly module to use (process_files.wasm)
</p>
</div>
<TextInput
text={"IPFS RPC address"}
@ -33,7 +35,7 @@ export const IpfsForm = () => {
setValue={setWasm}
/>
<div className="row">
<button className="btn btn-hello" onClick={deployService}>
<button className="btn btn-right" onClick={deployService}>
deploy service
</button>
</div>

View File

@ -1,56 +1,30 @@
import { useRecoilState, useRecoilValue } from "recoil";
import {
fileCIDState,
fileSizeCIDState,
fileSizeState,
rpcAddrState,
useGetFileSize,
} from "../state";
import { fileCIDState, rpcAddrState, useGetFileSize } from "../state";
import { TextInput } from "./TextInput";
export const SizeCalcForm = () => {
const rpcAddr = useRecoilValue(rpcAddrState);
const [fileCID, setFileCID] = useRecoilState(fileCIDState);
const fileSize = useRecoilValue(fileSizeState);
const fileSizeCID = useRecoilValue(fileSizeCIDState);
const getFileSize = useGetFileSize();
return (
<>
<div>
<h2>Get file size</h2>
<p className="p">
Upload any file to IPFS node
<div className="article">
<p>
Upload any file to IPFS node
<b>{rpcAddr}</b>
</p>
paste CID here and get the size of that file via ProcessFiles service
you have just deployed
</p>
<div className="row">
<label className="label bold">IPFS CID</label>
<input
className="input"
type="text"
onChange={(e) => setFileCID(e.target.value)}
value={fileCID}
/>
</div>
<TextInput text={"IPFS CID"} value={fileCID} setValue={setFileCID} />
<div className="row">
<button className="btn btn-hello" onClick={getFileSize}>
<button className="btn btn-right" onClick={getFileSize}>
get size
</button>
</div>
</div>
<div className="row">
<label className="label bold">File Size:</label>
<label className="mono">{fileSize}</label>
</div>
<div className="row">
<label className="label bold">
File size is uploaded to IPFS as CID:
</label>
<label className="mono">{fileSizeCID}</label>
</div>
</>
);
};

View File

@ -0,0 +1,23 @@
import { useRecoilValue } from "recoil";
import { fileSizeCIDState, fileSizeState } from "../state";
import { TextWithLabel } from "./TextInput";
export const SizeCalcResult = () => {
const fileSize = useRecoilValue(fileSizeState);
const fileSizeCID = useRecoilValue(fileSizeCIDState);
return (
<>
<h2>Result</h2>
<div className="article">
<p>
File size has been calculated and displayed below. Also the result of
the calculation has been uploaded to IPFS and is available under it's
CID
</p>
</div>
<TextWithLabel text="File size:" value={fileSize} />
<TextWithLabel text="File size IPFS CID:" value={fileSizeCID} />
</>
);
};

View File

@ -18,3 +18,15 @@ export const TextInput = (props: {
</div>
);
};
export const TextWithLabel = (props: {
text: string;
value: string | null;
}) => {
return (
<div className="row">
<label className="label bold">{props.text}</label>
<div className="input-ro">{props.value || ""}</div>
</div>
);
};

View File

@ -38,19 +38,19 @@ export const rpcAddrState = atom<string | null>({
default: null,
});
export const fileCIDState = atom<string>({
export const fileCIDState = atom<string | null>({
key: "fileCIDState",
default: "",
default: null,
});
export const fileSizeState = atom<string>({
export const fileSizeState = atom<string | null>({
key: "fileSizeState",
default: "",
default: null,
});
export const fileSizeCIDState = atom<string>({
export const fileSizeCIDState = atom<string | null>({
key: "fileSizeCIDState",
default: "",
default: null,
});
export const isConnectedState = selector({
@ -81,6 +81,14 @@ export const isDeployedState = selector({
},
});
export const hasResultState = selector({
key: "hasResultState",
get: ({ get }) => {
const fileSize = get(fileSizeState);
return fileSize !== null;
},
});
const getRpcAddr = async (client: FluenceClient) => {
if (client === null) {
console.log("getRpcAddr client is null");
@ -140,8 +148,9 @@ export const useGetFileSize = () => {
const rpcAddr = useRecoilValue(rpcAddrState);
const client = useRecoilValue(clientState);
const serviceId = useRecoilValue(serviceIdState);
const fileCID = useRecoilValue(fileCIDState);
const setFileSize = useSetRecoilState(fileSizeState);
const [fileCID, setFileSizeCID] = useRecoilState(fileCIDState);
const setFileSizeCID = useSetRecoilState(fileSizeCIDState);
return async () => {
if (client === null || serviceId === null || rpcAddr === null) {
@ -151,7 +160,7 @@ export const useGetFileSize = () => {
var putResult = await put_file_size(
client,
client.relayPeerId!,
fileCID,
fileCID!,
rpcAddr,
serviceId,
(size) => setFileSize(size.toString()),
@ -170,9 +179,12 @@ export const useGetFileSize = () => {
};
};
export const useRemoveServuce = () => {
export const useRemoveService = () => {
const client = useRecoilValue(clientState);
const [serviceId, setServiceId] = useRecoilState(serviceIdState);
const setFileCID = useSetRecoilState(fileCIDState);
const setFileSize = useSetRecoilState(fileSizeState);
const setFileSizeCID = useSetRecoilState(fileSizeCIDState);
return async () => {
if (client === null || serviceId === null) {
@ -183,5 +195,8 @@ export const useRemoveServuce = () => {
ttl: 10000,
});
setServiceId(null);
setFileCID(null);
setFileSize(null);
setFileSizeCID(null);
};
};