Refactor reusable components

pull/5770/head
ioedeveloper 1 month ago committed by Aniket
parent 17abed26a7
commit 30279d5d99
  1. 9
      apps/circuit-compiler/src/app/components/actions.tsx
  2. 49
      apps/circuit-compiler/src/app/components/compileBtn.tsx
  3. 14
      apps/circuit-compiler/src/app/components/container.tsx
  4. 36
      apps/circuit-compiler/src/app/components/options.tsx
  5. 16
      apps/noir-compiler/src/app/actions/index.ts
  6. 9
      apps/noir-compiler/src/app/app.tsx
  7. 37
      apps/noir-compiler/src/app/components/container.tsx
  8. 34
      apps/noir-compiler/src/app/reducers/state.ts
  9. 18
      apps/noir-compiler/src/app/types/index.ts
  10. 101
      apps/noir-compiler/src/css/app.css
  11. 2
      apps/noir-compiler/webpack.config.js
  12. 76
      libs/remix-ui/helper/src/lib/helper-components.tsx
  13. 6
      libs/remix-ui/helper/src/types/compilerTypes.ts

@ -1,9 +0,0 @@
import { CompileBtn } from "./compileBtn"
export function CircuitActions () {
return (
<div className="pb-2">
<CompileBtn />
</div>
)
}

@ -1,49 +0,0 @@
import { CustomTooltip, RenderIf, RenderIfNot, extractNameFromKey } from "@remix-ui/helper";
import { useContext } from "react";
import { CircuitAppContext } from "../contexts";
import { FormattedMessage } from "react-intl";
import { compileCircuit } from "../actions";
export function CompileBtn () {
const { plugin, appState } = useContext(CircuitAppContext)
return (
<CustomTooltip
placement="auto"
tooltipId="overlay-tooltip-compile"
tooltipText={
<div className="text-left">
<div>
<b>Ctrl+S</b> to compile {appState.filePath}
</div>
</div>
}
>
<button
className="btn btn-primary btn-block d-block w-100 text-break mb-1 mt-1"
onClick={() => { compileCircuit(plugin, appState) }}
disabled={(appState.filePath === "") || (appState.status === "compiling")}
data-id="compile_circuit_btn"
>
<div className="d-flex align-items-center justify-content-center">
<RenderIf condition={appState.status === 'compiling'}>
<i className="fas fa-sync fa-spin mr-2" aria-hidden="true"></i>
</RenderIf>
<div className="text-truncate overflow-hidden text-nowrap">
<span>
<FormattedMessage id="circuit.compile" />
</span>
<span className="ml-1 text-nowrap">
<RenderIf condition={appState.filePath === ""}>
<FormattedMessage id="circuit.noFileSelected" />
</RenderIf>
<RenderIfNot condition={appState.filePath === ""}>
<>{extractNameFromKey(appState.filePath)}</>
</RenderIfNot>
</span>
</div>
</div>
</button>
</CustomTooltip>
)
}

