Skip to content

Commit

Permalink
[Feature] generate input fields, syntax highlighting, light mode (Pro…
Browse files Browse the repository at this point in the history
…vableHQ#696)

* loading stash

* using link for router

* program form

* load program abstracted

* trailing return

* code editor

* dark mode switch

* tweaks

* new light code theme, auto add .aleo, flashing height fix

* resizable code editor

* auto .aleo refinement

* conditional on-chain forms

* before collapse

* collapse working

* refactor

* nested structs and records

* tweaks

* kind of working, before refactor

* before wasm fix

* working with wasm fix

* execute offline working

* modal and demo

* success and error execution response working

* fee estimation

* on-chain execution, fixing collapse key, estimate fee tweaks, on-chain rules

* setting up routing, preventing popping effect for code editor

* removing debugging, catching error case

* Update website/src/tabs/develop/execute/CodeEditor.jsx

Co-authored-by: Collin Chin <[email protected]>
Signed-off-by: Brent C <[email protected]>

* clarifying modal state

* fixing nested serialization

---------

Signed-off-by: Brent C <[email protected]>
Co-authored-by: Collin Chin <[email protected]>
  • Loading branch information
Brent C and collinc97 authored Aug 1, 2023
1 parent 106ebaf commit 429bd68
Show file tree
Hide file tree
Showing 10 changed files with 1,167 additions and 59 deletions.
1 change: 1 addition & 0 deletions website/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ module.exports = {
plugins: ["react-refresh"],
rules: {
"react-refresh/only-export-components": "warn",
"react/prop-types":"off"
},
};
407 changes: 406 additions & 1 deletion website/package-lock.json

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@
"dependencies": {
"@aleohq/wasm": "file:../wasm/pkg-parallel",
"@ant-design/icons": "^4.4.0",
"@codemirror/language": "^6.8.0",
"@codemirror/legacy-modes": "^6.3.3",
"@codemirror/stream-parser": "^0.19.9",
"@uiw/codemirror-theme-noctis-lilac": "^4.21.8",
"@uiw/codemirror-theme-okaidia": "^4.21.7",
"@uiw/react-codemirror": "^4.21.7",
"antd": "^5.6.4",
"axios": "^1.1.3",
"babel-loader": "^8.2.3",
Expand Down
20 changes: 1 addition & 19 deletions website/src/App.css
Original file line number Diff line number Diff line change
@@ -1,26 +1,8 @@
.logo {
height: 32px;
margin: 16px;
}

.logo:before {
content: "Aleo SDK";
color: white;
font-size: 20px;
font-weight: bold;
}

/*
* Input (disabled) - Make box appear not disabled
*
* https://www.w3schools.com/cssref/pr_class_cursor.asp
*/
input[type="text"]:disabled {
cursor: text;
}

/* Copy to clipboard icon formatting */
.ant-input-group-addon:last-child {
border-radius: 20px;
width: 42px;
}
}
98 changes: 62 additions & 36 deletions website/src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import "./App.css";
import { useEffect, useState } from "react";
import { ConfigProvider, Layout, Menu, theme } from "antd";
import { Outlet, useLocation, useNavigate } from "react-router-dom";
import { ConfigProvider, Layout, Menu, Switch, theme, Typography } from "antd";
import { Link, Outlet, useLocation, useNavigate } from "react-router-dom";

import {
ApiOutlined,
Expand All @@ -10,10 +10,44 @@ import {
SwapOutlined,
ToolOutlined,
UserOutlined,
FormatPainterOutlined,
FireOutlined,
} from "@ant-design/icons";

const { Content, Footer, Sider } = Layout;

const menuItems = [
{
label: <Link to="/account">Account</Link>,
key: "/account",
icon: <UserOutlined />,
},
{
label: <Link to="/record">Record</Link>,
key: "/record",
icon: <ProfileOutlined />,
},
{
label: <Link to="/rest">REST API</Link>,
key: "/rest",
icon: <ApiOutlined />,
},
{
label: <Link to="/advanced">Advanced</Link>,
key: "/advanced",
icon: <ToolOutlined />,
},
{
label: <Link to="/develop">Develop</Link>,
key: "/develop",
icon: <CodeOutlined />,
},
{
label: <Link to="/transfer">Transfer</Link>,
key: "transfer",
icon: <SwapOutlined />,
},
];
function App() {
const [menuIndex, setMenuIndex] = useState("account");

Expand All @@ -30,57 +64,49 @@ function App() {
}
}, [location, navigate]);

const menuItems = [
{
label: "Account",
key: "/account",
icon: <UserOutlined />,
},
{
label: "Record",
key: "/record",
icon: <ProfileOutlined />,
},
{
label: "REST API",
key: "/rest",
icon: <ApiOutlined />,
},
{
label: "Advanced",
key: "/advanced",
icon: <ToolOutlined />,
},
{
label: "Develop",
key: "/develop",
icon: <CodeOutlined />,
},
{
label: "Transfer",
key: "transfer",
icon: <SwapOutlined />,
},
];
const [darkMode, setDarkMode] = useState(true);

return (
<ConfigProvider
theme={{
algorithm: theme.darkAlgorithm,
algorithm: darkMode
? theme.darkAlgorithm
: theme.defaultAlgorithm,
token: {
colorPrimary: "#18e48f",
},
}}
>
<Layout style={{ minHeight: "100vh" }}>
<Sider breakpoint="lg" collapsedWidth="0" theme="light">
<div alt="Aleo SDK Logo" className="logo"></div>
<Typography.Title
level={4}
alt="Aleo SDK Logo"
style={{
margin: "16px",
fontWeight: "bold",
whiteSpace: "nowrap",
}}
>
Aleo SDK
</Typography.Title>
<Menu
theme="light"
mode="inline"
selectedKeys={[menuIndex]}
items={menuItems}
onClick={onClick}
/>
<Switch
style={{
marginTop: "24px",
marginLeft: "24px",
}}
checked={darkMode}
onChange={(value) => setDarkMode(value)}
checkedChildren="Dark"
unCheckedChildren="Light"
/>
</Sider>
<Layout>
<Content style={{ padding: "50px 50px" }}>
Expand Down
11 changes: 10 additions & 1 deletion website/src/routing.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ import { GetProgram } from "./tabs/rest/GetProgram.jsx";
import { GetTransaction } from "./tabs/rest/GetTransaction.jsx";
import { EncryptAccount } from "./tabs/advanced/EncryptAccount.jsx";
import { DecryptAccount } from "./tabs/advanced/DecryptAccount.jsx";
import { Execute } from "./tabs/develop/Execute.jsx";
import { ExecuteLegacy } from "./tabs/develop/ExecuteLegacy.jsx";
import { Deploy } from "./tabs/develop/Deploy.jsx";
import { Transfer } from "./tabs/develop/Transfer.jsx";
import { Split } from "./tabs/develop/Split.jsx";
import { Join } from "./tabs/develop/Join.jsx";
import { Execute } from "./tabs/develop/execute/";
import { GetMappingNames } from "./tabs/rest/GetMappingNames.jsx";
import { GetMappingValue } from "./tabs/rest/GetMappingValue.jsx";

Expand Down Expand Up @@ -108,6 +109,14 @@ export const router = createBrowserRouter([
</>
),
},
{
path: "/execute_legacy",
element: (
<>
<ExecuteLegacy />
</>
),
},
],
},
]);
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import init, * as aleo from "@aleohq/wasm";