@ -1,17 +1,17 @@
import { useContext } from 'react' import { useContext } from 'react'
import { CustomTooltip, RenderIf } from '@remix-ui/helper' import { CompileBtn, CustomTooltip, RenderIf } from '@remix-ui/helper'
import { FormattedMessage } from 'react-intl' import { FormattedMessage } from 'react-intl'
import { CircuitAppContext } from '../contexts' import { CircuitAppContext } from '../contexts'
import { CompileOptions } from './options' import { CompileOptions } from '@remix-ui/helper'
import { VersionList } from './versions' import { VersionList } from './versions'
import { Toggler } from './toggler' import { Toggler } from './toggler'
import { Configurations } from './configurations' import { Configurations } from './configurations'
import { CircuitActions } from './actions'
import { WitnessSection } from './witness' import { WitnessSection } from './witness'
import { CompilerFeedback } from './feedback' import { CompilerFeedback } from './feedback'
import { CompilerReport, PrimeValue } from '../types' import { CompilerReport, PrimeValue } from '../types'
import { SetupExports } from './setupExports' import { SetupExports } from './setupExports'
import { GenerateProof } from './generateProof' import { GenerateProof } from './generateProof'
import { compileCircuit } from '../actions'
export function Container () { export function Container () {
const circuitApp = useContext(CircuitAppContext) const circuitApp = useContext(CircuitAppContext)
@ -102,6 +102,10 @@ export function Container () {
} }
} }
const handleCompileClick = () => {
compileCircuit(circuitApp.plugin, circuitApp.appState)
}
return ( return (
<section> <section>
<article> <article>
@ -123,7 +127,9 @@ export function Container () {
<Toggler title='circuit.advancedConfigurations' dataId=''> <Toggler title='circuit.advancedConfigurations' dataId=''>
<Configurations setPrimeValue={handlePrimeChange} primeValue={circuitApp.appState.primeValue} versionValue={circuitApp.appState.version} /> <Configurations setPrimeValue={handlePrimeChange} primeValue={circuitApp.appState.primeValue} versionValue={circuitApp.appState.version} />
</Toggler> </Toggler>
<CircuitActions /> <div className="pb-2">
<CompileBtn id='circuit' plugin={circuitApp.plugin} appState={circuitApp.appState} compileAction={handleCompileClick} />
</div>
<RenderIf condition={circuitApp.appState.status !== 'compiling'}> <RenderIf condition={circuitApp.appState.status !== 'compiling'}>
<CompilerFeedback feedback={circuitApp.appState.compilerFeedback} filePathToId={circuitApp.appState.filePathToId} openErrorLocation={handleOpenErrorLocation} hideWarnings={circuitApp.appState.hideWarnings} askGPT={askGPT} /> <CompilerFeedback feedback={circuitApp.appState.compilerFeedback} filePathToId={circuitApp.appState.filePathToId} openErrorLocation={handleOpenErrorLocation} hideWarnings={circuitApp.appState.hideWarnings} askGPT={askGPT} />
</RenderIf> </RenderIf>

@ -1,36 +0,0 @@
import {FormattedMessage} from 'react-intl'
import { CompileOptionsProps } from '../types'
export function CompileOptions ({autoCompile, hideWarnings, setCircuitAutoCompile, setCircuitHideWarnings}: CompileOptionsProps) {
return (
<div>
<div className="mt-2 custom-control custom-checkbox">
<input
className="custom-control-input"
type="checkbox"
onChange={(e) => setCircuitAutoCompile(e.target.checked)}
title="Auto compile"
checked={autoCompile}
id="autoCompileCircuit"
/>
<label className="form-check-label custom-control-label" htmlFor="autoCompileCircuit" data-id="auto_compile_circuit_checkbox_input">
<FormattedMessage id="circuit.autoCompile" />
</label>
</div>
<div className="mt-1 mb-2 circuit_warnings_box custom-control custom-checkbox">
<input
className="custom-control-input"
onChange={(e) => setCircuitHideWarnings(e.target.checked)}
id="hideCircuitWarnings"
type="checkbox"
title="Hide warnings"
checked={hideWarnings}
/>
<label className="form-check-label custom-control-label" htmlFor="hideCircuitWarnings" data-id="hide_circuit_warnings_checkbox_input">
<FormattedMessage id="solidity.hideWarnings" />
</label>
</div>
</div>
)
}

@ -0,0 +1,16 @@
import { NoirPluginClient } from "../services/noirPluginClient"
import { AppState } from "../types"
export const compileNoirCircuit = async (plugin: NoirPluginClient, appState: AppState) => {
try {
if (appState.status !== "compiling") {
await plugin.compile(appState.filePath)
} else {
console.log('Existing noir compilation in progress')
}
} catch (e) {
plugin.emit('statusChanged', { key: 'error', title: e.message, type: 'error' })
plugin.internalEvents.emit('noir_compiling_errored', e)
console.error(e)
}
}

@ -1,14 +1,15 @@
import { useEffect, useState } from "react" import { useEffect, useReducer, useState } from "react"
import { NoirPluginClient } from "./services/noirPluginClient" import { NoirPluginClient } from "./services/noirPluginClient"
import { RenderIf } from '@remix-ui/helper' import { RenderIf } from '@remix-ui/helper'
import { IntlProvider } from 'react-intl' import { IntlProvider } from 'react-intl'
import { Container } from "./components/container" import { Container } from "./components/container"
import { NoirAppContext } from "./contexts" import { NoirAppContext } from "./contexts"
import { appInitialState, appReducer } from "./reducers/state"
const plugin = new NoirPluginClient() const plugin = new NoirPluginClient()
function App() { function App() {
// const [appState, dispatch] = useReducer(appReducer, appInitialState) const [appState, dispatch] = useReducer(appReducer, appInitialState)
const [locale, setLocale] = useState<{code: string; messages: any}>({ const [locale, setLocale] = useState<{code: string; messages: any}>({
code: 'en', code: 'en',
messages: null messages: null
@ -40,7 +41,9 @@ function App() {
} }
const value = { const value = {
plugin plugin,
dispatch,
appState
} }
return ( return (

@ -1,7 +1,9 @@
import { useContext } from 'react' import { useContext } from 'react'
import { CustomTooltip, RenderIf } from '@remix-ui/helper' import { CompileBtn, CustomTooltip, RenderIf } from '@remix-ui/helper'
import { FormattedMessage } from 'react-intl' import { FormattedMessage } from 'react-intl'
import { NoirAppContext } from '../contexts' import { NoirAppContext } from '../contexts'
import { CompileOptions } from '@remix-ui/helper'
import { compileNoirCircuit } from '../actions'
export function Container () { export function Container () {
const noirApp = useContext(NoirAppContext) const noirApp = useContext(NoirAppContext)
@ -19,11 +21,6 @@ export function Container () {
} }
} }
// const handleVersionSelect = (version: string) => {
// circuitApp.plugin.compilerVersion = version
// circuitApp.dispatch({ type: 'SET_COMPILER_VERSION', payload: version })
// }
// const handleOpenErrorLocation = async (location: string, startRange: string) => { // const handleOpenErrorLocation = async (location: string, startRange: string) => {
// if (location) { // if (location) {
// const fullPathLocation = await circuitApp.plugin.resolveReportPath(location) // const fullPathLocation = await circuitApp.plugin.resolveReportPath(location)
@ -41,13 +38,13 @@ export function Container () {
// circuitApp.dispatch({ type: 'SET_PRIME_VALUE', payload: value as PrimeValue }) // circuitApp.dispatch({ type: 'SET_PRIME_VALUE', payload: value as PrimeValue })
// } // }
// const handleCircuitAutoCompile = (value: boolean) => { const handleCircuitAutoCompile = (value: boolean) => {
// circuitApp.dispatch({ type: 'SET_AUTO_COMPILE', payload: value }) noirApp.dispatch({ type: 'SET_AUTO_COMPILE', payload: value })
// } }
// const handleCircuitHideWarnings = (value: boolean) => { const handleCircuitHideWarnings = (value: boolean) => {
// circuitApp.dispatch({ type: 'SET_HIDE_WARNINGS', payload: value }) noirApp.dispatch({ type: 'SET_HIDE_WARNINGS', payload: value })
// } }
// const askGPT = async (report: CompilerReport) => { // const askGPT = async (report: CompilerReport) => {
// if (report.labels.length > 0) { // if (report.labels.length > 0) {
@ -92,6 +89,10 @@ export function Container () {
// } // }
// } // }
const handleCompileClick = () => {
compileNoirCircuit(noirApp.plugin, noirApp.appState)
}
return ( return (
<section> <section>
<article> <article>
@ -108,13 +109,11 @@ export function Container () {
> >
<span className="far fa-file-certificate border-0 p-0 ml-2" onClick={() => showCompilerLicense()}></span> <span className="far fa-file-certificate border-0 p-0 ml-2" onClick={() => showCompilerLicense()}></span>
</CustomTooltip> </CustomTooltip>
{/* <VersionList setVersion={handleVersionSelect} versionList={circuitApp.appState.versionList} currentVersion={circuitApp.appState.version} /> <CompileOptions setCircuitAutoCompile={handleCircuitAutoCompile} setCircuitHideWarnings={handleCircuitHideWarnings} autoCompile={noirApp.appState.autoCompile} hideWarnings={noirApp.appState.hideWarnings} />
<CompileOptions setCircuitAutoCompile={handleCircuitAutoCompile} setCircuitHideWarnings={handleCircuitHideWarnings} autoCompile={circuitApp.appState.autoCompile} hideWarnings={circuitApp.appState.hideWarnings} /> <div className="pb-2">
<Toggler title='circuit.advancedConfigurations' dataId=''> <CompileBtn id="noir" plugin={noirApp.plugin} appState={noirApp.appState} compileAction={handleCompileClick} />
<Configurations setPrimeValue={handlePrimeChange} primeValue={circuitApp.appState.primeValue} versionValue={circuitApp.appState.version} /> </div>
</Toggler> {/* <RenderIf condition={circuitApp.appState.status !== 'compiling'}>
<CircuitActions />
<RenderIf condition={circuitApp.appState.status !== 'compiling'}>
<CompilerFeedback feedback={circuitApp.appState.compilerFeedback} filePathToId={circuitApp.appState.filePathToId} openErrorLocation={handleOpenErrorLocation} hideWarnings={circuitApp.appState.hideWarnings} askGPT={askGPT} /> <CompilerFeedback feedback={circuitApp.appState.compilerFeedback} filePathToId={circuitApp.appState.filePathToId} openErrorLocation={handleOpenErrorLocation} hideWarnings={circuitApp.appState.hideWarnings} askGPT={askGPT} />
</RenderIf> */} </RenderIf> */}
</div> </div>

@ -0,0 +1,34 @@
import { Actions, AppState } from '../types'
export interface ActionPayloadTypes {
SET_AUTO_COMPILE: boolean,
SET_HIDE_WARNINGS: boolean
}
export const appInitialState: AppState = {
filePath: '',
filePathToId: {},
autoCompile: false,
hideWarnings: false,
status: 'idle'
}
export const appReducer = (state = appInitialState, action: Actions): AppState => {
switch (action.type) {
case 'SET_AUTO_COMPILE':
return {
...state,
autoCompile: action.payload
}
case 'SET_HIDE_WARNINGS':
return {
...state,
hideWarnings: action.payload
}
default:
throw new Error()
}
}

@ -1,18 +1,26 @@
import { compiler_list } from 'circom_wasm' import { compiler_list } from 'circom_wasm'
import { Dispatch } from 'react' import { Dispatch } from 'react'
import type { NoirPluginClient } from '../services/noirPluginClient' import type { NoirPluginClient } from '../services/noirPluginClient'
import { ActionPayloadTypes } from '../reducers/state'
export type CompilerStatus = "compiling" | "idle" | "errored" | "warning"
export interface INoirAppContext { export interface INoirAppContext {
// appState: AppState appState: AppState
// dispatch: Dispatch<Actions>, dispatch: Dispatch<Actions>,
plugin: NoirPluginClient plugin: NoirPluginClient
} }
export interface AppState { export interface AppState {
version: string,
versionList: typeof compiler_list.wasm_builds,
filePath: string, filePath: string,
filePathToId: Record<string, string>, filePathToId: Record<string, string>,
autoCompile: boolean, autoCompile: boolean,
hideWarnings: boolean hideWarnings: boolean,
status: CompilerStatus
} }
export interface Action<T extends keyof ActionPayloadTypes> {
type: T
payload: ActionPayloadTypes[T]
}
export type Actions = {[A in keyof ActionPayloadTypes]: Action<A>}[keyof ActionPayloadTypes]

@ -0,0 +1,101 @@
body {
font-size : .8rem;
}
.noir_section {
padding: 12px 24px 16px;
}
.noir_label {
margin-bottom: 2px;
font-size: 11px;
line-height: 12px;
text-transform: uppercase;
}
.noir_warnings_box {
display: flex;
align-items: center;
}
.noir_warnings_box label {
margin: 0;
}
.noir_config_section:hover {
cursor: pointer;
}
.noir_config_section {
font-size: 1rem;
}
.noir_config {
display: flex;
align-items: center;
}
.noir_config label {
margin: 0;
}
.noir_inner_label {
margin-bottom: 2px;
font-size: 11px;
line-height: 12px;
text-transform: uppercase;
}
.noir_errors_box {
word-break: break-word;
}
.noir_feedback.success,
.noir_feedback.error,
.noir_feedback.warning {
white-space: pre-line;
word-wrap: break-word;
cursor: pointer;
position: relative;
margin: 0.5em 0 1em 0;
border-radius: 5px;
line-height: 20px;
padding: 8px 15px;
}
.noir_feedback.success pre,
.noir_feedback.error pre,
.noir_feedback.warning pre {
white-space: pre-line;
overflow-y: hidden;
background-color: transparent;
margin: 0;
font-size: 12px;
border: 0 none;
padding: 0;
border-radius: 0;
}
.noir_feedback.success .close,
.noir_feedback.error .close,
.noir_feedback.warning .close {
visibility: hidden;
white-space: pre-line;
font-weight: bold;
position: absolute;
color: hsl(0, 0%, 0%); /* black in style-guide.js */
top: 0;
right: 0;
padding: 0.5em;
}
.noir_feedback.success a,
.noir_feedback.error a,
.noir_feedback.warning a {
bottom: 0;
right: 0;
}
.custom-dropdown-items {
padding: 0.25rem 0.25rem;
border-radius: .25rem;
background: var(--custom-select);
}
.custom-dropdown-items a {
border-radius: .25rem;
text-transform: none;
text-decoration: none;
font-weight: normal;
font-size: 0.875rem;
padding: 0.25rem 0.25rem;
width: auto;
color: var(--text);
}

@ -11,7 +11,7 @@ module.exports = composePlugins(withNx(), (config) => {
let pkgNoirWasm = fs.readFileSync(path.resolve(__dirname, '../../node_modules/@noir-lang/noir_wasm/package.json'), 'utf8') let pkgNoirWasm = fs.readFileSync(path.resolve(__dirname, '../../node_modules/@noir-lang/noir_wasm/package.json'), 'utf8')
let typeCount = 0 let typeCount = 0
pkgNoirWasm = pkgNoirWasm.replace("node", "./node").replace("import", "./import").replace("require", "./require").replace(/"types"/g, match => ++typeCount === 2 ? '"./types"' : match).replace("default", "./default") pkgNoirWasm = pkgNoirWasm.replace(/"node"/, '"./node"').replace(/"import"/, '"./import"').replace(/"require"/, '"./require"').replace(/"types"/g, match => ++typeCount === 2 ? '"./types"' : match).replace(/"default"/, '"./default"')
fs.writeFileSync(path.resolve(__dirname, '../../node_modules/@noir-lang/noir_wasm/package.json'), pkgNoirWasm) fs.writeFileSync(path.resolve(__dirname, '../../node_modules/@noir-lang/noir_wasm/package.json'), pkgNoirWasm)
console.log('pkgNoirWasm: ', pkgNoirWasm) console.log('pkgNoirWasm: ', pkgNoirWasm)

@ -1,5 +1,9 @@
import { LayoutCompatibilityReport } from '@openzeppelin/upgrades-core/dist/storage/report' import { LayoutCompatibilityReport } from '@openzeppelin/upgrades-core/dist/storage/report'
import React from 'react' import React from 'react'
import { FormattedMessage } from 'react-intl'
import { CompileOptionsProps } from '../types/compilerTypes'
import { CustomTooltip } from './components/custom-tooltip'
import { extractNameFromKey } from './remix-ui-helper'
export const fileChangedToastMsg = (from: string, path: string) => ( export const fileChangedToastMsg = (from: string, path: string) => (
<div> <div>
@ -142,3 +146,75 @@ export function RenderIf({ condition, children }: { condition: boolean, children
export function RenderIfNot({ condition, children }: { condition: boolean, children: JSX.Element }) { export function RenderIfNot({ condition, children }: { condition: boolean, children: JSX.Element }) {
return condition ? null : children return condition ? null : children
} }
export const CompileOptions = ({ autoCompile, hideWarnings, setCircuitAutoCompile, setCircuitHideWarnings }: CompileOptionsProps) => (
<div>
<div className="mt-2 custom-control custom-checkbox">
<input
className="custom-control-input"
type="checkbox"
onChange={(e) => setCircuitAutoCompile(e.target.checked)}
title="Auto compile"
checked={autoCompile}
id="autoCompileCircuit"
/>
<label className="form-check-label custom-control-label" htmlFor="autoCompileCircuit" data-id="auto_compile_circuit_checkbox_input">
<FormattedMessage id="circuit.autoCompile" />
</label>
</div>
<div className="mt-1 mb-2 circuit_warnings_box custom-control custom-checkbox">
<input
className="custom-control-input"
onChange={(e) => setCircuitHideWarnings(e.target.checked)}
id="hideCircuitWarnings"
type="checkbox"
title="Hide warnings"
checked={hideWarnings}
/>
<label className="form-check-label custom-control-label" htmlFor="hideCircuitWarnings" data-id="hide_circuit_warnings_checkbox_input">
<FormattedMessage id="solidity.hideWarnings" />
</label>
</div>
</div>
)
export const CompileBtn = ({ plugin, appState, id, compileAction }: { plugin: any, appState: { status, filePath }, id: string, compileAction: () => void }) => (
<CustomTooltip
placement="auto"
tooltipId="overlay-tooltip-compile"
tooltipText={
<div className="text-left">
<div>
<b>Ctrl+S</b> to compile {appState.filePath}
</div>
</div>
}
>
<button
className="btn btn-primary btn-block d-block w-100 text-break mb-1 mt-1"
onClick={() => { compileAction() }}
disabled={(appState.filePath === "") || (appState.status === "compiling")}
data-id={`compile_${id}_btn`}
>
<div className="d-flex align-items-center justify-content-center">
<RenderIf condition={appState.status === 'compiling'}>
<i className="fas fa-sync fa-spin mr-2" aria-hidden="true"></i>
</RenderIf>
<div className="text-truncate overflow-hidden text-nowrap">
<span>
<FormattedMessage id="circuit.compile" />
</span>
<span className="ml-1 text-nowrap">
<RenderIf condition={appState.filePath === ""}>
<FormattedMessage id="circuit.noFileSelected" />
</RenderIf>
<RenderIfNot condition={appState.filePath === ""}>
<>{extractNameFromKey(appState.filePath)}</>
</RenderIfNot>
</span>
</div>
</div>
</button>
</CustomTooltip>
)

@ -0,0 +1,6 @@
export type CompileOptionsProps = {
setCircuitAutoCompile: (value: boolean) => void,
setCircuitHideWarnings: (value: boolean) => void,
autoCompile: boolean,
hideWarnings: boolean
}
Loading…
Cancel
Save