await init();

export const Execute = () => {
export const ExecuteLegacy = () => {
const [executionFeeRecord, setExecutionFeeRecord] = useState(null);
const [executeUrl, setExecuteUrl] = useState("https://vm.aleo.org/api");
const [functionID, setFunctionID] = useState(null);
Expand Down Expand Up @@ -211,7 +211,9 @@ export const Execute = () => {
setProgramResponse(null);
setTransactionID(null);
setExecutionError(null);
messageApi.info("Disclaimer: Fee estimation is experimental and may not represent a correct estimate on any current or future network");
messageApi.info(
"Disclaimer: Fee estimation is experimental and may not represent a correct estimate on any current or future network",
);
setTip("Estimating Execution Fee...");
let functionInputs = [];
try {
Expand Down
84 changes: 84 additions & 0 deletions website/src/tabs/develop/execute/CodeEditor.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import CodeMirror from "@uiw/react-codemirror";
import { okaidia } from "@uiw/codemirror-theme-okaidia";
import { noctisLilac } from "@uiw/codemirror-theme-noctis-lilac";
import { simpleMode } from "@codemirror/legacy-modes/mode/simple-mode";
import { StreamLanguage } from "@codemirror/language";
import { theme } from "antd";
import { useState } from "react";

const aleoSyntaxHighlight = {
start: [
{
regex: /(?:^|\s)(function|program|as|by|interface|closure|into|import)(?:$|\s)/,
token: "keyword",
},
{
regex: /(?:^|\s)(finalize|mapping)(?:$|\s)/,
token: "atom",
},
{
regex: /(?:^|\s)(abs.w|abs|add.w|add|and|assert|assert.eq|assert.neq|block.height|branch.eq|branch.neq|call|cast|cast.loosy|commit.bhp256|commit.bhp512|commit.bhp768|commit.bhp1024|commit.ped64|commit.ped128|div.w|div|double|gt|gte|hash.bhp256|hash.bhp512|hash.bhp768|hash.bhp1024|hash.ped64|hash.ped128|hash.psd2|hash.psd4|hash.psd8|inv|input|is.eq|is.neq|lt|lte|key|mod|mul.w|mul|nand|neg|nor|not|or|output|position|pow.w|pow|rand.chacha|rem.w|rem|shl.w|shl|shr.w|srh|sqrt|sub.w|sub|square|ternary|value|xor|get.or_use|get|set|contains|remove)(?:$|\s)/,
token: "property",
},
{
regex: /(?:field|group|address|scalar|u8|u16|u32|u64|u128|i8|i16|i32|i64|i128)\b/,
token: "number",
},
{
regex: /\.(constant|public|private|record|aleo)\b/,
token: "type",
},
{
regex: /(?:^|\s)(record)(?:$|\s)/,
token: "type",
},
{
regex: /\b([0-9]+)([ui](8|16|32|64|128))?\b/,
token: "number",
},
{
regex: /[cr][0-9]+/,
token: "variable",
},
],
};

export function CodeEditor({ value, onChange }) {
const [isFocused, setIsFocused] = useState(false);
const { token } = theme.useToken();

return (
<section
style={{
overflow: "auto",
borderRadius: token.borderRadius,
height: "300px",
outline: isFocused
? `1px solid ${token.colorPrimaryHover}`
: "none",
boxShadow: isFocused
? `0 0 0 ${token.controlOutlineWidth + 1}px ${
token.controlOutline
}`
: "none",
}}
>
<CodeMirror
style={{
overflow: "auto",
borderRadius: token.borderRadius,
}}
value={value}
extensions={[
StreamLanguage.define(simpleMode(aleoSyntaxHighlight)),
]}
theme={token.colorBgBase === "#000" ? okaidia : noctisLilac}
onChange={onChange}
height="300px"
option={{ indentUnit: 4 }}
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
/>
</section>
);
}
56 changes: 56 additions & 0 deletions website/src/tabs/develop/execute/LoadProgram.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { useState } from "react";
import { Form, Input } from "antd";
import axios from "axios";

export const LoadProgram = ({ onResponse }) => {
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
const form = Form.useFormInstance();

const onProgramSearch = (value) => {
if (!value || value.trim() === "") {
setError("Please input a program");
return;
}

if (!value.endsWith(".aleo") && !value.includes(".")) {
value += ".aleo";
form.setFieldsValue({
program_id: value,
});
}

setIsLoading(true);
const url = `https://vm.aleo.org/api/testnet3/program/${value}`;

axios
.get(url)
.then((response) => {
setIsLoading(false);
setError(null);
onResponse(response.data);
})
.catch((error) => {
setIsLoading(false);
setError(error.response?.data || error.message);
onResponse("");
});
};

return (
<Form.Item
label="Load Program"
name="program_id"
tooltip="Optionally load program from REST API"
help={error || ""}
validateStatus={error ? "warning" : ""}
>
<Input.Search
placeholder="Program ID"
onSearch={onProgramSearch}
disabled={isLoading}
loading={isLoading}
/>
</Form.Item>
);
};
Loading

0 comments on commit 429bd68

Please sign in to comment.